aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dockerignore3
-rw-r--r--.gitignore2
-rw-r--r--Android.bp12
-rw-r--r--Dockerfile50
-rw-r--r--cmd-runner/Cargo.lock30
-rw-r--r--cmd-runner/Cargo.toml11
-rw-r--r--common/Android.bp14
-rw-r--r--common/Cargo.lock1489
-rw-r--r--common/Cargo.toml84
-rw-r--r--common/build_scripts/Cargo.toml16
-rw-r--r--common/build_scripts/src/license.rs65
-rw-r--r--common/build_scripts/src/main.rs66
-rw-r--r--common/cmd_runner/Cargo.lock714
-rw-r--r--common/cmd_runner/Cargo.toml17
-rw-r--r--common/cmd_runner/src/cargo_workspace.rs106
-rw-r--r--common/cmd_runner/src/lib.rs (renamed from cmd-runner/src/lib.rs)3
-rw-r--r--common/cmd_runner/src/license_checker.rs105
-rw-r--r--common/deny.toml (renamed from nearby/presence/ldt_np_adv_ffi/deny.toml)41
-rw-r--r--common/derive_fuzztest/Cargo.toml24
-rw-r--r--common/derive_fuzztest/fuzz/.gitignore1
-rw-r--r--common/derive_fuzztest/fuzz/Cargo.toml16
-rw-r--r--common/derive_fuzztest/fuzz/src/bin/arbitrary.rs32
-rw-r--r--common/derive_fuzztest/fuzz/src/bin/integer_add.rs23
-rw-r--r--common/derive_fuzztest/src/lib.rs141
-rw-r--r--common/derive_fuzztest_macro/Cargo.toml23
-rw-r--r--common/derive_fuzztest_macro/src/lib.rs463
-rw-r--r--common/handle_map/Cargo.toml (renamed from nearby/util/handle_map/Cargo.toml)0
-rw-r--r--common/handle_map/benches/benches.rs (renamed from nearby/util/handle_map/benches/benches.rs)54
-rw-r--r--common/handle_map/src/declare_handle_map.rs (renamed from nearby/util/handle_map/src/declare_handle_map.rs)51
-rw-r--r--common/handle_map/src/guard.rs (renamed from nearby/util/handle_map/src/guard.rs)12
-rw-r--r--common/handle_map/src/lib.rs (renamed from nearby/util/handle_map/src/lib.rs)30
-rw-r--r--common/handle_map/src/shard.rs (renamed from nearby/util/handle_map/src/shard.rs)31
-rw-r--r--common/handle_map/src/tests.rs (renamed from nearby/util/handle_map/src/tests.rs)82
-rw-r--r--common/lock_adapter/Cargo.toml (renamed from nearby/util/lock_adapter/Cargo.toml)0
-rw-r--r--common/lock_adapter/src/lib.rs (renamed from nearby/util/lock_adapter/src/lib.rs)7
-rw-r--r--common/lock_adapter/src/spin.rs (renamed from nearby/util/lock_adapter/src/spin.rs)0
-rw-r--r--common/lock_adapter/src/stdlib.rs (renamed from nearby/util/lock_adapter/src/std.rs)0
-rw-r--r--common/pourover/Cargo.toml19
-rw-r--r--common/pourover/src/conversions.rs90
-rw-r--r--common/pourover/src/desc.rs396
-rw-r--r--common/pourover/src/lib.rs22
-rw-r--r--common/pourover/tests/Foo.java45
-rw-r--r--common/pourover/tests/call_method_integration.rs48
-rw-r--r--common/pourover/tests/common/foo_class.rs89
-rw-r--r--common/pourover/tests/common/mod.rs21
-rw-r--r--common/pourover/tests/desc_integration.rs107
-rw-r--r--common/pourover/tests/jni_method_integration.rs162
-rw-r--r--common/pourover_macro/Cargo.toml22
-rw-r--r--common/pourover_macro/src/call_method.rs100
-rw-r--r--common/pourover_macro/src/call_method/ast.rs290
-rw-r--r--common/pourover_macro/src/call_method/codegen.rs610
-rw-r--r--common/pourover_macro/src/jni_method.rs412
-rw-r--r--common/pourover_macro/src/jni_method/meta.rs209
-rw-r--r--common/pourover_macro/src/jni_method/meta_arg.rs119
-rw-r--r--common/pourover_macro/src/jni_method/substitutions.rs123
-rw-r--r--common/pourover_macro/src/lib.rs286
-rw-r--r--common/pourover_macro/src/type_parser.rs503
-rw-r--r--nearby/.cargo/config-boringssl.toml9
-rw-r--r--nearby/Android.bp22
-rw-r--r--nearby/Cargo.lock472
-rw-r--r--nearby/Cargo.toml66
-rw-r--r--nearby/README.md4
-rw-r--r--nearby/connections/ukey2/ukey2/Cargo.toml1
-rw-r--r--nearby/connections/ukey2/ukey2/src/lib.rs1
-rw-r--r--nearby/connections/ukey2/ukey2/src/proto_adapter.rs61
-rw-r--r--nearby/connections/ukey2/ukey2/src/state_machine.rs13
-rw-r--r--nearby/connections/ukey2/ukey2/src/tests.rs39
-rw-r--r--nearby/connections/ukey2/ukey2/src/ukey2_handshake.rs82
-rw-r--r--nearby/connections/ukey2/ukey2/tests/tests.rs90
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml2
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h17
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h126
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc202
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc8
-rw-r--r--nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs6
-rw-r--r--nearby/connections/ukey2/ukey2_connections/Cargo.toml1
-rw-r--r--nearby/connections/ukey2/ukey2_connections/benches/ukey2_benches.rs65
-rw-r--r--nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock460
-rw-r--r--nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.toml31
-rw-r--r--nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_connection.rs58
-rw-r--r--nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_from_saved_session.rs11
-rw-r--r--nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_handshake.rs41
-rw-r--r--nearby/connections/ukey2/ukey2_connections/src/crypto_utils.rs37
-rw-r--r--nearby/connections/ukey2/ukey2_connections/src/d2d_connection_context_v1.rs237
-rw-r--r--nearby/connections/ukey2/ukey2_connections/src/d2d_handshake_context.rs70
-rw-r--r--nearby/connections/ukey2/ukey2_connections/src/lib.rs2
-rw-r--r--nearby/connections/ukey2/ukey2_connections/src/tests.rs76
-rw-r--r--nearby/connections/ukey2/ukey2_jni/Cargo.toml2
-rw-r--r--nearby/connections/ukey2/ukey2_jni/java/src/jmh/java/com/google/security/cryptauth/lib/securegcm/ukey2/Ukey2Benchmark.java14
-rw-r--r--nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/AlertException.java36
-rw-r--r--nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/D2DHandshakeContext.java61
-rw-r--r--nearby/connections/ukey2/ukey2_jni/java/src/test/java/com/google/security/cryptauth/lib/securegcm/ukey2/TestUkey2Protocol.kt72
-rw-r--r--nearby/connections/ukey2/ukey2_jni/src/lib.rs153
-rw-r--r--nearby/connections/ukey2/ukey2_proto/proto/securegcm.proto232
-rw-r--r--nearby/connections/ukey2/ukey2_proto/proto/securemessage.proto12
-rw-r--r--nearby/connections/ukey2/ukey2_proto/proto/ukey.proto4
-rw-r--r--nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/device_to_device_messages.rs2
-rw-r--r--nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securegcm.rs2221
-rw-r--r--nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securemessage.rs183
-rw-r--r--nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/ukey.rs16
-rw-r--r--nearby/connections/ukey2/ukey2_shell/Cargo.toml1
-rw-r--r--nearby/connections/ukey2/ukey2_shell/src/main.rs7
-rw-r--r--nearby/crypto/README.md24
-rw-r--r--nearby/crypto/crypto_provider/Cargo.toml3
-rw-r--r--nearby/crypto/crypto_provider/benches/constant_time_eq_bench.rs6
-rw-r--r--nearby/crypto/crypto_provider/benches/hkdf_bench.rs5
-rw-r--r--nearby/crypto/crypto_provider/benches/hmac_bench.rs9
-rw-r--r--nearby/crypto/crypto_provider/src/aes/mod.rs2
-rw-r--r--nearby/crypto/crypto_provider/src/ed25519.rs178
-rw-r--r--nearby/crypto/crypto_provider_boringssl/Cargo.lock18
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs77
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm_siv.rs77
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/aes/mod.rs26
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/ed25519.rs28
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/hkdf.rs18
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/hmac.rs12
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/lib.rs14
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/p256.rs64
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/sha2.rs8
-rw-r--r--nearby/crypto/crypto_provider_boringssl/src/x25519.rs24
-rw-r--r--nearby/crypto/crypto_provider_default/Cargo.toml5
-rw-r--r--nearby/crypto/crypto_provider_default/src/lib.rs6
-rw-r--r--nearby/crypto/crypto_provider_openssl/Cargo.toml25
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/aes.rs273
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/ed25519.rs136
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs72
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs68
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs103
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs176
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/lib.rs134
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/p256.rs202
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/sha2.rs71
-rw-r--r--nearby/crypto/crypto_provider_openssl/src/x25519.rs106
-rw-r--r--nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs18
-rw-r--r--nearby/crypto/crypto_provider_rustcrypto/src/lib.rs2
-rw-r--r--nearby/crypto/crypto_provider_stubs/src/lib.rs14
-rw-r--r--nearby/crypto/crypto_provider_test/fuzz/Cargo.lock210
-rw-r--r--nearby/crypto/crypto_provider_test/fuzz/Cargo.toml22
-rw-r--r--nearby/crypto/crypto_provider_test/fuzz/src/bin/fuzz_p256.rs (renamed from nearby/crypto/crypto_provider_test/fuzz/fuzz_targets/fuzz_p256.rs)17
-rw-r--r--nearby/crypto/crypto_provider_test/src/aead/aes_gcm.rs1
-rw-r--r--nearby/crypto/crypto_provider_test/src/aead/aes_gcm_siv.rs1
-rw-r--r--nearby/crypto/crypto_provider_test/src/ed25519.rs7
-rw-r--r--nearby/crypto/crypto_provider_test/src/hkdf.rs23
-rw-r--r--nearby/crypto/crypto_provider_test/src/lib.rs4
-rw-r--r--nearby/crypto/crypto_provider_test/src/sha2.rs1
-rw-r--r--nearby/crypto/rand_core_05_adapter/Cargo.toml13
-rw-r--r--nearby/crypto/rand_core_05_adapter/src/lib.rs61
-rw-r--r--nearby/deny.toml74
-rw-r--r--nearby/presence/CMakeLists.txt69
-rw-r--r--nearby/presence/README.md11
-rw-r--r--nearby/presence/array_view/src/lib.rs5
-rw-r--r--nearby/presence/ldt/benches/ldt_scan.rs5
-rw-r--r--nearby/presence/ldt/examples/gen_ldt_xor_pad_test_vectors.rs2
-rw-r--r--nearby/presence/ldt/examples/ldt_benchmark.rs2
-rw-r--r--nearby/presence/ldt/examples/ldt_prp.rs2
-rw-r--r--nearby/presence/ldt/fuzz/Cargo.lock125
-rw-r--r--nearby/presence/ldt/fuzz/Cargo.toml33
-rw-r--r--nearby/presence/ldt/fuzz/src/bin/ldt_roundtrip.rs (renamed from nearby/presence/ldt/fuzz/fuzz_targets/ldt_roundtrip.rs)25
-rw-r--r--nearby/presence/ldt/src/lib.rs52
-rw-r--r--nearby/presence/ldt/tests/ldt_roundtrip.rs6
-rw-r--r--nearby/presence/ldt/tests/ldt_test_vectors.rs2
-rw-r--r--nearby/presence/ldt/tests/tests.rs13
-rw-r--r--nearby/presence/ldt_np_adv/Cargo.toml2
-rw-r--r--nearby/presence/ldt_np_adv/benches/ldt_adv_scan.rs25
-rw-r--r--nearby/presence/ldt_np_adv/fuzz/Cargo.lock125
-rw-r--r--nearby/presence/ldt_np_adv/fuzz/Cargo.toml42
-rw-r--r--nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_decrypt.rs (renamed from nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_decrypt.rs)17
-rw-r--r--nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_roundtrip.rs (renamed from nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_roundtrip.rs)29
-rw-r--r--nearby/presence/ldt_np_adv/resources/test/np_adv_test_vectors.json9886
-rw-r--r--nearby/presence/ldt_np_adv/src/lib.rs205
-rw-r--r--nearby/presence/ldt_np_adv/src/np_adv_test_vectors.rs72
-rw-r--r--nearby/presence/ldt_np_adv/src/tests.rs199
-rw-r--r--nearby/presence/ldt_np_adv_ffi/.cargo/config.toml9
-rw-r--r--nearby/presence/ldt_np_adv_ffi/Cargo.lock947
-rw-r--r--nearby/presence/ldt_np_adv_ffi/Cargo.toml41
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/CMakeLists.txt49
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/benchmarks/CMakeLists.txt24
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/benchmarks/ldt_benchmarks.cc (renamed from nearby/presence/ldt_np_c_sample/tests/ldt_benchmarks.cc)0
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/fuzz/CMakeLists.txt30
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/fuzz/ldt_fuzzer.cc125
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/include/np_ldt.h (renamed from nearby/presence/ldt_np_adv_ffi/include/np_ldt.h)0
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/sample/CMakeLists.txt19
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/sample/main.c (renamed from nearby/presence/ldt_np_c_sample/main.c)0
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/tests/CMakeLists.txt (renamed from nearby/presence/ldt_np_c_sample/tests/CMakeLists.txt)39
-rw-r--r--nearby/presence/ldt_np_adv_ffi/c/tests/ldt_ffi_tests.cc (renamed from nearby/presence/ldt_np_c_sample/tests/ldt_ffi_tests.cc)26
-rw-r--r--nearby/presence/ldt_np_adv_ffi/rust-toolchain.toml2
-rw-r--r--nearby/presence/ldt_np_adv_ffi/src/handle_map.rs3
-rw-r--r--nearby/presence/ldt_np_adv_ffi/src/lib.rs74
-rw-r--r--nearby/presence/ldt_np_adv_ffi_fuzz/CMakeLists.txt47
-rw-r--r--nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_bad_mac.c102
-rw-r--r--nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_correct_mac.c145
-rw-r--r--nearby/presence/ldt_np_c_sample/CMakeLists.txt52
-rw-r--r--nearby/presence/ldt_np_jni/Cargo.toml1
-rw-r--r--nearby/presence/ldt_np_jni/java/LdtNpJni/src/main/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJni.java54
-rw-r--r--nearby/presence/ldt_np_jni/java/LdtNpJni/src/test/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJniTests.kt10
-rw-r--r--nearby/presence/ldt_np_jni/src/lib.rs18
-rw-r--r--nearby/presence/np_adv/Cargo.toml3
-rw-r--r--nearby/presence/np_adv/benches/deser_adv.rs134
-rw-r--r--nearby/presence/np_adv/resources/test/mic-encrypted-test-vectors.json2295
-rw-r--r--nearby/presence/np_adv/resources/test/mic-extended-salt-encrypted-test-vectors.json2213
-rw-r--r--nearby/presence/np_adv/src/credential/book.rs133
-rw-r--r--nearby/presence/np_adv/src/credential/matched.rs318
-rw-r--r--nearby/presence/np_adv/src/credential/metadata/mod.rs79
-rw-r--r--nearby/presence/np_adv/src/credential/metadata/tests.rs95
-rw-r--r--nearby/presence/np_adv/src/credential/mod.rs335
-rw-r--r--nearby/presence/np_adv/src/credential/source.rs78
-rw-r--r--nearby/presence/np_adv/src/credential/tests.rs136
-rw-r--r--nearby/presence/np_adv/src/credential/v0.rs126
-rw-r--r--nearby/presence/np_adv/src/credential/v1.rs475
-rw-r--r--nearby/presence/np_adv/src/de_type.rs88
-rw-r--r--nearby/presence/np_adv/src/deser_v1_tests.rs562
-rw-r--r--nearby/presence/np_adv/src/deserialization_arena.rs14
-rw-r--r--nearby/presence/np_adv/src/extended/data_elements/mod.rs62
-rw-r--r--nearby/presence/np_adv/src/extended/data_elements/tests.rs120
-rw-r--r--nearby/presence/np_adv/src/extended/de_type.rs98
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/data_element/mod.rs260
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/data_element/tests.rs348
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/dev_tools.rs87
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mic_decrypt_tests.rs471
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mod.rs373
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests.rs88
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/coverage_gaming.rs60
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/mic_decrypt_tests.rs642
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/signature_decrypt_tests.rs (renamed from nearby/presence/np_adv/src/extended/deserialize/encrypted_section/signature_decrypt_tests.rs)371
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/mod.rs1052
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/parse_tests.rs703
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section/header/mod.rs141
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section/header/tests.rs194
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section/intermediate/mod.rs289
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section/intermediate/tests.rs725
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section/mod.rs (renamed from nearby/presence/ldt_np_adv_ffi/src/no_std.rs)13
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/section_tests.rs622
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/test_stubs.rs45
-rw-r--r--nearby/presence/np_adv/src/extended/deserialize/tests.rs145
-rw-r--r--nearby/presence/np_adv/src/extended/mod.rs98
-rw-r--r--nearby/presence/np_adv/src/extended/salt.rs113
-rw-r--r--nearby/presence/np_adv/src/extended/section_signature_payload.rs148
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/adv_tests.rs77
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/de_header_tests.rs13
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/mod.rs672
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/section/encoder.rs429
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/section/header.rs164
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/section/mod.rs204
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/section_tests.rs722
-rw-r--r--nearby/presence/np_adv/src/extended/serialize/test_vectors.rs176
-rw-r--r--nearby/presence/np_adv/src/filter/mod.rs51
-rw-r--r--nearby/presence/np_adv/src/filter/tests/actions_filter_tests.rs41
-rw-r--r--nearby/presence/np_adv/src/filter/tests/data_elements_filter_tests.rs28
-rw-r--r--nearby/presence/np_adv/src/filter/tests/mod.rs23
-rw-r--r--nearby/presence/np_adv/src/filter/tests/v0_filter_tests.rs124
-rw-r--r--nearby/presence/np_adv/src/header.rs165
-rw-r--r--nearby/presence/np_adv/src/header_parse_tests.rs60
-rw-r--r--nearby/presence/np_adv/src/helpers.rs39
-rw-r--r--nearby/presence/np_adv/src/legacy/actions/tests.rs368
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements.rs143
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/actions/macros.rs (renamed from nearby/presence/np_adv/src/legacy/actions/macros.rs)53
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/actions/mod.rs (renamed from nearby/presence/np_adv/src/legacy/actions/mod.rs)272
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/actions/tests.rs690
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/de_type/mod.rs127
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/de_type/tests.rs153
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/mod.rs266
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/tests.rs304
-rw-r--r--nearby/presence/np_adv/src/legacy/data_elements/tx_power.rs189
-rw-r--r--nearby/presence/np_adv/src/legacy/de_type/mod.rs356
-rw-r--r--nearby/presence/np_adv/src/legacy/de_type/tests.rs114
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/intermediate/mod.rs146
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/error_conditions.rs85
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/happy_path.rs106
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/mod.rs16
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/mod.rs557
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/tests.rs818
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/tests/error_conditions.rs321
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/tests/happy_path.rs587
-rw-r--r--nearby/presence/np_adv/src/legacy/deserialize/tests/mod.rs194
-rw-r--r--nearby/presence/np_adv/src/legacy/mod.rs129
-rw-r--r--nearby/presence/np_adv/src/legacy/random_data_elements.rs99
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/header.rs74
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/mod.rs437
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/tests.rs153
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/tests/error_conditions.rs193
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/tests/happy_path.rs244
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/tests/helpers.rs176
-rw-r--r--nearby/presence/np_adv/src/legacy/serialize/tests/mod.rs95
-rw-r--r--nearby/presence/np_adv/src/lib.rs663
-rw-r--r--nearby/presence/np_adv/src/shared_data.rs34
-rw-r--r--nearby/presence/np_adv/src/tests.rs16
-rw-r--r--nearby/presence/np_adv/src/tests/deser_v0_tests.rs (renamed from nearby/presence/np_adv/src/deser_v0_tests.rs)117
-rw-r--r--nearby/presence/np_adv/src/tests/deser_v1_tests.rs485
-rw-r--r--nearby/presence/np_adv/src/tests/deser_v1_tests/error_condition.rs257
-rw-r--r--nearby/presence/np_adv/src/tests/deser_v1_tests/happy_path.rs227
-rw-r--r--nearby/presence/np_adv/test.json24122
-rw-r--r--nearby/presence/np_adv/tests/examples_v0.rs75
-rw-r--r--nearby/presence/np_adv/tests/examples_v1.rs117
-rw-r--r--nearby/presence/np_adv_dynamic/Cargo.toml2
-rw-r--r--nearby/presence/np_adv_dynamic/src/extended.rs148
-rw-r--r--nearby/presence/np_adv_dynamic/src/legacy.rs256
-rw-r--r--nearby/presence/np_c_ffi/Cargo.lock1215
-rw-r--r--nearby/presence/np_c_ffi/Cargo.toml19
-rw-r--r--nearby/presence/np_c_ffi/cbindgen_configs/c_config.toml10
-rw-r--r--nearby/presence/np_c_ffi/cbindgen_configs/cpp_config.toml10
-rw-r--r--nearby/presence/np_c_ffi/deny.toml213
-rw-r--r--nearby/presence/np_c_ffi/include/c/np_c_ffi.h1009
-rw-r--r--nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_functions.h278
-rw-r--r--nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h465
-rw-r--r--nearby/presence/np_c_ffi/rust-toolchain.toml2
-rw-r--r--nearby/presence/np_c_ffi/src/credentials.rs95
-rw-r--r--nearby/presence/np_c_ffi/src/deserialize/mod.rs2
-rw-r--r--nearby/presence/np_c_ffi/src/deserialize/v0.rs51
-rw-r--r--nearby/presence/np_c_ffi/src/deserialize/v1.rs14
-rw-r--r--nearby/presence/np_c_ffi/src/lib.rs114
-rw-r--r--nearby/presence/np_c_ffi/src/serialize/mod.rs16
-rw-r--r--nearby/presence/np_c_ffi/src/serialize/v0.rs94
-rw-r--r--nearby/presence/np_c_ffi/src/serialize/v1.rs168
-rw-r--r--nearby/presence/np_c_ffi/src/v0.rs140
-rw-r--r--nearby/presence/np_c_ffi/src/v1.rs31
-rw-r--r--nearby/presence/np_cpp_ffi/CMakeLists.txt9
-rw-r--r--nearby/presence/np_cpp_ffi/benchmarks/CMakeLists.txt6
-rw-r--r--nearby/presence/np_cpp_ffi/benchmarks/np_c_ffi_benches.cc58
-rw-r--r--nearby/presence/np_cpp_ffi/benchmarks/np_cpp_benches.cc216
-rw-r--r--nearby/presence/np_cpp_ffi/benchmarks/np_ffi_bench.cc111
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/CMakeLists.txt28
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvEmptybin1 -> 0 bytes
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvSimplebin4 -> 0 bytes
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/corpus/V1AdvSimple1
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/deserialization_fuzzer.cc304
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_deserialize.cc54
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_valid_header.cc60
-rw-r--r--nearby/presence/np_cpp_ffi/fuzz/generate_fuzz_corpus.cc44
-rw-r--r--nearby/presence/np_cpp_ffi/include/nearby_protocol.h481
-rw-r--r--nearby/presence/np_cpp_ffi/nearby_protocol.cc463
-rw-r--r--nearby/presence/np_cpp_ffi/sample/main.cc240
-rw-r--r--nearby/presence/np_cpp_ffi/shared/shared_test_util.cc61
-rw-r--r--nearby/presence/np_cpp_ffi/shared/shared_test_util.h142
-rw-r--r--nearby/presence/np_cpp_ffi/tests/CMakeLists.txt10
-rw-r--r--nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc115
-rw-r--r--nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc112
-rw-r--r--nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc231
-rw-r--r--nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc168
-rw-r--r--nearby/presence/np_cpp_ffi/tests/np_cpp_test.h11
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v0_encrypted_deserialization_tests.cc171
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v0_encrypted_serialization_tests.cc58
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v0_private_identity_tests.cc211
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v0_unencrypted_deserialization_tests.cc (renamed from nearby/presence/np_cpp_ffi/tests/v0_public_identity_tests.cc)441
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v0_unencrypted_serialization_tests.cc170
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v1_encrypted_deserialization_tests.cc78
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v1_private_identity_tests.cc130
-rw-r--r--nearby/presence/np_cpp_ffi/tests/v1_unencrypted_deserialization_tests.cc (renamed from nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc)103
-rw-r--r--nearby/presence/np_ed25519/src/lib.rs219
-rw-r--r--nearby/presence/np_ffi_core/Cargo.toml3
-rw-r--r--nearby/presence/np_ffi_core/src/common.rs254
-rw-r--r--nearby/presence/np_ffi_core/src/credentials.rs223
-rw-r--r--nearby/presence/np_ffi_core/src/deserialize.rs (renamed from nearby/presence/np_ffi_core/src/deserialize/mod.rs)47
-rw-r--r--nearby/presence/np_ffi_core/src/deserialize/v0.rs367
-rw-r--r--nearby/presence/np_ffi_core/src/deserialize/v1.rs230
-rw-r--r--nearby/presence/np_ffi_core/src/lib.rs1
-rw-r--r--nearby/presence/np_ffi_core/src/serialize.rs (renamed from nearby/presence/np_ffi_core/src/serialize/mod.rs)1
-rw-r--r--nearby/presence/np_ffi_core/src/serialize/v0.rs275
-rw-r--r--nearby/presence/np_ffi_core/src/serialize/v1.rs242
-rw-r--r--nearby/presence/np_ffi_core/src/utils.rs4
-rw-r--r--nearby/presence/np_ffi_core/src/v0.rs410
-rw-r--r--nearby/presence/np_hkdf/Cargo.toml3
-rw-r--r--nearby/presence/np_hkdf/benches/np_hkdf.rs7
-rw-r--r--nearby/presence/np_hkdf/resources/test/hkdf-test-vectors.json6294
-rw-r--r--nearby/presence/np_hkdf/src/lib.rs167
-rw-r--r--nearby/presence/np_hkdf/src/v1_salt.rs80
-rw-r--r--nearby/presence/np_hkdf/tests/hmac.rs12
-rw-r--r--nearby/presence/np_hkdf/tests/test_vectors.rs165
-rw-r--r--nearby/presence/np_java_ffi/.gitignore8
-rw-r--r--nearby/presence/np_java_ffi/Cargo.toml22
-rw-r--r--nearby/presence/np_java_ffi/build.gradle.kts54
-rw-r--r--nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.jarbin0 -> 61574 bytes
-rw-r--r--nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xnearby/presence/np_java_ffi/gradlew244
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializationException.java37
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializeResult.java122
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedAdvertisement.java27
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV0Advertisement.java155
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Advertisement.java97
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Section.java95
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/Handle.java45
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/IdentityKind.java43
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/LegibleV1Sections.java80
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/NpAdv.java91
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/OwnedHandle.java129
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0DataElement.java114
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0Payload.java64
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V1DataElement.java63
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialBook.java140
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialSlab.java71
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/Utils.java35
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V0DiscoveryCredential.java31
-rw-r--r--nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V1DiscoveryCredential.java44
-rw-r--r--nearby/presence/np_java_ffi/settings.gradle.kts17
-rw-r--r--nearby/presence/np_java_ffi/src/class.rs62
-rw-r--r--nearby/presence/np_java_ffi/src/class/credential_book.rs65
-rw-r--r--nearby/presence/np_java_ffi/src/class/credential_slab.rs160
-rw-r--r--nearby/presence/np_java_ffi/src/class/deserialization_exception.rs86
-rw-r--r--nearby/presence/np_java_ffi/src/class/deserialize_result.rs103
-rw-r--r--nearby/presence/np_java_ffi/src/class/deserialized_v0_advertisement.rs79
-rw-r--r--nearby/presence/np_java_ffi/src/class/deserialized_v1_advertisement.rs50
-rw-r--r--nearby/presence/np_java_ffi/src/class/deserialized_v1_section.rs50
-rw-r--r--nearby/presence/np_java_ffi/src/class/handle.rs45
-rw-r--r--nearby/presence/np_java_ffi/src/class/identity_kind.rs117
-rw-r--r--nearby/presence/np_java_ffi/src/class/legible_v1_sections.rs159
-rw-r--r--nearby/presence/np_java_ffi/src/class/np_adv.rs95
-rw-r--r--nearby/presence/np_java_ffi/src/class/owned_handle.rs45
-rw-r--r--nearby/presence/np_java_ffi/src/class/v0_data_element.rs172
-rw-r--r--nearby/presence/np_java_ffi/src/class/v0_discovery_credential.rs72
-rw-r--r--nearby/presence/np_java_ffi/src/class/v0_payload.rs73
-rw-r--r--nearby/presence/np_java_ffi/src/class/v1_data_element.rs51
-rw-r--r--nearby/presence/np_java_ffi/src/class/v1_discovery_credential.rs101
-rw-r--r--nearby/presence/np_java_ffi/src/lib.rs21
-rw-r--r--nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/DeserializeTests.java199
-rw-r--r--nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/TestData.java410
-rw-r--r--nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/credential/CredentialBookTests.java40
-rw-r--r--nearby/presence/rand_ext/src/lib.rs4
-rw-r--r--nearby/presence/test_helper/Cargo.toml1
-rw-r--r--nearby/presence/test_helper/src/lib.rs14
-rw-r--r--nearby/presence/test_vector_hkdf/Cargo.toml17
-rw-r--r--nearby/presence/test_vector_hkdf/src/lib.rs91
-rw-r--r--nearby/presence/xts_aes/fuzz/Cargo.lock125
-rw-r--r--nearby/presence/xts_aes/fuzz/Cargo.toml30
-rw-r--r--nearby/presence/xts_aes/fuzz/src/bin/xts_roundtrip.rs (renamed from nearby/presence/xts_aes/fuzz/fuzz_targets/xts_roundtrip.rs)15
-rw-r--r--nearby/presence/xts_aes/tests/compare_with_xts_mode_test.rs4
-rw-r--r--nearby/presence/xts_aes/tests/wycheproof_test_vectors.rs2
-rw-r--r--nearby/presence/xts_aes/tests/xts_nist_test_vectors.rs2
-rw-r--r--nearby/presence/xts_aes/tests/xts_roundtrip_tests.rs4
-rw-r--r--nearby/scripts/openssl-patches/0001-Apply-android-patches.patch1017
-rw-r--r--nearby/scripts/openssl-patches/README.md38
-rw-r--r--nearby/src/coverage.rs14
-rw-r--r--nearby/src/crypto_ffi.rs112
-rw-r--r--nearby/src/ffi.rs80
-rw-r--r--nearby/src/fuzzers.rs43
-rw-r--r--nearby/src/jni.rs12
-rw-r--r--nearby/src/license.rs82
-rw-r--r--nearby/src/main.rs201
-rw-r--r--nearby/src/ukey2.rs12
-rw-r--r--remoteauth/Cargo.lock557
-rw-r--r--remoteauth/Cargo.toml2
439 files changed, 40921 insertions, 62234 deletions
diff --git a/.dockerignore b/.dockerignore
index d8f642c..bc549d9 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,5 +1,7 @@
**
+!common/
+common/target/
!nearby/.cargo
!nearby/connections/
!nearby/crypto/
@@ -12,3 +14,4 @@ nearby/presence/cmake-build
!nearby/deny.toml
!nearby/rustfmt.toml
!third_party
+third_party/boringssl/build
diff --git a/.gitignore b/.gitignore
index c1baf38..5c2ad01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,5 @@ target/
nearby/connections/ukey2/ukey2_c_ffi/cpp/build/
nearby/presence/ldt_np_jni/java/LdtNpJni/build/
**/auth_token.txt
+/bazel-*
+/.clwb/.bazelproject
diff --git a/Android.bp b/Android.bp
index 66bd177..47d73c6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,3 +43,15 @@ license {
"LICENSE",
],
}
+
+rust_defaults {
+ name: "beto_rust_defaults",
+ host_supported: true,
+ cargo_env_compat: true,
+ cargo_pkg_version: "0.1.0",
+ edition: "2021",
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+}
diff --git a/Dockerfile b/Dockerfile
index 1f0462e..9122d14 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,31 +12,40 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM ubuntu:22.10
+FROM ubuntu:22.04
# install system deps
-RUN apt-get update && apt-get install -y build-essential cmake gcc wget vim \
-clang git checkinstall zlib1g-dev libjsoncpp-dev libbenchmark-dev curl \
-protobuf-compiler pkg-config libdbus-1-dev libssl-dev ninja-build
+RUN apt-get update && apt-get install -y build-essential wget vim libstdc++-10-dev \
+clang git checkinstall zlib1g-dev curl protobuf-compiler cmake \
+pkg-config libdbus-1-dev ninja-build libssl-dev default-jre
RUN apt upgrade -y
+RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
+RUN apt-get -y install ./google-chrome-stable_current_amd64.deb
+RUN export CHROME_BIN="/usr/bin/google-chrome-stable"
+
+ENV CC=/usr/bin/clang
+ENV CXX=/usr/bin/clang++
+
# install cargo with default settings
-RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.72.0
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.77.1
ENV PATH="/root/.cargo/bin:${PATH}"
+RUN rustup install stable
+RUN rustup toolchain install nightly --force
+RUN rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
+RUN rustup target add wasm32-unknown-unknown thumbv7m-none-eabi
+
RUN cargo install --locked cargo-deny --color never 2>&1
-RUN cargo install cargo-fuzz --color never 2>&1
+RUN cargo install --locked cargo-llvm-cov --color never 2>&1
+RUN cargo install bindgen-cli --version 0.69.4 --color never 2>&1
+RUN cargo install wasm-pack --color never 2>&1
+
# unreleased PR https://github.com/ehuss/cargo-prefetch/pull/6
RUN cargo install cargo-prefetch \
--git https://github.com/marshallpierce/cargo-prefetch.git \
--rev f6affa68e950275f9fd773f2646ab7ee4db82897 \
--color never 2>&1
-# needed for generating boringssl bindings
-# Must use 0.64.0, as version >= 0.65.0 removes the option "--size_t-is-usize", an option
-# used by boringssl when generating rust bindings
-RUN cargo install bindgen-cli --version 0.64.0
-RUN cargo install wasm-pack --color never 2>&1
-RUN rustup toolchain add nightly
-RUN rustup target add wasm32-unknown-unknown
+
# boringssl build wants go
RUN curl -L https://go.dev/dl/go1.20.2.linux-amd64.tar.gz | tar -C /usr/local -xz
ENV PATH="$PATH:/usr/local/go/bin"
@@ -45,13 +54,20 @@ ENV PATH="$PATH:/usr/local/go/bin"
RUN git config --global user.email "docker@example.com"
RUN git config --global user.name "NP Docker"
-RUN mkdir -p /google
-COPY . /google
+# Download google-java-format
+RUN mkdir /opt/google-java-format
+WORKDIR /opt/google-java-format
+ENV GOOGLE_JAVA_FORMAT_VERSION="1.19.2"
+RUN wget "https://github.com/google/google-java-format/releases/download/v${GOOGLE_JAVA_FORMAT_VERSION}/google-java-format-${GOOGLE_JAVA_FORMAT_VERSION}-all-deps.jar" -q -O "google-java-format-all-deps.jar"
-WORKDIR /google/nearby
+RUN mkdir -p /beto-core
+COPY . /beto-core
+WORKDIR /beto-core
# prefetch dependencies so later build steps don't re-download on source changes
-RUN cargo prefetch --lockfile Cargo.lock
+RUN cargo prefetch --lockfile nearby/Cargo.lock 2>&1
+RUN cargo prefetch --lockfile common/Cargo.lock 2>&1
# when the image runs build and test everything to ensure env is setup correctly
+WORKDIR /beto-core/nearby
CMD ["cargo", "run", "--", "check-everything"]
diff --git a/cmd-runner/Cargo.lock b/cmd-runner/Cargo.lock
deleted file mode 100644
index 4dadf2e..0000000
--- a/cmd-runner/Cargo.lock
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "anyhow"
-version = "1.0.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
-
-[[package]]
-name = "cmd-runner"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "owo-colors",
- "shell-escape",
-]
-
-[[package]]
-name = "owo-colors"
-version = "3.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
-
-[[package]]
-name = "shell-escape"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
diff --git a/cmd-runner/Cargo.toml b/cmd-runner/Cargo.toml
deleted file mode 100644
index e79317e..0000000
--- a/cmd-runner/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "cmd-runner"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-[dependencies]
-anyhow = "1.0.64"
-shell-escape = "0.1.5"
-owo-colors = "3.5.0"
-
diff --git a/common/Android.bp b/common/Android.bp
new file mode 100644
index 0000000..358e30b
--- /dev/null
+++ b/common/Android.bp
@@ -0,0 +1,14 @@
+package {
+ default_visibility: ["//external/rust/beto-rust:__subpackages__"],
+ default_applicable_licenses: ["external_rust_beto-rust_license"],
+}
+
+rust_library_rlib {
+ name: "liblock_adapter",
+ crate_name: "lock_adapter",
+ defaults: ["beto_rust_defaults"],
+ srcs: ["lock_adapter/src/lib.rs"],
+ features: [
+ "std",
+ ],
+}
diff --git a/common/Cargo.lock b/common/Cargo.lock
new file mode 100644
index 0000000..758eb2d
--- /dev/null
+++ b/common/Cargo.lock
@@ -0,0 +1,1489 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+
+[[package]]
+name = "anstream"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+
+[[package]]
+name = "arbitrary"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
+
+[[package]]
+name = "autocfg"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+
+[[package]]
+name = "bstr"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "build_scripts"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap",
+ "cmd_runner",
+ "file-header",
+ "globset",
+ "log",
+ "xshell",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "bytes"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
+
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
+[[package]]
+name = "cc"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
+dependencies = [
+ "jobserver",
+ "libc",
+]
+
+[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "ciborium"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
+dependencies = [
+ "ciborium-io",
+ "ciborium-ll",
+ "serde",
+]
+
+[[package]]
+name = "ciborium-io"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
+
+[[package]]
+name = "ciborium-ll"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
+dependencies = [
+ "ciborium-io",
+ "half",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "cmd_runner"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap",
+ "file-header",
+ "globset",
+ "log",
+ "owo-colors",
+ "shell-escape",
+ "xshell",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "memchr",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "criterion"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
+dependencies = [
+ "anes",
+ "cast",
+ "ciborium",
+ "clap",
+ "criterion-plot",
+ "is-terminal",
+ "itertools",
+ "num-traits",
+ "once_cell",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
+dependencies = [
+ "cast",
+ "itertools",
+]
+
+[[package]]
+name = "crossbeam"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "derive_fuzz_example"
+version = "0.1.0"
+dependencies = [
+ "arbitrary",
+ "derive_fuzztest",
+ "libfuzzer-sys",
+ "quickcheck",
+]
+
+[[package]]
+name = "derive_fuzztest"
+version = "0.1.0"
+dependencies = [
+ "arbitrary",
+ "derive_fuzztest_macro",
+ "proptest",
+ "proptest-arbitrary-interop",
+ "quickcheck",
+]
+
+[[package]]
+name = "derive_fuzztest_macro"
+version = "0.1.0"
+dependencies = [
+ "derive_fuzztest",
+ "pretty_assertions",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "either"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
+
+[[package]]
+name = "env_logger"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
+
+[[package]]
+name = "file-header"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5568149106e77ae33bc3a2c3ef3839cbe63ffa4a8dd4a81612a6f9dfdbc2e9f"
+dependencies = [
+ "crossbeam",
+ "lazy_static",
+ "license",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "getrandom"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "globset"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "half"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+dependencies = [
+ "cfg-if",
+ "crunchy",
+]
+
+[[package]]
+name = "handle_map"
+version = "0.1.0"
+dependencies = [
+ "criterion",
+ "lazy_static",
+ "lock_adapter",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "java-locator"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90003f2fd9c52f212c21d8520f1128da0080bad6fff16b68fe6e7f2f0c3780c2"
+dependencies = [
+ "glob",
+ "lazy_static",
+]
+
+[[package]]
+name = "jni"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
+dependencies = [
+ "cesu8",
+ "cfg-if",
+ "combine",
+ "java-locator",
+ "jni-sys",
+ "libloading",
+ "log",
+ "thiserror",
+ "walkdir",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+
+[[package]]
+name = "jobserver"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "libfuzzer-sys"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
+dependencies = [
+ "arbitrary",
+ "cc",
+ "once_cell",
+]
+
+[[package]]
+name = "libloading"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "libm"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+
+[[package]]
+name = "license"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bba2f02ee1d13cd4bea565658939cd851d70e391f34f7c27b45b2077df3a2e4"
+dependencies = [
+ "reword",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+
+[[package]]
+name = "lock_adapter"
+version = "0.1.0"
+dependencies = [
+ "spin 0.9.8",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
+[[package]]
+name = "plotters"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
+dependencies = [
+ "plotters-backend",
+]
+
+[[package]]
+name = "pourover"
+version = "0.1.0"
+dependencies = [
+ "jni",
+ "pourover_macro",
+]
+
+[[package]]
+name = "pourover_macro"
+version = "0.1.0"
+dependencies = [
+ "jni",
+ "nom",
+ "pourover",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "pretty_assertions"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
+dependencies = [
+ "diff",
+ "yansi",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proptest"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf"
+dependencies = [
+ "bit-set",
+ "bit-vec",
+ "bitflags",
+ "lazy_static",
+ "num-traits",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+ "unarray",
+]
+
+[[package]]
+name = "proptest-arbitrary-interop"
+version = "0.1.0"
+source = "git+https://github.com/brson/proptest-arbitrary-interop.git?branch=incorrect-format#9ae407e9805feb109b3d49cc737166bda7e698c3"
+dependencies = [
+ "arbitrary",
+ "proptest",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quickcheck"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
+dependencies = [
+ "env_logger",
+ "log",
+ "rand",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+
+[[package]]
+name = "reword"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe272098dce9ed76b479995953f748d1851261390b08f8a0ff619c885a1f0765"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.198"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.198"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.116"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "unarray"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "web-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.5",
+ "windows_aarch64_msvc 0.52.5",
+ "windows_i686_gnu 0.52.5",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.5",
+ "windows_x86_64_gnu 0.52.5",
+ "windows_x86_64_gnullvm 0.52.5",
+ "windows_x86_64_msvc 0.52.5",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+
+[[package]]
+name = "xshell"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
+dependencies = [
+ "xshell-macros",
+]
+
+[[package]]
+name = "xshell-macros"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
+
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
diff --git a/common/Cargo.toml b/common/Cargo.toml
new file mode 100644
index 0000000..9e8972b
--- /dev/null
+++ b/common/Cargo.toml
@@ -0,0 +1,84 @@
+[workspace]
+members = [
+ "build_scripts",
+ "cmd_runner",
+ "derive_fuzztest",
+ "derive_fuzztest/fuzz",
+ "derive_fuzztest_macro",
+ "handle_map",
+ "lock_adapter",
+ "pourover",
+ "pourover_macro",
+]
+default-members = ["build_scripts"]
+resolver = "2"
+
+[workspace.lints.rust]
+missing_docs = "deny"
+trivial_casts = "deny"
+trivial_numeric_casts = "deny"
+unsafe_code = "deny"
+unsafe_op_in_unsafe_fn = "deny"
+unused_extern_crates = "deny"
+unused_import_braces = "deny"
+unused_results = "deny"
+
+[workspace.lints.clippy]
+expect_used = "deny"
+indexing_slicing = "deny"
+panic = "deny"
+unwrap_used = "deny"
+
+[workspace.dependencies]
+# local crates
+cmd_runner = { path = "cmd_runner" }
+derive_fuzztest = { path = "derive_fuzztest" }
+derive_fuzztest_macro = { path = "derive_fuzztest_macro" }
+lock_adapter = { path = "lock_adapter" }
+handle_map = { path = "handle_map" }
+pourover = { path = "pourover" }
+pourover_macro = { path = "pourover_macro" }
+
+# from crates.io
+anyhow = "1.0.75"
+arbitrary = "1.3.2"
+clap = { version = "4.4.11", features = ["derive"] }
+criterion = { version = "0.5.1", features = ["html_reports"] }
+jni = "0.21.1"
+lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
+libfuzzer-sys = "0.4.7"
+nom = { version = "7.1.3", default-features = false }
+pretty_assertions = "1.4.0"
+prettyplease = "0.2.16"
+proc-macro2 = "1.0"
+proptest = "1.4.0"
+proptest-arbitrary-interop = { git = "https://github.com/brson/proptest-arbitrary-interop.git", branch = "incorrect-format" }
+quickcheck = "1.0.3"
+quote = "1.0"
+spin = { version = "0.9.8", features = ["once", "lock_api", "rwlock"] }
+syn = { version = "2.0", features = ["full"] }
+xshell = "0.2.6"
+
+[workspace.package]
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[profile.test]
+# speed up test execution
+opt-level = 3
+
+[profile.bench]
+# Since xts, ldt, etc are in separate crates, use LTO to allow cross-crate inlining.
+# fat vs thin: thin compiles a lot faster, and doesn't seem any slower.
+lto = "thin"
+
+# build profile optimized for size
+[profile.release-min-size]
+inherits = "release"
+panic = "abort"
+codegen-units = 1
+lto = true
+# z optimizes for size
+opt-level = "z"
+strip = true
diff --git a/common/build_scripts/Cargo.toml b/common/build_scripts/Cargo.toml
new file mode 100644
index 0000000..8f9d217
--- /dev/null
+++ b/common/build_scripts/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "build_scripts"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+rust-version = "1.71.0"
+
+[dependencies]
+anyhow.workspace = true
+clap.workspace = true
+xshell.workspace = true
+cmd_runner.workspace = true
+log = "0.4.21"
+file-header = "0.1.2"
+chrono = "0.4.37"
+globset = "0.4.14"
diff --git a/common/build_scripts/src/license.rs b/common/build_scripts/src/license.rs
new file mode 100644
index 0000000..113b7a0
--- /dev/null
+++ b/common/build_scripts/src/license.rs
@@ -0,0 +1,65 @@
+// 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.
+
+use cmd_runner::license_checker::LicenseChecker;
+
+pub const LICENSE_CHECKER: LicenseChecker = LicenseChecker {
+ ignore: &[
+ "**/android/build/**",
+ "**/target/**",
+ "**/.idea/**",
+ "**/cmake-build/**",
+ "**/java/build/**",
+ "**/java/*/build/**",
+ "**/*.toml",
+ "**/*.md",
+ "**/*.lock",
+ "**/*.json",
+ "**/*.rsp",
+ "**/*.patch",
+ "**/*.dockerignore",
+ "**/*.apk",
+ "**/gradle/*",
+ "**/.gradle/*",
+ "**/.git*",
+ "**/*test*vectors.txt",
+ "**/auth_token.txt",
+ "**/*.mdb",
+ "**/.DS_Store",
+ "**/fuzz/corpus/**",
+ "**/.*.swp",
+ "**/*.vim",
+ "**/*.properties",
+ "**/third_party/**",
+ "**/*.png",
+ "**/*.ico",
+ "**/node_modules/**",
+ "**/.angular/**",
+ "**/.editorconfig",
+ "**/*.class",
+ "**/fuzz/artifacts/**",
+ "**/cmake-build-debug/**",
+ "**/tags",
+ ],
+};
+
+#[cfg(test)]
+mod tests {
+ use super::LICENSE_CHECKER;
+
+ #[test]
+ fn new_ignore_is_likely_buggy() {
+ LICENSE_CHECKER.check_new_ignore_is_likely_buggy();
+ }
+}
diff --git a/common/build_scripts/src/main.rs b/common/build_scripts/src/main.rs
new file mode 100644
index 0000000..53fd178
--- /dev/null
+++ b/common/build_scripts/src/main.rs
@@ -0,0 +1,66 @@
+// 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.
+
+use std::path;
+
+use clap::Parser;
+use cmd_runner::{
+ cargo_workspace::{CargoOptions, CargoWorkspaceSubcommand, FormatterOptions},
+ license_checker::LicenseSubcommand,
+};
+use license::LICENSE_CHECKER;
+use xshell::Shell;
+
+mod license;
+
+#[derive(clap::Parser)]
+struct Cli {
+ #[clap(subcommand)]
+ subcommand: Subcommand,
+}
+
+#[derive(clap::Subcommand, Debug, Clone)]
+enum Subcommand {
+ VerifyCi {
+ #[command(flatten)]
+ cargo_options: CargoOptions,
+ },
+ #[command(flatten)]
+ CargoWorkspace(CargoWorkspaceSubcommand),
+ #[command(flatten)]
+ License(LicenseSubcommand),
+}
+
+fn main() -> anyhow::Result<()> {
+ let args = Cli::parse();
+ let root_dir = path::Path::new(
+ &std::env::var_os("CARGO_MANIFEST_DIR")
+ .expect("Must be run via Cargo to establish root directory"),
+ )
+ .parent()
+ .expect("Workspace directory should exist")
+ .to_path_buf();
+ let sh = Shell::new()?;
+ sh.change_dir(&root_dir);
+ match args.subcommand {
+ Subcommand::VerifyCi { cargo_options } => {
+ cargo_options.check_workspace(&sh, "common")?;
+ FormatterOptions { reformat: false }.check_format(&sh)?;
+ LICENSE_CHECKER.check(&root_dir)?;
+ }
+ Subcommand::CargoWorkspace(workspace) => workspace.run("common", &sh)?,
+ Subcommand::License(license) => license.run(&LICENSE_CHECKER, &root_dir)?,
+ }
+ Ok(())
+}
diff --git a/common/cmd_runner/Cargo.lock b/common/cmd_runner/Cargo.lock
new file mode 100644
index 0000000..3f3f5e1
--- /dev/null
+++ b/common/cmd_runner/Cargo.lock
@@ -0,0 +1,714 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
+
+[[package]]
+name = "autocfg"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
+
+[[package]]
+name = "bstr"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.15.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
+
+[[package]]
+name = "cc"
+version = "1.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "cmd-runner"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap",
+ "file-header",
+ "globset",
+ "log",
+ "owo-colors",
+ "shell-escape",
+ "xshell",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "crossbeam"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
+name = "file-header"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5568149106e77ae33bc3a2c3ef3839cbe63ffa4a8dd4a81612a6f9dfdbc2e9f"
+dependencies = [
+ "crossbeam",
+ "lazy_static",
+ "license",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "globset"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "license"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "778718185117620a06e95d2b1e57d50166b1d6bfad93c8abfc1b3344c863ad8c"
+dependencies = [
+ "reword",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+
+[[package]]
+name = "reword"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe272098dce9ed76b479995953f748d1851261390b08f8a0ff619c885a1f0765"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.197"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.197"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.115"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shell-escape"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
+
+[[package]]
+name = "xshell"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
+dependencies = [
+ "xshell-macros",
+]
+
+[[package]]
+name = "xshell-macros"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
diff --git a/common/cmd_runner/Cargo.toml b/common/cmd_runner/Cargo.toml
new file mode 100644
index 0000000..435b29f
--- /dev/null
+++ b/common/cmd_runner/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "cmd_runner"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+anyhow = "1.0.64"
+shell-escape = "0.1.5"
+owo-colors = "3.5.0"
+xshell = "0.2.6"
+clap = { version = "4.5.4", features = ["derive"] }
+file-header = "0.1.2"
+chrono = "0.4.37"
+log = "0.4.21"
+globset = "0.4.14"
+
diff --git a/common/cmd_runner/src/cargo_workspace.rs b/common/cmd_runner/src/cargo_workspace.rs
new file mode 100644
index 0000000..2b6840e
--- /dev/null
+++ b/common/cmd_runner/src/cargo_workspace.rs
@@ -0,0 +1,106 @@
+// 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.
+
+use std::ffi::OsStr;
+
+use xshell::cmd;
+
+#[derive(clap::Subcommand, Debug, Clone)]
+pub enum CargoWorkspaceSubcommand {
+ /// Checks test, clippy, and cargo deny in the workspace
+ CheckWorkspace(CargoOptions),
+ /// Checks the formatting of the workspace
+ CheckFormat(FormatterOptions),
+}
+
+impl CargoWorkspaceSubcommand {
+ pub fn run(&self, tag: &str, sh: &xshell::Shell) -> anyhow::Result<()> {
+ match self {
+ CargoWorkspaceSubcommand::CheckWorkspace(cargo_options) => {
+ cargo_options.check_workspace(sh, tag)
+ }
+ CargoWorkspaceSubcommand::CheckFormat(formatter_options) => {
+ formatter_options.check_format(sh)
+ }
+ }
+ }
+}
+
+#[derive(clap::Args, Debug, Clone, Default)]
+pub struct CargoOptions {
+ #[arg(long, help = "whether to run cargo with --locked")]
+ locked: bool,
+ #[arg(long, help = "gather coverage metrics")]
+ coverage: bool,
+}
+
+impl CargoOptions {
+ /// Run `cargo test` or `cargo llvm-cov` depending on the configured options.
+ pub fn test<'sh, S: AsRef<OsStr>>(
+ &self,
+ sh: &'sh xshell::Shell,
+ tag: &str,
+ args: impl IntoIterator<Item = S>,
+ ) -> xshell::Cmd<'sh> {
+ let locked = if self.locked { "--locked" } else { "" };
+ if self.coverage {
+ cmd!(
+ sh,
+ "cargo llvm-cov {locked} {args...} --lcov --output-path target/{tag}.info -- --color=always"
+ )
+ } else {
+ cmd!(sh, "cargo test {locked} {args...} -- --color=always")
+ }
+ }
+
+ /// Run the default set of checks on a cargo workspace
+ pub fn check_workspace(&self, sh: &xshell::Shell, tag: &str) -> anyhow::Result<()> {
+ self.test(sh, tag, ["--workspace"]).run()?;
+ cmd!(
+ sh,
+ "cargo clippy --all-targets --workspace -- --deny warnings"
+ )
+ .run()?;
+ cmd!(sh, "cargo deny --workspace check").run()?;
+ // ensure the docs are valid (cross-references to other code, etc)
+ cmd!(
+ sh,
+ "cargo doc --quiet --workspace --no-deps --document-private-items
+ --target-dir target/dist_docs/{tag}"
+ )
+ .env("RUSTDOCFLAGS", "--deny warnings")
+ .run()?;
+ Ok(())
+ }
+}
+
+#[derive(clap::Args, Debug, Clone, Default)]
+pub struct FormatterOptions {
+ #[arg(
+ long,
+ help = "reformat files files in the workspace with the code formatter"
+ )]
+ pub reformat: bool,
+}
+
+impl FormatterOptions {
+ pub fn check_format(&self, sh: &xshell::Shell) -> anyhow::Result<()> {
+ if self.reformat {
+ cmd!(sh, "cargo fmt").run()?;
+ } else {
+ cmd!(sh, "cargo fmt --check").run()?;
+ }
+ Ok(())
+ }
+}
diff --git a/cmd-runner/src/lib.rs b/common/cmd_runner/src/lib.rs
index fa2f1f4..8c45df8 100644
--- a/cmd-runner/src/lib.rs
+++ b/common/cmd_runner/src/lib.rs
@@ -16,6 +16,9 @@ use anyhow::{anyhow, Context as _};
use owo_colors::OwoColorize as _;
use std::{collections, env, ffi, io, io::BufRead, path, process, thread};
+pub mod cargo_workspace;
+pub mod license_checker;
+
pub fn run_cmd_shell(
dir: &path::Path,
cmd: impl AsRef<ffi::OsStr>,
diff --git a/common/cmd_runner/src/license_checker.rs b/common/cmd_runner/src/license_checker.rs
new file mode 100644
index 0000000..19286bb
--- /dev/null
+++ b/common/cmd_runner/src/license_checker.rs
@@ -0,0 +1,105 @@
+// 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.
+
+use chrono::Datelike;
+use file_header::{check_headers_recursively, license::spdx::*};
+use std::path;
+
+#[derive(clap::Subcommand, Debug, Clone)]
+pub enum LicenseSubcommand {
+ /// Checks the workspace 3rd party crates and makes sure they have a valid license
+ CheckLicenseHeaders,
+ /// Generate new headers for any files that are missing them
+ AddLicenseHeaders,
+}
+
+impl LicenseSubcommand {
+ pub fn run(&self, checker: &LicenseChecker, root: &path::Path) -> anyhow::Result<()> {
+ match self {
+ LicenseSubcommand::CheckLicenseHeaders => checker.check(root)?,
+ LicenseSubcommand::AddLicenseHeaders => checker.add_missing(root)?,
+ }
+ Ok(())
+ }
+}
+
+pub struct LicenseChecker {
+ pub ignore: &'static [&'static str],
+}
+
+impl LicenseChecker {
+ pub fn check(&self, root: &path::Path) -> anyhow::Result<()> {
+ log::info!("Checking license headers");
+ let ignore = self.ignore_globset()?;
+ let results = check_headers_recursively(
+ root,
+ |p| !ignore.is_match(p),
+ APACHE_2_0.build_header(YearCopyrightOwnerValue::new(
+ u32::try_from(chrono::Utc::now().year())?,
+ "Google LLC".to_string(),
+ )),
+ 4,
+ )?;
+
+ for path in results.no_header_files.iter() {
+ eprintln!("Header not present: {path:?}");
+ }
+
+ for path in results.binary_files.iter() {
+ eprintln!("Binary file: {path:?}");
+ }
+ if !results.binary_files.is_empty() {
+ eprintln!("Consider adding binary files to the ignore list in src/licence.rs.");
+ }
+
+ if results.has_failure() {
+ Err(anyhow::anyhow!("License header check failed"))
+ } else {
+ Ok(())
+ }
+ }
+
+ pub fn add_missing(&self, root: &path::Path) -> anyhow::Result<()> {
+ let ignore = self.ignore_globset()?;
+ for p in file_header::add_headers_recursively(
+ root,
+ |p| !ignore.is_match(p),
+ APACHE_2_0.build_header(YearCopyrightOwnerValue::new(
+ u32::try_from(chrono::Utc::now().year())?,
+ "Google LLC".to_string(),
+ )),
+ )? {
+ println!("Added header: {:?}", p);
+ }
+
+ Ok(())
+ }
+
+ fn ignore_globset(&self) -> Result<globset::GlobSet, globset::Error> {
+ let mut builder = globset::GlobSet::builder();
+ for lic in self.ignore {
+ builder.add(globset::Glob::new(lic)?);
+ }
+ builder.build()
+ }
+
+ pub fn check_new_ignore_is_likely_buggy(&self) {
+ for dir in self.ignore {
+ assert!(
+ dir.starts_with("**/"),
+ "Matching on the root filesystem is likely unintended"
+ );
+ }
+ }
+}
diff --git a/nearby/presence/ldt_np_adv_ffi/deny.toml b/common/deny.toml
index ca51e11..bd3f18b 100644
--- a/nearby/presence/ldt_np_adv_ffi/deny.toml
+++ b/common/deny.toml
@@ -17,7 +17,7 @@
# this list would mean the nix crate, as well as any of its exclusive
# dependencies not shared by any other crates, would be ignored, as the target
# list here is effectively saying which targets you are building for.
-targets = [
+graph.targets = [
# The triple can be any string, but only the target triples built in to
# rustc (as of 1.40) can be checked against actual config expressions
#{ triple = "x86_64-unknown-linux-musl" },
@@ -31,24 +31,18 @@ targets = [
# More documentation for the advisories section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
[advisories]
+version = 2
# The path where the advisory database is cloned/fetched into
db-path = "~/.cargo/advisory-db"
# The url(s) of the advisory databases to use
db-urls = ["https://github.com/rustsec/advisory-db"]
-# The lint level for security vulnerabilities
-vulnerability = "deny"
-# The lint level for unmaintained crates
-unmaintained = "warn"
# The lint level for crates that have been yanked from their source registry
yanked = "warn"
-# The lint level for crates with security notices. Note that as of
-# 2019-12-17 there are no security notice advisories in
-# https://github.com/rustsec/advisory-db
-notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
- #"RUSTSEC-0000-0000",
+ # comment explaining why we have to ignore it
+ # "RUSTSEC-FOO",
]
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
# lower than the range specified will be ignored. Note that ignored advisories
@@ -70,37 +64,16 @@ ignore = [
# More documentation for the licenses section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
[licenses]
-# The lint level for crates which do not have a detectable license
-unlicensed = "deny"
+version = 2
# List of explicitly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
allow = [
"MIT",
"Apache-2.0",
- "BSD-3-Clause",
"Unicode-DFS-2016",
+ "ISC",
]
-# List of explicitly disallowed licenses
-# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
-deny = [
- #"Nokia",
-]
-# Lint level for licenses considered copyleft
-copyleft = "warn"
-# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
-# * both - The license will be approved if it is both OSI-approved *AND* FSF
-# * either - The license will be approved if it is either OSI-approved *OR* FSF
-# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
-# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
-# * neither - This predicate is ignored and the default lint level is used
-allow-osi-fsf-free = "neither"
-# Lint level used when no other predicates are matched
-# 1. License isn't in the allow or deny lists
-# 2. License isn't copyleft
-# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
-default = "deny"
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
# canonical license text of a valid SPDX license file.
@@ -111,7 +84,7 @@ confidence-threshold = 0.8
exceptions = [
# Each entry is the crate and version constraint, and its specific allow
# list
- #{ allow = ["Zlib"], name = "adler32", version = "*" },
+
]
# Some crates don't have (easily) machine readable licensing information,
diff --git a/common/derive_fuzztest/Cargo.toml b/common/derive_fuzztest/Cargo.toml
new file mode 100644
index 0000000..6a22ce5
--- /dev/null
+++ b/common/derive_fuzztest/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "derive_fuzztest"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+arbitrary.workspace = true
+derive_fuzztest_macro.workspace = true
+proptest = { workspace = true, optional = true }
+proptest-arbitrary-interop = { workspace = true, optional = true }
+quickcheck = { workspace = true, optional = true }
+
+[features]
+default = ["quickcheck"]
+quickcheck = ["dep:quickcheck", "derive_fuzztest_macro/quickcheck"]
+proptest = [
+ "dep:proptest",
+ "dep:proptest-arbitrary-interop",
+ "derive_fuzztest_macro/proptest",
+]
+
+[lints]
+workspace = true
diff --git a/common/derive_fuzztest/fuzz/.gitignore b/common/derive_fuzztest/fuzz/.gitignore
new file mode 100644
index 0000000..b94a8f4
--- /dev/null
+++ b/common/derive_fuzztest/fuzz/.gitignore
@@ -0,0 +1 @@
+/corpus \ No newline at end of file
diff --git a/common/derive_fuzztest/fuzz/Cargo.toml b/common/derive_fuzztest/fuzz/Cargo.toml
new file mode 100644
index 0000000..1f493b6
--- /dev/null
+++ b/common/derive_fuzztest/fuzz/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "derive_fuzz_example"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[package.metadata]
+cargo-fuzz = true
+
+[dependencies]
+arbitrary.workspace = true
+derive_fuzztest.workspace = true
+quickcheck.workspace = true
+
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
diff --git a/common/derive_fuzztest/fuzz/src/bin/arbitrary.rs b/common/derive_fuzztest/fuzz/src/bin/arbitrary.rs
new file mode 100644
index 0000000..8f8d77b
--- /dev/null
+++ b/common/derive_fuzztest/fuzz/src/bin/arbitrary.rs
@@ -0,0 +1,32 @@
+// 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.
+
+#![cfg_attr(fuzzing, no_main)]
+
+use arbitrary::{Arbitrary, Unstructured};
+use derive_fuzztest::fuzztest;
+
+#[derive(Debug, Clone)]
+pub struct SmallU8(u8);
+
+impl<'a> Arbitrary<'a> for SmallU8 {
+ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
+ Ok(SmallU8(u.int_in_range(0..=127)?))
+ }
+}
+
+#[fuzztest]
+pub fn test(a: SmallU8, b: SmallU8) {
+ let _ = a.0 + b.0; // Succeeds because our custom arbitrary impl only generates 0-127 so it never overflows
+}
diff --git a/common/derive_fuzztest/fuzz/src/bin/integer_add.rs b/common/derive_fuzztest/fuzz/src/bin/integer_add.rs
new file mode 100644
index 0000000..38b8172
--- /dev/null
+++ b/common/derive_fuzztest/fuzz/src/bin/integer_add.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#![cfg_attr(fuzzing, no_main)]
+
+use derive_fuzztest::fuzztest;
+
+#[fuzztest]
+pub fn test(a: u8, b: u8) {
+ let _ = a.checked_add(b);
+ // a + b; // This fails because a + b can overflow.
+}
diff --git a/common/derive_fuzztest/src/lib.rs b/common/derive_fuzztest/src/lib.rs
new file mode 100644
index 0000000..c0dd11c
--- /dev/null
+++ b/common/derive_fuzztest/src/lib.rs
@@ -0,0 +1,141 @@
+// 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.
+
+//! Derive macros that generates both a fuzz target for use with `cargo fuzz`, and a property test
+//! (via `quickcheck` or `proptest`) for use with `cargo test`.
+//!
+//! The reason for having both is that property testing allows for quick iteration to make sure the
+//! test works, and can be checked in presubmit CI, while fuzzing can test the input space more
+//! exhaustively and run continuously.
+//!
+//! # Example
+//!
+//! ```no_run
+//! #![cfg_attr(fuzzing, no_main)]
+//!
+//! #[derive_fuzztest::fuzztest]
+//! fn transitive_ord(a: u32, b: u32, c: u32) {
+//! if a >= b && b >= c {
+//! assert!(a >= c);
+//! }
+//! if a <= b && b <= c {
+//! assert!(a <= c);
+//! }
+//! }
+//!
+//! #[test]
+//! fn additional_test_here() {
+//! /* ... */
+//! }
+//! ```
+//!
+//! # Usage
+//!
+//!
+//! Run the generated property tests
+//! ```sh
+//! cargo test
+//! ```
+//!
+//! Run continuous fuzzing
+//! ```sh
+//! cargo +nightly fuzz run <binary name>
+//! ```
+//!
+//! # Crate structure
+//!
+//! If you use `#[fuzz]` or `#[fuzztest]`, the fuzz target imposes the following requirements:
+//!
+//! * The target must be in a separate `[[bin]]` target that only contains a single fuzz target.
+//! * The crate containing the bin target has `[package.metadata] cargo-fuzz = true`
+//! * The bin target is annotated with `#![cfg_attr(fuzzing, no_main)]`
+//!
+//! The recommended structure for your crate `foo` is to put your tests under `foo/fuzz/src/bin`:
+//!
+//! ```text
+//! foo
+//! ├── fuzz
+//! │ ├── src
+//! │ │ └── bin
+//! │ │ └── fuzz_target_1.rs
+//! │ └── Cargo.toml
+//! ├── src
+//! │ └── [project source]
+//! └── Cargo.toml
+//! ```
+//!
+//! This is different from the default structure generated by `cargo fuzz init` or `cargo fuzz add`
+//! so that we can take advantage of [target
+//! auto-discovery](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#target-auto-discovery).
+//! If you prefer, the default structure generated by `cargo fuzz` can also work, but make sure you
+//! remove `test = false` from the generated target in `Cargo.toml`.
+//!
+//! You will also need to declare a dependency on the `libfuzzer-sys` crate, but only if fuzzing is
+//! requested:
+//!
+//! ```toml
+//! [target.'cfg(fuzzing)'.dependencies]
+//! libfuzzer-sys = "*"
+//! ```
+//!
+//! (The reason for this conditional dependency is that `libfuzzer-sys` injects a main function to
+//! the resulting binary, and there will be linking failures if we link that in without defining a
+//! corresponding `fuzz_target`.)
+//!
+//! # Features
+//!
+//! * `quickcheck` (default) — Enable generation of
+//! [`quickcheck`](https://docs.rs/quickcheck/latest/quickcheck/) property tests.
+//! * `proptest` — Enable generation of [`proptest`](https://docs.rs/proptest/latest/proptest/)
+//! property tests.
+//!
+//! #### See also
+//! * [Announcing Better Support for Fuzzing with Structured Inputs in
+//! Rust](https://fitzgeraldnick.com/2020/01/16/better-support-for-fuzzing-structured-inputs-in-rust.html#how-is-all-this-different-from-quickcheck-and-proptest)
+//! * [Bridging Fuzzing and Property
+//! Testing](https://blog.yoshuawuyts.com/bridging-fuzzing-and-property-testing/)
+
+pub use derive_fuzztest_macro::{fuzz, fuzztest, proptest};
+
+#[doc(hidden)]
+pub mod reexport {
+ #[cfg(feature = "proptest")]
+ pub use proptest;
+ #[cfg(feature = "proptest")]
+ pub use proptest_arbitrary_interop;
+ #[cfg(feature = "quickcheck")]
+ pub use quickcheck;
+}
+
+#[cfg(feature = "quickcheck")]
+#[doc(hidden)]
+pub mod arbitrary_bridge {
+
+ /// Wrapper type that allows `arbitrary::Arbitrary` to be used as `quickcheck::Arbitrary`
+ #[derive(Debug, Clone)]
+ pub struct ArbitraryAdapter<T: for<'a> arbitrary::Arbitrary<'a>>(
+ pub Result<T, arbitrary::Error>,
+ );
+
+ impl<T> quickcheck::Arbitrary for ArbitraryAdapter<T>
+ where
+ T: for<'a> arbitrary::Arbitrary<'a> + Clone + 'static,
+ {
+ fn arbitrary(g: &mut quickcheck::Gen) -> Self {
+ let bytes = Vec::<u8>::arbitrary(g);
+ let mut unstructured = arbitrary::Unstructured::new(&bytes);
+ Self(T::arbitrary(&mut unstructured))
+ }
+ }
+}
diff --git a/common/derive_fuzztest_macro/Cargo.toml b/common/derive_fuzztest_macro/Cargo.toml
new file mode 100644
index 0000000..37b480a
--- /dev/null
+++ b/common/derive_fuzztest_macro/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "derive_fuzztest_macro"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+quote.workspace = true
+proc-macro2.workspace = true
+syn = { workspace = true, features = ["extra-traits"]}
+
+[dev-dependencies]
+derive_fuzztest.workspace = true
+pretty_assertions.workspace = true
+prettyplease.workspace = true
+
+[features]
+quickcheck = []
+proptest = []
+
+[lib]
+proc-macro = true
+doc = false
diff --git a/common/derive_fuzztest_macro/src/lib.rs b/common/derive_fuzztest_macro/src/lib.rs
new file mode 100644
index 0000000..beb692a
--- /dev/null
+++ b/common/derive_fuzztest_macro/src/lib.rs
@@ -0,0 +1,463 @@
+// 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.
+
+//! Internal crate for use by [`derive_fuzztest`](../derive_fuzztest/index.html). See the
+//! documentation there for usage information.
+
+use proc_macro::TokenStream;
+use proc_macro2::TokenStream as TokenStream2;
+use quote::quote;
+use syn::{parse::Nothing, spanned::Spanned, ItemFn, Pat, PatType, Type};
+
+/// Define a fuzz test.
+///
+/// All input parameters of the given function must implement `arbitrary::Arbitrary`.
+///
+/// This macro derives new items based on the given function.
+/// 1. A `fuzz_target!` is generated that can be used with `cargo fuzz`.
+/// 2. Property tests (`quickcheck` or `proptest`, based on which features are enabled) are
+/// generated that can be tested using `cargo test`.
+///
+/// See the crate documentation [`derive_fuzztest`](../derive_fuzztest/index.html) for details.
+#[proc_macro_attribute]
+pub fn fuzztest(attr: TokenStream, item: TokenStream) -> TokenStream {
+ fuzztest_impl(attr.into(), item.into())
+ .unwrap_or_else(|e| e.into_compile_error())
+ .into()
+}
+
+fn fuzztest_impl(attr: TokenStream2, item: TokenStream2) -> syn::Result<TokenStream2> {
+ syn::parse2::<Nothing>(attr)?;
+ let func = syn::parse2::<ItemFn>(item)?;
+ let fn_def = FunctionDefinition::parse(func)?;
+ let original_fn = &fn_def.func;
+ let fuzz_target = derive_fuzz_target(&fn_def);
+ let proptest_target = proptest::derive_proptest(&fn_def);
+ let quickcheck_target = quickcheck::derive_quickcheck(&fn_def);
+
+ Ok(quote! {
+ #[allow(unused)]
+ #original_fn
+ #fuzz_target
+ #proptest_target
+ #quickcheck_target
+ })
+}
+
+/// Define a fuzz target only without corresponding test.
+///
+/// All input parameters of the given function must implement `arbitrary::Arbitrary`.
+///
+/// This macro derives a `fuzz_target!` that can be used with `cargo fuzz`. If you wish to generate
+/// property tests that can be used with `cargo test` as well, use [`fuzztest`][macro@fuzztest].
+///
+/// See the crate documentation [`derive_fuzztest`](../derive_fuzztest/index.html) for details.
+#[proc_macro_attribute]
+pub fn fuzz(attr: TokenStream, item: TokenStream) -> TokenStream {
+ fuzz_impl(attr.into(), item.into())
+ .unwrap_or_else(|e| e.into_compile_error())
+ .into()
+}
+
+fn fuzz_impl(attr: TokenStream2, item: TokenStream2) -> syn::Result<TokenStream2> {
+ syn::parse2::<Nothing>(attr)?;
+ let func = syn::parse2::<ItemFn>(item)?;
+ let fn_def = FunctionDefinition::parse(func)?;
+ let original_fn = &fn_def.func;
+ let fuzz_target = derive_fuzz_target(&fn_def);
+
+ Ok(quote! {
+ #[allow(unused)]
+ #original_fn
+ #fuzz_target
+ })
+}
+
+/// Define a property test.
+///
+/// This is similar to using `quickcheck!` or `proptest::proptest!` directly.
+///
+/// All input parameters of the given function must implement `arbitrary::Arbitrary`.
+///
+/// Unlike [`fuzztest`][macro@fuzztest], this macro does not have to be placed in a `[[bin]]` target
+/// and a single file can contain multiple of these tests. The generated tests can be run with
+/// `cargo test` as usual.
+#[proc_macro_attribute]
+pub fn proptest(attr: TokenStream, item: TokenStream) -> TokenStream {
+ proptest_impl(attr.into(), item.into())
+ .unwrap_or_else(|e| e.into_compile_error())
+ .into()
+}
+
+fn proptest_impl(attr: TokenStream2, item: TokenStream2) -> syn::Result<TokenStream2> {
+ syn::parse2::<Nothing>(attr)?;
+ let func = syn::parse2::<ItemFn>(item)?;
+ let fn_def = FunctionDefinition::parse(func)?;
+ let original_fn = &fn_def.func;
+ let proptest_target = proptest::derive_proptest(&fn_def);
+
+ Ok(quote! {
+ #[allow(unused)]
+ #original_fn
+ #proptest_target
+ })
+}
+
+fn derive_fuzz_target(fn_def: &FunctionDefinition) -> proc_macro2::TokenStream {
+ let FunctionDefinition { func, args, types } = fn_def;
+ let func_ident = &func.sig.ident;
+ quote! {
+ #[automatically_derived]
+ #[cfg(fuzzing)]
+ ::libfuzzer_sys::fuzz_target!(|args: ( #(#types),* )| {
+ let ( #(#args),* ) = args; // https://github.com/rust-fuzz/libfuzzer/issues/77
+ #func_ident ( #(#args),* )
+ });
+
+ #[cfg(not(any(fuzzing, rust_analyzer)))]
+ fn main() {
+ ::std::unreachable!("Run this target with `cargo fuzz` or `cargo test` instead");
+ }
+ }
+}
+
+#[cfg(any(feature = "quickcheck", test))]
+mod quickcheck {
+ use crate::FunctionDefinition;
+ use quote::quote;
+
+ pub(crate) fn derive_quickcheck(fn_def: &FunctionDefinition) -> proc_macro2::TokenStream {
+ let FunctionDefinition { func, args, types } = fn_def;
+ let func_ident = &func.sig.ident;
+ let adapted_types: Vec<_> = types
+ .iter()
+ .map(|ty| quote! { ArbitraryAdapter<#ty> })
+ .collect();
+ let arg_pattern: Vec<_> = args
+ .iter()
+ .map(|arg| quote! { ArbitraryAdapter(::core::result::Result::Ok(#arg)) })
+ .collect();
+ let test_name = quote::format_ident!("quickcheck_{func_ident}");
+ quote! {
+ #[automatically_derived]
+ #[test]
+ fn #test_name() {
+ use ::derive_fuzztest::reexport::quickcheck::TestResult;
+ use ::derive_fuzztest::arbitrary_bridge::ArbitraryAdapter;
+
+ fn inner(args: (#(#adapted_types),*)) -> TestResult {
+ let (#(#arg_pattern),*) = args else { return TestResult::discard() };
+ match ::std::panic::catch_unwind(move || {
+ #func_ident ( #(#args),* );
+ }) {
+ ::core::result::Result::Ok(()) => TestResult::passed(),
+ ::core::result::Result::Err(e) => TestResult::error(::std::format!("{e:?}")),
+ }
+ }
+
+ ::derive_fuzztest::reexport::quickcheck::QuickCheck::new().tests(1024)
+ .quickcheck(inner as fn(_) -> TestResult);
+ }
+ }
+ }
+}
+
+#[cfg(not(any(feature = "quickcheck", test)))]
+mod quickcheck {
+ use crate::FunctionDefinition;
+
+ pub(crate) fn derive_quickcheck(_fn_def: &FunctionDefinition) -> proc_macro2::TokenStream {
+ proc_macro2::TokenStream::default()
+ }
+}
+
+#[cfg(any(feature = "proptest", test))]
+mod proptest {
+ use crate::FunctionDefinition;
+ use quote::quote;
+ use syn::{Ident, Signature};
+
+ pub(crate) fn derive_proptest(fn_def: &FunctionDefinition) -> proc_macro2::TokenStream {
+ let FunctionDefinition { func, args, types } = fn_def;
+ let func_attrs = &func.attrs;
+ let Signature {
+ constness,
+ asyncness,
+ unsafety,
+ abi,
+ fn_token,
+ ident,
+ generics,
+ paren_token: _,
+ inputs: _,
+ variadic: _,
+ output,
+ } = &func.sig;
+ let proptest_ident = Ident::new(&format!("proptest_{ident}"), ident.span());
+ quote! {
+ #[automatically_derived]
+ #[cfg(test)]
+ mod #proptest_ident {
+ use super::*;
+ use ::derive_fuzztest::reexport::proptest;
+ use ::derive_fuzztest::reexport::proptest_arbitrary_interop::arb;
+
+ proptest::proptest! {
+ #![proptest_config(proptest::prelude::ProptestConfig {
+ cases: 1024,
+ failure_persistence: Some(Box::new(proptest::test_runner::FileFailurePersistence::WithSource("regression"))),
+ ..Default::default()
+ })]
+ #[test]
+ #(#func_attrs)*
+ #constness #asyncness #unsafety #abi #fn_token #proptest_ident #generics ( args in arb::<(#(#types),*)>() ) #output {
+ let (#(#args),*) = args;
+ #ident ( #(#args),* );
+ }
+ }
+ }
+ }
+ }
+}
+
+#[cfg(not(any(feature = "proptest", test)))]
+mod proptest {
+ use crate::FunctionDefinition;
+
+ pub(crate) fn derive_proptest(_fn_def: &FunctionDefinition) -> proc_macro2::TokenStream {
+ proc_macro2::TokenStream::default()
+ }
+}
+
+/// Representation of a function definition annotated with one of the attribute macros in this
+/// crate.
+struct FunctionDefinition {
+ func: ItemFn,
+ args: Vec<Pat>,
+ types: Vec<Type>,
+}
+
+impl FunctionDefinition {
+ pub fn parse(func: ItemFn) -> syn::Result<Self> {
+ let (args, types) = func
+ .sig
+ .inputs
+ .clone()
+ .into_iter()
+ .map(|arg| match arg {
+ syn::FnArg::Receiver(arg_receiver) => Err(syn::Error::new(
+ arg_receiver.span(),
+ "Receiver not supported",
+ )),
+ syn::FnArg::Typed(PatType {
+ attrs: _,
+ pat,
+ colon_token: _,
+ ty,
+ }) => Ok((*pat, *ty)),
+ })
+ .try_fold((Vec::new(), Vec::new()), |(mut args, mut types), result| {
+ result.map(|(arg, type_)| {
+ args.push(arg);
+ types.push(type_);
+ (args, types)
+ })
+ })?;
+ Ok(Self { func, args, types })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{fuzz_impl, fuzztest_impl, proptest_impl};
+ use quote::quote;
+ use syn::parse_quote;
+
+ /// Assert that a token stream for a `syn::File` is the same as expected.
+ ///
+ /// Usage is similar to `assert_eq!`:
+ /// ```no_run
+ /// assert_syn_file!(
+ /// macro_impl(quote! {
+ /// fn foobar() {}
+ /// }),
+ /// quote! {
+ /// fn macro_rewritten_foobar() {}
+ /// }
+ /// );
+ /// ```
+ macro_rules! assert_syn_file {
+ ($actual:expr, $expected:expr) => {
+ let actual = syn::parse2::<syn::File>($actual).unwrap();
+ let expected: syn::File = $expected;
+ assert!(
+ actual == expected,
+ "{}",
+ pretty_assertions::StrComparison::new(
+ &prettyplease::unparse(&expected),
+ &prettyplease::unparse(&actual),
+ )
+ )
+ };
+ }
+
+ #[test]
+ fn test_fuzztest_expansion() {
+ assert_syn_file!(
+ fuzztest_impl(
+ quote! {},
+ quote! {
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+ }
+ )
+ .unwrap(),
+ parse_quote! {
+ #[allow(unused)]
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+
+ #[automatically_derived]
+ #[cfg(fuzzing)]
+ ::libfuzzer_sys::fuzz_target!(|args: (&[u8])| {
+ let (input) = args;
+ foobar(input)
+ });
+
+ #[cfg(not(any(fuzzing, rust_analyzer)))]
+ fn main() {
+ ::std::unreachable!("Run this target with `cargo fuzz` or `cargo test` instead");
+ }
+
+ #[automatically_derived]
+ #[cfg(test)]
+ mod proptest_foobar {
+ use super::*;
+ use ::derive_fuzztest::reexport::proptest;
+ use ::derive_fuzztest::reexport::proptest_arbitrary_interop::arb;
+ proptest::proptest! {
+ #![proptest_config(proptest::prelude::ProptestConfig {
+ cases: 1024,
+ failure_persistence: Some(Box::new(proptest::test_runner::FileFailurePersistence::WithSource("regression"))),
+ ..Default::default()
+ })]
+ #[test]
+ fn proptest_foobar(args in arb::<(&[u8])>()) {
+ let (input) = args;
+ foobar(input);
+ }
+ }
+ }
+
+ #[automatically_derived]
+ #[test]
+ fn quickcheck_foobar() {
+ use ::derive_fuzztest::reexport::quickcheck::TestResult;
+ use ::derive_fuzztest::arbitrary_bridge::ArbitraryAdapter;
+
+ fn inner(args: (ArbitraryAdapter<&[u8]>)) -> TestResult {
+ let (ArbitraryAdapter(::core::result::Result::Ok(input))) = args else {
+ return TestResult::discard()
+ };
+ match ::std::panic::catch_unwind(move || {
+ foobar(input);
+ }) {
+ ::core::result::Result::Ok(()) => TestResult::passed(),
+ ::core::result::Result::Err(e) => TestResult::error(::std::format!("{e:?}")),
+ }
+ }
+ ::derive_fuzztest::reexport::quickcheck::QuickCheck::new()
+ .tests(1024)
+ .quickcheck(inner as fn(_) -> TestResult);
+ }
+ }
+ );
+ }
+
+ #[test]
+ fn test_fuzz_expansion() {
+ assert_syn_file!(
+ fuzz_impl(
+ quote! {},
+ quote! {
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+ }
+ )
+ .unwrap(),
+ parse_quote! {
+ #[allow(unused)]
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+
+ #[automatically_derived]
+ #[cfg(fuzzing)]
+ ::libfuzzer_sys::fuzz_target!(|args: (&[u8])| {
+ let (input) = args;
+ foobar(input)
+ });
+
+ #[cfg(not(any(fuzzing, rust_analyzer)))]
+ fn main() {
+ ::std::unreachable!("Run this target with `cargo fuzz` or `cargo test` instead");
+ }
+ }
+ );
+ }
+
+ #[test]
+ fn test_proptest_expansion() {
+ assert_syn_file!(
+ proptest_impl(
+ quote! {},
+ quote! {
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+ }
+ )
+ .unwrap(),
+ parse_quote! {
+ #[allow(unused)]
+ fn foobar(input: &[u8]) {
+ panic!("I am just a test")
+ }
+
+ #[automatically_derived]
+ #[cfg(test)]
+ mod proptest_foobar {
+ use super::*;
+ use ::derive_fuzztest::reexport::proptest;
+ use ::derive_fuzztest::reexport::proptest_arbitrary_interop::arb;
+ proptest::proptest! {
+ #![proptest_config(proptest::prelude::ProptestConfig {
+ cases: 1024,
+ failure_persistence: Some(Box::new(proptest::test_runner::FileFailurePersistence::WithSource("regression"))),
+ ..Default::default()
+ })]
+ #[test]
+ fn proptest_foobar(args in arb::<(&[u8])>()) {
+ let (input) = args;
+ foobar(input);
+ }
+ }
+ }
+ }
+ );
+ }
+}
diff --git a/nearby/util/handle_map/Cargo.toml b/common/handle_map/Cargo.toml
index 13973d4..13973d4 100644
--- a/nearby/util/handle_map/Cargo.toml
+++ b/common/handle_map/Cargo.toml
diff --git a/nearby/util/handle_map/benches/benches.rs b/common/handle_map/benches/benches.rs
index f1988ba..176a54e 100644
--- a/nearby/util/handle_map/benches/benches.rs
+++ b/common/handle_map/benches/benches.rs
@@ -36,7 +36,10 @@ const DEFAULT_SHARDS_AND_THREADS: u8 = 8;
type BenchHandleMap = HandleMap<u8>;
fn build_handle_map(num_shards: u8) -> BenchHandleMap {
- let dimensions = HandleMapDimensions { num_shards, max_active_handles: MAX_ACTIVE_HANDLES };
+ let dimensions = HandleMapDimensions {
+ num_shards,
+ max_active_handles: MAX_ACTIVE_HANDLES,
+ };
HandleMap::with_dimensions(dimensions)
}
@@ -97,12 +100,15 @@ fn single_threaded_allocate_deallocate_near_empty_benchmark(c: &mut Criterion) {
let handle_map = build_handle_map(8);
let handle_map_ref = &handle_map;
// Perform repeated allocation/deallocation pairs
- c.bench_function("single-threaded allocate/deallocate pairs (empty init state)", |b| {
- b.iter(|| {
- let handle = handle_map_ref.allocate(|| black_box(0xDD)).unwrap();
- handle_map_ref.deallocate(handle);
- })
- });
+ c.bench_function(
+ "single-threaded allocate/deallocate pairs (empty init state)",
+ |b| {
+ b.iter(|| {
+ let handle = handle_map_ref.allocate(|| black_box(0xDD)).unwrap();
+ handle_map_ref.deallocate(handle);
+ })
+ },
+ );
}
/// Benchmark for repeated allocation->deallocation starting
@@ -192,18 +198,38 @@ struct ReadWriteCount {
num_writes: usize,
}
-const READS_ONLY: ReadWriteCount = ReadWriteCount { num_reads: 4, num_writes: 0 };
+const READS_ONLY: ReadWriteCount = ReadWriteCount {
+ num_reads: 4,
+ num_writes: 0,
+};
-const READ_LEANING: ReadWriteCount = ReadWriteCount { num_reads: 3, num_writes: 1 };
+const READ_LEANING: ReadWriteCount = ReadWriteCount {
+ num_reads: 3,
+ num_writes: 1,
+};
-const BALANCED: ReadWriteCount = ReadWriteCount { num_reads: 2, num_writes: 2 };
+const BALANCED: ReadWriteCount = ReadWriteCount {
+ num_reads: 2,
+ num_writes: 2,
+};
-const WRITE_LEANING: ReadWriteCount = ReadWriteCount { num_reads: 1, num_writes: 3 };
+const WRITE_LEANING: ReadWriteCount = ReadWriteCount {
+ num_reads: 1,
+ num_writes: 3,
+};
-const WRITES_ONLY: ReadWriteCount = ReadWriteCount { num_reads: 0, num_writes: 4 };
+const WRITES_ONLY: ReadWriteCount = ReadWriteCount {
+ num_reads: 0,
+ num_writes: 4,
+};
-const READ_WRITE_COUNTS: [ReadWriteCount; 5] =
- [READS_ONLY, READ_LEANING, BALANCED, WRITE_LEANING, WRITES_ONLY];
+const READ_WRITE_COUNTS: [ReadWriteCount; 5] = [
+ READS_ONLY,
+ READ_LEANING,
+ BALANCED,
+ WRITE_LEANING,
+ WRITES_ONLY,
+];
/// Benchmarks a repeated allocate/[X writes]/[Y reads]/deallocate workflow across
/// the default number of threads and shards.
diff --git a/nearby/util/handle_map/src/declare_handle_map.rs b/common/handle_map/src/declare_handle_map.rs
index c19a012..89078fa 100644
--- a/nearby/util/handle_map/src/declare_handle_map.rs
+++ b/common/handle_map/src/declare_handle_map.rs
@@ -16,17 +16,18 @@
#[macro_export]
/// ```ignore
-/// declare_handle_map! {
-/// mod $handle_module_name {
-/// #[dimensions = $map_dimension_provider]
-/// type $handle_type_name: HandleLike<Object = $wrapped_type>;
-/// }
-/// }
+/// declare_handle_map! (
+/// $handle_module_name,
+/// $map_dimension_provider,
+/// $handle_type_name,
+/// $wrapped_type,
+/// )
/// ```
///
-/// Declares a new public module with name `handle_module_name` which includes a new type
-/// `handle_type_name` which is `#[repr(C)]` and represents FFI-accessible handles
-/// to values of type `wrapped_type`.
+/// Declares a new public module with name `handle_module_name` which implements handle functionality
+/// for the given struct `handle_type_name` which is `#[repr(C)]` and represents FFI-accessible
+/// handles to values of type `wrapped_type`. `handle_type_name` expects a struct with a single u64
+/// field `handle_id`.
///
/// Internal to the generated module, a new static `SingletonHandleMap` is created, where the
/// maximum number of active handles and the number of shards are given by
@@ -54,14 +55,16 @@
/// }
/// }
///
-/// declare_handle_map! {
-/// mod string_handle {
-/// #[dimensions = super::get_string_handle_map_dimensions()]
-/// type StringHandle: HandleLike<Object = String>;
-/// }
+/// struct StringHandle {
+/// handle_id: u64
/// }
///
-/// use string_handle::StringHandle;
+/// declare_handle_map!(
+/// string_handle,
+/// super::get_string_handle_map_dimensions(),
+/// super::StringHandle,
+/// String
+/// );
///
/// fn main() {
/// // Note: this method could panic if there are
@@ -90,10 +93,10 @@
/// ```
macro_rules! declare_handle_map {
(
- mod $handle_module_name:ident {
- #[dimensions = $map_dimension_provider:expr]
- type $handle_type_name:ident: HandleLike<Object = $wrapped_type:ty>;
- }
+ $handle_module_name:ident,
+ $map_dimension_provider:expr,
+ $handle_type_name:ty,
+ $wrapped_type:ty
) => {
#[doc = ::core::concat!(
"Macro-generated (via `handle_map::declare_handle_map!`) module which",
@@ -102,21 +105,19 @@ macro_rules! declare_handle_map {
" which references values of type `", ::core::stringify!($wrapped_type), "`."
)]
pub mod $handle_module_name {
-
lazy_static! {
static ref GLOBAL_HANDLE_MAP: $crate::HandleMap<$wrapped_type> =
$crate::HandleMap::with_dimensions($map_dimension_provider);
}
+ pub (crate) fn get_current_allocation_count() -> u32 {
+ GLOBAL_HANDLE_MAP.get_current_allocation_count()
+ }
+
#[doc = ::core::concat!(
"A `#[repr(C)]` handle to a value of type `",
::core::stringify!($wrapped_type), "`."
)]
- #[repr(C)]
- #[derive(Clone, Copy, PartialEq, Eq)]
- pub struct $handle_type_name {
- handle_id: u64,
- }
impl $handle_type_name {
/// Cast the given raw Handle to this HandleLike
diff --git a/nearby/util/handle_map/src/guard.rs b/common/handle_map/src/guard.rs
index 0c8c9d7..67d9787 100644
--- a/nearby/util/handle_map/src/guard.rs
+++ b/common/handle_map/src/guard.rs
@@ -14,7 +14,7 @@
use crate::Handle;
use core::ops::{Deref, DerefMut};
-use lock_adapter::std::RwMapping;
+use lock_adapter::stdlib::RwMapping;
use std::collections::HashMap;
use std::marker::PhantomData;
@@ -23,7 +23,7 @@ use std::marker::PhantomData;
/// dropped, the underlying read lock on the associated
/// shard will be dropped.
pub struct ObjectReadGuardImpl<'a, T: 'a> {
- pub(crate) guard: lock_adapter::std::MappedRwLockReadGuard<
+ pub(crate) guard: lock_adapter::stdlib::MappedRwLockReadGuard<
'a,
<Self as ObjectReadGuard>::Arg,
<Self as ObjectReadGuard>::Ret,
@@ -81,7 +81,7 @@ impl<'a, T> ObjectReadGuard for ObjectReadGuardImpl<'a, T> {
/// dropped, the underlying read-write lock on the associated
/// shard will be dropped.
pub struct ObjectReadWriteGuardImpl<'a, T: 'a> {
- pub(crate) guard: lock_adapter::std::MappedRwLockWriteGuard<
+ pub(crate) guard: lock_adapter::stdlib::MappedRwLockWriteGuard<
'a,
<Self as ObjectReadWriteGuard>::Arg,
<Self as ObjectReadWriteGuard>::Ret,
@@ -131,11 +131,13 @@ impl<'a, T> RwMapping for ObjectReadWriteGuardMapping<'a, T> {
fn map<'b>(&self, arg: &'b Self::Arg) -> &'b Self::Ret {
#[allow(clippy::expect_used)]
- arg.get(&self.handle).expect("Caller must verify that provided hande exists")
+ arg.get(&self.handle)
+ .expect("Caller must verify that provided hande exists")
}
fn map_mut<'b>(&self, arg: &'b mut Self::Arg) -> &'b mut Self::Ret {
#[allow(clippy::expect_used)]
- arg.get_mut(&self.handle).expect("Caller must verify that provided hande exists")
+ arg.get_mut(&self.handle)
+ .expect("Caller must verify that provided hande exists")
}
}
diff --git a/nearby/util/handle_map/src/lib.rs b/common/handle_map/src/lib.rs
index 22009c1..72bb78a 100644
--- a/nearby/util/handle_map/src/lib.rs
+++ b/common/handle_map/src/lib.rs
@@ -16,9 +16,7 @@
//! a safer alternative to raw pointers for FFI interop.
use core::fmt::Debug;
-use std::boxed::Box;
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
-use std::vec::Vec;
pub mod declare_handle_map;
mod guard;
@@ -159,21 +157,23 @@ impl<T: Send + Sync> HandleMap<T> {
initial_value_provider: impl FnOnce() -> T,
) -> Result<Handle, HandleMapFullError> {
let wrapped_value_provider = move || Ok(initial_value_provider());
- self.try_allocate::<core::convert::Infallible>(wrapped_value_provider).map_err(
- |e| match e {
+ self.try_allocate::<core::convert::Infallible>(wrapped_value_provider)
+ .map_err(|e| match e {
HandleMapTryAllocateError::ValueProviderFailed(never) => match never {},
HandleMapTryAllocateError::HandleMapFull => HandleMapFullError,
- },
- )
+ })
}
/// Attempts to allocate a new object within the given handle-map, returning
- /// a handle to the location it was stored at. This operation
- /// may fail if attempting to allocate over the `dimensions.max_active_handles`
- /// limit imposed on the handle-map, in which case this method
- /// will return a `HandleMapTryAllocateError::HandleMapFull`,
- /// or if the passed initial-value provider fails, in which case this
- /// will return the error wrapped in `HandleMapTryAllocateError::ValueProviderFailed`.
+ /// a handle to the location it was stored at.
+ ///
+ /// This operation may fail if attempting to allocate over the `dimensions.max_active_handles`
+ /// limit imposed on the handle-map, in which case this method will return a
+ /// `HandleMapTryAllocateError::HandleMapFull` and the given `initial_value_provider` will not
+ /// be run.
+ ///
+ /// The passed initial-value provider may also fail, in which case this will return the error
+ /// wrapped in `HandleMapTryAllocateError::ValueProviderFailed`.
///
/// If your initial-value provider is infallible, see [`Self::allocate`] instead.
pub fn try_allocate<E: Debug>(
@@ -257,10 +257,8 @@ impl<T: Send + Sync> HandleMap<T> {
}
/// Gets the actual number of elements stored in the entire map.
- /// Only suitable for single-threaded sections of tests.
- #[cfg(test)]
- pub(crate) fn len(&self) -> usize {
- self.handle_map_shards.iter().map(|s| s.len()).sum()
+ pub fn get_current_allocation_count(&self) -> u32 {
+ self.outstanding_allocations_counter.load(Ordering::Relaxed)
}
/// Sets the new-handle-id counter to the given value.
diff --git a/nearby/util/handle_map/src/shard.rs b/common/handle_map/src/shard.rs
index e5aad2f..c7cf509 100644
--- a/nearby/util/handle_map/src/shard.rs
+++ b/common/handle_map/src/shard.rs
@@ -13,7 +13,7 @@
// limitations under the License.
use core::ops::{Deref, DerefMut};
-use lock_adapter::std::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+use lock_adapter::stdlib::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use lock_adapter::RwLock as _;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
@@ -52,7 +52,9 @@ pub(crate) struct HandleMapShard<T: Send + Sync> {
impl<T: Send + Sync> Default for HandleMapShard<T> {
fn default() -> Self {
- Self { data: RwLock::new(HashMap::new()) }
+ Self {
+ data: RwLock::new(HashMap::new()),
+ }
}
}
@@ -63,9 +65,14 @@ impl<T: Send + Sync> HandleMapShard<T> {
if read_only_map_ref.contains_key(&handle) {
let object_read_guard = ShardReadGuard::<T>::map(
map_read_guard,
- ObjectReadGuardMapping { handle, _marker: PhantomData },
+ ObjectReadGuardMapping {
+ handle,
+ _marker: PhantomData,
+ },
);
- Ok(ObjectReadGuardImpl { guard: object_read_guard })
+ Ok(ObjectReadGuardImpl {
+ guard: object_read_guard,
+ })
} else {
// Auto-drop the read guard, and return an error
Err(HandleNotPresentError)
@@ -102,9 +109,14 @@ impl<T: Send + Sync> HandleMapShard<T> {
// Expose only the pointed-to object with a mapped read-write guard
let object_read_write_guard = ShardReadWriteGuard::<T>::map(
map_read_write_guard,
- ObjectReadWriteGuardMapping { handle, _marker: PhantomData },
+ ObjectReadWriteGuardMapping {
+ handle,
+ _marker: PhantomData,
+ },
);
- Ok(ObjectReadWriteGuardImpl { guard: object_read_write_guard })
+ Ok(ObjectReadWriteGuardImpl {
+ guard: object_read_write_guard,
+ })
}
pub fn deallocate(
@@ -188,11 +200,4 @@ impl<T: Send + Sync> HandleMapShard<T> {
}
}
}
- /// Gets the actual number of elements stored in this shard.
- /// Only suitable for single-threaded sections of tests.
- #[cfg(test)]
- pub fn len(&self) -> usize {
- let guard = ShardReadWriteLock::<T>::read(&self.data);
- guard.deref().len()
- }
}
diff --git a/nearby/util/handle_map/src/tests.rs b/common/handle_map/src/tests.rs
index 90e773a..658b55d 100644
--- a/nearby/util/handle_map/src/tests.rs
+++ b/common/handle_map/src/tests.rs
@@ -34,8 +34,10 @@ const NUM_SHARDS: u8 = 4;
// Deliberately picking a higher number of threads.
const NUM_ACTIVE_THREADS: u32 = 8;
-const DEFAULT_DIMENSIONS: HandleMapDimensions =
- HandleMapDimensions { num_shards: NUM_SHARDS, max_active_handles: MAX_ACTIVE_HANDLES };
+const DEFAULT_DIMENSIONS: HandleMapDimensions = HandleMapDimensions {
+ num_shards: NUM_SHARDS,
+ max_active_handles: MAX_ACTIVE_HANDLES,
+};
fn build_handle_map<T: Send + Sync>() -> HandleMap<T> {
HandleMap::with_dimensions(DEFAULT_DIMENSIONS)
@@ -67,7 +69,9 @@ where
fn test_read_consistency_same_address() {
let num_repetitions_per_thread = 10000;
let handle_map = build_handle_map::<String>();
- let handle = handle_map.allocate(|| "hello".to_string()).expect("Allocation shouldn't fail");
+ let handle = handle_map
+ .allocate(|| "hello".to_string())
+ .expect("Allocation shouldn't fail");
let test_fn = Arc::new(move || {
let value_ref = handle_map.get(handle).expect("Getting shouldn't fail");
assert_eq!("hello", value_ref.deref());
@@ -92,8 +96,8 @@ fn test_overload_with_allocations() {
});
test_for_each_thread(test_fn, num_repetitions_per_thread);
- let actual_num_active_handles = handle_map_post_function_ref.len();
- assert_eq!(MAX_ACTIVE_HANDLES as usize, actual_num_active_handles);
+ let actual_num_active_handles = handle_map_post_function_ref.get_current_allocation_count();
+ assert_eq!(MAX_ACTIVE_HANDLES, actual_num_active_handles);
}
/// Tests deallocations and allocations near the allocation limit.
@@ -122,8 +126,8 @@ fn test_overload_allocations_deallocations() {
// No matter what happened above, we should have the same number
// of handles as when we started, because every successful allocation
// should have been paired with a successful deallocation.
- let actual_num_active_handles = handle_map_post_function_ref.len();
- assert_eq!((MAX_ACTIVE_HANDLES - 1) as usize, actual_num_active_handles);
+ let actual_num_active_handles = handle_map_post_function_ref.get_current_allocation_count();
+ assert_eq!(MAX_ACTIVE_HANDLES - 1, actual_num_active_handles);
//Verify that we still have space for one more entry after all that.
let _ = handle_map_post_function_ref.allocate(|| 0xEE).unwrap();
@@ -136,15 +140,19 @@ fn test_full_lifecycle_independent_handles() {
let num_repetitions_per_thread = 10000;
let handle_map = build_handle_map::<String>();
let test_fn = Arc::new(move || {
- let handle =
- handle_map.allocate(|| "Hello".to_string()).expect("Allocation shouldn't fail");
+ let handle = handle_map
+ .allocate(|| "Hello".to_string())
+ .expect("Allocation shouldn't fail");
{
- let value_ref = handle_map.get(handle).expect("Getting the value shouldn't fail");
+ let value_ref = handle_map
+ .get(handle)
+ .expect("Getting the value shouldn't fail");
assert_eq!("Hello", &*value_ref);
};
{
- let mut value_mut_ref =
- handle_map.get_mut(handle).expect("Mutating the value shouldn't fail");
+ let mut value_mut_ref = handle_map
+ .get_mut(handle)
+ .expect("Mutating the value shouldn't fail");
value_mut_ref.deref_mut().push_str(" World!");
};
{
@@ -153,7 +161,9 @@ fn test_full_lifecycle_independent_handles() {
.expect("Getting the value after modification shouldn't fail");
assert_eq!("Hello World!", &*value_ref);
};
- let removed = handle_map.deallocate(handle).expect("Deallocation shouldn't fail");
+ let removed = handle_map
+ .deallocate(handle)
+ .expect("Deallocation shouldn't fail");
assert_eq!("Hello World!", removed);
});
test_for_each_thread(test_fn, num_repetitions_per_thread);
@@ -175,8 +185,9 @@ fn test_consistency_of_same_handle_multithreaded_modifications() {
let join_handle_a = thread::spawn(move || {
for i in 1..num_repetitions_per_thread {
{
- let value_ref =
- handle_map.get(handle).expect("Getting the value from thread A shouldn't fail");
+ let value_ref = handle_map
+ .get(handle)
+ .expect("Getting the value from thread A shouldn't fail");
let value = &value_ref.0;
assert_eq!(i, value.len());
}
@@ -221,7 +232,9 @@ fn test_non_overwriting_old_handles() {
let num_repetitions_per_thread = 100;
let mut handle_map = build_handle_map::<u8>();
for _ in 0..(num_repetitions_per_thread * NUM_ACTIVE_THREADS) {
- let handle = handle_map.allocate(|| 0xFF).expect("Initial allocations shouldn't fail");
+ let handle = handle_map
+ .allocate(|| 0xFF)
+ .expect("Initial allocations shouldn't fail");
let _ = all_handles.insert(handle);
}
// Reset the new-handle-id counter
@@ -245,7 +258,9 @@ fn test_non_overwriting_old_handles() {
thread_handles.push(thread_handle);
}
for thread_handle in thread_handles {
- let handles: Vec<Handle> = thread_handle.join().expect("Individual threads shouldn't fail");
+ let handles: Vec<Handle> = thread_handle
+ .join()
+ .expect("Individual threads shouldn't fail");
for handle in handles {
let was_distinct = all_handles.insert(handle);
assert!(was_distinct);
@@ -257,16 +272,23 @@ fn test_non_overwriting_old_handles() {
fn test_id_wraparound() {
let mut handle_map = build_handle_map::<u8>();
handle_map.set_new_handle_id_counter(u64::MAX);
- let _ = handle_map.allocate(|| 0xAB).expect("Counter wrap-around allocation should not fail");
- let _ =
- handle_map.allocate(|| 0xCD).expect("Post-counter-wrap-around allocation should not fail");
+ let _ = handle_map
+ .allocate(|| 0xAB)
+ .expect("Counter wrap-around allocation should not fail");
+ let _ = handle_map
+ .allocate(|| 0xCD)
+ .expect("Post-counter-wrap-around allocation should not fail");
}
#[test]
fn test_deallocate_unallocated_handle() {
let handle_map = build_handle_map::<usize>();
- let handle = handle_map.allocate(|| 2).expect("Allocation shouldn't fail");
- let deallocated = handle_map.deallocate(handle).expect("Deallocation shouldn't fail");
+ let handle = handle_map
+ .allocate(|| 2)
+ .expect("Allocation shouldn't fail");
+ let deallocated = handle_map
+ .deallocate(handle)
+ .expect("Deallocation shouldn't fail");
assert_eq!(2, deallocated);
let double_deallocate_result = handle_map.deallocate(handle);
assert!(double_deallocate_result.is_err());
@@ -275,8 +297,12 @@ fn test_deallocate_unallocated_handle() {
#[test]
fn test_get_unallocated_handle() {
let handle_map = build_handle_map::<u8>();
- let handle = handle_map.allocate(|| 0xFE).expect("Allocation shouldn't fail");
- let deallocated = handle_map.deallocate(handle).expect("Deallocation shouldn't fail");
+ let handle = handle_map
+ .allocate(|| 0xFE)
+ .expect("Allocation shouldn't fail");
+ let deallocated = handle_map
+ .deallocate(handle)
+ .expect("Deallocation shouldn't fail");
assert_eq!(0xFE, deallocated);
let read_result = handle_map.get(handle);
assert!(read_result.is_err());
@@ -285,8 +311,12 @@ fn test_get_unallocated_handle() {
#[test]
fn test_get_mut_unallocated_handle() {
let handle_map = build_handle_map::<(usize, usize, usize)>();
- let handle = handle_map.allocate(|| (1, 2, 3)).expect("Allocation shouldn't fail");
- let deallocated = handle_map.deallocate(handle).expect("Deallocation shouldn't fail");
+ let handle = handle_map
+ .allocate(|| (1, 2, 3))
+ .expect("Allocation shouldn't fail");
+ let deallocated = handle_map
+ .deallocate(handle)
+ .expect("Deallocation shouldn't fail");
assert_eq!((1, 2, 3), deallocated);
let get_mut_result = handle_map.get_mut(handle);
assert!(get_mut_result.is_err());
diff --git a/nearby/util/lock_adapter/Cargo.toml b/common/lock_adapter/Cargo.toml
index 6e3174b..6e3174b 100644
--- a/nearby/util/lock_adapter/Cargo.toml
+++ b/common/lock_adapter/Cargo.toml
diff --git a/nearby/util/lock_adapter/src/lib.rs b/common/lock_adapter/src/lib.rs
index 6bf6f0f..1c77ee8 100644
--- a/nearby/util/lock_adapter/src/lib.rs
+++ b/common/lock_adapter/src/lib.rs
@@ -15,7 +15,10 @@
//! An abstraction layer for Rust synchronization primitives which provides both no_std and std library
//! based implementations
-#![cfg_attr(not(feature = "std"), no_std)]
+#![no_std]
+
+#[cfg(feature = "std")]
+extern crate std;
/// A Spinlock-based implementation of Mutex using the `spin` crate that can be used in `no_std`
/// environments.
@@ -28,7 +31,7 @@ pub mod spin;
///
/// Available with the feature `std`.
#[cfg(feature = "std")]
-pub mod std;
+pub mod stdlib;
/// A trait for mutex implementations that doesn't support poisoning. If the thread panicked while
/// holding the mutex, the data will be released normally (as spin::Mutex would).
diff --git a/nearby/util/lock_adapter/src/spin.rs b/common/lock_adapter/src/spin.rs
index e894cef..e894cef 100644
--- a/nearby/util/lock_adapter/src/spin.rs
+++ b/common/lock_adapter/src/spin.rs
diff --git a/nearby/util/lock_adapter/src/std.rs b/common/lock_adapter/src/stdlib.rs
index c950d85..c950d85 100644
--- a/nearby/util/lock_adapter/src/std.rs
+++ b/common/lock_adapter/src/stdlib.rs
diff --git a/common/pourover/Cargo.toml b/common/pourover/Cargo.toml
new file mode 100644
index 0000000..eb03cdb
--- /dev/null
+++ b/common/pourover/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "pourover"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[lints]
+workspace = true
+# Needed for FFI, but cannot be overidden in this file. Usages will be marked
+# with `#[allow(unsafe_code)]`.
+# rust.unsafe_code = "allow"
+
+[dependencies]
+jni.workspace = true
+pourover_macro.workspace = true
+
+[dev-dependencies]
+# Enable JVM creation for `tests/desc_integration.rs`
+jni = { workspace = true, features = ["invocation"] }
diff --git a/common/pourover/src/conversions.rs b/common/pourover/src/conversions.rs
new file mode 100644
index 0000000..e311e6d
--- /dev/null
+++ b/common/pourover/src/conversions.rs
@@ -0,0 +1,90 @@
+// 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.
+
+//! Helper traits to convert byte signedness for Java interop
+
+/// A helper trait to bitcast data to its signed representation
+pub trait ToSigned {
+ /// The signed version of this type.
+ type Signed;
+
+ /// Bitcast to signed
+ fn to_signed(self) -> Self::Signed;
+}
+
+impl<'a> ToSigned for &'a [u8] {
+ type Signed = &'a [i8];
+
+ #[allow(unsafe_code)]
+ fn to_signed(self) -> Self::Signed {
+ let len = self.len();
+ // Safety:
+ // u8 and i8 have the same layout and the lifetime is maintained
+ unsafe { core::slice::from_raw_parts(self.as_ptr() as *const i8, len) }
+ }
+}
+
+/// A helper trait to bitcast data to its unsigned representation
+pub trait ToUnsigned {
+ /// The unsigned version of this type.
+ type Unsigned;
+
+ /// Bitcast to unsigned
+ fn to_unsigned(self) -> Self::Unsigned;
+}
+
+impl<'a> ToUnsigned for &'a [i8] {
+ type Unsigned = &'a [u8];
+
+ #[allow(unsafe_code)]
+ fn to_unsigned(self) -> Self::Unsigned {
+ let len = self.len();
+ // Safety:
+ // u8 and i8 have the same layout and the lifetime is maintained
+ unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, len) }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_to_signed() {
+ let input: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe];
+ let expected: &[i8] = &[1, 2, 3, 0, -1, -2];
+
+ assert_eq!(expected, input.to_signed());
+ }
+
+ #[test]
+ fn test_to_unsigned() {
+ let input: &[i8] = &[1, 2, 3, 0, -1, -2];
+ let expected: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe];
+
+ assert_eq!(expected, input.to_unsigned());
+ }
+
+ #[test]
+ fn test_roundtrip_unsigned() {
+ let case: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe];
+ assert_eq!(case, case.to_signed().to_unsigned());
+ }
+
+ #[test]
+ fn test_roundtrip_signed() {
+ let case: &[i8] = &[1, 2, 3, 0, -1, -2];
+ assert_eq!(case, case.to_unsigned().to_signed());
+ }
+}
diff --git a/common/pourover/src/desc.rs b/common/pourover/src/desc.rs
new file mode 100644
index 0000000..26bada6
--- /dev/null
+++ b/common/pourover/src/desc.rs
@@ -0,0 +1,396 @@
+// 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.
+
+//! Cacheable descriptors. These `jni` crate compatible descriptors will cache their value on first
+//! lookup. They are meant to be combined with static variables in order to globally cache their
+//! associated id values.
+//!
+//! ### Example
+//!
+//! ```java
+//! package com.example;
+//!
+//! public class MyClass {
+//! public int foo;
+//! public int getBar() { /* ... */ }
+//! }
+//! ```
+//!
+//! ```rust
+//! use pourover::desc::*;
+//!
+//! static MY_CLASS_DESC: ClassDesc = ClassDesc::new("com/example/MyClass");
+//! static MY_CLASS_FOO_FIELD: FieldDesc = MY_CLASS_DESC.field("foo", "I");
+//! static MY_CLASS_GET_BAR_METHOD: MethodDesc = MY_CLASS_DESC.method("getBar", "I()");
+//! ```
+
+#![allow(unsafe_code)]
+
+use jni::{
+ descriptors::Desc,
+ objects::{GlobalRef, JClass, JFieldID, JMethodID, JObject, JStaticFieldID, JStaticMethodID},
+ JNIEnv,
+};
+use std::sync::{LockResult, RwLock, RwLockReadGuard};
+
+/// JNI descriptor that caches a Java class.
+pub struct ClassDesc {
+ /// The JNI descriptor for this class.
+ descriptor: &'static str,
+ /// The cached class
+ ///
+ /// The implementation assumes that `None` is only written to the lock when `&mut self` is
+ /// held. Only `Some` is valid to write to this lock while `&self` is held.
+ cls: RwLock<Option<GlobalRef>>,
+}
+
+impl ClassDesc {
+ /// Create a new descriptor with the given JNI descriptor string.
+ pub const fn new(descriptor: &'static str) -> Self {
+ Self {
+ descriptor,
+ cls: RwLock::new(None),
+ }
+ }
+
+ /// Create a new descriptor for a field member of this class.
+ pub const fn field<'cls>(&'cls self, name: &'static str, sig: &'static str) -> FieldDesc<'cls> {
+ FieldDesc::new(self, name, sig)
+ }
+
+ /// Create a new descriptor for a static field member of this class.
+ pub const fn static_field<'cls>(
+ &'cls self,
+ name: &'static str,
+ sig: &'static str,
+ ) -> StaticFieldDesc<'cls> {
+ StaticFieldDesc::new(self, name, sig)
+ }
+
+ /// Create a new descriptor for a method member of this class.
+ pub const fn method<'cls>(
+ &'cls self,
+ name: &'static str,
+ sig: &'static str,
+ ) -> MethodDesc<'cls> {
+ MethodDesc::new(self, name, sig)
+ }
+
+ /// Create a new descriptor for a constructor for this class.
+ pub const fn constructor<'cls>(&'cls self, sig: &'static str) -> MethodDesc<'cls> {
+ MethodDesc::new(self, "<init>", sig)
+ }
+
+ /// Create a new descriptor for a static method member of this class.
+ pub const fn static_method<'cls>(
+ &'cls self,
+ name: &'static str,
+ sig: &'static str,
+ ) -> StaticMethodDesc<'cls> {
+ StaticMethodDesc::new(self, name, sig)
+ }
+
+ /// Free the cached GlobalRef to the class object. This will happen automatically on drop, but
+ /// this method is provided to allow the value to be dropped early. This can be used to perform
+ /// cleanup on a thread that is already attached to the JVM.
+ pub fn free(&mut self) {
+ // Get a mutable reference ignoring poison state
+ let mut guard = self.cls.write().ignore_poison();
+ let global = guard.take();
+ // Drop the guard before global in case it panics. We don't want to poison the lock.
+ core::mem::drop(guard);
+ // Drop the GlobalRef value to cleanup
+ core::mem::drop(global);
+ }
+
+ fn get_cached(&self) -> Option<CachedClass<'_>> {
+ CachedClass::from_lock(&self.cls)
+ }
+}
+
+/// Wrapper to allow RwLock references to be returned from Desc. Use the `AsRef` impl to get the
+/// associated `JClass` reference. The inner `Option` must always be `Some`. This is enfocred by
+/// the `from_lock` constructor.
+pub struct CachedClass<'lock>(RwLockReadGuard<'lock, Option<GlobalRef>>);
+
+impl<'lock> CachedClass<'lock> {
+ /// Read from the given lock and create a `CachedClass` instance if the lock contains a cached
+ /// class value. The given lock must have valid data even if it is poisoned.
+ fn from_lock(lock: &'lock RwLock<Option<GlobalRef>>) -> Option<CachedClass<'lock>> {
+ let guard = lock.read().ignore_poison();
+
+ // Validate that there is a GlobalRef value already, otherwise avoid constructing `Self`.
+ if guard.is_some() {
+ Some(Self(guard))
+ } else {
+ None
+ }
+ }
+}
+
+// Implement AsRef so that we can use this type as `Desc::Output` in [`ClassDesc`].
+impl<'lock> AsRef<JClass<'static>> for CachedClass<'lock> {
+ fn as_ref(&self) -> &JClass<'static> {
+ // `unwrap` is valid since we checked for `Some` in the constructor.
+ #[allow(clippy::expect_used)]
+ let global = self
+ .0
+ .as_ref()
+ .expect("Created CachedClass in an invalid state");
+ // No direct conversion to JClass, so let's go through JObject first.
+ let obj: &JObject<'static> = global.as_ref();
+ // This assumes our object is a class object.
+ let cls: &JClass<'static> = From::from(obj);
+ cls
+ }
+}
+
+/// # Safety
+///
+/// This returns the correct class instance via `JNIEnv::find_class`. The cached class is held in a
+/// [`GlobalRef`] so that it cannot be unloaded.
+unsafe impl<'a, 'local> Desc<'local, JClass<'static>> for &'a ClassDesc {
+ type Output = CachedClass<'a>;
+
+ fn lookup(self, env: &mut JNIEnv<'local>) -> jni::errors::Result<Self::Output> {
+ // Check the cache
+ if let Some(cls) = self.get_cached() {
+ return Ok(cls);
+ }
+
+ {
+ // Ignoring poison is fine because we only write fully-constructed values.
+ let mut guard = self.cls.write().ignore_poison();
+
+ // Multiple threads could have hit this block at the same time. Only allocate the
+ // `GlobalRef` if it was not already allocated.
+ if guard.is_none() {
+ let cls = env.find_class(self.descriptor)?;
+ let global = env.new_global_ref(cls)?;
+
+ // Only directly assign valid values. That way poison state can't have broken
+ // invariants. If the above panicked then it will poison without changing the
+ // lock's data, and everything will still be fine albeit with a sprinkle of
+ // possibly-leaked memory.
+ *guard = Some(global);
+ }
+ }
+
+ // Safe to unwrap since we just set `self.cls` to `Some`. `ClassDesc::free` can't be called
+ // before this point because it takes a mutable reference to `*self`.
+ #[allow(clippy::unwrap_used)]
+ Ok(self.get_cached().unwrap())
+ }
+}
+
+/// A descriptor for a class member. `Id` is expected to implement the [`MemberId`] trait.
+///
+/// See [`FieldDesc`], [`StaticFieldDesc`], [`MethodDesc`], and [`StaticMethodDesc`] aliases.
+pub struct MemberDesc<'cls, Id> {
+ cls: &'cls ClassDesc,
+ name: &'static str,
+ sig: &'static str,
+ id: RwLock<Option<Id>>,
+}
+
+/// Descriptor for a field.
+pub type FieldDesc<'cls> = MemberDesc<'cls, JFieldID>;
+/// Descriptor for a static field.
+pub type StaticFieldDesc<'cls> = MemberDesc<'cls, JStaticFieldID>;
+/// Descriptor for a method.
+pub type MethodDesc<'cls> = MemberDesc<'cls, JMethodID>;
+/// Descriptor for a static method.
+pub type StaticMethodDesc<'cls> = MemberDesc<'cls, JStaticMethodID>;
+
+impl<'cls, Id: MemberId> MemberDesc<'cls, Id> {
+ /// Create a new descriptor for a member of the given class with the given name and signature.
+ ///
+ /// Please use the helpers on [`ClassDesc`] instead of directly calling this method.
+ pub const fn new(cls: &'cls ClassDesc, name: &'static str, sig: &'static str) -> Self {
+ Self {
+ cls,
+ name,
+ sig,
+ id: RwLock::new(None),
+ }
+ }
+
+ /// Get the class descriptor that this member is associated to.
+ pub const fn cls(&self) -> &'cls ClassDesc {
+ self.cls
+ }
+}
+
+/// # Safety
+///
+/// This returns the correct id. It is the same id obtained from the JNI. This id can be a pointer
+/// in some JVM implementations. See trait [`MemberId`].
+unsafe impl<'cls, 'local, Id: MemberId> Desc<'local, Id> for &MemberDesc<'cls, Id> {
+ type Output = Id;
+
+ fn lookup(self, env: &mut JNIEnv<'local>) -> jni::errors::Result<Self::Output> {
+ // Check the cache.
+ if let Some(id) = *self.id.read().ignore_poison() {
+ return Ok(id);
+ }
+
+ {
+ // Ignoring poison is fine because we only write valid values.
+ let mut guard = self.id.write().ignore_poison();
+
+ // Multiple threads could have hit this block at the same time. Only lookup the id if
+ // the lookup was not already performed.
+ if guard.is_none() {
+ let id = Id::lookup(env, self)?;
+
+ // Only directly assign valid values. That way poison state can't have broken
+ // invariants. If the above panicked then it will poison without changing the
+ // lock's data and everything will still be fine.
+ *guard = Some(id);
+
+ Ok(id)
+ } else {
+ // Can unwrap since we just checked for `None`.
+ #[allow(clippy::unwrap_used)]
+ Ok(*guard.as_ref().unwrap())
+ }
+ }
+ }
+}
+
+/// Helper trait that calls into `jni` to lookup the id values. This is specialized on the id's
+/// type to call the correct lookup function.
+///
+/// # Safety
+///
+/// Implementers must be an ID returned from the JNI. `lookup` must be implemented such that the
+/// returned ID matches the JNI descriptor given. All values must be sourced from the JNI APIs.
+/// See [`::jni::descriptors::Desc`].
+pub unsafe trait MemberId: Sized + Copy + AsRef<Self> {
+ /// Lookup the id of the given descriptor via the given environment.
+ fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self>;
+}
+
+/// # Safety
+///
+/// This fetches the matching ID from the JNI APIs.
+unsafe impl MemberId for JFieldID {
+ fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
+ env.get_field_id(desc.cls(), desc.name, desc.sig)
+ }
+}
+
+/// # Safety
+///
+/// This fetches the matching ID from the JNI APIs.
+unsafe impl MemberId for JStaticFieldID {
+ fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
+ env.get_static_field_id(desc.cls(), desc.name, desc.sig)
+ }
+}
+
+/// # Safety
+///
+/// This fetches the matching ID from the JNI APIs.
+unsafe impl MemberId for JMethodID {
+ fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
+ env.get_method_id(desc.cls(), desc.name, desc.sig)
+ }
+}
+
+/// # Safety
+///
+/// This fetches the matching ID from the JNI APIs.
+unsafe impl MemberId for JStaticMethodID {
+ fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
+ env.get_static_method_id(desc.cls(), desc.name, desc.sig)
+ }
+}
+
+/// Internal helper to ignore the poison state of `LockResult`.
+///
+/// The poison state occurs when a panic occurs during the lock's critical section. This means that
+/// the invariants of the locked data that were protected by the lock may be broken. When this
+/// trait is used below, it is used in scenarios where the locked data does not have invariants
+/// that can be broken in this way. In these cases, the possibly-poisoned lock is being used purely
+/// for synchronization, so the poison state may be ignored.
+trait IgnoreLockPoison {
+ type Guard;
+
+ /// Extract the inner `Guard` of this `LockResult`. This ignores whether the lock state is
+ /// poisoned or not.
+ fn ignore_poison(self) -> Self::Guard;
+}
+
+impl<G> IgnoreLockPoison for LockResult<G> {
+ type Guard = G;
+ fn ignore_poison(self) -> Self::Guard {
+ self.unwrap_or_else(|poison| poison.into_inner())
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ const DESC: &str = "com/example/Foo";
+ static FOO: ClassDesc = ClassDesc::new(DESC);
+
+ static FIELD: FieldDesc = FOO.field("foo", "I");
+ static STATIC_FIELD: StaticFieldDesc = FOO.static_field("sfoo", "J");
+ static CONSTRUCTOR: MethodDesc = FOO.constructor("(I)V");
+ static METHOD: MethodDesc = FOO.method("mfoo", "()Z");
+ static STATIC_METHOD: StaticMethodDesc = FOO.static_method("smfoo", "()I");
+
+ #[test]
+ fn class_desc_created_properly() {
+ assert_eq!(DESC, FOO.descriptor);
+ assert!(FOO.cls.read().ignore_poison().is_none());
+ }
+
+ #[test]
+ fn field_desc_created_properly() {
+ assert!(std::ptr::eq(&FOO, FIELD.cls()));
+ assert_eq!("foo", FIELD.name);
+ assert_eq!("I", FIELD.sig);
+ }
+
+ #[test]
+ fn static_field_desc_created_properly() {
+ assert!(std::ptr::eq(&FOO, STATIC_FIELD.cls()));
+ assert_eq!("sfoo", STATIC_FIELD.name);
+ assert_eq!("J", STATIC_FIELD.sig);
+ }
+
+ #[test]
+ fn constructor_desc_created_properly() {
+ assert!(std::ptr::eq(&FOO, CONSTRUCTOR.cls()));
+ assert_eq!("<init>", CONSTRUCTOR.name);
+ assert_eq!("(I)V", CONSTRUCTOR.sig);
+ }
+
+ #[test]
+ fn method_desc_created_properly() {
+ assert!(std::ptr::eq(&FOO, METHOD.cls()));
+ assert_eq!("mfoo", METHOD.name);
+ assert_eq!("()Z", METHOD.sig);
+ }
+
+ #[test]
+ fn static_method_desc_created_properly() {
+ assert!(std::ptr::eq(&FOO, STATIC_METHOD.cls()));
+ assert_eq!("smfoo", STATIC_METHOD.name);
+ assert_eq!("()I", STATIC_METHOD.sig);
+ }
+}
diff --git a/common/pourover/src/lib.rs b/common/pourover/src/lib.rs
new file mode 100644
index 0000000..ed861ea
--- /dev/null
+++ b/common/pourover/src/lib.rs
@@ -0,0 +1,22 @@
+// 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.
+
+//! Utilties for JNI interactions.
+
+pub use pourover_macro::{call_constructor, call_method, call_static_method, jni_method};
+
+pub mod desc;
+
+mod conversions;
+pub use conversions::{ToSigned, ToUnsigned};
diff --git a/common/pourover/tests/Foo.java b/common/pourover/tests/Foo.java
new file mode 100644
index 0000000..eb76e9b
--- /dev/null
+++ b/common/pourover/tests/Foo.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.example;
+
+/** Test class for integration tests. See {@code common/foo_class.rs} for how to compile and use. */
+public final class Foo {
+
+ public static long sfoo = 321;
+
+ public int foo;
+
+ public static int smfoo() {
+ return 3;
+ }
+
+ public Foo(int f) {
+ this.foo = f;
+ }
+
+ public int getFoo() {
+ return foo;
+ }
+
+ public boolean mfoo() {
+ return true;
+ }
+
+ public native int nativeReturnsInt(int n);
+
+ public native String nativeReturnsObject(int n);
+}
diff --git a/common/pourover/tests/call_method_integration.rs b/common/pourover/tests/call_method_integration.rs
new file mode 100644
index 0000000..5de2547
--- /dev/null
+++ b/common/pourover/tests/call_method_integration.rs
@@ -0,0 +1,48 @@
+// 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.
+
+use jni::{objects::JObject, JavaVM};
+use std::error::Error;
+
+mod common;
+use common::foo_class::*;
+
+#[test]
+fn jni_access() -> Result<(), Box<dyn Error>> {
+ // Create the environment
+ let vm = JavaVM::new(
+ jni::InitArgsBuilder::new()
+ .version(jni::JNIVersion::V8)
+ .option("-Xcheck:jni")
+ .build()?,
+ )?;
+ let mut env = vm.attach_current_thread()?;
+
+ // Load `Foo.class`
+ {
+ let foo_class = compile_foo()?;
+ let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?;
+ env.delete_local_ref(loaded_foo)?;
+ }
+
+ let foo_obj = pourover::call_constructor!(&mut env, &FOO, "(I)V", 123)?;
+ let inner_int = pourover::call_method!(&mut env, &FOO, "getFoo", "()I", &foo_obj)?;
+ assert_eq!(123, inner_int);
+ env.delete_local_ref(foo_obj)?;
+
+ let static_int = pourover::call_static_method!(&mut env, &FOO, "smfoo", "()I")?;
+ assert_eq!(3, static_int);
+
+ Ok(())
+}
diff --git a/common/pourover/tests/common/foo_class.rs b/common/pourover/tests/common/foo_class.rs
new file mode 100644
index 0000000..3ded762
--- /dev/null
+++ b/common/pourover/tests/common/foo_class.rs
@@ -0,0 +1,89 @@
+// 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.
+
+//! Java integration for the `Foo.java` test class.
+//!
+//! There are pourover descriptors for each member of `Foo`. Keep these in sync with changes to
+//! `Foo.java`.
+//!
+//! Compilation is done at runtime. There isn't a way to create a build.rs for an integration test.
+//! use [`compile_foo`] to get the class bytes and load the class using
+//! [`jni::JNIEnv::define_class`].
+
+use pourover::desc::*;
+use std::error::Error;
+use std::process::Command;
+
+pub const CLASS_DESC: &str = "com/example/Foo";
+pub static FOO: ClassDesc = ClassDesc::new(CLASS_DESC);
+
+pub static FIELD: FieldDesc = FOO.field("foo", "I");
+pub static STATIC_FIELD: StaticFieldDesc = FOO.static_field("sfoo", "J");
+pub static CONSTRUCTOR: MethodDesc = FOO.constructor("(I)V");
+pub static METHOD: MethodDesc = FOO.method("mfoo", "()Z");
+pub static STATIC_METHOD: StaticMethodDesc = FOO.static_method("smfoo", "()I");
+pub static NATIVE_METHOD: MethodDesc = FOO.method("nativeReturnsInt", "(I)I");
+pub static NATIVE_OBJECT_METHOD: MethodDesc =
+ FOO.method("nativeReturnsObject", "(I)Ljava/lang/String;");
+
+/// Quick test to ensure that Java is available on the system. The version will be logged to
+/// stdout.
+#[test]
+fn has_java() -> Result<(), Box<dyn Error>> {
+ let _ = Command::new("java").arg("--version").status()?;
+ Ok(())
+}
+
+/// Compile `Foo.java` and return the class file's bytes.
+#[track_caller]
+pub fn compile_foo() -> Result<Vec<u8>, Box<dyn Error>> {
+ // Avoid concurrent tests colliding on the file system by adding a hash of the call-site to the
+ // temp file path
+ let caller_hash = {
+ use core::hash::{Hash, Hasher};
+ let caller = core::panic::Location::caller();
+ let mut hasher = std::collections::hash_map::DefaultHasher::new();
+ caller.hash(&mut hasher);
+ hasher.finish()
+ };
+
+ // Create a temporary dir to generate class files
+ let mut tmp = std::env::temp_dir();
+ tmp.push(format!("test-java-build-{caller_hash:016x}"));
+
+ if let Err(err) = std::fs::create_dir(&tmp) {
+ println!("error creating {}: {}", tmp.display(), &err);
+ }
+
+ // Compile Foo.java into the temp dir
+ let _ = Command::new("javac")
+ .args(["--release", "8"])
+ .arg("-d")
+ .arg(&tmp)
+ .arg("tests/Foo.java")
+ .status()?;
+
+ // Read the class file bytes
+ let class = {
+ let mut class_file = tmp.clone();
+ class_file.push("com/example/Foo.class");
+ std::fs::read(&class_file)?
+ };
+
+ // Clean up the temp dir. If an error occurs before this we will leave the temp dir on the
+ // filesystem. That should work better for debugging than cleaning up in all cases.
+ std::fs::remove_dir_all(&tmp)?;
+
+ Ok(class)
+}
diff --git a/common/pourover/tests/common/mod.rs b/common/pourover/tests/common/mod.rs
new file mode 100644
index 0000000..1dad720
--- /dev/null
+++ b/common/pourover/tests/common/mod.rs
@@ -0,0 +1,21 @@
+// 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.
+
+//! Common module for pourover integration tests. This file must use the `mod.rs` name to avoid
+//! being compiled as an integration test.
+
+// Not every item is used in every test
+#![allow(dead_code)]
+
+pub mod foo_class;
diff --git a/common/pourover/tests/desc_integration.rs b/common/pourover/tests/desc_integration.rs
new file mode 100644
index 0000000..dd330c3
--- /dev/null
+++ b/common/pourover/tests/desc_integration.rs
@@ -0,0 +1,107 @@
+// 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.
+
+#![allow(unsafe_code)]
+
+use jni::{
+ descriptors::Desc,
+ objects::JObject,
+ signature::{JavaType, Primitive, ReturnType},
+ JavaVM,
+};
+use std::error::Error;
+
+mod common;
+use common::foo_class::*;
+
+#[test]
+fn jni_access() -> Result<(), Box<dyn Error>> {
+ // Create the environment
+ let vm = JavaVM::new(
+ jni::InitArgsBuilder::new()
+ .version(jni::JNIVersion::V8)
+ .option("-Xcheck:jni")
+ .build()?,
+ )?;
+ let mut env = vm.attach_current_thread()?;
+
+ // Load `Foo.class`
+ {
+ let foo_class = compile_foo()?;
+ let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?;
+ let loaded_foo = env.auto_local(loaded_foo);
+
+ let found_foo = FOO.lookup(&mut env)?;
+ assert!(env.is_same_object(&loaded_foo, found_foo.as_ref())?);
+ }
+
+ // Verify we can call the constructor
+ let obj_foo = {
+ let method_id = CONSTRUCTOR.lookup(&mut env)?;
+ let args = &[jni::sys::jvalue { i: 123 }];
+ // Safety: `args` must match the constructor arg count and types.
+ unsafe { env.new_object_unchecked(CONSTRUCTOR.cls(), method_id, args) }?
+ };
+ assert!(env.is_instance_of(&obj_foo, &FOO)?);
+
+ // Verify we can access all of the members
+
+ let field_value = {
+ env.get_field_unchecked(&obj_foo, &FIELD, ReturnType::Primitive(Primitive::Int))?
+ .i()?
+ };
+ assert_eq!(123, field_value);
+
+ let method_value = {
+ let method_id = METHOD.lookup(&mut env)?;
+ let args = &[];
+ // Safety: `args` must match the method arg count and types.
+ unsafe {
+ env.call_method_unchecked(
+ &obj_foo,
+ method_id,
+ ReturnType::Primitive(Primitive::Boolean),
+ args,
+ )
+ }?
+ .z()?
+ };
+ assert!(method_value);
+
+ env.delete_local_ref(obj_foo)?;
+
+ let static_field_value = {
+ env.get_static_field_unchecked(&FOO, &STATIC_FIELD, JavaType::Primitive(Primitive::Long))?
+ .j()?
+ };
+ assert_eq!(321, static_field_value);
+
+ let static_method_value = {
+ let method_id = STATIC_METHOD.lookup(&mut env)?;
+ let args = &[];
+ // Safety: `args` must match the method arg count and types.
+ unsafe {
+ env.call_static_method_unchecked(
+ &FOO,
+ method_id,
+ ReturnType::Primitive(Primitive::Int),
+ args,
+ )
+ }?
+ .i()?
+ };
+ assert_eq!(3, static_method_value);
+
+ Ok(())
+}
diff --git a/common/pourover/tests/jni_method_integration.rs b/common/pourover/tests/jni_method_integration.rs
new file mode 100644
index 0000000..4bd6547
--- /dev/null
+++ b/common/pourover/tests/jni_method_integration.rs
@@ -0,0 +1,162 @@
+// 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.
+
+#![allow(unsafe_code, clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+
+use jni::{
+ descriptors::Desc,
+ objects::{JObject, JString},
+ signature::{Primitive, ReturnType},
+ sys::jint,
+ JNIEnv, JavaVM,
+};
+use std::error::Error;
+use std::sync::atomic::{AtomicBool, Ordering};
+
+mod common;
+use common::foo_class::*;
+
+static NATIVE_METHOD_CALLED: AtomicBool = AtomicBool::new(false);
+static TEST_PANIC: AtomicBool = AtomicBool::new(false);
+
+#[pourover::jni_method(
+ package = "com.example",
+ class = "Foo",
+ panic_returns = -1
+)]
+extern "system" fn nativeReturnsInt<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>,
+ n: jint,
+) -> jint {
+ NATIVE_METHOD_CALLED.store(true, Ordering::SeqCst);
+
+ let foo_value = env
+ .get_field_unchecked(&this, &FIELD, ReturnType::Primitive(Primitive::Int))
+ .unwrap()
+ .i()
+ .unwrap();
+
+ n * foo_value
+}
+
+#[pourover::jni_method(
+ package = "com.example",
+ class = "Foo",
+ panic_returns = JObject::null().into(),
+)]
+extern "system" fn nativeReturnsObject<'local>(
+ env: JNIEnv<'local>,
+ _this: JObject<'local>,
+ n: jint,
+) -> JString<'local> {
+ if TEST_PANIC.load(Ordering::SeqCst) {
+ panic!("testing panic case");
+ }
+ env.new_string(n.to_string()).unwrap()
+}
+
+#[test]
+fn can_call_native_method() -> Result<(), Box<dyn Error>> {
+ // Create the environment
+ let vm = JavaVM::new(
+ jni::InitArgsBuilder::new()
+ .version(jni::JNIVersion::V8)
+ .option("-Xcheck:jni")
+ .build()?,
+ )?;
+ let mut env = vm.attach_current_thread()?;
+
+ // Load `Foo.class`
+ {
+ let foo_class = compile_foo()?;
+ let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?;
+ env.delete_local_ref(loaded_foo)?;
+ }
+
+ let obj_foo = {
+ let method_id = CONSTRUCTOR.lookup(&mut env)?;
+ let args = &[jni::sys::jvalue { i: 123 }];
+ // Safety: `args` must match the constructor arg count and types.
+ unsafe { env.new_object_unchecked(CONSTRUCTOR.cls(), method_id, args) }?
+ };
+ let obj_foo = env.auto_local(obj_foo);
+
+ NATIVE_METHOD_CALLED.store(false, Ordering::SeqCst);
+
+ // TODO: It would be better if the JVM was able to find the method on its own,
+ // but, since we are using the invocation API to create the JVM, I haven't found a way to make
+ // it visible to the JVM. Normally the methods are loaded dynamically with
+ // `System.loadLibrary`, but in this case the symbols already exist in the executable, and I'm
+ // unsure why the JVM cannot find them. I have tried compiling with
+ // `-Zexport-executable-symbols` but that wasn't working for me.
+ env.register_native_methods(
+ &FOO,
+ &[
+ jni::NativeMethod {
+ name: "nativeReturnsInt".into(),
+ sig: "(I)I".into(),
+ fn_ptr: crate::nativeReturnsInt as *mut std::ffi::c_void,
+ },
+ jni::NativeMethod {
+ name: "nativeReturnsObject".into(),
+ sig: "(I)Ljava/lang/String;".into(),
+ fn_ptr: crate::nativeReturnsObject as *mut std::ffi::c_void,
+ },
+ ],
+ )?;
+
+ let method_value = {
+ let method_id = NATIVE_METHOD.lookup(&mut env)?;
+ let args = &[jni::sys::jvalue { i: 3 }];
+ // Safety: `args` must match the method arg count and types.
+ unsafe {
+ env.call_method_unchecked(
+ &obj_foo,
+ method_id,
+ ReturnType::Primitive(Primitive::Int),
+ args,
+ )
+ }?
+ .i()?
+ };
+
+ assert_eq!(369, method_value);
+ assert!(NATIVE_METHOD_CALLED.load(Ordering::SeqCst));
+
+ TEST_PANIC.store(false, Ordering::SeqCst);
+ let string_value: JString = {
+ let method_id = NATIVE_OBJECT_METHOD.lookup(&mut env)?;
+ let args = &[jni::sys::jvalue { i: 1234 }];
+ // Safety: `args` must match the method arg count and types.
+ unsafe { env.call_method_unchecked(&obj_foo, method_id, ReturnType::Object, args) }?
+ .l()?
+ .into()
+ };
+ assert_eq!("1234", env.get_string(&string_value)?.to_str()?);
+ env.delete_local_ref(string_value)?;
+
+ TEST_PANIC.store(true, Ordering::SeqCst);
+ let string_value: JString = {
+ let method_id = NATIVE_OBJECT_METHOD.lookup(&mut env)?;
+ let args = &[jni::sys::jvalue { i: 1234 }];
+ // Safety: `args` must match the method arg count and types.
+ unsafe { env.call_method_unchecked(&obj_foo, method_id, ReturnType::Object, args) }?
+ .l()?
+ .into()
+ };
+ assert!(string_value.is_null());
+
+ Ok(())
+}
diff --git a/common/pourover_macro/Cargo.toml b/common/pourover_macro/Cargo.toml
new file mode 100644
index 0000000..0473dd4
--- /dev/null
+++ b/common/pourover_macro/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "pourover_macro"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[lints]
+workspace = true
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2.workspace = true
+syn.workspace = true
+quote.workspace = true
+nom = { workspace = true, features = ["alloc"] }
+jni = { workspace = true, optional = true }
+
+[dev-dependencies]
+pourover.workspace = true # doc only
+jni.workspace = true # doc only
diff --git a/common/pourover_macro/src/call_method.rs b/common/pourover_macro/src/call_method.rs
new file mode 100644
index 0000000..5886a86
--- /dev/null
+++ b/common/pourover_macro/src/call_method.rs
@@ -0,0 +1,100 @@
+// 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.
+
+//! Implementation of the `call_method!` series of macros. These macros are meant to be used as
+//! function-like macros and implement a statically type-safe way to call Java methods while also
+//! caching the method id. The macro arguments are implemented in [`mod ast`](mod@ast) and the
+//! generated code is implemented in [`mod codegen`](mod@codegen).
+
+use proc_macro2::TokenStream;
+use syn::parse_quote;
+
+use ast::{ConstructorArgs, InstanceArgs, StaticArgs};
+use codegen::{MethodCall, MethodInfo, Receiver};
+
+mod ast;
+mod codegen;
+
+/// See [`crate::call_method!`] for usage.
+pub fn call_method(args: TokenStream) -> syn::Result<TokenStream> {
+ let args = syn::parse2::<InstanceArgs>(args)?;
+
+ let method_info = MethodInfo::new(args.cls, args.name, args.sig);
+ let receiver = Receiver::Instance(args.this);
+ let method_call = MethodCall::new(
+ args.env,
+ method_info,
+ receiver,
+ args.args.into_iter().collect(),
+ );
+
+ method_call.generate().map_err(syn::Error::from)
+}
+
+/// See [`crate::call_static_method!`] for usage.
+pub fn call_static_method(args: TokenStream) -> syn::Result<TokenStream> {
+ let args = syn::parse2::<StaticArgs>(args)?;
+
+ let method_info = MethodInfo::new(args.cls, args.name, args.sig);
+ let receiver = Receiver::Static;
+ let method_call = MethodCall::new(
+ args.env,
+ method_info,
+ receiver,
+ args.args.into_iter().collect(),
+ );
+
+ method_call.generate().map_err(syn::Error::from)
+}
+
+/// See [`crate::call_constructor!`] for usage.
+pub fn call_constructor(args: TokenStream) -> syn::Result<TokenStream> {
+ let args = syn::parse2::<ConstructorArgs>(args)?;
+
+ let name = parse_quote!["<init>"];
+ let method_info = MethodInfo::new(args.cls, name, args.sig);
+ let receiver = Receiver::Constructor;
+ let method_call = MethodCall::new(
+ args.env,
+ method_info,
+ receiver,
+ args.args.into_iter().collect(),
+ );
+
+ method_call.generate().map_err(syn::Error::from)
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use quote::quote;
+
+ #[test]
+ fn call_method_error() {
+ let out = call_method(quote![&mut env, &CLS, "method", "INVALID", &this_obj]);
+ assert!(out.is_err());
+ }
+
+ #[test]
+ fn call_static_method_error() {
+ let out = call_static_method(quote![&mut env, &CLS, "method", "INVALID"]);
+ assert!(out.is_err());
+ }
+
+ #[test]
+ fn call_constructor_error() {
+ let out = call_constructor(quote![&mut env, &CLS, "INVALID"]);
+ assert!(out.is_err());
+ }
+}
diff --git a/common/pourover_macro/src/call_method/ast.rs b/common/pourover_macro/src/call_method/ast.rs
new file mode 100644
index 0000000..c5e66f9
--- /dev/null
+++ b/common/pourover_macro/src/call_method/ast.rs
@@ -0,0 +1,290 @@
+// 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 trees for the arguments to the `call_method!` series of proc macros.
+
+use syn::{
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ Expr, LitStr, Token,
+};
+
+/// The trailing method arguments
+type Args = Punctuated<Expr, Token![,]>;
+
+/// See [`crate::call_constructor!`].
+pub struct ConstructorArgs {
+ pub env: Expr,
+ pub cls: Expr,
+ pub sig: LitStr,
+ pub args: Args,
+}
+
+impl Parse for ConstructorArgs {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ let env = CommaSep::parse(stream)?.node;
+ let cls = CommaSep::parse(stream)?.node;
+ let sig = stream.parse()?;
+ let args = parse_args(stream)?;
+
+ Ok(Self {
+ env,
+ cls,
+ sig,
+ args,
+ })
+ }
+}
+
+/// See [`crate::call_static_method!`].
+pub struct StaticArgs {
+ pub env: Expr,
+ pub cls: Expr,
+ pub name: Expr,
+ pub sig: LitStr,
+ pub args: Args,
+}
+
+impl Parse for StaticArgs {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ let env = CommaSep::parse(stream)?.node;
+ let cls = CommaSep::parse(stream)?.node;
+ let name = CommaSep::parse(stream)?.node;
+ let sig = stream.parse()?;
+ let args = parse_args(stream)?;
+
+ Ok(Self {
+ env,
+ cls,
+ name,
+ sig,
+ args,
+ })
+ }
+}
+
+/// See [`crate::call_method!`].
+pub struct InstanceArgs {
+ pub env: Expr,
+ pub cls: Expr,
+ pub name: Expr,
+ pub sig: LitStr,
+ pub this: Expr,
+ pub args: Args,
+}
+
+impl Parse for InstanceArgs {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ let env = CommaSep::parse(stream)?.node;
+ let cls = CommaSep::parse(stream)?.node;
+ let name = CommaSep::parse(stream)?.node;
+ let sig = CommaSep::parse(stream)?.node;
+ let this = stream.parse()?;
+ let args = parse_args(stream)?;
+
+ Ok(Self {
+ env,
+ cls,
+ name,
+ sig,
+ this,
+ args,
+ })
+ }
+}
+
+/// Parses the variable number of arguments to the method. A leading comma is required when there
+/// are arguments being passed.
+fn parse_args(stream: ParseStream<'_>) -> syn::Result<Args> {
+ Ok(if stream.is_empty() {
+ Punctuated::new()
+ } else {
+ let _ = stream.parse::<Token![,]>()?;
+ Punctuated::parse_terminated(stream)?
+ })
+}
+
+/// A syntax node followed by a comma.
+#[allow(dead_code)]
+pub struct CommaSep<T> {
+ pub node: T,
+ pub comma: Token![,],
+}
+
+impl<T: Parse> Parse for CommaSep<T> {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ Ok(Self {
+ node: stream.parse()?,
+ comma: stream.parse()?,
+ })
+ }
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+mod test {
+ use super::*;
+ use quote::quote;
+ use syn::parse::Parser;
+
+ #[test]
+ fn comma_sep_correct() {
+ let ret: CommaSep<syn::Ident> = syn::parse2(quote![abc,]).unwrap();
+
+ assert_eq!(ret.node, "abc");
+ }
+
+ #[test]
+ fn comma_sep_incorrect() {
+ assert!(syn::parse2::<CommaSep<syn::Ident>>(quote![abc]).is_err());
+ assert!(syn::parse2::<CommaSep<syn::Ident>>(quote![,abc]).is_err());
+ assert!(syn::parse2::<CommaSep<syn::Ident>>(quote![,]).is_err());
+ }
+
+ #[test]
+ fn parse_args_no_args() {
+ let args = parse_args.parse2(quote![]).unwrap();
+
+ assert_eq!(0, args.len());
+ }
+
+ #[test]
+ fn parse_args_no_args_extra_comma() {
+ let args = parse_args.parse2(quote![,]).unwrap();
+
+ assert_eq!(0, args.len());
+ }
+
+ #[test]
+ fn parse_args_single_no_trailing() {
+ let args = parse_args.parse2(quote![, foo]).unwrap();
+
+ assert_eq!(1, args.len());
+ }
+
+ #[test]
+ fn parse_args_single_trailing() {
+ let args = parse_args.parse2(quote![, foo,]).unwrap();
+
+ assert_eq!(1, args.len());
+ }
+
+ #[test]
+ fn parse_args_multi_no_trailing() {
+ let args = parse_args.parse2(quote![, one, two, three]).unwrap();
+
+ assert_eq!(3, args.len());
+ }
+
+ #[test]
+ fn parse_args_multi_trailing() {
+ let args = parse_args.parse2(quote![, one, two, three,]).unwrap();
+
+ assert_eq!(3, args.len());
+ }
+
+ #[test]
+ fn parse_args_error_two_commas() {
+ let res = parse_args.parse2(quote![, ,]);
+
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn parse_constructor_args() {
+ let tests = [
+ quote![&mut env, &CLS, "()V"],
+ quote![&mut env, &CLS, "()V",],
+ quote![&mut env, &CLS, "(I)V", 123],
+ quote![&mut env, &CLS, "(I)V", 123,],
+ quote![&mut env, &CLS, "(ILjava/lang/String;)V", 123, &some_str],
+ quote![&mut env, &CLS, "(ILjava/lang/String;)V", 123, &some_str,],
+ ];
+
+ for valid in tests {
+ assert!(
+ syn::parse2::<ConstructorArgs>(valid.clone()).is_ok(),
+ "test: {valid}"
+ );
+ }
+ }
+
+ #[test]
+ fn parse_static_method_args() {
+ let tests = [
+ quote![&mut env, &CLS, "methodName", "()V"],
+ quote![&mut env, &CLS, "methodName", "()V",],
+ quote![&mut env, &CLS, "methodName", "(I)V", 123],
+ quote![&mut env, &CLS, "methodName", "(I)V", 123,],
+ quote![
+ &mut env,
+ &CLS,
+ "methodName",
+ "(ILjava/lang/String;)V",
+ 123,
+ &some_str
+ ],
+ quote![
+ &mut env,
+ &CLS,
+ "methodName",
+ "(ILjava/lang/String;)V",
+ 123,
+ &some_str,
+ ],
+ ];
+
+ for valid in tests {
+ assert!(
+ syn::parse2::<StaticArgs>(valid.clone()).is_ok(),
+ "test: {valid}"
+ );
+ }
+ }
+
+ #[test]
+ fn parse_method_args() {
+ let tests = [
+ quote![&mut env, &CLS, "methodName", "()V", &this_obj],
+ quote![&mut env, &CLS, "methodName", "()V", &this_obj,],
+ quote![&mut env, &CLS, "methodName", "(I)V", &this_obj, 123],
+ quote![&mut env, &CLS, "methodName", "(I)V", &this_obj, 123,],
+ quote![
+ &mut env,
+ &CLS,
+ "methodName",
+ "(ILjava/lang/String;)V",
+ &this_obj,
+ 123,
+ &some_str
+ ],
+ quote![
+ &mut env,
+ &CLS,
+ "methodName",
+ "(ILjava/lang/String;)V",
+ &this_obj,
+ 123,
+ &some_str,
+ ],
+ ];
+
+ for valid in tests {
+ assert!(
+ syn::parse2::<InstanceArgs>(valid.clone()).is_ok(),
+ "test: {valid}"
+ );
+ }
+ }
+}
diff --git a/common/pourover_macro/src/call_method/codegen.rs b/common/pourover_macro/src/call_method/codegen.rs
new file mode 100644
index 0000000..bce3976
--- /dev/null
+++ b/common/pourover_macro/src/call_method/codegen.rs
@@ -0,0 +1,610 @@
+// 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.
+
+//! Code generation for the `call_method!` series of proc-macros. This module is used by creating a
+//! [`MethodCall`] instance and calling [`MethodCall::generate`]. The generated code will vary
+//! for each macro based on the contained [`Receiver`] value. If there is a detected issue with the
+//! [`MethodCall`] provided, then `generate` will return a [`CodegenError`] with information on
+//! what is wrong. This error can be converted into a [`syn::Error`] for reporting any failures to
+//! the user.
+
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, quote_spanned, TokenStreamExt};
+use syn::{parse_quote, spanned::Spanned, Expr, Ident, ItemStatic, LitStr, Type};
+
+use crate::type_parser::{JavaType, MethodSig, NonArray, Primitive, ReturnType};
+
+/// The errors that can be encountered during codegen. Used in [`CodegenError`].
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum ErrorKind {
+ InvalidArgsLength { expected: usize, found: usize },
+ ConstructorRetValShouldBeVoid,
+ InvalidTypeSignature,
+}
+
+/// An error encountered during codegen with span information. Can be converted to [`syn::Error`].
+/// using [`From`].
+#[derive(Clone, Debug)]
+pub struct CodegenError(pub Span, pub ErrorKind);
+
+impl From<CodegenError> for syn::Error {
+ fn from(CodegenError(span, kind): CodegenError) -> syn::Error {
+ use ErrorKind::*;
+ match kind {
+ InvalidArgsLength { expected, found } => {
+ syn::Error::new(span, format!("The number of args does not match the type signature provided: expected={expected}, found={found}"))
+ }
+ ConstructorRetValShouldBeVoid => {
+ syn::Error::new(span, "Return type should be `void` (`V`) for constructor methods")
+ }
+ InvalidTypeSignature => syn::Error::new(span, "Failed to parse type signature"),
+ }
+ }
+}
+
+/// Codegen can fail with [`CodegenError`].
+pub type CodegenResult<T> = Result<T, CodegenError>;
+
+/// Describes a method that will be generated. Create one with [`MethodCall::new`] and generate
+/// code with [`MethodCall::generate`]. This should be given AST nodes from the macro input so that
+/// errors are associated properly to the input span.
+pub struct MethodCall {
+ env: Expr,
+ method: MethodInfo,
+ receiver: Receiver,
+ arg_exprs: Vec<Expr>,
+}
+
+impl MethodCall {
+ /// Create a new MethodCall instance
+ pub fn new(env: Expr, method: MethodInfo, receiver: Receiver, arg_exprs: Vec<Expr>) -> Self {
+ Self {
+ env,
+ method,
+ receiver,
+ arg_exprs,
+ }
+ }
+
+ /// Generate code to call the described method.
+ pub fn generate(&self) -> CodegenResult<TokenStream> {
+ // Needs to be threaded manually to other methods since self-referential structs can't
+ // exist.
+ let sig = self.method.sig()?;
+
+ let args = self.generate_args(&sig)?;
+
+ let method_call = self
+ .receiver
+ .generate_call(&self.env, &self.method, &sig, &args)?;
+
+ // Wrap the generated code in a closure so that we can access the outer scope but any
+ // variables we define aren't accessible by the outer scope. There is small hygiene issue
+ // where the arg exprs have our `env` variable in scope. If this becomes an issue we can
+ // refactor these exprs to be passed as closure parameters instead.
+ Ok(quote! {
+ (|| {
+ #method_call
+ })()
+ })
+ }
+
+ /// Generate the `&[jni::jvalue]` arguments slice that will be passed to the `jni` method call.
+ /// This validates the argument count and types.
+ fn generate_args(&self, sig: &MethodSig<'_>) -> CodegenResult<Expr> {
+ // Safety: must check that arg count matches the signature
+ if self.arg_exprs.len() != sig.args.len() {
+ return Err(CodegenError(
+ self.method.sig.span(),
+ ErrorKind::InvalidArgsLength {
+ expected: sig.args.len(),
+ found: self.arg_exprs.len(),
+ },
+ ));
+ }
+
+ // Create each `jvalue` expression
+ let type_expr_pairs = core::iter::zip(sig.args.iter().copied(), self.arg_exprs.iter());
+ let jvalues = type_expr_pairs.map(|(ty, expr)| generate_jvalue(ty, expr));
+
+ // Put the `jvalue` expressions in a slice.
+ Ok(parse_quote! {
+ &[#(#jvalues),*]
+ })
+ }
+}
+
+/// The receiver of the method call and the type of the method.
+pub enum Receiver {
+ /// A constructor.
+ Constructor,
+ /// A static method.
+ Static,
+ /// An instance method. The `Expr` here is the `this` object.
+ Instance(Expr),
+}
+
+impl Receiver {
+ /// Generate the code that performs the JNI call.
+ fn generate_call(
+ &self,
+ env: &Expr,
+ method_info: &MethodInfo,
+ sig: &MethodSig<'_>,
+ args: &Expr,
+ ) -> CodegenResult<TokenStream> {
+ // Constructors are void methods. Validate this fact.
+ if matches!(*self, Receiver::Constructor) && !sig.ret.is_void() {
+ return Err(CodegenError(
+ method_info.sig.span(),
+ ErrorKind::ConstructorRetValShouldBeVoid,
+ ));
+ }
+
+ // The static item containing the `pourover::[Static]MethodDesc`.
+ let method_desc = self.generate_method_desc(method_info);
+
+ // The `jni::signature::ReturnType` that the `jni` crate uses to perform the correct native
+ // call.
+ let return_type = return_type_from_sig(sig.ret);
+
+ // A conversion expression to convert from `jni::object::JValueOwned` to the actual return
+ // type. We have this information from the parsed method signature whereas the `jni` crate
+ // only knows this at runtime.
+ let conversion = return_value_conversion_from_sig(sig.ret);
+
+ // This preamble is used to evaluate all the client-provided expressions outside of the
+ // `unsafe` block. This is the same for all receiver kinds.
+ let mut method_call = quote! {
+ #method_desc
+
+ let env: &mut ::jni::JNIEnv = #env;
+ let method_id = ::jni::descriptors::Desc::lookup(&METHOD_DESC, env)?;
+ let args: &[::jni::sys::jvalue] = #args;
+ };
+
+ // Generate the unsafe JNI call.
+ //
+ // Safety: `args` contains the arguments to this method. The type signature of this
+ // method is `#sig`.
+ //
+ // `args` must adhere to the following:
+ // - `args.len()` must match the number of arguments given in the type signature.
+ // - The union value of each arg in `args` must match the type specified in the type
+ // signature.
+ //
+ // These conditions are upheld by this proc macro and a compile error will be caused if
+ // they are broken. No user-provided code is executed within the `unsafe` block.
+ method_call.append_all(match self {
+ Self::Constructor => quote! {
+ unsafe {
+ env.new_object_unchecked(
+ METHOD_DESC.cls(),
+ method_id,
+ args,
+ )
+ }
+ },
+ Self::Static => quote! {
+ unsafe {
+ env.call_static_method_unchecked(
+ METHOD_DESC.cls(),
+ method_id,
+ #return_type,
+ args,
+ )
+ }#conversion
+ },
+ Self::Instance(this) => quote! {
+ let this_obj: &JObject = #this;
+ unsafe {
+ env.call_method_unchecked(
+ this_obj,
+ method_id,
+ #return_type,
+ args,
+ )
+ }#conversion
+ },
+ });
+
+ Ok(method_call)
+ }
+
+ fn generate_method_desc(&self, MethodInfo { cls, name, sig, .. }: &MethodInfo) -> ItemStatic {
+ match self {
+ Self::Constructor => parse_quote! {
+ static METHOD_DESC: ::pourover::desc::MethodDesc = (#cls).constructor(#sig);
+ },
+ Self::Static => parse_quote! {
+ static METHOD_DESC: ::pourover::desc::StaticMethodDesc = (#cls).static_method(#name, #sig);
+ },
+ Self::Instance(_) => parse_quote! {
+ static METHOD_DESC: ::pourover::desc::MethodDesc = (#cls).method(#name, #sig);
+ },
+ }
+ }
+}
+
+/// Information about the method being called
+pub struct MethodInfo {
+ cls: Expr,
+ name: Expr,
+ sig: LitStr,
+ /// Derived from `sig.value()`. This string must be stored in the struct so that we can return
+ /// a `MethodSig` instance that references it from `MethodInfo::sig()`.
+ sig_str: String,
+}
+
+impl MethodInfo {
+ pub fn new(cls: Expr, name: Expr, sig: LitStr) -> Self {
+ let sig_str = sig.value();
+ Self {
+ cls,
+ name,
+ sig,
+ sig_str,
+ }
+ }
+
+ /// Parse the type signature from `sig`. Will return a [`CodegenError`] if the signature cannot
+ /// be parsed.
+ fn sig(&self) -> CodegenResult<MethodSig<'_>> {
+ MethodSig::try_from_str(&self.sig_str)
+ .ok_or_else(|| CodegenError(self.sig.span(), ErrorKind::InvalidTypeSignature))
+ }
+}
+
+/// Generate a `jni::sys::jvalue` instance given a Java type and a Rust value.
+///
+/// Safety: The generated `jvalue` must match the given type `ty`.
+fn generate_jvalue(ty: JavaType<'_>, expr: &Expr) -> TokenStream {
+ // The `jvalue` field to inhabit
+ let union_field: Ident;
+ // The expected input type
+ let type_name: Type;
+ // Whether we need to call `JObject::as_raw()` on the input type
+ let needs_as_raw: bool;
+
+ // Fill the above values based the type signature.
+ match ty {
+ JavaType::Array { depth, ty } => {
+ union_field = parse_quote![l];
+ if let NonArray::Primitive(p) = ty {
+ if depth.get() == 1 {
+ let prim_type = prim_to_sys_type(p);
+ type_name = parse_quote![::jni::objects::JPrimitiveArray<'_, #prim_type>]
+ } else {
+ type_name = parse_quote![&::jni::objects::JObjectArray<'_>];
+ }
+ } else {
+ type_name = parse_quote![&::jni::objects::JObjectArray<'_>];
+ }
+ needs_as_raw = true;
+ }
+ JavaType::NonArray(NonArray::Object { cls }) => {
+ union_field = parse_quote![l];
+ type_name = match cls {
+ "java/lang/String" => parse_quote![&::jni::objects::JString<'_>],
+ "java/util/List" => parse_quote![&::jni::objects::JList<'_>],
+ "java/util/Map" => parse_quote![&::jni::objects::JMap<'_>],
+ _ => parse_quote![&::jni::objects::JObject<'_>],
+ };
+ needs_as_raw = true;
+ }
+ JavaType::NonArray(NonArray::Primitive(p)) => {
+ union_field = prim_to_union_field(p);
+ type_name = prim_to_sys_type(p);
+ needs_as_raw = false;
+ }
+ }
+
+ // The as_raw() tokens if required.
+ let as_raw = if needs_as_raw {
+ quote! { .as_raw() }
+ } else {
+ quote![]
+ };
+
+ // Create the `jvalue` expression. This uses `identity` to produce nice type error messages.
+ quote_spanned! { expr.span() =>
+ ::jni::sys::jvalue {
+ #union_field: ::core::convert::identity::<#type_name>(#expr) #as_raw
+ }
+ }
+}
+
+/// Get a `::jni::signature::ReturnType` expression from a [`crate::type_parser::ReturnType`]. This
+/// value is passed to the `jni` crate so that it knows which JNI method to call.
+fn return_type_from_sig(ret: ReturnType<'_>) -> Expr {
+ let prim_type = |prim| parse_quote![::jni::signature::ReturnType::Primitive(::jni::signature::Primitive::#prim)];
+
+ use crate::type_parser::{JavaType::*, NonArray::*, Primitive::*};
+
+ match ret {
+ ReturnType::Void => prim_type(quote![Void]),
+ ReturnType::Returns(NonArray(Primitive(Boolean))) => prim_type(quote![Boolean]),
+ ReturnType::Returns(NonArray(Primitive(Byte))) => prim_type(quote![Byte]),
+ ReturnType::Returns(NonArray(Primitive(Char))) => prim_type(quote![Char]),
+ ReturnType::Returns(NonArray(Primitive(Double))) => prim_type(quote![Double]),
+ ReturnType::Returns(NonArray(Primitive(Float))) => prim_type(quote![Float]),
+ ReturnType::Returns(NonArray(Primitive(Int))) => prim_type(quote![Int]),
+ ReturnType::Returns(NonArray(Primitive(Long))) => prim_type(quote![Long]),
+ ReturnType::Returns(NonArray(Primitive(Short))) => prim_type(quote![Short]),
+ ReturnType::Returns(NonArray(Object { .. })) => {
+ parse_quote![::jni::signature::ReturnType::Object]
+ }
+ ReturnType::Returns(Array { .. }) => parse_quote![::jni::signature::ReturnType::Array],
+ }
+}
+
+/// A postfix call on a `jni::objects::JValueOwned` instance to convert it to the type specified by
+/// `ret`. Since we have this information from the type signature we can perform this conversion
+/// in the macro.
+fn return_value_conversion_from_sig(ret: ReturnType<'_>) -> TokenStream {
+ use crate::type_parser::{JavaType::*, NonArray::*};
+
+ match ret {
+ ReturnType::Void => quote! { .and_then(::jni::objects::JValueOwned::v) },
+ ReturnType::Returns(NonArray(Primitive(p))) => {
+ let prim = prim_to_union_field(p);
+ quote! { .and_then(::jni::objects::JValueOwned::#prim) }
+ }
+ ReturnType::Returns(NonArray(Object { cls })) => {
+ let mut conversion = quote! { .and_then(::jni::objects::JValueOwned::l) };
+ match cls {
+ "java/lang/String" => {
+ conversion.append_all(quote! { .map(::jni::objects::JString::from) });
+ }
+ "java/util/List" => {
+ conversion.append_all(quote! { .map(::jni::objects::JList::from) });
+ }
+ "java/util/Map" => {
+ conversion.append_all(quote! { .map(::jni::objects::JMap::from) });
+ }
+ _ => {
+ // Already a JObject, so we are good here
+ }
+ }
+ conversion
+ }
+ ReturnType::Returns(Array {
+ depth,
+ ty: Primitive(p),
+ }) if depth.get() == 1 => {
+ let sys_type = prim_to_sys_type(p);
+ quote! {
+ .and_then(::jni::objects::JValueOwned::l)
+ .map(::jni::objects::JPrimitiveArray::<#sys_type>::from)
+ }
+ }
+ ReturnType::Returns(Array { .. }) => quote! {
+ .and_then(::jni::objects::JValueOwned::l)
+ .map(::jni::objects::JObjectArray::from)
+ },
+ }
+}
+
+/// From a [`Primitive`], this gets the `jni::sys::jvalue` union field name for that type. This is
+/// also the `jni::objects::JValueGen` getter name.
+fn prim_to_union_field(p: Primitive) -> Ident {
+ quote::format_ident!("{}", p.as_char().to_ascii_lowercase())
+}
+
+/// From a [`Primitive`], this gets the matching `jvalue::sys` type.
+fn prim_to_sys_type(p: Primitive) -> Type {
+ match p {
+ Primitive::Boolean => parse_quote![::jni::sys::jboolean],
+ Primitive::Byte => parse_quote![::jni::sys::jbyte],
+ Primitive::Char => parse_quote![::jni::sys::jchar],
+ Primitive::Double => parse_quote![::jni::sys::jdouble],
+ Primitive::Float => parse_quote![::jni::sys::jfloat],
+ Primitive::Int => parse_quote![::jni::sys::jint],
+ Primitive::Long => parse_quote![::jni::sys::jlong],
+ Primitive::Short => parse_quote![::jni::sys::jshort],
+ }
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+mod tests {
+ use super::*;
+ use crate::test_util::contains_ident;
+ use quote::ToTokens;
+ use syn::parse_quote;
+
+ fn example_method_call() -> MethodCall {
+ MethodCall::new(
+ parse_quote![&mut env],
+ MethodInfo::new(
+ parse_quote![&FOO_CLS],
+ parse_quote!["example"],
+ parse_quote!["(II)I"],
+ ),
+ Receiver::Instance(parse_quote![&foo]),
+ vec![parse_quote![123], parse_quote![2 + 3]],
+ )
+ }
+
+ #[test]
+ fn args_are_counted() {
+ let mut call = example_method_call();
+ call.arg_exprs.push(parse_quote![too_many]);
+
+ let CodegenError(_span, kind) = call.generate().unwrap_err();
+
+ assert_eq!(
+ ErrorKind::InvalidArgsLength {
+ expected: 2,
+ found: 3
+ },
+ kind
+ );
+ }
+
+ #[test]
+ fn constructor_return_type_is_void() {
+ let mut call = example_method_call();
+ call.receiver = Receiver::Constructor;
+
+ let CodegenError(_span, kind) = call.generate().unwrap_err();
+
+ assert_eq!(ErrorKind::ConstructorRetValShouldBeVoid, kind);
+ }
+
+ #[test]
+ fn invalid_type_sig_is_error() {
+ let mut call = example_method_call();
+ call.method.sig = parse_quote!["L"];
+ call.method.sig_str = call.method.sig.value();
+
+ let CodegenError(_span, kind) = call.generate().unwrap_err();
+
+ assert_eq!(ErrorKind::InvalidTypeSignature, kind);
+ }
+
+ #[test]
+ fn jni_types_are_used_for_stdlib_classes_input() {
+ let types = [
+ ("Ljava/lang/String;", "JString"),
+ ("Ljava/util/Map;", "JMap"),
+ ("Ljava/util/List;", "JList"),
+ ("[Ljava/lang/String;", "JObjectArray"),
+ ("[[I", "JObjectArray"),
+ ("[I", "JPrimitiveArray"),
+ ("Lcom/example/MyObject;", "JObject"),
+ ("Z", "jboolean"),
+ ("C", "jchar"),
+ ("B", "jbyte"),
+ ("S", "jshort"),
+ ("I", "jint"),
+ ("J", "jlong"),
+ ("F", "jfloat"),
+ ("D", "jdouble"),
+ ];
+
+ for (desc, jni_type) in types {
+ let jt = JavaType::try_from_str(desc).unwrap();
+ let expr = parse_quote![some_value];
+
+ let jvalue = generate_jvalue(jt, &expr);
+
+ assert!(
+ contains_ident(jvalue, jni_type),
+ "desc: {desc}, jni_type: {jni_type}"
+ );
+ }
+ }
+
+ #[test]
+ fn jni_types_are_used_for_stdlib_classes_output() {
+ let types = [
+ ("Ljava/lang/String;", "JString"),
+ ("Ljava/util/Map;", "JMap"),
+ ("Ljava/util/List;", "JList"),
+ ("[Ljava/lang/String;", "JObjectArray"),
+ ("[[I", "JObjectArray"),
+ ("[I", "JPrimitiveArray"),
+ ];
+
+ for (desc, jni_type) in types {
+ let rt = ReturnType::try_from_str(desc).unwrap();
+
+ let conversion = return_value_conversion_from_sig(rt);
+
+ assert!(
+ contains_ident(conversion, jni_type),
+ "desc: {desc}, jni_type: {jni_type}"
+ );
+ }
+ }
+
+ #[test]
+ fn return_type_passed_to_jni_is_correct() {
+ let types = [
+ ("Ljava/lang/String;", "Object"),
+ ("Ljava/util/Map;", "Object"),
+ ("Ljava/util/List;", "Object"),
+ ("[Ljava/lang/String;", "Array"),
+ ("[[I", "Array"),
+ ("[I", "Array"),
+ ("V", "Void"),
+ ("Z", "Boolean"),
+ ("C", "Char"),
+ ("B", "Byte"),
+ ("S", "Short"),
+ ("I", "Int"),
+ ("J", "Long"),
+ ("F", "Float"),
+ ("D", "Double"),
+ ];
+
+ for (desc, return_type) in types {
+ let rt = ReturnType::try_from_str(desc).unwrap();
+
+ let expr = return_type_from_sig(rt).into_token_stream();
+
+ assert!(
+ contains_ident(expr, return_type),
+ "desc: {desc}, return_type: {return_type}"
+ );
+ }
+ }
+
+ #[test]
+ fn method_desc_is_correct() {
+ let mut call = example_method_call();
+ call.method.sig = parse_quote!["(II)V"];
+ call.method.sig_str = call.method.sig.value();
+
+ let tests = [
+ (Receiver::Constructor, "constructor"),
+ (Receiver::Static, "static_method"),
+ (Receiver::Instance(parse_quote![this_value]), "method"),
+ ];
+
+ for (receiver, method_ident) in tests {
+ let desc = receiver.generate_method_desc(&call.method);
+ let rhs = desc.expr.into_token_stream();
+
+ assert!(contains_ident(rhs, method_ident), "method: {method_ident}");
+ }
+ }
+
+ #[test]
+ fn jni_call_is_correct() {
+ let mut call = example_method_call();
+ call.method.sig = parse_quote!["(II)V"];
+ call.method.sig_str = call.method.sig.value();
+ let sig = call.method.sig().unwrap();
+ let args = parse_quote![test_stub];
+
+ let tests = [
+ (Receiver::Constructor, "new_object_unchecked"),
+ (Receiver::Static, "call_static_method_unchecked"),
+ (
+ Receiver::Instance(parse_quote![this_value]),
+ "call_method_unchecked",
+ ),
+ ];
+
+ for (receiver, method_ident) in tests {
+ let call = receiver
+ .generate_call(&call.env, &call.method, &sig, &args)
+ .unwrap();
+
+ assert!(contains_ident(call, method_ident), "method: {method_ident}");
+ }
+ }
+}
diff --git a/common/pourover_macro/src/jni_method.rs b/common/pourover_macro/src/jni_method.rs
new file mode 100644
index 0000000..760aa64
--- /dev/null
+++ b/common/pourover_macro/src/jni_method.rs
@@ -0,0 +1,412 @@
+// 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.
+
+use proc_macro2::TokenStream;
+use syn::{punctuated::Punctuated, spanned::Spanned, ItemFn, LitStr, Token};
+
+mod meta;
+mod meta_arg;
+mod substitutions;
+
+use meta::JniMethodMeta;
+use substitutions::substitute_method_chars;
+
+pub fn jni_method(meta: TokenStream, item: TokenStream) -> syn::Result<ItemFn> {
+ let meta = syn::parse2::<JniMethodMeta>(meta)?;
+ let mut func = syn::parse2::<ItemFn>(item)?;
+
+ // Check that ABI is set to `extern "system"`
+ if let Some(
+ ref abi @ syn::Abi {
+ name: Some(ref abi_name),
+ ..
+ },
+ ) = func.sig.abi
+ {
+ if abi_name.value() != "system" {
+ return Err(syn::Error::new(
+ abi.span(),
+ "JNI methods are required to have the `extern \"system\"` ABI",
+ ));
+ }
+ } else {
+ return Err(syn::Error::new(
+ func.sig.span(),
+ "JNI methods are required to have the `extern \"system\"` ABI",
+ ));
+ }
+
+ let export_attr = {
+ // Format the name of the function as expected by the JNI layer
+ let (method_name, method_name_span) = if let Some(meta_name) = &meta.method_name {
+ (meta_name.value(), meta_name.span())
+ } else {
+ (func.sig.ident.to_string(), func.sig.ident.span())
+ };
+ if method_name.starts_with("Java_") {
+ return Err(syn::Error::new(
+ method_name_span,
+ "The `jni_method` attribute will perform the JNI name formatting",
+ ));
+ }
+ let method_name = substitute_method_chars(&method_name);
+
+ // NOTE: doesn't handle overload suffix
+ let link_name = LitStr::new(
+ &format!("Java_{class}_{method_name}", class = &meta.class_desc),
+ method_name_span,
+ );
+
+ syn::parse_quote! { #[export_name = #link_name] }
+ };
+ func.attrs.push(export_attr);
+
+ // Allow function name to be non_snake_case if we are using it as the Java method name
+ if meta.method_name.is_none() {
+ let allow_attr = syn::parse_quote! { #[allow(non_snake_case)] };
+ func.attrs.push(allow_attr);
+ }
+
+ // Add a panic handler if requested
+ if let Some(panic_returns) = meta.panic_returns {
+ let block = &func.block;
+ let return_type = &func.sig.output;
+ let mut lifetimes = Punctuated::new();
+ for param in func.sig.generics.lifetimes() {
+ lifetimes.push_value(param.clone());
+ lifetimes.push_punct(<Token![,]>::default());
+ }
+
+ let panic_check = quote::quote_spanned! { panic_returns.span() =>
+ #[cfg(not(panic = "unwind"))]
+ ::core::compile_error!("Cannot use `panic_returns` with non-unwinding panic handler");
+ };
+
+ func.block = syn::parse_quote! {
+ {
+ #panic_check
+ match ::std::panic::catch_unwind(move || {
+ #block
+ }) {
+ Ok(ret) => ret,
+ Err(_err) => {
+ fn __on_panic<#lifetimes>() #return_type { #panic_returns }
+ __on_panic()
+ },
+ }
+ }
+ };
+ }
+
+ // Return the modified function
+ Ok(func)
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+mod tests {
+ use super::*;
+ use crate::test_util::contains_ident;
+ use quote::{quote, ToTokens};
+
+ #[test]
+ fn can_parse() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "system" fn nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let out = jni_method(meta, func).unwrap();
+
+ assert!(contains_ident(out.into_token_stream(), "catch_unwind"));
+ }
+
+ fn parse_example_output() -> syn::ItemFn {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "system" fn nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ jni_method(meta, func).expect("failed to generate example")
+ }
+
+ fn parse_example_output_method_name() -> syn::ItemFn {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ method_name = "nativeBar",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "system" fn native_bar<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ jni_method(meta, func).expect("failed to generate example")
+ }
+
+ #[test]
+ fn check_output_is_itemfn() {
+ let _item_fn = parse_example_output();
+ }
+
+ #[test]
+ fn check_output_export_name() {
+ let out = parse_example_output();
+
+ let export_name = out
+ .attrs
+ .iter()
+ .find_map(|attr| {
+ let syn::Meta::NameValue(nv) = &attr.meta else {
+ return None;
+ };
+ if !nv.path.is_ident("export_name") {
+ return None;
+ }
+ let syn::Expr::Lit(syn::ExprLit {
+ lit: syn::Lit::Str(lit_str),
+ ..
+ }) = &nv.value
+ else {
+ return None;
+ };
+ Some(lit_str.value())
+ })
+ .expect("Failed to find `export_name` attribute");
+ assert_eq!("Java_com_example_Foo_00024Inner_nativeFoo", export_name);
+ }
+
+ #[test]
+ fn check_output_export_name_with_method_name() {
+ let out = parse_example_output_method_name();
+
+ let export_name = out
+ .attrs
+ .iter()
+ .find_map(|attr| {
+ let syn::Meta::NameValue(nv) = &attr.meta else {
+ return None;
+ };
+ if !nv.path.is_ident("export_name") {
+ return None;
+ }
+ let syn::Expr::Lit(syn::ExprLit {
+ lit: syn::Lit::Str(lit_str),
+ ..
+ }) = &nv.value
+ else {
+ return None;
+ };
+ Some(lit_str.value())
+ })
+ .expect("Failed to find `export_name` attribute");
+ assert_eq!("Java_com_example_Foo_00024Inner_nativeBar", export_name);
+ }
+
+ #[test]
+ fn check_output_allow_non_snake_case() {
+ let out = parse_example_output();
+
+ let _allow_attr = out
+ .attrs
+ .iter()
+ .find(|attr| {
+ let syn::Meta::List(ml) = &attr.meta else {
+ return false;
+ };
+ if !ml.path.is_ident("allow") {
+ return false;
+ }
+ let Ok(value) = syn::parse2::<syn::Path>(ml.tokens.clone()) else {
+ return false;
+ };
+ value.is_ident("non_snake_case")
+ })
+ .expect("Failed to find `allow(non_snake_case)` attribute");
+ }
+
+ #[test]
+ fn check_output_allow_non_snake_case_not_present_with_method_name() {
+ let out = parse_example_output_method_name();
+
+ let allow_attr = out.attrs.iter().find(|attr| {
+ let syn::Meta::List(ml) = &attr.meta else {
+ return false;
+ };
+ if !ml.path.is_ident("allow") {
+ return false;
+ }
+ let Ok(value) = syn::parse2::<syn::Path>(ml.tokens.clone()) else {
+ return false;
+ };
+ value.is_ident("non_snake_case")
+ });
+ assert!(allow_attr.is_none());
+ }
+
+ #[test]
+ fn no_panic_returns() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ };
+
+ let func = quote! {
+ extern "system" fn nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let out = match jni_method(meta, func) {
+ Ok(item_fn) => item_fn.into_token_stream(),
+ Err(err) => err.into_compile_error(),
+ };
+ assert!(!contains_ident(out.clone(), "compile_error"));
+ assert!(!contains_ident(out, "catch_unwind"));
+ }
+
+ #[test]
+ fn missing_extern() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ fn nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let Err(err) = jni_method(meta, func) else {
+ panic!("Should fail to generate code");
+ };
+
+ assert!(err
+ .to_string()
+ .contains("JNI methods are required to have the `extern \"system\"` ABI"));
+ }
+
+ #[test]
+ fn wrong_extern() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "C" fn nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let Err(err) = jni_method(meta, func) else {
+ panic!("Should fail to generate code");
+ };
+
+ assert!(err
+ .to_string()
+ .contains("JNI methods are required to have the `extern \"system\"` ABI"));
+ }
+
+ #[test]
+ fn already_mangled() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "system" fn Java_com_example_Foo_00024Inner_nativeFoo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let Err(err) = jni_method(meta, func) else {
+ panic!("Should fail to generate code");
+ };
+
+ assert!(err
+ .to_string()
+ .contains("The `jni_method` attribute will perform the JNI name formatting"));
+ }
+
+ #[test]
+ fn already_mangled_method_name() {
+ let meta = quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ method_name = "Java_com_example_Foo_00024Inner_nativeFoo",
+ panic_returns = false,
+ };
+
+ let func = quote! {
+ extern "system" fn native_foo<'local>(
+ mut env: JNIEnv<'local>,
+ this: JObject<'local>
+ ) -> jint {
+ 123
+ }
+ };
+
+ let Err(err) = jni_method(meta, func) else {
+ panic!("Should fail to generate code");
+ };
+
+ assert!(err
+ .to_string()
+ .contains("The `jni_method` attribute will perform the JNI name formatting"));
+ }
+}
diff --git a/common/pourover_macro/src/jni_method/meta.rs b/common/pourover_macro/src/jni_method/meta.rs
new file mode 100644
index 0000000..85e8c1a
--- /dev/null
+++ b/common/pourover_macro/src/jni_method/meta.rs
@@ -0,0 +1,209 @@
+// 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.
+
+use proc_macro2::Span;
+use syn::{
+ parse::{Parse, ParseStream},
+ Expr, LitStr, Token,
+};
+
+use super::meta_arg::MetaArg;
+use super::substitutions::{substitute_class_chars, substitute_package_chars};
+
+pub struct JniMethodMeta {
+ /// The class descriptor in [export_name format](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names)
+ pub class_desc: String,
+ /// The method name in Java. Use the Rust method name if not specified
+ pub method_name: Option<LitStr>,
+ /// The expression to run when a panic is encountered. The value of this expression will be
+ /// returned by the annotated function.
+ pub panic_returns: Option<Expr>,
+}
+
+impl Parse for JniMethodMeta {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ let mut package = None;
+ let mut class = None;
+ let mut method_name = None;
+ let mut panic_returns = None;
+
+ fn set_once<T>(opt: &mut Option<T>, value: T, span: Span, field: &str) -> syn::Result<()> {
+ if let Some(_old) = opt.replace(value) {
+ return Err(syn::Error::new(
+ span,
+ format!("`{field}` should not be specified twice"),
+ ));
+ }
+ Ok(())
+ }
+
+ type Structure = syn::punctuated::Punctuated<MetaArg, Token![,]>;
+
+ for arg in Structure::parse_terminated(stream)? {
+ match arg {
+ MetaArg::Package {
+ package_token,
+ value,
+ ..
+ } => {
+ set_once(&mut package, value, package_token.span, "package")?;
+ }
+ MetaArg::Class {
+ class_token, value, ..
+ } => {
+ set_once(&mut class, value, class_token.span, "class")?;
+ }
+ MetaArg::MethodName {
+ method_name_token,
+ value,
+ ..
+ } => {
+ set_once(
+ &mut method_name,
+ value,
+ method_name_token.span,
+ "method_name",
+ )?;
+ }
+ MetaArg::PanicReturns {
+ panic_returns_token,
+ value,
+ ..
+ } => {
+ set_once(
+ &mut panic_returns,
+ value,
+ panic_returns_token.span,
+ "panic_returns",
+ )?;
+ }
+ }
+ }
+
+ let Some(package) = package else {
+ return Err(syn::Error::new(stream.span(), "`package` is required"));
+ };
+
+ let Some(class) = class else {
+ return Err(syn::Error::new(stream.span(), "`class` is required"));
+ };
+
+ let package = {
+ let package_str = package.value();
+ if package_str.contains('/') {
+ return Err(syn::Error::new(
+ stream.span(),
+ "`package` should use '.' as a separator",
+ ));
+ }
+ substitute_package_chars(&package_str)
+ };
+ let class = substitute_class_chars(&class.value());
+ let class_desc = format!("{package}_{class}");
+
+ Ok(Self {
+ class_desc,
+ method_name,
+ panic_returns,
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use syn::parse_quote;
+
+ #[test]
+ fn can_parse() {
+ let meta: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+ assert_eq!("com_example_Foo_00024Inner", &meta.class_desc);
+ assert!(meta.panic_returns.is_some());
+ }
+
+ #[test]
+ fn can_parse_missing_panic_returns() {
+ let meta: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ };
+ assert_eq!("com_example_Foo_00024Inner", &meta.class_desc);
+ assert!(meta.panic_returns.is_none());
+ }
+
+ #[test]
+ #[should_panic]
+ fn double_package() {
+ let _: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+ }
+
+ #[test]
+ #[should_panic]
+ fn package_uses_slashes() {
+ let _: JniMethodMeta = parse_quote! {
+ package = "com/example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+ }
+
+ #[test]
+ #[should_panic]
+ fn missing_package() {
+ let _: JniMethodMeta = parse_quote! {
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+ }
+
+ #[test]
+ #[should_panic]
+ fn double_class() {
+ let _: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ class = "Foo.Inner",
+ panic_returns = false,
+ };
+ }
+
+ #[test]
+ #[should_panic]
+ fn missing_class() {
+ let _: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ panic_returns = false,
+ };
+ }
+
+ #[test]
+ #[should_panic]
+ fn double_panic_returns() {
+ let _: JniMethodMeta = parse_quote! {
+ package = "com.example",
+ class = "Foo.Inner",
+ panic_returns = false,
+ panic_returns = false,
+ };
+ }
+}
diff --git a/common/pourover_macro/src/jni_method/meta_arg.rs b/common/pourover_macro/src/jni_method/meta_arg.rs
new file mode 100644
index 0000000..02b1900
--- /dev/null
+++ b/common/pourover_macro/src/jni_method/meta_arg.rs
@@ -0,0 +1,119 @@
+// 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.
+
+use syn::{
+ parse::{Parse, ParseStream},
+ Expr, LitStr, Token,
+};
+
+/// Custom keywords
+pub mod kw {
+ syn::custom_keyword!(package);
+ syn::custom_keyword!(class);
+ syn::custom_keyword!(method_name);
+ syn::custom_keyword!(panic_returns);
+}
+
+/// Arguments to the attribute
+pub enum MetaArg {
+ Package {
+ package_token: kw::package,
+ _eq_token: Token![=],
+ value: LitStr,
+ },
+ Class {
+ class_token: kw::class,
+ _eq_token: Token![=],
+ value: LitStr,
+ },
+ MethodName {
+ method_name_token: kw::method_name,
+ _eq_token: Token![=],
+ value: LitStr,
+ },
+ PanicReturns {
+ panic_returns_token: kw::panic_returns,
+ _eq_token: Token![=],
+ value: Expr,
+ },
+}
+
+impl Parse for MetaArg {
+ fn parse(stream: ParseStream<'_>) -> syn::Result<Self> {
+ let lookahead = stream.lookahead1();
+ if lookahead.peek(kw::package) {
+ Ok(MetaArg::Package {
+ package_token: stream.parse::<kw::package>()?,
+ _eq_token: stream.parse()?,
+ value: stream.parse()?,
+ })
+ } else if lookahead.peek(kw::class) {
+ Ok(MetaArg::Class {
+ class_token: stream.parse::<kw::class>()?,
+ _eq_token: stream.parse()?,
+ value: stream.parse()?,
+ })
+ } else if lookahead.peek(kw::method_name) {
+ Ok(MetaArg::MethodName {
+ method_name_token: stream.parse::<kw::method_name>()?,
+ _eq_token: stream.parse()?,
+ value: stream.parse()?,
+ })
+ } else if lookahead.peek(kw::panic_returns) {
+ Ok(MetaArg::PanicReturns {
+ panic_returns_token: stream.parse::<kw::panic_returns>()?,
+ _eq_token: stream.parse()?,
+ value: stream.parse()?,
+ })
+ } else {
+ Err(lookahead.error())
+ }
+ }
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
+mod tests {
+ use super::*;
+ use syn::parse_quote;
+
+ #[test]
+ fn parse_meta_arg_package() {
+ let MetaArg::Package { value, .. } = parse_quote!(package = "com.example") else {
+ panic!("failed to parse")
+ };
+
+ assert_eq!("com.example", value.value());
+ }
+
+ #[test]
+ fn parse_meta_arg_class() {
+ let MetaArg::Class { value, .. } = parse_quote!(class = "Foo") else {
+ panic!("failed to parse")
+ };
+
+ assert_eq!("Foo", value.value());
+ }
+
+ #[test]
+ fn parse_meta_arg_panic_returns() {
+ let MetaArg::PanicReturns { value, .. } = parse_quote!(panic_returns = { foo() }) else {
+ panic!("failed to parse")
+ };
+
+ let syn::Expr::Block(_) = value else {
+ panic!("not a block expression")
+ };
+ }
+}
diff --git a/common/pourover_macro/src/jni_method/substitutions.rs b/common/pourover_macro/src/jni_method/substitutions.rs
new file mode 100644
index 0000000..229bb5d
--- /dev/null
+++ b/common/pourover_macro/src/jni_method/substitutions.rs
@@ -0,0 +1,123 @@
+// 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.
+
+//! Name substitutions for JNI name mangling. See
+//! <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names>
+//! for spec details.
+
+pub fn substitute_method_chars(s: &str) -> String {
+ s.chars()
+ .flat_map(|c| -> CharIter {
+ match c {
+ '$' => "_00024".into(),
+ '_' => "_1".into(),
+ _ => c.into(),
+ }
+ })
+ .collect()
+}
+
+pub fn substitute_package_chars(s: &str) -> String {
+ s.chars()
+ .flat_map(|c| -> CharIter {
+ match c {
+ '.' => "_".into(),
+ '$' => "_00024".into(),
+ '_' => "_1".into(),
+ _ => c.into(),
+ }
+ })
+ .collect()
+}
+
+pub fn substitute_class_chars(s: &str) -> String {
+ s.chars()
+ .flat_map(|c| -> CharIter {
+ match c {
+ // Use dot or dollar for inner classes: `'.' -> '$' -> "_00024"`
+ '.' | '$' => "_00024".into(),
+ '_' => "_1".into(),
+ _ => c.into(),
+ }
+ })
+ .collect()
+}
+
+/// A `char` iterator that can be created from either a `char` or a `&'static str`.
+enum CharIter {
+ One(core::option::IntoIter<char>),
+ Many(core::str::Chars<'static>),
+}
+
+impl Iterator for CharIter {
+ type Item = char;
+ fn next(&mut self) -> Option<char> {
+ match *self {
+ Self::One(ref mut iter) => iter.next(),
+ Self::Many(ref mut iter) => iter.next(),
+ }
+ }
+}
+
+impl From<char> for CharIter {
+ fn from(c: char) -> Self {
+ Self::One(Some(c).into_iter())
+ }
+}
+
+impl From<&'static str> for CharIter {
+ fn from(s: &'static str) -> Self {
+ Self::Many(s.chars())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_char_iter_one() {
+ let seq = CharIter::from('a').collect::<String>();
+ assert_eq!("a", &seq);
+ }
+
+ #[test]
+ fn test_char_iter_many() {
+ let seq = CharIter::from("asdf").collect::<String>();
+ assert_eq!("asdf", &seq);
+ }
+
+ #[test]
+ fn test_substitute_method_chars() {
+ let mangled = substitute_method_chars("method_with_under$cores");
+ assert_eq!("method_1with_1under_00024cores", &mangled);
+ }
+
+ #[test]
+ fn test_substitute_package_chars() {
+ let mangled = substitute_package_chars("com.weird_name.java");
+ assert_eq!("com_weird_1name_java", &mangled);
+ }
+
+ #[test]
+ fn test_substitute_class_chars() {
+ // Both dot and dollar should work here
+
+ let mangled = substitute_class_chars("Foo.Inner");
+ assert_eq!("Foo_00024Inner", &mangled);
+
+ let mangled = substitute_class_chars("Foo$Inner");
+ assert_eq!("Foo_00024Inner", &mangled);
+ }
+}
diff --git a/common/pourover_macro/src/lib.rs b/common/pourover_macro/src/lib.rs
new file mode 100644
index 0000000..f46b7b1
--- /dev/null
+++ b/common/pourover_macro/src/lib.rs
@@ -0,0 +1,286 @@
+// 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.
+
+//! Proc macros for `pourover`. These macros are reexported by the `pourover` crate, so this crate
+//! is an implementation detail.
+
+use proc_macro::TokenStream;
+
+mod call_method;
+mod jni_method;
+mod type_parser;
+
+/// Export a function as a JNI native method. This will attach a `#[export_name = "..."]` attribute that
+/// is formatted with the given parameters. The provided `package`, `class`, and `method_name` will
+/// be combined and formatted in according to the [JNI method name resolution rules][JNI naming].
+///
+/// [JNI naming]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names
+///
+/// # Parameters
+/// - `package` (LitStr): the Java package for the class being implemented
+/// - `class` (LitStr): the Java class being implemented. Use `Foo.Inner` syntax for inner
+/// classes.
+/// - `method_name` (*optional* LitStr): the method's name in Java. The Rust function name will be
+/// used if this parameter is not set.
+/// - `panic_returns` (*optional* Expr): the value to return when a panic is encountered. This can
+/// not access local variables. This may only be used with `panic=unwind` and will produce a
+/// compile error otherwise.
+///
+/// When using `panic_returns` function arguments must be [`std::panic::UnwindSafe`]. See
+/// [`std::panic::catch_unwind`] for details. In practice this will not cause issues as JNI
+/// arguments and return values are passed by pointer or value and not by Rust reference.
+///
+/// # Example
+/// ```
+/// # use pourover_macro::jni_method;
+/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
+///
+/// #[jni_method(package = "my.package", class = "Foo", panic_returns = -1)]
+/// extern "system" fn getFoo<'local>(
+/// mut env: JNIEnv<'local>,
+/// this: JObject<'local>,
+/// ) -> jint {
+/// // ...
+/// 0
+/// }
+/// ```
+///
+/// This function will be exported with `#[export_name = "Java_my_package_Foo_getFoo"]`.
+#[proc_macro_attribute]
+pub fn jni_method(meta: TokenStream, item: TokenStream) -> TokenStream {
+ use quote::ToTokens;
+ match jni_method::jni_method(meta.into(), item.into()) {
+ Ok(item_fn) => item_fn.into_token_stream(),
+ Err(err) => err.into_compile_error(),
+ }
+ .into()
+}
+
+/// Call a Java method.
+///
+/// # Parameters
+/// `call_method!($env, $cls, $name, $sig, $this, $($args),*)`
+/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
+/// - `cls` (Expr: `&'static ClassDesc`): The class containing the method.
+/// - `name` (Expr: `&'static str`): The name of the method.
+/// - `sig` (LitStr): The JNI type signature of the method. This needs to be a literal so that it
+/// can be parsed by the macro to type-check args and return a correctly-typed value.
+/// - `this` (Expr: `&JObject`): The Java object receiving the method call.
+/// - `args` (Expr ...): A variable number of arguments to be passed to the method.
+///
+/// # Caching
+/// Each macro callsite will generate a `static` `MethodDesc` to cache the
+/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
+/// multiple times.
+///
+/// # Type-Safety
+/// The given type signature will be parsed and arguments will be type checked against it. The
+/// expected types are from the `jni` crate:
+/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
+/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
+/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
+///
+/// Similarly, the return type will be one of the types above.
+///
+/// # Returns
+/// The macro will evaluate to `jni::errors::Result<R>` where `R` is the return type parsed from
+/// the type signature.
+///
+/// # Example
+/// Let's call `sayHello` from the following class.
+/// ```java
+/// package com.example;
+/// class Foo {
+/// int sayHello(String name) { /* ... */ }
+/// }
+/// ```
+/// We can use `call_method!` to implement the function call.
+/// ```rust
+/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
+/// # use pourover_macro::call_method;
+/// # use pourover::desc::*;
+/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
+/// fn say_hello<'l>(
+/// env: &mut JNIEnv<'l>,
+/// my_obj: &JObject<'_>,
+/// name: &JString<'_>
+/// ) -> jni::errors::Result<jint> {
+/// call_method!(env, &MY_CLASS, "sayHello", "(Ljava/lang/String;)I", my_obj, name)
+/// }
+/// ```
+#[proc_macro]
+pub fn call_method(args: TokenStream) -> TokenStream {
+ call_method::call_method(args.into())
+ .unwrap_or_else(syn::Error::into_compile_error)
+ .into()
+}
+
+/// Call a static Java method.
+///
+/// # Parameters
+/// `call_static_method!($env, $cls, $name, $sig, $($args),*)`
+/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
+/// - `cls` (Expr: `&'static ClassDesc`): The class containing the method.
+/// - `name` (Expr: `&'static str`): The name of the method.
+/// - `sig` (LitStr): The JNI type signature of the method. This needs to be a literal so that it
+/// can be parsed by the macro to type-check args and return a correctly-typed value.
+/// - `args` (Expr ...): A variable number of arguments to be passed to the method.
+///
+/// # Caching
+/// Each macro callsite will generate a `static` `StaticMethodDesc` to cache the
+/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
+/// multiple times.
+///
+/// # Type-Safety
+/// The given type signature will be parsed and arguments will be type checked against it. The
+/// expected types are from the `jni` crate:
+/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
+/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
+/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
+///
+/// Similarly, the return type will be one of the types above.
+///
+/// # Returns
+/// The macro will evaluate to `jni::errors::Result<R>` where `R` is the return type parsed from
+/// the type signature.
+///
+/// # Example
+/// Let's call `sayHello` from the following class.
+/// ```java
+/// package com.example;
+/// class Foo {
+/// static int sayHello(String name) { /* ... */ }
+/// }
+/// ```
+/// We can use `call_static_method!` to implement the function call.
+/// ```rust
+/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
+/// # use pourover_macro::call_static_method;
+/// # use pourover::desc::*;
+/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
+/// fn say_hello<'l>(
+/// env: &mut JNIEnv<'l>,
+/// name: &JString<'_>
+/// ) -> jni::errors::Result<jint> {
+/// call_static_method!(env, &MY_CLASS, "sayHello", "(Ljava/lang/String;)I", name)
+/// }
+/// ```
+#[proc_macro]
+pub fn call_static_method(args: TokenStream) -> TokenStream {
+ call_method::call_static_method(args.into())
+ .unwrap_or_else(syn::Error::into_compile_error)
+ .into()
+}
+
+/// Call a Java constructor.
+///
+/// # Parameters
+/// `call_constructor!($env, $cls, $sig, $($args),*)`
+/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
+/// - `cls` (Expr: `&'static ClassDesc`): The class to be constructed.
+/// - `sig` (LitStr): The JNI type signature of the constructor. This needs to be a literal so that it
+/// can be parsed by the macro to type-check args and return a correctly-typed value.
+/// - `args` (Expr ...): A variable number of arguments to be passed to the constructor.
+///
+/// # Caching
+/// Each macro callsite will generate a `static` `MethodDesc` to cache the
+/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
+/// multiple times.
+///
+/// # Type-Safety
+/// The given type signature will be parsed and arguments will be type checked against it. The
+/// expected types are from the `jni` crate:
+/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
+/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
+/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
+///
+/// # Returns
+/// The macro will evaluate to `jni::errors::Result<jni::objects::JObject>`.
+///
+/// # Example
+/// Let's call the constructor from the following class.
+/// ```java
+/// package com.example;
+/// class Foo {
+/// Foo(String name) { /* ... */ }
+/// }
+/// ```
+/// We can use `call_constructor!` to implement the function call.
+/// ```rust
+/// # use jni::{objects::{JObject, JString}, JNIEnv};
+/// # use pourover_macro::call_constructor;
+/// # use pourover::desc::*;
+/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
+/// fn construct_foo<'l>(
+/// env: &mut JNIEnv<'l>,
+/// name: &JString<'_>
+/// ) -> jni::errors::Result<JObject<'l>> {
+/// call_constructor!(env, &MY_CLASS, "(Ljava/lang/String;)V", name)
+/// }
+/// ```
+#[proc_macro]
+pub fn call_constructor(args: TokenStream) -> TokenStream {
+ call_method::call_constructor(args.into())
+ .unwrap_or_else(syn::Error::into_compile_error)
+ .into()
+}
+
+#[cfg(test)]
+pub(crate) mod test_util {
+ use proc_macro2::{TokenStream, TokenTree};
+
+ /// Iterator that traverses TokenTree:Group structures in preorder.
+ struct FlatStream {
+ streams: Vec<<TokenStream as IntoIterator>::IntoIter>,
+ }
+
+ impl FlatStream {
+ fn new(stream: TokenStream) -> Self {
+ Self {
+ streams: vec![stream.into_iter()],
+ }
+ }
+ }
+
+ impl Iterator for FlatStream {
+ type Item = TokenTree;
+
+ fn next(&mut self) -> Option<TokenTree> {
+ let next = loop {
+ let stream = self.streams.last_mut()?;
+ if let Some(next) = stream.next() {
+ break next;
+ }
+ let _ = self.streams.pop();
+ };
+
+ if let TokenTree::Group(group) = &next {
+ self.streams.push(group.stream().into_iter());
+ }
+
+ Some(next)
+ }
+ }
+
+ pub fn contains_ident(stream: TokenStream, ident: &str) -> bool {
+ FlatStream::new(stream)
+ .filter_map(|tree| {
+ let TokenTree::Ident(ident) = tree else {
+ return None;
+ };
+ Some(ident.to_string())
+ })
+ .any(|ident_str| ident_str == ident)
+ }
+}
diff --git a/common/pourover_macro/src/type_parser.rs b/common/pourover_macro/src/type_parser.rs
new file mode 100644
index 0000000..e6834e2
--- /dev/null
+++ b/common/pourover_macro/src/type_parser.rs
@@ -0,0 +1,503 @@
+// 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.
+
+//! Parsers for JNI type descriptors.
+
+// There is code that is used in tests but not in the crate.
+#![allow(dead_code)]
+
+use core::fmt;
+use core::num::NonZeroU8;
+use nom::{IResult, Parser};
+
+/// Describes a type in Java
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum JavaType<'a> {
+ /// An array type.
+ Array {
+ /// The number of dimensions. The JVM spec limits this to 255.
+ depth: NonZeroU8,
+ /// The type of objects in the array.
+ ty: NonArray<'a>,
+ },
+ /// A non-array type. See [`NonArray`].
+ NonArray(NonArray<'a>),
+}
+
+impl<'a> JavaType<'a> {
+ /// Check if this type is a primitive type.
+ pub fn is_primitive(&self) -> bool {
+ matches!(*self, Self::NonArray(NonArray::Primitive(_)))
+ }
+
+ fn parse(s: &'a str) -> IResult<&'a str, JavaType<'a>> {
+ use nom::bytes::complete::take_while1;
+ use nom::combinator::{map, map_opt, opt};
+
+ let parse_array = opt(map_opt(take_while1(|c| c == '['), |brackets: &str| {
+ u8::try_from(brackets.len()).ok().and_then(NonZeroU8::new)
+ }));
+
+ map(
+ parse_array.and(NonArray::parse),
+ |(depth, ty)| match depth {
+ Some(depth) => JavaType::Array { depth, ty },
+ None => JavaType::NonArray(ty),
+ },
+ )(s)
+ }
+
+ /// Try to parse a type from the given string in JNI descriptor format.
+ pub fn try_from_str(s: &'a str) -> Option<Self> {
+ run_parser(Self::parse, s)
+ }
+}
+
+impl<'a> fmt::Display for JavaType<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ JavaType::Array { depth, ty } => {
+ for _ in 0..depth.get() {
+ write!(f, "[")?;
+ }
+ write!(f, "{ty}")
+ }
+ JavaType::NonArray(ty) => write!(f, "{ty}"),
+ }
+ }
+}
+
+impl<'a> From<NonArray<'a>> for JavaType<'a> {
+ fn from(ty: NonArray<'a>) -> Self {
+ JavaType::NonArray(ty)
+ }
+}
+
+impl<'a> From<Primitive> for JavaType<'a> {
+ fn from(prim: Primitive) -> Self {
+ JavaType::NonArray(NonArray::Primitive(prim))
+ }
+}
+
+#[cfg(jni)]
+impl<'a> From<JavaType<'a>> for jni::signature::ReturnType {
+ fn from(ty: JavaType<'a>) -> Self {
+ match ty {
+ JavaType::Array { .. } => Self::Array,
+ JavaType::NonArray(NonArray::Object { .. }) => Self::Object,
+ JavaType::NonArray(NonArray::Primitive(p)) => Self::Primitive(p.into()),
+ }
+ }
+}
+
+/// Describes a non-array type in Java
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum NonArray<'a> {
+ /// A primitive type. See [`Primitive`].
+ Primitive(Primitive),
+ /// An object type.
+ Object {
+ /// The class name in JNI form.
+ cls: &'a str,
+ },
+}
+
+impl<'a> NonArray<'a> {
+ fn parse(s: &'a str) -> IResult<&'a str, NonArray<'a>> {
+ use nom::branch::alt;
+ use nom::bytes::complete::take_while1;
+ use nom::character::complete::char;
+ use nom::combinator::map;
+ use nom::sequence::delimited;
+
+ let parse_prim = map(Primitive::parse, NonArray::Primitive);
+
+ let parse_object = map(
+ delimited(char('L'), take_while1(|c| c != ';'), char(';')),
+ |cls| NonArray::Object { cls },
+ );
+
+ alt((parse_prim, parse_object))(s)
+ }
+}
+
+impl<'a> fmt::Display for NonArray<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ NonArray::Primitive(p) => write!(f, "{p}"),
+ NonArray::Object { cls } => write!(f, "L{cls};"),
+ }
+ }
+}
+
+impl<'a> From<Primitive> for NonArray<'a> {
+ fn from(p: Primitive) -> Self {
+ Self::Primitive(p)
+ }
+}
+
+/// Describes a primitive type in Java
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Primitive {
+ /// Java `boolean`
+ Boolean,
+ /// Java `byte`
+ Byte,
+ /// Java `char`
+ Char,
+ /// Java `double`
+ Double,
+ /// Java `float`
+ Float,
+ /// Java `int`
+ Int,
+ /// Java `long`
+ Long,
+ /// Java `short`
+ Short,
+}
+
+impl Primitive {
+ fn parse(s: &str) -> IResult<&str, Primitive> {
+ use nom::branch::alt;
+ use nom::character::complete::char as match_char;
+ use nom::combinator::value;
+
+ let parse_prim = |c: char, p: Primitive| value(p, match_char(c));
+
+ alt((
+ parse_prim('Z', Primitive::Boolean),
+ parse_prim('B', Primitive::Byte),
+ parse_prim('C', Primitive::Char),
+ parse_prim('D', Primitive::Double),
+ parse_prim('F', Primitive::Float),
+ parse_prim('I', Primitive::Int),
+ parse_prim('J', Primitive::Long),
+ parse_prim('S', Primitive::Short),
+ ))(s)
+ }
+
+ pub fn as_char(&self) -> char {
+ match self {
+ Primitive::Boolean => 'Z',
+ Primitive::Byte => 'B',
+ Primitive::Char => 'C',
+ Primitive::Double => 'D',
+ Primitive::Float => 'F',
+ Primitive::Int => 'I',
+ Primitive::Long => 'J',
+ Primitive::Short => 'S',
+ }
+ }
+}
+
+impl fmt::Display for Primitive {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match *self {
+ Primitive::Boolean => 'Z',
+ Primitive::Byte => 'B',
+ Primitive::Char => 'C',
+ Primitive::Double => 'D',
+ Primitive::Float => 'F',
+ Primitive::Int => 'I',
+ Primitive::Long => 'J',
+ Primitive::Short => 'S',
+ }
+ )
+ }
+}
+
+#[cfg(jni)]
+impl From<Primitive> for jni::signature::Primitive {
+ fn from(p: Primitive) -> Self {
+ match p {
+ Primitive::Boolean => Self::Boolean,
+ Primitive::Byte => Self::Byte,
+ Primitive::Char => Self::Char,
+ Primitive::Double => Self::Double,
+ Primitive::Float => Self::Float,
+ Primitive::Int => Self::Int,
+ Primitive::Long => Self::Long,
+ Primitive::Short => Self::Short,
+ }
+ }
+}
+
+/// A Java return type. This may be `void`.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum ReturnType<'a> {
+ /// Java `void`. Only valid in return position.
+ Void,
+ /// A non-void return type.
+ Returns(JavaType<'a>),
+}
+
+impl<'a> ReturnType<'a> {
+ fn parse(s: &'a str) -> IResult<&'a str, ReturnType<'a>> {
+ use nom::branch::alt;
+ use nom::character::complete::char;
+ use nom::combinator::{map, value};
+
+ alt((
+ value(ReturnType::Void, char('V')),
+ map(JavaType::parse, ReturnType::Returns),
+ ))(s)
+ }
+
+ /// Try to parse a return type from the given string in JNI descriptor format.
+ pub fn try_from_str(s: &'a str) -> Option<Self> {
+ run_parser(Self::parse, s)
+ }
+
+ /// Check if the return type is `ReturnType::Void`
+ pub fn is_void(&self) -> bool {
+ matches!(*self, Self::Void)
+ }
+}
+
+impl<'a> From<JavaType<'a>> for ReturnType<'a> {
+ fn from(ty: JavaType<'a>) -> Self {
+ Self::Returns(ty)
+ }
+}
+
+#[cfg(jni)]
+impl<'a> From<ReturnType<'a>> for jni::signature::ReturnType {
+ fn from(ty: ReturnType<'a>) -> Self {
+ match ty {
+ ReturnType::Void => Self::Primitive(jni::signature::Primitive::Void),
+ ReturnType::Returns(ty) => ty.into(),
+ }
+ }
+}
+
+/// A type signature of a Java method.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct MethodSig<'a> {
+ /// The types of each argument.
+ pub args: Vec<JavaType<'a>>,
+ /// The return type.
+ pub ret: ReturnType<'a>,
+}
+
+impl<'a> MethodSig<'a> {
+ fn parse(s: &'a str) -> IResult<&'a str, MethodSig<'a>> {
+ use nom::character::complete::char;
+ use nom::combinator::map;
+ use nom::multi::many0;
+ use nom::sequence::delimited;
+
+ let parse_args = delimited(char('('), many0(JavaType::parse), char(')'));
+ let mut parser = map(parse_args.and(ReturnType::parse), |(args, ret)| MethodSig {
+ args,
+ ret,
+ });
+
+ parser(s)
+ }
+
+ /// Try to parse a method signature from the given string in JNI descriptor format.
+ pub fn try_from_str(s: &'a str) -> Option<Self> {
+ run_parser(Self::parse, s)
+ }
+}
+
+/// Helper to run a parser and return its result if it parsed the entire string.
+fn run_parser<'a, O, E>(mut parser: impl Parser<&'a str, O, E>, s: &'a str) -> Option<O> {
+ parser.parse(s).ok().and_then(|(rest, out)| {
+ if !rest.is_empty() {
+ return None;
+ }
+ Some(out)
+ })
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn parse_primitive() {
+ let (rest, parsed) = JavaType::parse("II").unwrap();
+ assert_eq!("I", rest);
+ assert_eq!(
+ JavaType::NonArray(NonArray::Primitive(Primitive::Int)),
+ parsed
+ );
+ }
+
+ #[test]
+ fn parse_object() {
+ let (rest, parsed) = JavaType::parse("Ljava/lang/String;I").unwrap();
+ assert_eq!("I", rest);
+ assert_eq!(
+ JavaType::NonArray(NonArray::Object {
+ cls: "java/lang/String"
+ }),
+ parsed
+ );
+ }
+
+ #[test]
+ fn parse_primitive_array() {
+ let (rest, parsed) = JavaType::parse("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[II").unwrap();
+ assert_eq!("I", rest);
+ assert_eq!(
+ JavaType::Array {
+ depth: NonZeroU8::new(255).unwrap(),
+ ty: NonArray::Primitive(Primitive::Int)
+ },
+ parsed
+ );
+ }
+
+ #[test]
+ fn parse_object_array() {
+ let (rest, parsed) = JavaType::parse("[[[Ljava/lang/String;I").unwrap();
+ assert_eq!("I", rest);
+ assert_eq!(
+ JavaType::Array {
+ depth: NonZeroU8::new(3).unwrap(),
+ ty: NonArray::Object {
+ cls: "java/lang/String"
+ }
+ },
+ parsed
+ );
+ }
+
+ #[test]
+ fn parse_invalid_array() {
+ let opt = JavaType::try_from_str("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[I");
+
+ assert_eq!(None, opt);
+ }
+
+ #[test]
+ fn parse_invalid_method() {
+ let parsed = MethodSig::try_from_str("I(I)I");
+ assert_eq!(None, parsed);
+ }
+
+ #[test]
+ fn parse_argless_method() {
+ let parsed = MethodSig::try_from_str("()V").unwrap();
+ assert_eq!(ReturnType::Void, parsed.ret);
+ assert_eq!(0, parsed.args.len());
+ }
+
+ #[test]
+ fn parse_void_method() {
+ let parsed = MethodSig::try_from_str("([ILjava/lang/String;Z)V").unwrap();
+ assert_eq!(ReturnType::Void, parsed.ret);
+ assert_eq!(3, parsed.args.len());
+ assert_eq!(
+ JavaType::Array {
+ depth: NonZeroU8::new(1).unwrap(),
+ ty: NonArray::Primitive(Primitive::Int)
+ },
+ parsed.args[0]
+ );
+ assert_eq!(
+ JavaType::NonArray(NonArray::Object {
+ cls: "java/lang/String"
+ }),
+ parsed.args[1]
+ );
+ assert_eq!(
+ JavaType::NonArray(NonArray::Primitive(Primitive::Boolean)),
+ parsed.args[2]
+ );
+ }
+
+ #[test]
+ fn parse_nonvoid_method() {
+ let parsed = MethodSig::try_from_str("([ILjava/lang/String;Z)D").unwrap();
+ assert_eq!(
+ ReturnType::Returns(JavaType::NonArray(NonArray::Primitive(Primitive::Double))),
+ parsed.ret
+ );
+ assert_eq!(3, parsed.args.len());
+ assert_eq!(
+ JavaType::Array {
+ depth: NonZeroU8::new(1).unwrap(),
+ ty: NonArray::Primitive(Primitive::Int)
+ },
+ parsed.args[0]
+ );
+ assert_eq!(
+ JavaType::NonArray(NonArray::Object {
+ cls: "java/lang/String"
+ }),
+ parsed.args[1]
+ );
+ assert_eq!(
+ JavaType::NonArray(NonArray::Primitive(Primitive::Boolean)),
+ parsed.args[2]
+ );
+ }
+
+ #[test]
+ fn parse_trailing_data_will_error() {
+ assert!(JavaType::try_from_str("Itrailing").is_none());
+ assert!(JavaType::try_from_str("Lcom/example/Foo;trailing").is_none());
+ assert!(JavaType::try_from_str("[Ztrailing").is_none());
+ assert!(MethodSig::try_from_str("()Itrailing").is_none());
+ assert!(MethodSig::try_from_str("()Lcom/example/Foo;trailing").is_none());
+ assert!(MethodSig::try_from_str("()[Ztrailing").is_none());
+ }
+
+ #[test]
+ fn java_type_roundtrip_through_display() {
+ let tests = [
+ "Z",
+ "C",
+ "B",
+ "S",
+ "I",
+ "J",
+ "F",
+ "D",
+ "Ljava/lang/String;",
+ "[Z",
+ "[[B",
+ "[[[Ljava/lang/String;",
+ ];
+
+ for test in tests {
+ let parsed = JavaType::try_from_str(test).unwrap();
+
+ let display = format!("{parsed}");
+
+ assert_eq!(test, display);
+ }
+ }
+
+ #[test]
+ fn test_is_prim() {
+ assert!(JavaType::try_from_str("I").unwrap().is_primitive());
+ assert!(JavaType::try_from_str("Z").unwrap().is_primitive());
+ assert!(!JavaType::try_from_str("[I").unwrap().is_primitive());
+ assert!(!JavaType::try_from_str("[Ljava/lang/String;")
+ .unwrap()
+ .is_primitive());
+ assert!(!JavaType::try_from_str("Ljava/lang/String;")
+ .unwrap()
+ .is_primitive());
+ }
+}
diff --git a/nearby/.cargo/config-boringssl.toml b/nearby/.cargo/config-boringssl.toml
deleted file mode 100644
index 2bde6df..0000000
--- a/nearby/.cargo/config-boringssl.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-# The packages to override
-paths = [
- "../third_party/boringssl/rust/bssl-sys",
- "../boringssl-build/rust-openssl/openssl",
- "../boringssl-build/rust-openssl/openssl-sys",
-]
-
-[env]
-WORKSPACE_DIR = { value = "", relative = true }
diff --git a/nearby/Android.bp b/nearby/Android.bp
index d79a7da..e68ecf3 100644
--- a/nearby/Android.bp
+++ b/nearby/Android.bp
@@ -10,18 +10,6 @@ package {
default_applicable_licenses: ["external_rust_beto-rust_license"],
}
-rust_defaults {
- name: "beto_rust_defaults",
- host_supported: true,
- cargo_env_compat: true,
- cargo_pkg_version: "0.1.0",
- edition: "2021",
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
-}
-
rust_library_rlib {
name: "libcrypto_provider",
crate_name: "crypto_provider",
@@ -51,16 +39,6 @@ rust_library_rlib {
}
rust_library_rlib {
- name: "liblock_adapter",
- crate_name: "lock_adapter",
- defaults: ["beto_rust_defaults"],
- srcs: ["util/lock_adapter/src/lib.rs"],
- features: [
- "std",
- ],
-}
-
-rust_library_rlib {
name: "libcrypto_provider_default",
crate_name: "crypto_provider_default",
defaults: ["beto_rust_defaults"],
diff --git a/nearby/Cargo.lock b/nearby/Cargo.lock
index 3a3934a..2524c30 100644
--- a/nearby/Cargo.lock
+++ b/nearby/Cargo.lock
@@ -69,12 +69,6 @@ dependencies = [
]
[[package]]
-name = "aliasable"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
-
-[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -97,9 +91,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
-version = "0.6.5"
+version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -145,9 +139,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.79"
+version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
[[package]]
name = "array_ref"
@@ -171,9 +165,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
-version = "0.21.6"
+version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64ct"
@@ -189,9 +183,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "blake2"
@@ -222,9 +216,9 @@ dependencies = [
[[package]]
name = "bssl-crypto"
-version = "0.1.0"
+version = "0.2.0"
dependencies = [
- "bssl-sys 0.1.0",
+ "bssl-sys",
]
[[package]]
@@ -232,12 +226,6 @@ name = "bssl-sys"
version = "0.1.0"
[[package]]
-name = "bssl-sys"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "312d12393c060384f2e6ed14c7b4be37b3dd90249857485613c1a91b9a1abb5c"
-
-[[package]]
name = "bstr"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -253,11 +241,12 @@ version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
- "clap",
+ "clap 4.5.1",
"cmd-runner",
"crossbeam",
"env_logger",
"file-header",
+ "glob",
"globset",
"log",
"owo-colors",
@@ -305,6 +294,25 @@ dependencies = [
]
[[package]]
+name = "cbindgen"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49"
+dependencies = [
+ "clap 3.2.25",
+ "heck",
+ "indexmap",
+ "log",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "syn 1.0.109",
+ "tempfile",
+ "toml",
+]
+
+[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -327,14 +335,14 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.31"
+version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.3",
]
[[package]]
@@ -378,7 +386,22 @@ dependencies = [
name = "clap"
version = "4.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
+checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
+dependencies = [
+ "atty",
+ "bitflags 1.3.2",
+ "clap_lex 0.2.4",
+ "indexmap",
+ "strsim 0.10.0",
+ "termcolor",
+ "textwrap",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
dependencies = [
"clap_builder",
"clap_derive",
@@ -386,33 +409,42 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.4.14"
+version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
+checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
dependencies = [
"anstream",
"anstyle",
- "clap_lex",
- "strsim",
+ "clap_lex 0.7.0",
+ "strsim 0.11.0",
]
[[package]]
name = "clap_derive"
-version = "4.4.7"
+version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
name = "clap_lex"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "cmd-runner"
@@ -478,7 +510,7 @@ dependencies = [
"anes",
"cast",
"ciborium",
- "clap",
+ "clap 4.5.1",
"criterion-plot",
"is-terminal",
"itertools",
@@ -589,8 +621,7 @@ name = "crypto_provider"
version = "0.1.0"
dependencies = [
"criterion",
- "crypto_provider_openssl",
- "crypto_provider_rustcrypto",
+ "crypto_provider_default",
"hex-literal",
"rand",
"rand_ext",
@@ -612,25 +643,10 @@ dependencies = [
"cfg-if",
"crypto_provider",
"crypto_provider_boringssl",
- "crypto_provider_openssl",
"crypto_provider_rustcrypto",
]
[[package]]
-name = "crypto_provider_openssl"
-version = "0.1.0"
-dependencies = [
- "cfg-if",
- "crypto_provider",
- "crypto_provider_stubs",
- "crypto_provider_test",
- "hex-literal",
- "openssl",
- "ouroboros",
- "rstest",
-]
-
-[[package]]
name = "crypto_provider_rustcrypto"
version = "0.1.0"
dependencies = [
@@ -714,7 +730,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
@@ -756,9 +772,9 @@ dependencies = [
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -796,9 +812,9 @@ dependencies = [
[[package]]
name = "env_logger"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
@@ -863,19 +879,10 @@ dependencies = [
]
[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-dependencies = [
- "foreign-types-shared",
-]
-
-[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
+name = "fnv"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "generic-array"
@@ -917,6 +924,12 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "globset"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "globset"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
@@ -1101,6 +1114,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
+name = "java-locator"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90003f2fd9c52f212c21d8520f1128da0080bad6fff16b68fe6e7f2f0c3780c2"
+dependencies = [
+ "glob",
+ "lazy_static",
+]
+
+[[package]]
name = "jni"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1109,7 +1132,9 @@ dependencies = [
"cesu8",
"cfg-if",
"combine",
+ "java-locator",
"jni-sys",
+ "libloading",
"log",
"thiserror",
"walkdir",
@@ -1148,7 +1173,7 @@ dependencies = [
"anyhow",
"base64",
"blake2",
- "clap",
+ "clap 4.5.1",
"criterion",
"crypto_provider",
"crypto_provider_default",
@@ -1177,7 +1202,6 @@ dependencies = [
"criterion",
"crypto_provider",
"crypto_provider_default",
- "crypto_provider_openssl",
"crypto_provider_rustcrypto",
"hex",
"ldt",
@@ -1192,6 +1216,21 @@ dependencies = [
]
[[package]]
+name = "ldt_np_adv_ffi"
+version = "0.1.0"
+dependencies = [
+ "cfg-if",
+ "crypto_provider",
+ "crypto_provider_default",
+ "lazy_static",
+ "ldt",
+ "ldt_np_adv",
+ "np_hkdf",
+ "rand",
+ "spin 0.9.8",
+]
+
+[[package]]
name = "ldt_np_jni"
version = "0.1.0"
dependencies = [
@@ -1213,9 +1252,19 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.152"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "libloading"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
[[package]]
name = "license"
@@ -1230,9 +1279,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_adapter"
@@ -1324,7 +1373,15 @@ dependencies = [
"crypto_provider",
"np_adv",
"sink",
- "thiserror",
+]
+
+[[package]]
+name = "np_c_ffi"
+version = "0.1.0"
+dependencies = [
+ "cbindgen",
+ "lock_adapter",
+ "np_ffi_core",
]
[[package]]
@@ -1419,67 +1476,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
-name = "openssl"
-version = "0.10.62"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
-dependencies = [
- "bitflags 2.4.1",
- "cfg-if",
- "foreign-types",
- "libc",
- "once_cell",
- "openssl-macros",
- "openssl-sys",
-]
-
-[[package]]
-name = "openssl-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.98"
+name = "os_str_bytes"
+version = "6.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
-dependencies = [
- "bssl-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc",
- "libc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "ouroboros"
-version = "0.17.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2ba07320d39dfea882faa70554b4bd342a5f273ed59ba7c1c6b4c840492c954"
-dependencies = [
- "aliasable",
- "ouroboros_macro",
- "static_assertions",
-]
-
-[[package]]
-name = "ouroboros_macro"
-version = "0.17.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
+checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
[[package]]
name = "owo-colors"
@@ -1508,12 +1508,6 @@ dependencies = [
]
[[package]]
-name = "pkg-config"
-version = "0.3.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
-
-[[package]]
name = "platforms"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1560,49 +1554,49 @@ dependencies = [
]
[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+name = "pourover"
+version = "0.1.0"
+dependencies = [
+ "jni",
+ "pourover_macro",
+]
[[package]]
-name = "primeorder"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+name = "pourover_macro"
+version = "0.1.0"
dependencies = [
- "elliptic-curve",
+ "pourover_macro_core",
]
[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+name = "pourover_macro_core"
+version = "0.1.0"
dependencies = [
- "proc-macro-error-attr",
"proc-macro2",
"quote",
- "syn 1.0.109",
- "version_check",
+ "syn 2.0.50",
]
[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "primeorder"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
+ "elliptic-curve",
]
[[package]]
name = "proc-macro2"
-version = "1.0.76"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -1751,15 +1745,6 @@ dependencies = [
]
[[package]]
-name = "redox_syscall"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1826,7 +1811,7 @@ dependencies = [
"regex",
"relative-path",
"rustc_version",
- "syn 2.0.48",
+ "syn 2.0.50",
"unicode-ident",
]
@@ -1839,7 +1824,7 @@ dependencies = [
"quote",
"rand",
"rustc_version",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
@@ -1853,11 +1838,11 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.38.28"
+version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
@@ -1912,29 +1897,29 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
-version = "1.0.195"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.195"
+version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
name = "serde_json"
-version = "1.0.111"
+version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
@@ -2000,16 +1985,16 @@ dependencies = [
]
[[package]]
-name = "static_assertions"
-version = "1.1.0"
+name = "strsim"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
-version = "0.10.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "strum"
@@ -2027,7 +2012,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
@@ -2048,9 +2033,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.48"
+version = "2.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
dependencies = [
"proc-macro2",
"quote",
@@ -2059,13 +2044,12 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.9.0"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
+checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
dependencies = [
"cfg-if",
"fastrand",
- "redox_syscall",
"rustix",
"windows-sys 0.52.0",
]
@@ -2089,22 +2073,22 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.56"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.56"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
]
[[package]]
@@ -2124,6 +2108,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
+name = "toml"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2201,7 +2194,7 @@ dependencies = [
name = "ukey2_shell"
version = "0.1.0"
dependencies = [
- "clap",
+ "clap 4.5.1",
"crypto_provider_rustcrypto",
"ukey2_connections",
"ukey2_rs",
@@ -2236,12 +2229,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2284,7 +2271,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
"wasm-bindgen-shared",
]
@@ -2306,7 +2293,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.50",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2394,7 +2381,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.0",
+ "windows-targets 0.52.3",
]
[[package]]
@@ -2443,6 +2430,21 @@ dependencies = [
]
[[package]]
+name = "windows-targets"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.3",
+ "windows_aarch64_msvc 0.52.3",
+ "windows_i686_gnu 0.52.3",
+ "windows_i686_msvc 0.52.3",
+ "windows_x86_64_gnu 0.52.3",
+ "windows_x86_64_gnullvm 0.52.3",
+ "windows_x86_64_msvc 0.52.3",
+]
+
+[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2461,6 +2463,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+
+[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2479,6 +2487,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
+
+[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2497,6 +2511,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
+name = "windows_i686_gnu"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+
+[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2515,6 +2535,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
+name = "windows_i686_msvc"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
+
+[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2533,6 +2559,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+
+[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2551,6 +2583,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
+
+[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2569,6 +2607,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
+
+[[package]]
name = "wycheproof"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/nearby/Cargo.toml b/nearby/Cargo.toml
index 236b74f..4081209 100644
--- a/nearby/Cargo.toml
+++ b/nearby/Cargo.toml
@@ -2,59 +2,60 @@
members = [
"connections/ukey2/ukey2",
"connections/ukey2/ukey2_connections",
+ "connections/ukey2/ukey2_connections/fuzz",
"connections/ukey2/ukey2_c_ffi",
"connections/ukey2/ukey2_jni",
"connections/ukey2/ukey2_proto",
"connections/ukey2/ukey2_shell",
"crypto/crypto_provider",
- "crypto/crypto_provider_openssl",
"crypto/crypto_provider_rustcrypto",
"crypto/crypto_provider_stubs",
"crypto/crypto_provider_test",
+ "crypto/crypto_provider_test/fuzz",
"crypto/crypto_provider_default",
- "crypto/rand_core_05_adapter",
"presence/array_view",
"presence/ldt",
+ "presence/ldt/fuzz",
"presence/ldt_np_adv",
+ "presence/ldt_np_adv/fuzz",
+ "presence/ldt_np_adv_ffi",
"presence/ldt_np_jni",
"presence/ldt_tbc",
"presence/np_adv",
"presence/np_adv_dynamic",
+ "presence/np_c_ffi",
"presence/np_ed25519",
"presence/np_ffi_core",
"presence/np_hkdf",
+ "presence/np_java_ffi",
"presence/rand_ext",
"presence/sink",
"presence/test_helper",
+ "presence/test_vector_hkdf",
"presence/xts_aes",
- "util/lock_adapter",
- "util/handle_map",
+ "presence/xts_aes/fuzz",
]
-# TODO: remove ldt_np_adv_ffi once support for no_std + alloc no longer requires nightly
# TODO: remove boringssl once we figure out a better plan for integrating the build system
-# TODO: remove np_c_ffi once cbindgen no longer requires nightly
exclude = [
- "presence/ldt_np_adv_ffi",
"crypto/crypto_provider_boringssl",
- "presence/np_c_ffi",
]
[workspace.lints.rust]
-unsafe_code = "deny"
missing_docs = "deny"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
+unsafe_code = "deny"
+unsafe_op_in_unsafe_fn = "deny"
unused_extern_crates = "deny"
unused_import_braces = "deny"
unused_results = "deny"
[workspace.lints.clippy]
+expect_used = "deny"
indexing_slicing = "deny"
-unwrap_used = "deny"
panic = "deny"
-expect_used = "deny"
-
+unwrap_used = "deny"
[workspace.dependencies]
# local crates
@@ -62,16 +63,14 @@ array_ref = { path = "presence/array_ref" }
array_view = { path = "presence/array_view" }
crypto_provider = { path = "crypto/crypto_provider", default-features = false }
crypto_provider_default = { path = "crypto/crypto_provider_default", default-features = false }
-crypto_provider_openssl = { path = "crypto/crypto_provider_openssl" }
crypto_provider_boringssl = { path = "crypto/crypto_provider_boringssl" }
crypto_provider_rustcrypto = { path = "crypto/crypto_provider_rustcrypto" }
crypto_provider_stubs = { path = "crypto/crypto_provider_stubs" }
crypto_provider_test = { path = "crypto/crypto_provider_test" }
-lock_adapter = { path = "util/lock_adapter" }
-handle_map = { path = "util/handle_map" }
-rand_core_05_adapter = { path = "crypto/rand_core_05_adapter" }
rand_ext = { path = "presence/rand_ext" }
test_helper = { path = "presence/test_helper" }
+ukey2_connections = { path = "connections/ukey2/ukey2_connections" }
+ukey2_rs = { path = "connections/ukey2/ukey2" }
ukey2_proto = { path = "connections/ukey2/ukey2_proto" }
np_hkdf = { path = "presence/np_hkdf" }
xts_aes = { path = "presence/xts_aes" }
@@ -81,8 +80,18 @@ ldt_tbc = { path = "presence/ldt_tbc" }
np_adv = { path = "presence/np_adv" }
np_adv_dynamic = { path = "presence/np_adv_dynamic" }
np_ed25519 = { path = "presence/np_ed25519" }
-np_ffi_core = { path = "presence/np_ffi_core" }
+np_ffi_core = { path = "presence/np_ffi_core", default-features=false }
+np_java_ffi = { path = "presence/np_java_ffi" }
sink = { path = "presence/sink" }
+test_vector_hkdf = { path = "presence/test_vector_hkdf" }
+
+# from utils workspace
+derive_fuzztest = { path = "../common/derive_fuzztest" }
+derive_fuzztest_macro = { path = "../common/derive_fuzztest_macro" }
+handle_map = { path = "../common/handle_map" }
+lock_adapter = { path = "../common/lock_adapter" }
+pourover = { path = "../common/pourover" }
+pourover_macro = { path = "../common/pourover_macro" }
# from crates.io
rand = { version = "0.8.5", default-features = false }
@@ -90,10 +99,12 @@ rand_core = { version = "0.6.4", features = ["getrandom"] }
rand_pcg = "0.3.1"
sha2 = { version = "0.10.8", default-features = false }
aes = "0.8.3"
+arbitrary = "1.3.2"
cbc = { version = "0.1.2", features = ["block-padding"] }
ctr = "0.9.2"
hkdf = "0.12.3"
hmac = "0.12.1"
+nom = { version = "7.1.3", default-features = false }
ed25519-dalek = { version = "2.1.0", default-features = false }
ed25519 = "2.2.3"
aes-gcm = "0.10.3"
@@ -121,7 +132,6 @@ criterion = { version = "0.5.1", features = ["html_reports"] }
clap = { version = "4.4.11", features = ["derive"] }
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
hex-literal = "0.4.1"
-openssl = "0.10.61"
cfg-if = "1.0.0"
blake2 = "0.10.6"
hdrhistogram = "7.5.4"
@@ -136,10 +146,19 @@ tempfile = "3.8.1"
thiserror = "1.0.51"
tinyvec = { version = "1.6.0", features = ["rustc_1_55"] }
mlua = "0.9.2"
-strum = { version = "0.25.0", default-features=false }
-strum_macros = { version = "0.25.3", default-features=false }
+strum = { version = "0.25.0", default-features = false }
+strum_macros = { version = "0.25.3", default-features = false }
owo-colors = "3.5.0"
rhai = { version = "1.16.3", features = ["sync"] }
+cbindgen = "0.26.0"
+syn = { version = "2.0", features = ["full"] }
+proc-macro2 = "1.0"
+quote = "1.0"
+itertools = "0.12.1"
+quickcheck = "1.0.3"
+proptest = "1.4.0"
+proptest-arbitrary-interop = { git = "https://github.com/brson/proptest-arbitrary-interop.git", branch = "incorrect-format" }
+libfuzzer-sys = "0.4.7"
[workspace.package]
version = "0.1.0"
@@ -174,22 +193,23 @@ rust-version = "1.71.0"
[dependencies]
clap.workspace = true
-cmd-runner = { path = "../cmd-runner" }
+cmd_runner = { path = "../common/cmd_runner" }
anyhow.workspace = true
shell-escape = "0.1.5"
owo-colors.workspace = true
semver = "1.0.17"
walkdir = "2.3.3"
globset = "0.4.10"
+glob = "0.3.1"
crossbeam = "0.8.2"
chrono.workspace = true
thiserror.workspace = true
log.workspace = true
env_logger.workspace = true
-which = "4.4.0"
file-header = "0.1.2"
-serde_json.workspace = true
+serde_json = { workspace = true, features = ["std"] }
regex = "1.10.2"
+xshell = "0.2.6"
[dev-dependencies]
tempfile.workspace = true
diff --git a/nearby/README.md b/nearby/README.md
index 86db67d..f951a8b 100644
--- a/nearby/README.md
+++ b/nearby/README.md
@@ -32,10 +32,10 @@ Our project requires specific versions of system dependencies like OpenSSL and
protobuf in order to build correctly. To make the setup of this easier you can
use Docker to handle setting up the environment in a container.
-First install Docker then build and run the image:
+First install Docker then build and run the image from repo root:
```
-sudo docker build -t nearby_rust:v1.0 ..
+sudo docker build -t nearby_rust:v1.0 .
sudo docker run --rm -it nearby_rust:v1.0
```
diff --git a/nearby/connections/ukey2/ukey2/Cargo.toml b/nearby/connections/ukey2/ukey2/Cargo.toml
index 2ac6f3a..35de144 100644
--- a/nearby/connections/ukey2/ukey2/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2/Cargo.toml
@@ -10,7 +10,6 @@ workspace = true
[features]
default = []
test_rustcrypto = ["crypto_provider_default/rustcrypto"]
-test_openssl = ["crypto_provider_default/openssl"]
test_boringssl = ["crypto_provider_default/boringssl"]
[dependencies]
diff --git a/nearby/connections/ukey2/ukey2/src/lib.rs b/nearby/connections/ukey2/ukey2/src/lib.rs
index dc17b83..4d64bc8 100644
--- a/nearby/connections/ukey2/ukey2/src/lib.rs
+++ b/nearby/connections/ukey2/ukey2/src/lib.rs
@@ -25,6 +25,7 @@ mod state_machine;
mod tests;
mod ukey2_handshake;
+pub use proto_adapter::NextProtocol;
pub use state_machine::{SendAlert, StateMachine};
pub use ukey2_handshake::{
CompletedHandshake, HandshakeImplementation, Ukey2Client, Ukey2ClientStage1, Ukey2Server,
diff --git a/nearby/connections/ukey2/ukey2/src/proto_adapter.rs b/nearby/connections/ukey2/ukey2/src/proto_adapter.rs
index 2986276..0ecbe8a 100644
--- a/nearby/connections/ukey2/ukey2/src/proto_adapter.rs
+++ b/nearby/connections/ukey2/ukey2/src/proto_adapter.rs
@@ -17,6 +17,8 @@
use crypto_provider::elliptic_curve::EcdhProvider;
use crypto_provider::p256::{P256EcdhProvider, P256PublicKey, P256};
use crypto_provider::CryptoProvider;
+use std::collections::HashSet;
+use std::fmt::{Display, Formatter};
use ukey2_proto::ukey2_all_proto::{securemessage, ukey};
/// For generated proto types for UKEY2 messages
@@ -71,6 +73,41 @@ pub(crate) trait IntoAdapter<A> {
fn into_adapter(self) -> Result<A, ukey::ukey2alert::AlertType>;
}
+/// Enum representing the different supported next_protocol strings, ordered by desirability.
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
+#[repr(i32)]
+pub enum NextProtocol {
+ /// AES-256-GCM-SIV, for use with newer clients.
+ Aes256GcmSiv,
+ /// AES_256_CBC-HMAC_SHA256, already in use and supported by all clients.
+ Aes256CbcHmacSha256,
+}
+
+impl TryFrom<&String> for NextProtocol {
+ type Error = ukey::ukey2alert::AlertType;
+
+ fn try_from(value: &String) -> Result<Self, Self::Error> {
+ match value.as_str() {
+ "AES_256_GCM_SIV" => Ok(NextProtocol::Aes256GcmSiv),
+ "AES_256_CBC-HMAC_SHA256" => Ok(NextProtocol::Aes256CbcHmacSha256),
+ _ => Err(ukey::ukey2alert::AlertType::BAD_NEXT_PROTOCOL),
+ }
+ }
+}
+
+impl Display for NextProtocol {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ NextProtocol::Aes256CbcHmacSha256 => "AES_256_CBC-HMAC_SHA256",
+ NextProtocol::Aes256GcmSiv => "AES_256_GCM_SIV",
+ },
+ )
+ }
+}
+
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum MessageType {
ClientInit,
@@ -81,7 +118,7 @@ pub(crate) enum MessageType {
pub(crate) struct ClientInit {
version: i32,
commitments: Vec<CipherCommitment>,
- next_protocol: String,
+ next_protocols: HashSet<NextProtocol>,
}
impl ClientInit {
@@ -93,8 +130,8 @@ impl ClientInit {
&self.commitments
}
- pub fn next_protocol(&self) -> &str {
- &self.next_protocol
+ pub fn next_protocols(&self) -> &HashSet<NextProtocol> {
+ &self.next_protocols
}
}
@@ -104,6 +141,7 @@ pub(crate) struct ServerInit {
random: [u8; 32],
handshake_cipher: HandshakeCipher,
pub(crate) public_key: Vec<u8>,
+ selected_next_protocol: NextProtocol,
}
impl ServerInit {
@@ -114,6 +152,10 @@ impl ServerInit {
pub fn handshake_cipher(&self) -> HandshakeCipher {
self.handshake_cipher
}
+
+ pub fn selected_next_protocol(&self) -> NextProtocol {
+ self.selected_next_protocol
+ }
}
pub(crate) struct ClientFinished {
@@ -208,8 +250,13 @@ impl IntoAdapter<ClientInit> for ukey::Ukey2ClientInit {
.next_protocol
.filter(|n| !n.is_empty())
.ok_or(ukey::ukey2alert::AlertType::BAD_NEXT_PROTOCOL)?;
+ let mut next_protocols: HashSet<NextProtocol> =
+ HashSet::from([(&next_protocol).try_into()?]);
+ let other_next_protocols: Vec<NextProtocol> =
+ self.next_protocols.iter().filter_map(|p| p.try_into().ok()).collect();
+ next_protocols.extend(&other_next_protocols);
Ok(ClientInit {
- next_protocol,
+ next_protocols,
version,
commitments: self
.cipher_commitments
@@ -234,7 +281,11 @@ impl IntoAdapter<ServerInit> for ukey::Ukey2ServerInit {
// We will be handling bad pubkeys in the layers above
let public_key: Vec<u8> =
self.public_key.ok_or(ukey::ukey2alert::AlertType::BAD_PUBLIC_KEY)?;
- Ok(ServerInit { handshake_cipher, version, public_key, random })
+ let selected_next_protocol = self
+ .selected_next_protocol
+ .and_then(|p| (&p).try_into().ok())
+ .unwrap_or(NextProtocol::Aes256CbcHmacSha256);
+ Ok(ServerInit { handshake_cipher, version, public_key, random, selected_next_protocol })
}
}
diff --git a/nearby/connections/ukey2/ukey2/src/state_machine.rs b/nearby/connections/ukey2/ukey2/src/state_machine.rs
index d2021e6..b4ad360 100644
--- a/nearby/connections/ukey2/ukey2/src/state_machine.rs
+++ b/nearby/connections/ukey2/ukey2/src/state_machine.rs
@@ -12,17 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use std::fmt::Debug;
+
+use log::error;
+
+use crypto_provider::CryptoProvider;
+use ukey2_proto::protobuf::Message;
+use ukey2_proto::ukey2_all_proto::ukey;
+
use crate::proto_adapter::{IntoAdapter, MessageType, ToWrappedMessage as _};
use crate::ukey2_handshake::ClientFinishedError;
use crate::ukey2_handshake::{
ClientInit, ClientInitError, Ukey2Client, Ukey2ClientStage1, Ukey2Server, Ukey2ServerStage1,
Ukey2ServerStage2,
};
-use crypto_provider::CryptoProvider;
-use log::error;
-use std::fmt::Debug;
-use ukey2_proto::protobuf::Message;
-use ukey2_proto::ukey2_all_proto::ukey;
/// An alert type and message to be sent to the other party.
#[derive(Debug, PartialEq, Eq)]
diff --git a/nearby/connections/ukey2/ukey2/src/tests.rs b/nearby/connections/ukey2/ukey2/src/tests.rs
index 92c0358..1b2424a 100644
--- a/nearby/connections/ukey2/ukey2/src/tests.rs
+++ b/nearby/connections/ukey2/ukey2/src/tests.rs
@@ -12,22 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#![allow(clippy::unwrap_used)]
+use std::collections::hash_set;
+
+use rand::rngs::StdRng;
+use rand::{Rng, SeedableRng};
+use sha2::Digest;
use crate::{
proto_adapter::{IntoAdapter as _, MessageType, ToWrappedMessage as _},
ukey2_handshake::HandshakeCipher,
- HandshakeImplementation, StateMachine, Ukey2ClientStage1, Ukey2ServerStage1,
+ HandshakeImplementation, NextProtocol, StateMachine, Ukey2ClientStage1, Ukey2ServerStage1,
};
use crypto_provider::elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey};
use crypto_provider::p256::P256;
use crypto_provider::x25519::X25519;
use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
-use rand::rngs::StdRng;
-use rand::{Rng, SeedableRng};
-use sha2::Digest;
-use std::collections::hash_set;
use ukey2_proto::protobuf::Message;
use ukey2_proto::ukey2_all_proto::ukey;
@@ -39,11 +39,12 @@ type P256EphemeralSecret =
<<CryptoProviderImpl as CryptoProvider>::P256 as EcdhProvider<P256>>::EphemeralSecret;
#[test]
+#[allow(clippy::unwrap_used)]
fn advance_from_init_to_finish_client_test() {
let mut rng = StdRng::from_entropy();
let client1 = Ukey2ClientStage1::<CryptoProviderImpl>::from(
&mut rng,
- "next protocol".to_string(),
+ vec![NextProtocol::Aes256CbcHmacSha256],
HandshakeImplementation::Spec,
);
@@ -68,6 +69,7 @@ fn advance_from_init_to_finish_client_test() {
}
#[test]
+#[allow(clippy::unwrap_used)]
fn advance_from_init_to_complete_server_x25519_test() {
let mut rng = StdRng::from_entropy();
let mut next_protocols = hash_set::HashSet::new();
@@ -121,6 +123,7 @@ fn advance_from_init_to_complete_server_x25519_test() {
}
#[test]
+#[allow(clippy::unwrap_used)]
fn advance_from_init_to_complete_server_p256_test() {
let mut rng = StdRng::from_entropy();
let mut next_protocols = hash_set::HashSet::new();
@@ -182,6 +185,7 @@ fn cipher_type_discriminant() {
}
#[test]
+#[allow(clippy::unwrap_used)]
fn convert_to_message_type() {
assert_eq!(
MessageType::ClientInit,
@@ -198,7 +202,28 @@ fn convert_to_message_type() {
}
#[test]
+#[allow(clippy::unwrap_used)]
fn convert_to_cipher_type() {
assert_eq!(HandshakeCipher::P256Sha512, 100.into_adapter().unwrap());
assert_eq!(HandshakeCipher::Curve25519Sha512, 200.into_adapter().unwrap());
}
+
+#[test]
+fn convert_next_protocols() {
+ assert_eq!(
+ (&"AES_256_CBC-HMAC_SHA256".to_string()).try_into(),
+ Ok(NextProtocol::Aes256CbcHmacSha256)
+ );
+ assert_eq!((&"AES_256_GCM_SIV".to_string()).try_into(), Ok(NextProtocol::Aes256GcmSiv));
+ assert_eq!(
+ TryInto::<NextProtocol>::try_into(&"Random protocol".to_string()),
+ Err(ukey::ukey2alert::AlertType::BAD_NEXT_PROTOCOL)
+ );
+}
+
+#[test]
+fn sort_next_protocols() {
+ let mut next_protocols = [NextProtocol::Aes256CbcHmacSha256, NextProtocol::Aes256GcmSiv];
+ next_protocols.sort();
+ assert_eq!(next_protocols, [NextProtocol::Aes256GcmSiv, NextProtocol::Aes256CbcHmacSha256])
+}
diff --git a/nearby/connections/ukey2/ukey2/src/ukey2_handshake.rs b/nearby/connections/ukey2/ukey2/src/ukey2_handshake.rs
index 0b2be0e..95d3b92 100644
--- a/nearby/connections/ukey2/ukey2/src/ukey2_handshake.rs
+++ b/nearby/connections/ukey2/ukey2/src/ukey2_handshake.rs
@@ -16,10 +16,12 @@
// TODO: remove this and convert all unwraps to expects
#![allow(clippy::unwrap_used)]
-pub(crate) use crate::proto_adapter::{
- CipherCommitment, ClientFinished, ClientInit, GenericPublicKey, HandshakeCipher,
- IntoAdapter as _, ServerInit, ToWrappedMessage as _,
+use std::{
+ collections::HashSet,
+ fmt::{self, Formatter},
+ marker::PhantomData,
};
+
use crypto_provider::elliptic_curve::EphemeralSecret;
use crypto_provider::p256::{P256EcdhProvider, P256PublicKey, P256};
use crypto_provider::x25519::X25519;
@@ -30,14 +32,15 @@ use crypto_provider::{
sha2::{Sha256, Sha512},
CryptoRng,
};
-use std::{
- collections::hash_set,
- fmt::{self, Formatter},
- marker::PhantomData,
-};
use ukey2_proto::protobuf::Message;
use ukey2_proto::ukey2_all_proto::{securemessage, ukey};
+use crate::proto_adapter::NextProtocol;
+pub(crate) use crate::proto_adapter::{
+ CipherCommitment, ClientFinished, ClientInit, GenericPublicKey, HandshakeCipher,
+ IntoAdapter as _, ServerInit, ToWrappedMessage as _,
+};
+
pub trait WireCompatibilityLayer {
fn encode_public_key<C: CryptoProvider>(
&self,
@@ -145,7 +148,7 @@ impl WireCompatibilityLayer for HandshakeImplementation {
}
pub struct Ukey2ServerStage1<C: CryptoProvider> {
- pub(crate) next_protocols: hash_set::HashSet<String>,
+ pub(crate) next_protocols: HashSet<NextProtocol>,
pub(crate) handshake_impl: HandshakeImplementation,
_marker: PhantomData<C>,
}
@@ -157,11 +160,12 @@ impl<C: CryptoProvider> fmt::Debug for Ukey2ServerStage1<C> {
}
impl<C: CryptoProvider> Ukey2ServerStage1<C> {
- pub fn from(
- next_protocols: hash_set::HashSet<String>,
- handshake_impl: HandshakeImplementation,
- ) -> Self {
- Self { next_protocols, handshake_impl, _marker: PhantomData }
+ pub fn from(next_protocols: HashSet<String>, handshake_impl: HandshakeImplementation) -> Self {
+ Self {
+ next_protocols: next_protocols.iter().filter_map(|p| p.try_into().ok()).collect(),
+ handshake_impl,
+ _marker: PhantomData,
+ }
}
pub(crate) fn handle_client_init<R: rand::Rng + rand::CryptoRng>(
@@ -174,10 +178,11 @@ impl<C: CryptoProvider> Ukey2ServerStage1<C> {
return Err(ClientInitError::BadVersion);
}
- let next_protocol = client_init.next_protocol();
- if !self.next_protocols.contains(next_protocol) {
+ let next_protocols = client_init.next_protocols();
+ let Some(selected_protocol) = next_protocols.intersection(&self.next_protocols).min()
+ else {
return Err(ClientInitError::BadNextProtocol);
- }
+ };
// nothing to check here about client_init.random -- already been validated as 32 bytes
@@ -207,7 +212,7 @@ impl<C: CryptoProvider> Ukey2ServerStage1<C> {
commitment.clone(),
secret,
self.handshake_impl,
- next_protocol.to_string(),
+ *selected_protocol,
))
}
HandshakeCipher::P256Sha512 => {
@@ -224,7 +229,7 @@ impl<C: CryptoProvider> Ukey2ServerStage1<C> {
commitment.clone(),
secret,
self.handshake_impl,
- next_protocol.to_string(),
+ *selected_protocol,
))
}
}
@@ -242,7 +247,7 @@ pub struct Ukey2ServerStage2<C: CryptoProvider> {
commitment: CipherCommitment,
key_pair: ServerKeyPair<C>,
pub(crate) handshake_impl: HandshakeImplementation,
- next_protocol: String,
+ next_protocol: NextProtocol,
_marker: PhantomData<C>,
}
@@ -262,7 +267,7 @@ impl<C: CryptoProvider> Ukey2ServerStage2<C> {
commitment: CipherCommitment,
key_pair: ServerKeyPair<C>,
handshake_impl: HandshakeImplementation,
- next_protocol: String,
+ next_protocol: NextProtocol,
) -> Self {
let random: [u8; 32] = rng.gen();
let mut server_init = ukey::Ukey2ServerInit::default();
@@ -278,6 +283,7 @@ impl<C: CryptoProvider> Ukey2ServerStage2<C> {
)
.unwrap(),
});
+ server_init.set_selected_next_protocol(next_protocol.to_string());
Self {
client_init_msg,
@@ -372,7 +378,7 @@ pub struct Ukey2ClientStage1<C: CryptoProvider> {
client_init_bytes: Vec<u8>,
commitment_ciphers: Vec<HandshakeCipher>,
handshake_impl: HandshakeImplementation,
- next_protocol: String,
+ next_protocols: Vec<NextProtocol>,
_marker: PhantomData<C>,
}
@@ -383,11 +389,15 @@ impl<C: CryptoProvider> fmt::Debug for Ukey2ClientStage1<C> {
}
impl<C: CryptoProvider> Ukey2ClientStage1<C> {
+ // Clippy: we assert that there must be at least one element in `next_protocols`, so indexing
+ // [0] is safe.
+ #[allow(clippy::indexing_slicing)]
pub fn from<R: rand::Rng + rand::SeedableRng + rand::CryptoRng>(
rng: &mut R,
- next_protocol: String,
+ next_protocols: Vec<NextProtocol>,
handshake_impl: HandshakeImplementation,
) -> Self {
+ assert!(!next_protocols.is_empty());
let random = rng.gen::<[u8; 32]>().to_vec();
// Curve25519 ClientFinished Message
let curve25519_secret =
@@ -408,10 +418,10 @@ impl<C: CryptoProvider> Ukey2ClientStage1<C> {
// P256 ClientFinished Message
let p256_secret = <C::P256 as EcdhProvider<P256>>::EphemeralSecret::generate_random(
- &mut<<<C::P256 as EcdhProvider<P256>>::EphemeralSecret as EphemeralSecret<
- P256,
- >>::Rng as CryptoRng>::new(),
- );
+ &mut <<<C::P256 as EcdhProvider<P256>>::EphemeralSecret as EphemeralSecret<
+ P256,
+ >>::Rng as CryptoRng>::new(),
+ );
let p256_client_finished_bytes = {
let client_finished = ukey::Ukey2ClientFinished {
public_key: Some(
@@ -446,7 +456,8 @@ impl<C: CryptoProvider> Ukey2ClientStage1<C> {
version: Some(1),
random: Some(random),
cipher_commitments: vec![curve25519_commitment, p256_commitment],
- next_protocol: Some(next_protocol.to_string()),
+ next_protocol: Some(next_protocols[0].to_string()),
+ next_protocols: next_protocols.iter().map(|x| x.to_string()).collect(),
..Default::default()
};
client_init.to_wrapped_msg().write_to_bytes().unwrap()
@@ -463,7 +474,7 @@ impl<C: CryptoProvider> Ukey2ClientStage1<C> {
HandshakeCipher::P256Sha512,
],
handshake_impl,
- next_protocol,
+ next_protocols,
_marker: PhantomData,
}
}
@@ -481,6 +492,11 @@ impl<C: CryptoProvider> Ukey2ClientStage1<C> {
return Err(ServerInitError::BadVersion);
}
+ if !self.next_protocols.contains(&server_init.selected_next_protocol()) {
+ return Err(ServerInitError::BadNextProtocol);
+ }
+ let next_protocol = server_init.selected_next_protocol();
+
// loop over all commitments every time for a semblance of constant time-ness
let server_cipher = self
.commitment_ciphers
@@ -537,7 +553,7 @@ impl<C: CryptoProvider> Ukey2ClientStage1<C> {
self.client_init_bytes,
server_init_bytes.to_vec(),
shared_secret_bytes,
- self.next_protocol,
+ next_protocol,
),
})
}
@@ -551,6 +567,8 @@ pub(crate) enum ServerInitError {
BadPublicKey,
/// The diffie-hellman key exchange failed to generate a shared secret
BadKeyExchange,
+ /// The server sent an invalid next protocol that is not available to the client.
+ BadNextProtocol,
}
#[derive(Clone)]
@@ -596,7 +614,7 @@ pub struct CompletedHandshake {
client_init_bytes: Vec<u8>,
server_init_bytes: Vec<u8>,
shared_secret: Vec<u8>,
- pub next_protocol: String,
+ pub next_protocol: NextProtocol,
}
impl CompletedHandshake {
@@ -604,7 +622,7 @@ impl CompletedHandshake {
client_init_bytes: Vec<u8>,
server_init_bytes: Vec<u8>,
shared_secret: Vec<u8>,
- next_protocol: String,
+ next_protocol: NextProtocol,
) -> Self {
Self { client_init_bytes, server_init_bytes, shared_secret, next_protocol }
}
diff --git a/nearby/connections/ukey2/ukey2/tests/tests.rs b/nearby/connections/ukey2/ukey2/tests/tests.rs
index 85b972c..d0acacf 100644
--- a/nearby/connections/ukey2/ukey2/tests/tests.rs
+++ b/nearby/connections/ukey2/ukey2/tests/tests.rs
@@ -21,9 +21,8 @@ use ukey2_rs::*;
#[test]
fn full_integration_state_machine() {
- let mut next_protocols = hash_set::HashSet::new();
- let next_protocol = "AES_256_CBC-HMAC_SHA256".to_string();
- let _ = next_protocols.insert(next_protocol.clone());
+ let next_protocol = NextProtocol::Aes256CbcHmacSha256;
+ let next_protocols = hash_set::HashSet::from([next_protocol.to_string()]);
let server1 = Ukey2ServerStage1::<CryptoProviderImpl>::from(
next_protocols,
HandshakeImplementation::Spec,
@@ -31,7 +30,7 @@ fn full_integration_state_machine() {
let mut rng = StdRng::from_entropy();
let client1 = Ukey2ClientStage1::<CryptoProviderImpl>::from(
&mut rng,
- next_protocol,
+ vec![next_protocol],
HandshakeImplementation::Spec,
);
let server2 = server1.advance_state(&mut rng, client1.client_init_msg()).unwrap();
@@ -58,9 +57,8 @@ fn full_integration_state_machine() {
#[test]
fn full_integration_state_machine_public_key_in_protobuf() {
- let mut next_protocols = hash_set::HashSet::new();
- let next_protocol = "AES_256_CBC-HMAC_SHA256".to_string();
- let _ = next_protocols.insert(next_protocol.clone());
+ let next_protocol = NextProtocol::Aes256CbcHmacSha256;
+ let next_protocols = hash_set::HashSet::from([next_protocol.to_string()]);
let server1 = Ukey2ServerStage1::<CryptoProviderImpl>::from(
next_protocols,
HandshakeImplementation::PublicKeyInProtobuf,
@@ -68,7 +66,7 @@ fn full_integration_state_machine_public_key_in_protobuf() {
let mut rng = StdRng::from_entropy();
let client1 = Ukey2ClientStage1::<CryptoProviderImpl>::from(
&mut rng,
- next_protocol,
+ vec![next_protocol],
HandshakeImplementation::PublicKeyInProtobuf,
);
let server2 = server1.advance_state(&mut rng, client1.client_init_msg()).unwrap();
@@ -92,3 +90,79 @@ fn full_integration_state_machine_public_key_in_protobuf() {
.derive_array::<32>()
);
}
+
+#[test]
+fn full_integration_state_machine_multiple_next_protocols_sort() {
+ let raw_next_protocols = [NextProtocol::Aes256CbcHmacSha256, NextProtocol::Aes256GcmSiv];
+ let next_protocols = hash_set::HashSet::from(raw_next_protocols.map(|p| p.to_string()));
+ let server1 = Ukey2ServerStage1::<CryptoProviderImpl>::from(
+ next_protocols,
+ HandshakeImplementation::Spec,
+ );
+ let mut rng = StdRng::from_entropy();
+ let client1 = Ukey2ClientStage1::<CryptoProviderImpl>::from(
+ &mut rng,
+ raw_next_protocols.to_vec(),
+ HandshakeImplementation::Spec,
+ );
+ let server2 = server1.advance_state(&mut rng, client1.client_init_msg()).unwrap();
+
+ let client2 = client1.advance_state(&mut rng, server2.server_init_msg()).unwrap();
+
+ let server3 = server2.advance_state(&mut rng, client2.client_finished_msg()).unwrap();
+
+ assert_eq!(
+ server3.completed_handshake().auth_string::<CryptoProviderImpl>().derive_array::<32>(),
+ client2.completed_handshake().auth_string::<CryptoProviderImpl>().derive_array::<32>()
+ );
+ assert_eq!(
+ server3
+ .completed_handshake()
+ .next_protocol_secret::<CryptoProviderImpl>()
+ .derive_array::<32>(),
+ client2
+ .completed_handshake()
+ .next_protocol_secret::<CryptoProviderImpl>()
+ .derive_array::<32>()
+ );
+ assert_eq!(server3.completed_handshake().next_protocol, NextProtocol::Aes256GcmSiv);
+ assert_eq!(client2.completed_handshake().next_protocol, NextProtocol::Aes256GcmSiv);
+}
+
+#[test]
+fn full_integration_state_machine_multiple_next_protocols_client() {
+ let raw_next_protocols = [NextProtocol::Aes256CbcHmacSha256, NextProtocol::Aes256GcmSiv];
+ let next_protocols = hash_set::HashSet::from(raw_next_protocols.map(|p| p.to_string()));
+ let server1 = Ukey2ServerStage1::<CryptoProviderImpl>::from(
+ next_protocols,
+ HandshakeImplementation::Spec,
+ );
+ let mut rng = StdRng::from_entropy();
+ let client1 = Ukey2ClientStage1::<CryptoProviderImpl>::from(
+ &mut rng,
+ [NextProtocol::Aes256CbcHmacSha256].to_vec(),
+ HandshakeImplementation::Spec,
+ );
+ let server2 = server1.advance_state(&mut rng, client1.client_init_msg()).unwrap();
+
+ let client2 = client1.advance_state(&mut rng, server2.server_init_msg()).unwrap();
+
+ let server3 = server2.advance_state(&mut rng, client2.client_finished_msg()).unwrap();
+
+ assert_eq!(
+ server3.completed_handshake().auth_string::<CryptoProviderImpl>().derive_array::<32>(),
+ client2.completed_handshake().auth_string::<CryptoProviderImpl>().derive_array::<32>()
+ );
+ assert_eq!(
+ server3
+ .completed_handshake()
+ .next_protocol_secret::<CryptoProviderImpl>()
+ .derive_array::<32>(),
+ client2
+ .completed_handshake()
+ .next_protocol_secret::<CryptoProviderImpl>()
+ .derive_array::<32>()
+ );
+ assert_eq!(server3.completed_handshake().next_protocol, NextProtocol::Aes256CbcHmacSha256);
+ assert_eq!(client2.completed_handshake().next_protocol, NextProtocol::Aes256CbcHmacSha256);
+}
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml b/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
index 182ecf2..1034359 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
@@ -6,7 +6,6 @@ publish.workspace = true
[dependencies]
ukey2_connections = { path = "../ukey2_connections" }
-ukey2_rs = { path = "../ukey2" }
cfg-if.workspace = true
crypto_provider_default.workspace = true
lock_adapter = {workspace = true, features = ["spin"]}
@@ -19,7 +18,6 @@ rand_chacha.workspace = true
[features]
default = ["rustcrypto", "std"]
std = ["lock_adapter/std"]
-openssl = ["crypto_provider_default/openssl", "std"]
boringssl = ["crypto_provider_default/boringssl", "std"]
rustcrypto = ["crypto_provider_default/rustcrypto"]
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
index e1f7e1e..e19aa68 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
@@ -64,13 +64,20 @@ void rust_dealloc_ffi_byte_array(RustFFIByteArray array);
// Common handshake methods
bool is_handshake_complete(Ukey2HandshakeContextHandle handle);
RustFFIByteArray get_next_handshake_message(Ukey2HandshakeContextHandle handle);
-CMessageParseResult parse_handshake_message(Ukey2HandshakeContextHandle handle, CFFIByteArray message);
-Ukey2ConnectionContextHandle to_connection_context(Ukey2HandshakeContextHandle handle);
-RustFFIByteArray get_verification_string(Ukey2HandshakeContextHandle handle, size_t output_length);
+CMessageParseResult parse_handshake_message(Ukey2HandshakeContextHandle handle,
+ CFFIByteArray message);
+Ukey2ConnectionContextHandle to_connection_context(
+ Ukey2HandshakeContextHandle handle);
+RustFFIByteArray get_verification_string(Ukey2HandshakeContextHandle handle,
+ size_t output_length);
// D2DConnectionContextV1 methods
-RustFFIByteArray encode_message_to_peer(Ukey2ConnectionContextHandle handle, CFFIByteArray message, CFFIByteArray associated_data);
-RustFFIByteArray decode_message_from_peer(Ukey2ConnectionContextHandle handle, CFFIByteArray message, CFFIByteArray associated_data);
+RustFFIByteArray encode_message_to_peer(Ukey2ConnectionContextHandle handle,
+ CFFIByteArray message,
+ CFFIByteArray associated_data);
+RustFFIByteArray decode_message_from_peer(Ukey2ConnectionContextHandle handle,
+ CFFIByteArray message,
+ CFFIByteArray associated_data);
RustFFIByteArray get_session_unique(Ukey2ConnectionContextHandle handle);
int get_sequence_number_for_encoding(Ukey2ConnectionContextHandle handle);
int get_sequence_number_for_decoding(Ukey2ConnectionContextHandle handle);
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
index 654e293..457286d 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
@@ -11,80 +11,88 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-
-#include "ukey2_bindings.h"
+#pragma once
#include <string>
+#include "ukey2_bindings.h"
+
+namespace rust {
struct D2DRestoreConnectionContextV1Result;
-// The Connection object that can handle encryption/decryption of messages over the wire.
-// This object should only be constructed via FromSavedSession() or Ukey2Handshake::ToConnectionContext().
+// The Connection object that can handle encryption/decryption of messages over
+// the wire. This object should only be constructed via FromSavedSession() or
+// Ukey2Handshake::ToConnectionContext().
class D2DConnectionContextV1 {
- public:
- // Encodes a message to the connection peer using the derived key from the handshake
- // If associated_data is not empty, it will be used to compute the signature and the same
- // associated_data string must be passed into DecodeMessageFromPeer() in order for the
- // message to be validated.
- std::string EncodeMessageToPeer(std::string message, std::string associated_data);
- // Decodes a message from the connection peer. If associated_data was passed into
- // EncodeMessageToPeer(), that same associated_data must be passed here in order for
- // this function to succeed.
- std::string DecodeMessageFromPeer(std::string message, std::string associated_data);
- // Gets a session-specific unique identifier.
- std::string GetSessionUnique();
- // Gets the encoding sequence number.
- int GetSequenceNumberForEncoding();
- // Gets the decoding sequence number.
- int GetSequenceNumberForDecoding();
- // Returns byte data suitable for use with FromSavedSession().
- std::string SaveSession();
- // Recreates the state of a previous D2DConnectionContextV1 using the data from SaveSession().
- // This function will return an error if the byte pattern is not as expected.
- // Expected format:
- // -------------------------------------------------------------------------------------------
- // | 1 byte | 4 bytes | 4 bytes | 32 bytes | 32 bytes |
- // -------------------------------------------------------------------------------------------
- // Protocol version | Encode sequence number | Decode sequence number | Encode key | Decode key
- // (always 1)
- static D2DRestoreConnectionContextV1Result FromSavedSession(std::string data);
+ public:
+ // Encodes a message to the connection peer using the derived key from the
+ // handshake If associated_data is not empty, it will be used to compute the
+ // signature and the same associated_data string must be passed into
+ // DecodeMessageFromPeer() in order for the message to be validated.
+ std::string EncodeMessageToPeer(std::string message,
+ std::string associated_data);
+ // Decodes a message from the connection peer. If associated_data was passed
+ // into EncodeMessageToPeer(), that same associated_data must be passed here
+ // in order for this function to succeed.
+ std::string DecodeMessageFromPeer(std::string message,
+ std::string associated_data);
+ // Gets a session-specific unique identifier.
+ std::string GetSessionUnique();
+ // Gets the encoding sequence number.
+ int GetSequenceNumberForEncoding();
+ // Gets the decoding sequence number.
+ int GetSequenceNumberForDecoding();
+ // Returns byte data suitable for use with FromSavedSession().
+ std::string SaveSession();
+ // Recreates the state of a previous D2DConnectionContextV1 using the data
+ // from SaveSession(). This function will return an error if the byte pattern
+ // is not as expected. Expected format:
+ // ---------------------------------------------------------------------------
+ // | 1 byte | 4 bytes | 4 bytes | 32 bytes | 32 bytes |
+ // ---------------------------------------------------------------------------
+ // Version | Encode sequence # | Decode sequence # | Encode key | Decode key
+ static D2DRestoreConnectionContextV1Result FromSavedSession(std::string data);
- private:
- friend class Ukey2Handshake;
- D2DConnectionContextV1(Ukey2ConnectionContextHandle handle) : handle_(handle) {}
- const Ukey2ConnectionContextHandle handle_;
+ private:
+ friend class Ukey2Handshake;
+ D2DConnectionContextV1(Ukey2ConnectionContextHandle handle)
+ : handle_(handle) {}
+ const Ukey2ConnectionContextHandle handle_;
};
struct D2DRestoreConnectionContextV1Result {
- D2DConnectionContextV1 handle;
- CD2DRestoreConnectionContextV1Status status;
+ D2DConnectionContextV1 handle;
+ CD2DRestoreConnectionContextV1Status status;
};
struct ParseResult {
- bool success;
- std::string alert_to_send;
+ bool success;
+ std::string alert_to_send;
};
-// Base handshake. This should be used to start a secure channel represented by a D2DConnectionContextV1.
+// Base handshake. This should be used to start a secure channel represented by
+// a D2DConnectionContextV1.
class Ukey2Handshake {
- public:
- // Creates a Ukey2Handshake instance for the responder.
- static Ukey2Handshake ForResponder();
- // Creates a Ukey2Handshake instance for the initiator.
- static Ukey2Handshake ForInitiator();
- // Returns true if the handshake is complete, false otherwise.
- bool IsHandshakeComplete();
- // Returns raw byte data with the message to send over the wire.
- std::string GetNextHandshakeMessage();
- // Parses the raw handshake message received over the wire.
- ParseResult ParseHandshakeMessage(std::string message);
- // Returns the authentication string of length output_length to be confirmed on both devices.
- std::string GetVerificationString(size_t output_length);
- // Turns this Ukey2Handshake instance into a D2DConnectionContextV1. This method once called,
- // renders the Ukey2Handshake object unusable.
- D2DConnectionContextV1 ToConnectionContext();
+ public:
+ // Creates a Ukey2Handshake instance for the responder.
+ static Ukey2Handshake ForResponder();
+ // Creates a Ukey2Handshake instance for the initiator.
+ static Ukey2Handshake ForInitiator();
+ // Returns true if the handshake is complete, false otherwise.
+ bool IsHandshakeComplete();
+ // Returns raw byte data with the message to send over the wire.
+ std::string GetNextHandshakeMessage();
+ // Parses the raw handshake message received over the wire.
+ ParseResult ParseHandshakeMessage(std::string message);
+ // Returns the authentication string of length output_length to be confirmed
+ // on both devices.
+ std::string GetVerificationString(size_t output_length);
+ // Turns this Ukey2Handshake instance into a D2DConnectionContextV1. This
+ // method once called, renders the Ukey2Handshake object unusable.
+ D2DConnectionContextV1 ToConnectionContext();
- private:
- Ukey2Handshake(Ukey2HandshakeContextHandle handle) : handle_(handle) {}
- const Ukey2HandshakeContextHandle handle_;
+ private:
+ Ukey2Handshake(Ukey2HandshakeContextHandle handle) : handle_(handle) {}
+ const Ukey2HandshakeContextHandle handle_;
};
+} // namespace rust
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
index 6b03f1c..354112c 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
@@ -12,139 +12,143 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "ukey2_bindings.h"
-#include "ukey2_ffi.h"
-
#include <cassert>
#include <cstring>
#include <iostream>
#include <string>
+#include "ukey2_bindings.h"
+#include "ukey2_ffi.h"
+
CFFIByteArray nullByteArray() {
- return {
- .handle = nullptr,
- .len = 0,
- };
+ return {
+ .handle = nullptr,
+ .len = 0,
+ };
}
// Implementation of functions
-Ukey2Handshake Ukey2Handshake::ForInitiator() {
- return Ukey2Handshake(initiator_new());
+rust::Ukey2Handshake rust::Ukey2Handshake::ForInitiator() {
+ return Ukey2Handshake(initiator_new());
}
-Ukey2Handshake Ukey2Handshake::ForResponder() {
- return Ukey2Handshake(responder_new());
+rust::Ukey2Handshake rust::Ukey2Handshake::ForResponder() {
+ return Ukey2Handshake(responder_new());
}
-bool Ukey2Handshake::IsHandshakeComplete() {
- return is_handshake_complete(handle_);
+bool rust::Ukey2Handshake::IsHandshakeComplete() {
+ return is_handshake_complete(handle_);
}
-std::string Ukey2Handshake::GetNextHandshakeMessage() {
- RustFFIByteArray array = get_next_handshake_message(handle_);
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::Ukey2Handshake::GetNextHandshakeMessage() {
+ RustFFIByteArray array = get_next_handshake_message(handle_);
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-ParseResult Ukey2Handshake::ParseHandshakeMessage(std::string message) {
- CFFIByteArray messageRaw{
- .handle = (uint8_t*)message.c_str(),
- .len = message.length(),
- };
- CMessageParseResult result = parse_handshake_message(handle_, messageRaw);
- std::string alert;
- if (!result.success) {
- std::cout << "parse failed" << std::endl;
- RustFFIByteArray array = result.alert_to_send;
- if (array.handle != nullptr) {
- alert = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- }
+rust::ParseResult rust::Ukey2Handshake::ParseHandshakeMessage(
+ std::string message) {
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ CMessageParseResult result = parse_handshake_message(handle_, messageRaw);
+ std::string alert;
+ if (!result.success) {
+ std::cout << "parse failed" << std::endl;
+ RustFFIByteArray array = result.alert_to_send;
+ if (array.handle != nullptr) {
+ alert = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
}
- return ParseResult {
- .success = result.success,
- .alert_to_send = alert,
- };
+ }
+ return ParseResult{
+ .success = result.success,
+ .alert_to_send = alert,
+ };
}
-std::string Ukey2Handshake::GetVerificationString(size_t output_length) {
- RustFFIByteArray array = get_verification_string(handle_, output_length);
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::Ukey2Handshake::GetVerificationString(size_t output_length) {
+ RustFFIByteArray array = get_verification_string(handle_, output_length);
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-D2DConnectionContextV1 Ukey2Handshake::ToConnectionContext() {
- assert(IsHandshakeComplete());
- return D2DConnectionContextV1(to_connection_context(handle_));
+rust::D2DConnectionContextV1 rust::Ukey2Handshake::ToConnectionContext() {
+ assert(IsHandshakeComplete());
+ return D2DConnectionContextV1(to_connection_context(handle_));
}
-std::string D2DConnectionContextV1::DecodeMessageFromPeer(std::string message, std::string associated_data) {
- CFFIByteArray messageRaw{
- .handle = (uint8_t*)message.c_str(),
- .len = message.length(),
- };
- CFFIByteArray associatedDataRaw{
- .handle = (uint8_t*)associated_data.c_str(),
- .len = associated_data.length(),
- };
- RustFFIByteArray array =
- decode_message_from_peer(handle_, messageRaw, associatedDataRaw);
- if (array.handle == nullptr) {
- return "";
- }
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::D2DConnectionContextV1::DecodeMessageFromPeer(
+ std::string message, std::string associated_data) {
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ CFFIByteArray associatedDataRaw{
+ .handle = (uint8_t*)associated_data.c_str(),
+ .len = associated_data.length(),
+ };
+ RustFFIByteArray array =
+ decode_message_from_peer(handle_, messageRaw, associatedDataRaw);
+ if (array.handle == nullptr) {
+ return "";
+ }
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-std::string D2DConnectionContextV1::EncodeMessageToPeer(std::string message, std::string associated_data) {
- CFFIByteArray messageRaw{
- .handle = (uint8_t*)message.c_str(),
- .len = message.length(),
- };
- CFFIByteArray associatedDataRaw{
- .handle = (uint8_t*)associated_data.c_str(),
- .len = associated_data.length(),
- };
- RustFFIByteArray array =
- encode_message_to_peer(handle_, messageRaw, associatedDataRaw);
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::D2DConnectionContextV1::EncodeMessageToPeer(
+ std::string message, std::string associated_data) {
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ CFFIByteArray associatedDataRaw{
+ .handle = (uint8_t*)associated_data.c_str(),
+ .len = associated_data.length(),
+ };
+ RustFFIByteArray array =
+ encode_message_to_peer(handle_, messageRaw, associatedDataRaw);
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-std::string D2DConnectionContextV1::GetSessionUnique() {
- RustFFIByteArray array = get_session_unique(handle_);
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::D2DConnectionContextV1::GetSessionUnique() {
+ RustFFIByteArray array = get_session_unique(handle_);
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-int D2DConnectionContextV1::GetSequenceNumberForEncoding() {
- return get_sequence_number_for_encoding(handle_);
+int rust::D2DConnectionContextV1::GetSequenceNumberForEncoding() {
+ return get_sequence_number_for_encoding(handle_);
}
-int D2DConnectionContextV1::GetSequenceNumberForDecoding() {
- return get_sequence_number_for_decoding(handle_);
+int rust::D2DConnectionContextV1::GetSequenceNumberForDecoding() {
+ return get_sequence_number_for_decoding(handle_);
}
-std::string D2DConnectionContextV1::SaveSession() {
- RustFFIByteArray array = save_session(handle_);
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+std::string rust::D2DConnectionContextV1::SaveSession() {
+ RustFFIByteArray array = save_session(handle_);
+ std::string ret = std::string((const char*)array.handle, array.len);
+ rust_dealloc_ffi_byte_array(array);
+ return ret;
}
-D2DRestoreConnectionContextV1Result D2DConnectionContextV1::FromSavedSession(std::string data) {
- CFFIByteArray arr{
- .handle = (uint8_t*)data.c_str(),
- .len = data.length(),
- };
- auto result = from_saved_session(arr);
- return {
- D2DConnectionContextV1(result.handle),
- result.status,
- };
+rust::D2DRestoreConnectionContextV1Result
+rust::D2DConnectionContextV1::FromSavedSession(std::string data) {
+ CFFIByteArray arr{
+ .handle = (uint8_t*)data.c_str(),
+ .len = data.length(),
+ };
+ auto result = from_saved_session(arr);
+ return {
+ D2DConnectionContextV1(result.handle),
+ result.status,
+ };
}
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc
index 962ada8..1a23278 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc
@@ -12,15 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "ukey2_ffi.h"
-
#include <string>
#include "gtest/gtest.h"
+#include "ukey2_ffi.h"
+namespace rust {
namespace {
-void RunHandshake(Ukey2Handshake initiator_handle, Ukey2Handshake responder_handle) {
+void RunHandshake(Ukey2Handshake initiator_handle,
+ Ukey2Handshake responder_handle) {
ParseResult parse_result = responder_handle.ParseHandshakeMessage(
initiator_handle.GetNextHandshakeMessage());
ASSERT_TRUE(parse_result.success);
@@ -87,3 +88,4 @@ TEST(Ukey2RustTest, TestSaveRestoreSession) {
}
} // namespace
+} // namespace rust
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs b/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
index e5cc548..77d9b59 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
+++ b/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
@@ -25,11 +25,11 @@ use rand_chacha::ChaCha20Rng;
#[cfg(not(feature = "std"))]
use lock_adapter::spin::Mutex;
#[cfg(feature = "std")]
-use lock_adapter::std::Mutex;
+use lock_adapter::stdlib::Mutex;
use ukey2_connections::{
D2DConnectionContextV1, D2DHandshakeContext, HandleMessageError, HandshakeImplementation,
- InitiatorD2DHandshakeContext, ServerD2DHandshakeContext,
+ InitiatorD2DHandshakeContext, NextProtocol, ServerD2DHandshakeContext,
};
#[repr(C)]
@@ -188,6 +188,7 @@ pub extern "C" fn to_connection_context(handle: u64) -> u64 {
pub extern "C" fn responder_new() -> u64 {
let ctx = Box::new(ServerD2DHandshakeContext::<CryptoProvider>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ &[NextProtocol::Aes256CbcHmacSha256],
));
insert_gen_handle(ctx)
}
@@ -200,6 +201,7 @@ pub extern "C" fn responder_new() -> u64 {
pub extern "C" fn initiator_new() -> u64 {
let ctx = Box::new(InitiatorD2DHandshakeContext::<CryptoProvider>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ vec![NextProtocol::Aes256CbcHmacSha256],
));
insert_gen_handle(ctx)
}
diff --git a/nearby/connections/ukey2/ukey2_connections/Cargo.toml b/nearby/connections/ukey2/ukey2_connections/Cargo.toml
index b1c34a1..5c9622b 100644
--- a/nearby/connections/ukey2/ukey2_connections/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_connections/Cargo.toml
@@ -11,7 +11,6 @@ workspace = true
default = []
test_boringssl = ["crypto_provider_default/boringssl"]
test_rustcrypto = ["crypto_provider_default/rustcrypto"]
-test_openssl = ["crypto_provider_default/openssl"]
[dependencies]
ukey2_rs = { path = "../ukey2" }
diff --git a/nearby/connections/ukey2/ukey2_connections/benches/ukey2_benches.rs b/nearby/connections/ukey2/ukey2_connections/benches/ukey2_benches.rs
index f816165..8c55d23 100644
--- a/nearby/connections/ukey2/ukey2_connections/benches/ukey2_benches.rs
+++ b/nearby/connections/ukey2/ukey2_connections/benches/ukey2_benches.rs
@@ -23,10 +23,11 @@ use ukey2_connections::{
D2DConnectionContextV1, D2DHandshakeContext, InitiatorD2DHandshakeContext,
ServerD2DHandshakeContext,
};
-use ukey2_rs::HandshakeImplementation;
+use ukey2_rs::{HandshakeImplementation, NextProtocol};
fn run_handshake_with_rng<C, R>(
mut rng: R,
+ next_protocols: Vec<NextProtocol>,
) -> (D2DConnectionContextV1<R>, D2DConnectionContextV1<R>)
where
C: CryptoProvider,
@@ -35,10 +36,12 @@ where
let mut initiator_ctx = InitiatorD2DHandshakeContext::<C, R>::new_impl(
HandshakeImplementation::Spec,
R::from_rng(&mut rng).unwrap(),
+ next_protocols.clone(),
);
let mut server_ctx = ServerD2DHandshakeContext::<C, R>::new_impl(
HandshakeImplementation::Spec,
R::from_rng(&mut rng).unwrap(),
+ &next_protocols,
);
server_ctx
.handle_handshake_message(
@@ -60,27 +63,61 @@ where
(initiator_ctx.to_connection_context().unwrap(), server_ctx.to_connection_context().unwrap())
}
-fn criterion_benchmark(c: &mut Criterion) {
+fn cbc_criterion_benchmark(c: &mut Criterion) {
let kib = 1024;
let mut group = c.benchmark_group("throughput");
let mut plaintext = Vec::new();
- let (mut initiator_ctx, mut server_ctx) =
- run_handshake_with_rng::<CryptoProviderImpl, _>(rand::rngs::StdRng::from_entropy());
+ let (mut initiator_ctx, mut server_ctx) = run_handshake_with_rng::<CryptoProviderImpl, _>(
+ rand::rngs::StdRng::from_entropy(),
+ vec![NextProtocol::Aes256CbcHmacSha256],
+ );
+ for len in [10 * kib, 1024 * kib] {
+ let _ = group.throughput(Throughput::Bytes(len as u64));
+ plaintext.resize(len, 0);
+ rand::thread_rng().fill(&mut plaintext[..]);
+ let _ = group.bench_function(
+ format!("AES-CBC-256_HMAC-SHA256 UKEY2 encrypt/decrypt {}KiB", len / kib),
+ |b| {
+ b.iter(|| {
+ let msg = initiator_ctx
+ .encode_message_to_peer::<CryptoProviderImpl, &[u8]>(&plaintext, None);
+ black_box(
+ server_ctx
+ .decode_message_from_peer::<CryptoProviderImpl, &[u8]>(&msg, None),
+ )
+ })
+ },
+ );
+ }
+}
+
+fn gcm_criterion_benchmark(c: &mut Criterion) {
+ let kib = 1024;
+ let mut group = c.benchmark_group("throughput");
+ let mut plaintext = Vec::new();
+ let (mut initiator_ctx, mut server_ctx) = run_handshake_with_rng::<CryptoProviderImpl, _>(
+ rand::rngs::StdRng::from_entropy(),
+ vec![NextProtocol::Aes256GcmSiv],
+ );
for len in [10 * kib, 1024 * kib] {
let _ = group.throughput(Throughput::Bytes(len as u64));
plaintext.resize(len, 0);
rand::thread_rng().fill(&mut plaintext[..]);
- let _ = group.bench_function(format!("UKEY2 encrypt/decrypt {}KiB", len / kib), |b| {
- b.iter(|| {
- let msg = initiator_ctx
- .encode_message_to_peer::<CryptoProviderImpl, &[u8]>(&plaintext, None);
- black_box(
- server_ctx.decode_message_from_peer::<CryptoProviderImpl, &[u8]>(&msg, None),
- )
- })
- });
+ let _ = group.bench_function(
+ format!("AES-GCM-SIV UKEY2 encrypt/decrypt {}KiB", len / kib),
+ |b| {
+ b.iter(|| {
+ let msg = initiator_ctx
+ .encode_message_to_peer::<CryptoProviderImpl, &[u8]>(&plaintext, None);
+ black_box(
+ server_ctx
+ .decode_message_from_peer::<CryptoProviderImpl, &[u8]>(&msg, None),
+ )
+ })
+ },
+ );
}
}
-criterion_group!(benches, criterion_benchmark);
+criterion_group!(benches, cbc_criterion_benchmark, gcm_criterion_benchmark);
criterion_main!(benches);
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
index 167e0de..f5f4fac 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
@@ -55,9 +55,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.2"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
@@ -70,21 +70,21 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anyhow"
-version = "1.0.72"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
+checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "arbitrary"
-version = "1.3.0"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
@@ -103,9 +103,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "bitflags"
-version = "1.3.2"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bitflags"
@@ -133,9 +133,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.13.0"
+version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytes"
@@ -160,11 +160,12 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
+ "libc",
]
[[package]]
@@ -175,9 +176,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "ciborium"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
+checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
@@ -186,15 +187,15 @@ dependencies = [
[[package]]
name = "ciborium-io"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
@@ -212,18 +213,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.4.14"
+version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
+checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.4.14"
+version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
+checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
dependencies = [
"anstyle",
"clap_lex",
@@ -237,15 +238,15 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "const-oid"
-version = "0.9.4"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
@@ -287,53 +288,41 @@ dependencies = [
]
[[package]]
-name = "crossbeam-channel"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
name = "crossbeam-deque"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
- "cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.9.15"
+version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
- "autocfg",
- "cfg-if",
"crossbeam-utils",
- "memoffset",
- "scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
-dependencies = [
- "cfg-if",
-]
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-bigint"
-version = "0.5.2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array",
"rand_core",
@@ -395,9 +384,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "4.0.0"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -411,9 +400,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
@@ -422,9 +411,9 @@ dependencies = [
[[package]]
name = "der"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
dependencies = [
"const-oid",
"zeroize",
@@ -432,9 +421,9 @@ dependencies = [
[[package]]
name = "derive_arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
@@ -454,18 +443,18 @@ dependencies = [
[[package]]
name = "ed25519"
-version = "2.2.1"
+version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"signature",
]
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -476,15 +465,15 @@ dependencies = [
[[package]]
name = "either"
-version = "1.8.1"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "elliptic-curve"
-version = "0.13.5"
+version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -501,33 +490,19 @@ dependencies = [
[[package]]
name = "errno"
-version = "0.3.1"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
- "errno-dragonfly",
"libc",
"windows-sys 0.48.0",
]
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
name = "fastrand"
-version = "1.9.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
-dependencies = [
- "instant",
-]
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "ff"
@@ -541,9 +516,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
-version = "0.1.20"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "generic-array"
@@ -558,9 +533,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -590,9 +565,13 @@ dependencies = [
[[package]]
name = "half"
-version = "1.8.2"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
+dependencies = [
+ "cfg-if",
+ "crunchy",
+]
[[package]]
name = "hashbrown"
@@ -602,15 +581,15 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
-version = "0.3.2"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3"
[[package]]
name = "hkdf"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
@@ -625,6 +604,15 @@ dependencies = [
]
[[package]]
+name = "home"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -645,34 +633,14 @@ dependencies = [
]
[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
-dependencies = [
- "hermit-abi",
- "libc",
- "windows-sys 0.48.0",
-]
-
-[[package]]
name = "is-terminal"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
dependencies = [
"hermit-abi",
- "rustix 0.38.13",
- "windows-sys 0.52.0",
+ "rustix",
+ "windows-sys",
]
[[package]]
@@ -686,39 +654,39 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.9"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "jobserver"
-version = "0.1.26"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
-version = "0.3.64"
+version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
+checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
@@ -727,15 +695,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "log"
@@ -745,18 +707,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "memoffset"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
-dependencies = [
- "autocfg",
-]
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "minimal-lexical"
@@ -805,20 +758,10 @@ dependencies = [
]
[[package]]
-name = "num_cpus"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
@@ -844,9 +787,9 @@ dependencies = [
[[package]]
name = "platforms"
-version = "3.0.2"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
+checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
[[package]]
name = "plotters"
@@ -896,18 +839,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "primeorder"
-version = "0.13.2"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -965,9 +908,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -1004,9 +947,9 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.7.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
dependencies = [
"either",
"rayon-core",
@@ -1014,30 +957,19 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.11.0"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "num_cpus",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
-dependencies = [
- "bitflags 1.3.2",
]
[[package]]
name = "regex"
-version = "1.9.1"
+version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
@@ -1047,9 +979,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.3.3"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
@@ -1058,9 +990,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.7.4"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc_version"
@@ -1073,13 +1005,12 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.37.23"
+version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
"bitflags 1.3.2",
"errno",
- "io-lifetimes",
"libc",
"linux-raw-sys 0.3.8",
"windows-sys 0.48.0",
@@ -1100,9 +1031,9 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.15"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "same-file"
@@ -1114,12 +1045,6 @@ dependencies = [
]
[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
name = "sec1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1134,24 +1059,24 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.18"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
-version = "1.0.171"
+version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.171"
+version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
@@ -1160,9 +1085,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.103"
+version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
@@ -1182,9 +1107,9 @@ dependencies = [
[[package]]
name = "signature"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
[[package]]
name = "subtle"
@@ -1194,9 +1119,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "2.0.26"
+version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@@ -1205,32 +1130,30 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.6.0"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
+checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
dependencies = [
- "autocfg",
"cfg-if",
"fastrand",
- "redox_syscall",
- "rustix 0.37.23",
- "windows-sys 0.48.0",
+ "rustix",
+ "windows-sys",
]
[[package]]
name = "thiserror"
-version = "1.0.43"
+version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
+checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.43"
+version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
+checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [
"proc-macro2",
"quote",
@@ -1255,9 +1178,9 @@ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ukey2_connections"
@@ -1305,9 +1228,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "universal-hash"
@@ -1327,9 +1250,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
-version = "2.3.3"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
@@ -1343,9 +1266,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.87"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1353,9 +1276,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.87"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
dependencies = [
"bumpalo",
"log",
@@ -1368,9 +1291,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.87"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1378,9 +1301,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.87"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
@@ -1391,15 +1314,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.87"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
+checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "web-sys"
-version = "0.3.64"
+version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
+checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1407,13 +1330,14 @@ dependencies = [
[[package]]
name = "which"
-version = "4.4.0"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
- "libc",
+ "home",
"once_cell",
+ "rustix",
]
[[package]]
@@ -1434,9 +1358,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
@@ -1449,9 +1373,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.48.1",
]
@@ -1467,9 +1391,9 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.48.1"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
@@ -1497,9 +1421,9 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_gnullvm"
@@ -1509,9 +1433,9 @@ checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_aarch64_msvc"
@@ -1521,9 +1445,9 @@ checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_gnu"
@@ -1533,9 +1457,9 @@ checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_i686_msvc"
@@ -1545,9 +1469,9 @@ checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnu"
@@ -1557,9 +1481,9 @@ checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -1569,9 +1493,9 @@ checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "windows_x86_64_msvc"
@@ -1581,9 +1505,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
@@ -1591,6 +1515,6 @@ dependencies = [
[[package]]
name = "zeroize"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.toml b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.toml
index b8a1295..2c94ebb 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.toml
@@ -1,43 +1,34 @@
[package]
name = "ukey2_connections-fuzz"
-version = "0.0.0"
-publish = false
-edition = "2021"
+version.workspace = true
+publish.workspace = true
+edition.workspace = true
[package.metadata]
cargo-fuzz = true
[dependencies]
-libfuzzer-sys = "0.4"
-crypto_provider_rustcrypto = { path = "../../../../crypto/crypto_provider_rustcrypto" }
-ukey2_rs = { path = "../../ukey2" }
-rand_chacha = "0.3.1"
-arbitrary = { version = "1.2.3", features = ["derive"] }
+arbitrary = { workspace = true, features = ["derive"] }
+crypto_provider_rustcrypto.workspace = true
+derive_fuzztest.workspace = true
+rand_chacha.workspace = true
+ukey2_connections.workspace = true
+ukey2_rs.workspace = true
-[dependencies.ukey2_connections]
-path = ".."
-
-# Prevent this from interfering with workspaces
-[workspace]
-members = ["."]
-
-[profile.release]
-debug = 1
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
[[bin]]
name = "fuzz_connection"
path = "fuzz_targets/fuzz_connection.rs"
-test = false
doc = false
[[bin]]
name = "fuzz_handshake"
path = "fuzz_targets/fuzz_handshake.rs"
-test = false
doc = false
[[bin]]
name = "fuzz_from_saved_session"
path = "fuzz_targets/fuzz_from_saved_session.rs"
-test = false
doc = false
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_connection.rs b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_connection.rs
index 1db7e63..8a02bc0 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_connection.rs
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_connection.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +15,15 @@
use arbitrary::Arbitrary;
use crypto_provider_rustcrypto::RustCrypto;
-use libfuzzer_sys::fuzz_target;
+use derive_fuzztest::fuzztest;
use rand_chacha::rand_core::SeedableRng;
use ukey2_connections::HandshakeImplementation;
use ukey2_connections::{
D2DHandshakeContext, InitiatorD2DHandshakeContext, ServerD2DHandshakeContext,
};
+use ukey2_rs::NextProtocol;
-#[derive(Debug, Arbitrary)]
+#[derive(Clone, Debug, Arbitrary)]
enum Type {
SentByInitiator,
SentByServer,
@@ -30,28 +31,24 @@ enum Type {
ReceivedByServer,
}
-#[derive(Debug, Arbitrary)]
-struct Message<'a> {
+#[derive(Clone, Debug, Arbitrary)]
+struct Message {
sender: Type,
- payload: &'a [u8],
- associated_data: Option<&'a [u8]>,
+ payload: Vec<u8>,
+ associated_data: Option<Vec<u8>>,
}
-#[derive(Debug, Arbitrary)]
-struct FuzzInput<'a> {
- client_rng_seed: [u8; 32],
- server_rng_seed: [u8; 32],
- messages: Vec<Message<'a>>,
-}
-
-fuzz_target!(|input: FuzzInput| {
+#[fuzztest]
+fn test(client_rng_seed: [u8; 32], server_rng_seed: [u8; 32], messages: Vec<Message>) {
let mut initiator_ctx = InitiatorD2DHandshakeContext::<RustCrypto, _>::new_impl(
HandshakeImplementation::Spec,
- rand_chacha::ChaChaRng::from_seed(input.client_rng_seed),
+ rand_chacha::ChaChaRng::from_seed(client_rng_seed),
+ vec![NextProtocol::Aes256CbcHmacSha256],
);
let mut server_ctx = ServerD2DHandshakeContext::<RustCrypto, _>::new_impl(
HandshakeImplementation::Spec,
- rand_chacha::ChaChaRng::from_seed(input.server_rng_seed),
+ rand_chacha::ChaChaRng::from_seed(server_rng_seed),
+ &[NextProtocol::Aes256CbcHmacSha256],
);
let client_init = initiator_ctx
.get_next_handshake_message()
@@ -81,39 +78,40 @@ fuzz_target!(|input: FuzzInput| {
"Initator handshake context should be converted to connection context successfully",
);
- for Message {
- sender,
- payload,
- associated_data,
- } in input.messages
- {
+ for Message { sender, payload, associated_data } in messages {
match sender {
Type::SentByInitiator => {
let ciphertext = initiator_connection
- .encode_message_to_peer::<RustCrypto, _>(payload, associated_data);
+ .encode_message_to_peer::<RustCrypto, _>(&payload, associated_data.as_ref());
let decoded = server_connection
- .decode_message_from_peer::<RustCrypto, _>(&ciphertext, associated_data)
+ .decode_message_from_peer::<RustCrypto, _>(
+ &ciphertext,
+ associated_data.as_ref(),
+ )
.unwrap();
assert_eq!(decoded, payload);
}
Type::SentByServer => {
let ciphertext = server_connection
- .encode_message_to_peer::<RustCrypto, _>(payload, associated_data);
+ .encode_message_to_peer::<RustCrypto, _>(&payload, associated_data.as_ref());
let decoded = initiator_connection
- .decode_message_from_peer::<RustCrypto, _>(&ciphertext, associated_data)
+ .decode_message_from_peer::<RustCrypto, _>(
+ &ciphertext,
+ associated_data.as_ref(),
+ )
.unwrap();
assert_eq!(decoded, payload);
}
Type::ReceivedByInitiator => {
// Both Ok and Err results are possible here since the input is Arbitrary payload
let _unused_result = initiator_connection
- .decode_message_from_peer::<RustCrypto, _>(&payload, associated_data);
+ .decode_message_from_peer::<RustCrypto, _>(&payload, associated_data.as_ref());
}
Type::ReceivedByServer => {
// Both Ok and Err results are possible here since the input is Arbitrary payload
let _unused_result = server_connection
- .decode_message_from_peer::<RustCrypto, _>(&payload, associated_data);
+ .decode_message_from_peer::<RustCrypto, _>(&payload, associated_data.as_ref());
}
}
}
-});
+}
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_from_saved_session.rs b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_from_saved_session.rs
index c2cd385..0d35f7e 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_from_saved_session.rs
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_from_saved_session.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,17 +13,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use libfuzzer_sys::fuzz_target;
-use ukey2_connections::{D2DConnectionContextV1, DeserializeError};
use crypto_provider_rustcrypto::RustCrypto;
+use derive_fuzztest::fuzztest;
+use ukey2_connections::{D2DConnectionContextV1, DeserializeError};
const PROTOCOL_VERSION: u8 = 1;
-fuzz_target!(|input: [u8; 73]| {
+#[fuzztest]
+fn test(input: [u8; 73]) {
let result = D2DConnectionContextV1::from_saved_session::<RustCrypto>(&input);
if input[0] != PROTOCOL_VERSION {
assert_eq!(result.unwrap_err(), DeserializeError::BadProtocolVersion);
} else {
assert!(result.is_ok());
}
-});
+}
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_handshake.rs b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_handshake.rs
index 3007c9a..24cde94 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_handshake.rs
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/fuzz_targets/fuzz_handshake.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,55 +13,54 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use arbitrary::Arbitrary;
use crypto_provider_rustcrypto::RustCrypto;
-use libfuzzer_sys::fuzz_target;
+use derive_fuzztest::fuzztest;
use rand_chacha::rand_core::SeedableRng;
use ukey2_connections::HandshakeImplementation;
use ukey2_connections::{
D2DHandshakeContext, InitiatorD2DHandshakeContext, ServerD2DHandshakeContext,
};
+use ukey2_rs::NextProtocol;
-#[derive(Debug, Arbitrary)]
-struct FuzzInput<'a> {
+#[fuzztest]
+fn test(
client_rng_seed: [u8; 32],
server_rng_seed: [u8; 32],
- override_client_init: Option<&'a [u8]>,
- override_server_init: Option<&'a [u8]>,
- override_client_finish: Option<&'a [u8]>,
-}
-
-fuzz_target!(|input: FuzzInput| {
+ override_client_init: Option<Vec<u8>>,
+ override_server_init: Option<Vec<u8>>,
+ override_client_finish: Option<Vec<u8>>,
+) {
let mut initiator_ctx = InitiatorD2DHandshakeContext::<RustCrypto, _>::new_impl(
HandshakeImplementation::Spec,
- rand_chacha::ChaChaRng::from_seed(input.client_rng_seed),
+ rand_chacha::ChaChaRng::from_seed(client_rng_seed),
+ vec![NextProtocol::Aes256CbcHmacSha256],
);
let mut server_ctx = ServerD2DHandshakeContext::<RustCrypto, _>::new_impl(
HandshakeImplementation::Spec,
- rand_chacha::ChaChaRng::from_seed(input.server_rng_seed),
+ rand_chacha::ChaChaRng::from_seed(server_rng_seed),
+ &[NextProtocol::Aes256CbcHmacSha256],
);
let client_init = initiator_ctx
.get_next_handshake_message()
.expect("Initial get_next_handshake_message should succeed");
- let client_init_with_override = input.override_client_init.unwrap_or(&client_init);
+ let client_init_with_override = override_client_init.unwrap_or(client_init);
let _result = server_ctx
- .handle_handshake_message(client_init_with_override)
+ .handle_handshake_message(&client_init_with_override)
.and_then(|_| {
let server_init = server_ctx.get_next_handshake_message().expect(concat!(
"get_next_handshake_message should succeed when previous ",
"handle_handshake_message succeeded"
));
- let server_init_with_override = input.override_server_init.unwrap_or(&server_init);
- initiator_ctx.handle_handshake_message(server_init_with_override)
+ let server_init_with_override = override_server_init.unwrap_or(server_init);
+ initiator_ctx.handle_handshake_message(&server_init_with_override)
})
.and_then(|_| {
let client_finish = initiator_ctx.get_next_handshake_message().expect(concat!(
"get_next_handshake_message should succeed when previous ",
"handle_handshake_message succeeded"
));
- let client_finish_with_override =
- input.override_client_finish.unwrap_or(&client_finish);
- server_ctx.handle_handshake_message(client_finish_with_override)
+ let client_finish_with_override = override_client_finish.unwrap_or(client_finish);
+ server_ctx.handle_handshake_message(&client_finish_with_override)
})
.map(|_| {
assert!(server_ctx.is_handshake_complete());
@@ -71,4 +70,4 @@ fuzz_target!(|input: FuzzInput| {
}
// Note: initiator keeps returning client_finish at the Complete state
});
-});
+}
diff --git a/nearby/connections/ukey2/ukey2_connections/src/crypto_utils.rs b/nearby/connections/ukey2/ukey2_connections/src/crypto_utils.rs
index f4bd671..815d3f0 100644
--- a/nearby/connections/ukey2/ukey2_connections/src/crypto_utils.rs
+++ b/nearby/connections/ukey2/ukey2_connections/src/crypto_utils.rs
@@ -13,10 +13,11 @@
// limitations under the License.
use crate::d2d_connection_context_v1::{Aes256Key as RawAes256Key, AesCbcIv};
+use crypto_provider::aead::AeadError;
use crypto_provider::aes::cbc::DecryptionError;
-/// Encrypt message of length N
-pub(crate) fn encrypt<
+/// Encrypt message of length N with AES-CBC-256
+pub(crate) fn encrypt_cbc<
R: rand::Rng + rand::CryptoRng,
A: crypto_provider::aes::cbc::AesCbcPkcs7Padded,
>(
@@ -29,10 +30,40 @@ pub(crate) fn encrypt<
(ciphertext, iv)
}
-pub(crate) fn decrypt<A: crypto_provider::aes::cbc::AesCbcPkcs7Padded>(
+/// Decrypt message of length N with AES-CBC-256
+pub(crate) fn decrypt_cbc<A: crypto_provider::aes::cbc::AesCbcPkcs7Padded>(
key: &RawAes256Key,
ciphertext: &[u8],
iv: &AesCbcIv,
) -> Result<Vec<u8>, DecryptionError> {
A::decrypt(&key[..].try_into().unwrap(), iv, ciphertext)
}
+
+// TODO: Implement caching of these ciphers per connection so we don't recreate on each computation.
+pub(crate) fn encrypt_gcm_siv<
+ A: crypto_provider::aead::AesGcmSiv
+ + crypto_provider::aead::AeadInit<crypto_provider::aes::Aes256Key>,
+>(
+ key: &RawAes256Key,
+ plaintext: &[u8],
+ aad: &[u8],
+ nonce: &A::Nonce,
+) -> Result<Vec<u8>, AeadError> {
+ let converted_key = key.as_slice().try_into().unwrap();
+ let encrypter = A::new(&converted_key);
+ encrypter.encrypt(plaintext, aad, nonce)
+}
+
+pub(crate) fn decrypt_gcm_siv<
+ A: crypto_provider::aead::AesGcmSiv
+ + crypto_provider::aead::AeadInit<crypto_provider::aes::Aes256Key>,
+>(
+ key: &RawAes256Key,
+ ciphertext: &[u8],
+ aad: &[u8],
+ nonce: &A::Nonce,
+) -> Result<Vec<u8>, AeadError> {
+ let converted_key = key.as_slice().try_into().unwrap();
+ let decrypter = A::new(&converted_key);
+ decrypter.decrypt(ciphertext, aad, nonce)
+}
diff --git a/nearby/connections/ukey2/ukey2_connections/src/d2d_connection_context_v1.rs b/nearby/connections/ukey2/ukey2_connections/src/d2d_connection_context_v1.rs
index 70a1556..22def10 100644
--- a/nearby/connections/ukey2/ukey2_connections/src/d2d_connection_context_v1.rs
+++ b/nearby/connections/ukey2/ukey2_connections/src/d2d_connection_context_v1.rs
@@ -18,14 +18,15 @@ use std::fmt::Formatter;
use bytes::BufMut;
use rand::SeedableRng as _;
+use crypto_provider::aead::Aead;
use crypto_provider::{hkdf::Hkdf, hmac::Hmac, sha2::Sha256, CryptoProvider};
-use ukey2_proto::protobuf::Message as _;
+use ukey2_proto::protobuf::{Enum, Message as _};
use ukey2_proto::ukey2_all_proto::{
device_to_device_messages::DeviceToDeviceMessage,
securegcm::{GcmMetadata, Type},
securemessage::{EncScheme, Header, HeaderAndBody, SecureMessage, SigScheme},
};
-use ukey2_rs::CompletedHandshake;
+use ukey2_rs::{CompletedHandshake, NextProtocol};
use crate::{crypto_utils, java_utils};
@@ -52,7 +53,7 @@ const SESSION_UNIQUE_SALT: [u8; 32] = [
];
pub(crate) type AesCbcIv = [u8; 16];
-pub type Aes256Key = [u8; 32];
+pub type Aes256Key = [u8; AES_256_KEY_SIZE];
const HKDF_INFO_KEY_INITIATOR: &[u8; 6] = b"client";
const HKDF_INFO_KEY_RESPONDER: &[u8; 6] = b"server";
@@ -118,6 +119,7 @@ where
signing_key: Aes256Key,
verify_key: Aes256Key,
rng: R,
+ protocol: NextProtocol,
}
/// Error type for [`decode_message_from_peer`][D2DConnectionContextV1::decode_message_from_peer].
@@ -160,14 +162,13 @@ impl<R> D2DConnectionContextV1<R>
where
R: rand::Rng + rand::SeedableRng + rand::CryptoRng,
{
- pub(crate) const NEXT_PROTOCOL_IDENTIFIER: &'static str = "AES_256_CBC-HMAC_SHA256";
-
pub fn new<C: CryptoProvider>(
decode_sequence_num: i32,
encode_sequence_num: i32,
encode_key: Aes256Key,
decode_key: Aes256Key,
rng: R,
+ protocol: NextProtocol,
) -> Self {
let encryption_key = derive_aes256_key::<C>(&encode_key, b"ENC:2");
let decryption_key = derive_aes256_key::<C>(&decode_key, b"ENC:2");
@@ -183,6 +184,7 @@ where
signing_key,
verify_key,
rng,
+ protocol,
}
}
@@ -198,6 +200,7 @@ where
encryption_key::<32, C>(&next_protocol_secret, HKDF_INFO_KEY_INITIATOR).unwrap(),
encryption_key::<32, C>(&next_protocol_secret, HKDF_INFO_KEY_RESPONDER).unwrap(),
rng,
+ handshake.next_protocol,
)
}
@@ -213,6 +216,7 @@ where
encryption_key::<32, C>(&next_protocol_secret, HKDF_INFO_KEY_RESPONDER).unwrap(),
encryption_key::<32, C>(&next_protocol_secret, HKDF_INFO_KEY_INITIATOR).unwrap(),
rng,
+ handshake.next_protocol,
)
}
@@ -240,6 +244,9 @@ where
ret.put_i32(self.decode_sequence_num);
ret.extend_from_slice(self.encode_key.as_slice());
ret.extend_from_slice(self.decode_key.as_slice());
+ if self.protocol == NextProtocol::Aes256GcmSiv {
+ ret.extend_from_slice(&EncScheme::AES_256_GCM_SIV.value().to_be_bytes())
+ }
ret
}
@@ -247,31 +254,52 @@ where
session: &[u8],
rng: R,
) -> Result<Self, DeserializeError> {
- if session.len() != 73 {
+ if session.len() != 73 && session.len() != 77 {
return Err(DeserializeError::BadDataLength);
}
let (rem, _) = nom::bytes::complete::tag(PROTOCOL_VERSION.to_be_bytes())(session)
.map_err(|_: nom::Err<nom::error::Error<_>>| DeserializeError::BadProtocolVersion)?;
-
- let (_, (encode_sequence_num, decode_sequence_num, encode_key, decode_key)) =
- nom::combinator::all_consuming(nom::sequence::tuple::<_, _, nom::error::Error<_>, _>(
- (
- nom::number::complete::be_i32,
- nom::number::complete::be_i32,
- nom::combinator::map_res(
- nom::bytes::complete::take(32_usize),
- TryInto::<Aes256Key>::try_into,
- ),
- nom::combinator::map_res(
- nom::bytes::complete::take(32_usize),
- TryInto::<Aes256Key>::try_into,
- ),
+ let (
+ _,
+ (encode_sequence_num, decode_sequence_num, encode_key, decode_key, next_protocol_int),
+ ) = nom::combinator::all_consuming(nom::sequence::tuple::<_, _, nom::error::Error<_>, _>(
+ (
+ nom::number::complete::be_i32,
+ nom::number::complete::be_i32,
+ nom::combinator::map_res(
+ nom::bytes::complete::take(32_usize),
+ TryInto::<Aes256Key>::try_into,
+ ),
+ nom::combinator::map_res(
+ nom::bytes::complete::take(32_usize),
+ TryInto::<Aes256Key>::try_into,
),
- ))(rem)
- // This should always succeed since all of the parsers above are valid over the entire
- // [u8] space, and we already checked the length at the start.
- .expect("Saved session parsing should succeed");
- Ok(Self::new::<C>(encode_sequence_num, decode_sequence_num, encode_key, decode_key, rng))
+ nom::combinator::opt(nom::number::complete::be_i32),
+ ),
+ ))(rem)
+ // This should always succeed since all of the parsers above are valid over the entire
+ // [u8] space, and we already checked the length at the start.
+ .expect("Saved session parsing should succeed");
+
+ let next_protocol = if let Some(next_protocol_raw) = next_protocol_int {
+ let enc_scheme =
+ EncScheme::from_i32(next_protocol_raw).ok_or(DeserializeError::BadData)?;
+ match enc_scheme {
+ EncScheme::NONE => Err(DeserializeError::BadData),
+ EncScheme::AES_256_CBC => Ok(NextProtocol::Aes256CbcHmacSha256),
+ EncScheme::AES_256_GCM_SIV => Ok(NextProtocol::Aes256GcmSiv),
+ }?
+ } else {
+ NextProtocol::Aes256CbcHmacSha256
+ };
+ Ok(Self::new::<C>(
+ encode_sequence_num,
+ decode_sequence_num,
+ encode_key,
+ decode_key,
+ rng,
+ next_protocol,
+ ))
}
/// Once initiator and responder have exchanged public keys, use this method to encrypt and
@@ -292,11 +320,6 @@ where
message: payload.to_vec(),
sequence_num: self.get_sequence_number_for_encoding(),
});
- let (ciphertext, iv) = crypto_utils::encrypt::<_, C::AesCbcPkcs7Padded>(
- &self.encryption_key,
- message.as_slice(),
- &mut self.rng,
- );
let metadata = GcmMetadata {
type_: Some(Type::DEVICE_TO_DEVICE_MESSAGE.into()),
// As specified in
@@ -304,32 +327,74 @@ where
version: Some(1),
..Default::default()
};
- let header = Header {
- signature_scheme: Some(SigScheme::HMAC_SHA256.into()),
- encryption_scheme: Some(EncScheme::AES_256_CBC.into()),
- iv: Some(iv.to_vec()),
- public_metadata: Some(metadata.write_to_bytes().unwrap()),
- associated_data_length: associated_data.as_ref().map(|d| d.as_ref().len() as u32),
- ..Default::default()
+ let (ciphertext, header) = match self.protocol {
+ NextProtocol::Aes256GcmSiv => {
+ let nonce: [u8; 12] = self.rng.gen();
+ let ciphertext = crypto_utils::encrypt_gcm_siv::<C::Aes256GcmSiv>(
+ &self.encryption_key,
+ &message,
+ associated_data.as_ref().map_or(&[], AsRef::as_ref),
+ &nonce,
+ )
+ .unwrap();
+ (
+ ciphertext,
+ Header {
+ signature_scheme: Some(SigScheme::AEAD.into()),
+ encryption_scheme: Some(EncScheme::AES_256_GCM_SIV.into()),
+ nonce: Some(nonce.to_vec()),
+ public_metadata: Some(metadata.write_to_bytes().unwrap()),
+ associated_data_length: associated_data
+ .as_ref()
+ .map(|d| d.as_ref().len() as u32),
+ ..Default::default()
+ },
+ )
+ }
+ NextProtocol::Aes256CbcHmacSha256 => {
+ let (ciphertext, iv) = crypto_utils::encrypt_cbc::<_, C::AesCbcPkcs7Padded>(
+ &self.encryption_key,
+ message.as_slice(),
+ &mut self.rng,
+ );
+ (
+ ciphertext,
+ Header {
+ signature_scheme: Some(SigScheme::HMAC_SHA256.into()),
+ encryption_scheme: Some(EncScheme::AES_256_CBC.into()),
+ iv: Some(iv.to_vec()),
+ public_metadata: Some(metadata.write_to_bytes().unwrap()),
+ associated_data_length: associated_data
+ .as_ref()
+ .map(|d| d.as_ref().len() as u32),
+ ..Default::default()
+ },
+ )
+ }
};
+
let header_and_body = HeaderAndBody {
header: Some(header).into(),
body: Some(ciphertext),
..Default::default()
};
let header_and_body_bytes = header_and_body.write_to_bytes().unwrap();
-
- // add sha256 MAC
- let mut hmac = C::HmacSha256::new_from_slice(&self.signing_key).unwrap();
- hmac.update(header_and_body_bytes.as_slice());
- if let Some(associated_data_vec) = associated_data.as_ref() {
- hmac.update(associated_data_vec.as_ref())
- }
- let result_mac = hmac.finalize().to_vec();
+ let signature = match self.protocol {
+ NextProtocol::Aes256CbcHmacSha256 => {
+ // add sha256 MAC
+ let mut hmac = C::HmacSha256::new_from_slice(&self.signing_key).unwrap();
+ hmac.update(header_and_body_bytes.as_slice());
+ if let Some(associated_data_vec) = associated_data.as_ref() {
+ hmac.update(associated_data_vec.as_ref())
+ }
+ Some(hmac.finalize().to_vec())
+ }
+ NextProtocol::Aes256GcmSiv => Some(vec![]),
+ };
let secure_message = SecureMessage {
header_and_body: Some(header_and_body_bytes),
- signature: Some(result_mac),
+ signature,
..Default::default()
};
secure_message.write_to_bytes().unwrap()
@@ -349,36 +414,60 @@ where
) -> Result<Vec<u8>, DecodeError> {
// first confirm that the payload MAC matches the header_and_body
let message = SecureMessage::parse_from_bytes(payload).map_err(|_| DecodeError::BadData)?;
- let payload_mac: [u8; 32] = message
- .signature
- .and_then(|signature| signature.try_into().ok())
- .ok_or(DecodeError::BadData)?;
- let payload = message.header_and_body.ok_or(DecodeError::BadData)?;
- let mut hmac = C::HmacSha256::new_from_slice(&self.verify_key).unwrap();
- hmac.update(&payload);
- if let Some(associated_data) = associated_data.as_ref() {
- hmac.update(associated_data.as_ref())
+ let header_and_body = message.header_and_body.ok_or(DecodeError::BadData)?;
+ match self.protocol {
+ NextProtocol::Aes256CbcHmacSha256 => {
+ let payload_mac: [u8; 32] = message
+ .signature
+ .and_then(|signature| signature.try_into().ok())
+ .ok_or(DecodeError::BadData)?;
+ let mut hmac = C::HmacSha256::new_from_slice(&self.verify_key).unwrap();
+ hmac.update(&header_and_body);
+ if let Some(associated_data) = associated_data.as_ref() {
+ hmac.update(associated_data.as_ref())
+ }
+ hmac.verify(payload_mac).map_err(|_| DecodeError::BadData)?;
+ }
+ NextProtocol::Aes256GcmSiv => {} // No need to check signature on an AEAD cipher.
}
- hmac.verify(payload_mac).map_err(|_| DecodeError::BadData)?;
+
let payload =
- HeaderAndBody::parse_from_bytes(&payload).map_err(|_| DecodeError::BadData)?;
- let associated_data_len =
- payload.header.as_ref().and_then(|header| header.associated_data_length);
- if associated_data_len != associated_data.map(|ad| ad.as_ref().len() as u32) {
- return Err(DecodeError::BadData);
- }
- let iv: AesCbcIv = payload
- .header
- .as_ref()
- .and_then(|header| header.iv().try_into().ok())
- .ok_or(DecodeError::BadData)?;
- let decrypted = crypto_utils::decrypt::<C::AesCbcPkcs7Padded>(
- &self.decryption_key,
- &payload.body.unwrap_or_default(),
- &iv,
- )
- .map_err(|_| DecodeError::BadData)?;
- let d2d_message = unwrap_device_to_device_message(decrypted.as_slice())?;
+ HeaderAndBody::parse_from_bytes(&header_and_body).map_err(|_| DecodeError::BadData)?;
+ let decrypted = match self.protocol {
+ NextProtocol::Aes256GcmSiv => {
+ let nonce: <<C as CryptoProvider>::Aes256GcmSiv as Aead>::Nonce = payload
+ .header
+ .as_ref()
+ .and_then(|header| header.nonce().try_into().ok())
+ .ok_or(DecodeError::BadData)?;
+ crypto_utils::decrypt_gcm_siv::<C::Aes256GcmSiv>(
+ &self.decryption_key,
+ &payload.body.unwrap_or_default(),
+ associated_data.as_ref().map_or(&[], AsRef::as_ref),
+ &nonce,
+ )
+ .map_err(|_| DecodeError::BadData)?
+ }
+ NextProtocol::Aes256CbcHmacSha256 => {
+ let associated_data_len =
+ payload.header.as_ref().and_then(|header| header.associated_data_length);
+ if associated_data_len != associated_data.map(|ad| ad.as_ref().len() as u32) {
+ return Err(DecodeError::BadData);
+ }
+ let iv: AesCbcIv = payload
+ .header
+ .as_ref()
+ .and_then(|header| header.iv().try_into().ok())
+ .ok_or(DecodeError::BadData)?;
+ crypto_utils::decrypt_cbc::<C::AesCbcPkcs7Padded>(
+ &self.decryption_key,
+ &payload.body.unwrap_or_default(),
+ &iv,
+ )
+ .map_err(|_| DecodeError::BadData)?
+ }
+ };
+ let d2d_message = unwrap_device_to_device_message(&decrypted)?;
if d2d_message.sequence_num != self.get_sequence_number_for_decoding() + 1 {
return Err(DecodeError::BadSequenceNumber);
}
diff --git a/nearby/connections/ukey2/ukey2_connections/src/d2d_handshake_context.rs b/nearby/connections/ukey2/ukey2_connections/src/d2d_handshake_context.rs
index d9e1524..5e7262b 100644
--- a/nearby/connections/ukey2/ukey2_connections/src/d2d_handshake_context.rs
+++ b/nearby/connections/ukey2/ukey2_connections/src/d2d_handshake_context.rs
@@ -15,11 +15,11 @@
use crate::d2d_connection_context_v1::D2DConnectionContextV1;
use crypto_provider::CryptoProvider;
-use rand::{rngs::StdRng, SeedableRng as _};
+use rand::SeedableRng as _;
use std::{collections::HashSet, mem};
use ukey2_rs::{
- CompletedHandshake, HandshakeImplementation, StateMachine, Ukey2Client, Ukey2ClientStage1,
- Ukey2Server, Ukey2ServerStage1, Ukey2ServerStage2,
+ CompletedHandshake, HandshakeImplementation, NextProtocol, StateMachine, Ukey2Client,
+ Ukey2ClientStage1, Ukey2Server, Ukey2ServerStage1, Ukey2ServerStage2,
};
#[derive(Debug)]
@@ -99,8 +99,8 @@ where
}
impl<C: CryptoProvider> InitiatorD2DHandshakeContext<C, rand::rngs::StdRng> {
- pub fn new(handshake_impl: HandshakeImplementation) -> Self {
- Self::new_impl(handshake_impl, rand::rngs::StdRng::from_entropy())
+ pub fn new(handshake_impl: HandshakeImplementation, next_protocols: Vec<NextProtocol>) -> Self {
+ Self::new_impl(handshake_impl, rand::rngs::StdRng::from_entropy(), next_protocols)
}
}
@@ -110,12 +110,12 @@ where
{
// Used for testing / fuzzing only.
#[doc(hidden)]
- pub fn new_impl(handshake_impl: HandshakeImplementation, mut rng: R) -> Self {
- let client = Ukey2ClientStage1::from(
- &mut rng,
- D2DConnectionContextV1::<StdRng>::NEXT_PROTOCOL_IDENTIFIER.to_owned(),
- handshake_impl,
- );
+ pub fn new_impl(
+ handshake_impl: HandshakeImplementation,
+ mut rng: R,
+ next_protocols: Vec<NextProtocol>,
+ ) -> Self {
+ let client = Ukey2ClientStage1::from(&mut rng, next_protocols, handshake_impl);
Self { state: InitiatorState::Stage1(client), rng }
}
}
@@ -157,6 +157,14 @@ where
}
}
+ fn to_connection_context(&mut self) -> Result<D2DConnectionContextV1<R>, HandshakeError> {
+ // Since self.rng is expected to be a seeded PRNG, not an OsRng directly, from_rng
+ // should never fail. https://rust-random.github.io/book/guide-err.html
+ let rng = R::from_rng(&mut self.rng).unwrap();
+ self.to_completed_handshake()
+ .map(|h| D2DConnectionContextV1::from_initiator_handshake::<C>(h, rng))
+ }
+
fn to_completed_handshake(&self) -> Result<&CompletedHandshake, HandshakeError> {
match &self.state {
InitiatorState::Stage1(_) | InitiatorState::Invalid => {
@@ -165,18 +173,6 @@ where
InitiatorState::Complete(c) => Ok(c.completed_handshake()),
}
}
-
- fn to_connection_context(&mut self) -> Result<D2DConnectionContextV1<R>, HandshakeError> {
- // Since self.rng is expected to be a seeded PRNG, not an OsRng directly, from_rng
- // should never fail. https://rust-random.github.io/book/guide-err.html
- let rng = R::from_rng(&mut self.rng).unwrap();
- self.to_completed_handshake().and_then(|h| match h.next_protocol.as_ref() {
- D2DConnectionContextV1::<R>::NEXT_PROTOCOL_IDENTIFIER => {
- Ok(D2DConnectionContextV1::from_initiator_handshake::<C>(h, rng))
- }
- _ => Err(HandshakeError::HandshakeNotComplete),
- })
- }
}
enum ServerState<C: CryptoProvider> {
@@ -198,8 +194,8 @@ where
}
impl<C: CryptoProvider> ServerD2DHandshakeContext<C, rand::rngs::StdRng> {
- pub fn new(handshake_impl: HandshakeImplementation) -> Self {
- Self::new_impl(handshake_impl, rand::rngs::StdRng::from_entropy())
+ pub fn new(handshake_impl: HandshakeImplementation, next_protocols: &[NextProtocol]) -> Self {
+ Self::new_impl(handshake_impl, rand::rngs::StdRng::from_entropy(), next_protocols)
}
}
@@ -209,13 +205,14 @@ where
{
// Used for testing / fuzzing only.
#[doc(hidden)]
- pub fn new_impl(handshake_impl: HandshakeImplementation, rng: R) -> Self {
+ pub fn new_impl(
+ handshake_impl: HandshakeImplementation,
+ rng: R,
+ next_protocols: &[NextProtocol],
+ ) -> Self {
Self {
state: ServerState::Stage1(Ukey2ServerStage1::from(
- HashSet::from([
- D2DConnectionContextV1::<rand::rngs::StdRng>::NEXT_PROTOCOL_IDENTIFIER
- .to_owned(),
- ]),
+ HashSet::from_iter(next_protocols.iter().map(|np| np.to_string())),
handshake_impl,
)),
rng,
@@ -280,16 +277,7 @@ where
// Since self.rng is expected to be a seeded PRNG, not an OsRng directly, from_rng
// should never fail. https://rust-random.github.io/book/guide-err.html
let rng = R::from_rng(&mut self.rng).unwrap();
- self.to_completed_handshake().map(|h| match h.next_protocol.as_ref() {
- D2DConnectionContextV1::<R>::NEXT_PROTOCOL_IDENTIFIER => {
- D2DConnectionContextV1::from_responder_handshake::<C>(h, rng)
- }
- _ => {
- // This should never happen because ukey2_handshake should set next_protocol to
- // one of the values we passed in Ukey2ServerStage1::from, which doesn't contain
- // any other value.
- panic!("Unknown next protocol: {}", h.next_protocol);
- }
- })
+ self.to_completed_handshake()
+ .map(|h| D2DConnectionContextV1::from_responder_handshake::<C>(h, rng))
}
}
diff --git a/nearby/connections/ukey2/ukey2_connections/src/lib.rs b/nearby/connections/ukey2/ukey2_connections/src/lib.rs
index b3ed937..eb8a55b 100644
--- a/nearby/connections/ukey2/ukey2_connections/src/lib.rs
+++ b/nearby/connections/ukey2/ukey2_connections/src/lib.rs
@@ -42,4 +42,4 @@ pub use d2d_handshake_context::{
D2DHandshakeContext, HandleMessageError, HandshakeError, InitiatorD2DHandshakeContext,
ServerD2DHandshakeContext,
};
-pub use ukey2_rs::HandshakeImplementation;
+pub use ukey2_rs::{HandshakeImplementation, NextProtocol};
diff --git a/nearby/connections/ukey2/ukey2_connections/src/tests.rs b/nearby/connections/ukey2/ukey2_connections/src/tests.rs
index d6acecc..9f0b13e 100644
--- a/nearby/connections/ukey2/ukey2_connections/src/tests.rs
+++ b/nearby/connections/ukey2/ukey2_connections/src/tests.rs
@@ -18,10 +18,10 @@ use crypto_provider::CryptoProvider;
use crypto_provider_default::CryptoProviderImpl;
use rand::SeedableRng;
use rand::{rngs::StdRng, CryptoRng, RngCore};
-use ukey2_rs::HandshakeImplementation;
+use ukey2_rs::{HandshakeImplementation, NextProtocol};
use crate::{
- crypto_utils::{decrypt, encrypt},
+ crypto_utils::{decrypt_cbc, encrypt_cbc},
java_utils, Aes256Key, D2DConnectionContextV1, D2DHandshakeContext, DeserializeError,
InitiatorD2DHandshakeContext, ServerD2DHandshakeContext,
};
@@ -33,8 +33,8 @@ fn crypto_test_encrypt_decrypt() {
let message = b"Hello World!";
let key = b"42424242424242424242424242424242";
let (ciphertext, iv) =
- encrypt::<_, AesCbcPkcs7Padded>(key, message, &mut rand::rngs::StdRng::from_entropy());
- let decrypt_result = decrypt::<AesCbcPkcs7Padded>(key, ciphertext.as_slice(), &iv);
+ encrypt_cbc::<_, AesCbcPkcs7Padded>(key, message, &mut rand::rngs::StdRng::from_entropy());
+ let decrypt_result = decrypt_cbc::<AesCbcPkcs7Padded>(key, ciphertext.as_slice(), &iv);
let ptext = decrypt_result.expect("Decrypt should be successful");
assert_eq!(ptext, message.to_vec());
}
@@ -44,7 +44,7 @@ fn crypto_test_encrypt_seeded() {
let message = b"Hello World!";
let key = b"42424242424242424242424242424242";
let mut rng = MockRng;
- let (ciphertext, iv) = encrypt::<_, AesCbcPkcs7Padded>(key, message, &mut rng);
+ let (ciphertext, iv) = encrypt_cbc::<_, AesCbcPkcs7Padded>(key, message, &mut rng);
// Expected values extracted from the results of the current implementation.
// This test makes sure that we don't accidentally change the encryption logic that
// causes incompatibility between versions.
@@ -60,7 +60,7 @@ fn crypto_test_decrypt_seeded() {
let iv = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
let ciphertext = [20, 59, 195, 101, 11, 208, 245, 128, 247, 196, 81, 80, 158, 77, 174, 61];
let key = b"42424242424242424242424242424242";
- let plaintext = decrypt::<AesCbcPkcs7Padded>(key, &ciphertext, &iv).unwrap();
+ let plaintext = decrypt_cbc::<AesCbcPkcs7Padded>(key, &ciphertext, &iv).unwrap();
assert_eq!(plaintext, b"Hello World!");
}
@@ -68,27 +68,41 @@ fn crypto_test_decrypt_seeded() {
fn decrypt_test_wrong_key() {
let message = b"Hello World!";
let good_key = b"42424242424242424242424242424242";
- let (ciphertext, iv) =
- encrypt::<_, AesCbcPkcs7Padded>(good_key, message, &mut rand::rngs::StdRng::from_entropy());
+ let (ciphertext, iv) = encrypt_cbc::<_, AesCbcPkcs7Padded>(
+ good_key,
+ message,
+ &mut rand::rngs::StdRng::from_entropy(),
+ );
let bad_key = b"43434343434343434343434343434343";
- let decrypt_result = decrypt::<AesCbcPkcs7Padded>(bad_key, ciphertext.as_slice(), &iv);
+ let decrypt_result = decrypt_cbc::<AesCbcPkcs7Padded>(bad_key, ciphertext.as_slice(), &iv);
match decrypt_result {
// The padding is valid, but the decrypted value should be bad since the keys don't match
Ok(decrypted_bad) => assert_ne!(decrypted_bad, message),
// The padding is bad, so it returns an error and is unable to decrypt
Err(crypto_provider::aes::cbc::DecryptionError::BadPadding) => (),
}
- let decrypt_result = decrypt::<AesCbcPkcs7Padded>(good_key, ciphertext.as_slice(), &iv);
+ let decrypt_result = decrypt_cbc::<AesCbcPkcs7Padded>(good_key, ciphertext.as_slice(), &iv);
let ptext = decrypt_result.unwrap();
assert_eq!(ptext, message.to_vec());
}
-fn run_handshake() -> (D2DConnectionContextV1, D2DConnectionContextV1) {
- run_handshake_with_rng::<CryptoProviderImpl, _>(rand::rngs::StdRng::from_entropy())
+fn run_cbc_handshake() -> (D2DConnectionContextV1, D2DConnectionContextV1) {
+ run_handshake_with_rng::<CryptoProviderImpl, _>(
+ rand::rngs::StdRng::from_entropy(),
+ vec![NextProtocol::Aes256CbcHmacSha256],
+ )
+}
+
+fn run_gcm_handshake() -> (D2DConnectionContextV1, D2DConnectionContextV1) {
+ run_handshake_with_rng::<CryptoProviderImpl, _>(
+ rand::rngs::StdRng::from_entropy(),
+ vec![NextProtocol::Aes256GcmSiv],
+ )
}
fn run_handshake_with_rng<C, R>(
mut rng: R,
+ next_protocols: Vec<NextProtocol>,
) -> (D2DConnectionContextV1<R>, D2DConnectionContextV1<R>)
where
C: CryptoProvider,
@@ -97,10 +111,12 @@ where
let mut initiator_ctx = InitiatorD2DHandshakeContext::<C, R>::new_impl(
HandshakeImplementation::Spec,
R::from_rng(&mut rng).unwrap(),
+ next_protocols.clone(),
);
let mut server_ctx = ServerD2DHandshakeContext::<C, R>::new_impl(
HandshakeImplementation::Spec,
R::from_rng(&mut rng).unwrap(),
+ &next_protocols,
);
server_ctx
.handle_handshake_message(
@@ -130,7 +146,10 @@ fn send_receive_message_seeded() {
let rng = MockRng;
let message = b"Hello World!";
let (mut init_conn_ctx, mut server_conn_ctx) =
- run_handshake_with_rng::<RustCryptoImpl<MockRng>, _>(rng);
+ run_handshake_with_rng::<RustCryptoImpl<MockRng>, _>(
+ rng,
+ vec![NextProtocol::Aes256CbcHmacSha256],
+ );
let encoded =
init_conn_ctx.encode_message_to_peer::<RustCryptoImpl<MockRng>, &[u8]>(message, None);
// Expected values extracted from the results of the current implementation.
@@ -140,10 +159,10 @@ fn send_receive_message_seeded() {
encoded,
&[
10, 64, 10, 28, 8, 1, 16, 2, 42, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 50, 4, 8, 13, 16, 1, 18, 32, 58, 224, 12, 10, 216, 38, 219, 232, 231, 222, 226, 63, 37,
- 20, 92, 208, 40, 8, 29, 98, 226, 132, 30, 61, 229, 78, 20, 182, 217, 26, 176, 77, 18,
- 32, 212, 221, 67, 39, 137, 138, 163, 222, 119, 216, 28, 176, 130, 152, 211, 63, 182,
- 45, 239, 234, 248, 148, 9, 150, 204, 117, 32, 216, 5, 126, 224, 39
+ 50, 4, 8, 13, 16, 1, 18, 32, 23, 58, 102, 24, 40, 222, 59, 212, 182, 181, 96, 44, 57,
+ 21, 93, 253, 71, 54, 67, 37, 226, 43, 104, 224, 178, 221, 219, 189, 106, 135, 175, 150,
+ 18, 32, 134, 9, 237, 41, 112, 183, 129, 198, 240, 13, 139, 66, 21, 56, 28, 100, 142,
+ 240, 155, 52, 242, 11, 211, 132, 175, 230, 15, 241, 208, 185, 15, 105
]
);
let decoded = server_conn_ctx
@@ -155,7 +174,17 @@ fn send_receive_message_seeded() {
#[test]
fn send_receive_message() {
let message = b"Hello World!";
- let (mut init_conn_ctx, mut server_conn_ctx) = run_handshake();
+ let (mut init_conn_ctx, mut server_conn_ctx) = run_cbc_handshake();
+ let encoded = init_conn_ctx.encode_message_to_peer::<CryptoProviderImpl, &[u8]>(message, None);
+ let decoded = server_conn_ctx
+ .decode_message_from_peer::<CryptoProviderImpl, &[u8]>(encoded.as_slice(), None);
+ assert_eq!(message.to_vec(), decoded.expect("Decode should be successful"));
+}
+
+#[test]
+fn send_receive_message_gcm() {
+ let message = b"Hello World!";
+ let (mut init_conn_ctx, mut server_conn_ctx) = run_gcm_handshake();
let encoded = init_conn_ctx.encode_message_to_peer::<CryptoProviderImpl, &[u8]>(message, None);
let decoded = server_conn_ctx
.decode_message_from_peer::<CryptoProviderImpl, &[u8]>(encoded.as_slice(), None);
@@ -165,7 +194,7 @@ fn send_receive_message() {
#[test]
fn send_receive_message_associated_data() {
let message = b"Hello World!";
- let (mut init_conn_ctx, mut server_conn_ctx) = run_handshake();
+ let (mut init_conn_ctx, mut server_conn_ctx) = run_cbc_handshake();
let encoded = init_conn_ctx
.encode_message_to_peer::<CryptoProviderImpl, _>(message, Some(b"associated data"));
let decoded = server_conn_ctx.decode_message_from_peer::<CryptoProviderImpl, _>(
@@ -187,7 +216,7 @@ fn send_receive_message_associated_data() {
#[test]
fn test_save_restore_session() {
- let (init_conn_ctx, server_conn_ctx) = run_handshake();
+ let (init_conn_ctx, server_conn_ctx) = run_cbc_handshake();
let init_session = init_conn_ctx.save_session();
let server_session = server_conn_ctx.save_session();
let mut init_restored_ctx =
@@ -206,7 +235,7 @@ fn test_save_restore_session() {
#[test]
fn test_save_restore_bad_session() {
- let (init_conn_ctx, server_conn_ctx) = run_handshake();
+ let (init_conn_ctx, server_conn_ctx) = run_cbc_handshake();
let init_session = init_conn_ctx.save_session();
let server_session = server_conn_ctx.save_session();
let _ =
@@ -219,7 +248,7 @@ fn test_save_restore_bad_session() {
#[test]
fn test_save_restore_bad_protocol_version() {
- let (init_conn_ctx, server_conn_ctx) = run_handshake();
+ let (init_conn_ctx, server_conn_ctx) = run_cbc_handshake();
let init_session = init_conn_ctx.save_session();
let mut server_session = server_conn_ctx.save_session();
let _ =
@@ -233,7 +262,7 @@ fn test_save_restore_bad_protocol_version() {
#[test]
fn test_unique_session() {
- let (mut init_conn_ctx, mut server_conn_ctx) = run_handshake();
+ let (mut init_conn_ctx, mut server_conn_ctx) = run_cbc_handshake();
let init_session = init_conn_ctx.get_session_unique::<CryptoProviderImpl>();
let server_session = server_conn_ctx.get_session_unique::<CryptoProviderImpl>();
let message = b"Hello World!";
@@ -249,6 +278,7 @@ fn test_unique_session() {
Aes256Key::default(),
Aes256Key::default(),
StdRng::from_entropy(),
+ NextProtocol::Aes256CbcHmacSha256,
);
assert_eq!(init_session, init_session_after);
assert_eq!(server_session, server_session_after);
diff --git a/nearby/connections/ukey2/ukey2_jni/Cargo.toml b/nearby/connections/ukey2/ukey2_jni/Cargo.toml
index 08566dd..bd615f5 100644
--- a/nearby/connections/ukey2/ukey2_jni/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_jni/Cargo.toml
@@ -11,7 +11,6 @@ workspace = true
[dependencies]
ukey2_connections = { path = "../ukey2_connections" }
-ukey2_rs = { path = "../ukey2" }
lock_adapter = {workspace = true, features = ["spin"]}
cfg-if.workspace = true
@@ -24,7 +23,6 @@ log = { workspace = true, features = ["std"] }
[features]
default = ["rustcrypto"]
-openssl = ["crypto_provider_default/openssl", "std"]
rustcrypto = ["crypto_provider_default/rustcrypto"]
boringssl = ["crypto_provider_default/boringssl"]
std = ["lock_adapter/std"]
diff --git a/nearby/connections/ukey2/ukey2_jni/java/src/jmh/java/com/google/security/cryptauth/lib/securegcm/ukey2/Ukey2Benchmark.java b/nearby/connections/ukey2/ukey2_jni/java/src/jmh/java/com/google/security/cryptauth/lib/securegcm/ukey2/Ukey2Benchmark.java
index 9cca229..537280a 100644
--- a/nearby/connections/ukey2/ukey2_jni/java/src/jmh/java/com/google/security/cryptauth/lib/securegcm/ukey2/Ukey2Benchmark.java
+++ b/nearby/connections/ukey2/ukey2_jni/java/src/jmh/java/com/google/security/cryptauth/lib/securegcm/ukey2/Ukey2Benchmark.java
@@ -16,13 +16,13 @@
package com.google.security.cryptauth.lib.securegcm.ukey2;
+import com.google.security.cryptauth.lib.securegcm.ukey2.D2DHandshakeContext.NextProtocol;
import com.google.security.cryptauth.lib.securegcm.ukey2.D2DHandshakeContext.Role;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
-import java.util.concurrent.TimeUnit;
-import java.util.Random;
-
/**
* Benchmark for encoding and decoding UKEY2 messages over the JNI, analogous to `ukey2_benches.rs`.
* The parameters and the operations also roughly matches the that of the Rust Criterion benchmark.
@@ -44,17 +44,19 @@ public class Ukey2Benchmark {
D2DConnectionContextV1 connContext;
D2DConnectionContextV1 serverConnContext;
- @Param({"10", "1024"})
+ @Param({"10", "512", "1024"})
int sizeKibs;
+ @Param NextProtocol nextProtocol;
+
byte[] inputBytes;
@Setup
public void setup() throws Exception {
D2DHandshakeContext initiatorContext =
- new D2DHandshakeContext(Role.INITIATOR);
+ new D2DHandshakeContext(Role.INITIATOR, new NextProtocol[] {nextProtocol});
D2DHandshakeContext serverContext =
- new D2DHandshakeContext(Role.RESPONDER);
+ new D2DHandshakeContext(Role.RESPONDER, new NextProtocol[] {nextProtocol});
serverContext.parseHandshakeMessage(initiatorContext.getNextHandshakeMessage());
initiatorContext.parseHandshakeMessage(serverContext.getNextHandshakeMessage());
serverContext.parseHandshakeMessage(initiatorContext.getNextHandshakeMessage());
diff --git a/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/AlertException.java b/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/AlertException.java
new file mode 100644
index 0000000..bab017d
--- /dev/null
+++ b/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/AlertException.java
@@ -0,0 +1,36 @@
+// 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
+//
+// 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.
+
+package com.google.security.cryptauth.lib.securegcm.ukey2;
+
+/**
+ * An alert exception that contains the alert message to send to the connection peer in case
+ * anything went wrong.
+ */
+public class AlertException extends Exception {
+
+ private final byte[] alertMessageToSend;
+
+ public AlertException(String message, byte[] alertMessageToSend) {
+ super(message);
+ this.alertMessageToSend = alertMessageToSend;
+ }
+
+ /**
+ * @return a message suitable for sending to other member of handshake.
+ */
+ public byte[] getAlertMessageToSend() {
+ return alertMessageToSend;
+ }
+}
diff --git a/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/D2DHandshakeContext.java b/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/D2DHandshakeContext.java
index 429295e..a2db5ee 100644
--- a/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/D2DHandshakeContext.java
+++ b/nearby/connections/ukey2/ukey2_jni/java/src/main/java/com/google/security/cryptauth/lib/securegcm/ukey2/D2DHandshakeContext.java
@@ -28,25 +28,43 @@ public class D2DHandshakeContext {
RESPONDER,
}
+ public enum NextProtocol {
+ AES_256_GCM_SIV,
+ AES_256_CBC_HMAC_SHA256,
+ }
+
private final long contextPtr;
private static native boolean is_handshake_complete(long contextPtr) throws BadHandleException;
- private static native long create_context(boolean isClient);
+ private static native long create_context(boolean isClient, int[] supported_next_protocols);
private static native byte[] get_next_handshake_message(long contextPtr)
throws BadHandleException;
private static native void parse_handshake_message(long contextPtr, byte[] message)
- throws BadHandleException, HandshakeException;
+ throws AlertException, BadHandleException, HandshakeException;
private static native byte[] get_verification_string(long contextPtr, int length)
throws BadHandleException, HandshakeException;
private static native long to_connection_context(long contextPtr) throws HandshakeException;
- public D2DHandshakeContext(@Nonnull Role role) {
- this.contextPtr = create_context(role == Role.INITIATOR);
+ public D2DHandshakeContext(@Nonnull Role role) throws HandshakeException {
+ this(role, new NextProtocol[] {NextProtocol.AES_256_CBC_HMAC_SHA256});
+ }
+
+ public D2DHandshakeContext(@Nonnull Role role, @Nonnull NextProtocol[] nextProtocols)
+ throws HandshakeException {
+ if (nextProtocols.length < 1) {
+ throw new HandshakeException("Need more than one supported next protocol!");
+ }
+ int[] nextProtocolCodes = new int[nextProtocols.length];
+ for (int i = 0; i < nextProtocols.length; i++) {
+ nextProtocolCodes[i] = nextProtocols[i].ordinal();
+ }
+
+ this.contextPtr = create_context(role == Role.INITIATOR, nextProtocolCodes);
}
/**
@@ -54,20 +72,42 @@ public class D2DHandshakeContext {
*
* @return a D2DHandshakeContext for the role of initiator in the handshake.
*/
- public static D2DHandshakeContext forInitiator() {
+ public static D2DHandshakeContext forInitiator() throws HandshakeException {
return new D2DHandshakeContext(Role.INITIATOR);
}
/**
* Convenience constructor that creates a UKEY2 D2DHandshakeContext for the initiator role.
*
+ * @param nextProtocols Specification for the supported next protocols for this initiator.
+ * @return a D2DHandshakeContext for the role of initiator in the handshake.
+ */
+ public static D2DHandshakeContext forInitiator(NextProtocol[] nextProtocols)
+ throws HandshakeException {
+ return new D2DHandshakeContext(Role.INITIATOR, nextProtocols);
+ }
+
+ /**
+ * Convenience constructor that creates a UKEY2 D2DHandshakeContext for the initiator role.
+ *
* @return a D2DHandshakeContext for the role of responder/server in the handshake.
*/
- public static D2DHandshakeContext forResponder() {
+ public static D2DHandshakeContext forResponder() throws HandshakeException {
return new D2DHandshakeContext(Role.RESPONDER);
}
/**
+ * Convenience constructor that creates a UKEY2 D2DHandshakeContext for the initiator role.
+ *
+ * @param nextProtocols Specification for the supported next protocols for this responder.
+ * @return a D2DHandshakeContext for the role of responder/server in the handshake.
+ */
+ public static D2DHandshakeContext forResponder(NextProtocol[] nextProtocols)
+ throws HandshakeException {
+ return new D2DHandshakeContext(Role.RESPONDER, nextProtocols);
+ }
+
+ /**
* Function that checks if the handshake is completed.
*
* @return true/false depending on if the handshake is complete.
@@ -90,10 +130,15 @@ public class D2DHandshakeContext {
* Parses the handshake message.
*
* @param message - handshake message from the other side.
+ * @throws AlertException - Thrown if the message is unable to be parsed.
+ * @throws BadHandleException - Thrown if the handle is no longer valid, for example after calling
+ * {@link D2DHandshakeContext#toConnectionContext()}
+ * @throws HandshakeException - Thrown if the handshake is not complete when this function is
+ * called.
*/
@Nonnull
public void parseHandshakeMessage(@Nonnull byte[] message)
- throws BadHandleException, HandshakeException {
+ throws AlertException, BadHandleException, HandshakeException {
parse_handshake_message(contextPtr, message);
}
@@ -106,7 +151,7 @@ public class D2DHandshakeContext {
* @param length - The length of the returned verification string.
* @return - The returned verification string as a byte array.
* @throws BadHandleException - Thrown if the handle is no longer valid, for example after calling
- * {@link D2DHandshakeContext#toConnectionContext}
+ * {@link D2DHandshakeContext#toConnectionContext()}
* @throws HandshakeException - Thrown if the handshake is not complete when this function is
* called.
*/
diff --git a/nearby/connections/ukey2/ukey2_jni/java/src/test/java/com/google/security/cryptauth/lib/securegcm/ukey2/TestUkey2Protocol.kt b/nearby/connections/ukey2/ukey2_jni/java/src/test/java/com/google/security/cryptauth/lib/securegcm/ukey2/TestUkey2Protocol.kt
index f770977..ba3811c 100644
--- a/nearby/connections/ukey2/ukey2_jni/java/src/test/java/com/google/security/cryptauth/lib/securegcm/ukey2/TestUkey2Protocol.kt
+++ b/nearby/connections/ukey2/ukey2_jni/java/src/test/java/com/google/security/cryptauth/lib/securegcm/ukey2/TestUkey2Protocol.kt
@@ -36,7 +36,6 @@ class TestUkey2Protocol {
@Test
fun testHandshake() {
val initiatorContext = D2DHandshakeContext(D2DHandshakeContext.Role.INITIATOR)
- println("got initial context")
assertFalse(initiatorContext.isHandshakeComplete)
val serverContext = D2DHandshakeContext(D2DHandshakeContext.Role.RESPONDER)
assertFalse(serverContext.isHandshakeComplete)
@@ -164,4 +163,75 @@ class TestUkey2Protocol {
assertArrayEquals(
serverContext.getVerificationString(32), initiatorContext.getVerificationString(32))
}
+
+ @Test
+ fun throwsAlertExceptionWhenBadMessage() {
+ val serverContext = D2DHandshakeContext(D2DHandshakeContext.Role.RESPONDER)
+ val exception =
+ assertThrows<AlertException> {
+ serverContext.parseHandshakeMessage("Hello UKEY2".toByteArray())
+ }
+ assert(exception.alertMessageToSend.isNotEmpty())
+ }
+
+ @Test
+ fun testGcm() {
+ val initiatorContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.INITIATOR,
+ arrayOf(D2DHandshakeContext.NextProtocol.AES_256_GCM_SIV))
+ val serverContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.RESPONDER,
+ arrayOf(D2DHandshakeContext.NextProtocol.AES_256_GCM_SIV))
+ assertDoesNotThrow {
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ initiatorContext.parseHandshakeMessage(serverContext.nextHandshakeMessage)
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ }
+ assert(serverContext.isHandshakeComplete)
+ assert(initiatorContext.isHandshakeComplete)
+ }
+
+ @Test
+ fun testGcmServer_cbcClient() {
+ val initiatorContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.INITIATOR,
+ arrayOf(D2DHandshakeContext.NextProtocol.AES_256_CBC_HMAC_SHA256))
+ val serverContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.RESPONDER,
+ arrayOf(
+ D2DHandshakeContext.NextProtocol.AES_256_CBC_HMAC_SHA256,
+ D2DHandshakeContext.NextProtocol.AES_256_GCM_SIV))
+ assertDoesNotThrow {
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ initiatorContext.parseHandshakeMessage(serverContext.nextHandshakeMessage)
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ }
+ assert(serverContext.isHandshakeComplete)
+ assert(initiatorContext.isHandshakeComplete)
+ }
+
+ @Test
+ fun testGcmClient_cbcServer() {
+ val initiatorContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.INITIATOR,
+ arrayOf(
+ D2DHandshakeContext.NextProtocol.AES_256_CBC_HMAC_SHA256,
+ D2DHandshakeContext.NextProtocol.AES_256_GCM_SIV))
+ val serverContext =
+ D2DHandshakeContext(
+ D2DHandshakeContext.Role.RESPONDER,
+ arrayOf(D2DHandshakeContext.NextProtocol.AES_256_CBC_HMAC_SHA256))
+ assertDoesNotThrow {
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ initiatorContext.parseHandshakeMessage(serverContext.nextHandshakeMessage)
+ serverContext.parseHandshakeMessage(initiatorContext.nextHandshakeMessage)
+ }
+ assert(serverContext.isHandshakeComplete)
+ assert(initiatorContext.isHandshakeComplete)
+ }
}
diff --git a/nearby/connections/ukey2/ukey2_jni/src/lib.rs b/nearby/connections/ukey2/ukey2_jni/src/lib.rs
index c500ddd..24bb607 100644
--- a/nearby/connections/ukey2/ukey2_jni/src/lib.rs
+++ b/nearby/connections/ukey2/ukey2_jni/src/lib.rs
@@ -18,25 +18,24 @@
//TODO: remove this and fix instances of unwrap/panic
#![allow(clippy::unwrap_used, clippy::panic)]
-use std::collections::HashMap;
-
-use jni::objects::JClass;
-use jni::sys::{jboolean, jbyteArray, jint, jlong, JNI_TRUE};
+use jni::objects::{JClass, JObject, JThrowable};
+use jni::sys::{jboolean, jbyteArray, jint, jintArray, jlong, JNI_TRUE};
use jni::JNIEnv;
use lazy_static::lazy_static;
use lock_adapter::NoPoisonMutex;
use rand::Rng;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
+use std::collections::HashMap;
#[cfg(not(feature = "std"))]
use lock_adapter::spin::Mutex;
#[cfg(feature = "std")]
-use lock_adapter::std::Mutex;
+use lock_adapter::stdlib::Mutex;
use ukey2_connections::{
D2DConnectionContextV1, D2DHandshakeContext, DecodeError, DeserializeError, HandleMessageError,
- HandshakeError, HandshakeImplementation, InitiatorD2DHandshakeContext,
+ HandshakeError, HandshakeImplementation, InitiatorD2DHandshakeContext, NextProtocol,
ServerD2DHandshakeContext,
};
@@ -110,20 +109,56 @@ pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2
}
/// Creates a new handshake context
+// Safety:
+// - Valid pointer: We know the message pointer is safe as it is coming directly from the JVM.
+// - This pointer is nullable, but we null-check and default to AES-CBC-256_HMAC-SHA256 otherwise.
+// - Lifetime - the jintArray passed in here is consumed immediately and is copied into a Rust array,
+// so this data does not outlive this frame.
+// - Aliasing - there is no other JObject representing this as it is only used in one place.
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2DHandshakeContext_create_1context(
- _: JNIEnv,
+ env: JNIEnv,
_: JClass,
is_client: jboolean,
+ next_protocols: jintArray,
) -> jlong {
+ let next_protocols = if next_protocols.is_null() {
+ vec![NextProtocol::Aes256CbcHmacSha256]
+ } else {
+ let next_protocols_len =
+ env.get_array_length(next_protocols).expect("Array should be valid!");
+ let mut next_protocol_buf =
+ vec![0; usize::try_from(next_protocols_len).expect("len should be valid usize!")];
+ env.get_int_array_region(next_protocols, 0, &mut next_protocol_buf)
+ .expect("Should've extracted next protocols!");
+ next_protocol_buf
+ .iter()
+ .map(|p| match *p {
+ 0 => NextProtocol::Aes256CbcHmacSha256,
+ 1 => NextProtocol::Aes256GcmSiv,
+ _ => {
+ env.throw_new(
+ "com/google/security/cryptauth/lib/securegcm/ukey2/HandshakeException",
+ "Unsupported next protocols selected! Supported: [0, 1]",
+ )
+ .expect("failed to find error class");
+ unreachable!()
+ }
+ })
+ .collect()
+ };
+
if is_client == JNI_TRUE {
let client_obj = Box::new(InitiatorD2DHandshakeContext::<CryptoProvider>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ next_protocols,
));
insert_handshake_handle(client_obj) as jlong
} else {
let server_obj = Box::new(ServerD2DHandshakeContext::<CryptoProvider>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ &next_protocols,
));
insert_handshake_handle(server_obj) as jlong
}
@@ -172,16 +207,42 @@ pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2
};
if let Err(e) = result {
if !env.exception_check().unwrap() {
- env.throw_new(
- "com/google/security/cryptauth/lib/securegcm/ukey2/HandshakeException",
+ let msg =
match e {
JniError::BadHandle => "Bad handle",
JniError::DecodeError(_) => "Unable to decode message",
- JniError::HandleMessageError(_) => "Unable to handle message",
+ JniError::HandleMessageError(hme) => match hme {
+ HandleMessageError::InvalidState | HandleMessageError::BadMessage => {
+ "Unable to handle message"
+ }
+ HandleMessageError::ErrorMessage(error_msg) => {
+ let exception: JThrowable = env.new_object(
+ "com/google/security/cryptauth/lib/securegcm/ukey2/AlertException",
+ "(Ljava/lang/String;[B)V",
+ &[
+ env
+ .new_string("Failed to handle message, sending alert")
+ .expect("valid str message for alert exception")
+ .into(),
+ unsafe { JObject::from_raw(env
+ .byte_array_from_slice(&error_msg)
+ .expect("valid byte array for alert exception")) }
+ .into(),
+ ],
+ ).expect("Did not successfully create AlertException").into();
+ env.throw(exception).expect("Throw alert exception");
+ ""
+ }
+ },
JniError::HandshakeError(_) => "Handshake incomplete",
- },
- )
- .expect("failed to find error class");
+ };
+ if !env.exception_check().unwrap() {
+ env.throw_new(
+ "com/google/security/cryptauth/lib/securegcm/ukey2/HandshakeException",
+ msg,
+ )
+ .expect("failed to find error class");
+ }
}
}
}
@@ -271,23 +332,19 @@ pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2
// We create the empty array here so we don't run into issues requesting a new byte array from
// the JNI env while an exception is being thrown.
let empty_array = env.new_byte_array(0).unwrap();
- let result = if let Some(ctx) =
- CONNECTION_HANDLE_MAPPING.lock().get_mut(&(context_handle as u64))
- {
- Ok(ctx.encode_message_to_peer::<CryptoProvider, _>(
- env.convert_byte_array(payload).unwrap().as_slice(),
- if associated_data.is_null() {
- None
- } else {
- Some(
- env.convert_byte_array(associated_data)
- .unwrap(),
- )
- },
- ))
- } else {
- Err(JniError::BadHandle)
- };
+ let result =
+ if let Some(ctx) = CONNECTION_HANDLE_MAPPING.lock().get_mut(&(context_handle as u64)) {
+ Ok(ctx.encode_message_to_peer::<CryptoProvider, _>(
+ env.convert_byte_array(payload).unwrap().as_slice(),
+ if associated_data.is_null() {
+ None
+ } else {
+ Some(env.convert_byte_array(associated_data).unwrap())
+ },
+ ))
+ } else {
+ Err(JniError::BadHandle)
+ };
if let Ok(ret_vec) = result {
env.byte_array_from_slice(ret_vec.as_slice()).expect("unable to create jByteArray")
} else {
@@ -312,24 +369,20 @@ pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2
associated_data: jbyteArray,
) -> jbyteArray {
let empty_array = env.new_byte_array(0).unwrap();
- let result = if let Some(ctx) =
- CONNECTION_HANDLE_MAPPING.lock().get_mut(&(context_handle as u64))
- {
- ctx.decode_message_from_peer::<CryptoProvider, _>(
- env.convert_byte_array(message).unwrap().as_slice(),
- if associated_data.is_null() {
- None
- } else {
- Some(
- env.convert_byte_array(associated_data)
- .unwrap(),
- )
- },
- )
- .map_err(JniError::DecodeError)
- } else {
- Err(JniError::BadHandle)
- };
+ let result =
+ if let Some(ctx) = CONNECTION_HANDLE_MAPPING.lock().get_mut(&(context_handle as u64)) {
+ ctx.decode_message_from_peer::<CryptoProvider, _>(
+ env.convert_byte_array(message).unwrap().as_slice(),
+ if associated_data.is_null() {
+ None
+ } else {
+ Some(env.convert_byte_array(associated_data).unwrap())
+ },
+ )
+ .map_err(JniError::DecodeError)
+ } else {
+ Err(JniError::BadHandle)
+ };
if let Ok(message) = result {
env.byte_array_from_slice(message.as_slice()).expect("unable to create jByteArray")
} else {
@@ -409,9 +462,7 @@ pub extern "system" fn Java_com_google_security_cryptauth_lib_securegcm_ukey2_D2
_: JClass,
session_info: jbyteArray,
) -> jlong {
- let session_info_rust = env
- .convert_byte_array(session_info)
- .expect("bad session_info data");
+ let session_info_rust = env.convert_byte_array(session_info).expect("bad session_info data");
let ctx =
D2DConnectionContextV1::from_saved_session::<CryptoProvider>(session_info_rust.as_slice());
if ctx.is_err() {
diff --git a/nearby/connections/ukey2/ukey2_proto/proto/securegcm.proto b/nearby/connections/ukey2/ukey2_proto/proto/securegcm.proto
index 40ac604..d5f2b14 100644
--- a/nearby/connections/ukey2/ukey2_proto/proto/securegcm.proto
+++ b/nearby/connections/ukey2/ukey2_proto/proto/securegcm.proto
@@ -21,216 +21,6 @@ option java_package = "com.google.security.cryptauth.lib.securegcm";
option java_outer_classname = "SecureGcmProto";
option objc_class_prefix = "SGCM";
-// Message used only during enrollment
-// Field numbers should be kept in sync with DeviceInfo in:
-// java/com/google/security/cryptauth/backend/services/common/common.proto
-message GcmDeviceInfo {
- // This field's name does not match the one in DeviceInfo for legacy reasons.
- // Consider using long_device_id and device_type instead when enrolling
- // non-android devices.
- optional fixed64 android_device_id = 1;
-
- // Used for device_address of DeviceInfo field 2, but for GCM capable devices.
- optional bytes gcm_registration_id = 102;
-
- // Used for device_address of DeviceInfo field 2, but for iOS devices.
- optional bytes apn_registration_id = 202;
-
- // Does the user have notifications enabled for the given device address.
- optional bool notification_enabled = 203 [default = true];
-
- // Used for device_address of DeviceInfo field 2, a Bluetooth Mac address for
- // the device (e.g., to be used with EasyUnlock)
- optional string bluetooth_mac_address = 302;
-
- // SHA-256 hash of the device master key (from the key exchange).
- // Differs from DeviceInfo field 3, which contains the actual master key.
- optional bytes device_master_key_hash = 103;
-
- // A SecureMessage.EcP256PublicKey
- required bytes user_public_key = 4;
-
- // device's model name
- // (e.g., an android.os.Build.MODEL or UIDevice.model)
- optional string device_model = 7;
-
- // device's locale
- optional string locale = 8;
-
- // The handle for user_public_key (and implicitly, a master key)
- optional bytes key_handle = 9;
-
- // The initial counter value for the device, sent by the device
- optional int64 counter = 12 [default = 0];
-
- // The Operating System version on the device
- // (e.g., an android.os.Build.DISPLAY or UIDevice.systemVersion)
- optional string device_os_version = 13;
-
- // The Operating System version number on the device
- // (e.g., an android.os.Build.VERSION.SDK_INT)
- optional int64 device_os_version_code = 14;
-
- // The Operating System release on the device
- // (e.g., an android.os.Build.VERSION.RELEASE)
- optional string device_os_release = 15;
-
- // The Operating System codename on the device
- // (e.g., an android.os.Build.VERSION.CODENAME or UIDevice.systemName)
- optional string device_os_codename = 16;
-
- // The software version running on the device
- // (e.g., Authenticator app version string)
- optional string device_software_version = 17;
-
- // The software version number running on the device
- // (e.g., Authenticator app version code)
- optional int64 device_software_version_code = 18;
-
- // Software package information if applicable
- // (e.g., com.google.android.apps.authenticator2)
- optional string device_software_package = 19;
-
- // Size of the display in thousandths of an inch (e.g., 7000 mils = 7 in)
- optional int32 device_display_diagonal_mils = 22;
-
- // For Authzen capable devices, their Authzen protocol version
- optional int32 device_authzen_version = 24;
-
- // Not all devices have device identifiers that fit in 64 bits.
- optional bytes long_device_id = 29;
-
- // The device manufacturer name
- // (e.g., android.os.Build.MANUFACTURER)
- optional string device_manufacturer = 31;
-
- // Used to indicate which type of device this is.
- optional DeviceType device_type = 32 [default = ANDROID];
-
- // Fields corresponding to screenlock type/features and hardware features
- // should be numbered in the 400 range.
-
- // Is this device using a secure screenlock (e.g., pattern or pin unlock)
- optional bool using_secure_screenlock = 400 [default = false];
-
- // Is auto-unlocking the screenlock (e.g., when at "home") supported?
- optional bool auto_unlock_screenlock_supported = 401 [default = false];
-
- // Is auto-unlocking the screenlock (e.g., when at "home") enabled?
- optional bool auto_unlock_screenlock_enabled = 402 [default = false];
-
- // Does the device have a Bluetooth (classic) radio?
- optional bool bluetooth_radio_supported = 403 [default = false];
-
- // Is the Bluetooth (classic) radio on?
- optional bool bluetooth_radio_enabled = 404 [default = false];
-
- // Does the device hardware support a mobile data connection?
- optional bool mobile_data_supported = 405 [default = false];
-
- // Does the device support tethering?
- optional bool tethering_supported = 406 [default = false];
-
- // Does the device have a BLE radio?
- optional bool ble_radio_supported = 407 [default = false];
-
- // Is the device a "Pixel Experience" Android device?
- optional bool pixel_experience = 408 [default = false];
-
- // Is the device running in the ARC++ container on a chromebook?
- optional bool arc_plus_plus = 409 [default = false];
-
- // Is the value set in |using_secure_screenlock| reliable? On some Android
- // devices, the platform API to get the screenlock state is not trustworthy.
- // See b/32212161.
- optional bool is_screenlock_state_flaky = 410 [default = false];
-
- // A list of multi-device software features supported by the device.
- repeated SoftwareFeature supported_software_features = 411;
-
- // A list of multi-device software features currently enabled (active) on the
- // device.
- repeated SoftwareFeature enabled_software_features = 412;
-
- // The enrollment session id this is sent with
- optional bytes enrollment_session_id = 1000;
-
- // A copy of the user's OAuth token
- optional string oauth_token = 1001;
-}
-
-// This enum is used by iOS devices as values for device_display_diagonal_mils
-// in GcmDeviceInfo. There is no good way to calculate it on those devices.
-enum AppleDeviceDiagonalMils {
- // This is the mils diagonal on an iPhone 5.
- APPLE_PHONE = 4000;
- // This is the mils diagonal on an iPad mini.
- APPLE_PAD = 7900;
-}
-
-// This should be kept in sync with DeviceType in:
-// java/com/google/security/cryptauth/backend/services/common/common_enums.proto
-enum DeviceType {
- UNKNOWN = 0;
- ANDROID = 1;
- CHROME = 2;
- IOS = 3;
- BROWSER = 4;
- OSX = 5;
-}
-
-// MultiDevice features which may be supported and enabled on a device. See
-enum SoftwareFeature {
- UNKNOWN_FEATURE = 0;
- BETTER_TOGETHER_HOST = 1;
- BETTER_TOGETHER_CLIENT = 2;
- EASY_UNLOCK_HOST = 3;
- EASY_UNLOCK_CLIENT = 4;
- MAGIC_TETHER_HOST = 5;
- MAGIC_TETHER_CLIENT = 6;
- SMS_CONNECT_HOST = 7;
- SMS_CONNECT_CLIENT = 8;
-}
-
-// A list of "reasons" that can be provided for calling server-side APIs.
-// This is particularly important for calls that can be triggered by different
-// kinds of events. Please try to keep reasons as generic as possible, so that
-// codes can be re-used by various callers in a sensible fashion.
-enum InvocationReason {
- REASON_UNKNOWN = 0;
- // First run of the software package invoking this call
- REASON_INITIALIZATION = 1;
- // Ordinary periodic actions (e.g. monthly master key rotation)
- REASON_PERIODIC = 2;
- // Slow-cycle periodic action (e.g. yearly keypair rotation???)
- REASON_SLOW_PERIODIC = 3;
- // Fast-cycle periodic action (e.g. daily sync for Smart Lock users)
- REASON_FAST_PERIODIC = 4;
- // Expired state (e.g. expired credentials, or cached entries) was detected
- REASON_EXPIRATION = 5;
- // An unexpected protocol failure occurred (so attempting to repair state)
- REASON_FAILURE_RECOVERY = 6;
- // A new account has been added to the device
- REASON_NEW_ACCOUNT = 7;
- // An existing account on the device has been changed
- REASON_CHANGED_ACCOUNT = 8;
- // The user toggled the state of a feature (e.g. Smart Lock enabled via BT)
- REASON_FEATURE_TOGGLED = 9;
- // A "push" from the server caused this action (e.g. a sync tickle)
- REASON_SERVER_INITIATED = 10;
- // A local address change triggered this (e.g. GCM registration id changed)
- REASON_ADDRESS_CHANGE = 11;
- // A software update has triggered this
- REASON_SOFTWARE_UPDATE = 12;
- // A manual action by the user triggered this (e.g. commands sent via adb)
- REASON_MANUAL = 13;
- // A custom key has been invalidated on the device (e.g. screen lock is
- // disabled).
- REASON_CUSTOM_KEY_INVALIDATION = 14;
- // Periodic action triggered by auth_proximity
- REASON_PROXIMITY_PERIODIC = 15;
-}
-
enum Type {
ENROLLMENT = 0;
TICKLE = 1;
@@ -284,25 +74,3 @@ message GcmMetadata {
required Type type = 1;
optional int32 version = 2 [default = 0];
}
-
-message Tickle {
- // Time after which this tickle should expire
- optional fixed64 expiry_time = 1;
-}
-
-message LoginNotificationInfo {
- // Time at which the server received the login notification request.
- optional fixed64 creation_time = 2;
-
- // Must correspond to user_id in LoginNotificationRequest, if set.
- optional string email = 3;
-
- // Host where the user's credentials were used to login, if meaningful.
- optional string host = 4;
-
- // Location from where the user's credentials were used, if meaningful.
- optional string source = 5;
-
- // Type of login, e.g. ssh, gnome-screensaver, or web.
- optional string event_type = 6;
-}
diff --git a/nearby/connections/ukey2/ukey2_proto/proto/securemessage.proto b/nearby/connections/ukey2/ukey2_proto/proto/securemessage.proto
index 7a19739..bbaa5d5 100644
--- a/nearby/connections/ukey2/ukey2_proto/proto/securemessage.proto
+++ b/nearby/connections/ukey2/ukey2_proto/proto/securemessage.proto
@@ -72,18 +72,6 @@ message HeaderAndBody {
required bytes body = 2;
}
-// Must be kept wire-format compatible with HeaderAndBody. Provides the
-// SecureMessage code with a consistent wire-format representation that
-// remains stable irrespective of protobuf implementation choices. This
-// low-level representation of a HeaderAndBody should not be used by
-// any code outside of the SecureMessage library implementation/tests.
-message HeaderAndBodyInternal {
- // A raw (wire-format) byte encoding of a Header, suitable for hashing
- required bytes header = 1;
- // Payload data
- required bytes body = 2;
-}
-
// -------
// The remainder of the messages defined here are provided only for
// convenience. They are not needed for SecureMessage proper, but are
diff --git a/nearby/connections/ukey2/ukey2_proto/proto/ukey.proto b/nearby/connections/ukey2/ukey2_proto/proto/ukey.proto
index 1edec1f..450541c 100644
--- a/nearby/connections/ukey2/ukey2_proto/proto/ukey.proto
+++ b/nearby/connections/ukey2/ukey2_proto/proto/ukey.proto
@@ -87,8 +87,8 @@ message Ukey2ClientInit {
// Next protocol that the client wants to speak.
optional string next_protocol = 4;
- // Other next protocols the client can speak.
- repeated string other_next_protocols = 5;
+ // Next protocols the client can speak.
+ repeated string next_protocols = 5;
}
message Ukey2ServerInit {
diff --git a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/device_to_device_messages.rs b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/device_to_device_messages.rs
index 71c247b..fb44c51 100644
--- a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/device_to_device_messages.rs
+++ b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/device_to_device_messages.rs
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// 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.
diff --git a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securegcm.rs b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securegcm.rs
index 70a927d..37fda69 100644
--- a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securegcm.rs
+++ b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securegcm.rs
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// 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.
@@ -41,1562 +41,6 @@
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
#[derive(PartialEq,Clone,Default,Debug)]
-// @@protoc_insertion_point(message:securegcm.GcmDeviceInfo)
-pub struct GcmDeviceInfo {
- // message fields
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.android_device_id)
- pub android_device_id: ::std::option::Option<u64>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.gcm_registration_id)
- pub gcm_registration_id: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.apn_registration_id)
- pub apn_registration_id: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.notification_enabled)
- pub notification_enabled: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.bluetooth_mac_address)
- pub bluetooth_mac_address: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_master_key_hash)
- pub device_master_key_hash: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.user_public_key)
- pub user_public_key: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_model)
- pub device_model: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.locale)
- pub locale: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.key_handle)
- pub key_handle: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.counter)
- pub counter: ::std::option::Option<i64>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_os_version)
- pub device_os_version: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_os_version_code)
- pub device_os_version_code: ::std::option::Option<i64>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_os_release)
- pub device_os_release: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_os_codename)
- pub device_os_codename: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_software_version)
- pub device_software_version: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_software_version_code)
- pub device_software_version_code: ::std::option::Option<i64>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_software_package)
- pub device_software_package: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_display_diagonal_mils)
- pub device_display_diagonal_mils: ::std::option::Option<i32>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_authzen_version)
- pub device_authzen_version: ::std::option::Option<i32>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.long_device_id)
- pub long_device_id: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_manufacturer)
- pub device_manufacturer: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.device_type)
- pub device_type: ::std::option::Option<::protobuf::EnumOrUnknown<DeviceType>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.using_secure_screenlock)
- pub using_secure_screenlock: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.auto_unlock_screenlock_supported)
- pub auto_unlock_screenlock_supported: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.auto_unlock_screenlock_enabled)
- pub auto_unlock_screenlock_enabled: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.bluetooth_radio_supported)
- pub bluetooth_radio_supported: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.bluetooth_radio_enabled)
- pub bluetooth_radio_enabled: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.mobile_data_supported)
- pub mobile_data_supported: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.tethering_supported)
- pub tethering_supported: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.ble_radio_supported)
- pub ble_radio_supported: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.pixel_experience)
- pub pixel_experience: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.arc_plus_plus)
- pub arc_plus_plus: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.is_screenlock_state_flaky)
- pub is_screenlock_state_flaky: ::std::option::Option<bool>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.supported_software_features)
- pub supported_software_features: ::std::vec::Vec<::protobuf::EnumOrUnknown<SoftwareFeature>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.enabled_software_features)
- pub enabled_software_features: ::std::vec::Vec<::protobuf::EnumOrUnknown<SoftwareFeature>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.enrollment_session_id)
- pub enrollment_session_id: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securegcm.GcmDeviceInfo.oauth_token)
- pub oauth_token: ::std::option::Option<::std::string::String>,
- // special fields
- // @@protoc_insertion_point(special_field:securegcm.GcmDeviceInfo.special_fields)
- pub special_fields: ::protobuf::SpecialFields,
-}
-
-impl<'a> ::std::default::Default for &'a GcmDeviceInfo {
- fn default() -> &'a GcmDeviceInfo {
- <GcmDeviceInfo as ::protobuf::Message>::default_instance()
- }
-}
-
-impl GcmDeviceInfo {
- pub fn new() -> GcmDeviceInfo {
- ::std::default::Default::default()
- }
-
- // optional fixed64 android_device_id = 1;
-
- pub fn android_device_id(&self) -> u64 {
- self.android_device_id.unwrap_or(0)
- }
-
- pub fn clear_android_device_id(&mut self) {
- self.android_device_id = ::std::option::Option::None;
- }
-
- pub fn has_android_device_id(&self) -> bool {
- self.android_device_id.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_android_device_id(&mut self, v: u64) {
- self.android_device_id = ::std::option::Option::Some(v);
- }
-
- // optional bytes gcm_registration_id = 102;
-
- pub fn gcm_registration_id(&self) -> &[u8] {
- match self.gcm_registration_id.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_gcm_registration_id(&mut self) {
- self.gcm_registration_id = ::std::option::Option::None;
- }
-
- pub fn has_gcm_registration_id(&self) -> bool {
- self.gcm_registration_id.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_gcm_registration_id(&mut self, v: ::std::vec::Vec<u8>) {
- self.gcm_registration_id = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_gcm_registration_id(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.gcm_registration_id.is_none() {
- self.gcm_registration_id = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.gcm_registration_id.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_gcm_registration_id(&mut self) -> ::std::vec::Vec<u8> {
- self.gcm_registration_id.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional bytes apn_registration_id = 202;
-
- pub fn apn_registration_id(&self) -> &[u8] {
- match self.apn_registration_id.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_apn_registration_id(&mut self) {
- self.apn_registration_id = ::std::option::Option::None;
- }
-
- pub fn has_apn_registration_id(&self) -> bool {
- self.apn_registration_id.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_apn_registration_id(&mut self, v: ::std::vec::Vec<u8>) {
- self.apn_registration_id = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_apn_registration_id(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.apn_registration_id.is_none() {
- self.apn_registration_id = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.apn_registration_id.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_apn_registration_id(&mut self) -> ::std::vec::Vec<u8> {
- self.apn_registration_id.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional bool notification_enabled = 203;
-
- pub fn notification_enabled(&self) -> bool {
- self.notification_enabled.unwrap_or(true)
- }
-
- pub fn clear_notification_enabled(&mut self) {
- self.notification_enabled = ::std::option::Option::None;
- }
-
- pub fn has_notification_enabled(&self) -> bool {
- self.notification_enabled.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_notification_enabled(&mut self, v: bool) {
- self.notification_enabled = ::std::option::Option::Some(v);
- }
-
- // optional string bluetooth_mac_address = 302;
-
- pub fn bluetooth_mac_address(&self) -> &str {
- match self.bluetooth_mac_address.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_bluetooth_mac_address(&mut self) {
- self.bluetooth_mac_address = ::std::option::Option::None;
- }
-
- pub fn has_bluetooth_mac_address(&self) -> bool {
- self.bluetooth_mac_address.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_bluetooth_mac_address(&mut self, v: ::std::string::String) {
- self.bluetooth_mac_address = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_bluetooth_mac_address(&mut self) -> &mut ::std::string::String {
- if self.bluetooth_mac_address.is_none() {
- self.bluetooth_mac_address = ::std::option::Option::Some(::std::string::String::new());
- }
- self.bluetooth_mac_address.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_bluetooth_mac_address(&mut self) -> ::std::string::String {
- self.bluetooth_mac_address.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional bytes device_master_key_hash = 103;
-
- pub fn device_master_key_hash(&self) -> &[u8] {
- match self.device_master_key_hash.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_device_master_key_hash(&mut self) {
- self.device_master_key_hash = ::std::option::Option::None;
- }
-
- pub fn has_device_master_key_hash(&self) -> bool {
- self.device_master_key_hash.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_master_key_hash(&mut self, v: ::std::vec::Vec<u8>) {
- self.device_master_key_hash = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_master_key_hash(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.device_master_key_hash.is_none() {
- self.device_master_key_hash = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.device_master_key_hash.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_master_key_hash(&mut self) -> ::std::vec::Vec<u8> {
- self.device_master_key_hash.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // required bytes user_public_key = 4;
-
- pub fn user_public_key(&self) -> &[u8] {
- match self.user_public_key.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_user_public_key(&mut self) {
- self.user_public_key = ::std::option::Option::None;
- }
-
- pub fn has_user_public_key(&self) -> bool {
- self.user_public_key.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_user_public_key(&mut self, v: ::std::vec::Vec<u8>) {
- self.user_public_key = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_user_public_key(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.user_public_key.is_none() {
- self.user_public_key = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.user_public_key.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_user_public_key(&mut self) -> ::std::vec::Vec<u8> {
- self.user_public_key.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional string device_model = 7;
-
- pub fn device_model(&self) -> &str {
- match self.device_model.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_model(&mut self) {
- self.device_model = ::std::option::Option::None;
- }
-
- pub fn has_device_model(&self) -> bool {
- self.device_model.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_model(&mut self, v: ::std::string::String) {
- self.device_model = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_model(&mut self) -> &mut ::std::string::String {
- if self.device_model.is_none() {
- self.device_model = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_model.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_model(&mut self) -> ::std::string::String {
- self.device_model.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string locale = 8;
-
- pub fn locale(&self) -> &str {
- match self.locale.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_locale(&mut self) {
- self.locale = ::std::option::Option::None;
- }
-
- pub fn has_locale(&self) -> bool {
- self.locale.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_locale(&mut self, v: ::std::string::String) {
- self.locale = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_locale(&mut self) -> &mut ::std::string::String {
- if self.locale.is_none() {
- self.locale = ::std::option::Option::Some(::std::string::String::new());
- }
- self.locale.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_locale(&mut self) -> ::std::string::String {
- self.locale.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional bytes key_handle = 9;
-
- pub fn key_handle(&self) -> &[u8] {
- match self.key_handle.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_key_handle(&mut self) {
- self.key_handle = ::std::option::Option::None;
- }
-
- pub fn has_key_handle(&self) -> bool {
- self.key_handle.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_key_handle(&mut self, v: ::std::vec::Vec<u8>) {
- self.key_handle = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_key_handle(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.key_handle.is_none() {
- self.key_handle = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.key_handle.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_key_handle(&mut self) -> ::std::vec::Vec<u8> {
- self.key_handle.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional int64 counter = 12;
-
- pub fn counter(&self) -> i64 {
- self.counter.unwrap_or(0i64)
- }
-
- pub fn clear_counter(&mut self) {
- self.counter = ::std::option::Option::None;
- }
-
- pub fn has_counter(&self) -> bool {
- self.counter.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_counter(&mut self, v: i64) {
- self.counter = ::std::option::Option::Some(v);
- }
-
- // optional string device_os_version = 13;
-
- pub fn device_os_version(&self) -> &str {
- match self.device_os_version.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_os_version(&mut self) {
- self.device_os_version = ::std::option::Option::None;
- }
-
- pub fn has_device_os_version(&self) -> bool {
- self.device_os_version.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_os_version(&mut self, v: ::std::string::String) {
- self.device_os_version = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_os_version(&mut self) -> &mut ::std::string::String {
- if self.device_os_version.is_none() {
- self.device_os_version = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_os_version.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_os_version(&mut self) -> ::std::string::String {
- self.device_os_version.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional int64 device_os_version_code = 14;
-
- pub fn device_os_version_code(&self) -> i64 {
- self.device_os_version_code.unwrap_or(0)
- }
-
- pub fn clear_device_os_version_code(&mut self) {
- self.device_os_version_code = ::std::option::Option::None;
- }
-
- pub fn has_device_os_version_code(&self) -> bool {
- self.device_os_version_code.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_os_version_code(&mut self, v: i64) {
- self.device_os_version_code = ::std::option::Option::Some(v);
- }
-
- // optional string device_os_release = 15;
-
- pub fn device_os_release(&self) -> &str {
- match self.device_os_release.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_os_release(&mut self) {
- self.device_os_release = ::std::option::Option::None;
- }
-
- pub fn has_device_os_release(&self) -> bool {
- self.device_os_release.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_os_release(&mut self, v: ::std::string::String) {
- self.device_os_release = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_os_release(&mut self) -> &mut ::std::string::String {
- if self.device_os_release.is_none() {
- self.device_os_release = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_os_release.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_os_release(&mut self) -> ::std::string::String {
- self.device_os_release.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string device_os_codename = 16;
-
- pub fn device_os_codename(&self) -> &str {
- match self.device_os_codename.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_os_codename(&mut self) {
- self.device_os_codename = ::std::option::Option::None;
- }
-
- pub fn has_device_os_codename(&self) -> bool {
- self.device_os_codename.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_os_codename(&mut self, v: ::std::string::String) {
- self.device_os_codename = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_os_codename(&mut self) -> &mut ::std::string::String {
- if self.device_os_codename.is_none() {
- self.device_os_codename = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_os_codename.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_os_codename(&mut self) -> ::std::string::String {
- self.device_os_codename.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string device_software_version = 17;
-
- pub fn device_software_version(&self) -> &str {
- match self.device_software_version.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_software_version(&mut self) {
- self.device_software_version = ::std::option::Option::None;
- }
-
- pub fn has_device_software_version(&self) -> bool {
- self.device_software_version.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_software_version(&mut self, v: ::std::string::String) {
- self.device_software_version = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_software_version(&mut self) -> &mut ::std::string::String {
- if self.device_software_version.is_none() {
- self.device_software_version = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_software_version.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_software_version(&mut self) -> ::std::string::String {
- self.device_software_version.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional int64 device_software_version_code = 18;
-
- pub fn device_software_version_code(&self) -> i64 {
- self.device_software_version_code.unwrap_or(0)
- }
-
- pub fn clear_device_software_version_code(&mut self) {
- self.device_software_version_code = ::std::option::Option::None;
- }
-
- pub fn has_device_software_version_code(&self) -> bool {
- self.device_software_version_code.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_software_version_code(&mut self, v: i64) {
- self.device_software_version_code = ::std::option::Option::Some(v);
- }
-
- // optional string device_software_package = 19;
-
- pub fn device_software_package(&self) -> &str {
- match self.device_software_package.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_software_package(&mut self) {
- self.device_software_package = ::std::option::Option::None;
- }
-
- pub fn has_device_software_package(&self) -> bool {
- self.device_software_package.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_software_package(&mut self, v: ::std::string::String) {
- self.device_software_package = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_software_package(&mut self) -> &mut ::std::string::String {
- if self.device_software_package.is_none() {
- self.device_software_package = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_software_package.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_software_package(&mut self) -> ::std::string::String {
- self.device_software_package.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional int32 device_display_diagonal_mils = 22;
-
- pub fn device_display_diagonal_mils(&self) -> i32 {
- self.device_display_diagonal_mils.unwrap_or(0)
- }
-
- pub fn clear_device_display_diagonal_mils(&mut self) {
- self.device_display_diagonal_mils = ::std::option::Option::None;
- }
-
- pub fn has_device_display_diagonal_mils(&self) -> bool {
- self.device_display_diagonal_mils.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_display_diagonal_mils(&mut self, v: i32) {
- self.device_display_diagonal_mils = ::std::option::Option::Some(v);
- }
-
- // optional int32 device_authzen_version = 24;
-
- pub fn device_authzen_version(&self) -> i32 {
- self.device_authzen_version.unwrap_or(0)
- }
-
- pub fn clear_device_authzen_version(&mut self) {
- self.device_authzen_version = ::std::option::Option::None;
- }
-
- pub fn has_device_authzen_version(&self) -> bool {
- self.device_authzen_version.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_authzen_version(&mut self, v: i32) {
- self.device_authzen_version = ::std::option::Option::Some(v);
- }
-
- // optional bytes long_device_id = 29;
-
- pub fn long_device_id(&self) -> &[u8] {
- match self.long_device_id.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_long_device_id(&mut self) {
- self.long_device_id = ::std::option::Option::None;
- }
-
- pub fn has_long_device_id(&self) -> bool {
- self.long_device_id.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_long_device_id(&mut self, v: ::std::vec::Vec<u8>) {
- self.long_device_id = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_long_device_id(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.long_device_id.is_none() {
- self.long_device_id = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.long_device_id.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_long_device_id(&mut self) -> ::std::vec::Vec<u8> {
- self.long_device_id.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional string device_manufacturer = 31;
-
- pub fn device_manufacturer(&self) -> &str {
- match self.device_manufacturer.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_device_manufacturer(&mut self) {
- self.device_manufacturer = ::std::option::Option::None;
- }
-
- pub fn has_device_manufacturer(&self) -> bool {
- self.device_manufacturer.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_manufacturer(&mut self, v: ::std::string::String) {
- self.device_manufacturer = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_device_manufacturer(&mut self) -> &mut ::std::string::String {
- if self.device_manufacturer.is_none() {
- self.device_manufacturer = ::std::option::Option::Some(::std::string::String::new());
- }
- self.device_manufacturer.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_device_manufacturer(&mut self) -> ::std::string::String {
- self.device_manufacturer.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional .securegcm.DeviceType device_type = 32;
-
- pub fn device_type(&self) -> DeviceType {
- match self.device_type {
- Some(e) => e.enum_value_or(DeviceType::ANDROID),
- None => DeviceType::ANDROID,
- }
- }
-
- pub fn clear_device_type(&mut self) {
- self.device_type = ::std::option::Option::None;
- }
-
- pub fn has_device_type(&self) -> bool {
- self.device_type.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_device_type(&mut self, v: DeviceType) {
- self.device_type = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
- }
-
- // optional bool using_secure_screenlock = 400;
-
- pub fn using_secure_screenlock(&self) -> bool {
- self.using_secure_screenlock.unwrap_or(false)
- }
-
- pub fn clear_using_secure_screenlock(&mut self) {
- self.using_secure_screenlock = ::std::option::Option::None;
- }
-
- pub fn has_using_secure_screenlock(&self) -> bool {
- self.using_secure_screenlock.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_using_secure_screenlock(&mut self, v: bool) {
- self.using_secure_screenlock = ::std::option::Option::Some(v);
- }
-
- // optional bool auto_unlock_screenlock_supported = 401;
-
- pub fn auto_unlock_screenlock_supported(&self) -> bool {
- self.auto_unlock_screenlock_supported.unwrap_or(false)
- }
-
- pub fn clear_auto_unlock_screenlock_supported(&mut self) {
- self.auto_unlock_screenlock_supported = ::std::option::Option::None;
- }
-
- pub fn has_auto_unlock_screenlock_supported(&self) -> bool {
- self.auto_unlock_screenlock_supported.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_auto_unlock_screenlock_supported(&mut self, v: bool) {
- self.auto_unlock_screenlock_supported = ::std::option::Option::Some(v);
- }
-
- // optional bool auto_unlock_screenlock_enabled = 402;
-
- pub fn auto_unlock_screenlock_enabled(&self) -> bool {
- self.auto_unlock_screenlock_enabled.unwrap_or(false)
- }
-
- pub fn clear_auto_unlock_screenlock_enabled(&mut self) {
- self.auto_unlock_screenlock_enabled = ::std::option::Option::None;
- }
-
- pub fn has_auto_unlock_screenlock_enabled(&self) -> bool {
- self.auto_unlock_screenlock_enabled.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_auto_unlock_screenlock_enabled(&mut self, v: bool) {
- self.auto_unlock_screenlock_enabled = ::std::option::Option::Some(v);
- }
-
- // optional bool bluetooth_radio_supported = 403;
-
- pub fn bluetooth_radio_supported(&self) -> bool {
- self.bluetooth_radio_supported.unwrap_or(false)
- }
-
- pub fn clear_bluetooth_radio_supported(&mut self) {
- self.bluetooth_radio_supported = ::std::option::Option::None;
- }
-
- pub fn has_bluetooth_radio_supported(&self) -> bool {
- self.bluetooth_radio_supported.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_bluetooth_radio_supported(&mut self, v: bool) {
- self.bluetooth_radio_supported = ::std::option::Option::Some(v);
- }
-
- // optional bool bluetooth_radio_enabled = 404;
-
- pub fn bluetooth_radio_enabled(&self) -> bool {
- self.bluetooth_radio_enabled.unwrap_or(false)
- }
-
- pub fn clear_bluetooth_radio_enabled(&mut self) {
- self.bluetooth_radio_enabled = ::std::option::Option::None;
- }
-
- pub fn has_bluetooth_radio_enabled(&self) -> bool {
- self.bluetooth_radio_enabled.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_bluetooth_radio_enabled(&mut self, v: bool) {
- self.bluetooth_radio_enabled = ::std::option::Option::Some(v);
- }
-
- // optional bool mobile_data_supported = 405;
-
- pub fn mobile_data_supported(&self) -> bool {
- self.mobile_data_supported.unwrap_or(false)
- }
-
- pub fn clear_mobile_data_supported(&mut self) {
- self.mobile_data_supported = ::std::option::Option::None;
- }
-
- pub fn has_mobile_data_supported(&self) -> bool {
- self.mobile_data_supported.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_mobile_data_supported(&mut self, v: bool) {
- self.mobile_data_supported = ::std::option::Option::Some(v);
- }
-
- // optional bool tethering_supported = 406;
-
- pub fn tethering_supported(&self) -> bool {
- self.tethering_supported.unwrap_or(false)
- }
-
- pub fn clear_tethering_supported(&mut self) {
- self.tethering_supported = ::std::option::Option::None;
- }
-
- pub fn has_tethering_supported(&self) -> bool {
- self.tethering_supported.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_tethering_supported(&mut self, v: bool) {
- self.tethering_supported = ::std::option::Option::Some(v);
- }
-
- // optional bool ble_radio_supported = 407;
-
- pub fn ble_radio_supported(&self) -> bool {
- self.ble_radio_supported.unwrap_or(false)
- }
-
- pub fn clear_ble_radio_supported(&mut self) {
- self.ble_radio_supported = ::std::option::Option::None;
- }
-
- pub fn has_ble_radio_supported(&self) -> bool {
- self.ble_radio_supported.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_ble_radio_supported(&mut self, v: bool) {
- self.ble_radio_supported = ::std::option::Option::Some(v);
- }
-
- // optional bool pixel_experience = 408;
-
- pub fn pixel_experience(&self) -> bool {
- self.pixel_experience.unwrap_or(false)
- }
-
- pub fn clear_pixel_experience(&mut self) {
- self.pixel_experience = ::std::option::Option::None;
- }
-
- pub fn has_pixel_experience(&self) -> bool {
- self.pixel_experience.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_pixel_experience(&mut self, v: bool) {
- self.pixel_experience = ::std::option::Option::Some(v);
- }
-
- // optional bool arc_plus_plus = 409;
-
- pub fn arc_plus_plus(&self) -> bool {
- self.arc_plus_plus.unwrap_or(false)
- }
-
- pub fn clear_arc_plus_plus(&mut self) {
- self.arc_plus_plus = ::std::option::Option::None;
- }
-
- pub fn has_arc_plus_plus(&self) -> bool {
- self.arc_plus_plus.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_arc_plus_plus(&mut self, v: bool) {
- self.arc_plus_plus = ::std::option::Option::Some(v);
- }
-
- // optional bool is_screenlock_state_flaky = 410;
-
- pub fn is_screenlock_state_flaky(&self) -> bool {
- self.is_screenlock_state_flaky.unwrap_or(false)
- }
-
- pub fn clear_is_screenlock_state_flaky(&mut self) {
- self.is_screenlock_state_flaky = ::std::option::Option::None;
- }
-
- pub fn has_is_screenlock_state_flaky(&self) -> bool {
- self.is_screenlock_state_flaky.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_is_screenlock_state_flaky(&mut self, v: bool) {
- self.is_screenlock_state_flaky = ::std::option::Option::Some(v);
- }
-
- // optional bytes enrollment_session_id = 1000;
-
- pub fn enrollment_session_id(&self) -> &[u8] {
- match self.enrollment_session_id.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_enrollment_session_id(&mut self) {
- self.enrollment_session_id = ::std::option::Option::None;
- }
-
- pub fn has_enrollment_session_id(&self) -> bool {
- self.enrollment_session_id.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_enrollment_session_id(&mut self, v: ::std::vec::Vec<u8>) {
- self.enrollment_session_id = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_enrollment_session_id(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.enrollment_session_id.is_none() {
- self.enrollment_session_id = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.enrollment_session_id.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_enrollment_session_id(&mut self) -> ::std::vec::Vec<u8> {
- self.enrollment_session_id.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // optional string oauth_token = 1001;
-
- pub fn oauth_token(&self) -> &str {
- match self.oauth_token.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_oauth_token(&mut self) {
- self.oauth_token = ::std::option::Option::None;
- }
-
- pub fn has_oauth_token(&self) -> bool {
- self.oauth_token.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_oauth_token(&mut self, v: ::std::string::String) {
- self.oauth_token = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_oauth_token(&mut self) -> &mut ::std::string::String {
- if self.oauth_token.is_none() {
- self.oauth_token = ::std::option::Option::Some(::std::string::String::new());
- }
- self.oauth_token.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_oauth_token(&mut self) -> ::std::string::String {
- self.oauth_token.take().unwrap_or_else(|| ::std::string::String::new())
- }
-}
-
-impl ::protobuf::Message for GcmDeviceInfo {
- const NAME: &'static str = "GcmDeviceInfo";
-
- fn is_initialized(&self) -> bool {
- if self.user_public_key.is_none() {
- return false;
- }
- true
- }
-
- fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
- while let Some(tag) = is.read_raw_tag_or_eof()? {
- match tag {
- 9 => {
- self.android_device_id = ::std::option::Option::Some(is.read_fixed64()?);
- },
- 818 => {
- self.gcm_registration_id = ::std::option::Option::Some(is.read_bytes()?);
- },
- 1618 => {
- self.apn_registration_id = ::std::option::Option::Some(is.read_bytes()?);
- },
- 1624 => {
- self.notification_enabled = ::std::option::Option::Some(is.read_bool()?);
- },
- 2418 => {
- self.bluetooth_mac_address = ::std::option::Option::Some(is.read_string()?);
- },
- 826 => {
- self.device_master_key_hash = ::std::option::Option::Some(is.read_bytes()?);
- },
- 34 => {
- self.user_public_key = ::std::option::Option::Some(is.read_bytes()?);
- },
- 58 => {
- self.device_model = ::std::option::Option::Some(is.read_string()?);
- },
- 66 => {
- self.locale = ::std::option::Option::Some(is.read_string()?);
- },
- 74 => {
- self.key_handle = ::std::option::Option::Some(is.read_bytes()?);
- },
- 96 => {
- self.counter = ::std::option::Option::Some(is.read_int64()?);
- },
- 106 => {
- self.device_os_version = ::std::option::Option::Some(is.read_string()?);
- },
- 112 => {
- self.device_os_version_code = ::std::option::Option::Some(is.read_int64()?);
- },
- 122 => {
- self.device_os_release = ::std::option::Option::Some(is.read_string()?);
- },
- 130 => {
- self.device_os_codename = ::std::option::Option::Some(is.read_string()?);
- },
- 138 => {
- self.device_software_version = ::std::option::Option::Some(is.read_string()?);
- },
- 144 => {
- self.device_software_version_code = ::std::option::Option::Some(is.read_int64()?);
- },
- 154 => {
- self.device_software_package = ::std::option::Option::Some(is.read_string()?);
- },
- 176 => {
- self.device_display_diagonal_mils = ::std::option::Option::Some(is.read_int32()?);
- },
- 192 => {
- self.device_authzen_version = ::std::option::Option::Some(is.read_int32()?);
- },
- 234 => {
- self.long_device_id = ::std::option::Option::Some(is.read_bytes()?);
- },
- 250 => {
- self.device_manufacturer = ::std::option::Option::Some(is.read_string()?);
- },
- 256 => {
- self.device_type = ::std::option::Option::Some(is.read_enum_or_unknown()?);
- },
- 3200 => {
- self.using_secure_screenlock = ::std::option::Option::Some(is.read_bool()?);
- },
- 3208 => {
- self.auto_unlock_screenlock_supported = ::std::option::Option::Some(is.read_bool()?);
- },
- 3216 => {
- self.auto_unlock_screenlock_enabled = ::std::option::Option::Some(is.read_bool()?);
- },
- 3224 => {
- self.bluetooth_radio_supported = ::std::option::Option::Some(is.read_bool()?);
- },
- 3232 => {
- self.bluetooth_radio_enabled = ::std::option::Option::Some(is.read_bool()?);
- },
- 3240 => {
- self.mobile_data_supported = ::std::option::Option::Some(is.read_bool()?);
- },
- 3248 => {
- self.tethering_supported = ::std::option::Option::Some(is.read_bool()?);
- },
- 3256 => {
- self.ble_radio_supported = ::std::option::Option::Some(is.read_bool()?);
- },
- 3264 => {
- self.pixel_experience = ::std::option::Option::Some(is.read_bool()?);
- },
- 3272 => {
- self.arc_plus_plus = ::std::option::Option::Some(is.read_bool()?);
- },
- 3280 => {
- self.is_screenlock_state_flaky = ::std::option::Option::Some(is.read_bool()?);
- },
- 3288 => {
- self.supported_software_features.push(is.read_enum_or_unknown()?);
- },
- 3290 => {
- ::protobuf::rt::read_repeated_packed_enum_or_unknown_into(is, &mut self.supported_software_features)?
- },
- 3296 => {
- self.enabled_software_features.push(is.read_enum_or_unknown()?);
- },
- 3298 => {
- ::protobuf::rt::read_repeated_packed_enum_or_unknown_into(is, &mut self.enabled_software_features)?
- },
- 8002 => {
- self.enrollment_session_id = ::std::option::Option::Some(is.read_bytes()?);
- },
- 8010 => {
- self.oauth_token = ::std::option::Option::Some(is.read_string()?);
- },
- tag => {
- ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
- },
- };
- }
- ::std::result::Result::Ok(())
- }
-
- // Compute sizes of nested messages
- #[allow(unused_variables)]
- fn compute_size(&self) -> u64 {
- let mut my_size = 0;
- if let Some(v) = self.android_device_id {
- my_size += 1 + 8;
- }
- if let Some(v) = self.gcm_registration_id.as_ref() {
- my_size += ::protobuf::rt::bytes_size(102, &v);
- }
- if let Some(v) = self.apn_registration_id.as_ref() {
- my_size += ::protobuf::rt::bytes_size(202, &v);
- }
- if let Some(v) = self.notification_enabled {
- my_size += 2 + 1;
- }
- if let Some(v) = self.bluetooth_mac_address.as_ref() {
- my_size += ::protobuf::rt::string_size(302, &v);
- }
- if let Some(v) = self.device_master_key_hash.as_ref() {
- my_size += ::protobuf::rt::bytes_size(103, &v);
- }
- if let Some(v) = self.user_public_key.as_ref() {
- my_size += ::protobuf::rt::bytes_size(4, &v);
- }
- if let Some(v) = self.device_model.as_ref() {
- my_size += ::protobuf::rt::string_size(7, &v);
- }
- if let Some(v) = self.locale.as_ref() {
- my_size += ::protobuf::rt::string_size(8, &v);
- }
- if let Some(v) = self.key_handle.as_ref() {
- my_size += ::protobuf::rt::bytes_size(9, &v);
- }
- if let Some(v) = self.counter {
- my_size += ::protobuf::rt::int64_size(12, v);
- }
- if let Some(v) = self.device_os_version.as_ref() {
- my_size += ::protobuf::rt::string_size(13, &v);
- }
- if let Some(v) = self.device_os_version_code {
- my_size += ::protobuf::rt::int64_size(14, v);
- }
- if let Some(v) = self.device_os_release.as_ref() {
- my_size += ::protobuf::rt::string_size(15, &v);
- }
- if let Some(v) = self.device_os_codename.as_ref() {
- my_size += ::protobuf::rt::string_size(16, &v);
- }
- if let Some(v) = self.device_software_version.as_ref() {
- my_size += ::protobuf::rt::string_size(17, &v);
- }
- if let Some(v) = self.device_software_version_code {
- my_size += ::protobuf::rt::int64_size(18, v);
- }
- if let Some(v) = self.device_software_package.as_ref() {
- my_size += ::protobuf::rt::string_size(19, &v);
- }
- if let Some(v) = self.device_display_diagonal_mils {
- my_size += ::protobuf::rt::int32_size(22, v);
- }
- if let Some(v) = self.device_authzen_version {
- my_size += ::protobuf::rt::int32_size(24, v);
- }
- if let Some(v) = self.long_device_id.as_ref() {
- my_size += ::protobuf::rt::bytes_size(29, &v);
- }
- if let Some(v) = self.device_manufacturer.as_ref() {
- my_size += ::protobuf::rt::string_size(31, &v);
- }
- if let Some(v) = self.device_type {
- my_size += ::protobuf::rt::int32_size(32, v.value());
- }
- if let Some(v) = self.using_secure_screenlock {
- my_size += 2 + 1;
- }
- if let Some(v) = self.auto_unlock_screenlock_supported {
- my_size += 2 + 1;
- }
- if let Some(v) = self.auto_unlock_screenlock_enabled {
- my_size += 2 + 1;
- }
- if let Some(v) = self.bluetooth_radio_supported {
- my_size += 2 + 1;
- }
- if let Some(v) = self.bluetooth_radio_enabled {
- my_size += 2 + 1;
- }
- if let Some(v) = self.mobile_data_supported {
- my_size += 2 + 1;
- }
- if let Some(v) = self.tethering_supported {
- my_size += 2 + 1;
- }
- if let Some(v) = self.ble_radio_supported {
- my_size += 2 + 1;
- }
- if let Some(v) = self.pixel_experience {
- my_size += 2 + 1;
- }
- if let Some(v) = self.arc_plus_plus {
- my_size += 2 + 1;
- }
- if let Some(v) = self.is_screenlock_state_flaky {
- my_size += 2 + 1;
- }
- for value in &self.supported_software_features {
- my_size += ::protobuf::rt::int32_size(411, value.value());
- };
- for value in &self.enabled_software_features {
- my_size += ::protobuf::rt::int32_size(412, value.value());
- };
- if let Some(v) = self.enrollment_session_id.as_ref() {
- my_size += ::protobuf::rt::bytes_size(1000, &v);
- }
- if let Some(v) = self.oauth_token.as_ref() {
- my_size += ::protobuf::rt::string_size(1001, &v);
- }
- my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
- self.special_fields.cached_size().set(my_size as u32);
- my_size
- }
-
- fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
- if let Some(v) = self.android_device_id {
- os.write_fixed64(1, v)?;
- }
- if let Some(v) = self.gcm_registration_id.as_ref() {
- os.write_bytes(102, v)?;
- }
- if let Some(v) = self.apn_registration_id.as_ref() {
- os.write_bytes(202, v)?;
- }
- if let Some(v) = self.notification_enabled {
- os.write_bool(203, v)?;
- }
- if let Some(v) = self.bluetooth_mac_address.as_ref() {
- os.write_string(302, v)?;
- }
- if let Some(v) = self.device_master_key_hash.as_ref() {
- os.write_bytes(103, v)?;
- }
- if let Some(v) = self.user_public_key.as_ref() {
- os.write_bytes(4, v)?;
- }
- if let Some(v) = self.device_model.as_ref() {
- os.write_string(7, v)?;
- }
- if let Some(v) = self.locale.as_ref() {
- os.write_string(8, v)?;
- }
- if let Some(v) = self.key_handle.as_ref() {
- os.write_bytes(9, v)?;
- }
- if let Some(v) = self.counter {
- os.write_int64(12, v)?;
- }
- if let Some(v) = self.device_os_version.as_ref() {
- os.write_string(13, v)?;
- }
- if let Some(v) = self.device_os_version_code {
- os.write_int64(14, v)?;
- }
- if let Some(v) = self.device_os_release.as_ref() {
- os.write_string(15, v)?;
- }
- if let Some(v) = self.device_os_codename.as_ref() {
- os.write_string(16, v)?;
- }
- if let Some(v) = self.device_software_version.as_ref() {
- os.write_string(17, v)?;
- }
- if let Some(v) = self.device_software_version_code {
- os.write_int64(18, v)?;
- }
- if let Some(v) = self.device_software_package.as_ref() {
- os.write_string(19, v)?;
- }
- if let Some(v) = self.device_display_diagonal_mils {
- os.write_int32(22, v)?;
- }
- if let Some(v) = self.device_authzen_version {
- os.write_int32(24, v)?;
- }
- if let Some(v) = self.long_device_id.as_ref() {
- os.write_bytes(29, v)?;
- }
- if let Some(v) = self.device_manufacturer.as_ref() {
- os.write_string(31, v)?;
- }
- if let Some(v) = self.device_type {
- os.write_enum(32, ::protobuf::EnumOrUnknown::value(&v))?;
- }
- if let Some(v) = self.using_secure_screenlock {
- os.write_bool(400, v)?;
- }
- if let Some(v) = self.auto_unlock_screenlock_supported {
- os.write_bool(401, v)?;
- }
- if let Some(v) = self.auto_unlock_screenlock_enabled {
- os.write_bool(402, v)?;
- }
- if let Some(v) = self.bluetooth_radio_supported {
- os.write_bool(403, v)?;
- }
- if let Some(v) = self.bluetooth_radio_enabled {
- os.write_bool(404, v)?;
- }
- if let Some(v) = self.mobile_data_supported {
- os.write_bool(405, v)?;
- }
- if let Some(v) = self.tethering_supported {
- os.write_bool(406, v)?;
- }
- if let Some(v) = self.ble_radio_supported {
- os.write_bool(407, v)?;
- }
- if let Some(v) = self.pixel_experience {
- os.write_bool(408, v)?;
- }
- if let Some(v) = self.arc_plus_plus {
- os.write_bool(409, v)?;
- }
- if let Some(v) = self.is_screenlock_state_flaky {
- os.write_bool(410, v)?;
- }
- for v in &self.supported_software_features {
- os.write_enum(411, ::protobuf::EnumOrUnknown::value(v))?;
- };
- for v in &self.enabled_software_features {
- os.write_enum(412, ::protobuf::EnumOrUnknown::value(v))?;
- };
- if let Some(v) = self.enrollment_session_id.as_ref() {
- os.write_bytes(1000, v)?;
- }
- if let Some(v) = self.oauth_token.as_ref() {
- os.write_string(1001, v)?;
- }
- os.write_unknown_fields(self.special_fields.unknown_fields())?;
- ::std::result::Result::Ok(())
- }
-
- fn special_fields(&self) -> &::protobuf::SpecialFields {
- &self.special_fields
- }
-
- fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
- &mut self.special_fields
- }
-
- fn new() -> GcmDeviceInfo {
- GcmDeviceInfo::new()
- }
-
- fn clear(&mut self) {
- self.android_device_id = ::std::option::Option::None;
- self.gcm_registration_id = ::std::option::Option::None;
- self.apn_registration_id = ::std::option::Option::None;
- self.notification_enabled = ::std::option::Option::None;
- self.bluetooth_mac_address = ::std::option::Option::None;
- self.device_master_key_hash = ::std::option::Option::None;
- self.user_public_key = ::std::option::Option::None;
- self.device_model = ::std::option::Option::None;
- self.locale = ::std::option::Option::None;
- self.key_handle = ::std::option::Option::None;
- self.counter = ::std::option::Option::None;
- self.device_os_version = ::std::option::Option::None;
- self.device_os_version_code = ::std::option::Option::None;
- self.device_os_release = ::std::option::Option::None;
- self.device_os_codename = ::std::option::Option::None;
- self.device_software_version = ::std::option::Option::None;
- self.device_software_version_code = ::std::option::Option::None;
- self.device_software_package = ::std::option::Option::None;
- self.device_display_diagonal_mils = ::std::option::Option::None;
- self.device_authzen_version = ::std::option::Option::None;
- self.long_device_id = ::std::option::Option::None;
- self.device_manufacturer = ::std::option::Option::None;
- self.device_type = ::std::option::Option::None;
- self.using_secure_screenlock = ::std::option::Option::None;
- self.auto_unlock_screenlock_supported = ::std::option::Option::None;
- self.auto_unlock_screenlock_enabled = ::std::option::Option::None;
- self.bluetooth_radio_supported = ::std::option::Option::None;
- self.bluetooth_radio_enabled = ::std::option::Option::None;
- self.mobile_data_supported = ::std::option::Option::None;
- self.tethering_supported = ::std::option::Option::None;
- self.ble_radio_supported = ::std::option::Option::None;
- self.pixel_experience = ::std::option::Option::None;
- self.arc_plus_plus = ::std::option::Option::None;
- self.is_screenlock_state_flaky = ::std::option::Option::None;
- self.supported_software_features.clear();
- self.enabled_software_features.clear();
- self.enrollment_session_id = ::std::option::Option::None;
- self.oauth_token = ::std::option::Option::None;
- self.special_fields.clear();
- }
-
- fn default_instance() -> &'static GcmDeviceInfo {
- static instance: GcmDeviceInfo = GcmDeviceInfo {
- android_device_id: ::std::option::Option::None,
- gcm_registration_id: ::std::option::Option::None,
- apn_registration_id: ::std::option::Option::None,
- notification_enabled: ::std::option::Option::None,
- bluetooth_mac_address: ::std::option::Option::None,
- device_master_key_hash: ::std::option::Option::None,
- user_public_key: ::std::option::Option::None,
- device_model: ::std::option::Option::None,
- locale: ::std::option::Option::None,
- key_handle: ::std::option::Option::None,
- counter: ::std::option::Option::None,
- device_os_version: ::std::option::Option::None,
- device_os_version_code: ::std::option::Option::None,
- device_os_release: ::std::option::Option::None,
- device_os_codename: ::std::option::Option::None,
- device_software_version: ::std::option::Option::None,
- device_software_version_code: ::std::option::Option::None,
- device_software_package: ::std::option::Option::None,
- device_display_diagonal_mils: ::std::option::Option::None,
- device_authzen_version: ::std::option::Option::None,
- long_device_id: ::std::option::Option::None,
- device_manufacturer: ::std::option::Option::None,
- device_type: ::std::option::Option::None,
- using_secure_screenlock: ::std::option::Option::None,
- auto_unlock_screenlock_supported: ::std::option::Option::None,
- auto_unlock_screenlock_enabled: ::std::option::Option::None,
- bluetooth_radio_supported: ::std::option::Option::None,
- bluetooth_radio_enabled: ::std::option::Option::None,
- mobile_data_supported: ::std::option::Option::None,
- tethering_supported: ::std::option::Option::None,
- ble_radio_supported: ::std::option::Option::None,
- pixel_experience: ::std::option::Option::None,
- arc_plus_plus: ::std::option::Option::None,
- is_screenlock_state_flaky: ::std::option::Option::None,
- supported_software_features: ::std::vec::Vec::new(),
- enabled_software_features: ::std::vec::Vec::new(),
- enrollment_session_id: ::std::option::Option::None,
- oauth_token: ::std::option::Option::None,
- special_fields: ::protobuf::SpecialFields::new(),
- };
- &instance
- }
-}
-
-#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:securegcm.GcmMetadata)
pub struct GcmMetadata {
// message fields
@@ -1743,669 +187,6 @@ impl ::protobuf::Message for GcmMetadata {
}
}
-#[derive(PartialEq,Clone,Default,Debug)]
-// @@protoc_insertion_point(message:securegcm.Tickle)
-pub struct Tickle {
- // message fields
- // @@protoc_insertion_point(field:securegcm.Tickle.expiry_time)
- pub expiry_time: ::std::option::Option<u64>,
- // special fields
- // @@protoc_insertion_point(special_field:securegcm.Tickle.special_fields)
- pub special_fields: ::protobuf::SpecialFields,
-}
-
-impl<'a> ::std::default::Default for &'a Tickle {
- fn default() -> &'a Tickle {
- <Tickle as ::protobuf::Message>::default_instance()
- }
-}
-
-impl Tickle {
- pub fn new() -> Tickle {
- ::std::default::Default::default()
- }
-
- // optional fixed64 expiry_time = 1;
-
- pub fn expiry_time(&self) -> u64 {
- self.expiry_time.unwrap_or(0)
- }
-
- pub fn clear_expiry_time(&mut self) {
- self.expiry_time = ::std::option::Option::None;
- }
-
- pub fn has_expiry_time(&self) -> bool {
- self.expiry_time.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_expiry_time(&mut self, v: u64) {
- self.expiry_time = ::std::option::Option::Some(v);
- }
-}
-
-impl ::protobuf::Message for Tickle {
- const NAME: &'static str = "Tickle";
-
- fn is_initialized(&self) -> bool {
- true
- }
-
- fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
- while let Some(tag) = is.read_raw_tag_or_eof()? {
- match tag {
- 9 => {
- self.expiry_time = ::std::option::Option::Some(is.read_fixed64()?);
- },
- tag => {
- ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
- },
- };
- }
- ::std::result::Result::Ok(())
- }
-
- // Compute sizes of nested messages
- #[allow(unused_variables)]
- fn compute_size(&self) -> u64 {
- let mut my_size = 0;
- if let Some(v) = self.expiry_time {
- my_size += 1 + 8;
- }
- my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
- self.special_fields.cached_size().set(my_size as u32);
- my_size
- }
-
- fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
- if let Some(v) = self.expiry_time {
- os.write_fixed64(1, v)?;
- }
- os.write_unknown_fields(self.special_fields.unknown_fields())?;
- ::std::result::Result::Ok(())
- }
-
- fn special_fields(&self) -> &::protobuf::SpecialFields {
- &self.special_fields
- }
-
- fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
- &mut self.special_fields
- }
-
- fn new() -> Tickle {
- Tickle::new()
- }
-
- fn clear(&mut self) {
- self.expiry_time = ::std::option::Option::None;
- self.special_fields.clear();
- }
-
- fn default_instance() -> &'static Tickle {
- static instance: Tickle = Tickle {
- expiry_time: ::std::option::Option::None,
- special_fields: ::protobuf::SpecialFields::new(),
- };
- &instance
- }
-}
-
-#[derive(PartialEq,Clone,Default,Debug)]
-// @@protoc_insertion_point(message:securegcm.LoginNotificationInfo)
-pub struct LoginNotificationInfo {
- // message fields
- // @@protoc_insertion_point(field:securegcm.LoginNotificationInfo.creation_time)
- pub creation_time: ::std::option::Option<u64>,
- // @@protoc_insertion_point(field:securegcm.LoginNotificationInfo.email)
- pub email: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.LoginNotificationInfo.host)
- pub host: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.LoginNotificationInfo.source)
- pub source: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.LoginNotificationInfo.event_type)
- pub event_type: ::std::option::Option<::std::string::String>,
- // special fields
- // @@protoc_insertion_point(special_field:securegcm.LoginNotificationInfo.special_fields)
- pub special_fields: ::protobuf::SpecialFields,
-}
-
-impl<'a> ::std::default::Default for &'a LoginNotificationInfo {
- fn default() -> &'a LoginNotificationInfo {
- <LoginNotificationInfo as ::protobuf::Message>::default_instance()
- }
-}
-
-impl LoginNotificationInfo {
- pub fn new() -> LoginNotificationInfo {
- ::std::default::Default::default()
- }
-
- // optional fixed64 creation_time = 2;
-
- pub fn creation_time(&self) -> u64 {
- self.creation_time.unwrap_or(0)
- }
-
- pub fn clear_creation_time(&mut self) {
- self.creation_time = ::std::option::Option::None;
- }
-
- pub fn has_creation_time(&self) -> bool {
- self.creation_time.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_creation_time(&mut self, v: u64) {
- self.creation_time = ::std::option::Option::Some(v);
- }
-
- // optional string email = 3;
-
- pub fn email(&self) -> &str {
- match self.email.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_email(&mut self) {
- self.email = ::std::option::Option::None;
- }
-
- pub fn has_email(&self) -> bool {
- self.email.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_email(&mut self, v: ::std::string::String) {
- self.email = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_email(&mut self) -> &mut ::std::string::String {
- if self.email.is_none() {
- self.email = ::std::option::Option::Some(::std::string::String::new());
- }
- self.email.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_email(&mut self) -> ::std::string::String {
- self.email.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string host = 4;
-
- pub fn host(&self) -> &str {
- match self.host.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_host(&mut self) {
- self.host = ::std::option::Option::None;
- }
-
- pub fn has_host(&self) -> bool {
- self.host.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_host(&mut self, v: ::std::string::String) {
- self.host = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_host(&mut self) -> &mut ::std::string::String {
- if self.host.is_none() {
- self.host = ::std::option::Option::Some(::std::string::String::new());
- }
- self.host.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_host(&mut self) -> ::std::string::String {
- self.host.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string source = 5;
-
- pub fn source(&self) -> &str {
- match self.source.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_source(&mut self) {
- self.source = ::std::option::Option::None;
- }
-
- pub fn has_source(&self) -> bool {
- self.source.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_source(&mut self, v: ::std::string::String) {
- self.source = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_source(&mut self) -> &mut ::std::string::String {
- if self.source.is_none() {
- self.source = ::std::option::Option::Some(::std::string::String::new());
- }
- self.source.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_source(&mut self) -> ::std::string::String {
- self.source.take().unwrap_or_else(|| ::std::string::String::new())
- }
-
- // optional string event_type = 6;
-
- pub fn event_type(&self) -> &str {
- match self.event_type.as_ref() {
- Some(v) => v,
- None => "",
- }
- }
-
- pub fn clear_event_type(&mut self) {
- self.event_type = ::std::option::Option::None;
- }
-
- pub fn has_event_type(&self) -> bool {
- self.event_type.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_event_type(&mut self, v: ::std::string::String) {
- self.event_type = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_event_type(&mut self) -> &mut ::std::string::String {
- if self.event_type.is_none() {
- self.event_type = ::std::option::Option::Some(::std::string::String::new());
- }
- self.event_type.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_event_type(&mut self) -> ::std::string::String {
- self.event_type.take().unwrap_or_else(|| ::std::string::String::new())
- }
-}
-
-impl ::protobuf::Message for LoginNotificationInfo {
- const NAME: &'static str = "LoginNotificationInfo";
-
- fn is_initialized(&self) -> bool {
- true
- }
-
- fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
- while let Some(tag) = is.read_raw_tag_or_eof()? {
- match tag {
- 17 => {
- self.creation_time = ::std::option::Option::Some(is.read_fixed64()?);
- },
- 26 => {
- self.email = ::std::option::Option::Some(is.read_string()?);
- },
- 34 => {
- self.host = ::std::option::Option::Some(is.read_string()?);
- },
- 42 => {
- self.source = ::std::option::Option::Some(is.read_string()?);
- },
- 50 => {
- self.event_type = ::std::option::Option::Some(is.read_string()?);
- },
- tag => {
- ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
- },
- };
- }
- ::std::result::Result::Ok(())
- }
-
- // Compute sizes of nested messages
- #[allow(unused_variables)]
- fn compute_size(&self) -> u64 {
- let mut my_size = 0;
- if let Some(v) = self.creation_time {
- my_size += 1 + 8;
- }
- if let Some(v) = self.email.as_ref() {
- my_size += ::protobuf::rt::string_size(3, &v);
- }
- if let Some(v) = self.host.as_ref() {
- my_size += ::protobuf::rt::string_size(4, &v);
- }
- if let Some(v) = self.source.as_ref() {
- my_size += ::protobuf::rt::string_size(5, &v);
- }
- if let Some(v) = self.event_type.as_ref() {
- my_size += ::protobuf::rt::string_size(6, &v);
- }
- my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
- self.special_fields.cached_size().set(my_size as u32);
- my_size
- }
-
- fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
- if let Some(v) = self.creation_time {
- os.write_fixed64(2, v)?;
- }
- if let Some(v) = self.email.as_ref() {
- os.write_string(3, v)?;
- }
- if let Some(v) = self.host.as_ref() {
- os.write_string(4, v)?;
- }
- if let Some(v) = self.source.as_ref() {
- os.write_string(5, v)?;
- }
- if let Some(v) = self.event_type.as_ref() {
- os.write_string(6, v)?;
- }
- os.write_unknown_fields(self.special_fields.unknown_fields())?;
- ::std::result::Result::Ok(())
- }
-
- fn special_fields(&self) -> &::protobuf::SpecialFields {
- &self.special_fields
- }
-
- fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
- &mut self.special_fields
- }
-
- fn new() -> LoginNotificationInfo {
- LoginNotificationInfo::new()
- }
-
- fn clear(&mut self) {
- self.creation_time = ::std::option::Option::None;
- self.email = ::std::option::Option::None;
- self.host = ::std::option::Option::None;
- self.source = ::std::option::Option::None;
- self.event_type = ::std::option::Option::None;
- self.special_fields.clear();
- }
-
- fn default_instance() -> &'static LoginNotificationInfo {
- static instance: LoginNotificationInfo = LoginNotificationInfo {
- creation_time: ::std::option::Option::None,
- email: ::std::option::Option::None,
- host: ::std::option::Option::None,
- source: ::std::option::Option::None,
- event_type: ::std::option::Option::None,
- special_fields: ::protobuf::SpecialFields::new(),
- };
- &instance
- }
-}
-
-#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
-// @@protoc_insertion_point(enum:securegcm.AppleDeviceDiagonalMils)
-pub enum AppleDeviceDiagonalMils {
- // @@protoc_insertion_point(enum_value:securegcm.AppleDeviceDiagonalMils.APPLE_PHONE)
- APPLE_PHONE = 4000,
- // @@protoc_insertion_point(enum_value:securegcm.AppleDeviceDiagonalMils.APPLE_PAD)
- APPLE_PAD = 7900,
-}
-
-impl ::protobuf::Enum for AppleDeviceDiagonalMils {
- const NAME: &'static str = "AppleDeviceDiagonalMils";
-
- fn value(&self) -> i32 {
- *self as i32
- }
-
- fn from_i32(value: i32) -> ::std::option::Option<AppleDeviceDiagonalMils> {
- match value {
- 4000 => ::std::option::Option::Some(AppleDeviceDiagonalMils::APPLE_PHONE),
- 7900 => ::std::option::Option::Some(AppleDeviceDiagonalMils::APPLE_PAD),
- _ => ::std::option::Option::None
- }
- }
-
- const VALUES: &'static [AppleDeviceDiagonalMils] = &[
- AppleDeviceDiagonalMils::APPLE_PHONE,
- AppleDeviceDiagonalMils::APPLE_PAD,
- ];
-}
-
-// Note, `Default` is implemented although default value is not 0
-impl ::std::default::Default for AppleDeviceDiagonalMils {
- fn default() -> Self {
- AppleDeviceDiagonalMils::APPLE_PHONE
- }
-}
-
-
-#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
-// @@protoc_insertion_point(enum:securegcm.DeviceType)
-pub enum DeviceType {
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.UNKNOWN)
- UNKNOWN = 0,
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.ANDROID)
- ANDROID = 1,
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.CHROME)
- CHROME = 2,
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.IOS)
- IOS = 3,
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.BROWSER)
- BROWSER = 4,
- // @@protoc_insertion_point(enum_value:securegcm.DeviceType.OSX)
- OSX = 5,
-}
-
-impl ::protobuf::Enum for DeviceType {
- const NAME: &'static str = "DeviceType";
-
- fn value(&self) -> i32 {
- *self as i32
- }
-
- fn from_i32(value: i32) -> ::std::option::Option<DeviceType> {
- match value {
- 0 => ::std::option::Option::Some(DeviceType::UNKNOWN),
- 1 => ::std::option::Option::Some(DeviceType::ANDROID),
- 2 => ::std::option::Option::Some(DeviceType::CHROME),
- 3 => ::std::option::Option::Some(DeviceType::IOS),
- 4 => ::std::option::Option::Some(DeviceType::BROWSER),
- 5 => ::std::option::Option::Some(DeviceType::OSX),
- _ => ::std::option::Option::None
- }
- }
-
- const VALUES: &'static [DeviceType] = &[
- DeviceType::UNKNOWN,
- DeviceType::ANDROID,
- DeviceType::CHROME,
- DeviceType::IOS,
- DeviceType::BROWSER,
- DeviceType::OSX,
- ];
-}
-
-impl ::std::default::Default for DeviceType {
- fn default() -> Self {
- DeviceType::UNKNOWN
- }
-}
-
-
-#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
-// @@protoc_insertion_point(enum:securegcm.SoftwareFeature)
-pub enum SoftwareFeature {
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.UNKNOWN_FEATURE)
- UNKNOWN_FEATURE = 0,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.BETTER_TOGETHER_HOST)
- BETTER_TOGETHER_HOST = 1,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.BETTER_TOGETHER_CLIENT)
- BETTER_TOGETHER_CLIENT = 2,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.EASY_UNLOCK_HOST)
- EASY_UNLOCK_HOST = 3,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.EASY_UNLOCK_CLIENT)
- EASY_UNLOCK_CLIENT = 4,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.MAGIC_TETHER_HOST)
- MAGIC_TETHER_HOST = 5,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.MAGIC_TETHER_CLIENT)
- MAGIC_TETHER_CLIENT = 6,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.SMS_CONNECT_HOST)
- SMS_CONNECT_HOST = 7,
- // @@protoc_insertion_point(enum_value:securegcm.SoftwareFeature.SMS_CONNECT_CLIENT)
- SMS_CONNECT_CLIENT = 8,
-}
-
-impl ::protobuf::Enum for SoftwareFeature {
- const NAME: &'static str = "SoftwareFeature";
-
- fn value(&self) -> i32 {
- *self as i32
- }
-
- fn from_i32(value: i32) -> ::std::option::Option<SoftwareFeature> {
- match value {
- 0 => ::std::option::Option::Some(SoftwareFeature::UNKNOWN_FEATURE),
- 1 => ::std::option::Option::Some(SoftwareFeature::BETTER_TOGETHER_HOST),
- 2 => ::std::option::Option::Some(SoftwareFeature::BETTER_TOGETHER_CLIENT),
- 3 => ::std::option::Option::Some(SoftwareFeature::EASY_UNLOCK_HOST),
- 4 => ::std::option::Option::Some(SoftwareFeature::EASY_UNLOCK_CLIENT),
- 5 => ::std::option::Option::Some(SoftwareFeature::MAGIC_TETHER_HOST),
- 6 => ::std::option::Option::Some(SoftwareFeature::MAGIC_TETHER_CLIENT),
- 7 => ::std::option::Option::Some(SoftwareFeature::SMS_CONNECT_HOST),
- 8 => ::std::option::Option::Some(SoftwareFeature::SMS_CONNECT_CLIENT),
- _ => ::std::option::Option::None
- }
- }
-
- const VALUES: &'static [SoftwareFeature] = &[
- SoftwareFeature::UNKNOWN_FEATURE,
- SoftwareFeature::BETTER_TOGETHER_HOST,
- SoftwareFeature::BETTER_TOGETHER_CLIENT,
- SoftwareFeature::EASY_UNLOCK_HOST,
- SoftwareFeature::EASY_UNLOCK_CLIENT,
- SoftwareFeature::MAGIC_TETHER_HOST,
- SoftwareFeature::MAGIC_TETHER_CLIENT,
- SoftwareFeature::SMS_CONNECT_HOST,
- SoftwareFeature::SMS_CONNECT_CLIENT,
- ];
-}
-
-impl ::std::default::Default for SoftwareFeature {
- fn default() -> Self {
- SoftwareFeature::UNKNOWN_FEATURE
- }
-}
-
-
-#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
-// @@protoc_insertion_point(enum:securegcm.InvocationReason)
-pub enum InvocationReason {
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_UNKNOWN)
- REASON_UNKNOWN = 0,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_INITIALIZATION)
- REASON_INITIALIZATION = 1,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_PERIODIC)
- REASON_PERIODIC = 2,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_SLOW_PERIODIC)
- REASON_SLOW_PERIODIC = 3,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_FAST_PERIODIC)
- REASON_FAST_PERIODIC = 4,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_EXPIRATION)
- REASON_EXPIRATION = 5,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_FAILURE_RECOVERY)
- REASON_FAILURE_RECOVERY = 6,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_NEW_ACCOUNT)
- REASON_NEW_ACCOUNT = 7,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_CHANGED_ACCOUNT)
- REASON_CHANGED_ACCOUNT = 8,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_FEATURE_TOGGLED)
- REASON_FEATURE_TOGGLED = 9,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_SERVER_INITIATED)
- REASON_SERVER_INITIATED = 10,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_ADDRESS_CHANGE)
- REASON_ADDRESS_CHANGE = 11,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_SOFTWARE_UPDATE)
- REASON_SOFTWARE_UPDATE = 12,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_MANUAL)
- REASON_MANUAL = 13,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_CUSTOM_KEY_INVALIDATION)
- REASON_CUSTOM_KEY_INVALIDATION = 14,
- // @@protoc_insertion_point(enum_value:securegcm.InvocationReason.REASON_PROXIMITY_PERIODIC)
- REASON_PROXIMITY_PERIODIC = 15,
-}
-
-impl ::protobuf::Enum for InvocationReason {
- const NAME: &'static str = "InvocationReason";
-
- fn value(&self) -> i32 {
- *self as i32
- }
-
- fn from_i32(value: i32) -> ::std::option::Option<InvocationReason> {
- match value {
- 0 => ::std::option::Option::Some(InvocationReason::REASON_UNKNOWN),
- 1 => ::std::option::Option::Some(InvocationReason::REASON_INITIALIZATION),
- 2 => ::std::option::Option::Some(InvocationReason::REASON_PERIODIC),
- 3 => ::std::option::Option::Some(InvocationReason::REASON_SLOW_PERIODIC),
- 4 => ::std::option::Option::Some(InvocationReason::REASON_FAST_PERIODIC),
- 5 => ::std::option::Option::Some(InvocationReason::REASON_EXPIRATION),
- 6 => ::std::option::Option::Some(InvocationReason::REASON_FAILURE_RECOVERY),
- 7 => ::std::option::Option::Some(InvocationReason::REASON_NEW_ACCOUNT),
- 8 => ::std::option::Option::Some(InvocationReason::REASON_CHANGED_ACCOUNT),
- 9 => ::std::option::Option::Some(InvocationReason::REASON_FEATURE_TOGGLED),
- 10 => ::std::option::Option::Some(InvocationReason::REASON_SERVER_INITIATED),
- 11 => ::std::option::Option::Some(InvocationReason::REASON_ADDRESS_CHANGE),
- 12 => ::std::option::Option::Some(InvocationReason::REASON_SOFTWARE_UPDATE),
- 13 => ::std::option::Option::Some(InvocationReason::REASON_MANUAL),
- 14 => ::std::option::Option::Some(InvocationReason::REASON_CUSTOM_KEY_INVALIDATION),
- 15 => ::std::option::Option::Some(InvocationReason::REASON_PROXIMITY_PERIODIC),
- _ => ::std::option::Option::None
- }
- }
-
- const VALUES: &'static [InvocationReason] = &[
- InvocationReason::REASON_UNKNOWN,
- InvocationReason::REASON_INITIALIZATION,
- InvocationReason::REASON_PERIODIC,
- InvocationReason::REASON_SLOW_PERIODIC,
- InvocationReason::REASON_FAST_PERIODIC,
- InvocationReason::REASON_EXPIRATION,
- InvocationReason::REASON_FAILURE_RECOVERY,
- InvocationReason::REASON_NEW_ACCOUNT,
- InvocationReason::REASON_CHANGED_ACCOUNT,
- InvocationReason::REASON_FEATURE_TOGGLED,
- InvocationReason::REASON_SERVER_INITIATED,
- InvocationReason::REASON_ADDRESS_CHANGE,
- InvocationReason::REASON_SOFTWARE_UPDATE,
- InvocationReason::REASON_MANUAL,
- InvocationReason::REASON_CUSTOM_KEY_INVALIDATION,
- InvocationReason::REASON_PROXIMITY_PERIODIC,
- ];
-}
-
-impl ::std::default::Default for InvocationReason {
- fn default() -> Self {
- InvocationReason::REASON_UNKNOWN
- }
-}
-
-
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:securegcm.Type)
pub enum Type {
diff --git a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securemessage.rs b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securemessage.rs
index d83d137..5fe83da 100644
--- a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securemessage.rs
+++ b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/securemessage.rs
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// 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.
@@ -803,187 +803,6 @@ impl ::protobuf::Message for HeaderAndBody {
}
#[derive(PartialEq,Clone,Default,Debug)]
-// @@protoc_insertion_point(message:securemessage.HeaderAndBodyInternal)
-pub struct HeaderAndBodyInternal {
- // message fields
- // @@protoc_insertion_point(field:securemessage.HeaderAndBodyInternal.header)
- pub header: ::std::option::Option<::std::vec::Vec<u8>>,
- // @@protoc_insertion_point(field:securemessage.HeaderAndBodyInternal.body)
- pub body: ::std::option::Option<::std::vec::Vec<u8>>,
- // special fields
- // @@protoc_insertion_point(special_field:securemessage.HeaderAndBodyInternal.special_fields)
- pub special_fields: ::protobuf::SpecialFields,
-}
-
-impl<'a> ::std::default::Default for &'a HeaderAndBodyInternal {
- fn default() -> &'a HeaderAndBodyInternal {
- <HeaderAndBodyInternal as ::protobuf::Message>::default_instance()
- }
-}
-
-impl HeaderAndBodyInternal {
- pub fn new() -> HeaderAndBodyInternal {
- ::std::default::Default::default()
- }
-
- // required bytes header = 1;
-
- pub fn header(&self) -> &[u8] {
- match self.header.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_header(&mut self) {
- self.header = ::std::option::Option::None;
- }
-
- pub fn has_header(&self) -> bool {
- self.header.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_header(&mut self, v: ::std::vec::Vec<u8>) {
- self.header = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_header(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.header.is_none() {
- self.header = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.header.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_header(&mut self) -> ::std::vec::Vec<u8> {
- self.header.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-
- // required bytes body = 2;
-
- pub fn body(&self) -> &[u8] {
- match self.body.as_ref() {
- Some(v) => v,
- None => &[],
- }
- }
-
- pub fn clear_body(&mut self) {
- self.body = ::std::option::Option::None;
- }
-
- pub fn has_body(&self) -> bool {
- self.body.is_some()
- }
-
- // Param is passed by value, moved
- pub fn set_body(&mut self, v: ::std::vec::Vec<u8>) {
- self.body = ::std::option::Option::Some(v);
- }
-
- // Mutable pointer to the field.
- // If field is not initialized, it is initialized with default value first.
- pub fn mut_body(&mut self) -> &mut ::std::vec::Vec<u8> {
- if self.body.is_none() {
- self.body = ::std::option::Option::Some(::std::vec::Vec::new());
- }
- self.body.as_mut().unwrap()
- }
-
- // Take field
- pub fn take_body(&mut self) -> ::std::vec::Vec<u8> {
- self.body.take().unwrap_or_else(|| ::std::vec::Vec::new())
- }
-}
-
-impl ::protobuf::Message for HeaderAndBodyInternal {
- const NAME: &'static str = "HeaderAndBodyInternal";
-
- fn is_initialized(&self) -> bool {
- if self.header.is_none() {
- return false;
- }
- if self.body.is_none() {
- return false;
- }
- true
- }
-
- fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
- while let Some(tag) = is.read_raw_tag_or_eof()? {
- match tag {
- 10 => {
- self.header = ::std::option::Option::Some(is.read_bytes()?);
- },
- 18 => {
- self.body = ::std::option::Option::Some(is.read_bytes()?);
- },
- tag => {
- ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
- },
- };
- }
- ::std::result::Result::Ok(())
- }
-
- // Compute sizes of nested messages
- #[allow(unused_variables)]
- fn compute_size(&self) -> u64 {
- let mut my_size = 0;
- if let Some(v) = self.header.as_ref() {
- my_size += ::protobuf::rt::bytes_size(1, &v);
- }
- if let Some(v) = self.body.as_ref() {
- my_size += ::protobuf::rt::bytes_size(2, &v);
- }
- my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
- self.special_fields.cached_size().set(my_size as u32);
- my_size
- }
-
- fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
- if let Some(v) = self.header.as_ref() {
- os.write_bytes(1, v)?;
- }
- if let Some(v) = self.body.as_ref() {
- os.write_bytes(2, v)?;
- }
- os.write_unknown_fields(self.special_fields.unknown_fields())?;
- ::std::result::Result::Ok(())
- }
-
- fn special_fields(&self) -> &::protobuf::SpecialFields {
- &self.special_fields
- }
-
- fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
- &mut self.special_fields
- }
-
- fn new() -> HeaderAndBodyInternal {
- HeaderAndBodyInternal::new()
- }
-
- fn clear(&mut self) {
- self.header = ::std::option::Option::None;
- self.body = ::std::option::Option::None;
- self.special_fields.clear();
- }
-
- fn default_instance() -> &'static HeaderAndBodyInternal {
- static instance: HeaderAndBodyInternal = HeaderAndBodyInternal {
- header: ::std::option::Option::None,
- body: ::std::option::Option::None,
- special_fields: ::protobuf::SpecialFields::new(),
- };
- &instance
- }
-}
-
-#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:securemessage.EcP256PublicKey)
pub struct EcP256PublicKey {
// message fields
diff --git a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/ukey.rs b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/ukey.rs
index 9be6b3d..5067ddd 100644
--- a/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/ukey.rs
+++ b/nearby/connections/ukey2/ukey2_proto/src/ukey2_all_proto/ukey.rs
@@ -1,4 +1,4 @@
-// Copyright 2023 Google LLC
+// 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.
@@ -499,8 +499,8 @@ pub struct Ukey2ClientInit {
pub cipher_commitments: ::std::vec::Vec<ukey2client_init::CipherCommitment>,
// @@protoc_insertion_point(field:securegcm.Ukey2ClientInit.next_protocol)
pub next_protocol: ::std::option::Option<::std::string::String>,
- // @@protoc_insertion_point(field:securegcm.Ukey2ClientInit.other_next_protocols)
- pub other_next_protocols: ::std::vec::Vec<::std::string::String>,
+ // @@protoc_insertion_point(field:securegcm.Ukey2ClientInit.next_protocols)
+ pub next_protocols: ::std::vec::Vec<::std::string::String>,
// special fields
// @@protoc_insertion_point(special_field:securegcm.Ukey2ClientInit.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -632,7 +632,7 @@ impl ::protobuf::Message for Ukey2ClientInit {
self.next_protocol = ::std::option::Option::Some(is.read_string()?);
},
42 => {
- self.other_next_protocols.push(is.read_string()?);
+ self.next_protocols.push(is.read_string()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
@@ -659,7 +659,7 @@ impl ::protobuf::Message for Ukey2ClientInit {
if let Some(v) = self.next_protocol.as_ref() {
my_size += ::protobuf::rt::string_size(4, &v);
}
- for value in &self.other_next_protocols {
+ for value in &self.next_protocols {
my_size += ::protobuf::rt::string_size(5, &value);
};
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
@@ -680,7 +680,7 @@ impl ::protobuf::Message for Ukey2ClientInit {
if let Some(v) = self.next_protocol.as_ref() {
os.write_string(4, v)?;
}
- for v in &self.other_next_protocols {
+ for v in &self.next_protocols {
os.write_string(5, &v)?;
};
os.write_unknown_fields(self.special_fields.unknown_fields())?;
@@ -704,7 +704,7 @@ impl ::protobuf::Message for Ukey2ClientInit {
self.random = ::std::option::Option::None;
self.cipher_commitments.clear();
self.next_protocol = ::std::option::Option::None;
- self.other_next_protocols.clear();
+ self.next_protocols.clear();
self.special_fields.clear();
}
@@ -714,7 +714,7 @@ impl ::protobuf::Message for Ukey2ClientInit {
random: ::std::option::Option::None,
cipher_commitments: ::std::vec::Vec::new(),
next_protocol: ::std::option::Option::None,
- other_next_protocols: ::std::vec::Vec::new(),
+ next_protocols: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
diff --git a/nearby/connections/ukey2/ukey2_shell/Cargo.toml b/nearby/connections/ukey2/ukey2_shell/Cargo.toml
index 2ac12fa..c5c84ea 100644
--- a/nearby/connections/ukey2/ukey2_shell/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_shell/Cargo.toml
@@ -9,6 +9,5 @@ workspace = true
[dependencies]
crypto_provider_rustcrypto = { workspace = true, features = [ "alloc" ] }
-ukey2_rs = { version = "0.1.0", path = "../ukey2" }
ukey2_connections = { version = "0.1.0", path = "../ukey2_connections" }
clap = { workspace = true, features = ["std", "derive"] }
diff --git a/nearby/connections/ukey2/ukey2_shell/src/main.rs b/nearby/connections/ukey2/ukey2_shell/src/main.rs
index 3eca7b0..c50ee93 100644
--- a/nearby/connections/ukey2/ukey2_shell/src/main.rs
+++ b/nearby/connections/ukey2/ukey2_shell/src/main.rs
@@ -25,10 +25,9 @@ use clap::Parser;
use crypto_provider_rustcrypto::RustCrypto;
use ukey2_connections::{
- D2DConnectionContextV1, D2DHandshakeContext, InitiatorD2DHandshakeContext,
- ServerD2DHandshakeContext,
+ D2DConnectionContextV1, D2DHandshakeContext, HandshakeImplementation,
+ InitiatorD2DHandshakeContext, NextProtocol, ServerD2DHandshakeContext,
};
-use ukey2_rs::HandshakeImplementation;
const MODE_INITIATOR: &str = "initiator";
const MODE_RESPONDER: &str = "responder";
@@ -139,6 +138,7 @@ impl Ukey2Shell {
fn run_as_initiator(&self) -> bool {
let mut initiator_ctx = InitiatorD2DHandshakeContext::<RustCrypto, _>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ vec![NextProtocol::Aes256CbcHmacSha256, NextProtocol::Aes256GcmSiv],
);
write_frame(initiator_ctx.get_next_handshake_message().unwrap());
let server_init_msg = read_frame();
@@ -166,6 +166,7 @@ impl Ukey2Shell {
fn run_as_responder(&self) -> bool {
let mut server_ctx = ServerD2DHandshakeContext::<RustCrypto, _>::new(
HandshakeImplementation::PublicKeyInProtobuf,
+ &[NextProtocol::Aes256GcmSiv, NextProtocol::Aes256CbcHmacSha256],
);
let initiator_init_msg = read_frame();
server_ctx.handle_handshake_message(initiator_init_msg.as_slice()).unwrap();
diff --git a/nearby/crypto/README.md b/nearby/crypto/README.md
index 4cb65be..698a954 100644
--- a/nearby/crypto/README.md
+++ b/nearby/crypto/README.md
@@ -1,7 +1,7 @@
# What is this?
A crypto provider that abstracts over different crypto implementations, mainly the Rust
-implementations by [RustCrypto](https://github.com/RustCrypto), OpenSSL and BoringSSL.
+implementations by [RustCrypto](https://github.com/RustCrypto) and BoringSSL.
## Project structure
@@ -11,7 +11,7 @@ Our own abstraction on top of crypto implementations, including functionalities
like AES, SHA2, X25519 and P256 ECDH, HKDF, HMAC, etc.
Two implementations are currently provided, `crypto_provider_rustcrypto` and
-`crypto_provider_openssl`.
+`crypto_provider_boringssl`.
#### `crypto_provider::aes`
Abstraction on top plain AES, including AES-CTR and AES-CBC.
@@ -26,25 +26,11 @@ and is easy to use from FFI (when we get to that point).
Implementations of `crypto_provider` types using the convenient pure-Rust primitives
from [Rust Crypto](https://github.com/RustCrypto).
-### `crypto_provider_openssl`
+### `crypto_provider_boringssl`
Implementations of `crypto_provider` types using the
-[openSSL Rust crate](https://github.com/sfackler/rust-openssl), which is a Rust
-wrapper for openSSL.
-
-#### Using BoringSSL
-
-`crypto_provider_openssl` can also be made to use BoringSSL via the `boringssl` feature. This
-translates to using the `openssl` and `openssl-sys` crates' `unstable_boringssl` feature. Since the
-depenedency `bssl-sys` is not on crates.io, to test the BoringSSL integration, you'll need to run
-`cargo run -- build-boringssl`, which clones BoringSSL. Then, to use the Android version of
-`rust-openssl`, run `cargo run -- prepare-rust-openssl`.
-
-* Run `cargo run -- build-boringssl` to setup the workspace
-* Run `cargo --config=.cargo/config-boringssl.toml test --features=boringssl` to test the crypto
- provider implementations.
-* Run `cargo --config=.cargo/config-boringssl.toml run -p <package> --features=openssl,boringssl
- --no-default-features` on FFI, JNI, or shell targets to make them use BoringSSL.
+[bssl-crypto](https://boringssl.googlesource.com/boringssl/+/master/rust/bssl-crypto), which is a
+Rust binding layer for BoringSSL.
## Setup
diff --git a/nearby/crypto/crypto_provider/Cargo.toml b/nearby/crypto/crypto_provider/Cargo.toml
index 1a588bb..bafdfcc 100644
--- a/nearby/crypto/crypto_provider/Cargo.toml
+++ b/nearby/crypto/crypto_provider/Cargo.toml
@@ -13,8 +13,7 @@ tinyvec.workspace = true
[dev-dependencies]
criterion.workspace = true
hex-literal.workspace = true
-crypto_provider_openssl.workspace = true
-crypto_provider_rustcrypto = { workspace = true, features = ["std"] }
+crypto_provider_default = { workspace = true, features = ["std"]}
rand_ext.workspace = true
rand.workspace = true
diff --git a/nearby/crypto/crypto_provider/benches/constant_time_eq_bench.rs b/nearby/crypto/crypto_provider/benches/constant_time_eq_bench.rs
index 70c65cf..3859616 100644
--- a/nearby/crypto/crypto_provider/benches/constant_time_eq_bench.rs
+++ b/nearby/crypto/crypto_provider/benches/constant_time_eq_bench.rs
@@ -18,8 +18,7 @@ use criterion::{
criterion_group, criterion_main, measurement::WallTime, BatchSize, BenchmarkGroup, Criterion,
};
use crypto_provider::CryptoProvider;
-use crypto_provider_openssl::Openssl;
-use crypto_provider_rustcrypto::RustCrypto;
+use crypto_provider_default::CryptoProviderImpl;
use rand::{distributions::Standard, rngs::ThreadRng, Rng};
fn constant_time_eq_equals(c: &mut Criterion) {
@@ -57,8 +56,7 @@ fn constant_time_eq_equals(c: &mut Criterion) {
}
}
- add_benches::<RustCrypto>(&mut group, &mut rng);
- add_benches::<Openssl>(&mut group, &mut rng);
+ add_benches::<CryptoProviderImpl>(&mut group, &mut rng);
}
criterion_group!(benches, constant_time_eq_equals);
diff --git a/nearby/crypto/crypto_provider/benches/hkdf_bench.rs b/nearby/crypto/crypto_provider/benches/hkdf_bench.rs
index e73f8cf..6464c7e 100644
--- a/nearby/crypto/crypto_provider/benches/hkdf_bench.rs
+++ b/nearby/crypto/crypto_provider/benches/hkdf_bench.rs
@@ -19,8 +19,7 @@ use hex_literal::hex;
use crypto_provider::hkdf::Hkdf;
use crypto_provider::CryptoProvider;
-use crypto_provider_openssl::Openssl;
-use crypto_provider_rustcrypto::RustCrypto;
+use crypto_provider_default::CryptoProviderImpl;
// simple benchmark, which creates a new hmac, updates once, then finalizes
fn hkdf_sha256_operations<C: CryptoProvider>(c: &mut Criterion) {
@@ -46,6 +45,6 @@ fn hkdf_sha256_operations<C: CryptoProvider>(c: &mut Criterion) {
});
}
-criterion_group!(benches, hkdf_sha256_operations::<RustCrypto>, hkdf_sha256_operations::<Openssl>,);
+criterion_group!(benches, hkdf_sha256_operations::<CryptoProviderImpl>);
criterion_main!(benches);
diff --git a/nearby/crypto/crypto_provider/benches/hmac_bench.rs b/nearby/crypto/crypto_provider/benches/hmac_bench.rs
index 9bcfde0..0d856d4 100644
--- a/nearby/crypto/crypto_provider/benches/hmac_bench.rs
+++ b/nearby/crypto/crypto_provider/benches/hmac_bench.rs
@@ -18,8 +18,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
use crypto_provider::hmac::Hmac;
use crypto_provider::{CryptoProvider, CryptoRng};
-use crypto_provider_openssl::Openssl;
-use crypto_provider_rustcrypto::RustCrypto;
+use crypto_provider_default::CryptoProviderImpl;
use rand_ext::random_bytes;
// simple benchmark, which creates a new hmac, updates once, then finalizes
@@ -53,10 +52,8 @@ fn hmac_sha512_operations<C: CryptoProvider>(c: &mut Criterion) {
criterion_group!(
benches,
- hmac_sha256_operations::<RustCrypto>,
- hmac_sha256_operations::<Openssl>,
- hmac_sha512_operations::<RustCrypto>,
- hmac_sha512_operations::<Openssl>
+ hmac_sha256_operations::<CryptoProviderImpl>,
+ hmac_sha512_operations::<CryptoProviderImpl>,
);
criterion_main!(benches);
diff --git a/nearby/crypto/crypto_provider/src/aes/mod.rs b/nearby/crypto/crypto_provider/src/aes/mod.rs
index e359bad..b3dbd6a 100644
--- a/nearby/crypto/crypto_provider/src/aes/mod.rs
+++ b/nearby/crypto/crypto_provider/src/aes/mod.rs
@@ -15,7 +15,7 @@
//! An abstraction layer around AES implementations.
//!
//! The design is an attempt to make it easy to provide implementations that are both idiomatic
-//! Rust (e.g. RustCrypto) as well as FFI-backed (e.g. openssl and other C impls).
+//! Rust (e.g. RustCrypto) as well as FFI-backed (e.g. boringSSL and other C impls).
use core::{array, fmt};
pub mod ctr;
diff --git a/nearby/crypto/crypto_provider/src/ed25519.rs b/nearby/crypto/crypto_provider/src/ed25519.rs
index b435ca2..94e98d0 100644
--- a/nearby/crypto/crypto_provider/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider/src/ed25519.rs
@@ -14,16 +14,7 @@
use core::fmt::Debug;
-/// Collection of types used to provide an implementation of ed25519, the Edwards-curve Digital
-/// Signature Algorithm scheme using sha-512 (sha2) and Curve25519
-pub trait Ed25519Provider {
- /// The keypair which includes both public and secret halves of an asymmetric key.
- type KeyPair: KeyPair<PublicKey = Self::PublicKey, Signature = Self::Signature>;
- /// The ed25519 public key, used when verifying a message
- type PublicKey: PublicKey<Signature = Self::Signature>;
- /// The ed25519 signature which is the result of signing a message
- type Signature: Signature;
-}
+// User-facing, crypto-provider independent structs
/// The length of a ed25519 `Signature`, in bytes.
pub const SIGNATURE_LENGTH: usize = 64;
@@ -74,35 +65,139 @@ impl core::default::Default for RawPrivateKeyPermit {
/// Useful for when you want a data-structure to be
/// crypto-provider independent and contain a private key.
#[derive(Clone)]
-pub struct PrivateKey {
- wrapped: RawPrivateKey,
-}
+pub struct PrivateKey(RawPrivateKey);
impl PrivateKey {
/// Derives the public key corresponding to this private key.
- pub fn derive_public_key<E: Ed25519Provider>(&self) -> E::PublicKey {
+ pub fn derive_public_key<E: Ed25519Provider>(&self) -> PublicKey {
let key_pair = E::KeyPair::from_private_key(self);
- key_pair.public()
+ key_pair.public_key().to_external()
}
+ /// Sign the given message and return a digital signature
+ pub fn sign<E: Ed25519Provider>(&self, msg: &[u8]) -> Signature {
+ let key_pair = E::KeyPair::from_private_key(self);
+ key_pair.sign(msg).to_external()
+ }
+ /// Generate an ed25519 private key from a CSPRNG
+ /// generate is not available in `no-std`.
+ #[cfg(feature = "std")]
+ pub fn generate<E: Ed25519Provider>() -> Self {
+ let key_pair = E::KeyPair::generate();
+ key_pair.private_key()
+ }
+
/// Returns the raw bytes of this private key.
/// This operation is only possible while holding a [`RawPrivateKeyPermit`].
pub fn raw_private_key(&self, _permit: &RawPrivateKeyPermit) -> RawPrivateKey {
- self.wrapped
+ self.0
}
/// Constructs a private key from the raw bytes of the key.
/// This operation is only possible while holding a [`RawPrivateKeyPermit`].
pub fn from_raw_private_key(wrapped: RawPrivateKey, _permit: &RawPrivateKeyPermit) -> Self {
- Self { wrapped }
+ PrivateKey(wrapped)
+ }
+}
+
+/// error returned when bad bytes are provided to generate keypair
+#[derive(Debug)]
+pub struct InvalidPublicKeyBytes;
+
+/// Error returned if the verification on the signature + message fails
+#[derive(Debug)]
+pub struct SignatureError;
+
+/// A crypto-provider-independent representation of a valid
+/// public key for an ed25519 key-pair in the Edwards Y-format.
+///
+/// Useful for when you want a data-structure to be crypto-provider
+/// independent and contain a public key.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct PublicKey(RawPublicKey);
+
+impl PublicKey {
+ /// Attempts to parse a public key from an array of bytes.
+ /// If the input is not in the Edwards Y-format, this method
+ /// will yield an `InvalidPublicKeyBytes` error.
+ pub fn from_bytes<E: Ed25519Provider>(
+ wrapped: RawPublicKey,
+ ) -> Result<Self, InvalidPublicKeyBytes> {
+ // Simply verify that we can construct the crypto-provider-dependent variant.
+ let _ = <E::PublicKey as PublicKeyImpl>::from_bytes(&wrapped)?;
+ Ok(PublicKey(wrapped))
+ }
+ /// Converts this public-key into the raw bytes of this public-key.
+ pub fn into_bytes(self) -> RawPublicKey {
+ self.0
+ }
+
+ /// Converts this crypto-provider-independent public key to a crypto-provider's internal rep.
+ #[allow(clippy::expect_used)]
+ fn as_internal<E: Ed25519Provider>(&self) -> E::PublicKey {
+ <E::PublicKey as PublicKeyImpl>::from_bytes(&self.0)
+ .expect("Public key bytes validated upon construction.")
+ }
+
+ /// Succeeds if the signature on the given message is verified
+ /// by this public key.
+ pub fn verify_strict<E: Ed25519Provider>(
+ &self,
+ message: &[u8],
+ signature: Signature,
+ ) -> Result<(), SignatureError> {
+ let public_key = self.as_internal::<E>();
+ let signature = signature.as_internal::<E>();
+ public_key.verify_strict(message, &signature)
+ }
+}
+
+/// A crypto-provider-independent representation of an Ed25519 signature.
+/// The underlying representation here can be any arbitrary bytes - verifying
+/// code handles determining whether/not the signature actually corresponds
+/// to a real Ed25519 signature and matches the given public key.
+#[derive(Clone)]
+pub struct Signature(RawSignature);
+
+impl From<RawSignature> for Signature {
+ fn from(wrapped: RawSignature) -> Self {
+ Signature(wrapped)
}
}
+impl Signature {
+ /// Constructs a signature from raw bytes.
+ pub fn new(wrapped: RawSignature) -> Self {
+ Signature(wrapped)
+ }
+ /// Transforms this signature back into raw bytes.
+ pub fn to_bytes(self) -> RawSignature {
+ self.0
+ }
+ /// Converts this crypto-provider-independent signature to a crypto-provider's internal rep.
+ fn as_internal<E: Ed25519Provider>(&self) -> E::Signature {
+ <E::Signature as SignatureImpl>::from_bytes(&self.0)
+ }
+}
+
+// Implementor-facing crypto-provider-internal traits.
+
+/// Collection of types used to provide an implementation of ed25519, the Edwards-curve Digital
+/// Signature Algorithm scheme using sha-512 (sha2) and Curve25519
+pub trait Ed25519Provider {
+ /// The internal representation of a keypair which includes both public and secret halves of an asymmetric key.
+ type KeyPair: KeyPairImpl<PublicKey = Self::PublicKey, Signature = Self::Signature>;
+ /// The internal representation of an ed25519 public key, used when verifying a message
+ type PublicKey: PublicKeyImpl<Signature = Self::Signature>;
+ /// The internal representation of an ed25519 signature which is the result of signing a message
+ type Signature: SignatureImpl;
+}
+
/// The keypair which includes both public and secret halves of an asymmetric key.
-pub trait KeyPair: Sized {
+pub trait KeyPairImpl: Sized {
/// The ed25519 public key, used when verifying a message
- type PublicKey: PublicKey;
+ type PublicKey: PublicKeyImpl;
/// The ed25519 signature returned when signing a message
- type Signature: Signature;
+ type Signature: SignatureImpl;
/// Returns the private key bytes of the `KeyPair`.
/// This operation is only possible while holding a [`RawPrivateKeyPermit`].
@@ -120,7 +215,7 @@ pub trait KeyPair: Sized {
// since the way that we're exposing it would require a valid
// [`RawPrivateKeyPermit`] to extract them again.
let wrapped = self.raw_private_key(&RawPrivateKeyPermit::new());
- PrivateKey { wrapped }
+ PrivateKey(wrapped)
}
/// Builds a key-pair from a [`PrivateKey`], given in an opaque form.
@@ -132,7 +227,7 @@ pub trait KeyPair: Sized {
// the bytes of the private key, since the way that they
// were originally expressed would still require a valid
// [`RawPrivateKeyPermit`] to access them.
- let raw_private_key = &private_key.wrapped;
+ let raw_private_key = &private_key.0;
Self::from_raw_private_key(raw_private_key, &RawPrivateKeyPermit::new())
}
@@ -145,34 +240,49 @@ pub trait KeyPair: Sized {
fn generate() -> Self;
/// getter function for the Public Key of the key pair
- fn public(&self) -> Self::PublicKey;
+ fn public_key(&self) -> Self::PublicKey;
}
/// An ed25519 signature
-pub trait Signature: Sized {
- /// Create a new signature from a byte slice, and return an error on an invalid signature
- /// An `Ok` result does not guarantee that the Signature is valid, however it will catch a
- /// number of invalid signatures relatively inexpensively.
+pub trait SignatureImpl: Sized {
+ /// Create a new signature from a fixed size byte array. This represents a container for the
+ /// byte serialization of an Ed25519 signature, and does not necessarily represent well-formed
+ /// field or curve elements.
+ ///
+ /// Signature verification libraries are expected to reject invalid field
+ /// elements at the time a signature is verified (not constructed).
fn from_bytes(bytes: &RawSignature) -> Self;
/// Returns a slice of the signature bytes
fn to_bytes(&self) -> RawSignature;
+
+ /// Returns a crypto-provider-independent `Signature` from this implementation-specific struct.
+ fn to_external(&self) -> Signature {
+ let wrapped = self.to_bytes();
+ Signature(wrapped)
+ }
}
/// An ed25519 public key
-pub trait PublicKey {
+pub trait PublicKeyImpl {
/// the signature type being used by verify
- type Signature: Signature;
+ type Signature: SignatureImpl;
/// Builds this public key from an array of bytes in
/// the format yielded by `to_bytes`.
- fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidBytes>
+ fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidPublicKeyBytes>
where
Self: Sized;
/// Yields the bytes of the public key
fn to_bytes(&self) -> RawPublicKey;
+ /// Returns a crypto-provider-independent `PublicKey` from this implementation-specific struct.
+ fn to_external(&self) -> PublicKey {
+ let wrapped = self.to_bytes();
+ PublicKey(wrapped)
+ }
+
/// Succeeds if the signature was a valid signature created by this Keypair on the prehashed_message.
fn verify_strict(
&self,
@@ -180,11 +290,3 @@ pub trait PublicKey {
signature: &Self::Signature,
) -> Result<(), SignatureError>;
}
-
-/// error returned when bad bytes are provided to generate keypair
-#[derive(Debug)]
-pub struct InvalidBytes;
-
-/// Error returned if the verification on the signature + message fails
-#[derive(Debug)]
-pub struct SignatureError;
diff --git a/nearby/crypto/crypto_provider_boringssl/Cargo.lock b/nearby/crypto/crypto_provider_boringssl/Cargo.lock
index 11ec2e3..356a65d 100644
--- a/nearby/crypto/crypto_provider_boringssl/Cargo.lock
+++ b/nearby/crypto/crypto_provider_boringssl/Cargo.lock
@@ -19,7 +19,7 @@ checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"
[[package]]
name = "bssl-crypto"
-version = "0.1.0"
+version = "0.2.0"
dependencies = [
"bssl-sys",
]
@@ -66,6 +66,12 @@ dependencies = [
]
[[package]]
+name = "either"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+
+[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -95,6 +101,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
+[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -333,6 +348,7 @@ name = "test_helper"
version = "0.1.0"
dependencies = [
"hex",
+ "itertools",
"serde_json",
]
diff --git a/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs b/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs
index 03bb087..75fb385 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm.rs
@@ -19,52 +19,89 @@ use bssl_crypto::aead::Aead as _;
use crypto_provider::aead::{Aead, AeadError, AeadInit};
use crypto_provider::aes::{Aes128Key, Aes256Key, AesKey};
-pub struct AesGcm(bssl_crypto::aead::AesGcm);
+pub struct AesGcm128(bssl_crypto::aead::Aes128Gcm);
-impl AeadInit<Aes128Key> for AesGcm {
+pub struct AesGcm256(bssl_crypto::aead::Aes256Gcm);
+
+impl AeadInit<Aes128Key> for AesGcm128 {
fn new(key: &Aes128Key) -> Self {
- Self(bssl_crypto::aead::new_aes_128_gcm(key.as_array()))
+ Self(bssl_crypto::aead::Aes128Gcm::new(key.as_array()))
+ }
+}
+
+impl crypto_provider::aead::AesGcm for AesGcm128 {}
+
+impl Aead for AesGcm128 {
+ const TAG_SIZE: usize = 16;
+ type Nonce = [u8; 12];
+ type Tag = [u8; 16];
+
+ fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+ Ok(self.0.seal(nonce, msg, aad))
+ }
+
+ fn encrypt_detached(
+ &self,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ ) -> Result<Self::Tag, AeadError> {
+ Ok(self.0.seal_in_place(nonce, msg, aad))
+ }
+
+ fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+ self.0.open(nonce, msg, aad).ok_or(AeadError)
+ }
+
+ fn decrypt_detached(
+ &self,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ tag: &Self::Tag,
+ ) -> Result<(), AeadError> {
+ self.0.open_in_place(nonce, msg, tag, aad).map_err(|_| AeadError)
}
}
-impl AeadInit<Aes256Key> for AesGcm {
+impl AeadInit<Aes256Key> for AesGcm256 {
fn new(key: &Aes256Key) -> Self {
- Self(bssl_crypto::aead::new_aes_256_gcm(key.as_array()))
+ Self(bssl_crypto::aead::Aes256Gcm::new(key.as_array()))
}
}
-impl crypto_provider::aead::AesGcm for AesGcm {}
+impl crypto_provider::aead::AesGcm for AesGcm256 {}
-impl Aead for AesGcm {
+impl Aead for AesGcm256 {
const TAG_SIZE: usize = 16;
type Nonce = [u8; 12];
type Tag = [u8; 16];
fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
- self.0.encrypt(msg, aad, nonce).map_err(|_| AeadError)
+ Ok(self.0.seal(nonce, msg, aad))
}
fn encrypt_detached(
&self,
- _msg: &mut [u8],
- _aad: &[u8],
- _nonce: &Self::Nonce,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
) -> Result<Self::Tag, AeadError> {
- unimplemented!("Not yet supported by boringssl")
+ Ok(self.0.seal_in_place(nonce, msg, aad))
}
fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
- self.0.decrypt(msg, aad, nonce).map_err(|_| AeadError)
+ self.0.open(nonce, msg, aad).ok_or(AeadError)
}
fn decrypt_detached(
&self,
- _msg: &mut [u8],
- _aad: &[u8],
- _nonce: &Self::Nonce,
- _tag: &Self::Tag,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ tag: &Self::Tag,
) -> Result<(), AeadError> {
- unimplemented!("Not yet supported by boringssl")
+ self.0.open_in_place(nonce, msg, tag, aad).map_err(|_| AeadError)
}
}
@@ -78,12 +115,12 @@ mod tests {
use super::*;
#[apply(aes_128_gcm_test_cases)]
- fn aes_gcm_128_test(testcase: CryptoProviderTestCase<AesGcm>) {
+ fn aes_gcm_128_test(testcase: CryptoProviderTestCase<AesGcm128>) {
testcase(PhantomData);
}
#[apply(aes_256_gcm_test_cases)]
- fn aes_gcm_256_test(testcase: CryptoProviderTestCase<AesGcm>) {
+ fn aes_gcm_256_test(testcase: CryptoProviderTestCase<AesGcm256>) {
testcase(PhantomData);
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm_siv.rs b/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm_siv.rs
index d1fb0e7..ac26c43 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm_siv.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/aead/aes_gcm_siv.rs
@@ -18,52 +18,89 @@ use bssl_crypto::aead::Aead as _;
use crypto_provider::aead::{Aead, AeadError, AeadInit};
use crypto_provider::aes::{Aes128Key, Aes256Key, AesKey};
-pub struct AesGcmSiv(bssl_crypto::aead::AesGcmSiv);
+pub struct AesGcmSiv128(bssl_crypto::aead::Aes128GcmSiv);
-impl AeadInit<Aes128Key> for AesGcmSiv {
+impl AeadInit<Aes128Key> for AesGcmSiv128 {
fn new(key: &Aes128Key) -> Self {
- Self(bssl_crypto::aead::new_aes_128_gcm_siv(key.as_array()))
+ Self(bssl_crypto::aead::Aes128GcmSiv::new(key.as_array()))
}
}
-impl AeadInit<Aes256Key> for AesGcmSiv {
+impl crypto_provider::aead::AesGcmSiv for AesGcmSiv128 {}
+
+impl Aead for AesGcmSiv128 {
+ const TAG_SIZE: usize = 16;
+ type Nonce = [u8; 12];
+ type Tag = [u8; 16];
+
+ fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+ Ok(self.0.seal(nonce, msg, aad))
+ }
+
+ fn encrypt_detached(
+ &self,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ ) -> Result<Self::Tag, AeadError> {
+ Ok(self.0.seal_in_place(nonce, msg, aad))
+ }
+
+ fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
+ self.0.open(nonce, msg, aad).ok_or(AeadError)
+ }
+
+ fn decrypt_detached(
+ &self,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ tag: &Self::Tag,
+ ) -> Result<(), AeadError> {
+ self.0.open_in_place(nonce, msg, tag, aad).map_err(|_| AeadError)
+ }
+}
+
+pub struct AesGcmSiv256(bssl_crypto::aead::Aes256GcmSiv);
+
+impl AeadInit<Aes256Key> for AesGcmSiv256 {
fn new(key: &Aes256Key) -> Self {
- Self(bssl_crypto::aead::new_aes_256_gcm_siv(key.as_array()))
+ Self(bssl_crypto::aead::Aes256GcmSiv::new(key.as_array()))
}
}
-impl crypto_provider::aead::AesGcmSiv for AesGcmSiv {}
+impl crypto_provider::aead::AesGcmSiv for AesGcmSiv256 {}
-impl Aead for AesGcmSiv {
+impl Aead for AesGcmSiv256 {
const TAG_SIZE: usize = 16;
type Nonce = [u8; 12];
type Tag = [u8; 16];
fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
- self.0.encrypt(msg, aad, nonce).map_err(|_| AeadError)
+ Ok(self.0.seal(nonce, msg, aad))
}
fn encrypt_detached(
&self,
- _msg: &mut [u8],
- _aad: &[u8],
- _nonce: &Self::Nonce,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
) -> Result<Self::Tag, AeadError> {
- unimplemented!("Not yet supported by boringssl")
+ Ok(self.0.seal_in_place(nonce, msg, aad))
}
fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &Self::Nonce) -> Result<Vec<u8>, AeadError> {
- self.0.decrypt(msg, aad, nonce).map_err(|_| AeadError)
+ self.0.open(nonce, msg, aad).ok_or(AeadError)
}
fn decrypt_detached(
&self,
- _msg: &mut [u8],
- _aad: &[u8],
- _nonce: &Self::Nonce,
- _tag: &Self::Tag,
+ msg: &mut [u8],
+ aad: &[u8],
+ nonce: &Self::Nonce,
+ tag: &Self::Tag,
) -> Result<(), AeadError> {
- unimplemented!("Not yet supported by boringssl")
+ self.0.open_in_place(nonce, msg, tag, aad).map_err(|_| AeadError)
}
}
@@ -77,12 +114,12 @@ mod tests {
use super::*;
#[apply(aes_128_gcm_siv_test_cases)]
- fn aes_gcm_siv_128_test(testcase: CryptoProviderTestCase<AesGcmSiv>) {
+ fn aes_gcm_siv_128_test(testcase: CryptoProviderTestCase<AesGcmSiv128>) {
testcase(PhantomData);
}
#[apply(aes_256_gcm_siv_test_cases)]
- fn aes_gcm_siv_256_test(testcase: CryptoProviderTestCase<AesGcmSiv>) {
+ fn aes_gcm_siv_256_test(testcase: CryptoProviderTestCase<AesGcmSiv256>) {
testcase(PhantomData);
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/aes/mod.rs b/nearby/crypto/crypto_provider_boringssl/src/aes/mod.rs
index d5cbe58..d9f3315 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/aes/mod.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/aes/mod.rs
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use bssl_crypto::aes::{AesDecryptKey, AesEncryptKey};
+use bssl_crypto::aes::{DecryptKey, EncryptKey};
use crypto_provider::aes::{
Aes, Aes128Key, Aes256Key, AesBlock, AesCipher, AesDecryptCipher, AesEncryptCipher, AesKey,
};
@@ -40,28 +40,28 @@ impl Aes for Aes256 {
}
/// A BoringSSL backed AES-128 Encryption Cipher
-pub struct Aes128EncryptCipher(AesEncryptKey);
+pub struct Aes128EncryptCipher(EncryptKey);
/// A BoringSSL backed AES-128 Decryption Cipher
-pub struct Aes128DecryptCipher(AesDecryptKey);
+pub struct Aes128DecryptCipher(DecryptKey);
/// A BoringSSL backed AES-256 Encryption Cipher
-pub struct Aes256EncryptCipher(AesEncryptKey);
+pub struct Aes256EncryptCipher(EncryptKey);
/// A BoringSSL backed AES-256 Decryption Cipher
-pub struct Aes256DecryptCipher(AesDecryptKey);
+pub struct Aes256DecryptCipher(DecryptKey);
impl AesCipher for Aes128EncryptCipher {
type Key = Aes128Key;
fn new(key: &Self::Key) -> Self {
- Self(bssl_crypto::aes::AesEncryptKey::new_aes_128(*key.as_array()))
+ Self(EncryptKey::new_128(key.as_array()))
}
}
impl AesEncryptCipher for Aes128EncryptCipher {
fn encrypt(&self, block: &mut AesBlock) {
- bssl_crypto::aes::Aes::encrypt(&self.0, block)
+ self.0.encrypt_in_place(block)
}
}
@@ -69,13 +69,13 @@ impl AesCipher for Aes128DecryptCipher {
type Key = Aes128Key;
fn new(key: &Self::Key) -> Self {
- Self(bssl_crypto::aes::AesDecryptKey::new_aes_128(*key.as_array()))
+ Self(DecryptKey::new_128(key.as_array()))
}
}
impl AesDecryptCipher for Aes128DecryptCipher {
fn decrypt(&self, block: &mut AesBlock) {
- bssl_crypto::aes::Aes::decrypt(&self.0, block)
+ self.0.decrypt_in_place(block)
}
}
@@ -83,13 +83,13 @@ impl AesCipher for Aes256EncryptCipher {
type Key = Aes256Key;
fn new(key: &Self::Key) -> Self {
- Self(bssl_crypto::aes::AesEncryptKey::new_aes_256(*key.as_array()))
+ Self(EncryptKey::new_256(key.as_array()))
}
}
impl AesEncryptCipher for Aes256EncryptCipher {
fn encrypt(&self, block: &mut AesBlock) {
- bssl_crypto::aes::Aes::encrypt(&self.0, block)
+ self.0.encrypt_in_place(block)
}
}
@@ -97,13 +97,13 @@ impl AesCipher for Aes256DecryptCipher {
type Key = Aes256Key;
fn new(key: &Self::Key) -> Self {
- Self(bssl_crypto::aes::AesDecryptKey::new_aes_256(*key.as_array()))
+ Self(DecryptKey::new_256(key.as_array()))
}
}
impl AesDecryptCipher for Aes256DecryptCipher {
fn decrypt(&self, block: &mut AesBlock) {
- bssl_crypto::aes::Aes::decrypt(&self.0, block)
+ self.0.decrypt_in_place(block)
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/ed25519.rs b/nearby/crypto/crypto_provider_boringssl/src/ed25519.rs
index b5c374a..0841e2b 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/ed25519.rs
@@ -13,8 +13,8 @@
// limitations under the License.
use crypto_provider::ed25519::{
- InvalidBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature, Signature as _,
- SignatureError,
+ InvalidPublicKeyBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature,
+ SignatureError, SignatureImpl,
};
pub struct Ed25519;
@@ -27,7 +27,7 @@ impl crypto_provider::ed25519::Ed25519Provider for Ed25519 {
pub struct KeyPair(bssl_crypto::ed25519::PrivateKey);
-impl crypto_provider::ed25519::KeyPair for KeyPair {
+impl crypto_provider::ed25519::KeyPairImpl for KeyPair {
type PublicKey = PublicKey;
type Signature = Signature;
@@ -39,7 +39,7 @@ impl crypto_provider::ed25519::KeyPair for KeyPair {
where
Self: Sized,
{
- let private_key = bssl_crypto::ed25519::PrivateKey::new_from_seed(bytes);
+ let private_key = bssl_crypto::ed25519::PrivateKey::from_seed(bytes);
Self(private_key)
}
@@ -51,37 +51,37 @@ impl crypto_provider::ed25519::KeyPair for KeyPair {
Self(bssl_crypto::ed25519::PrivateKey::generate())
}
- fn public(&self) -> Self::PublicKey {
- PublicKey(self.0.public())
+ fn public_key(&self) -> Self::PublicKey {
+ PublicKey(self.0.to_public())
}
}
pub struct Signature(bssl_crypto::ed25519::Signature);
-impl crypto_provider::ed25519::Signature for Signature {
+impl crypto_provider::ed25519::SignatureImpl for Signature {
fn from_bytes(bytes: &RawSignature) -> Self {
- Self(bssl_crypto::ed25519::Signature::from_bytes(*bytes))
+ Self(bssl_crypto::ed25519::Signature::from(*bytes))
}
fn to_bytes(&self) -> RawSignature {
- self.0.to_bytes()
+ self.0
}
}
pub struct PublicKey(bssl_crypto::ed25519::PublicKey);
-impl crypto_provider::ed25519::PublicKey for PublicKey {
+impl crypto_provider::ed25519::PublicKeyImpl for PublicKey {
type Signature = Signature;
- fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidBytes>
+ fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidPublicKeyBytes>
where
Self: Sized,
{
- Ok(Self(bssl_crypto::ed25519::PublicKey::from_bytes(*bytes)))
+ Ok(Self(bssl_crypto::ed25519::PublicKey::from_bytes(bytes)))
}
fn to_bytes(&self) -> RawPublicKey {
- self.0.to_bytes()
+ *self.0.as_bytes()
}
fn verify_strict(
@@ -90,7 +90,7 @@ impl crypto_provider::ed25519::PublicKey for PublicKey {
signature: &Self::Signature,
) -> Result<(), SignatureError> {
self.0
- .verify(message, bssl_crypto::ed25519::Signature::from_bytes(signature.to_bytes()))
+ .verify(message, &bssl_crypto::ed25519::Signature::from(signature.to_bytes()))
.map_err(|_| SignatureError)
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs b/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
index c162d3d..7b01a2c 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
@@ -18,15 +18,21 @@
//! See the _Using BoringSSL_ section in `crypto/README.md` for instructions on
//! how to test against BoringSSL, or see the subcommands in the top level crate.
-use bssl_crypto::digest::Md;
+use bssl_crypto::digest::Algorithm;
+use bssl_crypto::hkdf::Salt;
+use core::marker::PhantomData;
use crypto_provider::hkdf::InvalidLength;
/// Struct providing BoringSSL implemented Hkdf operations.
-pub struct Hkdf<M: Md>(bssl_crypto::hkdf::Hkdf<M>);
+pub struct Hkdf<M: Algorithm>(bssl_crypto::hkdf::Prk, PhantomData<M>);
-impl<M: Md> crypto_provider::hkdf::Hkdf for Hkdf<M> {
+impl<M: Algorithm> crypto_provider::hkdf::Hkdf for Hkdf<M> {
fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self {
- Self(bssl_crypto::hkdf::Hkdf::<M>::new(salt, ikm))
+ let bssl_salt = match salt {
+ None => Salt::None,
+ Some(raw_salt) => Salt::NonEmpty(raw_salt),
+ };
+ Self(bssl_crypto::hkdf::Hkdf::<M>::extract(ikm, bssl_salt), PhantomData)
}
fn expand_multi_info(
@@ -37,14 +43,14 @@ impl<M: Md> crypto_provider::hkdf::Hkdf for Hkdf<M> {
if okm.is_empty() {
return Ok(());
}
- self.0.expand_multi_info(info_components, okm).map_err(|_| InvalidLength)
+ self.0.expand_into(&info_components.concat(), okm).map_err(|_| InvalidLength)
}
fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
if okm.is_empty() {
return Ok(());
}
- self.0.expand(info, okm).map_err(|_| InvalidLength)
+ self.0.expand_into(info, okm).map_err(|_| InvalidLength)
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/hmac.rs b/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
index 7a5e867..53e829e 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
@@ -19,7 +19,7 @@ pub struct HmacSha256(bssl_crypto::hmac::HmacSha256);
impl crypto_provider::hmac::Hmac<32> for HmacSha256 {
fn new_from_key(key: [u8; 32]) -> Self {
- Self(bssl_crypto::hmac::HmacSha256::new(key))
+ Self(bssl_crypto::hmac::HmacSha256::new(&key))
}
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
@@ -31,7 +31,7 @@ impl crypto_provider::hmac::Hmac<32> for HmacSha256 {
}
fn finalize(self) -> [u8; 32] {
- self.0.finalize()
+ self.0.digest()
}
fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
@@ -39,7 +39,7 @@ impl crypto_provider::hmac::Hmac<32> for HmacSha256 {
}
fn verify(self, tag: [u8; 32]) -> Result<(), MacError> {
- self.0.verify(tag).map_err(|_| MacError)
+ self.0.verify(&tag).map_err(|_| MacError)
}
fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
@@ -52,7 +52,7 @@ pub struct HmacSha512(bssl_crypto::hmac::HmacSha512);
impl crypto_provider::hmac::Hmac<64> for HmacSha512 {
fn new_from_key(key: [u8; 64]) -> Self {
- Self(bssl_crypto::hmac::HmacSha512::new(key))
+ Self(bssl_crypto::hmac::HmacSha512::new(&key))
}
fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
@@ -64,7 +64,7 @@ impl crypto_provider::hmac::Hmac<64> for HmacSha512 {
}
fn finalize(self) -> [u8; 64] {
- self.0.finalize()
+ self.0.digest()
}
fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
@@ -72,7 +72,7 @@ impl crypto_provider::hmac::Hmac<64> for HmacSha512 {
}
fn verify(self, tag: [u8; 64]) -> Result<(), MacError> {
- self.0.verify(tag).map_err(|_| MacError)
+ self.0.verify(&tag).map_err(|_| MacError)
}
fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
diff --git a/nearby/crypto/crypto_provider_boringssl/src/lib.rs b/nearby/crypto/crypto_provider_boringssl/src/lib.rs
index 75758b6..560169a 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/lib.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/lib.rs
@@ -23,7 +23,7 @@
//! Crate which provides impls for CryptoProvider backed by BoringSSL
//!
-use bssl_crypto::rand::rand_bytes;
+use bssl_crypto::rand_bytes;
use crypto_provider::{CryptoProvider, CryptoRng};
/// Implementation of `crypto_provider::aes` types using BoringSSL
@@ -69,18 +69,18 @@ impl CryptoProvider for Boringssl {
type AesCtr128 = aes::ctr::AesCtr128;
type AesCtr256 = aes::ctr::AesCtr256;
type Ed25519 = ed25519::Ed25519;
- type Aes128GcmSiv = aead::aes_gcm_siv::AesGcmSiv;
- type Aes256GcmSiv = aead::aes_gcm_siv::AesGcmSiv;
- type Aes128Gcm = aead::aes_gcm::AesGcm;
- type Aes256Gcm = aead::aes_gcm::AesGcm;
+ type Aes128GcmSiv = aead::aes_gcm_siv::AesGcmSiv128;
+ type Aes256GcmSiv = aead::aes_gcm_siv::AesGcmSiv256;
+ type Aes128Gcm = aead::aes_gcm::AesGcm128;
+ type Aes256Gcm = aead::aes_gcm::AesGcm256;
type CryptoRng = BoringSslRng;
fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
- bssl_crypto::mem::crypto_memcmp(a, b)
+ bssl_crypto::constant_time_compare(a, b)
}
}
-/// OpenSSL implemented random number generator
+/// BoringSSL implemented random number generator
pub struct BoringSslRng;
impl CryptoRng for BoringSslRng {
diff --git a/nearby/crypto/crypto_provider_boringssl/src/p256.rs b/nearby/crypto/crypto_provider_boringssl/src/p256.rs
index 7fefecd..564897b 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/p256.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/p256.rs
@@ -14,7 +14,9 @@
extern crate alloc;
+use alloc::vec;
use bssl_crypto::ecdh::{PrivateKey, PublicKey};
+use core::fmt::{Debug, Formatter};
use crypto_provider::{
elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey as _},
p256::{PointCompression, P256},
@@ -31,13 +33,25 @@ impl EcdhProvider<P256> for P256Ecdh {
}
/// A NIST-P256 public key.
-#[derive(Debug, PartialEq, Eq)]
-pub struct P256PublicKey(PublicKey<bssl_crypto::ecdh::P256>);
+pub struct P256PublicKey(PublicKey<bssl_crypto::ec::P256>);
+
+impl PartialEq for P256PublicKey {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.to_x962_uncompressed().as_ref() == other.0.to_x962_uncompressed().as_ref()
+ }
+}
+
+impl Debug for P256PublicKey {
+ fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
+ write!(f, "X9.62 bytes: {:?}", self.0.to_x962_uncompressed().as_ref())
+ }
+}
+
impl crypto_provider::p256::P256PublicKey for P256PublicKey {
- type Error = bssl_crypto::ecdh::Error;
+ type Error = Error;
fn from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
- PublicKey::try_from(bytes).map(Self)
+ PublicKey::from_x962_uncompressed(bytes).map(P256PublicKey).ok_or(Error::ConversionFailed)
}
fn to_sec1_bytes(&self, point_compression: PointCompression) -> ArrayVec<[u8; 65]> {
@@ -45,29 +59,37 @@ impl crypto_provider::p256::P256PublicKey for P256PublicKey {
PointCompression::Compressed => unimplemented!(),
PointCompression::Uncompressed => {
let mut bytes = ArrayVec::<[u8; 65]>::new();
- bytes.extend_from_slice(&self.0.to_vec());
+ bytes.extend_from_slice(self.0.to_x962_uncompressed().as_ref());
bytes
}
}
}
- #[allow(clippy::expect_used)]
+ #[allow(clippy::expect_used, clippy::indexing_slicing)]
fn to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error> {
- Ok(self.0.to_affine_coordinates())
+ let raw_key = self.0.to_x962_uncompressed();
+ let x = raw_key.as_ref()[1..33].try_into().map_err(|_| Error::ConversionFailed)?;
+ let y = raw_key.as_ref()[33..65].try_into().map_err(|_| Error::ConversionFailed)?;
+ Ok((x, y))
}
fn from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error> {
- PublicKey::<bssl_crypto::ecdh::P256>::from_affine_coordinates(x, y).map(Self)
+ let mut point = vec![0x04];
+ point.extend_from_slice(x);
+ point.extend_from_slice(y);
+ PublicKey::<bssl_crypto::ec::P256>::from_x962_uncompressed(&point)
+ .map(Self)
+ .ok_or(Error::ConversionFailed)
}
}
-/// Ephemeral secrect for use in a P256 Diffie-Hellman
+/// Ephemeral secret for use in a P256 Diffie-Hellman exchange.
pub struct P256EphemeralSecret {
- secret: PrivateKey<bssl_crypto::ecdh::P256>,
+ secret: PrivateKey<bssl_crypto::ec::P256>,
}
impl EphemeralSecret<P256> for P256EphemeralSecret {
type Impl = P256Ecdh;
- type Error = bssl_crypto::ecdh::Error;
+ type Error = Error;
type Rng = ();
type EncodedPublicKey =
<P256PublicKey as crypto_provider::elliptic_curve::PublicKey<P256>>::EncodedPublicKey;
@@ -77,19 +99,27 @@ impl EphemeralSecret<P256> for P256EphemeralSecret {
}
fn public_key_bytes(&self) -> Self::EncodedPublicKey {
- P256PublicKey((&self.secret).into()).to_bytes()
+ P256PublicKey(self.secret.to_public_key()).to_bytes()
}
fn diffie_hellman(
self,
other_pub: &P256PublicKey,
) -> Result<<Self::Impl as EcdhProvider<P256>>::SharedSecret, Self::Error> {
- let shared_secret = self.secret.diffie_hellman(&other_pub.0)?;
- let bytes: <Self::Impl as EcdhProvider<P256>>::SharedSecret = shared_secret.to_bytes();
- Ok(bytes)
+ let shared_secret = self.secret.compute_shared_key(&other_pub.0);
+ shared_secret.try_into().map_err(|_| Error::DiffieHellmanFailed)
}
}
+/// Error type for ECDH operations.
+#[derive(Debug)]
+pub enum Error {
+ /// Failed when trying to convert between representations.
+ ConversionFailed,
+ /// The Diffie-Hellman key exchange failed.
+ DiffieHellmanFailed,
+}
+
#[cfg(test)]
impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256> for P256EphemeralSecret {
#[allow(clippy::unwrap_used)]
@@ -97,7 +127,7 @@ impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256> for P
private_bytes: &[u8; 32],
_public_key: &P256PublicKey,
) -> Result<Self, Self::Error> {
- Ok(Self { secret: PrivateKey::from_private_bytes(private_bytes).unwrap() })
+ Ok(Self { secret: PrivateKey::from_big_endian(private_bytes).unwrap() })
}
}
@@ -109,7 +139,7 @@ mod tests {
#[apply(p256_test_cases)]
fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh>, name: &str) {
- if name == "to_bytes_compressed" {
+ if name.contains("compressed") {
return; // EC point compression not supported by bssl-crypto yet
}
testcase(PhantomData::<P256Ecdh>)
diff --git a/nearby/crypto/crypto_provider_boringssl/src/sha2.rs b/nearby/crypto/crypto_provider_boringssl/src/sha2.rs
index d95294d..fbee81d 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/sha2.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/sha2.rs
@@ -17,9 +17,9 @@ pub struct Sha256;
impl crypto_provider::sha2::Sha256 for Sha256 {
fn sha256(input: &[u8]) -> [u8; 32] {
- let mut digest = bssl_crypto::digest::Sha256::new_digest();
+ let mut digest = bssl_crypto::digest::Sha256::new();
digest.update(input);
- digest.finalize()
+ digest.digest()
}
}
@@ -28,8 +28,8 @@ pub struct Sha512;
impl crypto_provider::sha2::Sha512 for Sha512 {
fn sha512(input: &[u8]) -> [u8; 64] {
- let mut digest = bssl_crypto::digest::Sha512::new_digest();
+ let mut digest = bssl_crypto::digest::Sha512::new();
digest.update(input);
- digest.finalize()
+ digest.digest()
}
}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/x25519.rs b/nearby/crypto/crypto_provider_boringssl/src/x25519.rs
index 58d040b..f8444f6 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/x25519.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/x25519.rs
@@ -26,29 +26,30 @@ impl EcdhProvider<X25519> for X25519Ecdh {
/// A X25519 ephemeral secret used for Diffie-Hellman.
pub struct X25519EphemeralSecret {
+ public_key: bssl_crypto::x25519::PublicKey,
secret: bssl_crypto::x25519::PrivateKey,
}
impl EphemeralSecret<X25519> for X25519EphemeralSecret {
type Impl = X25519Ecdh;
- type Error = bssl_crypto::x25519::DiffieHellmanError;
+ type Error = Error;
type Rng = ();
type EncodedPublicKey = [u8; 32];
fn generate_random(_rng: &mut Self::Rng) -> Self {
- Self { secret: bssl_crypto::x25519::PrivateKey::generate() }
+ let key_pair = bssl_crypto::x25519::PrivateKey::generate();
+ Self { public_key: key_pair.0, secret: key_pair.1 }
}
fn public_key_bytes(&self) -> Self::EncodedPublicKey {
- let pubkey: bssl_crypto::x25519::PublicKey = (&self.secret).into();
- pubkey.to_bytes()
+ self.public_key
}
fn diffie_hellman(
self,
other_pub: &<X25519Ecdh as EcdhProvider<X25519>>::PublicKey,
) -> Result<<X25519Ecdh as EcdhProvider<X25519>>::SharedSecret, Self::Error> {
- self.secret.diffie_hellman(&other_pub.0).map(|secret| secret.to_bytes())
+ self.secret.compute_shared_key(&other_pub.0).ok_or(Error::WrongSize)
}
}
@@ -58,9 +59,12 @@ impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<X25519>
{
fn from_private_components(
private_bytes: &[u8; 32],
- _public_key: &X25519PublicKey,
+ public_key: &X25519PublicKey,
) -> Result<Self, Self::Error> {
- Ok(Self { secret: bssl_crypto::x25519::PrivateKey::from_private_bytes(private_bytes) })
+ Ok(Self {
+ public_key: public_key.0,
+ secret: bssl_crypto::x25519::PrivateKey(*private_bytes),
+ })
}
}
@@ -69,16 +73,16 @@ impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<X25519>
pub struct X25519PublicKey(bssl_crypto::x25519::PublicKey);
impl PublicKey<X25519> for X25519PublicKey {
- type Error = Error;
type EncodedPublicKey = [u8; 32];
+ type Error = Error;
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
let byte_arr: [u8; 32] = bytes.try_into().map_err(|_| Error::WrongSize)?;
- Ok(Self(bssl_crypto::x25519::PublicKey::from(&byte_arr)))
+ Ok(Self(bssl_crypto::x25519::PublicKey::from(byte_arr)))
}
fn to_bytes(&self) -> Self::EncodedPublicKey {
- self.0.to_bytes()
+ self.0
}
}
diff --git a/nearby/crypto/crypto_provider_default/Cargo.toml b/nearby/crypto/crypto_provider_default/Cargo.toml
index 4c906e4..d79739b 100644
--- a/nearby/crypto/crypto_provider_default/Cargo.toml
+++ b/nearby/crypto/crypto_provider_default/Cargo.toml
@@ -10,8 +10,7 @@ workspace = true
[dependencies]
crypto_provider.workspace = true
crypto_provider_rustcrypto = {workspace = true, optional = true}
-crypto_provider_boringssl = {path = "../crypto_provider_boringssl", optional = true}
-crypto_provider_openssl = {workspace = true, optional = true}
+crypto_provider_boringssl = {workspace = true, optional = true}
cfg-if.workspace = true
[features]
@@ -19,5 +18,3 @@ default = ["rustcrypto"]
std = ["crypto_provider_rustcrypto/std"]
rustcrypto = ["crypto_provider_rustcrypto"]
boringssl = ["crypto_provider_boringssl"]
-opensslbssl = ["crypto_provider_openssl/boringssl"]
-openssl = ["crypto_provider_openssl"]
diff --git a/nearby/crypto/crypto_provider_default/src/lib.rs b/nearby/crypto/crypto_provider_default/src/lib.rs
index 52da9d4..67f3e7d 100644
--- a/nearby/crypto/crypto_provider_default/src/lib.rs
+++ b/nearby/crypto/crypto_provider_default/src/lib.rs
@@ -18,12 +18,12 @@
#![no_std]
cfg_if::cfg_if! {
- if #[cfg(feature = "rustcrypto")] {
+ if #[cfg(all(feature = "rustcrypto", feature = "boringssl"))] {
+ compile_error!("Conflicting crypto_providers specified, must only enable a single crypto provider");
+ } else if #[cfg(feature = "rustcrypto")] {
pub use crypto_provider_rustcrypto::RustCrypto as CryptoProviderImpl;
} else if #[cfg(feature = "boringssl")] {
pub use crypto_provider_boringssl::Boringssl as CryptoProviderImpl;
- } else if #[cfg(any(feature = "openssl", feature = "opensslbssl"))] {
- pub use crypto_provider_openssl::Openssl as CryptoProviderImpl;
} else {
compile_error!("No crypto_provider feature enabled!");
}
diff --git a/nearby/crypto/crypto_provider_openssl/Cargo.toml b/nearby/crypto/crypto_provider_openssl/Cargo.toml
deleted file mode 100644
index 19ef3e4..0000000
--- a/nearby/crypto/crypto_provider_openssl/Cargo.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-[package]
-name = "crypto_provider_openssl"
-version.workspace = true
-edition.workspace = true
-publish.workspace = true
-
-[lints]
-workspace = true
-
-[dependencies]
-crypto_provider = { workspace = true, features = ["alloc", "std"] }
-crypto_provider_stubs.workspace = true
-openssl.workspace = true
-cfg-if.workspace = true
-
-ouroboros = "0.17.0"
-
-[features]
-default = []
-boringssl = ["openssl/unstable_boringssl"]
-
-[dev-dependencies]
-crypto_provider_test.workspace = true
-rstest.workspace = true
-hex-literal.workspace = true
diff --git a/nearby/crypto/crypto_provider_openssl/src/aes.rs b/nearby/crypto/crypto_provider_openssl/src/aes.rs
deleted file mode 100644
index 857be74..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/aes.rs
+++ /dev/null
@@ -1,273 +0,0 @@
-// 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.
-
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! Implementation of `crypto_provider::aes` types using openssl's `symm` module.
-
-use openssl::symm::{Cipher, Crypter, Mode};
-
-use crypto_provider::{
- aes::{
- cbc::{AesCbcIv, DecryptionError, EncryptionError},
- ctr::NonceAndCounter,
- Aes, Aes128Key, Aes256Key, AesBlock, AesCipher, AesDecryptCipher, AesEncryptCipher, AesKey,
- },
- tinyvec::SliceVec,
-};
-
-/// Uber struct which contains impls for AES-128 fns
-pub struct Aes128;
-
-impl Aes for Aes128 {
- type Key = Aes128Key;
- type EncryptCipher = Aes128Cipher;
- type DecryptCipher = Aes128Cipher;
-}
-
-/// Uber struct which contains impls for AES-256 fns
-pub struct Aes256;
-
-impl Aes for Aes256 {
- type Key = Aes256Key;
- type EncryptCipher = Aes256Cipher;
- type DecryptCipher = Aes256Cipher;
-}
-
-/// Wrapper around openssl's AES-128 impl
-pub struct Aes128Cipher(Aes128Key);
-
-impl AesCipher for Aes128Cipher {
- type Key = Aes128Key;
-
- fn new(key: &Self::Key) -> Self {
- Self(key.clone())
- }
-}
-
-impl AesEncryptCipher for Aes128Cipher {
- fn encrypt(&self, block: &mut AesBlock) {
- // openssl requires the output to be at least 32 bytes long
- let mut output = [0_u8; 32];
- let mut crypter =
- Crypter::new(Cipher::aes_128_ecb(), Mode::Encrypt, self.0.as_slice(), None).unwrap();
- crypter.pad(false);
- let _ = crypter.update(block, &mut output).unwrap();
- block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
- }
-}
-
-impl AesDecryptCipher for Aes128Cipher {
- fn decrypt(&self, block: &mut AesBlock) {
- // openssl requires the output to be at least 32 bytes long
- let mut output = [0_u8; 32];
- let mut crypter =
- Crypter::new(Cipher::aes_128_ecb(), Mode::Decrypt, self.0.as_slice(), None).unwrap();
- crypter.pad(false);
- let _ = crypter.update(block, &mut output).unwrap();
- block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
- }
-}
-
-/// Wrapper around openssl's AES-128 impl
-pub struct Aes256Cipher(Aes256Key);
-
-impl AesCipher for Aes256Cipher {
- type Key = Aes256Key;
-
- fn new(key: &Self::Key) -> Self {
- Self(key.clone())
- }
-}
-
-impl AesEncryptCipher for Aes256Cipher {
- fn encrypt(&self, block: &mut AesBlock) {
- // openssl requires the output to be at least 32 bytes long
- let mut output = [0_u8; 32];
- let mut crypter =
- Crypter::new(Cipher::aes_256_ecb(), Mode::Encrypt, self.0.as_slice(), None).unwrap();
- crypter.pad(false);
- let _ = crypter.update(block, &mut output).unwrap();
- block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
- }
-}
-
-impl AesDecryptCipher for Aes256Cipher {
- fn decrypt(&self, block: &mut AesBlock) {
- // openssl requires the output to be at least 32 bytes long
- let mut output = [0_u8; 32];
- let mut crypter =
- Crypter::new(Cipher::aes_256_ecb(), Mode::Decrypt, self.0.as_slice(), None).unwrap();
- crypter.pad(false);
- let _ = crypter.update(block, &mut output).unwrap();
- block.copy_from_slice(&output[..crypto_provider::aes::BLOCK_SIZE]);
- }
-}
-
-/// OpenSSL implementation of AES-CBC-PKCS7.
-pub struct OpenSslAesCbcPkcs7;
-
-impl crypto_provider::aes::cbc::AesCbcPkcs7Padded for OpenSslAesCbcPkcs7 {
- fn encrypt(key: &crypto_provider::aes::Aes256Key, iv: &AesCbcIv, message: &[u8]) -> Vec<u8> {
- openssl::symm::encrypt(Cipher::aes_256_cbc(), key.as_slice(), Some(iv.as_slice()), message)
- // The output buffer is allocated by the openssl crate and guarantees to have enough
- // space to hold the output value and does not overlap with the input slice.
- .expect("encrypt should always succeed")
- }
-
- fn encrypt_in_place(
- key: &Aes256Key,
- iv: &AesCbcIv,
- message: &mut SliceVec<u8>,
- ) -> Result<(), EncryptionError> {
- let encrypted = Self::encrypt(key, iv, message);
- if encrypted.len() > message.capacity() {
- return Err(EncryptionError::PaddingFailed);
- }
- message.clear();
- message.extend_from_slice(&encrypted);
- Ok(())
- }
-
- fn decrypt(
- key: &crypto_provider::aes::Aes256Key,
- iv: &AesCbcIv,
- ciphertext: &[u8],
- ) -> Result<Vec<u8>, DecryptionError> {
- openssl::symm::decrypt(
- Cipher::aes_256_cbc(),
- key.as_slice(),
- Some(iv.as_slice()),
- ciphertext,
- )
- .map_err(|_| DecryptionError::BadPadding)
- }
-
- fn decrypt_in_place(
- key: &Aes256Key,
- iv: &AesCbcIv,
- ciphertext: &mut SliceVec<u8>,
- ) -> Result<(), DecryptionError> {
- Self::decrypt(key, iv, ciphertext).map(|result| {
- ciphertext.clear();
- ciphertext.extend_from_slice(&result);
- })
- }
-}
-
-/// OpenSSL implementation of AES-CTR-128
-pub struct OpenSslAesCtr128 {
- enc_cipher: Crypter,
-}
-
-impl crypto_provider::aes::ctr::AesCtr for OpenSslAesCtr128 {
- type Key = crypto_provider::aes::Aes128Key;
- fn new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self {
- Self {
- enc_cipher: Crypter::new(
- Cipher::aes_128_ctr(),
- Mode::Encrypt,
- key.as_slice(),
- Some(&nonce_and_counter.as_block_array()),
- )
- .unwrap(),
- }
- }
-
- fn apply_keystream(&mut self, data: &mut [u8]) {
- let mut in_slice = vec![0u8; data.len()];
- in_slice.copy_from_slice(data);
- let _ = self.enc_cipher.update(&in_slice, data);
- }
-}
-
-/// OpenSSL implementation of AES-CTR-256
-pub struct OpenSslAesCtr256 {
- enc_cipher: Crypter,
-}
-
-impl crypto_provider::aes::ctr::AesCtr for OpenSslAesCtr256 {
- type Key = crypto_provider::aes::Aes256Key;
- fn new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self {
- Self {
- enc_cipher: Crypter::new(
- Cipher::aes_256_ctr(),
- Mode::Encrypt,
- key.as_slice(),
- Some(&nonce_and_counter.as_block_array()),
- )
- .unwrap(),
- }
- }
-
- fn apply_keystream(&mut self, data: &mut [u8]) {
- let mut in_slice = vec![0u8; data.len()];
- in_slice.copy_from_slice(data);
- let _ = self.enc_cipher.update(&in_slice, data);
- }
-}
-
-#[cfg(test)]
-mod tests {
- use core::marker::PhantomData;
-
- use crypto_provider_test::aes::cbc::*;
- use crypto_provider_test::aes::ctr::*;
- use crypto_provider_test::aes::*;
-
- use super::*;
-
- #[apply(aes_128_ctr_test_cases)]
- fn aes_128_ctr_test(testcase: CryptoProviderTestCase<OpenSslAesCtr128>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_256_ctr_test_cases)]
- fn aes_256_ctr_test(testcase: CryptoProviderTestCase<OpenSslAesCtr256>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_128_encrypt_test_cases)]
- fn aes_128_enc_test(testcase: CryptoProviderTestCase<Aes128Cipher>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_128_decrypt_test_cases)]
- fn aes_128_dec_test(testcase: CryptoProviderTestCase<Aes128Cipher>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_256_encrypt_test_cases)]
- fn aes_256_enc_test(testcase: CryptoProviderTestCase<Aes256Cipher>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_256_decrypt_test_cases)]
- fn aes_256_dec_test(testcase: CryptoProviderTestCase<Aes256Cipher>) {
- testcase(PhantomData);
- }
-
- #[apply(aes_256_cbc_test_cases)]
- fn aes_256_cbc_test(testcase: CryptoProviderTestCase<OpenSslAesCbcPkcs7>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/ed25519.rs b/nearby/crypto/crypto_provider_openssl/src/ed25519.rs
deleted file mode 100644
index 111348a..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/ed25519.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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.
-
-use crypto_provider::ed25519::{
- InvalidBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature, Signature as _,
- SignatureError,
-};
-use openssl::pkey::{Id, PKey, Private};
-use openssl::sign::{Signer, Verifier};
-
-pub struct Ed25519;
-
-impl crypto_provider::ed25519::Ed25519Provider for Ed25519 {
- type KeyPair = KeyPair;
- type PublicKey = PublicKey;
- type Signature = Signature;
-}
-
-pub struct KeyPair(PKey<Private>);
-
-impl crypto_provider::ed25519::KeyPair for KeyPair {
- type PublicKey = PublicKey;
- type Signature = Signature;
-
- fn raw_private_key(&self, _permit: &RawPrivateKeyPermit) -> RawPrivateKey {
- let private_key = self.0.raw_private_key().unwrap();
- let mut public_key = self.0.raw_public_key().unwrap();
- let mut result = private_key;
- result.append(&mut public_key);
- result.try_into().unwrap()
- }
-
- fn from_raw_private_key(bytes: &RawPrivateKey, _permit: &RawPrivateKeyPermit) -> Self {
- Self(PKey::private_key_from_raw_bytes(bytes, Id::ED25519).unwrap())
- }
-
- fn sign(&self, msg: &[u8]) -> Self::Signature {
- let mut signer =
- Signer::new_without_digest(&self.0).expect("should be able to create a signer");
- let sig_bytes: RawSignature = signer
- .sign_oneshot_to_vec(msg)
- .expect("singing should succeed")
- .try_into()
- .expect("signature should be a valid size");
-
- Self::Signature::from_bytes(&sig_bytes)
- }
-
- fn generate() -> Self {
- let key = PKey::generate_ed25519().expect("key generation should not fail");
- Self(key)
- }
-
- fn public(&self) -> Self::PublicKey {
- PublicKey(
- self.0.raw_public_key().expect("should be able to get a pubic key from a keypair"),
- )
- }
-}
-
-pub struct Signature(RawSignature);
-
-impl crypto_provider::ed25519::Signature for Signature {
- fn from_bytes(bytes: &RawSignature) -> Self {
- Self(*bytes)
- }
-
- fn to_bytes(&self) -> RawSignature {
- self.0
- }
-}
-
-pub struct PublicKey(Vec<u8>);
-
-impl crypto_provider::ed25519::PublicKey for PublicKey {
- type Signature = Signature;
-
- fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidBytes>
- where
- Self: Sized,
- {
- Ok(PublicKey(bytes.to_vec()))
- }
-
- fn to_bytes(&self) -> RawPublicKey {
- //Should be length 32
- self.0.as_slice().try_into().unwrap()
- }
-
- fn verify_strict(
- &self,
- message: &[u8],
- signature: &Self::Signature,
- ) -> Result<(), SignatureError> {
- let public_key = PKey::public_key_from_raw_bytes(self.0.as_slice(), Id::ED25519)
- .expect("should be a valid public key");
-
- let mut verifier = Verifier::new_without_digest(public_key.as_ref())
- .expect("should be able to init verifier");
- let result = verifier
- .verify_oneshot(signature.0.as_slice(), message)
- .expect("should be able to call verify");
- if result {
- Ok(())
- } else {
- Err(SignatureError)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::ed25519::Ed25519;
- use crypto_provider_test::ed25519::{run_rfc_test_vectors, run_wycheproof_test_vectors};
-
- #[test]
- fn wycheproof_test_ed25519_openssl() {
- run_wycheproof_test_vectors::<Ed25519>()
- }
-
- #[test]
- fn rfc_test_ed25519_openssl() {
- run_rfc_test_vectors::<Ed25519>()
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs b/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs
deleted file mode 100644
index 152cdfc..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.
-
-//! BoringSSL based HKDF implementation. Unfortunately, because the OpenSSL and BoringSSL APIs
-//! diverged for HKDF, we have to have separate implementations.
-//!
-//! See the _Using BoringSSL_ section in `crypto/README.md` for instructions on
-//! how to test against BoringSSL, or see the subcommands in the top level crate.
-
-use crate::OpenSslHash;
-use crypto_provider::hkdf::InvalidLength;
-use std::marker::PhantomData;
-
-/// openssl based hkdf implementation
-pub struct Hkdf<H: OpenSslHash> {
- _marker: PhantomData<H>,
- salt: Option<Vec<u8>>,
- ikm: Vec<u8>,
-}
-
-impl<H: OpenSslHash> crypto_provider::hkdf::Hkdf for Hkdf<H> {
- fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self {
- Self { _marker: Default::default(), salt: salt.map(Vec::from), ikm: Vec::from(ikm) }
- }
-
- fn expand_multi_info(
- &self,
- info_components: &[&[u8]],
- okm: &mut [u8],
- ) -> Result<(), InvalidLength> {
- // open ssl will panic in the case of a 0 length okm, but expected behavior is no-op
- if okm.is_empty() {
- return Ok(());
- }
- openssl::hkdf::hkdf(
- okm,
- H::get_md(),
- self.ikm.as_slice(),
- self.salt.as_deref().unwrap_or_default(),
- &info_components.concat(),
- )
- .map_err(|_| InvalidLength)
- .map(|_| ())
- }
-
- fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
- self.expand_multi_info(&[info], okm)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::Openssl;
- use core::marker::PhantomData;
- use crypto_provider_test::hkdf::*;
-
- #[apply(hkdf_test_cases)]
- fn hkdf_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs b/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs
deleted file mode 100644
index b726f5f..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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.
-
-use crate::OpenSslHash;
-use crypto_provider::hkdf::InvalidLength;
-use std::marker::PhantomData;
-
-/// openssl based hkdf implementation
-pub struct Hkdf<H: OpenSslHash> {
- _marker: PhantomData<H>,
- salt: Option<Vec<u8>>,
- ikm: Vec<u8>,
-}
-
-impl<H: OpenSslHash> crypto_provider::hkdf::Hkdf for Hkdf<H> {
- fn new(salt: Option<&[u8]>, ikm: &[u8]) -> Self {
- Self { _marker: Default::default(), salt: salt.map(Vec::from), ikm: Vec::from(ikm) }
- }
-
- fn expand_multi_info(
- &self,
- info_components: &[&[u8]],
- okm: &mut [u8],
- ) -> Result<(), InvalidLength> {
- // open ssl will panic in the case of a 0 length okm, but expected behavior is no-op
- if okm.is_empty() {
- return Ok(());
- }
- let mut ctx = openssl::pkey_ctx::PkeyCtx::new_id(openssl::pkey::Id::HKDF)
- .expect("hkdf context should not fail");
- let md = H::get_md();
- ctx.derive_init().expect("hkdf derive init should not fail");
- ctx.set_hkdf_md(md).expect("hkdf set md should not fail");
- let _ = self.salt.as_ref().map(|salt| {
- ctx.set_hkdf_salt(salt.as_slice()).expect("setting the salt is infallible")
- });
- ctx.set_hkdf_key(self.ikm.as_slice()).expect("should be able to set key");
- ctx.add_hkdf_info(&info_components.concat()).expect("should be able to add info");
- ctx.derive(Some(okm)).map_err(|_| InvalidLength).map(|_| ())
- }
-
- fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), InvalidLength> {
- self.expand_multi_info(&[info], okm)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::Openssl;
- use core::marker::PhantomData;
- use crypto_provider_test::hkdf::*;
-
- #[apply(hkdf_test_cases)]
- fn hkdf_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs b/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs
deleted file mode 100644
index 5272995..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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.
-
-//! BoringSSL based HMAC implementation. Unfortunately, because the OpenSSL and BoringSSL APIs
-//! diverged (https://boringssl.googlesource.com/boringssl/+/HEAD/PORTING.md#hmac-s), we have to
-//! have separate implementations.
-//!
-//! See the _Using BoringSSL_ section in `crypto/README.md` for instructions on
-//! how to test against BoringSSL, or see the subcommands in the top level crate.
-
-use crate::{sha2::OpenSslSha256, sha2::OpenSslSha512, OpenSslHash};
-use crypto_provider::hmac::{InvalidLength, MacError};
-use openssl::hmac::HmacCtx;
-use openssl::memcmp;
-use std::marker::PhantomData;
-
-/// BoringSSL based HMAC implementation
-pub struct Hmac<H: OpenSslHash> {
- marker: PhantomData<H>,
- ctx: HmacCtx,
-}
-
-trait Hash<const N: usize>: OpenSslHash {}
-impl Hash<32> for OpenSslSha256 {}
-impl Hash<64> for OpenSslSha512 {}
-
-impl<const N: usize, H: Hash<N>> crypto_provider::hmac::Hmac<N> for Hmac<H> {
- fn new_from_key(key: [u8; N]) -> Self {
- Self { marker: PhantomData, ctx: HmacCtx::new(&key, H::get_md()).unwrap() }
- }
-
- fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
- Ok(Self { marker: PhantomData, ctx: HmacCtx::new(key, H::get_md()).unwrap() })
- }
-
- fn update(&mut self, data: &[u8]) {
- self.ctx.update(data).expect("should be able to update signer");
- }
-
- fn finalize(mut self) -> [u8; N] {
- let mut buf = [0_u8; N];
- let _ = self.ctx.finalize(&mut buf).expect("wrong length");
- buf
- }
-
- fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
- let binding: [u8; N] = self.finalize();
- let slice = binding.as_slice();
- if memcmp::eq(slice, tag) {
- Ok(())
- } else {
- Err(MacError)
- }
- }
-
- fn verify(self, tag: [u8; N]) -> Result<(), MacError> {
- let binding: [u8; N] = self.finalize();
- let slice = binding.as_slice();
- if memcmp::eq(slice, &tag) {
- Ok(())
- } else {
- Err(MacError)
- }
- }
-
- fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
- let binding: [u8; N] = self.finalize();
- let slice = binding.as_slice();
- let len = tag.len();
- if len == 0 || len > H::get_digest().block_size() {
- return Err(MacError);
- }
- let left = slice.get(..len).ok_or(MacError)?;
- if memcmp::eq(left, tag) {
- Ok(())
- } else {
- Err(MacError)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::Openssl;
- use core::marker::PhantomData;
- use crypto_provider_test::hmac::*;
-
- #[apply(hmac_test_cases)]
- fn hmac_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs b/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs
deleted file mode 100644
index 42f857e..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-// 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.
-
-use crate::{sha2::OpenSslSha256, sha2::OpenSslSha512, OpenSslHash};
-use core::convert::TryInto;
-use crypto_provider::hmac::{InvalidLength, MacError};
-use openssl::memcmp;
-use openssl::pkey::{PKey, Private};
-use openssl::sign::Signer;
-use ouroboros::self_referencing;
-use std::marker::PhantomData;
-
-/// openssl based hmac implementation
-#[self_referencing]
-pub struct Hmac<H: OpenSslHash> {
- ctx: PKey<Private>,
- #[borrows(ctx)]
- #[covariant]
- signer: Signer<'this>,
- marker: PhantomData<H>,
-}
-
-impl crypto_provider::hmac::Hmac<32> for Hmac<OpenSslSha256> {
- fn new_from_key(key: [u8; 32]) -> Self {
- new_from_key(key)
- }
-
- fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
- new_from_slice(key)
- }
-
- fn update(&mut self, data: &[u8]) {
- update(self, data)
- }
-
- fn finalize(self) -> [u8; 32] {
- finalize(self)
- }
-
- fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
- verify_slice(self, tag)
- }
-
- fn verify(self, tag: [u8; 32]) -> Result<(), MacError> {
- verify(self, tag)
- }
-
- fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
- verify_truncated_left(self, tag)
- }
-}
-
-impl crypto_provider::hmac::Hmac<64> for Hmac<OpenSslSha512> {
- fn new_from_key(key: [u8; 64]) -> Self {
- new_from_key(key)
- }
-
- fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
- new_from_slice(key)
- }
-
- fn update(&mut self, data: &[u8]) {
- update(self, data)
- }
-
- fn finalize(self) -> [u8; 64] {
- finalize(self)
- }
-
- fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
- verify_slice(self, tag)
- }
-
- fn verify(self, tag: [u8; 64]) -> Result<(), MacError> {
- verify(self, tag)
- }
-
- fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
- verify_truncated_left(self, tag)
- }
-}
-
-fn hmac_from_builder<H: OpenSslHash>(ctx: PKey<Private>) -> Hmac<H> {
- let digest = H::get_digest();
- HmacBuilder {
- ctx,
- marker: PhantomData,
- signer_builder: |ctx: &openssl::pkey::PKey<openssl::pkey::Private>| {
- Signer::new(digest, ctx).expect("should be able to create signer")
- },
- }
- .build()
-}
-
-fn new_from_key<const N: usize, H: OpenSslHash>(key: [u8; N]) -> Hmac<H> {
- let ctx = openssl::pkey::PKey::hmac(&key)
- .expect("hmac creation shouldn't fail since key is of valid size");
- hmac_from_builder(ctx)
-}
-
-fn new_from_slice<H: OpenSslHash>(key: &[u8]) -> Result<Hmac<H>, InvalidLength> {
- openssl::pkey::PKey::hmac(key).map(hmac_from_builder).map_err(|_| InvalidLength)
-}
-
-fn update<H: OpenSslHash>(hmac: &mut Hmac<H>, data: &[u8]) {
- hmac.with_signer_mut(|signer| {
- signer.update(data).expect("should be able to update signer");
- })
-}
-
-fn finalize<const N: usize, H: OpenSslHash>(hmac: Hmac<H>) -> [u8; N] {
- hmac.borrow_signer()
- .sign_to_vec()
- .expect("sign to vec should succeed")
- .as_slice()
- .try_into()
- .expect("wrong length")
-}
-
-fn verify_slice<H: OpenSslHash>(hmac: Hmac<H>, tag: &[u8]) -> Result<(), MacError> {
- let binding = hmac.borrow_signer().sign_to_vec().expect("sign to vec should succeed");
- let slice = binding.as_slice();
- if memcmp::eq(slice, tag) {
- Ok(())
- } else {
- Err(MacError)
- }
-}
-
-fn verify<const N: usize, H: OpenSslHash>(hmac: Hmac<H>, tag: [u8; N]) -> Result<(), MacError> {
- let binding = hmac.borrow_signer().sign_to_vec().expect("sign to vec should succeed");
- let slice = binding.as_slice();
- if memcmp::eq(slice, &tag) {
- Ok(())
- } else {
- Err(MacError)
- }
-}
-
-fn verify_truncated_left<H: OpenSslHash>(hmac: Hmac<H>, tag: &[u8]) -> Result<(), MacError> {
- let binding = hmac.borrow_signer().sign_to_vec().expect("sign to vec should succeed");
- let slice = binding.as_slice();
- let len = tag.len();
- if len == 0 || len > H::get_digest().block_size() {
- return Err(MacError);
- }
- let left = slice.get(..len).ok_or(MacError)?;
- if memcmp::eq(left, tag) {
- Ok(())
- } else {
- Err(MacError)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::Openssl;
- use core::marker::PhantomData;
- use crypto_provider_test::hmac::*;
-
- #[apply(hmac_test_cases)]
- fn hmac_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/lib.rs b/nearby/crypto/crypto_provider_openssl/src/lib.rs
deleted file mode 100644
index 04b4e4c..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/lib.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-#![forbid(unsafe_code)]
-// 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.
-
-//! Crate which provides impls for CryptoProvider backed by openssl
-
-// This crate treats allocation errors as handleable, which leads to unwraps everywhere, so they
-// have to be allowed here. This will be fixed when we can migrate over to the new boringssl bindings
-#![allow(clippy::expect_used, clippy::unwrap_used)]
-
-use cfg_if::cfg_if;
-pub use openssl;
-use openssl::hash::MessageDigest;
-use openssl::md::MdRef;
-use openssl::rand::rand_bytes;
-
-use crypto_provider::CryptoRng;
-
-/// Contains the openssl backed AES implementations for CryptoProvider
-mod aes;
-/// Contains the openssl backed ed25519 impl for key generation, verification, and signing
-mod ed25519;
-
-cfg_if! {
- if #[cfg(feature = "boringssl")] {
- /// Contains the boringssl backed hkdf impl for CryptoProvider
- mod hkdf_boringssl;
- use hkdf_boringssl as hkdf;
- /// Contains the boringssl backed hmac impl for CryptoProvider
- mod hmac_boringssl;
- use hmac_boringssl as hmac;
- } else {
- /// Contains the openssl backed hkdf impl for CryptoProvider
- mod hkdf_openssl;
- use hkdf_openssl as hkdf;
- /// Contains the openssl backed hmac impl for CryptoProvider
- mod hmac_openssl;
- use hmac_openssl as hmac;
- }
-}
-/// Contains the openssl backed NIST-P256 impl for CryptoProvider
-mod p256;
-/// Contains the openssl backed SHA2 impl for CryptoProvider
-mod sha2;
-/// Contains the openssl backed X25519 impl for CryptoProvider
-mod x25519;
-
-/// The the openssl backed struct which implements CryptoProvider
-#[derive(Default, Clone, Debug, PartialEq, Eq)]
-pub struct Openssl;
-
-/// The trait which defines a has used in openssl crypto operations
-pub trait OpenSslHash {
- /// gets the message digest algorithm to be used by the hmac implementation
- fn get_digest() -> MessageDigest;
- /// gets a reference to a message digest algorithm to be used by the hkdf implementation
- fn get_md() -> &'static MdRef;
-}
-
-impl crypto_provider::CryptoProvider for Openssl {
- type HkdfSha256 = hkdf::Hkdf<sha2::OpenSslSha256>;
- type HmacSha256 = hmac::Hmac<sha2::OpenSslSha256>;
- type HkdfSha512 = hkdf::Hkdf<sha2::OpenSslSha512>;
- type HmacSha512 = hmac::Hmac<sha2::OpenSslSha512>;
- type AesCbcPkcs7Padded = aes::OpenSslAesCbcPkcs7;
- type X25519 = x25519::X25519Ecdh;
- type P256 = p256::P256Ecdh;
- type Sha256 = sha2::OpenSslSha256;
- type Sha512 = sha2::OpenSslSha512;
- type Aes128 = aes::Aes128;
- type Aes256 = aes::Aes256;
- type AesCtr128 = aes::OpenSslAesCtr128;
- type AesCtr256 = aes::OpenSslAesCtr256;
- type Ed25519 = ed25519::Ed25519;
- type Aes128GcmSiv = crypto_provider_stubs::Aes128Stubs;
- type Aes256GcmSiv = crypto_provider_stubs::Aes256Stubs;
- type Aes128Gcm = crypto_provider_stubs::Aes128Stubs;
- type Aes256Gcm = crypto_provider_stubs::Aes256Stubs;
- type CryptoRng = OpenSslRng;
-
- fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
- a.len() == b.len() && openssl::memcmp::eq(a, b)
- }
-}
-
-/// OpenSSL implemented random number generator
-pub struct OpenSslRng;
-
-impl CryptoRng for OpenSslRng {
- fn new() -> Self {
- OpenSslRng {}
- }
-
- fn next_u64(&mut self) -> u64 {
- let mut buf = [0; 8];
- rand_bytes(&mut buf).unwrap();
- u64::from_be_bytes(buf)
- }
-
- fn fill(&mut self, dest: &mut [u8]) {
- rand_bytes(dest).expect("Error in generating random bytes")
- }
-}
-
-#[cfg(test)]
-mod tests {
- use core::marker::PhantomData;
-
- use crypto_provider_test::sha2::*;
- use crypto_provider_test::{prelude::*, *};
-
- use crate::Openssl;
-
- #[apply(sha2_test_cases)]
- fn sha2_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-
- #[apply(constant_time_eq_test_cases)]
- fn constant_time_eq_tests(testcase: CryptoProviderTestCase<Openssl>) {
- testcase(PhantomData);
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/p256.rs b/nearby/crypto/crypto_provider_openssl/src/p256.rs
deleted file mode 100644
index 17dd6ce..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/p256.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-// 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.
-
-use crypto_provider::{
- elliptic_curve::{EcdhProvider, EphemeralSecret},
- p256::{PointCompression, P256},
- tinyvec::ArrayVec,
-};
-use openssl::bn::{BigNum, BigNumContext};
-use openssl::derive::Deriver;
-use openssl::ec::{EcGroup, EcKey, EcPoint, PointConversionForm};
-use openssl::error::ErrorStack;
-use openssl::nid::Nid;
-use openssl::pkey::{PKey, Private, Public};
-
-/// Public key type for P256 using OpenSSL's implementation.
-#[derive(Debug)]
-pub struct P256PublicKey(PKey<Public>);
-
-impl PartialEq for P256PublicKey {
- fn eq(&self, other: &Self) -> bool {
- self.0.public_eq(&other.0)
- }
-}
-
-/// Custom error type for OpenSSL operations.
-#[derive(Debug)]
-#[allow(clippy::enum_variant_names)]
-pub enum Error {
- /// Error from the openssl crate.
- OpenSslError(ErrorStack),
- /// Unexpected size for the given input.
- WrongSize,
- /// Invalid input given when creating keys from their byte representations.
- InvalidInput,
-}
-
-impl From<ErrorStack> for Error {
- fn from(value: ErrorStack) -> Self {
- Self::OpenSslError(value)
- }
-}
-
-/// The OpenSSL implementation of P256 public key.
-impl crypto_provider::p256::P256PublicKey for P256PublicKey {
- type Error = Error;
-
- fn from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
- if bytes == [0] {
- // Single 0 byte means infinity point.
- return Err(Error::InvalidInput);
- }
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
- let mut bncontext = BigNumContext::new()?;
- let ecpoint = EcPoint::from_bytes(&ecgroup, bytes, &mut bncontext)?;
- let eckey = EcKey::from_public_key(&ecgroup, &ecpoint)?;
- Ok(Self(eckey.try_into()?))
- }
-
- fn to_sec1_bytes(&self, point_compression: PointCompression) -> ArrayVec<[u8; 65]> {
- let point_conversion_form = match point_compression {
- PointCompression::Compressed => PointConversionForm::COMPRESSED,
- PointCompression::Uncompressed => PointConversionForm::UNCOMPRESSED,
- };
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
- let mut bncontext = BigNumContext::new().unwrap();
- let mut bytes = ArrayVec::<[u8; 65]>::new();
- bytes.extend_from_slice(
- &self
- .0
- .ec_key()
- .unwrap()
- .public_key()
- .to_bytes(&ecgroup, point_conversion_form, &mut bncontext)
- .unwrap(),
- );
- bytes
- }
-
- fn from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error> {
- let bn_x = BigNum::from_slice(x)?;
- let bn_y = BigNum::from_slice(y)?;
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
- let eckey = EcKey::from_public_key_affine_coordinates(&ecgroup, &bn_x, &bn_y)?;
- Ok(Self(eckey.try_into()?))
- }
-
- fn to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error> {
- let mut bnctx = openssl::bn::BigNumContext::new()?;
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
- let p256_key = self.0.ec_key()?;
- let mut p256x = BigNum::new()?;
- let mut p256y = BigNum::new()?;
- p256_key
- .public_key()
- .affine_coordinates_gfp(&ecgroup, &mut p256x, &mut p256y, &mut bnctx)?;
- Ok((
- p256x
- .to_vec_padded(32)
- .map_err(|_| Error::WrongSize)?
- .try_into()
- .expect("to_vec_padded(32) should always return vec of length 32"),
- p256y
- .to_vec_padded(32)
- .map_err(|_| Error::WrongSize)?
- .try_into()
- .expect("to_vec_padded(32) should always return vec of length 32"),
- ))
- }
-}
-
-/// Private key type for P256 using OpenSSL's implementation.
-pub struct P256EphemeralSecret(PKey<Private>);
-
-impl EphemeralSecret<P256> for P256EphemeralSecret {
- type Impl = P256Ecdh;
- type Error = Error;
- type Rng = ();
- type EncodedPublicKey = ArrayVec<[u8; 65]>;
-
- fn generate_random(_rng: &mut Self::Rng) -> Self {
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
- let eckey = EcKey::generate(&ecgroup).unwrap();
- Self(eckey.try_into().unwrap())
- }
-
- fn public_key_bytes(&self) -> Self::EncodedPublicKey {
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
- let mut bncontext = BigNumContext::new().unwrap();
- let mut bytes = Self::EncodedPublicKey::new();
- bytes.extend_from_slice(
- &self
- .0
- .ec_key()
- .unwrap()
- .public_key()
- .to_bytes(&ecgroup, PointConversionForm::COMPRESSED, &mut bncontext)
- .unwrap(),
- );
- bytes
- }
-
- fn diffie_hellman(
- self,
- other_pub: &<Self::Impl as EcdhProvider<P256>>::PublicKey,
- ) -> Result<<Self::Impl as EcdhProvider<P256>>::SharedSecret, Self::Error> {
- let mut deriver = Deriver::new(&self.0)?;
- deriver.set_peer(&other_pub.0)?;
- let mut buf = [0_u8; 32];
- let bytes_written = deriver.derive(&mut buf)?;
- debug_assert_eq!(bytes_written, 32);
- Ok(buf)
- }
-}
-
-#[cfg(test)]
-impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256> for P256EphemeralSecret {
- fn from_private_components(
- private_bytes: &[u8; 32],
- public_key: &P256PublicKey,
- ) -> Result<Self, Self::Error> {
- let ecgroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
- let private_key_bn = BigNum::from_slice(private_bytes)?;
- let eckey = EcKey::from_private_components(
- &ecgroup,
- &private_key_bn,
- public_key.0.ec_key()?.public_key(),
- )?;
- Ok(Self(eckey.try_into()?))
- }
-}
-
-/// The OpenSSL implementation of P256 ECDH.
-pub enum P256Ecdh {}
-impl EcdhProvider<P256> for P256Ecdh {
- type PublicKey = P256PublicKey;
- type EphemeralSecret = P256EphemeralSecret;
- type SharedSecret = [u8; 32];
-}
-
-#[cfg(test)]
-mod tests {
- use super::P256Ecdh;
- use core::marker::PhantomData;
- use crypto_provider_test::p256::*;
-
- #[apply(p256_test_cases)]
- fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh>, _name: &str) {
- testcase(PhantomData)
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/sha2.rs b/nearby/crypto/crypto_provider_openssl/src/sha2.rs
deleted file mode 100644
index 68fee79..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/sha2.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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.
-
-use openssl::hash::MessageDigest;
-use openssl::md::{Md, MdRef};
-use openssl::md_ctx::MdCtx;
-
-use crate::OpenSslHash;
-
-/// openssl sha256 digest algorithm
-#[derive(Clone)]
-pub struct OpenSslSha256 {}
-
-impl OpenSslHash for OpenSslSha256 {
- fn get_digest() -> MessageDigest {
- MessageDigest::sha256()
- }
-
- fn get_md() -> &'static MdRef {
- Md::sha256()
- }
-}
-
-impl crypto_provider::sha2::Sha256 for OpenSslSha256 {
- fn sha256(input: &[u8]) -> [u8; 32] {
- let mut mdctx = MdCtx::new().unwrap();
- mdctx.digest_init(Self::get_md()).unwrap();
- mdctx.digest_update(input).unwrap();
- let mut buf = [0_u8; 32];
- let size = mdctx.digest_final(&mut buf).unwrap();
- debug_assert_eq!(size, 32);
- buf
- }
-}
-
-/// openssl sha512 digest algorithm
-#[derive(Clone)]
-pub struct OpenSslSha512 {}
-
-impl OpenSslHash for OpenSslSha512 {
- fn get_digest() -> MessageDigest {
- MessageDigest::sha512()
- }
-
- fn get_md() -> &'static MdRef {
- Md::sha512()
- }
-}
-
-impl crypto_provider::sha2::Sha512 for OpenSslSha512 {
- fn sha512(input: &[u8]) -> [u8; 64] {
- let mut mdctx = MdCtx::new().unwrap();
- mdctx.digest_init(Self::get_md()).unwrap();
- mdctx.digest_update(input).unwrap();
- let mut buf = [0_u8; 64];
- let size = mdctx.digest_final(&mut buf).unwrap();
- debug_assert_eq!(size, 64);
- buf
- }
-}
diff --git a/nearby/crypto/crypto_provider_openssl/src/x25519.rs b/nearby/crypto/crypto_provider_openssl/src/x25519.rs
deleted file mode 100644
index 2cb4cab..0000000
--- a/nearby/crypto/crypto_provider_openssl/src/x25519.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.
-
-use crypto_provider::elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey};
-use crypto_provider::x25519::X25519;
-use openssl::derive::Deriver;
-use openssl::error::ErrorStack;
-use openssl::pkey::{Id, PKey, Private, Public};
-
-/// Public key type for X25519 using OpenSSL's implementation.
-#[derive(Debug)]
-pub struct X25519PublicKey(PKey<Public>);
-
-impl PartialEq for X25519PublicKey {
- fn eq(&self, other: &Self) -> bool {
- self.0.public_eq(&other.0)
- }
-}
-
-impl PublicKey<X25519> for X25519PublicKey {
- type Error = ErrorStack;
- type EncodedPublicKey = [u8; 32];
-
- fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
- let key = PKey::public_key_from_raw_bytes(bytes, Id::X25519)?;
- Ok(X25519PublicKey(key))
- }
-
- fn to_bytes(&self) -> Self::EncodedPublicKey {
- self.0.raw_public_key().unwrap().try_into().unwrap()
- }
-}
-
-/// Private key type for X25519 using OpenSSL's implementation.
-pub struct X25519PrivateKey(PKey<Private>);
-
-impl EphemeralSecret<X25519> for X25519PrivateKey {
- type Impl = X25519Ecdh;
- type Error = ErrorStack;
- type Rng = ();
- type EncodedPublicKey = [u8; 32];
-
- fn generate_random(_rng: &mut Self::Rng) -> Self {
- let private_key = openssl::pkey::PKey::generate_x25519().unwrap();
- Self(private_key)
- }
-
- fn public_key_bytes(&self) -> Self::EncodedPublicKey {
- self.0.raw_public_key().unwrap().try_into().unwrap()
- }
-
- fn diffie_hellman(
- self,
- other_pub: &X25519PublicKey,
- ) -> Result<<Self::Impl as EcdhProvider<X25519>>::SharedSecret, Self::Error> {
- let mut deriver = Deriver::new(&self.0)?;
- deriver.set_peer(&other_pub.0)?;
- let mut buf = [0_u8; 32];
- let num_bytes_written = deriver.derive(&mut buf)?;
- debug_assert_eq!(num_bytes_written, 32);
- Ok(buf)
- }
-}
-
-#[cfg(test)]
-impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<X25519> for X25519PrivateKey {
- fn from_private_components(
- private_bytes: &[u8; 32],
- _public_key: &<Self::Impl as EcdhProvider<X25519>>::PublicKey,
- ) -> Result<Self, Self::Error> {
- let pkey = PKey::private_key_from_raw_bytes(private_bytes, Id::X25519)?;
- Ok(Self(pkey))
- }
-}
-
-/// The OpenSSL implementation of X25519 ECDH.
-pub enum X25519Ecdh {}
-impl EcdhProvider<X25519> for X25519Ecdh {
- type PublicKey = X25519PublicKey;
- type EphemeralSecret = X25519PrivateKey;
- type SharedSecret = [u8; 32];
-}
-
-#[cfg(test)]
-mod tests {
- use core::marker::PhantomData;
- use crypto_provider_test::x25519::*;
-
- use super::X25519Ecdh;
-
- #[apply(x25519_test_cases)]
- fn x25519_tests(testcase: CryptoProviderTestCase<X25519Ecdh>) {
- testcase(PhantomData::<X25519Ecdh>)
- }
-}
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
index ce8089e..ee01101 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
@@ -15,8 +15,8 @@
use ed25519_dalek::Signer;
use crypto_provider::ed25519::{
- InvalidBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature, Signature as _,
- SignatureError, PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH,
+ InvalidPublicKeyBytes, RawPrivateKey, RawPrivateKeyPermit, RawPublicKey, RawSignature,
+ SignatureError, SignatureImpl, PRIVATE_KEY_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH,
};
pub struct Ed25519;
@@ -29,7 +29,7 @@ impl crypto_provider::ed25519::Ed25519Provider for Ed25519 {
pub struct KeyPair(ed25519_dalek::SigningKey);
-impl crypto_provider::ed25519::KeyPair for KeyPair {
+impl crypto_provider::ed25519::KeyPairImpl for KeyPair {
type PublicKey = PublicKey;
type Signature = Signature;
@@ -54,14 +54,14 @@ impl crypto_provider::ed25519::KeyPair for KeyPair {
Self(ed25519_dalek::SigningKey::generate(&mut csprng))
}
- fn public(&self) -> Self::PublicKey {
+ fn public_key(&self) -> Self::PublicKey {
PublicKey(self.0.verifying_key())
}
}
pub struct Signature(ed25519_dalek::Signature);
-impl crypto_provider::ed25519::Signature for Signature {
+impl crypto_provider::ed25519::SignatureImpl for Signature {
fn from_bytes(bytes: &RawSignature) -> Self {
Self(ed25519_dalek::Signature::from_bytes(bytes))
}
@@ -73,14 +73,16 @@ impl crypto_provider::ed25519::Signature for Signature {
pub struct PublicKey(ed25519_dalek::VerifyingKey);
-impl crypto_provider::ed25519::PublicKey for PublicKey {
+impl crypto_provider::ed25519::PublicKeyImpl for PublicKey {
type Signature = Signature;
- fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidBytes>
+ fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidPublicKeyBytes>
where
Self: Sized,
{
- ed25519_dalek::VerifyingKey::from_bytes(bytes).map(PublicKey).map_err(|_| InvalidBytes)
+ ed25519_dalek::VerifyingKey::from_bytes(bytes)
+ .map(PublicKey)
+ .map_err(|_| InvalidPublicKeyBytes)
}
fn to_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] {
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
index 2985dec..97cf6a7 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
@@ -56,7 +56,7 @@ cfg_if! {
}
}
-/// The the RustCrypto backed struct which implements CryptoProvider
+/// The RustCrypto backed struct which implements CryptoProvider
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct RustCryptoImpl<R: CryptoRng + SeedableRng + RngCore> {
_marker: PhantomData<R>,
diff --git a/nearby/crypto/crypto_provider_stubs/src/lib.rs b/nearby/crypto/crypto_provider_stubs/src/lib.rs
index 32c9381..35bc274 100644
--- a/nearby/crypto/crypto_provider_stubs/src/lib.rs
+++ b/nearby/crypto/crypto_provider_stubs/src/lib.rs
@@ -29,8 +29,8 @@ use crypto_provider::{
Aes, Aes128Key, Aes256Key, AesBlock, AesCipher, AesDecryptCipher, AesEncryptCipher,
},
ed25519::{
- self, Ed25519Provider, InvalidBytes, KeyPair, RawPrivateKey, RawPrivateKeyPermit,
- RawPublicKey, RawSignature, Signature, SignatureError,
+ self, Ed25519Provider, InvalidPublicKeyBytes, KeyPairImpl, RawPrivateKey,
+ RawPrivateKeyPermit, RawPublicKey, RawSignature, SignatureError, SignatureImpl,
},
elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey},
hkdf::{Hkdf, InvalidLength},
@@ -477,10 +477,10 @@ impl Ed25519Provider for Ed25519Stubs {
type Signature = SignatureStubs;
}
-impl ed25519::PublicKey for PublicKeyStubs {
+impl ed25519::PublicKeyImpl for PublicKeyStubs {
type Signature = SignatureStubs;
- fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidBytes>
+ fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidPublicKeyBytes>
where
Self: Sized,
{
@@ -502,7 +502,7 @@ impl ed25519::PublicKey for PublicKeyStubs {
pub struct SignatureStubs;
-impl Signature for SignatureStubs {
+impl SignatureImpl for SignatureStubs {
fn from_bytes(_bytes: &RawSignature) -> Self {
unimplemented!()
}
@@ -514,7 +514,7 @@ impl Signature for SignatureStubs {
pub struct KeyPairStubs;
-impl KeyPair for KeyPairStubs {
+impl KeyPairImpl for KeyPairStubs {
type PublicKey = PublicKeyStubs;
type Signature = SignatureStubs;
@@ -537,7 +537,7 @@ impl KeyPair for KeyPairStubs {
unimplemented!()
}
- fn public(&self) -> Self::PublicKey {
+ fn public_key(&self) -> Self::PublicKey {
unimplemented!()
}
}
diff --git a/nearby/crypto/crypto_provider_test/fuzz/Cargo.lock b/nearby/crypto/crypto_provider_test/fuzz/Cargo.lock
index 49c9513..844b537 100644
--- a/nearby/crypto/crypto_provider_test/fuzz/Cargo.lock
+++ b/nearby/crypto/crypto_provider_test/fuzz/Cargo.lock
@@ -54,12 +54,6 @@ dependencies = [
]
[[package]]
-name = "aliasable"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
-
-[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -75,12 +69,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
-name = "bitflags"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
-
-[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -99,6 +87,17 @@ dependencies = [
]
[[package]]
+name = "bssl-crypto"
+version = "0.2.0"
+dependencies = [
+ "bssl-sys",
+]
+
+[[package]]
+name = "bssl-sys"
+version = "0.1.0"
+
+[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -185,24 +184,21 @@ dependencies = [
]
[[package]]
-name = "crypto_provider_default"
+name = "crypto_provider_boringssl"
version = "0.1.0"
dependencies = [
- "cfg-if",
+ "bssl-crypto",
"crypto_provider",
- "crypto_provider_openssl",
- "crypto_provider_rustcrypto",
]
[[package]]
-name = "crypto_provider_openssl"
+name = "crypto_provider_default"
version = "0.1.0"
dependencies = [
"cfg-if",
"crypto_provider",
- "crypto_provider_stubs",
- "openssl",
- "ouroboros",
+ "crypto_provider_boringssl",
+ "crypto_provider_rustcrypto",
]
[[package]]
@@ -231,13 +227,6 @@ dependencies = [
]
[[package]]
-name = "crypto_provider_stubs"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
-]
-
-[[package]]
name = "crypto_provider_test-fuzz"
version = "0.0.0"
dependencies = [
@@ -258,9 +247,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "4.1.1"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -280,7 +269,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn",
]
[[package]]
@@ -301,7 +290,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn",
]
[[package]]
@@ -326,9 +315,9 @@ dependencies = [
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -368,24 +357,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7"
-
-[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-dependencies = [
- "foreign-types-shared",
-]
-
-[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "generic-array"
@@ -431,12 +405,6 @@ dependencies = [
]
[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -466,18 +434,18 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.27"
+version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
+checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
dependencies = [
"libc",
]
[[package]]
name = "libc"
-version = "0.2.152"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
@@ -503,68 +471,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
-name = "openssl"
-version = "0.10.62"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
-dependencies = [
- "bitflags",
- "cfg-if",
- "foreign-types",
- "libc",
- "once_cell",
- "openssl-macros",
- "openssl-sys",
-]
-
-[[package]]
-name = "openssl-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.98"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "ouroboros"
-version = "0.17.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2ba07320d39dfea882faa70554b4bd342a5f273ed59ba7c1c6b4c840492c954"
-dependencies = [
- "aliasable",
- "ouroboros_macro",
- "static_assertions",
-]
-
-[[package]]
-name = "ouroboros_macro"
-version = "0.17.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
-[[package]]
name = "p256"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -575,12 +481,6 @@ dependencies = [
]
[[package]]
-name = "pkg-config"
-version = "0.3.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
-
-[[package]]
name = "platforms"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -614,34 +514,10 @@ dependencies = [
]
[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
name = "proc-macro2"
-version = "1.0.76"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -729,12 +605,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -742,16 +612,6 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
@@ -790,12 +650,6 @@ dependencies = [
]
[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -809,9 +663,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
diff --git a/nearby/crypto/crypto_provider_test/fuzz/Cargo.toml b/nearby/crypto/crypto_provider_test/fuzz/Cargo.toml
index 68fad3e..10c3e5c 100644
--- a/nearby/crypto/crypto_provider_test/fuzz/Cargo.toml
+++ b/nearby/crypto/crypto_provider_test/fuzz/Cargo.toml
@@ -8,24 +8,18 @@ edition = "2021"
cargo-fuzz = true
[dependencies]
-libfuzzer-sys = "0.4"
-crypto_provider = { path = "../../crypto_provider" }
-crypto_provider_default = { path = "../../crypto_provider_default", default-features = false }
-arbitrary = { version = "1.2.3", features = ["derive"] }
+crypto_provider.workspace = true
+crypto_provider_default = { workspace = true, default-features = false }
+derive_fuzztest.workspace = true
+
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
[features]
default = ["crypto_provider_default/default"]
-openssl = ["crypto_provider_default/openssl"]
-
-# Prevent this from interfering with workspaces
-[workspace]
-members = ["."]
-
-[profile.release]
-debug = 1
+boringssl = ["crypto_provider_default/boringssl"]
[[bin]]
name = "fuzz_p256"
-path = "fuzz_targets/fuzz_p256.rs"
-test = false
+path = "src/bin/fuzz_p256.rs"
doc = false
diff --git a/nearby/crypto/crypto_provider_test/fuzz/fuzz_targets/fuzz_p256.rs b/nearby/crypto/crypto_provider_test/fuzz/src/bin/fuzz_p256.rs
index 00a0624..f5d3111 100644
--- a/nearby/crypto/crypto_provider_test/fuzz/fuzz_targets/fuzz_p256.rs
+++ b/nearby/crypto/crypto_provider_test/fuzz/src/bin/fuzz_p256.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,24 +13,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use arbitrary::Arbitrary;
use crypto_provider::{
elliptic_curve::EcdhProvider,
p256::{P256PublicKey, P256},
CryptoProvider,
};
use crypto_provider_default::CryptoProviderImpl;
-use libfuzzer_sys::fuzz_target;
-
-#[derive(Debug, Arbitrary)]
-struct FuzzInput {
- bytes: Vec<u8>,
-}
+use derive_fuzztest::fuzztest;
type P256PublicKeyAlias<P> = <<P as CryptoProvider>::P256 as EcdhProvider<P256>>::PublicKey;
-fuzz_target!(|input: FuzzInput| {
- let pubkey = P256PublicKeyAlias::<CryptoProviderImpl>::from_sec1_bytes(&input.bytes);
+#[fuzztest]
+fn test(input: Vec<u8>) {
+ let pubkey = P256PublicKeyAlias::<CryptoProviderImpl>::from_sec1_bytes(&input);
if let Ok(key) = pubkey {
let (x, y) = key
.to_affine_coordinates()
@@ -40,4 +35,4 @@ fuzz_target!(|input: FuzzInput| {
.expect("Creating public key from affine coordinates should succeed");
assert_eq!(key, recreated_pubkey);
}
-});
+}
diff --git a/nearby/crypto/crypto_provider_test/src/aead/aes_gcm.rs b/nearby/crypto/crypto_provider_test/src/aead/aes_gcm.rs
index 88eaf32..4a84a67 100644
--- a/nearby/crypto/crypto_provider_test/src/aead/aes_gcm.rs
+++ b/nearby/crypto/crypto_provider_test/src/aead/aes_gcm.rs
@@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-use alloc::vec::Vec;
use core::marker;
use hex_literal::hex;
diff --git a/nearby/crypto/crypto_provider_test/src/aead/aes_gcm_siv.rs b/nearby/crypto/crypto_provider_test/src/aead/aes_gcm_siv.rs
index 56d2215..672b9ce 100644
--- a/nearby/crypto/crypto_provider_test/src/aead/aes_gcm_siv.rs
+++ b/nearby/crypto/crypto_provider_test/src/aead/aes_gcm_siv.rs
@@ -11,7 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-use alloc::vec::Vec;
use core::marker;
use hex_literal::hex;
diff --git a/nearby/crypto/crypto_provider_test/src/ed25519.rs b/nearby/crypto/crypto_provider_test/src/ed25519.rs
index 0fdb484..f2bc7ef 100644
--- a/nearby/crypto/crypto_provider_test/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_test/src/ed25519.rs
@@ -15,11 +15,8 @@
extern crate alloc;
extern crate std;
-use alloc::borrow::ToOwned;
-use alloc::string::String;
-use alloc::vec::Vec;
use crypto_provider::ed25519::{
- Ed25519Provider, KeyPair, PublicKey, RawPrivateKeyPermit, RawSignature, Signature,
+ Ed25519Provider, KeyPairImpl, PublicKeyImpl, RawPrivateKeyPermit, RawSignature, SignatureImpl,
};
use wycheproof::TestResult;
@@ -149,7 +146,7 @@ where
sig.as_slice().try_into().expect("Test signature should be the correct length"),
);
- let pub_key = kp.public();
+ let pub_key = kp.public_key();
assert_eq!(pub_key.to_bytes().as_slice(), expected_pub_key.as_slice());
pub_key.verify_strict(msg.as_slice(), &signature).map_err(|_| "verify failed")?;
diff --git a/nearby/crypto/crypto_provider_test/src/hkdf.rs b/nearby/crypto/crypto_provider_test/src/hkdf.rs
index d664230..d8982fd 100644
--- a/nearby/crypto/crypto_provider_test/src/hkdf.rs
+++ b/nearby/crypto/crypto_provider_test/src/hkdf.rs
@@ -14,8 +14,6 @@
extern crate alloc;
pub use crate::prelude::*;
use crate::CryptoProvider;
-use alloc::vec;
-use alloc::vec::Vec;
use core::iter;
use core::marker::PhantomData;
use crypto_provider::hkdf::Hkdf;
@@ -51,7 +49,7 @@ fn hkdf_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C
const MAX_SHA256_LENGTH: usize = 255 * (256 / 8); // =8160
-///
+/// Content of a HKDF test-case.
pub struct Test<'a> {
ikm: &'a [u8],
salt: &'a [u8],
@@ -79,9 +77,8 @@ pub fn basic_test_hkdf<C: CryptoProvider>(_: PhantomData<C>) {
assert_eq!(okm, expected);
}
-// Test Vectors from https://tools.ietf.org/html/rfc5869.
#[rustfmt::skip]
- ///
+ /// Test Vectors from <https://tools.ietf.org/html/rfc5869>.
pub fn test_rfc5869_sha256<C: CryptoProvider>(_: PhantomData<C>) {
let tests = [
Test {
@@ -152,7 +149,7 @@ pub fn basic_test_hkdf<C: CryptoProvider>(_: PhantomData<C>) {
}
}
-///
+/// Tests a bunch of HKDFs of differing lengths.
pub fn test_lengths<C: CryptoProvider>(_: PhantomData<C>) {
let hkdf = C::HkdfSha256::new(None, &[]);
let mut longest = vec![0u8; MAX_SHA256_LENGTH];
@@ -173,28 +170,28 @@ pub fn test_lengths<C: CryptoProvider>(_: PhantomData<C>) {
}
}
-///
+/// Tests an HKDF with the maximum length for Sha256.
pub fn test_max_length<C: CryptoProvider>(_: PhantomData<C>) {
let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
let mut okm = vec![0u8; MAX_SHA256_LENGTH];
assert!(hkdf.expand(&[], &mut okm).is_ok());
}
-///
+/// Tests an HKDF above the maximum length for Sha256.
pub fn test_max_length_exceeded<C: CryptoProvider>(_: PhantomData<C>) {
let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
let mut okm = vec![0u8; MAX_SHA256_LENGTH + 1];
assert!(hkdf.expand(&[], &mut okm).is_err());
}
-///
+/// Tests an HKDF with an unsupported length.
pub fn test_unsupported_length<C: CryptoProvider>(_: PhantomData<C>) {
let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
let mut okm = vec![0u8; 90000];
assert!(hkdf.expand(&[], &mut okm).is_err());
}
-///
+/// Tests HKDF-Expand on the concatenation of info components.
pub fn test_expand_multi_info<C: CryptoProvider>(_: PhantomData<C>) {
let info_components = &[
&b"09090909090909090909090909090909090909090909"[..],
@@ -231,12 +228,12 @@ pub fn test_expand_multi_info<C: CryptoProvider>(_: PhantomData<C>) {
}
}
-///
+/// Runs hkdf test vectors using Sha256.
pub fn run_hkdf_sha256_vectors<C: CryptoProvider>(_: PhantomData<C>) {
run_hkdf_test_vectors::<C::HkdfSha256>(HashAlg::Sha256)
}
-///
+/// Runs hkdf test vectors using Sha512.
pub fn run_hkdf_sha512_vectors<C: CryptoProvider>(_: PhantomData<C>) {
run_hkdf_test_vectors::<C::HkdfSha512>(HashAlg::Sha512)
}
@@ -246,7 +243,7 @@ enum HashAlg {
Sha512,
}
-///
+/// Runs the wycheproof test vectors for the given hashing algorithm.
fn run_hkdf_test_vectors<K: Hkdf>(hash: HashAlg) {
let test_name = match hash {
HashAlg::Sha256 => wycheproof::hkdf::TestName::HkdfSha256,
diff --git a/nearby/crypto/crypto_provider_test/src/lib.rs b/nearby/crypto/crypto_provider_test/src/lib.rs
index 2209a3e..6ba6413 100644
--- a/nearby/crypto/crypto_provider_test/src/lib.rs
+++ b/nearby/crypto/crypto_provider_test/src/lib.rs
@@ -13,7 +13,7 @@
// limitations under the License.
extern crate alloc;
-use alloc::{format, string::String};
+use alloc::format;
use core::marker::PhantomData;
use crypto_provider::CryptoProvider;
@@ -47,7 +47,7 @@ pub mod prelude {
pub type CryptoProviderTestCase<T> = fn(PhantomData<T>);
#[derive(Debug)]
-pub(crate) struct TestError(String);
+pub(crate) struct TestError(#[allow(unused)] String);
impl TestError {
pub(crate) fn new<D: core::fmt::Debug>(value: D) -> Self {
diff --git a/nearby/crypto/crypto_provider_test/src/sha2.rs b/nearby/crypto/crypto_provider_test/src/sha2.rs
index 66a3025..b10ac9a 100644
--- a/nearby/crypto/crypto_provider_test/src/sha2.rs
+++ b/nearby/crypto/crypto_provider_test/src/sha2.rs
@@ -16,7 +16,6 @@ extern crate alloc;
extern crate std;
use crate::prelude::*;
use crate::CryptoProvider;
-use alloc::vec::Vec;
use core::{marker::PhantomData, str::FromStr};
use crypto_provider::sha2::{Sha256, Sha512};
use hex::FromHex;
diff --git a/nearby/crypto/rand_core_05_adapter/Cargo.toml b/nearby/crypto/rand_core_05_adapter/Cargo.toml
deleted file mode 100644
index 1a02526..0000000
--- a/nearby/crypto/rand_core_05_adapter/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "rand_core_05_adapter"
-version.workspace = true
-edition.workspace = true
-publish.workspace = true
-
-[lints]
-workspace = true
-
-[dependencies]
-rand.workspace = true
-# an older rand_core used by ed25519-dalek so we can adapt newer rand to it
-rand_core05 = { package = "rand_core", version = "0.5.1" }
diff --git a/nearby/crypto/rand_core_05_adapter/src/lib.rs b/nearby/crypto/rand_core_05_adapter/src/lib.rs
deleted file mode 100644
index 9de0020..0000000
--- a/nearby/crypto/rand_core_05_adapter/src/lib.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.
-
-//! Adapter for using rand_core 0.5 RNGs with code that expects rand_core 0.5 RNGs.
-
-#![no_std]
-
-/// A trivial adapter to expose rand 1.0/rand_core 0.6 rngs to ed25519-dalek's rand_core 0.5 types,
-/// which we import under a separate name so there's no clash.
-pub struct RandWrapper<'r, R: rand::RngCore + rand::CryptoRng> {
- rng: &'r mut R,
-}
-
-impl<'r, R: rand::RngCore + rand::CryptoRng> RandWrapper<'r, R> {
- /// Build a rand_core 0.5 compatible wrapper around the provided rng.
- pub fn from(rng: &'r mut R) -> RandWrapper<'r, R> {
- RandWrapper { rng }
- }
-}
-
-impl<'r, R: rand::RngCore + rand::CryptoRng> rand_core05::RngCore for RandWrapper<'r, R> {
- fn next_u32(&mut self) -> u32 {
- self.rng.next_u32()
- }
-
- fn next_u64(&mut self) -> u64 {
- self.rng.next_u64()
- }
-
- fn fill_bytes(&mut self, dest: &mut [u8]) {
- self.rng.fill_bytes(dest)
- }
-
- #[cfg(feature = "std")]
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core05::Error> {
- self.rng.try_fill_bytes(dest).map_err(|e| rand_core05::Error::new(e.take_inner()))
- }
-
- #[cfg(not(feature = "std"))]
- #[allow(clippy::expect_used)]
- fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core05::Error> {
- self.rng
- .try_fill_bytes(dest)
- .map_err(|e| rand_core05::Error::from(e.code().expect("for no_std this is never none")))
- }
-}
-
-impl<'r, R: rand::RngCore + rand::CryptoRng> rand_core05::CryptoRng for RandWrapper<'r, R> {
- // marker trait
-}
diff --git a/nearby/deny.toml b/nearby/deny.toml
index d9f6dc8..aaf8eea 100644
--- a/nearby/deny.toml
+++ b/nearby/deny.toml
@@ -9,24 +9,6 @@
# The values provided in this template are the default values that will be used
# when any section or field is not specified in your own configuration
-# If 1 or more target triples (and optionally, target_features) are specified,
-# only the specified targets will be checked when running `cargo deny check`.
-# This means, if a particular package is only ever used as a target specific
-# dependency, such as, for example, the `nix` crate only being used via the
-# `target_family = "unix"` configuration, that only having windows targets in
-# this list would mean the nix crate, as well as any of its exclusive
-# dependencies not shared by any other crates, would be ignored, as the target
-# list here is effectively saying which targets you are building for.
-targets = [
- # The triple can be any string, but only the target triples built in to
- # rustc (as of 1.40) can be checked against actual config expressions
- #{ triple = "x86_64-unknown-linux-musl" },
- # You can also specify which target_features you promise are enabled for a
- # particular target. target_features are currently not validated against
- # the actual valid features supported by the target architecture.
- #{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
-]
-
# This section is considered when running `cargo deny check advisories`
# More documentation for the advisories section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
@@ -35,21 +17,13 @@ targets = [
db-path = "~/.cargo/advisory-db"
# The url(s) of the advisory databases to use
db-urls = ["https://github.com/rustsec/advisory-db"]
-# The lint level for security vulnerabilities
-vulnerability = "deny"
-# The lint level for unmaintained crates
-unmaintained = "warn"
# The lint level for crates that have been yanked from their source registry
yanked = "warn"
-# The lint level for crates with security notices. Note that as of
-# 2019-12-17 there are no security notice advisories in
-# https://github.com/rustsec/advisory-db
-notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
- # criterion 0.4.0 depends on a version of atty w/unaligned reads
- "RUSTSEC-2021-0145",
+ # comment explaining why we have to ignore it
+ # "RUSTSEC-FOO",
]
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
# lower than the range specified will be ignored. Note that ignored advisories
@@ -71,8 +45,6 @@ ignore = [
# More documentation for the licenses section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
[licenses]
-# The lint level for crates which do not have a detectable license
-unlicensed = "deny"
# List of explicitly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
@@ -85,28 +57,9 @@ allow = [
"ISC",
"Unicode-DFS-2016",
"OpenSSL",
- "Unlicense"
+ "Unlicense",
+ "CC0-1.0"
]
-# List of explicitly disallowed licenses
-# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
-deny = [
- #"Nokia",
-]
-# Lint level for licenses considered copyleft
-copyleft = "warn"
-# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
-# * both - The license will be approved if it is both OSI-approved *AND* FSF
-# * either - The license will be approved if it is either OSI-approved *OR* FSF
-# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
-# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
-# * neither - This predicate is ignored and the default lint level is used
-allow-osi-fsf-free = "neither"
-# Lint level used when no other predicates are matched
-# 1. License isn't in the allow or deny lists
-# 2. License isn't copyleft
-# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
-default = "deny"
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
# canonical license text of a valid SPDX license file.
@@ -117,7 +70,20 @@ confidence-threshold = 0.8
exceptions = [
# Each entry is the crate and version constraint, and its specific allow
# list
- #{ allow = ["Zlib"], name = "adler32", version = "*" },
+
+
+ # "Reciprocal" licensed crate pulled directly from crates.io without modifications
+ # Important: Update https://third-party-mirror.googlesource.com/webpki-roots/ if you update this version
+ { allow = ["MPL-2.0"], name = "webpki-roots", version = "0.25.2" },
+ # "Reciprocal" licensed crate pulled directly from crates.io without modifications
+ # Important: Update https://third-party-mirror.googlesource.com/option-ext/ if you update this version
+ { allow = ["MPL-2.0"], name = "option-ext", version = "0.2.0" },
+ # "Reciprocal" licensed crate pulled directly from crates.io without modifications
+ # Important: Update https://third-party-mirror.googlesource.com/smartstring/ if you update this version
+ { allow = ["MPL-2.0"], name = "smartstring", version = "1.0.1" },
+ # "Reciprocal" licensed crate pulled directly from crates.io without modifications
+ # Important: Update https://third-party-mirror.googlesource.com/cbindgen/ if you update this version
+ { allow = ["MPL-2.0"], name = "cbindgen", version = "0.26.0" },
]
# Some crates don't have (easily) machine readable licensing information,
@@ -136,8 +102,8 @@ exceptions = [
# and the crate will be checked normally, which may produce warnings or errors
# depending on the rest of your configuration
#license-files = [
- # Each entry is a crate relative path, and the (opaque) hash of its contents
- #{ path = "LICENSE", hash = 0xbd0eed23 }
+# Each entry is a crate relative path, and the (opaque) hash of its contents
+#{ path = "LICENSE", hash = 0xbd0eed23 }
#]
[[licenses.clarify]]
diff --git a/nearby/presence/CMakeLists.txt b/nearby/presence/CMakeLists.txt
index 9670c34..bb099de 100644
--- a/nearby/presence/CMakeLists.txt
+++ b/nearby/presence/CMakeLists.txt
@@ -14,15 +14,12 @@
cmake_minimum_required(VERSION 3.14)
-project(NearbyProtocol)
+project(NearbyPresenceProtocol)
-# required for designated initializers on MSVC
set(CMAKE_CXX_STANDARD 20)
-# root directory of repo
set(BETO_CORE_ROOT ${CMAKE_SOURCE_DIR}/../..)
-
-# location of external third_party dependencies
+set(NEARBY_ROOT ${CMAKE_SOURCE_DIR}/..)
set(THIRD_PARTY_DIR ${BETO_CORE_ROOT}/third_party)
set(CMAKE_C_FLAGS_DEBUG "-DDEBUG")
@@ -32,13 +29,6 @@ if (UNIX)
set(CMAKE_CXX_FLAGS_DEBUG "-g ${CMAKE_C_FLAGS_DEBUG}")
endif ()
-find_package(OpenSSL REQUIRED)
-if (OPENSSL_FOUND)
- message(STATUS "OpenSSL Found: ${OPENSSL_VERSION}")
- message(STATUS "OpenSSL Include: ${OPENSSL_INCLUDE_DIR}")
- message(STATUS "OpenSSL Libraries: ${OPENSSL_LIBRARIES}")
-endif ()
-
if (MSVC)
add_compile_options(-W4 -O1 -MD)
endif ()
@@ -46,12 +36,16 @@ endif ()
if (ENABLE_TESTS)
message(STATUS "Enabling workspace wide tests")
+ # We want to suppress warnings coming from external libraries as they just
+ # pollute the build output
+ add_compile_options(-w)
+
# Setup GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG release-1.12.1
+ GIT_TAG v1.14.0
)
FetchContent_MakeAvailable(googletest)
enable_testing()
@@ -69,19 +63,46 @@ if (ENABLE_TESTS)
)
endif ()
-# Add these compile options for our own code, not needed for the above deps
+set(ABSL_PROPAGATE_CXX_STD ON)
+if (ENABLE_FUZZ)
+ if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+ MESSAGE(FATAL_ERROR "fuzzing is only enabed when building with Clang, please set CC and CXX to use clang instead of ${CMAKE_CXX_COMPILER_ID}")
+ endif ()
+
+ add_subdirectory(${THIRD_PARTY_DIR}/boringssl boringssl-build)
+ add_subdirectory(${THIRD_PARTY_DIR}/fuzztest fuzztest-build)
+ enable_testing()
+ include(GoogleTest)
+else ()
+ # fuzztest handles pulling in absl, so we if we are not building fuzzers we need
+ # to include it ourselves via third_party.
+ add_subdirectory(${THIRD_PARTY_DIR}/abseil-cpp ${THIRD_PARTY_DIR}/abseil-cpp/build)
+endif ()
+
if (UNIX)
- add_compile_options(-Wall -Wextra -Wimplicit-fallthrough -Wextra-semi
- -Wno-missing-field-initializers -Wno-unused-parameter -Wno-psabi
+ set_directory_properties(
+ PROPERTIES
+ COMPILE_OPTIONS
+ -Werror
+ -Wall
+ -Wextra
+ -Wimplicit-fallthrough
+ -Wextra-semi
-Wshadow
- -Wsign-compare)
-endif()
+ -Wsign-compare
+ )
+endif ()
+# rust std lib requires linking against these
+if (UNIX)
+ link_libraries(
+ dl pthread -fsanitize=address
+ )
+elseif (MSVC)
+ link_libraries(
+ bcrypt ntdll userenv ws2_32
+ )
+endif ()
add_subdirectory(np_cpp_ffi)
-add_subdirectory(ldt_np_c_sample)
-
-if (ENABLE_FUZZ)
- message(STATUS "Building fuzzers")
- add_subdirectory(ldt_np_adv_ffi_fuzz)
-endif ()
+add_subdirectory(ldt_np_adv_ffi/c)
diff --git a/nearby/presence/README.md b/nearby/presence/README.md
index fe63af1..e7868b5 100644
--- a/nearby/presence/README.md
+++ b/nearby/presence/README.md
@@ -59,17 +59,6 @@ brew install protobuf rapidjson google-benchmark
We depend on OpenSSL of version at least 3.0.5 being installed on your machine
to build the fuzzers, for macOS run:
-```
-brew install openssl@3
-```
-
-Your build system may still be picking up an older version so you will have to
-symlink to the brew installed version:
-
-```
-brew link --force openssl
-```
-
The in-box version of Clang which comes from XCode developer tools does not have
a fuzzer runtime so we will have to use our own
diff --git a/nearby/presence/array_view/src/lib.rs b/nearby/presence/array_view/src/lib.rs
index e2ea8d4..d4d7c84 100644
--- a/nearby/presence/array_view/src/lib.rs
+++ b/nearby/presence/array_view/src/lib.rs
@@ -62,7 +62,7 @@ impl<T, const N: usize> ArrayView<T, N> {
}
}
- /// Returns the prefix of the array as a slice.
+ /// Returns the occupied portion of the array as a slice.
pub fn as_slice(&self) -> &[T] {
&self.array[..self.len]
}
@@ -105,9 +105,8 @@ impl<T, const N: usize> borrow::Borrow<[T]> for ArrayView<T, N> {
}
#[cfg(test)]
+#[allow(clippy::unwrap_used)]
mod tests {
- #![allow(clippy::unwrap_used)]
-
extern crate std;
use crate::ArrayView;
use std::format;
diff --git a/nearby/presence/ldt/benches/ldt_scan.rs b/nearby/presence/ldt/benches/ldt_scan.rs
index b1711ad..f5fa359 100644
--- a/nearby/presence/ldt/benches/ldt_scan.rs
+++ b/nearby/presence/ldt/benches/ldt_scan.rs
@@ -19,7 +19,8 @@ use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_rustcrypto::RustCrypto;
use ctr::cipher::{KeyIvInit as _, StreamCipher as _, StreamCipherSeek as _};
use ldt::{
- DefaultPadder, LdtDecryptCipher, LdtEncryptCipher, LdtKey, Mix, Padder, Swap, XorPadder,
+ DefaultPadder, LdtCipher, LdtDecryptCipher, LdtEncryptCipher, LdtKey, Mix, Padder, Swap,
+ XorPadder,
};
use ldt_tbc::TweakableBlockCipher;
use sha2::Digest as _;
@@ -159,7 +160,9 @@ fn random_vec<C: CryptoProvider>(rng: &mut C::CryptoRng, len: usize) -> Vec<u8>
}
trait ScanCipher {
+ #[allow(dead_code)]
fn encrypt(&mut self, buf: &mut [u8]);
+
fn decrypt(&mut self, buf: &mut [u8]);
}
diff --git a/nearby/presence/ldt/examples/gen_ldt_xor_pad_test_vectors.rs b/nearby/presence/ldt/examples/gen_ldt_xor_pad_test_vectors.rs
index 7e7c943..43ba617 100644
--- a/nearby/presence/ldt/examples/gen_ldt_xor_pad_test_vectors.rs
+++ b/nearby/presence/ldt/examples/gen_ldt_xor_pad_test_vectors.rs
@@ -19,7 +19,7 @@
use crypto_provider::aes::BLOCK_SIZE;
use crypto_provider::{aes, CryptoProvider, CryptoRng};
use crypto_provider_rustcrypto::RustCrypto;
-use ldt::{LdtEncryptCipher, LdtKey, Swap, XorPadder};
+use ldt::{LdtCipher, LdtEncryptCipher, LdtKey, Swap, XorPadder};
use rand::{Rng as _, SeedableRng as _};
use rand_ext::*;
use serde_json::json;
diff --git a/nearby/presence/ldt/examples/ldt_benchmark.rs b/nearby/presence/ldt/examples/ldt_benchmark.rs
index 101e17b..a710d56 100644
--- a/nearby/presence/ldt/examples/ldt_benchmark.rs
+++ b/nearby/presence/ldt/examples/ldt_benchmark.rs
@@ -18,7 +18,7 @@
use clap::Parser as _;
use crypto_provider_rustcrypto::RustCrypto;
-use ldt::{LdtDecryptCipher, LdtEncryptCipher, LdtKey, Mix, Swap, XorPadder};
+use ldt::{LdtCipher, LdtDecryptCipher, LdtEncryptCipher, LdtKey, Mix, Swap, XorPadder};
use crypto_provider::{CryptoProvider, CryptoRng};
use ldt_tbc::TweakableBlockCipher;
diff --git a/nearby/presence/ldt/examples/ldt_prp.rs b/nearby/presence/ldt/examples/ldt_prp.rs
index 7734952..fea1904 100644
--- a/nearby/presence/ldt/examples/ldt_prp.rs
+++ b/nearby/presence/ldt/examples/ldt_prp.rs
@@ -23,7 +23,7 @@
#![allow(clippy::unwrap_used, clippy::indexing_slicing)]
-use clap::{self, Parser as _};
+use clap::Parser as _;
use crypto_provider::aes::BLOCK_SIZE;
use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_rustcrypto::RustCrypto;
diff --git a/nearby/presence/ldt/fuzz/Cargo.lock b/nearby/presence/ldt/fuzz/Cargo.lock
index 7262f74..3298a9e 100644
--- a/nearby/presence/ldt/fuzz/Cargo.lock
+++ b/nearby/presence/ldt/fuzz/Cargo.lock
@@ -55,9 +55,9 @@ dependencies = [
[[package]]
name = "arbitrary"
-version = "1.3.0"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
@@ -92,9 +92,9 @@ dependencies = [
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cbc"
@@ -107,11 +107,12 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
+ "libc",
]
[[package]]
@@ -132,24 +133,24 @@ dependencies = [
[[package]]
name = "const-oid"
-version = "0.9.4"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-bigint"
-version = "0.5.2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array",
"rand_core",
@@ -211,9 +212,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "4.0.0"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -227,9 +228,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
@@ -238,9 +239,9 @@ dependencies = [
[[package]]
name = "der"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
dependencies = [
"const-oid",
"zeroize",
@@ -248,9 +249,9 @@ dependencies = [
[[package]]
name = "derive_arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
@@ -270,18 +271,18 @@ dependencies = [
[[package]]
name = "ed25519"
-version = "2.2.1"
+version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"signature",
]
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -292,9 +293,9 @@ dependencies = [
[[package]]
name = "elliptic-curve"
-version = "0.13.5"
+version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -321,9 +322,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
-version = "0.1.20"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "generic-array"
@@ -338,9 +339,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -370,9 +371,9 @@ dependencies = [
[[package]]
name = "hkdf"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
@@ -398,9 +399,9 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.26"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
@@ -433,15 +434,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
@@ -450,9 +451,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
@@ -472,9 +473,9 @@ dependencies = [
[[package]]
name = "platforms"
-version = "3.0.2"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
+checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
[[package]]
name = "polyval"
@@ -496,27 +497,27 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "primeorder"
-version = "0.13.2"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -573,9 +574,9 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.18"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "sha2"
@@ -590,9 +591,9 @@ dependencies = [
[[package]]
name = "signature"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
[[package]]
name = "subtle"
@@ -602,9 +603,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "2.0.26"
+version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@@ -619,15 +620,15 @@ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "universal-hash"
@@ -653,9 +654,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
@@ -672,6 +673,6 @@ dependencies = [
[[package]]
name = "zeroize"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/nearby/presence/ldt/fuzz/Cargo.toml b/nearby/presence/ldt/fuzz/Cargo.toml
index 3f37e98..c192792 100644
--- a/nearby/presence/ldt/fuzz/Cargo.toml
+++ b/nearby/presence/ldt/fuzz/Cargo.toml
@@ -1,32 +1,23 @@
[package]
name = "ldt-fuzz"
-version = "0.0.0"
-authors = ["Automatically generated"]
-publish = false
-edition = "2018"
+version.workspace = true
+publish.workspace = true
+edition.workspace = true
[package.metadata]
cargo-fuzz = true
[dependencies]
-libfuzzer-sys = "0.4"
-arbitrary = { version = "1.1.7", features = ["derive"] }
+arbitrary = { workspace = true, features = ["derive"] }
+crypto_provider_rustcrypto.workspace = true
+derive_fuzztest.workspace = true
+ldt.workspace = true
+xts_aes.workspace = true
-[dependencies.ldt]
-path = ".."
-
-[dependencies.xts_aes]
-path = "../../xts_aes"
-
-[dependencies.crypto_provider_rustcrypto]
-path = "../../../crypto/crypto_provider_rustcrypto"
-
-# Prevent this from interfering with workspaces
-[workspace]
-members = ["."]
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
[[bin]]
-name = "ldt-roundtrip"
-path = "fuzz_targets/ldt_roundtrip.rs"
-test = false
+name = "ldt_roundtrip"
+path = "src/bin/ldt_roundtrip.rs"
doc = false
diff --git a/nearby/presence/ldt/fuzz/fuzz_targets/ldt_roundtrip.rs b/nearby/presence/ldt/fuzz/src/bin/ldt_roundtrip.rs
index 13e2a46..097900f 100644
--- a/nearby/presence/ldt/fuzz/fuzz_targets/ldt_roundtrip.rs
+++ b/nearby/presence/ldt/fuzz/src/bin/ldt_roundtrip.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,25 +14,28 @@
// limitations under the License.
use crypto_provider_rustcrypto::RustCrypto;
+use derive_fuzztest::fuzztest;
use ldt::*;
-use libfuzzer_sys::fuzz_target;
use xts_aes::XtsAes128;
-fuzz_target!(|data: LdtFuzzInput| {
- let ldt_enc =
- LdtEncryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(&LdtKey::from_concatenated(&data.ldt_key));
- let ldt_dec =
- LdtDecryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(&LdtKey::from_concatenated(&data.ldt_key));
+#[fuzztest]
+fn test(data: LdtFuzzInput) {
+ let ldt_enc = LdtEncryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(
+ &LdtKey::from_concatenated(&data.ldt_key),
+ );
+ let ldt_dec = LdtDecryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(
+ &LdtKey::from_concatenated(&data.ldt_key),
+ );
let len = 16 + (data.len as usize % 16);
- let padder: XorPadder<16> = data.xor_padder.clone().into();
+ let padder: XorPadder<16> = data.xor_padder.into();
- let mut buffer = data.plaintext.clone();
+ let mut buffer = data.plaintext;
ldt_enc.encrypt(&mut buffer[..len], &padder).unwrap();
ldt_dec.decrypt(&mut buffer[..len], &padder).unwrap();
assert_eq!(data.plaintext, buffer);
-});
+}
-#[derive(Debug, arbitrary::Arbitrary)]
+#[derive(Clone, Debug, arbitrary::Arbitrary)]
struct LdtFuzzInput {
// XTS-AES128 keys
ldt_key: [u8; 64],
diff --git a/nearby/presence/ldt/src/lib.rs b/nearby/presence/ldt/src/lib.rs
index 8596ad2..2b4a962 100644
--- a/nearby/presence/ldt/src/lib.rs
+++ b/nearby/presence/ldt/src/lib.rs
@@ -19,11 +19,20 @@
#[cfg(feature = "std")]
extern crate std;
-use core::{fmt, marker::PhantomData};
+use core::{fmt, marker::PhantomData, ops};
use crypto_provider::CryptoProvider;
use ldt_tbc::{ConcatenatedKeyArray, TweakableBlockCipher, TweakableBlockCipherKey};
use ldt_tbc::{TweakableBlockCipherDecrypter, TweakableBlockCipherEncrypter};
+/// Common functionality for [LdtEncryptCipher] and [LdtDecryptCipher]
+pub trait LdtCipher<const B: usize, T: TweakableBlockCipher<B>> {
+ /// The range of input lengths the cipher can operate on
+ const VALID_INPUT_LEN: ops::Range<usize>;
+
+ /// Create a new cipher with the provided [TweakableBlockCipher] and [Mix] function
+ fn new(key: &LdtKey<T::Key>) -> Self;
+}
+
/// Implementation of the [LDT](https://eprint.iacr.org/2017/841.pdf) length doubler encryption cipher.
///
/// `B` is the block size.
@@ -36,16 +45,21 @@ pub struct LdtEncryptCipher<const B: usize, T: TweakableBlockCipher<B>, M: Mix>
mix_phantom: PhantomData<M>,
}
-impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtEncryptCipher<B, T, M> {
- /// Create an [LdtEncryptCipher] with the provided Tweakable block cipher and Mix function
- pub fn new(key: &LdtKey<T::Key>) -> Self {
+impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtCipher<B, T>
+ for LdtEncryptCipher<B, T, M>
+{
+ const VALID_INPUT_LEN: ops::Range<usize> = input_len_range::<B>();
+
+ fn new(key: &LdtKey<T::Key>) -> Self {
LdtEncryptCipher {
cipher_1: T::EncryptionCipher::new(&key.key_1),
cipher_2: T::EncryptionCipher::new(&key.key_2),
mix_phantom: PhantomData,
}
}
+}
+impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtEncryptCipher<B, T, M> {
/// Encrypt `data` in place, performing the pad operation with `padder`.
///
/// Unless you have particular padding needs, use [DefaultPadder].
@@ -79,13 +93,6 @@ pub struct LdtDecryptCipher<const B: usize, T: TweakableBlockCipher<B>, M: Mix>
impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtDecryptCipher<B, T, M> {
/// Create an [LdtDecryptCipher] with the provided Tweakable block cipher and Mix function
- pub fn new(key: &LdtKey<T::Key>) -> Self {
- LdtDecryptCipher {
- cipher_1: T::DecryptionCipher::new(&key.key_1),
- cipher_2: T::DecryptionCipher::new(&key.key_2),
- mix_phantom: PhantomData,
- }
- }
/// Decrypt `data` in place, performing the pad operation with `padder`.
///
@@ -106,6 +113,26 @@ impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtDecryptCipher<B, T,
}
}
+impl<const B: usize, T: TweakableBlockCipher<B>, M: Mix> LdtCipher<B, T>
+ for LdtDecryptCipher<B, T, M>
+{
+ const VALID_INPUT_LEN: ops::Range<usize> = input_len_range::<B>();
+
+ fn new(key: &LdtKey<T::Key>) -> Self {
+ LdtDecryptCipher {
+ cipher_1: T::DecryptionCipher::new(&key.key_1),
+ cipher_2: T::DecryptionCipher::new(&key.key_2),
+ mix_phantom: PhantomData,
+ }
+ }
+}
+
+/// Returns the range of valid input lengths to encrypt or decrypt with LDT for a given tweakable
+/// block cipher block size `B`, namely `[B, B * 2)`.
+const fn input_len_range<const B: usize>() -> ops::Range<usize> {
+ B..B * 2
+}
+
// internal implementation of ldt cipher operations, re-used by encryption and decryption, by providing
// the corresponding cipher_op and mix operation
fn do_ldt<const B: usize, T, O, C, X, P>(
@@ -124,7 +151,7 @@ where
X: for<'a, 'b> Fn(&'a [u8], &'b [u8]) -> (&'b [u8], &'a [u8]),
P: Padder<B, T>,
{
- if data.len() < B || data.len() >= B * 2 {
+ if !input_len_range::<B>().contains(&data.len()) {
return Err(LdtError::InvalidLength(data.len()));
}
let s = data.len() - B;
@@ -229,6 +256,7 @@ pub trait Mix {
/// Per section 2.4, swapping `a` and `b` is a valid mix function
pub struct Swap {}
+
impl Mix for Swap {
fn forwards<'a, 'b>(a: &'a [u8], b: &'b [u8]) -> (&'b [u8], &'a [u8]) {
debug_assert_eq!(a.len(), b.len());
diff --git a/nearby/presence/ldt/tests/ldt_roundtrip.rs b/nearby/presence/ldt/tests/ldt_roundtrip.rs
index 251cefe..fabddf0 100644
--- a/nearby/presence/ldt/tests/ldt_roundtrip.rs
+++ b/nearby/presence/ldt/tests/ldt_roundtrip.rs
@@ -20,7 +20,7 @@ use crypto_provider_default::CryptoProviderImpl;
use ldt::*;
use ldt_tbc::TweakableBlockCipher;
use rand::rngs::StdRng;
-use rand::{self, distributions, Rng as _, SeedableRng as _};
+use rand::{distributions, Rng as _, SeedableRng as _};
use rand_ext::{random_bytes, random_vec};
use xts_aes::{XtsAes128, XtsAes256};
@@ -57,9 +57,7 @@ fn roundtrip_normal_padder() {
fn roundtrip_xor_padder() {
let mut rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
let mut rc_rng = rand::rngs::StdRng::from_entropy();
- // 2 bytes smaller because we're using a 2 byte salt
- let plaintext_len_range =
- distributions::Uniform::new_inclusive(BLOCK_SIZE, BLOCK_SIZE * 2 - 1 - 2);
+ let plaintext_len_range = distributions::Uniform::new_inclusive(BLOCK_SIZE, BLOCK_SIZE * 2 - 1);
for _ in 0..100_000 {
let padder: XorPadder<BLOCK_SIZE> =
diff --git a/nearby/presence/ldt/tests/ldt_test_vectors.rs b/nearby/presence/ldt/tests/ldt_test_vectors.rs
index 03b5d3f..1e8a5e1 100644
--- a/nearby/presence/ldt/tests/ldt_test_vectors.rs
+++ b/nearby/presence/ldt/tests/ldt_test_vectors.rs
@@ -16,7 +16,7 @@
use anyhow::anyhow;
use crypto_provider_default::CryptoProviderImpl;
-use ldt::{DefaultPadder, LdtDecryptCipher, LdtEncryptCipher, LdtKey, Swap, XorPadder};
+use ldt::{DefaultPadder, LdtCipher, LdtDecryptCipher, LdtEncryptCipher, LdtKey, Swap, XorPadder};
use std::{fs, io::Read as _};
use test_helper::{extract_key_array, extract_key_vec};
use xts_aes::XtsAes128;
diff --git a/nearby/presence/ldt/tests/tests.rs b/nearby/presence/ldt/tests/tests.rs
index 25938fb..e68273f 100644
--- a/nearby/presence/ldt/tests/tests.rs
+++ b/nearby/presence/ldt/tests/tests.rs
@@ -18,7 +18,8 @@ use alloc::vec;
use crypto_provider::aes::BLOCK_SIZE;
use crypto_provider_default::CryptoProviderImpl;
use ldt::{
- DefaultPadder, LdtDecryptCipher, LdtEncryptCipher, LdtError, LdtKey, Padder, Swap, XorPadder,
+ DefaultPadder, LdtCipher, LdtDecryptCipher, LdtEncryptCipher, LdtError, LdtKey, Padder, Swap,
+ XorPadder,
};
use xts_aes::{XtsAes128, XtsAes128Key};
@@ -137,20 +138,22 @@ fn xor_pad_too_big_panics() {
#[test]
fn encrypt_too_short_err() {
- do_length_check_enc(7)
+ do_length_check_enc(15)
}
#[test]
fn encrypt_too_long_err() {
- do_length_check_enc(40)
+ do_length_check_enc(32)
}
+
#[test]
fn decrypt_too_short_err() {
- do_length_check_dec(7)
+ do_length_check_dec(15)
}
+
#[test]
fn decrypt_too_long_err() {
- do_length_check_dec(40)
+ do_length_check_dec(32)
}
fn do_length_check_dec(len: usize) {
diff --git a/nearby/presence/ldt_np_adv/Cargo.toml b/nearby/presence/ldt_np_adv/Cargo.toml
index 3f19bdd..5d18a28 100644
--- a/nearby/presence/ldt_np_adv/Cargo.toml
+++ b/nearby/presence/ldt_np_adv/Cargo.toml
@@ -21,9 +21,9 @@ ldt_tbc.workspace = true
[dev-dependencies]
crypto_provider_default = { workspace = true, features = ["rustcrypto", "std"] }
-crypto_provider_openssl.workspace = true
rand_ext.workspace = true
test_helper.workspace = true
+test_vector_hkdf.workspace = true
rand.workspace = true
base64.workspace = true
diff --git a/nearby/presence/ldt_np_adv/benches/ldt_adv_scan.rs b/nearby/presence/ldt_np_adv/benches/ldt_adv_scan.rs
index 7c0b4aa..f9b1880 100644
--- a/nearby/presence/ldt_np_adv/benches/ldt_adv_scan.rs
+++ b/nearby/presence/ldt_np_adv/benches/ldt_adv_scan.rs
@@ -21,8 +21,7 @@ use array_view::ArrayView;
use rand::{Rng as _, SeedableRng as _};
use crypto_provider::CryptoProvider;
-use crypto_provider_openssl::Openssl;
-use crypto_provider_rustcrypto::RustCrypto;
+use crypto_provider_default::CryptoProviderImpl;
use np_hkdf::NpKeySeedHkdf;
@@ -37,7 +36,7 @@ fn ldt_adv_scan<C: CryptoProvider>(c: &mut Criterion) {
let payload_len = rng.gen_range(crypto_provider::aes::BLOCK_SIZE..=LDT_XTS_AES_MAX_LEN);
let payload = random_vec(&mut rng, payload_len);
- let salt = LegacySalt::from(rng.gen::<[u8; 2]>());
+ let salt = V0Salt::from(rng.gen::<[u8; 2]>());
#[allow(clippy::unit_arg)]
b.iter(|| {
let ciphers = build_ciphers(&configs);
@@ -49,7 +48,7 @@ fn ldt_adv_scan<C: CryptoProvider>(c: &mut Criterion) {
let payload_len = rng.gen_range(crypto_provider::aes::BLOCK_SIZE..=LDT_XTS_AES_MAX_LEN);
let payload = random_vec(&mut rng, payload_len);
- let salt = LegacySalt::from(rng.gen::<[u8; 2]>());
+ let salt = V0Salt::from(rng.gen::<[u8; 2]>());
let ciphers = build_ciphers(&configs);
#[allow(clippy::unit_arg)]
b.iter(|| black_box(find_matching_item::<C>(&ciphers, salt, &payload)));
@@ -57,15 +56,15 @@ fn ldt_adv_scan<C: CryptoProvider>(c: &mut Criterion) {
}
}
-criterion_group!(benches, ldt_adv_scan::<RustCrypto>, ldt_adv_scan::<Openssl>);
+criterion_group!(benches, ldt_adv_scan::<CryptoProviderImpl>);
criterion_main!(benches);
fn find_matching_item<C: CryptoProvider>(
- ciphers: &[LdtNpAdvDecrypterXtsAes128<C>],
- salt: LegacySalt,
+ ciphers: &[AuthenticatedNpLdtDecryptCipher<C>],
+ salt: V0Salt,
payload: &[u8],
) {
- let padder = salt_padder::<16, C>(salt);
+ let padder = salt_padder::<C>(salt);
let _ = ciphers
.iter()
.enumerate()
@@ -76,12 +75,12 @@ fn find_matching_item<C: CryptoProvider>(
.ok()
})
.next()
- .map(|(index, buffer)| MatchResult { matching_index: index, buffer });
+ .map(|(index, (token, plaintext))| MatchResult { matching_index: index, token, plaintext });
}
fn build_ciphers<C: CryptoProvider>(
configs: &[CipherConfig<C>],
-) -> Vec<LdtNpAdvDecrypterXtsAes128<C>> {
+) -> Vec<AuthenticatedNpLdtDecryptCipher<C>> {
configs
.iter()
.map(|config| {
@@ -100,8 +99,10 @@ struct CipherConfig<C: CryptoProvider> {
pub struct MatchResult<const O: usize> {
/// The index of the batch item that matched
matching_index: usize,
- /// The buffer holding the plaintext
- buffer: ArrayView<u8, O>,
+ /// The matched identity token
+ token: V0IdentityToken,
+ /// The buffer holding the remaining plaintext
+ plaintext: ArrayView<u8, O>,
}
fn random_configs<C: CryptoProvider, R: rand::Rng>(
diff --git a/nearby/presence/ldt_np_adv/fuzz/Cargo.lock b/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
index 3bfbfb9..0a85bd9 100644
--- a/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
+++ b/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
@@ -55,9 +55,9 @@ dependencies = [
[[package]]
name = "arbitrary"
-version = "1.3.0"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
@@ -96,9 +96,9 @@ dependencies = [
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cbc"
@@ -111,11 +111,12 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
+ "libc",
]
[[package]]
@@ -136,24 +137,24 @@ dependencies = [
[[package]]
name = "const-oid"
-version = "0.9.4"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-bigint"
-version = "0.5.2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array",
"rand_core",
@@ -215,9 +216,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "4.0.0"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -231,9 +232,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
@@ -242,9 +243,9 @@ dependencies = [
[[package]]
name = "der"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
dependencies = [
"const-oid",
"zeroize",
@@ -252,9 +253,9 @@ dependencies = [
[[package]]
name = "derive_arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
@@ -274,18 +275,18 @@ dependencies = [
[[package]]
name = "ed25519"
-version = "2.2.1"
+version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"signature",
]
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -296,9 +297,9 @@ dependencies = [
[[package]]
name = "elliptic-curve"
-version = "0.13.5"
+version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -325,9 +326,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
-version = "0.1.20"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "generic-array"
@@ -342,9 +343,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -374,9 +375,9 @@ dependencies = [
[[package]]
name = "hkdf"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
@@ -402,9 +403,9 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.26"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
@@ -451,15 +452,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
@@ -477,9 +478,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
@@ -499,9 +500,9 @@ dependencies = [
[[package]]
name = "platforms"
-version = "3.0.2"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
+checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
[[package]]
name = "polyval"
@@ -523,27 +524,27 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "primeorder"
-version = "0.13.2"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -600,9 +601,9 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.18"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "sha2"
@@ -617,9 +618,9 @@ dependencies = [
[[package]]
name = "signature"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
[[package]]
name = "subtle"
@@ -629,9 +630,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "2.0.26"
+version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@@ -646,15 +647,15 @@ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "universal-hash"
@@ -680,9 +681,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
@@ -699,6 +700,6 @@ dependencies = [
[[package]]
name = "zeroize"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/nearby/presence/ldt_np_adv/fuzz/Cargo.toml b/nearby/presence/ldt_np_adv/fuzz/Cargo.toml
index a346c6b..e4f497c 100644
--- a/nearby/presence/ldt_np_adv/fuzz/Cargo.toml
+++ b/nearby/presence/ldt_np_adv/fuzz/Cargo.toml
@@ -1,40 +1,30 @@
[package]
name = "ldt-np-adv-fuzz"
-version = "0.0.0"
-authors = ["Automatically generated"]
-publish = false
-edition = "2018"
+version.workspace = true
+publish.workspace = true
+edition.workspace = true
[package.metadata]
cargo-fuzz = true
[dependencies]
-libfuzzer-sys = "0.4"
-arbitrary = { version = "1.1.7", features = ["derive"] }
-crypto_provider_rustcrypto = { path = "../../../crypto/crypto_provider_rustcrypto", features = ["alloc"] }
+arbitrary = { workspace = true, features = ["derive"] }
+crypto_provider_rustcrypto = { workspace = true, features = ["alloc"] }
+derive_fuzztest.workspace = true
+ldt.workspace = true
+ldt_np_adv.workspace = true
+np_hkdf.workspace = true
+xts_aes.workspace = true
-[dependencies.ldt_np_adv]
-path = ".."
-
-[dependencies.np_hkdf]
-path = "../../np_hkdf"
-[dependencies.xts_aes]
-path = "../../xts_aes"
-[dependencies.ldt]
-path = "../../ldt"
-
-# Prevent this from interfering with workspaces
-[workspace]
-members = ["."]
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
[[bin]]
-name = "ldt-np-roundtrip"
-path = "fuzz_targets/ldt_np_roundtrip.rs"
-test = false
+name = "ldt_np_roundtrip"
+path = "src/bin/ldt_np_roundtrip.rs"
doc = false
[[bin]]
-name = "ldt-np-decrypt"
-path = "fuzz_targets/ldt_np_decrypt.rs"
-test = false
+name = "ldt_np_decrypt"
+path = "src/bin/ldt_np_decrypt.rs"
doc = false
diff --git a/nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_decrypt.rs b/nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_decrypt.rs
index 2039219..995ac15 100644
--- a/nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_decrypt.rs
+++ b/nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_decrypt.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,26 +14,25 @@
// limitations under the License.
use crypto_provider_rustcrypto::RustCrypto;
+use derive_fuzztest::fuzztest;
use ldt_np_adv::*;
-use libfuzzer_sys::fuzz_target;
-fuzz_target!(|data: LdtNpDecryptFuzzInput| {
+#[fuzztest]
+fn test(data: LdtNpDecryptFuzzInput) {
// try to decrypt data that won't pass validation
let salt = data.salt.into();
- let padder = salt_padder::<16, RustCrypto>(salt);
+ let padder = salt_padder::<RustCrypto>(salt);
let hkdf = np_hkdf::NpKeySeedHkdf::<RustCrypto>::new(&data.key_seed);
let cipher = build_np_adv_decrypter_from_key_seed::<RustCrypto>(&hkdf, data.metadata_key_hmac);
let len = 16 + (data.len as usize % 16);
let ciphertext = data.ciphertext;
- let err = cipher
- .decrypt_and_verify(&ciphertext[..len], &padder)
- .unwrap_err();
+ let err = cipher.decrypt_and_verify(&ciphertext[..len], &padder).unwrap_err();
assert_eq!(LdtAdvDecryptError::MacMismatch, err);
-});
+}
-#[derive(Debug, arbitrary::Arbitrary)]
+#[derive(Clone, Debug, arbitrary::Arbitrary)]
struct LdtNpDecryptFuzzInput {
key_seed: [u8; 32],
salt: [u8; 2],
diff --git a/nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_roundtrip.rs b/nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_roundtrip.rs
index 69f82c3..27ee8aa 100644
--- a/nearby/presence/ldt_np_adv/fuzz/fuzz_targets/ldt_np_roundtrip.rs
+++ b/nearby/presence/ldt_np_adv/fuzz/src/bin/ldt_np_roundtrip.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,35 +14,34 @@
// limitations under the License.
use crypto_provider_rustcrypto::RustCrypto;
+use derive_fuzztest::fuzztest;
use ldt::*;
use ldt_np_adv::*;
-use libfuzzer_sys::fuzz_target;
use xts_aes::XtsAes128;
-fuzz_target!(|data: LdtNpRoundtripFuzzInput| {
+#[fuzztest]
+fn test(data: LdtNpRoundtripFuzzInput) {
let salt = data.salt.into();
- let padder = salt_padder::<16, RustCrypto>(salt);
+ let padder = salt_padder::<RustCrypto>(salt);
let hkdf = np_hkdf::NpKeySeedHkdf::<RustCrypto>::new(&data.key_seed);
- let ldt_enc = LdtEncryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(&hkdf.legacy_ldt_key());
- let metadata_key_hmac: [u8; 32] = hkdf
- .legacy_metadata_key_hmac_key()
- .calculate_hmac(&data.plaintext[..14]);
+ let ldt_enc = LdtEncryptCipher::<16, XtsAes128<RustCrypto>, Swap>::new(&hkdf.v0_ldt_key());
+ let identity_token_hmac: [u8; 32] =
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<RustCrypto>(&data.plaintext[..14]);
- let cipher = build_np_adv_decrypter_from_key_seed::<RustCrypto>(&hkdf, metadata_key_hmac);
+ let cipher = build_np_adv_decrypter_from_key_seed::<RustCrypto>(&hkdf, identity_token_hmac);
let len = 16 + (data.len as usize % 16);
let mut ciphertext = data.plaintext;
ldt_enc.encrypt(&mut ciphertext[..len], &padder).unwrap();
- let plaintext = cipher
- .decrypt_and_verify(&ciphertext[..len], &padder)
- .unwrap();
+ let (token, plaintext) = cipher.decrypt_and_verify(&ciphertext[..len], &padder).unwrap();
- assert_eq!(&data.plaintext[..len], plaintext.as_slice());
-});
+ assert_eq!(&data.plaintext[..14], token.as_slice());
+ assert_eq!(&data.plaintext[14..len], plaintext.as_slice());
+}
-#[derive(Debug, arbitrary::Arbitrary)]
+#[derive(Clone, Debug, arbitrary::Arbitrary)]
struct LdtNpRoundtripFuzzInput {
key_seed: [u8; 32],
salt: [u8; 2],
diff --git a/nearby/presence/ldt_np_adv/resources/test/np_adv_test_vectors.json b/nearby/presence/ldt_np_adv/resources/test/np_adv_test_vectors.json
index f93ed7d..9c038f6 100644
--- a/nearby/presence/ldt_np_adv/resources/test/np_adv_test_vectors.json
+++ b/nearby/presence/ldt_np_adv/resources/test/np_adv_test_vectors.json
@@ -1,9002 +1,902 @@
[
{
- "key_seed": "CCDB2489E9FCAC42B39348B8941ED19A1D360E75E098C8C15E6B1CC2B620CD39",
- "ldt_key": "2E5F784296A2ECBB93D7D6E691541F610D6559D5A71903DD80E9FC84659DCAD60687E41330962A9499268ACE1F57857E35220D25B6AD795F9AEDC1A98D948937",
- "hmac_key": "CAEF6DF5857EB67D8D3904D28AF752DCD3115C3CD7C37ECC5076ACE2FAEA5931",
- "adv_salt": "32EE",
- "plaintext": "CD683FE1A1D1F846543D0A13D4AEA40040C8D67B",
- "ciphertext": "04344411F1E57C841FE0F7150636BC782455059A",
- "metadata_key_hmac": "DFB90A1F9B1FE28D18BBCCA52240B5CC2CCB5F8D5289A3CB64EB3541CA614BB4"
+ "adv_salt": "837A",
+ "ciphertext": "A3D54A03A1464A5D99ECE37D911D52B4E947D4089A",
+ "hmac_key": "BE092602F20D6B4EC33E2B9AEF678C2B023EA9FAB898301BEC13C38FDBFBDFF9",
+ "identity_token_hmac": "D93A08B8D832EA27B73E7E968A91B6C81B0DBBD4FC78296A69F47D022B64B08E",
+ "key_seed": "B79F74DE4ED9D43E3FF020A41E977AD5A323E42CA0BE566CB760E020B375840A",
+ "ldt_key": "5EEA9AC9AD55DDA8AF8E9C58A2A0755C3F14FC1A64B1EEAF7685F414841570A3218AD128B5BA7854ABA0F57F0D0ABE8A49A735EB6FC71761D8230C4B05FFFB39",
+ "plaintext": "240F027310713775CC527734711817A03BEB8E56A2"
+ },
+ {
+ "adv_salt": "96A6",
+ "ciphertext": "44C8C117FE2D5586022C937EF257D5C4044BFACD7BA9E87B40",
+ "hmac_key": "139AF9A6201E31A30F7FEE1F30611D38E972E9D184A1FCDD44BDCE63CD9AB49C",
+ "identity_token_hmac": "A36DCAE0D2A6653B48D3F5011575E9068125B1DF6C881E3BC7DB6B159EA72CB5",
+ "key_seed": "B500DA3B332D2479A6D8DB6E7D15ABF6B4FF4B904BE5F80AFAE122195A799FAB",
+ "ldt_key": "45C63D99AC38E54FB4FDB53DC596B454D76CEF966B599C27419F4819FC9810CD87312C979C48ED6B83C53125C9EF55192458BF679541E9861E8E49A5FA6BAF6E",
+ "plaintext": "5403F6847243EFA04FC14888589736F0A5679472ACB8B13E9D"
+ },
+ {
+ "adv_salt": "07B6",
+ "ciphertext": "E319FCF0BB99BBFC0777A05AB272EADC7F0E821AF8C338",
+ "hmac_key": "38E785461FF16DF3B7863F0F96B9D74B83F2A8525FA6A4A2F1DB3221EDD9F3BE",
+ "identity_token_hmac": "B1725BEEE1B8C61FD200FB13BE3585F39F9EECF6DD31E35C0133619B56ED048B",
+ "key_seed": "A077F988C1B6EA01E5D963A4E2A20D80FD488004E38883EADE3718227002FE71",
+ "ldt_key": "E2CC5F34FC7CF7B12D2A79ACFC59EA4BB129BDA2D56F538C4932A890A814567991FC5187ACFCC520744AB24DBCB30076D71E5B2A9F412F040D6BBCD20B0C758E",
+ "plaintext": "9745E73B23263894A11B0C1AB144CDDE85EF145BA18CAF"
+ },
+ {
+ "adv_salt": "B673",
+ "ciphertext": "D788023D9DA9237C2DDED0AAE3BFAD1DF9D1EB2641B3426776C5",
+ "hmac_key": "69C7E2FBEEF2D39029CD4C12B38F8BE0531766EFF1C9D8D341E0177F7708B7B5",
+ "identity_token_hmac": "D63CA07B22D9FE3D0F3FCF5A0924D73F21646215F366F6555BCD230B5990E2FB",
+ "key_seed": "1255F9C1EF194FF42AA4D890AE745CE4944D18F4E6F52672E808FA77CDB5149F",
+ "ldt_key": "A21D10CEF0130B8F6CAEF9A3BA2D6549440D008D9112A4289AAA128CD9E0536DE643AA593A485A898EC7113853ECDFC283DEA363C8AEE35DAC38DC77233FAF02",
+ "plaintext": "5C0EF76123617A69862568D1B3822767AF785A37D4834D7CA4F6"
+ },
+ {
+ "adv_salt": "1C75",
+ "ciphertext": "2AE1434E1D7E5B3F8F472E2CF8B2534CFF2A1B9A12",
+ "hmac_key": "10F332744FCFC9703953BA2F85C33CE1EA943E45FF43A48C78BE7FECBD34E338",
+ "identity_token_hmac": "D8BA9FF93E085E6929DE053FF5E297DD75B152ACB8AA9B44097331FE43BFB383",
+ "key_seed": "6249B433AD883CC6749400BAC62FD94AF309D2FAA3F0906E7AF2743B09E842F7",
+ "ldt_key": "DD7AFE6BB2C1216B81257E09E1E7C06E65A63B9C24A3AC1A5472B79CF264DB986381B58BE21BE91FCB55A40F74A563E50D65768603574E7778663528109ACEDE",
+ "plaintext": "9C0407828591BC9853079B1054D2A10C606572E71B"
+ },
+ {
+ "adv_salt": "51B7",
+ "ciphertext": "F66B47B187370914A59EE09EAEE4316E932B",
+ "hmac_key": "1B6460F0A60C325D5DE22E82EF4D002C6A323B6181CC3837B7A934CCCEA0EA53",
+ "identity_token_hmac": "F611A97D2914DAF39110CF9456CB281A384FF5C62DEA8416F45F49A464F726DB",
+ "key_seed": "777D1B46773DD5BA813A18AA35EDC68DD3D745C09FC265EB9C576B66C0C45168",
+ "ldt_key": "EFA36B82D474732A8CDA1A1388B8AF2C49CD1B1A5EBA2966BE98BCAFBF86F265CEA44C1F7AD32DB2C9DFFD58D2E7E2B377644B3DF806E180ADAAA1B98AC24247",
+ "plaintext": "B4F9CC4D7AFA0805B9AF2D196F690C1622B3"
+ },
+ {
+ "adv_salt": "75FB",
+ "ciphertext": "7778EE076A15789D61B2BBA7B70A7AD47AE2",
+ "hmac_key": "C7D207E1C26E848C1E06AA795504A9CFB7B19E1F6941924405A110AD9F600487",
+ "identity_token_hmac": "DBDF585FB25FBBF5577B43718F750D2DE0624835FB0C04D1E994DB0AE168EFE1",
+ "key_seed": "2E4D649C4150E4BBBE5257EDF4EB7D822F294B1545E636174D5FA9130166D9C9",
+ "ldt_key": "E83DFA126AA19B06E93F9DE23BF9B5E900E8179318E6D82F2C3F9A29C306DAAD280C8780DDFC28F0AD2C21D95342488771778C31FFB27D86A73CEC71928B5B66",
+ "plaintext": "CD6CC0B8FBB7A945D6CC1251C41BBF78B09A"
+ },
+ {
+ "adv_salt": "6B06",
+ "ciphertext": "5D19BEE1FEFC66260CB85107F192824DEB52BD887A5B",
+ "hmac_key": "8B4CB5A132FE3FA569ADCF4E6D3544FF87D9A3685672822A4155E4C5541C477F",
+ "identity_token_hmac": "87F4AF538B304AB7423E7C6DE66986CB0E3B0627288B12B5B6DCFE158A77102C",
+ "key_seed": "D6FA314EEA8A2BD61C0026516EE4BBE03620F11013CD17BF19BDECED48DAD396",
+ "ldt_key": "6E37C54D3A143CBE7B690F3659BEF8CAA0625960D88AF699DB29DF90C5736DA73B66D21C27862AEF984590069B4AE542156C381B864A53EC0ABAC796027568EC",
+ "plaintext": "2645CE96C6195ABECA54CBB8FE9F5EDE303E3C5CDF49"
+ },
+ {
+ "adv_salt": "858E",
+ "ciphertext": "43DFAFB88F737CD8C82C984CB63BC53B98",
+ "hmac_key": "CD7244FA9000586CA5C83A99ED4DD525A73847DA15403371C6A78467A30862E2",
+ "identity_token_hmac": "DD77C9770E7388701DEC7C9DC97B7225F19F06784F61E4E263B746EAAE9667BE",
+ "key_seed": "21AA1006D01D948D7F3878D0CF6BDA2C9FBC0CEA090147BE500062A8D1929620",
+ "ldt_key": "C39D2E1F194BA9BF4055F389AD3AF0F55366F803477CEE608DE018F0166793400EEF3F04DF9CD38AB01F39095E7F6CDE09BCF245EF38B91B29CEC130EA6277BD",
+ "plaintext": "E6978A5DF9C6EA4F57C8C0FBFC5310B6B6"
+ },
+ {
+ "adv_salt": "9D72",
+ "ciphertext": "3D546469EAF0B3CD40680CD1882A0BCA2525061690554DD3B0EE22A2",
+ "hmac_key": "93FE3B606C24EF0977399A2143DEA58BCC2804ADB51BCCE9033C3BD3B49BEF56",
+ "identity_token_hmac": "EB660374A3AC93ABB905EF49D6E0DF3AB2BDE95662A71D415B18D6D337DE76D0",
+ "key_seed": "DAF10E64CA62A68825D4FDD1610D1EA3F73DE73565F5F6A5EEF34F079FAFFF31",
+ "ldt_key": "1828E0C0EC85EAD87246E8ACB196C2D4E27F00B9B05D96942C95E3F90E423FD120BDCCA4C851BAA87D6F70B1F09C90E7C01C56499B8F7EA3EB066C8993317056",
+ "plaintext": "DC107CD0B5CA7D542327B0BFC785C41AD1F0E2EB6A4110361D276674"
+ },
+ {
+ "adv_salt": "0B4F",
+ "ciphertext": "745859D632D7B1A0BFD118D13B85B1BD",
+ "hmac_key": "6CA7661C2D4B90D3FB24F85C546A2DB1BBF013C3549B522CF6043DEBE145C771",
+ "identity_token_hmac": "0DEB10E261D6DEE81268BA4AD15E41D1FC6C4F04E73F12742400D3D2B5359C5D",
+ "key_seed": "D049B2FCD0CDD4596F93D9D7B868E88B3EEBAEF43E61A9FAF9158A6150A1EF5F",
+ "ldt_key": "B78A86927FD21E35A74BBF2CB83826D0F3C3ECC36930EC8C995597CD2EC6F1330B8D82E2F042C28B2493AB37783596F98AB85BAFCF4764201EDD9922B1E773F4",
+ "plaintext": "6FCE05ACE2E2B53392362B97920C3E12"
+ },
+ {
+ "adv_salt": "DB70",
+ "ciphertext": "9F6ABD20EBD91A3E4927662D302423DAFE74ABC3",
+ "hmac_key": "330915EAB5F5E75DC6747A893474BACAFC7F116FA2E693DEC2C7DCD6155A2FEF",
+ "identity_token_hmac": "D674C7AC837A05191E705C9ABF59C9456F8BE9B1A6B67910D5469ABE61403905",
+ "key_seed": "0961CBDD12A7B644E7B9E702271E4BA6017F429A6DCA110FF326CAC98B37AD5D",
+ "ldt_key": "7CFD66C5CA07AC6A4D530CA801DCA0338448322A3BC5A2B56BC028C0F31E5BFA5D8098DF92F6062214CC8A4E421F873B1388F26F4A7F8D97123FA9530A8F9B32",
+ "plaintext": "479F535BD5B82ABB82E5F014CF3865BE9453DF17"
+ },
+ {
+ "adv_salt": "F62F",
+ "ciphertext": "2E39B8DE8CEA7523627609C0A76C1CCD3E2122F82ACB2E7852",
+ "hmac_key": "04322B90B4ED3D3621EBEC8E27E4683A67BA2C82041403D26035E310A32F9278",
+ "identity_token_hmac": "AAB5BAD093219054629BB37AA41D83E34E4445CD4057D056858DBF8EB4397034",
+ "key_seed": "9B3A74F8DB6BCA0BD09AFFFE06DD78211AE9DF8F11A9F3A3417B39C2D01E4AE6",
+ "ldt_key": "1CAF350FD51CBE30E00A92B2198A17906F0AF4D45236595A5C54903C666744DC4DCF78FF098677898659E5987B35E6C573C3DE83750C29EC69853C3E4C353177",
+ "plaintext": "9D51CE24875ABC6F43E164ECE4679180826009C2D183A261AC"
+ },
+ {
+ "adv_salt": "1DF7",
+ "ciphertext": "A5B4B307838B1B761B52ACDD98AF4D8867DDEB43BC3A569D",
+ "hmac_key": "6EAD3FD46FF8E8FD4ADFA97D709120A07496FD0D84142C956EC9ACA2E35D7F0B",
+ "identity_token_hmac": "C5945044702D6DCE67A45EA35FA28C217C80A952C8A5F080F945F9B5E98C6394",
+ "key_seed": "CD657B540A64750A595AA0F644B5876CB07BC81137CD11CA44484CE5183F1993",
+ "ldt_key": "779E316C081F91AAD914EBB6562A7DAFC2A9B4193D92B4888BB72925FBC5D31DC279AC22E56575AF1F77DC55513EA0A0A02F248258A0799A1C7E9FBFF4A8F9E3",
+ "plaintext": "067C8183FB8641294C5BD71D2CC9384B27448DAA7ABDCA51"
+ },
+ {
+ "adv_salt": "C04A",
+ "ciphertext": "FAE99D33CA11035E83B25BD44716745DC09E9B93",
+ "hmac_key": "152204070190AC7162FE20CE7F87B93854B7B3619E424A3FBA00362444CBCE09",
+ "identity_token_hmac": "941D8591674C49951D466350D2693FC2B3676EBB7D7B571592C4A0348084F6A4",
+ "key_seed": "CC962B750300AF9F8E3A0815A2CC2D9382B91C4DACE92F84E0E90B5910A205DB",
+ "ldt_key": "AC57494B5908F709C98B61947D619007CC5A27E8F195897BBB6A9B3BF446FB36732FDD80C6D3C7C7462AED8D6E8C2E0D3B24A0F3C8A3D4317FC26E56FC446E6F",
+ "plaintext": "CC2CB221F08C8264834D8828F2C38F8CD138742E"
+ },
+ {
+ "adv_salt": "DDC9",
+ "ciphertext": "768AAEEB82FADA42AAAC879A4A3F64DA",
+ "hmac_key": "E5B3B593A79805E7D13F67FD2DFE1C3F370C4DF341522BC15122C66A457EF9A8",
+ "identity_token_hmac": "0EFDE1DC85702380F1E80C31C0CB20CC1A84ABDA047984E0BCFB85457A913540",
+ "key_seed": "E5C94807F0EE9585721AB18CF7202726A9988C27B18B4BC3B8965B65425D1EC1",
+ "ldt_key": "860D05C7AE3D48EE932CC244F644579259E3B8A5876919A62AE0AC64BAEC10A1F3FF69031077DE256D611D210F39DF21D5354A92020C67ECA7AA107157582897",
+ "plaintext": "84912B83445F4F172AB424DC4B5866CA"
+ },
+ {
+ "adv_salt": "F1E9",
+ "ciphertext": "2EA0800CCAB683820FA2B6374C9A85F2B4F796F5C05E4E880F6A",
+ "hmac_key": "801BB36813FB520F44EAA47BB377F90F923E32C5FFCB86F0C05D377CB8BABBFF",
+ "identity_token_hmac": "FF06F63BA8B586C7CBA78803F3EDFC37961E6340D1CE30833593F7BB4993FCE5",
+ "key_seed": "C89DF8AE8A40E7D121F11725EDED654E9F148002061645DCC338E2A096F77309",
+ "ldt_key": "690F37B0BF9C0EDF8152BF5F604EF5E4B8A2158C78E8AE1A514C217D09334BF2566E50A786C8DBFB5CE89C6A831BF2BF3590EB227742D92DA64CD7E048A4ADC6",
+ "plaintext": "D501664DB8049B24C9361ED89794C035478F38D16F80E8A2DA98"
+ },
+ {
+ "adv_salt": "9E18",
+ "ciphertext": "46161EADA1410BA034B67EB8706239ABB492802FDF8577CE9C2750A1DFB126",
+ "hmac_key": "EC60B45E22554C987304C8B8BAF5840B29031D9E3DA18A8930162EA90B5B09DC",
+ "identity_token_hmac": "57CB29DC2EF23C376C0C0AAD8BDC33502D595BFB4185DBC714ACCF86837B306A",
+ "key_seed": "ADEFF11EB08514AF099F3C8D3D87C19FDD13B0FA6056BE585555BEC6A15E3AF2",
+ "ldt_key": "5E4D969FE686B8E1BD8DCA17542F636E8A990165943637AE48C50C65B7164DC66A0CDFEF83B14D63410D46D6F4F05BBB87C9225A5B90123A4C7BB0BCB309ED2B",
+ "plaintext": "F203ADF87EBE1B2ADD0A2F234F016BBE73B6E52D93D7E2DBEFF4F7A2F3854A"
+ },
+ {
+ "adv_salt": "D1BE",
+ "ciphertext": "F589135CBA5632A5FC722D7867B5830DC84E089085",
+ "hmac_key": "F618404EC6BF2914E16F892EBF50FECD660AB380AE7BCD791BE086C0DE8C1F73",
+ "identity_token_hmac": "B096CA6E7A55E87F1843B730E8BA39D849E8398D4D91F21BB61D349EA0B80CDF",
+ "key_seed": "2CA0C6DEA290320E9A19899BC25E7E04E7FEBACB862D092D703246DF905DE6AC",
+ "ldt_key": "5CB0D8CD3D5519B9633E59DAE23B9FCF9D118A771051D5A0DC7048D7F178011050606687E211DEA1DFF2E204FD79E4A177963CCD8304EFE8F2CDA6C59E9B5E7D",
+ "plaintext": "B6BFEDE720032795891C4487A1FAECDEAB3456A650"
+ },
+ {
+ "adv_salt": "3FD9",
+ "ciphertext": "A0379898ADC0643A4803D19A8494F80452",
+ "hmac_key": "4E94A209650C7C46D8305F07B0BF0678D742B091AB2CC47B241483D2E161CD32",
+ "identity_token_hmac": "EA7E5643E1CEC8DCAB7CFAF7ECE09AB1790A3BED6B872CB7C7BADA3E181D60BC",
+ "key_seed": "4CEAB4B692FB0C1BB435FBA247C7171C1D18E60D5C8FCFD364A8016741DA64AD",
+ "ldt_key": "B4B8D87D8B72502EFDB340C8E090883751F48D855D0D41C74175C4B4F460ADE3F5A8DFD73431C78EB58B6E20203911B37450CC8CF8D759F3838D2676C7283835",
+ "plaintext": "5A02766D11BCE1529A159CD54BBED5EFF1"
+ },
+ {
+ "adv_salt": "D284",
+ "ciphertext": "59F8F5A7062564B2D2A76EF50896F901F64490FB4344",
+ "hmac_key": "8E821028E468700B4EAE999D7587758390881E984733B63F4266B09A79789981",
+ "identity_token_hmac": "77B6A66877A1F5F0B8D67CBF5149768D7D436215ED29C995927A0C72F7E59E00",
+ "key_seed": "CC127D438633974D6089E0070302248F4771920B69284BDDC10EB5EFC869AB65",
+ "ldt_key": "EA0932C453E066100CB5870FA19549ACC4470B59493DA3260AD7EA9992130B690FE7D178742D4D526EDC9126DB59E20905241DC065390E73FBF73FB35627FA3C",
+ "plaintext": "78AD3E63BF9931E2F0F0024D8E2581EC42E31D02E81C"
+ },
+ {
+ "adv_salt": "CCE2",
+ "ciphertext": "5721107BF13FCD455C7B1709A01F9117D1866BDC71AC996BF5F4E4",
+ "hmac_key": "217E8FB03E291C886BA12807F04BF334FCE42A0CE97BE91EE2E804B8154F179F",
+ "identity_token_hmac": "7FF0C58C0820FD3E27D06407B5EA6A2295FE6E6F3ABDF2216B46B12527EEE853",
+ "key_seed": "3E3E9F0D4675C1486C207E8F887189244DB317A7A5CB5200038BCA439DBEB43E",
+ "ldt_key": "EF24EA00E39981DE418DF10A9A51D01C24764ADC50DDA5DC90839B0553AF291C3FECFA46B2E9E65E0CF10754C59D10C230C2432F96572CDCBE8D061BBCD33F23",
+ "plaintext": "193A16F2383DE9F25BB8A9CB1113F5E52CA38DB8F6C3CD45025D05"
+ },
+ {
+ "adv_salt": "1BCB",
+ "ciphertext": "37C9179727A7C1E836A404C48A747DBD75B58A1D23EFCE204D5F50",
+ "hmac_key": "8F2F4BE5B3169271086E83C71E9B9348ACD2912565174BBDB1262A7840F3E32A",
+ "identity_token_hmac": "2C386D3797A9EF6E15F6D90A7A5182C45ED100A6E8920AF8823B25C022FD6C0F",
+ "key_seed": "C81AF9A3D6CB7150C1E8008737E5ED33F6F088BDCA4F6A6AE7E6B563CA23725D",
+ "ldt_key": "CF078C229178D3DD9BF48F51DE27B2D1432250CB1B0F67F5D2ADBECB2BA5743B017705ADA1B6CDE56CDEEE13A7461FB9A47955444F1992FA2E0D4886F21927D7",
+ "plaintext": "1D8CC80CC19E18DDB69FFD214F36869A5B78EB94B027ABCC5104B2"
+ },
+ {
+ "adv_salt": "C63C",
+ "ciphertext": "0F6D4AA3A9D4749A9BCF40B1505EB05776",
+ "hmac_key": "10582CC54F02A033EAA5FC4C1A6247EE563A74D80EC6C476E026CB4F2D17956F",
+ "identity_token_hmac": "B5C7278B84491072B0A1BB498A2E0D16F9236693B481A71DB14D7E79C2B3ED65",
+ "key_seed": "3ECF1FC2E62DB5EDE18A4AE95C634824A9E6E81E750AB74696D102546E9BBBF6",
+ "ldt_key": "B33996937E2E37A41407C8ECFF867D3CE49057412D968E513BEE72602616D70D04B9A10760CA5B104D2887FD24E92C925160529C985D2DE000B9A437EB2C6322",
+ "plaintext": "D11094AD21CF9E7D6B40737BFE75D3FB57"
+ },
+ {
+ "adv_salt": "93B5",
+ "ciphertext": "34B5B9320E5AB45ED9D317B281D5C506DC3377BD4F5E6579B71A4F",
+ "hmac_key": "B78802ADE1C1E235840299682F4A887AABE8C0C7CE302E97C09E43D3A4E63C42",
+ "identity_token_hmac": "FE0762AFB535721F478633F45AA82B45C8548F57EC506D3E7FC99B3987310ABE",
+ "key_seed": "4E4307B12B7D4AE374B141DA13BC0244F405590441087FBC4E4CB601BC8782C2",
+ "ldt_key": "9385F28378E997B357479AB99B537A917F4D7C8C035093E217498284F69BB904ABC851B91EE639134BED28EAA649C42234101B86380F195457AF14F758CCA0EA",
+ "plaintext": "C762C9CCA95E9058C382EAC3F85AEFCAF9577C2DB3B179B203499E"
+ },
+ {
+ "adv_salt": "6D7D",
+ "ciphertext": "A811F10BA24142D7655D84A4CCDFEECF3B0773EF9D68156BC4BD4D77A30B",
+ "hmac_key": "11651BC94CBD0EB53B3B6A1797BECFBDE748A53174416F85E68C5501E4D7EE40",
+ "identity_token_hmac": "8E35E56A14AE67F069C07ACF655233CCE20EF2E475A9ED06EADA6FD2283BD2FE",
+ "key_seed": "48DA18F6C4A2E8FE8FD65595EE6EE30150F88DF47E6E5533D15235B529A02B40",
+ "ldt_key": "7D030CF23298B907E6C330364F7B758C7A875B400FE712F01AF511483AFB07DB068BFE744E17914360041F451AD9416B046D784A79BC4427C1CBBD7416F8F6CC",
+ "plaintext": "464436B39F78BE4FC6F322354DCBC1899F26292243F624814D9F3DE898F1"
+ },
+ {
+ "adv_salt": "8E8D",
+ "ciphertext": "04EEE502D4F5AA60B94E0EBCDA1290264CEF1649BF30DF53A8",
+ "hmac_key": "318D9B3647011FCB71D9CF4BC713637895E073207CFFF196A3E6D770C9B6219B",
+ "identity_token_hmac": "B173B54D70C518BBB2A4C5A2A7334F2982577822AB1E2D487C365822BCD2A83A",
+ "key_seed": "A921F57C7C59EE2F89BF1F0EE7EEC865590A36BAB2DD2EFE3B3AC65A4354145A",
+ "ldt_key": "7B3BA48E4648C073143D02617CAD45493A55B77573662AEFFDAF23420180BBDFE152E8F954A9D43D85D3B3F1D0F35908AEF63832F1B1AFFEE991E4E4940761B1",
+ "plaintext": "D8E9CD99AA75B35F474AC5BE6D6ED95795D12C5AE8518D62F1"
+ },
+ {
+ "adv_salt": "C3E0",
+ "ciphertext": "24D350D1D9D2BC6AD3DDA958B3E7FD2F5821C858C5EFB70592",
+ "hmac_key": "E243DE29568404760BE59D1836D791ED8A0C78C7CAF4ECD49EE9AFF65BBE5076",
+ "identity_token_hmac": "E050BDFF46A32F0299A083563206F04F41ED6D9E4A8489F18A73E4209B41ECDD",
+ "key_seed": "9EBCBF72866BA9B742577C57F73FFFDC3CDEF13FB54257B36D95CCA1684FB626",
+ "ldt_key": "2CD45198DC0E1036046E67B0EE1F3899BDC2309ABF334F77564C7590066FF1D6833D9ADEF5037ED5ED0B6B595720159A81E33494846B2CC23E2E5F1BAFC7D87D",
+ "plaintext": "3E082216CB59F558991B00747C27BCAE6139C37BE41AD6A8E9"
+ },
+ {
+ "adv_salt": "CEEF",
+ "ciphertext": "59B25F6C47627DA4090B53063D5575442F06A08DE58EAB64D68BF8FAECA7",
+ "hmac_key": "C4DE203603F16FB3FEDD229456CB7A60E417D00A169DF9285A508B548BACA491",
+ "identity_token_hmac": "A23559801DF147E623EC67E779ECB673E84892D6EEB2678438BCF34A0457F675",
+ "key_seed": "2591BF35AD9148C46AE34848FD205F6EC1BBDF2B75BCD9F6E2604EE945CB8D23",
+ "ldt_key": "154130784C121CE60A793A0EFA716E469D58A70B5D8656054DEC2D55A145FFE990D454DBBC0FA2BEAAB2F340F2C7F7BA2877F8E742FDA6AA2E8F3D8FA5A4FFC9",
+ "plaintext": "7F9C2C7BC22D8B9E0C60B2368F36BA901CAE0DF7BAE687C5E0F92AE9865C"
+ },
+ {
+ "adv_salt": "7E2B",
+ "ciphertext": "1688E19A95742C16497585EB5E1BF8E729",
+ "hmac_key": "E7EF33D0CC8CEFD9926308D187A6613F8A9F1CE207CAFEC51F327407D5398438",
+ "identity_token_hmac": "59C9BBFDE59DB9CB354A905DB22215E25B747EC69CE22F9B76CA8F27C2297E8D",
+ "key_seed": "92343E22B489FA1C9ABC0BA72ECDC7D9A0398C02D4FD57734BE451C0A2F124E0",
+ "ldt_key": "0DE6ED726ACE044F30F18455137E7FB059C9EB0C573376FB0A3191D1699C747414EDE680A061AB213C3877EA9CABE725D6FEDB3DC7B56BAAA386471467E7CD6B",
+ "plaintext": "CCC3A15107F749514AA4EE7F2DC19AD77C"
+ },
+ {
+ "adv_salt": "1FC5",
+ "ciphertext": "CD7E0E0FF578E0E80BDB0FEED0C5491A12C346A27380D642BBC13CC6",
+ "hmac_key": "1288291EC7FBE104F8EC09DC9A78E1A47A8B362AC9A5377FE85B3D9EC50F68EC",
+ "identity_token_hmac": "6BB5AEA5ED0C1F4B56470F9D6629BBD29A23B6A601765CC004639A6A5E8BA626",
+ "key_seed": "14E59B92D58461D1093A92B936326986D141F71DAE9DBEC2B3BC4508345D2976",
+ "ldt_key": "6B76182617C20677B7A2F132F6F2FE3FA0166D7BD46D2DCC75645F95014EE9E1E0A553BE54D654E40A95FD2C56503487E7E163A2F58E996EC585CEEDCC3C47D0",
+ "plaintext": "9B1143A836ED3758A3D16D7B11621BBBE28A42ECF87F325550DE8192"
+ },
+ {
+ "adv_salt": "2D53",
+ "ciphertext": "EF83ABA138A689555458B97DB59EA003BB",
+ "hmac_key": "16248A307CDC2A250B424BF36988B0B6366EB803ACCE340AE88B07903183B401",
+ "identity_token_hmac": "64C0A74AE467B4603FD291FE6B32B49D8DC36457668015700EB89BC987095BC3",
+ "key_seed": "335FB592EFB2916D06EEB949514C40E4407490506AC269ECC30F66F70DEFA836",
+ "ldt_key": "A282B486080966A74C664BF30CE063B511A8F4FCA7DFC39D81C5BD314141705FBCC539418CA0CD6B5C5781D52CBFD4C1A722D1D00CA06F55EB85C16B7F631CAF",
+ "plaintext": "DEB6E4513B1B0CF9BA4A98D379A8E13403"
+ },
+ {
+ "adv_salt": "8ECE",
+ "ciphertext": "443127411C98DF4DA8A06D675255D709508C854ED3AC3C6CA0847DD054",
+ "hmac_key": "6E8C7E7E1CBE3CB0917F0DD7041B80C1ECAE2DB5A1EFDAC720830B4765F8F719",
+ "identity_token_hmac": "61644E0BFF22A073B2B04529CA04C34535B85E1D426FBBFF574FE28628D9EA31",
+ "key_seed": "40FC5113E1557A72F698E3AC3EF051FC3AEC386233954D61C936FD3B66882422",
+ "ldt_key": "775686C9C7FC526CED20B718E8675697776199E2371A558DE33E3E78C53CB734A2E933C02C41F8826DEEED9769EE7E558A780CDACE276D40BF067BF1000AFE80",
+ "plaintext": "6CDF43EAAAB305E79BBE1AD6FD7BD70A630E9CE50591D86A22456FB556"
+ },
+ {
+ "adv_salt": "9D91",
+ "ciphertext": "170FE1A9E44F0467B74F1A40C3B7DB88B0AC12490B5E1E",
+ "hmac_key": "F32663EB2FCE17B3C25297D9984AFCDD13316E7674E140818009F46F029C9513",
+ "identity_token_hmac": "6868CAE353ACE437F0217688CFFC414E64030D7C867D1D1E7A047D2B356A02A5",
+ "key_seed": "74958FA7D2A63FCB32DD38BD6CC4247DA571817FDC2D259DDF4044B7818E9B3E",
+ "ldt_key": "615CD06A1E653207B0132535C85839525E479E67E3438D8A3A8B8739F41D5FAE773429F1B70899136C3614F9E53E3ED0266B03A2F8C2E060B76B3AD8384E9B83",
+ "plaintext": "013B4F0CDCD662C220CF77C3EAED783048FFBA61D5E1B0"
+ },
+ {
+ "adv_salt": "73A6",
+ "ciphertext": "53911B8E6FA54286BA4DBEE7E103F4B73D10C873AF7EF3267F",
+ "hmac_key": "9245A0A189CFF97F3716521EC06C7B5EC28ACF1D175CF584577FC31677033C55",
+ "identity_token_hmac": "DF63054ABB719ADA13BF2FE69F0224962CAF30A444138646A14CC1B6274C038C",
+ "key_seed": "2CF63DF744353224F434313B0468607C5CCABA9C26C8258F0AF5D3FB4A3C4693",
+ "ldt_key": "2F762E3AEB80C1106D7774B3D0C211B302972CD0A4BF7D9C988D537436F2400C264702F0A630D1E69EF470A5B7094566F82D876412FA64139F0ABBF0CF9D1596",
+ "plaintext": "0D309F7E410220E23520E6BF1A33CD6C1AD4ED1CEF645339FD"
+ },
+ {
+ "adv_salt": "E85E",
+ "ciphertext": "BC1027E1A064D40A93DDFD479B7660AEE059519A8A173319D356B8E6436EBE",
+ "hmac_key": "78AE4E730FD438D605FD3EC3404C4C80BE1D406A0E61CB50987D90CCE12473D3",
+ "identity_token_hmac": "0D6DB7E94AF7A07B4EA5ECEDE6CCA60D49BF612C3B109EA0AAF5E7CF888813B5",
+ "key_seed": "121F2970696FC34F1BF2518216A6440D18EB8E3BC8618350E112CA0B30859022",
+ "ldt_key": "888E59808FC618FD9A4F7E625953B25AE6372B526F65870AA04C0677BEB554EB32317057612DF6B344861C3006989237870C5778FBE834DB73E3B30AB8A0BFF5",
+ "plaintext": "0D41C7319A3282F415077C042913C0A790D7116E74A94B267BF37F2F7617F2"
+ },
+ {
+ "adv_salt": "F380",
+ "ciphertext": "C01C4C4CC32F8211804EC1F30D8D4675CD39366E908A6DDF7C44FEBE",
+ "hmac_key": "ED79226508FC7349E3672C89302BACDF6523BB1EC1D91D978FFDF7218FBDBA6A",
+ "identity_token_hmac": "F1EC22047C3EC3185DA15CC5FA206103DC0E97F90D31D5F4D85DF66B20739402",
+ "key_seed": "A090D3D433D62BE1AB26AEB4613C96F44079A2BACE83E5E98028D7A3BC6F463A",
+ "ldt_key": "F882A283703F9B5F4A6F5CB7713B2E65220AF2A37711145546AFFBFB3054C31F520838544B4E5411DBDAE1BFE2C8452E73B954DA1EB1EA931EB0752155732AC7",
+ "plaintext": "A0D92E271704EBD8CE417F16ED748C52A32CF2F0D6BAC91710E3D32B"
+ },
+ {
+ "adv_salt": "00D1",
+ "ciphertext": "52025755D177839E5AFD6875F692FBB4F228BE5BC3583249390050E95EEF3C",
+ "hmac_key": "148D8C9025A23C28642569A13F70B90C8B4619F1D37B35610A73D7DD2002AF51",
+ "identity_token_hmac": "9E1144CC5EC70D0B8243E106516B277E53B5B75D2F82B7CF573F79202FACE05B",
+ "key_seed": "B00E867E23E7B5A4CE44967F173961C584D481506AB467A3A47589280D06F719",
+ "ldt_key": "BE576CD183CD359A2AAB6A3FB1D000BD1002FA7EF62BA2C68EFE5DC97A37C2B646EC64B21B5D17AC9AF991C8F4846DEF855D6D8ADDF344D112FC0308E1088F22",
+ "plaintext": "852403CEC6446A618E60EC5E46A4CDFC960B8D8332C75A403F680584E7F19C"
+ },
+ {
+ "adv_salt": "54F8",
+ "ciphertext": "AC2CD5D1A00D5BE2276FCD1D8B3DB3BA82E444E3C34550978EA861631EC8",
+ "hmac_key": "77AE3C0342EDD44559E430C72482E130DD5D71E6ECC981BDF08DB87511FA3605",
+ "identity_token_hmac": "A107BAB5AECB87954FAD5577CF3E081F6D7F6AAB482D1AA6DFE094746C046255",
+ "key_seed": "9775916C644EA12143896868986CF1E4B8B7DD4F2C95B322DFAD7B216CB23669",
+ "ldt_key": "888A01B8B67964BF529D506D66284D5D919403F5CE7705DB946253AC7F18716C74B0E0F15ECD96D0D60A2A6072798D0B347A7849C1137C24207C2BF9CF7966FE",
+ "plaintext": "62668FC2E5A380858863046818C061D30A1DDC3B29E7F1FFEDEC12DBD344"
+ },
+ {
+ "adv_salt": "AA38",
+ "ciphertext": "9E5962AFFA94C9143502358EA34B3E39FF5E4C9F7FBF57BB3206E2CFF635",
+ "hmac_key": "8E04FB092D8FA08D3E2BF791641C65E452A4B61C61ACEA5327E68F090229A015",
+ "identity_token_hmac": "224B6C4818E51AA638CCAC259B37F17957FA582E7992CAB661890E20C261B8B9",
+ "key_seed": "6CFF000FDC2F09BC79802265252E8800F974CC60421BBFF68F2089CAEBF01CD8",
+ "ldt_key": "3E3688B8589F59D7196CEA6EDC0193828B4E0B0D588675739A2775891BED869972F3596A72A97DF684B424A41FDE41C496D99EE49111F86A2847D5234441289C",
+ "plaintext": "51D1D11F873CDF7815FCE20010254FA8998ABE1525848EDD477CE2B5E2A8"
+ },
+ {
+ "adv_salt": "B1F3",
+ "ciphertext": "FE4366AEE6DF5F7D28BF0667085557D7CC4EA6E307A6C3295DA1AA1A56",
+ "hmac_key": "D3BD9864B5D175ECE39D123D43F0FBB781F637891A048FE8F6D6F2D44BF2DCC3",
+ "identity_token_hmac": "25CA8316EBD6A264FA762F72AFFB221FFA7F65F8330C12A3787233907D956D18",
+ "key_seed": "5814F434D390EA83722FA8F0D7BD91F65090BF6DFCFD42C28E4DCAEE4F095B98",
+ "ldt_key": "04AAD7F99CB9CA6A1A8246EFB82C3183BBE4B225D7C95D52403C82F4A819805D41ED1DAF64927ED74F63AA3A4DA3E2BF6B4D0F04E64CA51CEE24415AA512399A",
+ "plaintext": "8F3A30C6EFDE14B9367EDFD4166756D08226C64A78F7495CF001392510"
+ },
+ {
+ "adv_salt": "5DBB",
+ "ciphertext": "D24534D81CF934D117CF8A227B974C4A8670CC0794D7786F77D4",
+ "hmac_key": "AF4DA47793A376C768CEB102145C644670AE13566778327953E8B7965B26DC43",
+ "identity_token_hmac": "E359B6A3EEF1E0C5A5EC1E7B6D3362FD31F12AC9C43E717198CEB14F092A0ADB",
+ "key_seed": "484F18C39DF6592153C8A653BD398D961108A717A0AB2CC282813C6FD258C0B8",
+ "ldt_key": "FA78F41F44E5AF7861C11D23E563B91FC32370A0E3D40BFDF07495E9519EDEFFCAAC939D1F5C3B554265553307666CE02FBC31D31F29FDD3632BB24F39545F54",
+ "plaintext": "5F0D1829F7DE91792483F92AA7ED87012A64FC38D41F4D4461F5"
+ },
+ {
+ "adv_salt": "33A3",
+ "ciphertext": "F492673ECCC90ED523086900A06AB897FD03C0CB8BF74CFBF5FD07",
+ "hmac_key": "78E1D683B105EB15A33B7AD6C2DC0695C7848FE72A0BB1993988034823F63C7E",
+ "identity_token_hmac": "3F1FA207DEACA96FDB08E1619653117B42922CBAA1088CAF8225B248875774E2",
+ "key_seed": "632642AF207B26D998D5605BFD4FC57804270E76AFC0813B101AE5E25A8F06D5",
+ "ldt_key": "6C447AB95DDB5972EAFBC4E697BBA41D9B8F3393F4FCFD8AD83FCFAE4F719BEF694C1588300C2653C665B62BB6523CB333809643530A758A7731771A9E39D751",
+ "plaintext": "4FB623482FDF7DFADDA9F32F0ABB75DEDC8F516639934A414C23B1"
+ },
+ {
+ "adv_salt": "4D1D",
+ "ciphertext": "DEF23BF8CE6D352C03F684873197F1E126EF",
+ "hmac_key": "25669AAEBADA492252B93E6D7E94D75312D3B78B28D3A42B5A170F1532F91498",
+ "identity_token_hmac": "C4B1D109778B6E1C0069B0268E640D44F190AFE69E6E1C38940F05B24B5A705E",
+ "key_seed": "35344CFB928DD670C8F9B554CAFA56B71E898EEE153B7960D62444999D4F8EC7",
+ "ldt_key": "4DB7CD0D9F6E7E9B0985432CF28B73C6C04993B55816F6631F5E6B1EE8E0E25B653BEFB1C72F19B409972D02076DBE50138616ABCF243B55503BAFD17B1354CB",
+ "plaintext": "56F164E945994FD2F9FF17FB9A37D2CF848D"
+ },
+ {
+ "adv_salt": "171A",
+ "ciphertext": "62E2114BC26661BA79826CF62A546D1510020961EFFB600FB183DA4464",
+ "hmac_key": "01288B1D7E7F8EB6FEAC69FD20BB11AB56D345BCF0AE49A674170946A708FFE4",
+ "identity_token_hmac": "69F504A58777284025B9E33C2CE8585958A1E21763624D3026D4C6EEBB6F2157",
+ "key_seed": "6C0304E547553359B89861721D451170273DB250EC89F0386750F8AB208C4F7A",
+ "ldt_key": "8960E2FC42E9F317C808DF38E0B971944F5F1E971A77999120FFB125E6F78A046018AD83467760FE0FA2D770259D54663845BDDFF24E846969BC0ACEC57C8552",
+ "plaintext": "3B0C65B9D02FF4DD90DB2099A0A0CF10DC35A2E7C1DE8A281D15A1AAD6"
+ },
+ {
+ "adv_salt": "D96E",
+ "ciphertext": "289873B493AE26B051E1BA5C9630C03B",
+ "hmac_key": "7F34069F1E02C5863E59B49AE7A09A740FD9EF2130FE241930853C6638F6EA5C",
+ "identity_token_hmac": "4EE58E92ACD3792F79BAED54D9DCB9AEC99C8155666FA18BF47104C5205E4FBD",
+ "key_seed": "68E0BA10E0C3A18E5D61EE0370F54593E0288CDDF65C6C8057300CAD29B090B7",
+ "ldt_key": "441C58203B54555CF21A8AC286512FE9FD850074DE73056687B0C84F54891F2F51BB71595DCEC31BB425C760D62114706423EB5522B6938D1C26CD078C9E4958",
+ "plaintext": "F023B0469092095BF11BE2C8A3D1F538"
+ },
+ {
+ "adv_salt": "387F",
+ "ciphertext": "121B881D86C73C55C54B58ADF7C74888AD718266BDA183",
+ "hmac_key": "F52485E359F8C8AE2A9A2367E83F4DF59B3F9671371995CADA1FB7D676ED9ED1",
+ "identity_token_hmac": "38622556DA5CDA145459709B8A2EA758E36C4E7259ED1CC23EA3F16BAC9B3942",
+ "key_seed": "AB297422AE12CB88D6B1626645362D6A648B602421B1F50E9C5726F3524E5443",
+ "ldt_key": "B41F670F935CB3779A0D6A10E1CBFDD2262402DDA4EB4AE875F49D685BA4F78B3558D08F2A918E93758F1452ACAE11B091C11B0E43541BC631E2B640F6145B7C",
+ "plaintext": "F11D62D12CBB4AE6584A56A3C1DE1ECD6618AF34C198F8"
+ },
+ {
+ "adv_salt": "1577",
+ "ciphertext": "BDC6A5298AAAB19D43FDDEA801F547CF2BD10F55FAD4E7A9627D43E9D2CE",
+ "hmac_key": "6422A087D0436BE49D14DBB2669135E591FD7ED3546E94B1656B72FE993EC6D0",
+ "identity_token_hmac": "79FB70FA422A1E985FEAA92800389DC7011B114BFD2CFBAE02AFCF0869EBCDAA",
+ "key_seed": "A9AD292C8B18B7C15EF3FF48C0B96C7DDD41035ECC8CA2FA6E693DD26B9FF0B9",
+ "ldt_key": "4EDC9FCFCA44CBE5FA9F4FD05076E268C2B6B995FDEA5614CDD788830276E8A44AA2FC4CD016500324CCDA2A360721C6228938461164A38E7F2B5D3BD93C3640",
+ "plaintext": "6ADEB26B7E31EBFF8AA3033E03F4D51F2DF26AB6DCE786F4F36B92466070"
+ },
+ {
+ "adv_salt": "651E",
+ "ciphertext": "C6E7BF11F4C60727F4ED2FBFBF6D0F2FD862",
+ "hmac_key": "21FF3858D29A9CF38E86C40AAF83B5BD0A60B317906B4E3F4FFC2EAA718890EB",
+ "identity_token_hmac": "AE6CC49ACDA2014A5134AF8D3E318243EF342317E7B341D00AEC6839F31742D4",
+ "key_seed": "B4A98978D3F552C9A81DB5BEAFF274F596ACAF4E4A6612E81A064DEE39CE4F16",
+ "ldt_key": "A82FD91507080BC8F2FC5B4C3C2088752FACA99047CDC4A1776ECD1E461E28012398058C220DFA667507060C5D71ECD840F9DFC44E5DAFDBB499571EAC48DA9D",
+ "plaintext": "0E1AE48BF75A15436F226724B006968A2B6C"
+ },
+ {
+ "adv_salt": "63B3",
+ "ciphertext": "E274427BBA4C12E4FF1E03193096450E8F8849A6CBDCE3",
+ "hmac_key": "72E8C574A8402765B5220C5FD95292DD3C7230DCD6E78EB5171FDF68FB6B2410",
+ "identity_token_hmac": "735F48DAAD03872E8E2C9873F29DEABF03BB0E174F62F679CD10F5BD021E816C",
+ "key_seed": "93291E25813E14BC2A72616946D7A5EF03BA8292016307ADA7D5533672D25C42",
+ "ldt_key": "D5FC26F6C1B3363578EB84386B06169CFCD2800582F8E3089DEFF90F04C39C92F2FC98DCBFE9E696AFFD308FB0D7D60B0A5CF2A4CCEE7748F9B4BD3D5288A1AC",
+ "plaintext": "9D799C298ECC149A0FBD23D0B5D7532872748782B8417E"
},
{
- "key_seed": "7673D9F05DB9AEA7C7C794A24AEF8275384CECB1149B24B9150F56FAF35E3738",
- "ldt_key": "BC059EC24647A31ABA5FA99A6254868E422D26478F5D5D3BE65802D04353ECD1FF8FE74F36F7CB58FFC2DE87CEF1739E6EF6D64B3BB592F49BEEE2EBDE83F673",
- "hmac_key": "B78D559004B09975C2F52F5CACD5D4531A24AADE730E1B37E01BF8DD7D5AFA92",
- "adv_salt": "E578",
- "plaintext": "4306ECBADD6023CAA503600AC716EBDFC97EC8333D1CDC1FF91A76",
- "ciphertext": "877672F5A7AE17B57DADC197A8EC2D20F7BF14472AE73E8842A0C1",
- "metadata_key_hmac": "62DE26DA7D947434D0C371205398FB2A1B960B34AE226ED73AA118AD7016AF73"
- },
- {
- "key_seed": "A07E28586F397D9C8D2EBF5E8236647FDB887D15772BC7E3C0C85FC7754F5C4D",
- "ldt_key": "EBB039B779FF16AC0AF67D799B882107A694F689F19CB85E1C847CA34A58344A3581D059BDB0F0A7A0C34D19539E45215F4CBAE183B9047B34A347CBD3017F1F",
- "hmac_key": "AE83401E6174D5F087EFDB1E0FBB7D77808BE24CD708F3180036BBA298C76268",
- "adv_salt": "4D27",
- "plaintext": "EF34E725EDA3C6069C9B63C5E8000C3ACA9A027E",
- "ciphertext": "33466B24B8137296608257C97EC181F1EB574F04",
- "metadata_key_hmac": "5EA6CB73502B1419F1BC85D04E73EC72889635F972C8C221FDB0F0EC1CAF09CF"
- },
- {
- "key_seed": "71F35AB829BB1E2F7BDA59A65BE55741F7FC87BBDE81D6B10D85CB6557DC47AC",
- "ldt_key": "5960D8FED51947B2ED92B3F268DB6641A508629E747923B91F67C3F8426895ACAD3800AAA2F72D4EA3D26D1C620D2D8EFDAFAD7CAB0516F0DE82D1C8E5C0826A",
- "hmac_key": "3E14DEF966F921D933E3625A8C11AC4544D5A8A7882F53C67BAF9243DD1F7B2F",
- "adv_salt": "4330",
- "plaintext": "F46197691BD5D241DEC41D8CE7B4B58A932446DCD3",
- "ciphertext": "57642D5ACAFCA0DAD6B1DF1BEDBF11D3282CD1B822",
- "metadata_key_hmac": "ACB7C8AE37F526CD581783E63043A48FF823B094D0AA5E6311FEBFC4D8F57CC2"
- },
- {
- "key_seed": "8A5DD2068ADD99ABF9FF0020A1728AAA51DE020711BC6825D034764CD622E0DA",
- "ldt_key": "2698F62A3F4AC3CC2A47E779BB9C11C1C56ED1C47B2BDC3DC4A1607B91C02472D2BDEE84359CB7E8DF1539CBF87772374E4DA14B2D860FCD581780CB5E86E410",
- "hmac_key": "350C4F03B87A73C299D4875776CDAAFA4BD62BF0FF671A8DEB624844B413B1EA",
- "adv_salt": "87C9",
- "plaintext": "2FBFE59B984F78E52858AA5F954302FA039A17DC9B",
- "ciphertext": "045CB170393A527E4C27BCF5F0B5CC1C8ACA416A62",
- "metadata_key_hmac": "549162023841BF6155AFB443FB966C4173982D736ACC036E4EAFF0934806853B"
- },
- {
- "key_seed": "7E100C7A639AEBCA822893923FFE2D8F27A7F2488FE0A5BCC7275B3A02EA4F03",
- "ldt_key": "09119B7782E29A680A068AC19D469315E4381A063FBE8FE921BB20EC6C845E883CCA820D159C824194E53281E5228B1C3438A64B8DBADFD1E514397E4AC877C8",
- "hmac_key": "69A75B56EEAFEB03334758B127DD700E4A40517C4C6F9D2C43E35B9948615807",
- "adv_salt": "A2D2",
- "plaintext": "AC3A74E6D924FF68ED4EFB0CC6C5E78F",
- "ciphertext": "15707F19DDB011093048FA78B5411CAD",
- "metadata_key_hmac": "25100413FD7F97F99F5E266A7B240AC5F77C9009D52E488D07B08665BE97C4F9"
- },
- {
- "key_seed": "B109A2FD9FCC6ED5F0E4AC288C13C7D2A019CF1C3E74015B2B72BFE412FF2205",
- "ldt_key": "313B0D71CFC77E9B6F5D504473C0C2449B8AC600D0B0A8E138B24C4AC25293BDA7C061B39529DF9FFC8DB8B0924D6426E4ABFBC198E0D7B0B95F6B6EC1EED9DD",
- "hmac_key": "E06EFB927FA2EAEABF0ADD366231BE98A798232E117AAB23A43B7093C4F0B758",
- "adv_salt": "A39F",
- "plaintext": "34FCEE9C0B0D3DFB623FD68221220EAB",
- "ciphertext": "AF802195A59AF7DC3675757026789B67",
- "metadata_key_hmac": "D16684237542761E91538996F8C9F732D9E4CC2BF2E0641514C004048E2246FE"
- },
- {
- "key_seed": "7650C00799B0B33334FD2328E66632159F0510C206D9476CD7457B88449AD908",
- "ldt_key": "AEDA9657903EC6D5258CF7EE66853B9AC85962B7D2F9429A2B09013C6FF5C9B1931F73875822E027913F0BD0D00E73086193040A108958A66136528945DB05F1",
- "hmac_key": "8A4660095102A7727A50E6809C2FBE0AF359003F68E47D9CFA3AA7D4B8C1CD5B",
- "adv_salt": "7127",
- "plaintext": "E8E00B596CA5207090D29EABA3336F77EDC9916AB5D325A2BB798CFB79",
- "ciphertext": "94F71B56EBD8CF9829285FA6282C2A4FA781D1F060B7E46064EDB9F00E",
- "metadata_key_hmac": "545549A7AD83A0D60D5031E371BA1F90235606CE3C8C21469FAF2FA06147D112"
- },
- {
- "key_seed": "4BC857AB21F85D7019DF55B6DC04F222274369A6825692AC9D63BAC25EBEF47B",
- "ldt_key": "339C8EBBED3C88C1DF8C225F355E7FCA833874458F3CEB85BFBCFADD4F8C7AA04F860152E98A9E89142EFBE04A361397802464894E4F2F5B927A9750C8FC78CE",
- "hmac_key": "978FDC344AEC925814FC8E3F1663024915C9F2A95710F44A26BD4B2D4A7521F3",
- "adv_salt": "5669",
- "plaintext": "037BE6930684D4C235D234CA7DA8B515",
- "ciphertext": "BBB7E9148422FFBF79C506B00EA1F86F",
- "metadata_key_hmac": "E82B43F4CACF8E3D7047B484EAED8BD8FD772ECA7C7BA18FAFD4B6C991FB0723"
- },
- {
- "key_seed": "B0312EBB99279933724BCAA461A59F19AA0550107076D40297E3D91A64D38864",
- "ldt_key": "356D1D2EDF489DAEB0263916DAE62352FBD32BBE14DF306846784670B02EBE9B51368877E277A914CEFAC15CF3C763AF5EF0FC5E72CA2E83D994BD8F6FD93E14",
- "hmac_key": "48FE4A7DE06D21ABBBA9CA919C7F339C0D6495D38F8137FFC57FE85ECFA396C9",
- "adv_salt": "FEE3",
- "plaintext": "007455C803830AA1122787EEF4FCD71F57C29C06",
- "ciphertext": "E5739DD2B3172E84F5FCF17EC6C92B3BBD3F86F9",
- "metadata_key_hmac": "575F6793DC05B2184C21426FF985064CB2E6EEDFDB051C3E7A61E737E93BDFBC"
- },
- {
- "key_seed": "A6C270332D6B8DA4419490908DC76D6AF162E819BCB44C69BCB6B093C86025DB",
- "ldt_key": "C30EC3DD334F09F0618822C3E1D93D2C59EDE05F15712A173D7CDC9738132A441FBA14AE65D6D772332B1CC80C3DC880C232A39258A21A07D3D613D0DB1958EA",
- "hmac_key": "07F6BD1301DC800AE625475240241CEF294E0ADFE29CE4645295DE28644C7468",
- "adv_salt": "E79A",
- "plaintext": "69AED23A21571027A99FDBA8937B3728C7C8FE22",
- "ciphertext": "655793F9E26F92328504E2B1746C35D060D57F47",
- "metadata_key_hmac": "72F10799AAB2A3D1CFD021582F92EEF45245914E540073B0BC950D12DED27C5D"
- },
- {
- "key_seed": "1B3DB09F98B49E09FC7A7712DA6975A435C9228A8A10A4B7100015B1BF2A9170",
- "ldt_key": "D7E460C842C14011B55A3E5D1DFAD8EC4D1751A06687A6F3038FE52F9F900C9D01CD3907531209C5699E7611A1C690854D1A83B4B4CD468EBA6C5C7A1BD9E433",
- "hmac_key": "D62A374514FF4D010C6C706F71DD837CBB77204E8238133CE41DCF6C3DEEAD30",
- "adv_salt": "2EC3",
- "plaintext": "91C3CC39C1DFA0A98DDB8669F8BF4100C85EB809CE6E96A23A8F76D1ACA2",
- "ciphertext": "3575C1D1B970E2BAA292F39FFB0886B7FDA0C8F7A6ABFE2E4C23186F9796",
- "metadata_key_hmac": "442509E2FFDD39BDB85EA97040BD519CBACE8B49971B68D7E06F058A87EEDB89"
- },
- {
- "key_seed": "98C8FFD6BF66DDE36B52F95264970F3ABFA03546BB9E42EEAC73B861C4668EC8",
- "ldt_key": "7D0C4847D29D4110156447E82106A97715A6DD664BDF3B4262FBDCAC71C6D9ECC87D7824B1E65E741DDEFCF9BDD149C9B127C7AFA9E1FD73CEE66C441CE257EA",
- "hmac_key": "17971EB7FCD0281E0C5CE05969BDB40EBF768CB8B73E816DAE761DEFDE5C569B",
- "adv_salt": "D5D8",
- "plaintext": "2BC85FB9B4B8597E0B7E02AB5BB183F4C0",
- "ciphertext": "C50688FC3AD46A9C15A5C9818864856D7A",
- "metadata_key_hmac": "44DEE13232B3537982D17A0B6EAD9BC8357C00A7C590D7AB37B6F9C7BDD259F3"
- },
- {
- "key_seed": "1906EAF9DA10460DBC7CAF2DA723C0BD4A087462C162BA91FC9BC9C4B0D91264",
- "ldt_key": "06E58CF7DB917DAD1A8FC436B25FA4860AF9B0D8E80362499F2F80D294AA0BD88F070E0DCB8A9D801B35EE4FB587955B751658B9717596272CDCD7BE1DEB7D33",
- "hmac_key": "891198DB242A226E7D1BE5B08E5F786D38AE8C8FBA009EBBD8ED26DDBCD7053D",
- "adv_salt": "A352",
- "plaintext": "DB729216056241B8A2BF9A9A362DF2DB5F",
- "ciphertext": "B75F7873302FC7FFA4AD4FB9A320C96F43",
- "metadata_key_hmac": "B26F69630F29582F0516D5CFC12BEA2380CFCAE49FA987A491633AA9E60CA89E"
- },
- {
- "key_seed": "C903E4AD3E9CF458BFCCE2E1F5AD924523C20A7F1C73FB6A02F04C49D95A6066",
- "ldt_key": "8319E13B431FAE7314B09BD90C628C05F469877FE0F245D84A6C3670AD60C65568B6A2CE61DA831A47C53AF8BDFABE1A6461899CA0ED14CDEA3946FD0DAF302C",
- "hmac_key": "DF550EE4AA78C5DA0061C698AACA07A6F2D00B041554DA56CAC1BF42520EB77E",
- "adv_salt": "F5DE",
- "plaintext": "6757E541F331AE07400C295A4712FA634A712EA86517B559862FD6731E44",
- "ciphertext": "DA74D9D92E47043556FD82FA4D22E46D18A8A9A2313E2BEC9FB9E8D78267",
- "metadata_key_hmac": "0AD05442F7AC6ECF628844E9C3C7046FB926709CBC6519EE5775DE03A42CD811"
- },
- {
- "key_seed": "BEADE49E784716A7BEC51E332BD5540A25C1CE71A278A54CC07B649D048A5561",
- "ldt_key": "BD54BC42F56935AA1FC5D2A8C76294DAD6E40F00FC306BF33F29C0866B1B5F5F1261F78B08B6D61736DA480626DB27E07C9FBAD41582C25B6EE92EB2394163AB",
- "hmac_key": "FB9031E5428C831BD0969F4EDE7CBCA5244142D9EFDDA4A03FEA452D25A0254F",
- "adv_salt": "AABC",
- "plaintext": "63EB8971511A43049DFD7EEBB8075D82521F3654C458C3B5149DB1",
- "ciphertext": "C3A855294A2AEB154347758C6FB052BEAFC2789E60573AE8CA80B0",
- "metadata_key_hmac": "E5FA9F69D44C7E68DDC4F687C6BCAC9EA78690233AA3C545CCED835E7CCB2021"
- },
- {
- "key_seed": "F3916DA3C3328FC1271463E1C44D533C27C59D7C5CF9C7433E986605EB958E70",
- "ldt_key": "02EE10F2D441AE3C5C31E1872BB8E7C91D86279E9F8CF51915FFAF05F58A4F1C1CCBE91AF3BC8D4F61F4ED33F3D7C24B91D7DA9D8999F6576BC001307B260F75",
- "hmac_key": "8D50A24DDD4DF78A0D360B9A16356C73ED7C61DC8371B8477B9C34B09FDDE9A9",
- "adv_salt": "CAE1",
- "plaintext": "99EFD86FEDD4AB164A959BC0416802258BA2B968E3A52D",
- "ciphertext": "BA17B32F85E71560DF2F894B76661A03E51802D4674EC8",
- "metadata_key_hmac": "E7F669E5B1A44A2439ED07F2743E15AE10B44C51F19E16C43FE4E2EB4346A784"
- },
- {
- "key_seed": "C4317D4E906F9BA4539B813384B14E530AA69BFD2DEA76107FAD0847AFA8453E",
- "ldt_key": "988195FD6BCFACD2A4EDA1ADB4CE9F562D2053D41E94763B816C113A15A4A05C3F9D952831023940BC66BAF00A8C347FE77E0438990A01D42951B23B9920F01F",
- "hmac_key": "6DFBAD52E858DA32E6659D7173348B34F7E015E93F1F34DB6AAAC8DA11AFA82F",
- "adv_salt": "2B7C",
- "plaintext": "DD70CC7F846A0FC9EBB24F46E4D61C58",
- "ciphertext": "6218162C76FA90C27845628EAE8E2F5A",
- "metadata_key_hmac": "0F0C6BDCED527251DD706A3D2723FDF8E70A666E190755D5AB515AFCD3CE13B2"
- },
- {
- "key_seed": "3E702C13AEB7F8F75B8142978D771C9A6695F65E9D83724B600C7C504C06AD11",
- "ldt_key": "D97054FE9C78D83EA387377C8A9DF47959780CF1A3AE864B618ADE48F6F4C74F8C5F1CCD8BB22F12B4BE04B1728C0859ED849B92D6AE9A455421AC22EC75005F",
- "hmac_key": "A170DB24F77CEF208F83ABF01FA07B236D38FE276BFFADD60DFF5150AF1C5076",
- "adv_salt": "E442",
- "plaintext": "6566009789ADD17B430B8E31E70951A8917F2598FBDB63366EEDBBC0FA176F",
- "ciphertext": "041BF4C98B853251F8FBAF522F25F3439E57A1E6F817F5D08AC0EECB10EC91",
- "metadata_key_hmac": "2364F70676B650040030D6CF42B0E69D50FA56EA87C0BBA8B9127157531BA035"
- },
- {
- "key_seed": "CDC2C95F7099A6BCA83A96FFAA9848A06ECDE7A297EED14A9C88ACEDD485C55A",
- "ldt_key": "2E02B7A12A3F1280EBBC8B9B9E73CAD6D3A708F71335C21C9E690B7C6EDB221DFF27802E34A9FECE2886BEF0328AC0B685DF28CD591BC25DF5FC6F05AE0037D4",
- "hmac_key": "E037D28C89419F303C3B22704B03B9565CA4AEB4A820E2A7DAE163AF3093F315",
- "adv_salt": "313D",
- "plaintext": "A9334CAABC7A3EEEC389B8366574AC31FF921F4D025E74326871218B36",
- "ciphertext": "71F285C42EFBC9F80DBB857BC58B4B82CF22AA3E68A6B19845CA6EE672",
- "metadata_key_hmac": "8EEA0E056F28756417FAFBB00619EF84C7AF7953423F697243A35B53A98C2B3B"
- },
- {
- "key_seed": "9E3A32C3CA43D7DA82838C21DC8D7A92B34E3029F2150EB6AE08E21E54DA60B5",
- "ldt_key": "550C54BCE30C335EFC1B2CF3C69B6F36B199C11C48D8B82DE689245CB647C21FDD5697F8004D5D4409B9D7A5B5E4BCCED86624FBEB89C4E24D69FE614BB6F4F0",
- "hmac_key": "84DCADE652FFB2082BE54A83C761B8D3BCB3D004847DBC22B7B4F56E1DAD1AA8",
- "adv_salt": "22A7",
- "plaintext": "E800C9832BDCAC3DDB8115515F54B42DF4F46A0642",
- "ciphertext": "18C49172DE8492EC00FD766E94C32E65F9D94253E8",
- "metadata_key_hmac": "C7F591B8ECAEE9E130E70B87D4F4CC6F0CF79781C11BFA3205DBB647ED8A6EB9"
- },
- {
- "key_seed": "208584B114FB579D651DB0AE915AE22A74161DA1612FD66934AAB98970B4F3CF",
- "ldt_key": "18F509AF830D036179EE8F5579620233859AD012DCE5CC9964BF83AD1C8BEAC752A3F856066991F3F899D7CEE08F76943D0E898C73622FB6BEFE1635A752A258",
- "hmac_key": "D8A0B7CEEB921A4EAF78C315DCEF3AA1A219D8207C2EB750CF5C9A5C057F5AC0",
- "adv_salt": "9B40",
- "plaintext": "643A11C2ED48C3FBFB1568646836D664D2",
- "ciphertext": "ED655DE4A3CCA56EF5E45CD58BC6EC981B",
- "metadata_key_hmac": "BA95BFE69F798B5F499736260A9E16D1AEFDEA921BAE567166C7155553DD2A72"
- },
- {
- "key_seed": "AA182BA6F55C8B6E248AC754E735F24C73089ED81455F7327B4FD32CB10986F8",
- "ldt_key": "C6AF6AB4ECA397CA4C72F2231C91A31EF7BAE7402F214BEE91A26000A41C83AB49DE9F83A6DB14C1B7089B98CBD5EF56C821152A777A62A69224CD24C87214E3",
- "hmac_key": "B3B94FD6E36ED7EB23C5FFB2B9FE39AA8E958C7968B54CC1374C3DE2CACCF83C",
- "adv_salt": "BDB3",
- "plaintext": "6F1112EC7F239D89826A71A35CFBA83A",
- "ciphertext": "1D2EB0A2102A78B09B6FE01461420937",
- "metadata_key_hmac": "901621B523F0C0C37593BD1C9A8992A11D6E00B308956B0A1CA1B20342AAF924"
- },
- {
- "key_seed": "6396EF1AB8B1AB63FB63917F29FED78EFF57ADD13B849349B6537878F1580A9D",
- "ldt_key": "2D5ED0EF006E0D023A2D76051D936964DF8DCF63CA1E0B90A9AC4024E3544DEC4C1EA88718DE3B1B60845BC8915EDE331909415B024BC421BD5A4734ED06CD71",
- "hmac_key": "BCCB2F43EEABA659F0962C885B69037243F54692244700EF83FC4CEB4CF47AFE",
- "adv_salt": "4B17",
- "plaintext": "CF7231679510559FB935294595824823",
- "ciphertext": "6CFB394FA9522089E320871C70D84A65",
- "metadata_key_hmac": "B1DD5AF143DB53CE62FE9488C54E581B16C31EA6FC2B68D6F37F6497D6A8FD10"
- },
- {
- "key_seed": "CE60CB333D364A1D6915B37FBF1C92091829DE2B1B6B7B8FC4D1349038A44D6B",
- "ldt_key": "63307367255949F902F770F3F3AA6AA0DB1034A93C9B6D177182C097AE3834F55BB44259D53296B3AA80A2A3A950DA6C705A39248AA4A53EA2EE5029A612C339",
- "hmac_key": "B140C0E4E7FF5F891F795DC224BE23C376A6C2CA6E7828DB2A608B37F719C050",
- "adv_salt": "49C5",
- "plaintext": "16E6B82B12476FF394AD541550943BCD0687EA15B290F238",
- "ciphertext": "2BFDC35E78862910FBB626C9A124242A0E3101B4D1B506A0",
- "metadata_key_hmac": "6894A92C027E0D13A0A17F0A036D49621D8C092BF64B37A6D5D7F88719C34B1C"
- },
- {
- "key_seed": "E9CD02A26F9C4AA593C8FA3161F71A36A5B01B5997CD37E03FBAFE255F0A9904",
- "ldt_key": "82A0D8C3F7436C38DC56950A6BAB1295ED7AE5B20FD624B500E7FA2CD76949B47C6E7E92194A97D02D034F3FD963F3AD58F798D73B3CBE4E7FE133C033C7D2AA",
- "hmac_key": "269411A0CA960F8EFFD49327974D759EC1C658FCDDA6EE313917010EEA06CCE1",
- "adv_salt": "B23B",
- "plaintext": "EA133D6192C98F803D46FA4D09EE84EDBB432A315378A6ED5BF6691B",
- "ciphertext": "D85B0CA6B5E9A77FD2700CB0AC3D0C193A465F0E7CC52729ACC1A61A",
- "metadata_key_hmac": "58C3CAF1EEEBF55F0D7D27BEF516986EF9253BE453A8487EA39F56CCB6D53DD9"
- },
- {
- "key_seed": "D3BC36A108E864BF1013B0DEBD7C9F340442341A5C70EF7A9E8C437D33433EDA",
- "ldt_key": "99DD0595D3FCECAF7D98E0C26266CD1B04CA62DD2558B5021061A7F7E1D419A804547B513DACC7529952FF238B9B4720D62D4744B023925A88E5D3E24C3B26BB",
- "hmac_key": "B3681FA6E9112A91DB33D045EE54F3C7B914FE9FFE835C03A38D1D039FB56AA1",
- "adv_salt": "DBF4",
- "plaintext": "3557B3C4BCEC8E7B0ACD0A0134C47494A460F799E821C675F3AD12",
- "ciphertext": "449CCB6BB67FE23807FAE60469DB06C7D8E72C9364FF1310A27D37",
- "metadata_key_hmac": "4BB084A1FA068300E490F67B29CDC91AE45DA0C70709BAEBD33BA231AA2B4CE0"
- },
- {
- "key_seed": "6DD1A5FDC69B668839D44722823CB1CBEE2827A78943761C2DC92349283BD34B",
- "ldt_key": "1D3B333FB54E240DFCAA8892332A7E7323F93A4ADA114E9664BD7564969182EFFA6C193C0ECD2A67B18113E4CE254AE6C8350ED57126FC9A4D909860BA509DEB",
- "hmac_key": "D73A2C7983617D6F346895DA10012E42A8DD8FDDA9D6B21F3B8A91546E638848",
- "adv_salt": "A1F7",
- "plaintext": "B4F3EBA80957B3EFFFED35FA1487CC8FDCB0",
- "ciphertext": "4FA99A5587D446031AE0DD322E28DEA1CD3D",
- "metadata_key_hmac": "FDD24B63C520BB33D124E74DDAC334175C00BA0CF350F0CC6D3CFD51A57A5B12"
- },
- {
- "key_seed": "1521D786973327F460210B6E4A98241DFD125976BB346CC05582B705CF2C81E3",
- "ldt_key": "4273A7E59F40DB5DE89D3EAD6732B12FC8A7671B4CFB6DF7BDA02167B0F3414CA1EAF32BB53E1D892B9932DE2163ECA9CF4C822179C89BE705EDAB667C25B58D",
- "hmac_key": "90F0E29BD73A103AC87C3F60753DAA6641DEAA3E9034C25BD878ACD3EF14B7B9",
- "adv_salt": "650A",
- "plaintext": "98FD73B1CBF4A46CF1B855EC6D4DBB755716B2E1D2EC3C",
- "ciphertext": "56A77F96DDCB43A70530B88669BADD12F7F16E4DAC74D8",
- "metadata_key_hmac": "1E2DDAD56AFA04DD197D0E75BC60A3A303AE2FED2250D62BFD5613505DD3CB2C"
- },
- {
- "key_seed": "76C21E2D70694F810B5F730962CC6EC1E5B4F9542990E15DDBD2ABEA92B4AE69",
- "ldt_key": "CA8485DC112182FEBFFD7DF96365F8E7C97BAA0701F516C191DE98E772FBCAA94E87C062A2A69D94E66942D262D4C5DFCA62F2B293BB485B5AD399A1192FB5B2",
- "hmac_key": "F18E562B465B4D05D17C30AF43DC2A2C674DE6BC09D50A31A11E4246AFFF22F3",
- "adv_salt": "26D8",
- "plaintext": "8CFBAB03370DBAF4228B2BA60A4009A8",
- "ciphertext": "B5F69C72D7F281D68236E70FEFF3AE85",
- "metadata_key_hmac": "0F9AA07E623C81AA9F497CC6DDA13E0C6752170393EB205DFEDD3EFFBDA5E959"
- },
- {
- "key_seed": "9560513480DDAD0E1413E38F9D6E897ACE1A7632D596D23769498B8BE29715B1",
- "ldt_key": "10F5156C4B8B7829C1C4D6F145DEF13B9A324C35D5A3E4820F892584844CD853D94FA8CE5A1AD2823F59D5A96A4E9EC4411BFD13781392ADAAFE6EE12C85ADBB",
- "hmac_key": "25FF587E6307020556B1F164B8DE84074F17E3035DF540FA6F9DDA4D2C890ED3",
- "adv_salt": "6656",
- "plaintext": "2E131D72176A4200B363D13D80DD10A12A698AC0A1E099A4523F13F6A9094D",
- "ciphertext": "8E6C2B66D73724060636779E93F2EB02534AD93613BDD424AD387554C3257D",
- "metadata_key_hmac": "A3B660C747BDDBFB92E8B48B6DFBF3B6A927EBCD836B98968E4DBE1A225C0CCF"
- },
- {
- "key_seed": "8A7FA1444A5AB5FD9C754FB5C17B24521A4BBCA87304668ED171E63ADE00B53A",
- "ldt_key": "62E5CE70A1E00AB0344AFFC21660B81B9AF7DBC98E2B3BBFB0580F95CDF6607EE86E3E027910C133A445A54EEF164717F60BBF581FD911D16C16797F093AA376",
- "hmac_key": "A8796FDDAFDA42BEA46CFAFC15B3054AA95C7C6D9842C056C5D5CA3290870A2A",
- "adv_salt": "3ABB",
- "plaintext": "96C67D0472764E1FBA67D78C9E23130EA569D80850D67860705DB18A84D9",
- "ciphertext": "E253ABEFA95A3005FF8A637C64C4979D527823DA079C56ABD7F8A226254E",
- "metadata_key_hmac": "29630F405187DF2E46FD1568B885C8F342B6A0C736D05EF2708A15E89EB4F77E"
- },
- {
- "key_seed": "C9CEF79735A49737B2054FD28AFD49A32BC27413A645B81EA41ED0976EB2C1BA",
- "ldt_key": "CCD43C05EBB5729D56B9ABCD430ADD48AA324F888273F11990F29B1764976AC52F579204BBA9153C1C87E895FCB10EC57E5C27F67166794A4D056114ECE090FD",
- "hmac_key": "84E721FF3054B223F07971A69C4EF2065FFA8BEBBCA6E21F86D3195404D10CBD",
- "adv_salt": "DBF9",
- "plaintext": "3EB9E1F6C5C925B9DB9B9358054A7110AF19FFA771",
- "ciphertext": "05A4431BF908CAEC6B3FB847C2F45CE4CA666F2669",
- "metadata_key_hmac": "256FF13A29DD13554EA3B53476950960BA8FF3404DA2EA647D657DF077504116"
- },
- {
- "key_seed": "E48BFCC68FCA39CFE1CA4EDFC684E37D20BD27D56257CB0EF4F109AAD61D32A8",
- "ldt_key": "DB6EFAD0649A4D700171A22AE74D0C87CD78A15BC2103B2CDD10676190D519227039177E4FDA4003C6C2770E577BDAEDC1124EC003996B1F63B0DDF882988BA4",
- "hmac_key": "868E89F711B4890B4F3309E16C33CF8DDF9BFF32E94B3B9CBE091BFA3D9413DB",
- "adv_salt": "DD6C",
- "plaintext": "966A5DA11194D05AF55AE62928946B3066E956B3C268878B8B",
- "ciphertext": "A4E406ED299EAB31C8EAA4179CC35F6F5ACD3BAA2037C68340",
- "metadata_key_hmac": "9A521E13E251F0015C3740EA21D84E108263125989719A2E7E3C847DC4DC08DC"
- },
- {
- "key_seed": "36EB0F6236D1072C71FEBE86953757768518126B710BF644C724B22C6E811361",
- "ldt_key": "34D51D3D4D442AB9EDF9CA19D84D0A23BA2DEBA4F49F1322BC37A5CD72BF0EC5B7183DA85F90AE029F8DD752E177CCAE26D73DB63F27F99AB39B4C2027FA5731",
- "hmac_key": "6CF977E944CD2F42EA05A0F833E39E855FA219D30EA6ED07A85300654B8AF653",
- "adv_salt": "D695",
- "plaintext": "11C0603EFF5B63E3700C4441ADDD8BDB8B8D5413B06D0B547B65",
- "ciphertext": "1BD66DF65CA78541E3EA94ECC88C352450710DA6F22C5283EB15",
- "metadata_key_hmac": "7D26D8BECD71E3C98BB5B60493D5FBC5594473DC1A333BA123C4007B10FAE74C"
- },
- {
- "key_seed": "9608BC776DBA4873F0BFC953265CB8E4C36966BFD6230C35B63E723722458E08",
- "ldt_key": "22E962B7ABFCE353EEDA7F16CDAE977B7F496C938A663465C36BBD2B433A03F7A477190B8974A5ECF41C29ADB0E767A8BDDF4636F369C56E83EACF1B39FF3CE4",
- "hmac_key": "E69E2A790681904BFD66D09CD60F291E84DCACD490208F5682DF994291F4B3F4",
- "adv_salt": "4F53",
- "plaintext": "E125883CB677E805178785ED8FDC525E0054E48192CDE9",
- "ciphertext": "7DD36CB0146BDDD1FE95606A15CAD69164EDA3CE7C7B29",
- "metadata_key_hmac": "0EEAE07CBAE833B659F0236D45B965F7ED423CD8CAFD921E8B52932AF0FC36C5"
- },
- {
- "key_seed": "B2B6B53D51B08DF36375C4F761E4EF7696B8727CCC69C055F59E1DFAE7465B61",
- "ldt_key": "FF16F56B0EF97ED2DE15F7210D39F17D7E2A0809AB33B6F03A48B0D67FE60258A576E642A001C160068D183C6B8D691C42E7B9B5833AE1D4EB6C174A40022167",
- "hmac_key": "BACEE2A7FDB9343A443199D0AE356C3FA81F3B4E9A23AF015111FF65AA577396",
- "adv_salt": "6F8F",
- "plaintext": "D802DB2CEC8B2D5C60AD56EEDE2E9F703208D9074C87F301CDDE9ADE",
- "ciphertext": "940E65E0B35E2C55C95DB6615BDB983157F4E487030E089FD7BB36EC",
- "metadata_key_hmac": "7BFCA5F80A1C0151FCB6AF5B0254A5FA6D1C1D3838171C9BA7239D2691BB7DAC"
- },
- {
- "key_seed": "12DA1EBEAA3D43E08E600C6AA716B207D36C6758802374C0E4EA7C32BE675D34",
- "ldt_key": "062A158A5B903F3101F185D3BD4D40AAACEB2790C556E5DDC9AB463A5DDCE0787CF1179F73956D6C6899607BE6F76FA9336D6FA0B4CF1A2282675175910CBC49",
- "hmac_key": "3E8D020F7D8B0CE5D79C8F16F0343F04D7336C8D27041AFA158BBD005EEBBF6B",
- "adv_salt": "2D65",
- "plaintext": "402574521678897BBE04FC669DC869542E54E549331D42DA1A",
- "ciphertext": "12F37BB97EA1AC0409881C93DE6CCC872B56D1213F19E6F7D3",
- "metadata_key_hmac": "E0FB235D6DF5EE15F51D8BED378CD53C176A20FB9C609AD165229E0A7619EC29"
- },
- {
- "key_seed": "F7BA3402556935A790BECBF1BEB3152EE9416A022F90FC3D4446DF8D97600191",
- "ldt_key": "919BBF75697F5344409D34BD5D708B2A60272FC3E0B75378331B62BD1B4E1A11E0091FA4900E9DDC91E73AEF4D2386D9736F6270041B7B7D2843F8FD6D96A76C",
- "hmac_key": "50E71BD98F83211A1F4066ADD9F4854A157849C16C07A791D1BF42B9A9E4738C",
- "adv_salt": "34C7",
- "plaintext": "A84BC1B49EB1276B9B66B88EFF282C5FF055BA61F169FFCD860C1C",
- "ciphertext": "DA0275FCD07244BE53E80E32A4049CE8239AC7C4FAC554250CFB0D",
- "metadata_key_hmac": "7D9D7E557903E103A6F55D2AB5F8CDBE2BF501EA1EAD9D1DA31F8E536E4E9B8E"
- },
- {
- "key_seed": "B7743F2EB3B31527222B0938A519EC45B2F1EEBC58200CB62E353419232747F7",
- "ldt_key": "2B9060A96D16FD2CC61D30BBC3690007AAE85FD2167855933FF3A35ED3957C8D17168B6B3219152E40CE2F0246A4038F9F06DEF59559D16B1296C3B38BE9B70C",
- "hmac_key": "4623A09FE3176EC70944793D576E326FE057A72AB595FE23CFFF4845E99FC9AE",
- "adv_salt": "C4CF",
- "plaintext": "5D1CE03573BCA43C8766F10C03A2C810D54D8B70E2F4C5E5EEC5",
- "ciphertext": "E339FDB9FE6EA518EB5FDDC3C4DCF951963F2D90FBE4090EDCFE",
- "metadata_key_hmac": "92ED758AAEB7236E22ACCEBBC0B33AA23DC6727677D69594F09342984F5C863D"
- },
- {
- "key_seed": "7E6AD26DF188EAA50EA6BB1DC755E674332952F84A902CF17351BF83B3B3D40B",
- "ldt_key": "4823F16CFACE349ACECA6A797F7F6949B5CF0E86B14F2FA86A82F9E5344DD5FBA46CF1DBE420200966B1B4E16134A1735BA922829F7B9F504DDB76E87C8620B6",
- "hmac_key": "C867A614967B144D921C37E855F2EC8C017A0CA5150842136B67D247E4509D1C",
- "adv_salt": "DC9D",
- "plaintext": "AC66F58970822EBF3EC8FB8A6BC0B88ABE4AEE",
- "ciphertext": "697EE0ACABBD0F2C888A27005A568659EBACE0",
- "metadata_key_hmac": "5B9CBA94B48443F07B608B1DC93F5FBA745A593296EA9F670E6F148BE667D6B4"
- },
- {
- "key_seed": "3AA30B6E523E212F9BC549B1468624C3C39D4446C1613F99EC525E90B563E114",
- "ldt_key": "32EEA16100A29DEEDAF425D5EDCECBA51621B8F1A3FFA232D0804FED7B9F05B15A3D0638AB519640E927F61C2107E4A56556B054CB0323CAFF375A144FDDA9D9",
- "hmac_key": "07A1CF987BEF7C4DD83B831FFC6A67405ADC35B465063AD3201A15570EE65B6D",
- "adv_salt": "C521",
- "plaintext": "43FD7D528C2B9B610C8AEEBD9B136D6DABEF53F920BE",
- "ciphertext": "DEF7A393BE5094EFA7BFAC518C014979B32FABB4DB26",
- "metadata_key_hmac": "9AD8D7883FF0D6C9F2408EA1D04F6036C587CB9275F9EB53CACAA220F6B8AF42"
- },
- {
- "key_seed": "E9E8F9E8DAC560A5CD0136D59C94099D601EFDB849F599A3B58078BDD2DC3E96",
- "ldt_key": "A437E4C55CCDD67EAF8DFAF9C65213E8A2232FE624662D4B682ABB8A5B9B9D21307BCDE683C42FC22F0595AE41D59BA016140A309B8825143E5BF5C12B3B7549",
- "hmac_key": "6C4768193DDBB1477C893AC14A87563FF249654574814C4153DC1DE46CD9A2B6",
- "adv_salt": "3813",
- "plaintext": "856CFE7BF88E2E8695F34DE8694F3DFA61F2B8D93A148264E4354B",
- "ciphertext": "86EDC0F3E4F9A9BED9ABB4DB56C2E2316C61097F2944F2306A785A",
- "metadata_key_hmac": "ACC695BCF1063CB8ED7B2E456DE86FA0CC74C1FE44C4F637AF3495A409F6D0C9"
- },
- {
- "key_seed": "53E237DE3511AD7221FDC3EAB249724CB9FBA19C4FD08E65915188264C639AB7",
- "ldt_key": "16A2905D758DD04EFD7715AB796FE5E5CE922B3458733A8C369C4B5C1433A1597A50D58832593831F52B33FFF07EA67EBA625635F9949889CC57B92D99E39868",
- "hmac_key": "E29C815883E98D5DA9C4CA403AEB9EBED8F7590A15500692563113D74CC57112",
- "adv_salt": "4005",
- "plaintext": "77358652AB18EE47794341B2438A77770A358CD1E9A00DC0BBF79E0D5E",
- "ciphertext": "3606F86BF8017D9DCBC8442C1D9C50F4B853C6DC6F1E8121F59113B4E5",
- "metadata_key_hmac": "DF01BCC3F032DDE4CB7FA01CC8EEEC96C5339F2DA060240CAB3F1C8F0DA58E5F"
- },
- {
- "key_seed": "7312EB9FEA5C7CA9F945DF91E6CC5512844A1F3694FF1F8334C14A8CC1C514DB",
- "ldt_key": "9B14E89C2BFF72EEB7C9F484BF20DDADB3716055A55DA9CB9629F98B456E8F5FC16D03D399D8D2077668D58046029E1BFA35A75B22C0E2C66CD79F17214D3F40",
- "hmac_key": "CBAB6250E2F312A36E475FB89B17661810DA0F6B3E0E54980CCB409F72B6FB11",
- "adv_salt": "8A4B",
- "plaintext": "8649F437928B3DEB3271CF32D20C82D92B0DEFF30FC189B17E",
- "ciphertext": "3742B52ED6A5033C1E3B9C4AC90E025761AF6F021A36775D8F",
- "metadata_key_hmac": "3725CA84C82101D045522383C65A2CF82DC7ABEE776A2598CE6DF5979738CE9C"
- },
- {
- "key_seed": "1773861943D0B75137AC484431C0E3A5A01AD365E210D49FCB600ACA63EED3FC",
- "ldt_key": "0ADBB1905A684E8B43901DC20C5D5320A3F446E22F6897FD4000893FEDB66A21B2BFE78CE6E9614642444A885392BFECE5D01D9610971697BBB0243689AE20BD",
- "hmac_key": "8DE824B2E5E8EE81E6853B2B6B5476F01D8C32956110BABA92A826E3110D9E73",
- "adv_salt": "666B",
- "plaintext": "8F451FB1E8EA039FD315E22C77752A81E0A5",
- "ciphertext": "5FD110690047A765DBB47E7F2AF9AC7A2095",
- "metadata_key_hmac": "7094CD4AE6B7C81475FAECD9C12542CA1B0BA018DB216BA6437512E09B5B7F6B"
- },
- {
- "key_seed": "C81619628FCCA36C3333A9DF317A30A38E992B99B4C613D54EF5D8A84E041CB2",
- "ldt_key": "DF08364FCF56F754A435A293DB8F061F63EFEA9B7E6677D85F3C7FB184C6CCF577A2BD0ACDA5DC1D2523EE1F17124C2165FE283314C5570A77DF48ECDC355AF6",
- "hmac_key": "139F438F13C38116CEAF0008113831A0B2B4AB26C2C2C67E7E0789D457A6FB58",
- "adv_salt": "B2D5",
- "plaintext": "8EBB4881DD7A89B035180226619EA16AA87857F56336D921",
- "ciphertext": "4D405B876C12A543559F879C464E87A318B0E3778F2C884C",
- "metadata_key_hmac": "A51503260CDB7DA3B8A8A625C7D0FE672E9C4DFF1A61083507785911782EAB70"
- },
- {
- "key_seed": "C40DDC0D09883D89AB43D4868A619200BCA6AD3077298150EE3B24A538259899",
- "ldt_key": "9EAA4B0A788B9722526A0CDC24D12CAC087BCEBA93DEC1BF91A75B083E237CCC81EA08EA411E17E3D456BD84DD62D3767B816D71495013A76CE01381BF079DC1",
- "hmac_key": "1C06DD06F878794583907EB532AA977111887BBC3C04D206E6AAD6C4B396EEBC",
- "adv_salt": "6A17",
- "plaintext": "7F48ACA677EA0623CB99F4489684B63644F4",
- "ciphertext": "4643C1A64BE170CD2FAB442F1744774FD2F0",
- "metadata_key_hmac": "50B67E416D25520E17E3AA41D9D91B40E161B46EB4A844194F830412B51DD82A"
- },
- {
- "key_seed": "5303BA3383DADF741D20FA46C3EBE1B0857E0525C88E7D60491C7CC09BC83133",
- "ldt_key": "E7BD40E7A7AACD7C889767679F2A6F8F1ECD3EE7BE80C954E28CF4B18060ED8112FFECDCAF162A21F8D1A310F941B3B144B6430B2B02F284E3C278C246517BD9",
- "hmac_key": "2B9A31A18F3516FB7A03E7A0C018507499CF16075D6CDFE395F38F466133D106",
- "adv_salt": "F11C",
- "plaintext": "62C335B8AEBC64111E88458AC17DBCAAD9FFACE7F2F34A62AAEE1F03F409",
- "ciphertext": "7A187B905C3A923F2882D66C11CA32ADCE01EC46EF2F606DCD92E6EA1777",
- "metadata_key_hmac": "98B6F0CAB8B8DE46C4762284899C2E0AB18BF7FAB1016A312DF886AF3188056A"
- },
- {
- "key_seed": "753528F822537C4D415D303A60E262A1B2940080851F56EEB3A139ECFC542FBC",
- "ldt_key": "D0DBC4CBA4FCCDCEA4488E96818529AF39194E4CC727D4E7462E08E6489FBC514FA2E49FABF7EF2D79D4C64AD5BE6411F22A95BF0D6395FDF6D1A6D9E571D4F2",
- "hmac_key": "880716AF02E75D557E6F5FBE217E25EDAEAC5D4409B167D29C8F5D84B163D3FD",
- "adv_salt": "126E",
- "plaintext": "EDDB6DDE5172724C4AED0FC8DAAAB28D89C4278B1A40E3332944BC",
- "ciphertext": "1C6207B72F07609CD5A780F30D8FCE434C4F9B27AC7168709B5D5F",
- "metadata_key_hmac": "2AE916B61DA3329C97B25E50CC2E3F16BFE28E811CB4EB84D317B9FEA37F1448"
- },
- {
- "key_seed": "E758DEEBC05D7496829489D628C73ACC9610CEA8156F7FDCEE71F5CDDFF19FF1",
- "ldt_key": "798A19F3F00AB6043F151CF56B6E420F92579A1C7BA59EF6BED390547F269AE271CC0AFDFB7CFBCFA9D7556E7E4B65BA89C7DC769E7FCFF84274175A592A7124",
- "hmac_key": "F3773E92263D77390B619936774B47E41B4EBF50ACE1446B76738E5E538C83A2",
- "adv_salt": "DC11",
- "plaintext": "31E392CC99247408D4560CAEDC95CF866AEDAE",
- "ciphertext": "3B4814FF273551D37E33D7A957F066730E3B7B",
- "metadata_key_hmac": "FB168B3C5C1D90160D5A4E9BA3E77B485FBEE19A96B0201F72694C7DFA6E1E5E"
- },
- {
- "key_seed": "2B47278A6B48C731880FB87A2DCA8554639BA9D823B4747624B6E2859705848A",
- "ldt_key": "BB04B6BB8AB23527697B9D9EBF422C242C98BE7E3A61C52F4AA88980F3E31BD92FD51C039F907CC7D98AD0D2ECAFB1D1CB872B07273DB62BD1DFCE1D148EBBCC",
- "hmac_key": "45732D754EC4492F07C42B598CC4972345C04FD2A0B9AB260F24889181095855",
- "adv_salt": "5FDD",
- "plaintext": "51EF41FD9A1E6E3239B05D7B663E7628DACBC8EC579831740ACBA4BC",
- "ciphertext": "677BA674167B0C7C62245041C90F894F93BCA3822DF31B097DB940FE",
- "metadata_key_hmac": "665F0B4DDF0ECA663AEAB45D5C0F221EA736BFBF23C240D11FE78036D52D919A"
- },
- {
- "key_seed": "885E516FA5AE3EE60BECBB3CCD69F3277FC70FB98E93EEC511764DDB6DE834D7",
- "ldt_key": "C7764DBF1114AB161E4466C48DB5A441746E5634D68FC267C974CDAA38F867A7427F5844EEEE7EAB25E8CB811DEFD7A40AA1C38484D3949E3507FAC5067DCB31",
- "hmac_key": "6A46572FE998C253F213534B0FE6F875C944DBA34174045C1C991E050EC07E0A",
- "adv_salt": "2985",
- "plaintext": "12501D4AAC3B854F1A56A0CE3B2216F5327D8296777C5763B0299780",
- "ciphertext": "F18310F993F3BCFDCACFD8E3A61D97114FE73B2515B952DCC4505860",
- "metadata_key_hmac": "9A52C36B094238C0C3FBC0774B8CE7E5A4624EC70EDE250F1580548EB30BCAC2"
- },
- {
- "key_seed": "D56B601EE412A42981E5F9BF1AB7113ED37F06B99BAD84128C1B29FCD99AB55A",
- "ldt_key": "6DE9F0640326E8EF67D01DC252C3888F5C4BA0E3B1C8504022E328A6E679CCD1EF5508681D1A17FB7E76EB96C41EDDFFFAE08EA207A99256BCBA1C008A4BFEF2",
- "hmac_key": "B734884B932BAA0ACFE10228C97194F9CE395B3EDEA2A0433AEB92B21C136E1C",
- "adv_salt": "1810",
- "plaintext": "F9F1E08CA0D03CF62B915AE0FB3F306D288F3F3F9F78",
- "ciphertext": "04EC3FE723D1946741103511D1E7ECC723BB88E33060",
- "metadata_key_hmac": "A8383FA1B78EA4D04A5AE8E97BA985518DD9AC3FF6E897C71C3131C63BE1AB1E"
- },
- {
- "key_seed": "45BB14939A3827965AE97E6C098D34E1299F61FC22663695D0548DEDE836D06F",
- "ldt_key": "C2B7B55F49F3EBD92E0488A8F131E7E221F122EF963CF74EA0CC84ECA58AF09893D5BFDE1A2A5FEEA4560D0022786FDB112FC2070351420938DF112A850F2225",
- "hmac_key": "D754E3E689B9D6345A6476D6BCCAECA2E9E0D3BDFD71D6EE2FB3375F3891DAE2",
- "adv_salt": "8444",
- "plaintext": "04763A7656C5DFAB6A837336917B595F28",
- "ciphertext": "84564DF47E50AF227B6F8D5E63A1203F0D",
- "metadata_key_hmac": "49DDEB980A70C46077645F40DF71ABE5B2AAC895BA8636A5E8505DC9B9C1F47D"
- },
- {
- "key_seed": "5EA520B5A5F71495CFACACC3768168C9BD00E1923095EBB6C73081E1332A34D9",
- "ldt_key": "C59E13A7E1E3C3660737B37B29786658536BC0D4A04AC75F1092E7EC9F7D1CA21DFBA04A66A1AEF372F509DFA6A23E1574E14C701EBEF74BEDF3AFD989EEB01F",
- "hmac_key": "A3390A01124DE94322178DB2128C964DCDB914898F356FB7D92F7D65AB78F226",
- "adv_salt": "6967",
- "plaintext": "F4F059C16741C8AEA673ABCE63B6B6FC357BBBF1A362",
- "ciphertext": "846E2631110F587BD6F2E019B8385A490F5B01E1389F",
- "metadata_key_hmac": "501FDF96FE16C164ED5CC86C68CD077855490CFBF23D6E33E1207F98F2B6C6FF"
- },
- {
- "key_seed": "6D086EA32423D3814829003D2A4B80A3CECD9806E554E770769CC2DF85F17B25",
- "ldt_key": "D1ADCC0ABD0A7676AB6F624B91EADC14FF103711E95F61FF3EEBEDCCDF6F771472EF0B6DF8C1A4148D740EF7CD7C74D39E114DD6C8223F628A4AB1D7EBB1DC52",
- "hmac_key": "14F5EAB189EDD46596F0C6476051F0FAAFA98C0FFBE8AEB97EAED13FCCE61721",
- "adv_salt": "1B39",
- "plaintext": "2B2414E9FC526303C7AFEEFB88BCAF9BC6352EBF1D47CF",
- "ciphertext": "95D27ACEECC6CD1683CA568B16FB1B352D2A49E4ED261B",
- "metadata_key_hmac": "9B37A7FDECF53FC87FE673C5DA643F7CC3750BAF69AF8A459E46377E3299554F"
- },
- {
- "key_seed": "FBB48C887B96BBEDFB63CE3169BEB2C9F83C3EF8D691F4DB40C665581E609F66",
- "ldt_key": "65F098FF1543E2057A402DE0DF3464EADA379EA9C1E332C97AB38E803DC90EE811FF5F143D180D13C1216421025E8A966B6BB5A427D0E38595CB894104F9656A",
- "hmac_key": "43BFCB395E05EC1B3E0F17D91DD4142BB379FB902D623CC20F226FD79F7EAD04",
- "adv_salt": "1B93",
- "plaintext": "EE6A2392F7F711B335293E904630456BF5D8FFA11E70885B062F4DD7",
- "ciphertext": "4C0338F081FABCE8971695F79D1A50D34258B7113952EBCA7CC56D2D",
- "metadata_key_hmac": "7F8D64FF7F7CE6F8992179C7D46821B384102D113FA632713077D2EC2567AD46"
- },
- {
- "key_seed": "4C3068791225D0D0CE172BCDA1C834CB3F6D5A3EB3A8715F091241506F9D4FFA",
- "ldt_key": "3137D6D9EEE8A4534C7EEAE2AAB3546C0CF9CD596393C9F6868D05ACE1CFA0AD6903A5EC10536DFC9CDC875C777601647452E5F77CA0C4B61371F4D5346C408D",
- "hmac_key": "2FE9676B4AA49986EA5DA2401C133269B786317D646252D76304C6F054BDEC2D",
- "adv_salt": "A13E",
- "plaintext": "B1327C0315DA8E72BBAABB0FE86A8742",
- "ciphertext": "7E6507EA1FFD3BC7DB35FC4592BF1AC0",
- "metadata_key_hmac": "9540042EFCA7FC661E337DE0077115880ABD2CC39A8B5BEE17C2A5E622EDC1AB"
- },
- {
- "key_seed": "4DC6D9D1C0BD2CCFB35512AAE3C47A6EA53F01D531E19243E8E34DA7239E6910",
- "ldt_key": "085F9E2103793B6A062D69718245D6123E14DDFD370EA9140BC977D4B3AADC7A17E0DA21D9D32DC4D0415ACB0EC38787F9A92E96827576366BCB453C47FD3B79",
- "hmac_key": "C2B5F83A37BB2B09C48A4B09A030ED89DCC7352A81296D8D25CF3CF3D3DF1915",
- "adv_salt": "9365",
- "plaintext": "7498C00FB8330954C9AF29A70172F609D87ABBC6B4C07AF2542A3F",
- "ciphertext": "51BB7A9BD05CB79A9F53C16AD3ADFBF4FC7ABC6520CC165F5CBCE2",
- "metadata_key_hmac": "2170D9F7E820117052B1892384C5EA49850C672D0B325B02D2B920CEF51D50C5"
- },
- {
- "key_seed": "2E93A996FD7BA54B6E223913A6424A9E78C2BF654660D7A101EB60106F6E2D34",
- "ldt_key": "086D83C6B9EF677F2FF0751EBEABCCBDFD3CC5AFA4B19F100BA9C5BA1906858AC5B0ECA0CC49BEB013199F658366EBB40D58F42A0CABE9C90A9B6A41D2D4A8F1",
- "hmac_key": "81E7CEDFB01B32C2F1B57082D75A594A791267558ABCE8A3652C3BED7D1FE201",
- "adv_salt": "9B0C",
- "plaintext": "0CFBD922038FBE12059BB9C89566EDE98C94662754D0B5",
- "ciphertext": "95757F09585E76F32BB65EAD5ED22A83C1654EC08290D9",
- "metadata_key_hmac": "323A8A88C47EA852B343839D8234230A847E954D4BAD825DE2E22B2039A1F566"
- },
- {
- "key_seed": "A741ADDAC9A6DFDFC504013B902D3DF2940160E903B7D22C1EFC2B2386504A97",
- "ldt_key": "37F1AAB33A89C8BB79C8009D6A29B565704FF38641CC79C0CA09D1CDA73CAD58EC9628289C083846D764724E64763741CDBD0A5F8E75C24E28D883BEF3B0D221",
- "hmac_key": "A9358E0F639E9879D985DF06D547CFF8ADDEE0D1F1BB762942C1359706D94676",
- "adv_salt": "FE8B",
- "plaintext": "B855E6C34E803990374A952351683A3EE11A9DC9AF8B9B95BE4B77D161431C",
- "ciphertext": "DD5416F0008C369D9A9EEF4391886B8AB46C7DCD105FD186AE3100E591538B",
- "metadata_key_hmac": "0BB1A55A428C404E16494855A9171439B2DDE2BFB708884DE308F8AEE3DF9BAF"
- },
- {
- "key_seed": "FC20FDBE17A2011B670A9A5F8191190AF117822ADD3C9030969753C3AA7DD0AB",
- "ldt_key": "8A2725155600A03DAFDE9BDDBDF51D0350A6DE3BAA1210A54E09AE6D9657B7C975AEF4E2CB057DB80C24B5FBD3601501B80EDD38E4E0B6A4F941719BE8E4B21C",
- "hmac_key": "687CD66D7CEB8D59724E68FF1EB7602C34F19FECDD9BB41966C944CC7A1B0769",
- "adv_salt": "63E5",
- "plaintext": "1FFF9123DCFDA90C84EE36692CC1454675E8621AE5DA6A65",
- "ciphertext": "CA92DB91D551BEFC693C508A10B256435AFCEB49F0FE3096",
- "metadata_key_hmac": "F544A2B9F0207AF8A88E47FE408E926331D448C94504F6100D59A1AE6CA95BB6"
- },
- {
- "key_seed": "686BAE3B084557346B32DF983153F4F1C3233B975244D358FAE4C9651B66DFAF",
- "ldt_key": "DE80CC5B3AF1318B189DBD54E27B0DD9477E0D6A034B057E69DD1CF029DB2C0750AE67B47333C142034CEE7B2A68885690B109C5E0114CD165D2C4BF57200056",
- "hmac_key": "BC7AA3D96F3E8688DE2CF939F0AB6B9E5797F0717CAEB0343A35E2D0ABE577F4",
- "adv_salt": "A0C6",
- "plaintext": "1DB632F5463172CFE9BEFCB1D8053FA2CE49989688",
- "ciphertext": "3D54D60D010B56FDC56DC5AC1221BEE7C98FA6AA66",
- "metadata_key_hmac": "9B6D110128D2868EEE1E539F9867070BAD300157F0F9F7BE79E4A3377CEBF699"
- },
- {
- "key_seed": "F48CB050D56C56F2BF68C668C8995E3E1C85842BC9DAD696A792691B39D9B37F",
- "ldt_key": "2BDDAC5E9CC28E34656A72CEAD0ED9B742E0EB07ED1A62CF284667ADB0F621303A917C828AC1E48AF23B30C91508CD93D90CEC11F7765356855F9881A4CEA5CD",
- "hmac_key": "1D70DD188BAA206D12D8748DF8BD59CB49E7157066A4930BE0008EA64B2BE2DC",
- "adv_salt": "ED24",
- "plaintext": "EB7EB22ACC5DE936DDD1EFC1191E3E03DDC084E266C5F9C9528647",
- "ciphertext": "A936AD0E462B50C982065913CB0EAB81E8556871621796DDEE5984",
- "metadata_key_hmac": "BAE81BAFADA8E2D62FFD7D8920F7C3444D68F993D33E1EF8E7FD1C0103BDADA5"
- },
- {
- "key_seed": "47FE92ACDA70B97D1C8E764BB9D85DC262D3E89FF73B6D486C3B9C28210752D9",
- "ldt_key": "C0170B48E37AA9E271FCA686E30EDAA61CD32A5AE177DAD131D3510F78B89D0D090A5AF2DF4E71F0EB10BB3C12CC7990E979C24696E27B5523B8AAE77B25D431",
- "hmac_key": "B4EA8E59115CC92EB24803FDF2EBF6F9E00FC35C26350DCA68A59444F57A3121",
- "adv_salt": "5BEE",
- "plaintext": "5DE1B7A4A4CD2A2816326C21A86FAA7709CB38BE5020C3C3C4529520B2D4AF",
- "ciphertext": "B32932CA4C55F76290B1352435CDE49750DACCA224BC9A12ACDEE6273E1CAE",
- "metadata_key_hmac": "6AC40E38522B09F86B9164EC5DEDC982F5D382E11BEF43C38BF2C067AF0EF414"
- },
- {
- "key_seed": "3391E3D0A6622A01F0F8AE2CCC8004516C08EB6481FBCC4704DFBD13BBB9DC73",
- "ldt_key": "046C2F962E1CCD28BE2E42020E274382429948D78AC48C4EB89623F19F31168FA47B6B58DE6E720A0138797FBF4C57D453B63C397437ECE8666D346E43E8236A",
- "hmac_key": "A1C0C56FA3D27F8C0CD451FBE60358D70B12FB5DD2CC6C66F32C174F5EC9BFFF",
- "adv_salt": "C2F8",
- "plaintext": "C37A278E7D53F3E73D5002CCE45E134BFEE6AB49850072",
- "ciphertext": "46F94584B0D4B87311107AEB7E8B2CDC15F6E26BE24128",
- "metadata_key_hmac": "48E79F8509803B096BEB4A75139582757A57080B7703BF4F95697A822C67726E"
- },
- {
- "key_seed": "38B9DBF9ABDA33704A2168E9BD52F90E337302E3F7E07F4B0B464ABC614E7430",
- "ldt_key": "7AD9F3D9AE327ADBA9CECBC5F94DEF3AC7CF40A4449D2DCB84CABA549B0D36E7254C5C6DCEA577B897095E7B4EEC9EA8A3DFD24EB0EA09C6C51725320DAF2E89",
- "hmac_key": "B5F3C37B210937B2BF1E6A4294C86FDD6FDEB026936051AD98004FF6007FD76D",
- "adv_salt": "DDAF",
- "plaintext": "E03C3082240189D29C59621D198725F8DE880517518F382EB96D",
- "ciphertext": "10CD66A54174A7E413301E4A4E92B4D94B1CD73C76835797E1EB",
- "metadata_key_hmac": "880FFE60BF390EA2D88F0B22F71D9E8BE4B1C2F856809E6CC5F310DE53FEE644"
- },
- {
- "key_seed": "D191625D4D507328FEB93F5C2903269007E585E68E48D7AA468BBB2C8E42B2CE",
- "ldt_key": "0CAACAA6340DD428911C41F2450FC15545B2F08B3EC034F3E7E875146F2A07DD19D2C7773C26939A95757D65774142A1D3A0C634F23E4A420CF65C3ED854AC96",
- "hmac_key": "F31616B1820AAB2E7B2FC8ABADBEBDED259807E17ED665F589669EA1321CBE59",
- "adv_salt": "E47B",
- "plaintext": "2F241ACC16ACB854D72C3D54B5D26D77ED3418E92B51502928AE77A39B",
- "ciphertext": "25449D1203708D50D30923F1F8B59DD9E6FA2CE247D93770E876598985",
- "metadata_key_hmac": "2D8256EBC845953D61FE235FCD7F11EFDAFCF41B293A74ED235219335B77D943"
- },
- {
- "key_seed": "BF5A6418C6B69957F5DB9F398C443830E9EEB83FFC7BAC667B13FF7A26906ABB",
- "ldt_key": "5FD0795789FFF63B4CC94254E05BE3313D60A255BA212AE730CA97708DA619325EE83EEC295B95FEC20A20F38BD9C24C0F6BBFB8CFBD6DF2F023F9EC0C83E6C6",
- "hmac_key": "D097551A0CB465F2DAD0E07144CBC511BEFC216FC7CB2158CC6EB876029CE17F",
- "adv_salt": "2030",
- "plaintext": "9CEE002954D084AA2BE8313064E2E885E7072D24",
- "ciphertext": "887BCE7C97F197BE375984B06DC80886986DB0FE",
- "metadata_key_hmac": "E132320C8132C545DF1C811A26ED663A7DC9C4308741F6326D8137A1A496C768"
- },
- {
- "key_seed": "C69450316ADB438F3E3770169803B49AD2F7DBECD7C80D57BBAA416B7B577C5E",
- "ldt_key": "CFDBC2A26AE39B76DC6194DE00B651363EF93E28022647D193C90CBDF0EF85550BCDF0092BF4A3F1EA7DACE2852851AE2785A6F1D8C674D4039A866FE794962D",
- "hmac_key": "9F3133A3629E3924A829B2AB91EDBA4DFC1624CDC4BD50F58AC6FE88293EE1B8",
- "adv_salt": "AB4D",
- "plaintext": "DD2639454D2EB8E10486C8EAF591A5ADDC1DC329BD493C8B451559B98CB7",
- "ciphertext": "C3ED01D3C97D88E4D2EFE0AFFB70C59CDED3DDEE93588E7AB55EE5440439",
- "metadata_key_hmac": "EC1C7765710667BB77C5C7841C49F71BC246F7D16F44ED95C2877871A3900807"
- },
- {
- "key_seed": "52493BC618AF6AA2F1A380AC1F2DDBA2ED937B11DC57B34A59B35983A058538B",
- "ldt_key": "D4932E7D729E466ED4C8722AF5C7C2C54C78F7F1BEBF518226CF5B7D0F499F05DB2815252C323C6DFA4386EB9A83C3CBE18125D720EFCEDCA6079E597427D5A8",
- "hmac_key": "B95A0460351EDBC7B7DEFBF4D7A593EC0DAA34223DCD8DD27403F2E9F1E31433",
- "adv_salt": "60D2",
- "plaintext": "52D84A60CB537611D34467DE41AC5902DD670E91B882539988",
- "ciphertext": "994C6A1F16A95B0F362936579B2CD020680F4083987F302D6B",
- "metadata_key_hmac": "9DF639DDF92DAE260504072CB8A1D9342EE89C50A47FB84E7960A95904EC5A67"
- },
- {
- "key_seed": "B8229EB01E75BA575AA1DCB4CD2BC8AC322400A7F4F07CB5264788148EB1D301",
- "ldt_key": "749DB570D2483B1B6F8EB620120B14FF91A84C6074441A145C5FFB5524CBA9E4D95A776EBB9B2B6A876EBB3D6119E844763E5C2C01D3FA7E10DD820677E3FD77",
- "hmac_key": "E353F7A4F7BD1A6EE7ED475C8A02584CD00173076A80BB96D40D6775421C5F9C",
- "adv_salt": "FBA0",
- "plaintext": "045992CC7CDBF4755C1A2477D51C3F23781ECD337548DB753AE124BA1E",
- "ciphertext": "A0E1F33F23A5CA57D7DCBA88CC770C55D8EC1BBC7DF974EFA10167B798",
- "metadata_key_hmac": "146376174676638B43F84DDB78052DB6AB3C0C0BBF9DC8B3594805183826D178"
- },
- {
- "key_seed": "4321B4688EC7D9DDA0732CD27624B1A12CCE1E17A77C99C17914B0AA82419F7F",
- "ldt_key": "2699EA5FF56FEC771CB80ABD68854D56FD38FE6AB6B4CC4C43DB01A63486280D91E7980882D41B3F3F0F225319F765E62C247416866EB695FDF34C756010B8F3",
- "hmac_key": "0FD6C64B002DE65BAF239D8A14E1451D49BB86C5614EC7B89B3E19D6C4BDA787",
- "adv_salt": "2573",
- "plaintext": "E1F4E8DBF9C3A3C5417C3D2F7F12EDC36EE7EB8A1AA7D140052880F1B43F",
- "ciphertext": "9ED5913A29C5DE4870226D199E60B17B3F4093D695811095896BC5D8E0DC",
- "metadata_key_hmac": "AA72421717A2E5F2FFFB4C46DD76B3B1ACF7CC874039EE4CD6CB67B5255059C2"
- },
- {
- "key_seed": "32A9AFB7C4797E2E058F7EF5B8865B78A9DB3BDCE5DAB7BB1C8D81276C2FB366",
- "ldt_key": "76CD81D5D79AD3A9C195BF40ADDA5D8FB8914FA7FD9ADCF0803294CE111F3CD94A926F9E015DB3EFA0EE7B4A063E1B9A4070F391F5F04EA784856C79444437AA",
- "hmac_key": "C00A3A044C520A6518F22D22BE38C72C6D1E5DCC4F02154EB6C8EC7A472D7879",
- "adv_salt": "EBE0",
- "plaintext": "A6100086D2E8E08ECFFB3CCF2872CA162D8917B98F8F3C2FACB5",
- "ciphertext": "4BB5B9015F6263D206C503172D8F5764B00AE45EB1021069C36D",
- "metadata_key_hmac": "162294272CB61330CFFBCA718BC1DB3E4014E35F9FFB02544E3888EDF51846FF"
- },
- {
- "key_seed": "AC352972B4F2719F04353418A2150136FA39C884173E78C3EF5056EDAB755EED",
- "ldt_key": "60ECF6CF50A4D4AB7647454B76787F4677BD9C2593CADF4E3DE02D219DBB8301F886404225B7187B8B238E9BFE991972B9DCCB925F8573688DB39B775666D99C",
- "hmac_key": "3B2820C7CDC30E8DD382CDA3821F2BF138B1052F09AC12F261ECD5210D78D72D",
- "adv_salt": "1C85",
- "plaintext": "4E45393C4BADC74193B091E29A1A779854008EE09B",
- "ciphertext": "C560A43D859C1DC898A65011021935909E5DF8F990",
- "metadata_key_hmac": "C9849ECBD12A6786A35FA3338203A2742AE4653589D39BE1DB3C06C3E46362ED"
- },
- {
- "key_seed": "B2C0F8149154C9CC46229E9C18369EBFF39F0F3EEF32B8F27E12F65B2903E7AA",
- "ldt_key": "6F9071DFA96A1DA54B7B34A12574DBB1005DAD47DD0F7F7BD03C24632726ECA6114A1D3912D93771CFFBA6FD72654BA962E9E49C544A28F428FC854C65F05F97",
- "hmac_key": "A90B7956F9F7F63A125D4602104BC6B00BE03B92165B6791D1D9C0F02A6F6B17",
- "adv_salt": "1331",
- "plaintext": "0E53F8702AFC1C5D707A55EF3127F17B4B37C7409EDCF491CA83",
- "ciphertext": "484697262B3B548012649333839EC0871F1D80B14798F1C3009F",
- "metadata_key_hmac": "3622734AE40DED11E7317E6203FEF81E2CD9EF335F1B5367EE41116F2EBFC4AA"
- },
- {
- "key_seed": "F4C380BEF6D3F0790DB12C2749B409EFB86C08AA9D577B942C528E45E6E066FA",
- "ldt_key": "4FAC464CC036715DAAE8CC20A1EB2C752F2C4F65AC8767D807D465A285AEC934FF3453FC17496AEBCB162A5445902E2C7A7BA5D04407236BE8CCFA157E298350",
- "hmac_key": "3DE1EA0A96D39ED853A9A1236CEC7362E3262BB70228264CA28EBB45626573CF",
- "adv_salt": "D1CC",
- "plaintext": "36B65E91A8BFFC7B97A818B27DA1746DFFFD56830EE6E727CF1080B8FD",
- "ciphertext": "DA3D0EC3D7EE345446C0D3A69F59392F726388CDAA0D7FA42A974CE868",
- "metadata_key_hmac": "A248A9B938D6AB6D6EEEBB4E27DA6D85FEE7745DEC464EC46D0FE23B817570A7"
- },
- {
- "key_seed": "B9C652DC08F8A504D7545F709EBC88B5CC9E0C2A86DD2051A7E9F03FD1CDEC70",
- "ldt_key": "19B7D4078E491DF180524CE8AA2A9D8CF29F821428FB669CF8F68C4B63AE2A1B3405E1CDE97F35F10086FD1943A40DBD8528D8769D269687CD6E2D0716D8FF65",
- "hmac_key": "B9300189841F2274CD6077DF4C7004AEF8968137E21935678CA34BBB7692B18C",
- "adv_salt": "55A7",
- "plaintext": "84EAE0A184F385D615CA217FE434FE4B4B1FF0",
- "ciphertext": "F1C9E103D0E74A2EE6202667FFF755398CE4AF",
- "metadata_key_hmac": "A7AF9B4A97EDEF7033EFDE386E2519656798230489248B139547FE50E5680ED6"
- },
- {
- "key_seed": "7E3904C173082FFA3626FA79F4AB98D78079DB04A015F395C4334872429D9E02",
- "ldt_key": "CCFCDC6CC91B9480177E994C8CB668685C383A2279C4365635561EC866DF07D21FF8B6F05794331FADF21CEBF86BCF2B68F6779E9F8DF5FCF45D5B983D877D4A",
- "hmac_key": "7AFE8A851490B11ECD7E94FF528BDEC30EC65B3F8BF5D27A8D4ABBE98A1A8779",
- "adv_salt": "7831",
- "plaintext": "B91B4DABDB93A17AF70C75FE0AA56B2C9EA29E1B450D177419AFD7D3",
- "ciphertext": "222B0702B74B1B19B866726FC51FD1BAA72837E3AD36A3E09590FFAD",
- "metadata_key_hmac": "CC8C4A4A380FB928319DC3B7795BC02ECE8CEA1244723E7E65DA474E71922F30"
- },
- {
- "key_seed": "2818D375E41F4BFF60BC5D400165FCD87311018B6F29B05890412393A0341D40",
- "ldt_key": "475A78B0A6F340FAFB40B30D5E1C22CE7F0FE7FF9F193E95DB87A64E90233D707D2BD91B6A18C7FBFE1D63C00AAD1008043D61227E874220246839DECD31AD06",
- "hmac_key": "05011F4F63F4DD955FF26582E8D6F40EEB1F72F6136BB741BFE66DAB3366EDDF",
- "adv_salt": "4916",
- "plaintext": "5B5CA3B4765B3EB9F28F9477F2BE9EB39ED6F71A",
- "ciphertext": "384C0B47026B195EADF7A0EB288CAF28A8A8D7FF",
- "metadata_key_hmac": "680E2C19C42A2C4BB032CC5855B21C19647F2196043BAC75060FD7BC852288A0"
- },
- {
- "key_seed": "293B6D7B61EC04FF8B6324CDEE0B4215696B69EF91947293856DF8AEA7A33120",
- "ldt_key": "5748E0A5E16A3506C5C6037262324C47DEEECF82D89014898F42168F26AF064FADB35BEF373E83E087F47D6AD2E3ACA442A6A2A90D04AC13A9D2791EC60DAD05",
- "hmac_key": "942DFA6F88C0D4A8CC126C1F4E596DB791700F51238E73B6D00329B3100B72E8",
- "adv_salt": "0B70",
- "plaintext": "1F2FBA9E9CD01EE3570D9CFC677639A0A200083B47CBCCD9FC6367C6A31F53",
- "ciphertext": "BC7EF3E920713AEA138D84039C99CC8FB42920E1158A1FCC287B19F1EA5927",
- "metadata_key_hmac": "BE4555125280C327F2AB91B5086453A69D265BF882D38F241757828021703753"
- },
- {
- "key_seed": "D0086215DC791940C22CA11AF2E211656608183B727E634CD45E2EFB02DB4BC3",
- "ldt_key": "747DC06A5CF0E6B3544AD105C6E4646EEE1DA9C9A85A5ACF19FC4800F68D6D0E2B41D24D9F955626FECD92D44325703AEB5ADCC9EDC4FC4146F736ACA8AA1ADA",
- "hmac_key": "1DF706DB07F3404922298D733E284C95A59D0F5DD078E2053D0FAF9A17AF2017",
- "adv_salt": "5F49",
- "plaintext": "724683E15CDFD3426D6AB9DDE6D0D125C8D5",
- "ciphertext": "A7E55EB6D540B0D4572851CD336C4A66F7E2",
- "metadata_key_hmac": "DAE761B6D5295D790AF8C5422DE5261E152041F5AD42A0B456D5AEE6E7D1F354"
- },
- {
- "key_seed": "A71F8F6908A57048100CA20664D9910F1706B692337F605E381133A6DCE2CB0E",
- "ldt_key": "8386F0BA6A123E4E3B0B20F9EA2986E63BC56CA98AA781FB7847533180F9BDDFD399598724282AB64A4040E44D149075984FC3239FC91980044E5F65B35C4E00",
- "hmac_key": "430EBC4CC413E3350E61482401A1D06DE152759DC4A54162998B866F768CA6D2",
- "adv_salt": "C5E1",
- "plaintext": "3EECB162209101704CED7A0D843B8E9B7E932B0F82C4A9FF23BD164D0FFF",
- "ciphertext": "1C4E76CF6ACF99EED45D731A7D864E78709F931147BCB5005E47382B4160",
- "metadata_key_hmac": "4DD68F166C06B162AD8F84C1FF167C19AB8A596D50117487AF26E338A4D847A3"
- },
- {
- "key_seed": "3B98434E78544A66FFCED9EE8D7B2C063B7ED7AD7AEED29B5559DC39AEA56DF1",
- "ldt_key": "B953070D2CDA4353FE4E1B108004F1BF76D7CEA08019C64C888FBF702F67630B0500A7FC38231E59154786DD476C525E89F0A5BF95A1F226E20AFB5B7A856D10",
- "hmac_key": "B2403EDD29D4C66C0E6333FF49EF200F68EB66E9C3C1221880849418ABD71DA7",
- "adv_salt": "8507",
- "plaintext": "1AE5221F2BF314C8E35555188C6D9C0E48A446B5",
- "ciphertext": "7DED8D87E18E10496F0B58014B68CD2072C7890C",
- "metadata_key_hmac": "E0FE0BAA12BBF15AB1B0D5AB48389D52F0846C354D34FFFDEC80E2B3059CB917"
- },
- {
- "key_seed": "70DE3AB2D81F7ECC3C8BC8F4842C17E71C4B4A16486C9FFF8A2A08BC2BB45F61",
- "ldt_key": "D4E93D2956B9A53A5D5504A84E0B34CE48A949DEE52C821392E63442DB5973610BFD38E50FAEFDC2FB2764C298630E32B7BC2687F67F5C43773BAE4C7691D087",
- "hmac_key": "07F6A1092DCE7A0ECC5A25B91770F6611A1B259E1AEF307B7CADF418D0E7BEEB",
- "adv_salt": "DF66",
- "plaintext": "5034C0167A1F866508665B737DB926E5B7B2FC134B10460E9C59AA",
- "ciphertext": "AB4E6DD75D1D2D70BDE86441C93C6419B0FE469AFB22174D8832B2",
- "metadata_key_hmac": "F6EBDDDA8E24C585D980C9848AC5B575B21ECBFFA7E42C29A0A32667C776DB51"
- },
- {
- "key_seed": "D6070E362975BE4208C68075DC58AEE151560F34467C339DE799AD1F4F89B43B",
- "ldt_key": "F5B3013F1D2C809CD5972C4FD54DC52AE3D2CA049ACB9EFBBF415A6D70945B574550A5D69B47579426D3710F2C4C0C717EC23C7B59EF74CA3BB7FCEEFAFC8890",
- "hmac_key": "FA77A236AA7006B1CF1161E8C9FD37E9501067EFDAC1F05FF7AE2C48FD5212AE",
- "adv_salt": "38C9",
- "plaintext": "4B7F78A6F253F71F7BC3BCA63706E5B3A87F",
- "ciphertext": "D6743B0FC3C4849528CCD024E658C3001164",
- "metadata_key_hmac": "A1FD7AFD923C5E086F5EC7252ADACDE857C43743CF3F6369B062191A779C7174"
- },
- {
- "key_seed": "06D4CD5442C5FF74E3A72B644AE3117AA39C58AD5D6B2259A95279BD4E50ED3C",
- "ldt_key": "5FEF4BAFF726D4C0649FC5EFCDC7D4C7021E29AE3EE9F300599D5507BBE822237C487414AA54418DE0DDC35011E8EC387B2FB11EA242E6E9136EA550DFDBD82C",
- "hmac_key": "0C520AA5513E4B47457DC6A788890108714C05BC2B949CCD3437138C6F1C593A",
- "adv_salt": "4244",
- "plaintext": "56CF46926F1B3C2DDAA0DF35E126F2E60250",
- "ciphertext": "C5C14C2EA129C85575F9437DBD36DD9640FD",
- "metadata_key_hmac": "0BFD27EB29F997A790FDC9B951BDE7FB07F18144C0332F34257300621D6125A5"
- },
- {
- "key_seed": "25C7513D18B3B943099EE74FA3964B6D3AF65A85BE21EC1A493463F641B0993F",
- "ldt_key": "8892930D9E760904A6B57635D9191051C15D81432176129121DCE1D726FFE389FA1AE258E2782DC2536259783BE993C768F6CD19C5D42AC705973B9866F965A5",
- "hmac_key": "6A22C2CEC91B54BB1DAF7025CDA3010B73085E5F0207918C10006CC02E1402A5",
- "adv_salt": "269D",
- "plaintext": "86E9F2435157AB4B5BE5DAAF51D5E59840D0994CE3CE0883D2611924",
- "ciphertext": "52EBB65E85716A5FC5F364A92C753EFD030319E0FAAEC5F59970A5BF",
- "metadata_key_hmac": "B5CFBF695F95A5692CE9E44F6153823507BA69CD40349D9F5E2EDAD8DD23F21F"
- },
- {
- "key_seed": "6A3819092F4B9B1D287559B3333DEEB1A5C454C60AAAC5C338C859CE8A0EDF1D",
- "ldt_key": "965901C57078EFEF917F2117AFA8D10965F1AB7688428AA0EBCC2CEC5F4005B8CC9F9B5F714B07BB4544F6A6EC49DBA71EB99E23ED9861E4F051B0093A649795",
- "hmac_key": "A014E29D41094A6B2AF29F5803B09958F3B413724BD1DDFF9DE3A6922F5D33DE",
- "adv_salt": "FE52",
- "plaintext": "3E338836AAD143675865928DE46D0569B3293938",
- "ciphertext": "0CF2BBFACE17016EB783DF024A6B93022F7F8F8B",
- "metadata_key_hmac": "5C921A36EF9A5BC58E6A89FF629514312D2FABF72D0CB4EC838D0FABE0B163C9"
- },
- {
- "key_seed": "A3908EEB18C7B14040AF677D936F841FE16B743A3B5D0C9B7B7437FC4A6BA882",
- "ldt_key": "537B347160C78440DFB3BF95E7D9DE916E6B25B20A74895016AB2BCE4279597C46FE35F9308C9902A20E37CB2AD7CDD563CDCFBC31D69B7723A99F279EC4768A",
- "hmac_key": "51F878A943B59A2E31B968AE9C07B76FE066AB3503583DEA9063F50A30F4B2CB",
- "adv_salt": "16FF",
- "plaintext": "720F44EFD5E3E49F33982B9DB21065E4D810DC5DB39A1ED0",
- "ciphertext": "AB7006CA73C4740348DE94EC6B3FF8026532551D8D007EB6",
- "metadata_key_hmac": "27B116068950B115B39B2A68FBA268F3BD2CD09D5863D68FEAB33BA039019644"
- },
- {
- "key_seed": "BEB5B05E7982F57E486E70F4D06895FC35B75138987511BD89195A92F0D8DEA1",
- "ldt_key": "923863B15F3141EB2524D2302D363AE74E36E6349D9F3A0D074D098D8992465151D26913D8202E7DC45F057F02727C3DF35861D861CC31F87EE212DFFEF9CA5A",
- "hmac_key": "3B6868C1DF85C268AC1F34E6AFDF5F6872754B83BEEA87E5077D50D5403D9E6D",
- "adv_salt": "305D",
- "plaintext": "6BAC0E6CBE03B0F7C351156BBFEE2B9D5B",
- "ciphertext": "9B360B3073625C1ADA54FFFBDCA6EE7B89",
- "metadata_key_hmac": "14896DA42B1F8353A2ACF69032D651A852D40F5DE20B24EE990FE9D829687E91"
- },
- {
- "key_seed": "6A0E2C7C7E761BB93AD9F18C39AFB835754CC36D9B6D0C37007EFCEDE3E194AF",
- "ldt_key": "36F4D0B92C00D28AE0879F99AFC50B60F00CBEB9CDD6CFE59BC27E20312F4810482DA55332D168978D6BF6EE048CA21FAAFE115BC307BF91508F8FAF917F9110",
- "hmac_key": "21C79D059AAB19B891D0D463CBECB7FA1C0B893C04B066E23CC1C7FFE16A5416",
- "adv_salt": "88F9",
- "plaintext": "108C588C57004BFB98000921739695DC68CE92D05F9252C423E929A9E2A66B",
- "ciphertext": "F1EA3A73A26E0ABC68C096B43E5EC256CEB7398E705398999EA573EAC9E4A6",
- "metadata_key_hmac": "B3D5C50176029E28512FAC5E685B8420890108608BF4F7D019C627ACF309C4E6"
- },
- {
- "key_seed": "31C7CFADD40759B0E825EC5DBAF0931812F7E2B240F3FFACCCCB0F683D22ADAE",
- "ldt_key": "6D174F3A9D35C18C5873FC6C0A78D804F98EF4F131930DBE7A62C599ECF5432F58A10C2300E5B6428E4C0DC7E0510880DB7AE4FFA2791F6276B4DEFD8D5141E9",
- "hmac_key": "A0856C106CB1567EECA6F20E17038971EE7B56C67E0A91F3FA065AB51A2D1ED4",
- "adv_salt": "1EC0",
- "plaintext": "874FB6A79D5FFC5302E140950B2DC842FA9797D2FB6034DF74EA8A5373",
- "ciphertext": "13ACC4B28FB9086DD45C48D52719129E973E4C4C443C08563A52DC814D",
- "metadata_key_hmac": "273BCAAE09C489A4C8F388958D8B4A9876D7C6BE02D0DE29C75EEC96A608436A"
- },
- {
- "key_seed": "5956A478D8411CA8A465158C2B3006149908F1EFCCBF8990317F20999AA4F70F",
- "ldt_key": "4A4F052F402D0CB131C5B4FE1131AA7FD5C20ED9C2E748FD0EC1279F75858D47D648E5C0A457BCB65F222B3F17EAEF11940CD46A3A94805E51D11F16826ED5B7",
- "hmac_key": "41F71CB578DBB33D3F003E8D78DEC4CCD6917236F0D9A0AC02CABAE06C2B5D65",
- "adv_salt": "6BA1",
- "plaintext": "FCBEC0CA4213B4B37E2DD6C8012AE01DF1E1242AA434A148D359277E62",
- "ciphertext": "1E9AFC79DE49F4ECD3AEB564FFE40E4EA6A5194E61ACA01D8A9E9343BD",
- "metadata_key_hmac": "BD3C3DBD20B210AFC2E33546377BBA80BC72A87EDFA13A34F8B5327C44834223"
- },
- {
- "key_seed": "F148AE1510BFBF000897FF10BC5B28F67AEEA16C62A21EC917C25303DED409D6",
- "ldt_key": "9CD5DB4CF2C2AE6147962770007D6C55BD3590B36F78DBCF116A8B57231DE71C26B023060860768F5F74E6067C05E3CBF3F06969F4763D3D4C40AF761BFD2292",
- "hmac_key": "5C8B202DCAEFBE48669513A0A1AAC66FA6DA1E5C21442061B1A88E226C8112D8",
- "adv_salt": "F331",
- "plaintext": "89AA70C2B5389C5D1D1FA5B79BA158237CC15347EE30F0DDA3EEB2",
- "ciphertext": "8DD3EAE0D868337481296D1A5E573B37FAB61C545D24D6BB623EC7",
- "metadata_key_hmac": "221ED78ACCF95FDE481AF3326411BF7E818A218507C63C819866ED56385DDDAF"
- },
- {
- "key_seed": "61600C7568EFE18CE65962F07F83A858A4CCC4F2F8770E6A86E0AE198FB1C771",
- "ldt_key": "64803B5AEB725BE7E9541A7E7B2EAA9E43C80D6DE2A8700B89F48AC6AED908A894535C56B5AFEF66A3DAE9345ABA78B3E6363B81CA0BDC4F08809C32CA0165FD",
- "hmac_key": "B4A02866B9F951B61A74FAFA06A865D5B1B6251D26A62394FC83AFC4F64706AB",
- "adv_salt": "4624",
- "plaintext": "312025180184B7C1B9AC2ACB4CF48AB26EA6924F5423AE7DED",
- "ciphertext": "AF5C47FB013B6AAE01CD52207430D4506DF7E00927A943FCC2",
- "metadata_key_hmac": "7980BB8D1F4751C04CBF6C5D4917B2CD6B6B9443777F7B5486284D0A47F305BC"
- },
- {
- "key_seed": "F69E622B35584B35602B42740D4FFF8DA8871A984176CCDCA91353F9D22DB315",
- "ldt_key": "05D4C4E9BE27F96890EBBD83FCD4E434484156EF823501EA28F92CADE68E564D10DAAB07D442AC8591349EB228E07AE51D9F2B302F6EE44892D65423F0D467DF",
- "hmac_key": "1C78A8952309D55F09B6E806824F082EB42C1548EA9A860C5ADE79B058C223D1",
- "adv_salt": "A33B",
- "plaintext": "6A417988704D975DC2DDCCD8823986C1F4C74B288FBE72EB57",
- "ciphertext": "C37A68F6D2B29B640870300FD08DD35A5F0BC438D6CAC897C4",
- "metadata_key_hmac": "601E61D942E76B8997DD60775AAD1729D85AD7337F18174DEA7D67E3736E694C"
- },
- {
- "key_seed": "83E3CB4033F12083313C134BB30C47F5EA0FF6A00727A3F64FC1AFA040B14E60",
- "ldt_key": "8A4C959D115BE5FFD34936F1876DEEEB0836CC11B85FB29E4D914AC59D649B4C7B1BA55993C454572EA4F284718A56B2F66C5FB7BD7A0584E7206525DEB2249F",
- "hmac_key": "2C4481D23836DAF9AEF1871899359EC2996F322425E4EB126CD8126A11568524",
- "adv_salt": "66F1",
- "plaintext": "8A7AAB07B16F67A50F62A57F62E7604D9EF3DD",
- "ciphertext": "DCA7C698E366351965619E854DCE96280786A7",
- "metadata_key_hmac": "1C17DBBA079B2949E4EA054E6875EDD41A8C6BFD7D0E731759549835EFD43ED8"
- },
- {
- "key_seed": "9DEFCDC08EC6BD9D9D5EE8B4F1ECB0D080E80BA131D8E88C7108775B8FB1AFB5",
- "ldt_key": "EF241E356B44D5FD66FE56F10AB825DFD6F80A850360A0A97427793B575E001070BED7C33D520DE89C249F896DC987FCC689293F469D0264CD8DFD92E3FAB2CB",
- "hmac_key": "30FA2AEAA17C3A9A9E01139DE85BE7924C4212D382A2A924593B0772C84594D1",
- "adv_salt": "0BE3",
- "plaintext": "2B35B8AF25D51FD081579D2CF3FDB0B66DFF",
- "ciphertext": "483147378F66A935037F06ACAAB160429969",
- "metadata_key_hmac": "613573DC01B49019ED0F98559D39313F00E8BBD1B8AF91F23ECCE7DE5F535751"
- },
- {
- "key_seed": "EB477CBD2CC5A7CD961412673019D66F91FA55E676892842B8363694A780700C",
- "ldt_key": "066EA314177A5DBE76DD89A5E855E790B63CBF515E008D9D0A3CF24BF849735710E76B8453C0ED1F2D77C78245F022A6235E2A6760A53089110D60F3957B19CA",
- "hmac_key": "60669EA78CCA2BC2828878FFDAE7DF7BC3F0F360A97A6806C1C76D19C90DF5B7",
- "adv_salt": "2557",
- "plaintext": "D35F9D849F3EBF4072F9E27CF2C8B9B5C97664A06C7E0360407A260941A00E",
- "ciphertext": "FB6E965A8D084308748A5E70DD000544C2CC8BB2420426848DF29D09A57E4E",
- "metadata_key_hmac": "7DFB8ACC1E2547D2D9DE93FA873D03EEB1911979388FE21B69C50739AB45043E"
- },
- {
- "key_seed": "74AA682518382B6E3616DA0382721CA5E8DB50F030A50AC08276969E0562F4FA",
- "ldt_key": "B1A8CF202F4B3922456528E5566AB7E71E5C2A6B7FBC65EF9CF030DFF5E258DB44E4BF2D3224F434B20A14FDC7384F5EA87969F403A1308719935BC0CDAD0FC1",
- "hmac_key": "6B86101900B15E6E052900939C8FCD3B7594904560FB2C99699C5BC0AE78676C",
- "adv_salt": "3895",
- "plaintext": "20325082990043331BD2D3A80BB87E0B",
- "ciphertext": "96DDD4BFDC23FD460754FF6468E7C332",
- "metadata_key_hmac": "742E4068B5CA2992EFAE77AE5D6A85FC2EE4FC629048F57A7C113CF198266E8D"
- },
- {
- "key_seed": "9A26B82724E2E75F688219290A5E71306259FFD45358CFCAB56820AF0AB84825",
- "ldt_key": "716EF3C6A8E6D03AC8B48FB34352A3DF2BF8E585D3ABBC219CCAF7B724BC9F4A910FA552C9A7DA90943F22500AE0D795403FE3A39F5E06BF1CE082B82ACCA6D5",
- "hmac_key": "8740E6B8E4AA733172A5C1D7BCCC2E38019460DF4A145A16999BF7FDDBBA6465",
- "adv_salt": "E247",
- "plaintext": "2C99B82779CBCF25E5023FA300044F7BD8E73711D183",
- "ciphertext": "1C4E395A87CEC587FF9978A6C3839262C9CE2B1A4383",
- "metadata_key_hmac": "36722D3E0A836A8E7A74D5193128D3BEA3503688DEEF566DDAFD1090D4A422E9"
- },
- {
- "key_seed": "2372AF6AEE19D862907446970241429B0212F31C1531817FAE55B789DCE83419",
- "ldt_key": "7CD870141005EB628EEC6185B4019F0F038CD76BAA1B559ABAD2FFA079209609537914652B3FF00ABDECBE8718D0890117A3B2472D3CC0EB72F04D0FA7083961",
- "hmac_key": "567E5FE57EAF46A2E2C780EDEE97035315185FD8956BA5C4D76A78853663E746",
- "adv_salt": "E9C2",
- "plaintext": "2693825DC42C1DCF2A10AB81D9365BF891BCE6006C2DF0145F",
- "ciphertext": "61CDC03B68C66D50E063FD4C8F647877E9D3252584AD713978",
- "metadata_key_hmac": "42BBECE7CD1856970D01DA3E8734A65DFAEDF457DF1E72CA3599EABF0C22C41F"
- },
- {
- "key_seed": "9D08404ECCCBCA0EE51E331B6D696ACD3C7176999823E2C7EEF4302FFA9BE0B9",
- "ldt_key": "427CAD8F30A04435924421837BAB322F768179FBC4B784038984F8DAAD0BB82ADCE01C12C816A12BAE4623641BF1BEFBE1BDEFFFBD93D4BADDB001FE1C50337B",
- "hmac_key": "EFE1F944399E5F414382AD4387C61CC384B61E99CC0435F3096E942219B91366",
- "adv_salt": "B75D",
- "plaintext": "350843181BA9E2B6ACBE63B7BA7D7D150E74",
- "ciphertext": "5E9934E69293271897730ACBEBB03CA6FE15",
- "metadata_key_hmac": "2C1CB1BD3BFE989FDACC33EE426239A738C73A16173CC80D7EE05EC3F8404374"
- },
- {
- "key_seed": "74A2BB7471A0592D8DAC87B95547A1C9A3E8CB1AC308DF345A4DAB559034B5A9",
- "ldt_key": "443C06E1C7F2B1752B274C23C289694FEE4FA80FEA17652F10E02AFA2E2C2F36735AE72D8D83EE6ED574F60DE7E0017E4847784772E8BB3E2FFBB191804DCCA2",
- "hmac_key": "09566FCA537C7633AFAA67AAD2912B0D97C96CEF220994AAF0A33D2E02BAB4B1",
- "adv_salt": "59FB",
- "plaintext": "605007ADD735AFA8D07288AD1667877C7F33D8B574B3664540B3119927",
- "ciphertext": "C398C214954F7586A9E3ED39A942D48D42EFCC15D259C91A0C17D390E0",
- "metadata_key_hmac": "E7E896615023D1769C951BBBF61C102E5A99FC79CA90A9EAE14FB4D3ECEC750D"
- },
- {
- "key_seed": "5CE66AB96688C6F777EF69861F715B7220C045147C30874900DFCBAD34918F25",
- "ldt_key": "E7E24A6081A7D415F04EF19C540844B29837EB7AF9D97356BCC4AFB6CDAC80164A25448A12FECBDFA8E35B285A383B1BFE20E0CD0606E4E8078DD306BCB39405",
- "hmac_key": "8DAD5A1D48DDC9C8496E5861514833D1B84B19787D4E1B40C78754B2EF047152",
- "adv_salt": "3544",
- "plaintext": "8862C2582FB4EA240D177A750CEF79C34B706E78AC",
- "ciphertext": "DA89939D9BCDC1C14D85A5DC0A9CE0626522AE0E8E",
- "metadata_key_hmac": "6581B9A1D1F0F4D165A0167E18C7295A731DC235926B8E410169F1C63A4DA4E8"
- },
- {
- "key_seed": "EFC89CAC472E5F29C19909114C58ED36EE6CD3ACB421DF6E8196036B0BB2B26C",
- "ldt_key": "27260C19A758519766A2524EF2930AF8312BE757975561E9C850CBBF9EAC6BEE0432523725E7DF2B0186F95BA26B59AF8F773FE2E412D28646ADBCAFBE48F2F0",
- "hmac_key": "D0112796BB95B093CF956682B6EEC9929491F2CAAE8FAD2C957BB561F178DDDA",
- "adv_salt": "4B32",
- "plaintext": "FD682E2BE832CBBEEB345A4D38B78BA90AA637BE16BF51D4F9CB96",
- "ciphertext": "CB4790894F1FBD9598C560CCA62F478DC17FFD4A1DF3AE520C6278",
- "metadata_key_hmac": "A2BCD15C733F585645D887233A53E42DB824AD128F0BA0D979ABDBDC8EB376C1"
- },
- {
- "key_seed": "1C9FB26139981EA626FDE6F56495710AB4F459F081BB68157D0E15818B85FA7D",
- "ldt_key": "9E89B84362A0AD1CFFA71520222CDF3797CB0CD27963747DDDF30C64CC71471DAC44A480099B2CD48DFD7845A9B62451FD1FDACEE14E092A367B24EE1DEE3E06",
- "hmac_key": "B83A1B3299AF327CCA3EB519EABC9024FADF40E90F73BF2F6A9B1282B31AE24A",
- "adv_salt": "27B9",
- "plaintext": "115B2F632D6CC15F641AB023B8A19E8E9EE3",
- "ciphertext": "E19E55724D76166EAC48D7830F00605E1B52",
- "metadata_key_hmac": "8C595243A2DEECF05FCB3779E5B65B89437FEE12917C70243244C07A73534FF9"
- },
- {
- "key_seed": "12BE8D40B5A27A6FB578010630144DB83ACE0883724A4F521340E540E2E0C68C",
- "ldt_key": "89B8F5A1823B9677AB985DD4DA5A16B24CA4DE066A0973DA3C37D0BE255AD0BDD05A747766F147C09ACFE92F89E388B5C27883434D9E4BD4C67A4E30955D4C8B",
- "hmac_key": "7EEBC70EB7BBE030B3010F8C6F9BA6FD1808D3740F883E4739AD3D3BF91C0654",
- "adv_salt": "1190",
- "plaintext": "04B822A1371E8C9DC26A697DA51A9C77",
- "ciphertext": "2DC428ADB7F503967850DB31047E887B",
- "metadata_key_hmac": "B9F5FF9D4B7C4C7DA4F63598A9618417D1852E7CC85CC86CCBA8DD0497DD8D6E"
- },
- {
- "key_seed": "F37D48DE8C8C1004B7F9551D590293B45DA71C45C4EAABAA1EFE2F28963D70D4",
- "ldt_key": "11BC252F985F1F29B94903783DB6F8DFA80B41C13819507E5B4456294C04C5408AE4FD21EA7B5F2FF83CBCEB8D623BB5A6213CCD8DEEEAC85B97DB39031E6A04",
- "hmac_key": "94939EC6BBF5833A6A2D54E4CC76A19CE4ECD27443B58465133DB9E8979AFDB7",
- "adv_salt": "CD14",
- "plaintext": "6C8A96613B5ED22D15BF5505318AC7B6B72F4E6CF78E9228",
- "ciphertext": "9B0DC394A40DADABDE9454BF83DB14DF7683BF91FD6A6BE5",
- "metadata_key_hmac": "28BBE4B7634E6DB87EA9EE4CB6D0D02824FC0D02FE169EB277050E877F5325CF"
- },
- {
- "key_seed": "30AFA37FC0EA499F56BD5E3DBFAB8EC4F8831EF774EA8B470D06711E2526D17A",
- "ldt_key": "E738F03C91E9651B4798C43013DE639FF8BEAE84904EFA3B3293F52B6DBF07335F32B00CFD3D0108EE0C05EE0EA18D12ACA8FEA0B04EB082D0421F1EC93CA891",
- "hmac_key": "A6E71919A74F69E525B8F6E601294484F74399B8343F4A3EE4C39CA8E884C9BD",
- "adv_salt": "9126",
- "plaintext": "49B90ED5973BA948D4AD48CD58B18FF9BC0AE8F515",
- "ciphertext": "47FA6B4679CE70CED6D4D459BDE5A9D70CB55F1D73",
- "metadata_key_hmac": "A482A818936CBA441D8002C992A4E01FAAE6CD28BA441F635D5A2FDD942C90BF"
- },
- {
- "key_seed": "8528A2F34296E3729E50E56A55855F59FBC902DED9D2377DCC39BF7231F11172",
- "ldt_key": "0F0E76C4E3E7BF50E7D52E2AA6693419CB63824E94A0D4752D61E7FEBD0BAEC9939063AD802105C19BF9A00FDECB95CCE41E1DC198A8E496CC9AAAA8BBCDF7F7",
- "hmac_key": "DF969A9D68140F537FF7FFF16472AEA113894FA265C84B75540C207CCF6BB85C",
- "adv_salt": "105B",
- "plaintext": "4D85C3056EDA3F063DDD092586D497446997CB274174",
- "ciphertext": "4CF52656457A215F9D44683B783DA8D0D526EA42FBDC",
- "metadata_key_hmac": "850891BEE1675AFC5D85978754AE1A328E8AB5BDA781B33C9614694FA65B168D"
- },
- {
- "key_seed": "9D0D63B34C39D97396F1D4300ECD6F1DDF59EAD5CA6C91100BA47B0D53770A21",
- "ldt_key": "29FCEA9F70AFCAD6BE477C8A7DB85A9A34CA55C8ED3F1AA0013E35C3A911B3E947537AFB66A2E244B252BA1551081FE8C559478B2379A677DE0E18A22475FAAB",
- "hmac_key": "EDDA408416F36883183FD95538E71CFA009D9D97DFBBCB6017B14D746771A457",
- "adv_salt": "7C76",
- "plaintext": "24997451E6C5935B33124846BAF868A0F8B5910F1F1A9EAD",
- "ciphertext": "C322A62CBA22ACA0EF4AB79E14A58CDBC293D50C354F0148",
- "metadata_key_hmac": "6EBD3E2948C92FFF55571A81FD68E1DD9A41CF9D29AED0682D95BBEDEB9AFE07"
- },
- {
- "key_seed": "CF3449A532950AA71097A57B4FCD9408C8F17CBB686FE08FEC1591FD5E6EA7F7",
- "ldt_key": "5AFE3D6D4CDFD4D5065723402B7A2D9A7734301100ED0B8E47B2F85F7F20A56CC567F9C8456092DCB31D827354306DF52810B69F6EBF13734E9610893ED2128B",
- "hmac_key": "E8ED4FC24E00C92C57D2F637E267BD016B2ABDD60B9983C554B1C183F09D84C7",
- "adv_salt": "762F",
- "plaintext": "7335332B8D79B72EDF461FDB8A6111C3",
- "ciphertext": "3AC347CD0329B7ED01D92E95906BA819",
- "metadata_key_hmac": "58ABC3309FAFAF2E0051D91743BD6B5CB364C0A2F278C818A084E3F58AD017DE"
- },
- {
- "key_seed": "8502CC048239779635C0C16622C23F49B587E418289430A3122100F0CB72D7B1",
- "ldt_key": "BA0D750543DCDD3A505BC7FF3DF2CCDF5F911588685CED3EABA6500E970CE49DA97D93512403B037CE708FBF5BB53C725DD19CCFEFB809C375BEA90C59A4F9C2",
- "hmac_key": "F815117346818F376698B4A942459301FCBADA75C34833B2C20EC53EAB6B78F4",
- "adv_salt": "8C0F",
- "plaintext": "19D34DF12AF59C8ED87EEBED97FFFE2811C6CD64EE3139F427029E",
- "ciphertext": "93E13EE67578A7D8CB748E55889F8838F5854F5B9300D93091D762",
- "metadata_key_hmac": "DD2BDA4660BD3C149F56D4F0D8F39636531398BFB916E291A925594A1EE87CC4"
- },
- {
- "key_seed": "DAA6AE9055EC48FCFCF0F5EEA10F9D54FC37203F21E0427F6C6F3EDBE3CF67CC",
- "ldt_key": "BA1FF2973185299DC1E13C7FCD46A2CB8CF3E940F1F7B04DED6311DEFBCA0105F52BF9261A711EE436391471A7CF65A8D7182B4B1BCA9DD1321B37E93E8CC185",
- "hmac_key": "007AE606E82C1E917203D48CD3B0CF7465C1E57CB55E2AEB41F7558FAF75F9BA",
- "adv_salt": "C18A",
- "plaintext": "34692A405DA47315781587F7FD8687F7FCA8131369096DAD96",
- "ciphertext": "F17387CD4A36AD7B3FDD7291ADCEBEED9F408C1F9A1EFBC453",
- "metadata_key_hmac": "BCA6BE8297D3BCFA926F80D1026F1C8DA7CCAA804CA805E5BE523B375B930023"
- },
- {
- "key_seed": "F25660848C48B1809AA801DC67DED952DA73A200747DA59545DAD3F17273324D",
- "ldt_key": "2F7ABFE27A5D7A0BA0063F061A69E070D2581FFC8D5257B61385645807E5F7F2EB966DC84F19BC8BB31C9EFA40EEE5D684F9FB928369C76AF27371810BA4DC6E",
- "hmac_key": "64F9623263CF96FC66400186A2E6F7B4ADFE15F5E184E877F802FBABA4A6F3A8",
- "adv_salt": "D14C",
- "plaintext": "5773E1404053FD475905049812A1CC457BC51F1567C1456A",
- "ciphertext": "985840834C0AEF4921523F842CCB203E0DB581007D513215",
- "metadata_key_hmac": "D96254F0FCF232B538B7810568D884DC106988419FA5ED81C1EC852F3C317DBA"
- },
- {
- "key_seed": "6090BF93D4371B05AF47E60940DF4DC98A56CC961B46363ECE74394BE523BF49",
- "ldt_key": "5B61E2A831B733DE77A50F622F525ABC0CB299F1B96AC091F4D4122AF8048E54A9EDD97F6E53F05B382233C7D5C9BA4D1719474A1507C8F619E089EEA0C6C3BC",
- "hmac_key": "7F19CEF943471DB2AAE52A95B3A90BE0983A37D02A851090B1078E983C8A86D3",
- "adv_salt": "6394",
- "plaintext": "FA349723D47F0E779BF19B8C517B7DCC9FE668B94D",
- "ciphertext": "69C0C85FBCAAC15668AA6EB7472E613B1AA0C81E16",
- "metadata_key_hmac": "8EE8E3927B0BAEBAD706C032EEEAD2E03E70211AA691F0FDF493408B17FD90F7"
- },
- {
- "key_seed": "EC6E0C4933F7D73FB18A934619902BFC7C3DB0CD23754D57C3128E518F5A8173",
- "ldt_key": "EB02D82B568542D1F74692F528BE19910D2BC2D491144E5AFB8DBB257729CF7F21A7CBC8BB350C1FEAFFB10F4A8D3BFF379191D0647A12023AB44968D53F2F25",
- "hmac_key": "33C7B177902F2A5592A3B0166020215DA76B21CCF78959D7B21E7B0A304E0567",
- "adv_salt": "7A79",
- "plaintext": "39E5C5F7E08B25832D023E2FDE2B412E755814",
- "ciphertext": "8AA7FD7E155EBADA20E1E65092E07310C16EBD",
- "metadata_key_hmac": "A81E8596D25B7470C6A1B15B34D2C9D2593E25A8873322B296BF4AB480E1982F"
- },
- {
- "key_seed": "2A685A402E6B4C3BA13818AC2495E6D7798163BC1AECF576DF183270DB2AC66C",
- "ldt_key": "B9C393E46F60C9D1CA3FD883BE2828919E35291FCB7CF60F8E12FB544EE145330771D12DC6E1A02CF240D59B96B37093D993B2F1302222B04687D9472471472B",
- "hmac_key": "62DDA07FCD2BDDC9076F474054E0458F6879516FC6E77155A12605CDD9ADFA5E",
- "adv_salt": "03C6",
- "plaintext": "558FCDBB132EA29FD9242E12681D3A0531DBD6353EA6011D29928D2E",
- "ciphertext": "1E7FCD5BE6AA3ED1FE7C87AF62D81B0CAE76F8E62BF3DE639C1C6869",
- "metadata_key_hmac": "F380B338EB5639A65FB7C2B1C8ED5E433DDB6271B5FE4B470F77784F4203B401"
- },
- {
- "key_seed": "4D8A9B4D23A92C4C813D63980255838C29D17A06CD5CAB47737C926C0E5A5F2D",
- "ldt_key": "4C1BD292C6F1D788264B74C6A7D50B56D6337FE643197C7B771FCA218A3FBE612B767B9A132726A45072AD08FE5994BEA3EDDFF503B56985CC72016E263B7EF8",
- "hmac_key": "D60975FF61115BBB89BDBE3BF84B3A12019F754356FF66F2F1714A63201805FB",
- "adv_salt": "B3F8",
- "plaintext": "7197A958EA9D9D874353F3A5146BAA614A2C61A5815B5920419B5580",
- "ciphertext": "D516F8023B411DD3A2E21553B7F0DE0855D8E81BFB0283890C902BFE",
- "metadata_key_hmac": "EF3BA4E20A8112744B960DF77FF046FE9EA20C55115C088973624E1E3D8A6B5B"
- },
- {
- "key_seed": "C9C566D3088648DCE86E7DA80EB9564616C6B173A01A00FF7C0CF37A01B21831",
- "ldt_key": "CE038C13C852A8B6CDFCB62566A221B77031106FE9FE01A80A7EE530274839461BC90AE38440E97A02DBB6EAA332F069DDD3989ACBC3897C05B9C2D7F04FDEE7",
- "hmac_key": "0DAA5072EF22712A2B4170BD88D19A8E4A80A96BD57D509FBC204E79274BCDEB",
- "adv_salt": "153C",
- "plaintext": "B54CCE60149E29D8BDD9C6641E1EC88863CDA651",
- "ciphertext": "2CB51396470FDF4CACB8493B83B1E5EA0ADFC573",
- "metadata_key_hmac": "806A5DB9A3ACF83345C3EA3D45DB135BA9007A923B4C7E394AECBEC2F7BF2190"
- },
- {
- "key_seed": "4EC98D85F72FE8D7F6D04D4A202BA3300091FFC4B461EB93C286B0812AF56098",
- "ldt_key": "D10CA2BEF1B09144569A8AD318882FEC986B13902CC6C8E6FF3C3EA9158EB81F1E5567E6C3B67054A80866A5E2A64EF6B20FA825C37C882A57C785B5F8FED8EE",
- "hmac_key": "C50B0B4F9B844EAB7F75EA81790DA6B9202DBF09D588D3AD0E09F3C9C3153217",
- "adv_salt": "8AAF",
- "plaintext": "3E67656A66F8FA1CBF63B1CD162F39E4E99B0B837A",
- "ciphertext": "340A53833B28EE6D68A63B742E153CC9C15E5EB061",
- "metadata_key_hmac": "18094118719C7A553CCD7D75FA733B2EF100A0FF3E8CCAD62CDFFA7D839FB8F6"
- },
- {
- "key_seed": "9A064BAA308923176299AC838F59C742FAFCF03396754384486A643B619CEF78",
- "ldt_key": "799D31477FE6407751C233E8EA23E574B2C58B762195EB9BDDBCD2AEDF58F11C04768CB76CD9822E9DAFB0B74609AE4E91F67814085E19D21AF885AF079F98A6",
- "hmac_key": "87FB2C5EC3426F8F8118CD237AF67A2D915F8E51B31AF731B2C53704E1850E8B",
- "adv_salt": "5482",
- "plaintext": "97A88CDAAA31ADF5F25DF156A65263EE2E6AEE7E19A0B07D509C7D",
- "ciphertext": "D15B17B9D142E3B8D2478DEA14853ABD6D60CBF50E5C83A9558F90",
- "metadata_key_hmac": "4A17C1A21242275D9FFCF6F2197B0F5A92A4F42D7DEC63EC91C48B33219F68B4"
- },
- {
- "key_seed": "6E61EB596A2E5C30289BD0D62DFB6BC79EE546DD4DBFDF087426F31DA395D1AC",
- "ldt_key": "8A55C3EF7748594CC2C7A624DF2843D603BD7D03383F72246BEF686FB052585E32E192F9FCFA847A2443C23395A6BC71930B1A5278CF5459DE5C61CC8A806274",
- "hmac_key": "91741B464B1A30F832F2B1FFC94A0F4944A34A73160BB4A965466566C7FBA919",
- "adv_salt": "66B5",
- "plaintext": "9254F8FD7DD259B5F8D4ADB4168F6D9E9CC260",
- "ciphertext": "7A19067485676DF76D868F5548E81DF3F7B218",
- "metadata_key_hmac": "4889130DBBF07E75A1B864DE9D1FFF7C9D4645269633C4E484095D771C453A38"
- },
- {
- "key_seed": "413C29D326C97973AA72C9445AF1490F38A1D91741E7A5915F6D2546FA73780E",
- "ldt_key": "74B9A9EBBDEE549D75C619F19CF5797E58B71F29928E79B7700F7DDD02B2187166B23655B2432CFD057C3B4627F446CED8604D0306C61340C977139F6909C12D",
- "hmac_key": "17592D7D59DB2D61CC93FA408AEBD68E9B6AFEA5E9DB8041B4F661059588CC05",
- "adv_salt": "46D4",
- "plaintext": "EC3CCD49517F7C4D28B7060925DE6EC61246CD179E515057BDD2",
- "ciphertext": "D0C803AD7A7CFAE60D0AB2E902B4B0B264BAFDE23FF285822C34",
- "metadata_key_hmac": "A6A8A38E5899DCBFE53F8C2F096D14875C28B9F17469432C2467918B5124E289"
- },
- {
- "key_seed": "34D418B85A3F83C0C9161C9ECDE9F085E660C06B875FB09E7BD5DCFEABB5E716",
- "ldt_key": "2EA9F9885172C679AD31E64BD2101593A448C95BAE3ABDCA3495D31E5FC75CE5F209B6F1F73F108A77004A51700B79CA2748DD29A805F057022057DED77E7607",
- "hmac_key": "8DC19E5A9A7CB1008BDCFBE14906D56B66899D26E54925B372310BC02C1199ED",
- "adv_salt": "6BA3",
- "plaintext": "D08B3CDBBCC618CD992980B3D22B186DF94C0A646C762FFE544436B8",
- "ciphertext": "632A1D66239EA12E38F2DDCB9BB0ABDB10189ED3F173B5F494E508F6",
- "metadata_key_hmac": "C505EC0EA2BD905D96391B48B78AB0AE823AD75F952A29724984CF3C38EA2BBE"
- },
- {
- "key_seed": "2F46796E27F2E5FCDF269E2B1BA585644C7714D4D3BAF6B5ECC61882569A4C21",
- "ldt_key": "8425986BD785552A56CD689EA8AD2A05E3922710265F5A68BF83A2AB5655814A20E4850CCC76DBBDB38F1A61261142CDE744F4F9943A3D98E76DB2182A4A2628",
- "hmac_key": "7D33A33F4386C4586C035A5E49BD1F663973A7297A7B8E6FC8A47C6D2C1819EC",
- "adv_salt": "E2A4",
- "plaintext": "F800EB3409FDDFE1E82DF9236A7925C5A5B4CC3CBFFE7A09AFF1",
- "ciphertext": "EFE31E9A34ABF4880F19AB67C464448EF1FFCEA3A871A616C208",
- "metadata_key_hmac": "C84CA1DF801588E0F05FED981BC716D718F712EB7B851157C5E9A671E8C1EDA0"
- },
- {
- "key_seed": "9E289AC48C9757AD7085A31E4F274AF7343434BCAC94298F74D936F45FB13A5F",
- "ldt_key": "B53BF793638F38A19222BEDE90EED4D5974D321DB66100E4E97F23C6E576C03F8D22AAB72CAE5BFD7174B757306C90481C29D843AE3D463271E575A8A28EECC3",
- "hmac_key": "316CF1F279553D1F01E4021855F2456ABD87D17C4B0799AC59872B15F5DA2236",
- "adv_salt": "28D1",
- "plaintext": "6012835C1BB1059E313C7129CB01E73E4CE9BFBEC35AD1902591CA8E249D",
- "ciphertext": "8D5A0749FBF107D3EBD02F7C6D6A3E1660A310CBC01982AAFC53B9A33518",
- "metadata_key_hmac": "5B3C970E2CC40C1C010AFD7864B17662D968918B4560BE222A6625AF69663360"
- },
- {
- "key_seed": "41A099C5D66CB945FD237961326E7E7D3025A2AD4AFF31BC560677315DE6984F",
- "ldt_key": "66C76AAC504BA1EB783442279B852275DB61BF7411A16B54DE7BBFB36E046836C24D4F21C18AECC1B7C07CF1B8637F2C18D0BA897290F24CEA0ADAD7EBF3512A",
- "hmac_key": "0EA893132D505F883067D2E126DAAE91CAAD6815FC157458D5060D9FD486A7B0",
- "adv_salt": "4DE3",
- "plaintext": "B1CF8B0EF26BC648B580B8319D0B7A1747BB7EB0AA5E3408FECF5052A6AB38",
- "ciphertext": "0EE27C2179E912D1E3B755D7665A6CBF6CE5DCC2782342329B216B9710756F",
- "metadata_key_hmac": "67CFC854F10DE020F9367C3E4A1707445D77D6BE0CE9608F0FC7512DA64FA646"
- },
- {
- "key_seed": "22D103430AD13F0AAD09237D0956AC3CE7D346692ACBCC88C6B6169974A6C07F",
- "ldt_key": "663EE65D559972B0E5FD2C5D06A705B6AD5707E650FA56DD6E5CED45AAC0FF6953B27FA7E54D721195B17A24235B08D276227A773249962C7410C467CE9B9308",
- "hmac_key": "68B75BCD7A56B9FA87E376894B2B12206A4DF9036AAF59FEFF70A3E5BAA0D12D",
- "adv_salt": "1A9A",
- "plaintext": "569FFA5167D91F964AC3CC28E7E21B9C05B75CCC105A",
- "ciphertext": "06F069614B544A4C62A1C89E84DA8035FF09C11B31D2",
- "metadata_key_hmac": "53CBC54822859D915FD7611D6666C263A56662A6E4A0DA8C5D47955C8E6EC82A"
- },
- {
- "key_seed": "9680FC88D8C9AA02F5F51BF197DFB26C081662A881F2E25F36C93C39ADF91EBF",
- "ldt_key": "7F2A76B8E85178F52A34ED59FF49F22EDF11B692577F264280E48B47B5D0CA31241CC4745E0EB168D289C8C038331AE7763FEFD20BEDD5AE0D91182151630B71",
- "hmac_key": "138182688470F6442DBC195B17130D7938518F6BC83FA37ADDB8D27A02811988",
- "adv_salt": "B0DC",
- "plaintext": "B2193E84A9AAE8D050EDE19F3FEF625C635617B44DDEDE561D086F73",
- "ciphertext": "86F68E13C8DC80EA41E714D32F1F740605838006D7B0C03E71C2F825",
- "metadata_key_hmac": "5A315A06B4675F86C422B31DC8929678BB2D30F88AC0E4718AC1DB0057BF2504"
- },
- {
- "key_seed": "788B543F104FF097140DDAD8E3836D12A8BEE16E5A016A8DD663F46D5C8BD7D5",
- "ldt_key": "3BB2663D34518529E4DBA6585CFE7389933B578BD555A1513AE34A22613198FFD83167F31CBB07B61E01D3B3187B7967AFAFA4BE079244EA840FD1907921C831",
- "hmac_key": "7A013F5FCEDF4211D8AC39347A6EA17EA1FAE86C391A3D532C9CBAD3569868FC",
- "adv_salt": "0A54",
- "plaintext": "3868F0161F239403689EA195843E068F25BED2C4",
- "ciphertext": "07C2B953927FDC86CEEC14E9785E8309ED048A4E",
- "metadata_key_hmac": "21884989E2EEB3E60CFF4470A6DF3FB36E55B1377C28EBB03B84E1BAB7337F0D"
- },
- {
- "key_seed": "3859912F98565FBD72AAFD02C7241AC31C65B0D8B3C3BE15A7C5ABF44DB123D2",
- "ldt_key": "C943FE69AEA239EDDA3DBCA62B2D8C402D9CCB6A643F25CDF11C7BFD36CC8C612C950F7A81891F13495ACAE4CD08CD2930E115E0F9D0BD637FE8FC6785470D15",
- "hmac_key": "5DC5C8397BF983D109283C156A954FA5DC1A50A10DC43C04EC4D0D57A905DE88",
- "adv_salt": "9D1C",
- "plaintext": "435233CA5EBC5FF190707E5FDA434A17EE19C50B2921F4",
- "ciphertext": "DA361F78A91F12A55078769C4B1D11B6310C6E140C64CB",
- "metadata_key_hmac": "E0FB801AA32CF13BF47E00050A088DE6C53A5E9E40B484377A9E62E4EBA6A265"
- },
- {
- "key_seed": "16549C7D135CF031095B1C5E847BE71C69AC674597CD636A6E5903AD35B05128",
- "ldt_key": "3242D94DFE7A36E6FECAD6F5CC58454565D8574DC843658713C6494EABC5C7CD7EFDD5420EADABC5A561CEBEEB379956CB1351EF83711B2B2A40D7FED6C9D6C2",
- "hmac_key": "BAD2D225108964EBC04DEF61B9EBE88511C3BFB649D7F6B32EBAED20900E4DE3",
- "adv_salt": "9C64",
- "plaintext": "8B1B3CF0B247C961A552A4D9E154EBB59317A7A7B89E60C16842744453D1",
- "ciphertext": "FA710865DAFB0B545E82A91F73A437AB9B8F7209292B9068F3FDC8B6D4C7",
- "metadata_key_hmac": "5BE78832E7A926F05AD30277FF85BA56FA36DAAC13A97B05F8FF8A25B375188B"
- },
- {
- "key_seed": "FC774651E46E37F2955FA37BC0ADDB4F71797DF194CEFD1082509BCD139C3EDE",
- "ldt_key": "7E18FA91251EDCAE40CC43B2B3213E15B12A38A40CBB1F2A11D665F419A001D6A98055E49A52DD9A4E9AC913AC7C029C624B76FE869C242AA91269FA5A0E0E7B",
- "hmac_key": "8E028AADA56B355B3D18FB1FF73A0FB97959865B3164025E54312F4B09D9501C",
- "adv_salt": "B6C0",
- "plaintext": "48D81A930FBA128969438F5B9181D829B3932E755DB87658C9EBC35A1C59",
- "ciphertext": "7AC37A8A4379B10518D367C4615A099C600AF54E1370FB06C44FC88D26EA",
- "metadata_key_hmac": "B2E406516B8892B19E61FF0C99A32C65F20FBD9D92F9833C8E7414A40E1997D1"
- },
- {
- "key_seed": "9A68CE290FDE2590F423D2B173D6F700335D4935BA88EFBD84CCD9B98D62F148",
- "ldt_key": "1B13E1A2580433EB1EF83845B35C499643F2928B55A381CE9ACD29A258AD325CF21858C9A354013DFBDF322F74B728538A4EAFD696531D7F80826FFACCD098A8",
- "hmac_key": "31C2184AB947A9D39C101965EE706E2790FFA60DE7DC789597C52E3A3336ACDA",
- "adv_salt": "F2D5",
- "plaintext": "96A54987A54B00DC6E045D18FBD129D1DBDBB748BF44FF26BD867EC76203",
- "ciphertext": "471A0CBDB571FDA0A7495FE7967545F2C661A4CC418DDCCFCD241CAD19D9",
- "metadata_key_hmac": "E050224F87E969CD4F1B18AD5B19C2E8FCA68EF8965018F15BB1A7CC57EC9DCF"
- },
- {
- "key_seed": "71284F8BF099909B5643B6295CDC676620A79F1FF4C37CCD044518E16E05EFAF",
- "ldt_key": "1E6857D4B7B58BED2C299CFC0A88483BAD0C027F91C94975950A2BAFCE86FD399D614ADAEAD9D3DB80B6962520C05D5D68F99E6E9381DD65BB873DDC9E173061",
- "hmac_key": "502BEB8C34A8A56C52EEB7B1F445BB935514D8D80E836A42E8AD762742CD2D0A",
- "adv_salt": "C790",
- "plaintext": "BC6AC409397647D14E11EAE3653123A1",
- "ciphertext": "D3BAEB95A9B1DD399BC7572E1386AB62",
- "metadata_key_hmac": "B33A36BE15F25EBA65835FEF8A548F283B2A57A681234CAF2AE57202D28976AB"
- },
- {
- "key_seed": "DB32ADA65505A45781EF4E0D307B06911CE24C29B885FAD11EB653CEAA1801DA",
- "ldt_key": "CD71C2CF5C35511A1CC36EB3B3A008D3D16F2AE176C273DDF9007064E71B7F16D64437BE221402994F1D11A36C9743D5BA8B4D2688052127A9A9C7AE34E2448F",
- "hmac_key": "505F53627BB5E3E1443FB7A7504FDAB686EE6E8201F4DA5D59174BA77D10A3D4",
- "adv_salt": "62FB",
- "plaintext": "1D4D91AA7001F510B7708B11FAA34F6C2D3FAFC9A89666DF1CDB57366C19D4",
- "ciphertext": "31A32EB26FC116911AEDBB2DECBA5FEDB1B8E8A3F1D6F226C2E0FF4480D2AF",
- "metadata_key_hmac": "A17B8A4FE29187A40645F046971C4255F7287CF385504C556F044002CC46712E"
- },
- {
- "key_seed": "4ABCC9B9953A6A9924115ED9E6F99D348B3C511A3623831B0471C33D7DDF2A4A",
- "ldt_key": "B7F79966BFD45B6FF5B21826DD00CD71EF406E655F9212E2AA0F1CC651C623541FFD68C2345BD368E72869DED95F1CCD8F165581BB17752C62C3569170DF6C9D",
- "hmac_key": "59888DEE165F45DD32A4096222BFE29A04BE79AF4702A99AB1AC12CB7B3E4789",
- "adv_salt": "DE75",
- "plaintext": "3DFBC7C04B895DF08DB17B04B187B53F34CE3F",
- "ciphertext": "8732F4FCDCF9563AEB5258A3F6D9B12415C3A2",
- "metadata_key_hmac": "439C89FDDE11E70F2CC3B886CB1094276C1EE5117BDDDEDDAA3EAFB3BAF1C1D8"
- },
- {
- "key_seed": "2B1BEEBB2E17EB4B41F1D02DD6994A9E79115927C2FEC52843997C0E9B7A0857",
- "ldt_key": "79901D166785D10371F5EB9631ADE4AED6F867AFB62BCDDD078A8C77ABB042A178FE9BDA4ED565D6E84CE1B55BA75421236FC8314ED62A3381DFD063EB85F438",
- "hmac_key": "C7EC4159B8F69E7B89EC24F6757CA5B24D9BD7170A204E87C40ED79310545312",
- "adv_salt": "2FA8",
- "plaintext": "9D26AE2C24BAB406087FDF03F60436A9AFD891CA6081078AA6",
- "ciphertext": "B6134005E78E33683CB7D972708848E3AA5D31637C90787593",
- "metadata_key_hmac": "965CDB488C354A11737FE7F1E387BD788E943B26CA330634693F2827F14E150E"
- },
- {
- "key_seed": "4406B55C675E896426783D5CA64576B18831889D891151F3C8AD4A309E73E2C4",
- "ldt_key": "CA0F77A19D2AD1801BC76EA1FC100FEDBF17F82F478CCFEBB7FF5AC980567B4F9511E3E57C7FB8F097EDF5427000E5C895751D60692F7DC929174DD260948770",
- "hmac_key": "EBCDA862E6B338B9802FD70A00BD7A171FCEF676BE3E613F778CC8375A64A702",
- "adv_salt": "BF33",
- "plaintext": "7E79CF2DA280607780D4518EE475E9AE2015E7050A1872964F06",
- "ciphertext": "A229D7376013646117AA78B4B7436DDE99B80E64C1738F30E022",
- "metadata_key_hmac": "EFCF0CDC83FCF0E287F11795E0D11CEF911A1D729199AAF27D9037262070FBC2"
- },
- {
- "key_seed": "8190B60B4F263AD0661EECF3CF071A145AD22C1F04275CDEFD7073494F95F315",
- "ldt_key": "31B1ECFF18C4976AB3E81CF8F04A2FB0DFAC8FCCBC9DED641520DA9CC82EA4A33B33BF8E5F45AEE2BE1B02AC46B8119E53D4AEA80AB9B5F37263905A64BE6141",
- "hmac_key": "39B16AB474D1CEB8F37310CB3F72A6FF1E4B41E7FF89ED796B5B2C1AE38C948A",
- "adv_salt": "C79A",
- "plaintext": "3A8AF71CC6C5BB3C3D4B954C28F69DBBBE47",
- "ciphertext": "2AD075D01B2F8C7653DC6446AF981BE95E97",
- "metadata_key_hmac": "EA1BDF5B226105130FE5D85A030F7E045C11B238FC0CE0C3A3C45EF3274BB239"
- },
- {
- "key_seed": "F58783AE9ED0E7AFD00F12BDAD1ECC6DE8BADDA679101B84C36F7B2417D3CCA0",
- "ldt_key": "5595C8AB388892CE3EFA50C5F0BA40F1C646B775D7D1983AAD72687749A9933ADC9580566FF2A90415F49F76744CF1703C828AB6933867045EB54F6B76F5F15E",
- "hmac_key": "71208853D3DCDB60D3985FA4AB2954EC18651BC144AFE10820274A542AAD2D44",
- "adv_salt": "E686",
- "plaintext": "9E9C0C848A6610881B438584C9CB12E61870",
- "ciphertext": "7CAF839B2F82A56DB9880A371645734FE734",
- "metadata_key_hmac": "7182053162E3D3E19349B309FFF978EEAFD47AFFE57D9D37AA6E6561EBD55BE5"
- },
- {
- "key_seed": "B46AE555E1D0F018788D0B14C8A7C3B722980BDDCC417DC94B852493469A4A86",
- "ldt_key": "1FD8F39D1665AA7F3C4C01F0920C99B8F754A49EC3698175D55E857C660BF188F738071E29C11C7DBE5EFC129BC5462FCA468A0396B2992C345FE9F660B0DED7",
- "hmac_key": "DED8B1817D753047D90F39EF7977BE3F2D0840B29A3BB54C98978321F68F2C44",
- "adv_salt": "AD78",
- "plaintext": "0CB40F4D7AB70FD940CBD41D48E5510D71671772F4C7050D1A",
- "ciphertext": "BD4D7F6E0249481917C2B209976E83580D4B4AD8FC4E60F515",
- "metadata_key_hmac": "AD3121FDEEE62EBBCFBEE2EEC8ADED78E867F87BA5238AA6DBBB85852BECB0D7"
- },
- {
- "key_seed": "DB9DD2F4ED734844D261A336076358202EB6D828B99F396B19EBC133781A60A4",
- "ldt_key": "F091157C622B58661C92D079FD5FA8C7840ECA44CEADF634E2BBECC1CB2A42D3857BA8568AEE69CD92852384CEA086FFB45DC79C38813FE203832EC0216D03CA",
- "hmac_key": "B856B2988B484356EE19E32460774A2A4220D4009FF272732C13B70A839E19B1",
- "adv_salt": "8A36",
- "plaintext": "C7C38D01C61FE412DCC84D910EC3EB7D4E44F4DA11",
- "ciphertext": "D2CE35FBD1F5D2681B0EF65CB1006561480D39FD95",
- "metadata_key_hmac": "B38B088F5600DD5EE317BB271117BC516E7BA5CF39AF1B6AA53600F77495AA84"
- },
- {
- "key_seed": "8B51FCE2FF95A5F1E20138E5753B1F3C7E6F43E73C5CEB4495CE434CAE4EA356",
- "ldt_key": "4323C8D74660ECCD2718FCF59FBF4A90643E9865C1637877BD3E40C470EBFC68B76834820A5B5D39BD1476D45482751EC918ACE5303627EF6DED59EA36890C0D",
- "hmac_key": "25B8CFCA31C675CC7D8B74079C9CDC20644CCDD2E47D6A6273DD312EE4362A0D",
- "adv_salt": "E808",
- "plaintext": "F841AAB108AEDD72559A3E3015522D848C5751",
- "ciphertext": "9A9653222FD23F8C5B1B9D600216899D1F8AD2",
- "metadata_key_hmac": "31DEA95385C804AB3D94FC4FD6199A0947155D771DFF0FD1FCA26A9786F04ACC"
- },
- {
- "key_seed": "B4BEBB32109FCDCF93551DFFF147D74C2277529C90C37A434A6CD01B2D8E7B51",
- "ldt_key": "0CD0A7B2FF0588BE56F1292F2569AB952AB77EDA27786B25858A88A93E13DD45096ABE153F6B96E4D6382EB7A4D85F47BE6408041A86220CE687AA87F63BBE3D",
- "hmac_key": "5C1E37F63AE477877C96D0AB37269EBCAB560D2542024A2AA14FFD4A3F23E8D1",
- "adv_salt": "8CC6",
- "plaintext": "118914D47B6F4A6285D194ABBC07E85AD3F8459FA8EC23",
- "ciphertext": "B5BC04924C066803A5238772BF969141E84DFCF09A3402",
- "metadata_key_hmac": "0A8030F9F7AE9F0016312C3F766A35A28A7DC4827F9FF54E927F66E1092601EA"
- },
- {
- "key_seed": "8D36A709B972F31E6C65F898A6C1DDBA994764637C16DD7F3F0C01E25CDEF4BE",
- "ldt_key": "EB64426C4879E69CE572204C3CDE9645BC12F97DFCC08A2F833FD4E897C8A949E138DFF41D9DF6A6F4909C96C6DCF18C6E142A983302B4183160130049EA67FA",
- "hmac_key": "8B44C8C6CBC5308DA34EF69481C0E55CD8BCDA0DF97AB72D9FE32B439F32A3CF",
- "adv_salt": "5650",
- "plaintext": "55BB5DA88116677E60C209975D232FD18228",
- "ciphertext": "505D8431CD5FA2A8610E4637ED1642209E18",
- "metadata_key_hmac": "E6ABCCFD7722490F5737199427A5AC2D9590857E4E51A88F4D791B1E618D0989"
- },
- {
- "key_seed": "B4887F6B359B821DB4D60546C6294EC221BDF666B4196BE5BA61721FE0B28BB8",
- "ldt_key": "35CE72EF7251ABEA55353EB5BC0ECDA64A1168704A02640DCB5ED01A095152A0DC6F2224A8881E3553B80531B2CD69C18A4C341D968FE13FCA035C337C3CCCF1",
- "hmac_key": "04FB7DD651E419A2910EB55CDDB1BEC0C1ACC55E399E32A187302354DD27FF30",
- "adv_salt": "F882",
- "plaintext": "0DCC4777A5D21C65AB07BD1CB0F012B2",
- "ciphertext": "C6ECDB9157DD9B51D7E74F04DBBD7DBC",
- "metadata_key_hmac": "AECAC660CA2ADD550FA35AD8167A559FDDE6EA2311D0F4EDAFD2D5795941B925"
- },
- {
- "key_seed": "162CAD94DAD9F52B1249DEB412E9F5AFC7CBF5B49FAD17B01DC6A826C3C2CD43",
- "ldt_key": "F4E47C120FBBE55A36E57FC19EEFC68BD6FDB905A48BD705FF183DCB8A67FF7A8B5C8DD239C3E9E0EDFDEAB0B5E6721329315E9C7592B9294E593C962130EDFB",
- "hmac_key": "333DC195EC74020A025C45A88511E114B9483EBA1F1E654E10A2B44CBDD7CF26",
- "adv_salt": "5392",
- "plaintext": "978C189EFE7051EE0E5C66D3A14B95DA9C",
- "ciphertext": "3E0821E933EEC846E07092486FCFB5B4AD",
- "metadata_key_hmac": "DB7D14EF5BA498D4D1A98CFBA45BE5A666D707537417EF58C86323EE8871C584"
- },
- {
- "key_seed": "65A386C3B6117EF7447B253D30A4C6C1BDEF6AB3C3900CEC59F1CB57BCD7224A",
- "ldt_key": "AEC938648C3F12B794F472AFC642952AD3B54D3F7D2B87494D2789613D15F262C8288ED55607E1734FE46BC712CF233AC0AA42F4AE137534B3AD7E42E7313E7E",
- "hmac_key": "3C68EB194AF430833AB155780E977E77666A159AF096E1807DF7E7AB90C48060",
- "adv_salt": "0109",
- "plaintext": "FAA440F3974DF45683059B00DA301B02C4",
- "ciphertext": "62FEC26B06EA10192D9326C4B7F8DF9EDD",
- "metadata_key_hmac": "08F4014B16123D25EBC9F7A37916130B60A1840BEA2B3B0BBD2D3BD0C55A84FD"
- },
- {
- "key_seed": "F4F8F73D94974410827D1E45567FEED1B0DFE93CF5E6922FA271DC187DC55C6F",
- "ldt_key": "B2D62C5A37C2EF10A13311EF791191560702D2D4048BBCB51EA05CF1C96436953D110C0FBE0BCBBDC2B10FA0B9A151A5496D601F0C8553FA09ACF96A85F036F4",
- "hmac_key": "CB6D166C67FD8A2F15B6BF41A8687F297FFEE73742E2DC0188FE786F9E91FFCD",
- "adv_salt": "B7D5",
- "plaintext": "9841441046BD14AA74C6270768924FE80F1A9E87CF4FB58303C244D677857F",
- "ciphertext": "97DAE3E3E2E62618463FB56A8992B6DCDF75C243683B889888241D9D41A9A6",
- "metadata_key_hmac": "4C6B37E6E227CC21C346AB4949C97F46449D1B21DB5A10333DA96825979B285E"
- },
- {
- "key_seed": "8DBD9E5EB9C9EE1C09BDFC5F27A81AB3D51EA20257FD550B4928745D4B9EA8A0",
- "ldt_key": "00812DA977303D35CC113B82EF7145F5ED0B70DFDCDB22E34A930A960DA8AF57B09CD331FF8B8A523482992A5B1C8292AB7BB51C9CC990E768C76477ACA5C5FB",
- "hmac_key": "309D2CE7A6C72A0EA9932CBBE1C40E150C5F60B29EBB0DAB37561B119BE7F6C0",
- "adv_salt": "FBDE",
- "plaintext": "085A47079930F5713309A6D762120C5701",
- "ciphertext": "3888221A4488F4B6E106F38AA7B3A198C6",
- "metadata_key_hmac": "A3ABD92B5808B5BD09EC1D2F383C82A77E5E36D20E7E2519D65CC38798960BBD"
- },
- {
- "key_seed": "36B5FEAF45253E5FD7A3F2F2B75409EE518D5C231CBC6BC5642C94EF4BBA28A4",
- "ldt_key": "0005617531C346C2C728766D9B02767D5198F7A93262C134079F3F26189F32BF2A6083706BB77BDAF78A9785F7CBE319A5E82B4BDCFED200ECB70E87B900A9EA",
- "hmac_key": "DC4A9845768A5152B8B8795CFA8DFEA3B4B703303642E316D180AFF90A0DAD93",
- "adv_salt": "74BA",
- "plaintext": "9C499B714A71C5BCF065F99FFB91E98D7E3FF1F46964C1317D16C74304",
- "ciphertext": "9560CB581FBC1DC76B3C9BC40F4C166CA771D3D5EF1BD35B3868B1C0F2",
- "metadata_key_hmac": "E1F0037788E36AAE391E5644E9FAE133ADC982971DBC709959A05A8F4F84225F"
- },
- {
- "key_seed": "156BABAEC767C47FFACBA5F54BAED7E8FFDF0FDFDF197A0A3A9E706D82E3B6F5",
- "ldt_key": "40113FE72948F108C8B21B188B0412B4CF7B27472EF5B5D9CA7E637ECAA5EF3435E9B2B231B5617760CC926417CAE64C84E63C94648BFB076B9601E35A57BD2B",
- "hmac_key": "3D06CD322ABCF9994C4349F30201E8B30762ABAD01821FAB80BC8CFA89A98917",
- "adv_salt": "0272",
- "plaintext": "85DFBD49AAF71A3EF9B243E1ABE18B5A949C7900F197DACE4F07B433E3C0",
- "ciphertext": "EB60EB75B7DF32C0E527D498AB9FE613BCE84338DAB068CBC00880156F4F",
- "metadata_key_hmac": "746279DB37F08D7827E9A164802466DC9F19AD5D23C071F5B1D84FC36C65EE4D"
- },
- {
- "key_seed": "A7AA0C3F40BF3F5F82D329484E85E847AEE8F6C9B6D8F48E886EFB95ECA3A3CF",
- "ldt_key": "D81154AF670C91CA943B511D8881825912BAE9E931DA78CD284D6B1B66D9F18CA3BCB59417BBA6DB89AD244DAD51BD74EDEE4FFF1647E822379CA2DDD01C85D0",
- "hmac_key": "647B175FC721704E7F3914355F716BD4CCF89FDC6B40F0652D6991C78D7732CD",
- "adv_salt": "094D",
- "plaintext": "F1A7EF9EBE87F17ED1A9C5F20536F0B1",
- "ciphertext": "B796373F6BB4CF61B756EA3573BF3C79",
- "metadata_key_hmac": "EB93BFD52DB4FF7318E0347E2F2DDBC349D43B30505598BE5A2FA554A001251A"
- },
- {
- "key_seed": "090646E72BEF838D0B591084CF7F200A2AE04CA7EAD150A07067DDE54B44FC8A",
- "ldt_key": "44FC3318CFC2E466525C3D188C7C7C50623A9B12BFCFDA454BEF200B22998F0896FC1A03707908D689D16CF295BC617D50093ECF706FFAFC10B959011E21EF6C",
- "hmac_key": "A62908D0222822364C78A9D3176E33C038722B18E2401ACDC2EDE95DF85B0964",
- "adv_salt": "457A",
- "plaintext": "E467FD1BD1874BE21617B0813C3B8284C26D",
- "ciphertext": "A0FC977C5F13050F6007C6FBC51935CB5F2B",
- "metadata_key_hmac": "65CCCB5065AF7CD4CF8ED8550899224BEAB8D36C9070EBB2F838FEF09A52708B"
- },
- {
- "key_seed": "496478EB6984480B951E25F65E9FC85845B1418D32F55B4078B5419072EC726B",
- "ldt_key": "A55A53F3BC4C077F42460C09F35CDC2777DDCC57BB39B2015D2A14EEBD1F34ADC7F50F4FEE2EE3C32EC76C6FC1A7AE7BE0840E925DE517DCB10BC6ABEC6DD57C",
- "hmac_key": "CAEA21DE3A96C3F4C225249FE01A3F03AC650FD5603F444F38F3FF6FFDA15181",
- "adv_salt": "C7DF",
- "plaintext": "F0E1D9134AC84E5920EA442BFB97F4E7BD6430876E7756A282990768785222",
- "ciphertext": "E8490FC5A4D063F15F1A5A533A90B49B81F053815C48692ABCCC953FA9D4AF",
- "metadata_key_hmac": "BB2E44E96B5CD4C949B5FA3617BDB2636A5028F6E8B319B0A314E442EB6AB274"
- },
- {
- "key_seed": "81769F513E7F04A5F46654FAA812CC261445F811EC5C51B02108EAC1A0113C4D",
- "ldt_key": "CEB48FE083A2C24B0355E25C01EDDEBCE9A8CFE49FE1B1E8398399451457ED7888DA4FF7288717E348EE66035C118575CA2E370EE93A4B105DE78606B94B0A3D",
- "hmac_key": "517E210C373009FE4B346AA7542BD6796662EED0F43D24A4E2BF805FF2B23767",
- "adv_salt": "316E",
- "plaintext": "7B920A59980B213E011A05BBB148B3D840679B1B49EE260C9A",
- "ciphertext": "E4D3A9A7A8025C8AF0E94AE7683637BE2F15F4E6994F75F336",
- "metadata_key_hmac": "EA0ACA6C565FB416FC16F0D4D0152B6EFE6271978DAE0EE97D3254A5F3092F2D"
- },
- {
- "key_seed": "2CEDA9DEF003DFB2170584F5B4CC555B00BBDF31BCFA60365700772D40CD4DF4",
- "ldt_key": "A63B02E2C5923639AD6E668FA63075665041D82BE75EEF2B0D005EC029923BB3DAA1394B776A71525B1605A056F8DCEB50DBD7ADF4DEAD271D5DA38C1D490DFF",
- "hmac_key": "00C3B8DC4F7A9DDC6883A0AC253D4F62246C8DED8D5C7C5A816701A55392AC79",
- "adv_salt": "64E1",
- "plaintext": "568C456FF7E72EEF51E1DD3C89B84B2C60D10774339F7EBCE578",
- "ciphertext": "DDC02E7EC002DB5EFC89E7BACFE18A4176FA37E7A8FCD066151C",
- "metadata_key_hmac": "C2D87C8C84FEEA8B46DB522C4C5DD82DC974532DE5B0C47200A1CE4452018821"
- },
- {
- "key_seed": "E586C7755F84369EE2A78A4CE017880ED73950F49BEE1B91FF1E284BF56C2AF6",
- "ldt_key": "6BBB5418A787E5E06E2949E4D7B143931CB793E98FDC2E9D733E2C72C40C5AFDFEEE10FF5AD9A8D9BFFEAA49027397BE675D63250698206F4A908244D6402418",
- "hmac_key": "A5F151C706A0ECC923F706DE2A1A458760C251581609478B9F70533C39EF3D55",
- "adv_salt": "2872",
- "plaintext": "96C459E676B460380DF3D503CC7E30BE31E05CC9F0C401",
- "ciphertext": "16241F92F0A0AB166A9B4B64DA10A686B9C78B989A894F",
- "metadata_key_hmac": "B16BEB1B3CBB77AEB8F3748286FCEBD3F6F2C21EE8C201C5E57B9BE24E907318"
- },
- {
- "key_seed": "A845B8E174D742420B23349E36ECAF6E454D16F406F9BCA265071B3BD07662A5",
- "ldt_key": "D8CC56D5C1C4CD27BAF1ADAF310A61E9E9934054D067E7D5EE8B4F2D91AD0540181981BCA0B356F49B38337D8CDA5A500007FED0AC21434A041F0E86BF36FB08",
- "hmac_key": "8A78726DE42E0D88076AD5EA63DE08674CF8751BDFD0B9A74D233FD5511972F8",
- "adv_salt": "5656",
- "plaintext": "90D2B234C73C4DF113A4089EA4695FB3E1C5613A2C8F0DC7D0",
- "ciphertext": "5053DBAB225D49C12C4FFBCD36711953A3E00B8ADBDCF0AF8F",
- "metadata_key_hmac": "962782668CD846AC9D73E989A84F8FA095247B260ACB0E981854ACEBDAC13CF9"
- },
- {
- "key_seed": "959D5D206A50FC83E74679834926F1B4447FC27A28162C95CD000C9612C4E088",
- "ldt_key": "3B04A47EA64743AC0ED199A5BA0CCA7611F93E5600BB51D799CBF54E25DFD95F893FBB7877660A5351A859FC0F75C6EA33B470640554A1E2DE4D4452747EAD5D",
- "hmac_key": "74BD0A56417D845A30F13B84150705277DBB6971AE8E24B523B99E573711554C",
- "adv_salt": "BF9F",
- "plaintext": "AB0C6FADB67BD79EB6B94A0AC20567E926086E",
- "ciphertext": "FF008FB69B2440F889185B21DE5C3392516A9C",
- "metadata_key_hmac": "B268E72C523B1B0A969F4BB7474AE203EBC0E861643F1EC6B6090F670763321F"
- },
- {
- "key_seed": "51E94792E74002ACE7C3B512B18C37992BA25A9F74716BB981E322AD068348B7",
- "ldt_key": "015E2B7B4F81E5EC77B382488E1B49E358562657A670CD3E532983F360583B2914E7B4E848051CA857657DD426AE9BD1C102AFAA5D4D08E7E48346E57E75E865",
- "hmac_key": "C576F890E80E363AF243745856BC30CA6BB39FBE1A72749256C93AB7F87AB43E",
- "adv_salt": "8885",
- "plaintext": "331922A4837948608AEBEBCCDF8A44FAF93509B225CD",
- "ciphertext": "C5B89D2504EE3160361D0AD031A1BE698DCC5C37BD04",
- "metadata_key_hmac": "BA9060E2714880FB372713AFDA0DDC82C437C8B7E8BD37CD0504AF0B7D6B4AAB"
- },
- {
- "key_seed": "4F2400095D77803F8C2044BE940CC3AB2444B314DB20EAF0C1F837FDCD1B5441",
- "ldt_key": "17AB4714F2D72CA4C5371768D7C5569F6111E76305863F3702FFB514ACA56DCEC3DF724C1C6544E050E89B23F5741BC9297CA834E99A1A44E221587FF77B2CFC",
- "hmac_key": "1992486F199F19765F4CF13F1CE7EFAA085C116988B925F9AFFB89DAC36757DF",
- "adv_salt": "5818",
- "plaintext": "3EE4FC2AC25DD812DADCECF73A638085DB9FD791C20A40FD",
- "ciphertext": "7FCCEF8CCDB9771DBB025A611269B1276B9C0CDDADF63133",
- "metadata_key_hmac": "03B15393F8AD1DA3F2E7F58AC261017CBD3BDBB603545EC39FC44C887A003BD0"
- },
- {
- "key_seed": "E7137CC7DDA32EB0D1A6DCF6A8B48A14807D7F3265FECA890BE303333576FCCE",
- "ldt_key": "5F090F80CC5AA508CF9A64EA25E2E84EFE8421B39D8946AEBC0D209BCECDAA3053A16E1EED1FF14213FC6BBF0187E75B0A1944DFAB7E793D4ACE94D418F42EE2",
- "hmac_key": "45A6202083B74F0820356B21A83A4D61BF17E22EDC79274272332E6903E1A5B2",
- "adv_salt": "1316",
- "plaintext": "3187F589F42134ED6ADCA93D4412E1FC41E2FFF6",
- "ciphertext": "97EEE19E9828D5FAAA213D0666B26873322A6F37",
- "metadata_key_hmac": "36AFC08EF8950DACBC4049FBE005C001A773BA688CAB55AD71E3F05D4A8E1BB3"
- },
- {
- "key_seed": "BD762827B67F301BC4F1205800A102707E28899C983B462C959B59FDFBA61DE6",
- "ldt_key": "0DCA2FD12F7F8240F9F401DF62FAB2C9653DA29817D747E6BE7896E107C08A946FBC3E606B73B5383B7ACE9817D7E3867E076AF7FB88F1FFF15C39E0AEA236B4",
- "hmac_key": "5D4DC5B69019BF4D5DB619169979683AACC8C7BAC8D90704187B1367EA0D3B96",
- "adv_salt": "0C42",
- "plaintext": "4982BDCAA4A8410E4EC8114A87250768EED2DAC6666AED7B050A2875",
- "ciphertext": "8238354F1F9C09F1F2A998FA4CF8183E601E8D1201DF4B7406C895F2",
- "metadata_key_hmac": "2B4A242393CDB8EBC0096D1A821E902CCED72A4F091741B252CF307DBD27FBC3"
- },
- {
- "key_seed": "8A0747A091D9873604ED00DA5D28B4A671BC9F77A13275E0F57125EFE7F9EB0D",
- "ldt_key": "F50A9C0F74B5E0D8A67CC9F401493DF30327AD605E0F978B822DEBDA52DF4FD2081641BE86B20D9EC0FC9A6551E1DFA8862EC04A685A86530346438F7D99CA22",
- "hmac_key": "D12F236FA71A0E5454464BE860B6EF7FF5E73BBCDF4D7F3FF40EEB88635962F8",
- "adv_salt": "3221",
- "plaintext": "97CF5C94D322D5D5FFC04E1D598E163F60EB26C8",
- "ciphertext": "40E8649F75C1FFA554406D5528E5935CA625CCC1",
- "metadata_key_hmac": "B34E17DBB676F3700493F04649306EBAB8F3FBB4ED174B3D2208D59FEDE5C7F9"
- },
- {
- "key_seed": "5E75B1A297B2B785F45C13973332ADF3E739299CD692D9A30EFF819D6FD92A5E",
- "ldt_key": "E3CF63B24F1BC910162625022E9D8E9E6652D66F4D8B56CE68A355E752A99BFF573EB0A4BDE1BE9D8C6CF1BE0F643A57BCFE4D749A0FBA6ADE3EB9ED7E63C80B",
- "hmac_key": "70E61B022F48A8CE14DC6019A5BC6BE00DA34DD33FD7A927A18C67DCFFF59372",
- "adv_salt": "19F3",
- "plaintext": "62B9B3AAA7AE06C1CF4FC10DAB9592DF32D664EB1529",
- "ciphertext": "690158B2A92DB0D89AF96B2BAA2BDA0CB815A823BBAF",
- "metadata_key_hmac": "EE9F79CC56697C64835A45BB52F787F0EBF2F47F7D1F39C65656A0EDD942417F"
- },
- {
- "key_seed": "5F828B51F0DBBCF16F32B0D64EF0077E6E0ECF984FF6E5260ED08C2F199EEEC6",
- "ldt_key": "774E5108F1F1E369B9205084718CB8482C1033D8C37CF01A0947C8894515498DBF9BB6931F1BCF3832BD3C89157B373E3D20ACA532907936A47E977A1506D695",
- "hmac_key": "78A7578566907A579605F8C87EF2CD96B36EF30F29DFD1D19ADC6D080A7656C4",
- "adv_salt": "BA3A",
- "plaintext": "3DFA5DAE488331777806E37620BED8F6D7977D290D544A80A6",
- "ciphertext": "EB54BE270C16BCE344F4007DCE950C7878EEBAFE9399FD2D41",
- "metadata_key_hmac": "D70A299F865B49660C64E03E2B6A7D52FF6F5E0E334E2E5343150098136B59F4"
- },
- {
- "key_seed": "C13E52792E005B76773A7CAA506BB7521C7BB609C227D20566A0D34B401F5010",
- "ldt_key": "84098CB4CEB398349234613AB71C4FAD607EE8E9889FB33393B6D6036EC4947D26BF1AABBE6C3798FA01918A6EF490E8405F6D00DEAB21CB1A74040FB37D6B5D",
- "hmac_key": "E8091487A98ABF54E8A894597102F2DA954D2D450714000337CDD52D811C18EB",
- "adv_salt": "7D6D",
- "plaintext": "3BEDD94396C68C204AE757B0C9EA8F99DEBA24A089C8A3CEAD48B24363A9",
- "ciphertext": "ABAC2A91A0FF82E1CF952777BDCE67CF1583D4306E302C25ABE0FE0DCC7C",
- "metadata_key_hmac": "8758858A8DD887BE0B06A4CE5085FB489D7F8E523AAA2090E823983C400180B2"
- },
- {
- "key_seed": "99209F9ED8D3688E8A9BA71ACC974F6A33740EEE13D87E61117BBCD24ED46C9E",
- "ldt_key": "2C8FA07E51065220E580BBECBAA8CED2ADF38AAD30483CB2AF6E93528AA00DA008B256EA8347C18974421E1D7817D8E1240E523221F223524ADEFC87F23BC245",
- "hmac_key": "C2D44B7C9FBEE5AD19FAD4A2539B070CD52A5E4867843BFAF8AA20718F8C8532",
- "adv_salt": "26F5",
- "plaintext": "5F7788A29C92701BDD991C4F0BBBD89FE6D79830EBD58FB5DFA57F",
- "ciphertext": "6966882738DDE48CC1A810C98F33177E41919B31D2E40780D94BB9",
- "metadata_key_hmac": "B5231FEBA78D42FFF32386DFCBF05E4393B7883EC71D15774DEDE75D65063705"
- },
- {
- "key_seed": "966DF7A7630E058186C2F28FEA9E6B9D581DF8CDE8157EE6442FDCD09FF52242",
- "ldt_key": "0D99B0EDA92AD23AD08913C243DE0E033C3B6D60E9D9D8DD670AA41A14A4D5137FACE3AFDEF44EAD7E42DD20AE2A0F56B4441280627F5949315D1A5D83A0361F",
- "hmac_key": "80C2A8E33E4A6BBB28B97B2153F3C5781FB735DD082220AF5F83E21D076A5BB7",
- "adv_salt": "9F8A",
- "plaintext": "9AC43899EF5C19527C17A5B42490FEB1932DBF3D",
- "ciphertext": "052AB261787C5C32B97FAEEF61F2F7300579EA3D",
- "metadata_key_hmac": "E9E5C776B7933516400C1CBE21C865B0EBBA231A48B094741D6C05056E81604A"
- },
- {
- "key_seed": "3ACE45A27191E9008E66C3DB980CCB5044E1153E4DD3FECB051B26E568E895C3",
- "ldt_key": "B3D4B3B28AB6A70AE36C589C5C16866FF9B414FEDF67669CFDD19FB085B64AEE16D6782B9E5DB2C40151BF21DB2DD322640200454EB7C2BF4A21FBE60A1C2C86",
- "hmac_key": "146363C05656929CD63ACA8CE77879F6AF09CD6F820D5AC8D5E298283A3B3425",
- "adv_salt": "FF1B",
- "plaintext": "E44D6F311235103E94C01A3254A924794F80D0",
- "ciphertext": "6561655D1D86932BCEF36373B893FF3BA770F8",
- "metadata_key_hmac": "24DEE3BA49C15DD28B304F82F0A47DE1CFF96D303361E3C705AE931620ABCFF4"
- },
- {
- "key_seed": "1EF1E6BD839009CD1815ADAFA4C842A633D992A4714EAC96134D1C28EA6C402C",
- "ldt_key": "EAC3A6D962F5F1165527E85503E1C94DBF60050239E7833701295AB0AC6FA6F6AA6002D87E2FF49C620E55E7A3A466BD71CB5138AA781417E3194EB2DDC4E50C",
- "hmac_key": "D32C2E77C735D326B3DA3E7E719DDAA155A1273E07DDA985AD15922D5BF65CE5",
- "adv_salt": "A239",
- "plaintext": "D0A2F69C1C0B59F54EA0B5F87079235890E62E93B72D71",
- "ciphertext": "9216740B6A94FD6E2C2777F1E4F182491D6E662DCBF0D1",
- "metadata_key_hmac": "9A63CB63EE1C702468D288341B77367DD59EC18F6711038A825C33553C4F7D8B"
- },
- {
- "key_seed": "8B2535AB74D0E93B8E364F26280FEF24B6E78F93110F5BBF533874073138BC3A",
- "ldt_key": "35BEEB94D853346D0044288FEDE4BB649BF03356997BBA1FB994C29311733BE112474086B34A429E6D56D5C39D429DD7A8829C3FB8E5DE99AA8805CABCE2F68A",
- "hmac_key": "7F4E1608A595E7DCD915EE1339679AF08290A663ED76142B564CF33AA60E422B",
- "adv_salt": "8D71",
- "plaintext": "8B7C7D68516FECA71915B44644854032",
- "ciphertext": "BCFD8E27F1A7CDEAB05B41FE8E94E813",
- "metadata_key_hmac": "D1EC3ED33EF17B53D2E5C712C750AB9792608025A79166C87A631B5189CEFDE4"
- },
- {
- "key_seed": "68B0C0AEBB1B4F1A8A398533657B26D224DF5633DACC640005FEFDDB30AA85FE",
- "ldt_key": "E3CE400AC3AD9A993FC5C938CF1444CA907C0E62D3E399B40010E8FF70D812E2F5D0BF2F77796445C56CB25797B39359A991666217C8B3615A62A69EE56E57F2",
- "hmac_key": "EE969BA6D7F13BB60136DA7450DFD7C03E664E39AD3F0FCA38E382D46C2BC5AC",
- "adv_salt": "4BC7",
- "plaintext": "607E9F8FD75E15BE4FCB847A15710379EF38E4B31BAF2C7C9A615A61B1",
- "ciphertext": "CF992537BD9F2485F7A8AD17BC86EB95C0FAFED4E1F809C67E49BE2354",
- "metadata_key_hmac": "25C04A466CE86994FAFBA8AABCF18C35E67C314396ABACEBF5EA046E551E814B"
- },
- {
- "key_seed": "9A3A9BDD903C0173E410A0A3D14A8B91FD6FB25618D1D563CC029FD13ABA88BC",
- "ldt_key": "F0235A77EF2E0931E460CEE605F87A75E9A94D62D0E7D37CAF0523CEC6D13C311B1F9CA8BA4DC2EEF40B57BDB36DB2EF718CF8F3B48186A01517D3CD766A7101",
- "hmac_key": "6B112539523DD69EFEEA53DC54D0821B84A1BD2B37AF762728A82BFCFCA19949",
- "adv_salt": "3EF7",
- "plaintext": "C3D22D4D9B701A1459C3E76AFC5C8017",
- "ciphertext": "904D9A291CC4CF4A4BCCC38D387B8205",
- "metadata_key_hmac": "D8FFBFF6FF7D4E7D1C3CD8F77D4E2DD517BDCD57629394AAFBC19C7F0CA7D485"
- },
- {
- "key_seed": "61E8511E69651AE7A73DBD04B941FDE17A1C52A3F2AB122DA320E974232E6E95",
- "ldt_key": "6B7BE769068F80C0A373EB0D42CDC1954F74DE30A1CEF8E26D4F41C077AA068DE2F6AD43D0FDC3C7065D5C5FE0C88423DB13FD07D02FD2E5125EDDF85CAD30D6",
- "hmac_key": "89C68164AF8C1951C587F92EC69D306A6FC98BCEAEE158F1744887309E2B225C",
- "adv_salt": "D6C1",
- "plaintext": "93F8A03B2E25AFA0845646761EFEF765589492",
- "ciphertext": "39F3003C41BDE3078B7DC178756596F2FD9CE3",
- "metadata_key_hmac": "91E93B8A40ED64BE00109BC8A7FA7BA556CED575F4FED68490703415B515C59C"
- },
- {
- "key_seed": "F50FBA7C9FA978FDFC531AC8D80EAC2FCFE60597C3888E2D9DE78D743F44126D",
- "ldt_key": "45ECFAD30CA47A46F9C0A943F90255B33F96ED1B1443B47E5CA93A7787FB7E547E435A1885AC56C6DD9E19F2496C6158AC8D3E85A5D66EF5E91DCF6EBBD05577",
- "hmac_key": "D675D76E2070B2E5DF63878643CFDB9FEE5F1757CDEBB713B9A888AA808834C4",
- "adv_salt": "BE73",
- "plaintext": "9DD7CF9D31109D0319EFF2B0B77BA470A4",
- "ciphertext": "AC2387B613EE0C5E2F1C726D1E2CE80165",
- "metadata_key_hmac": "7E8E81B28F287F68DB90EC58BB234439EDE6EB16076BA17E6C9A9089148A7A12"
- },
- {
- "key_seed": "0E3AA4661227ECF85B9803754BFC759904E1146FB14805B2C466924184299853",
- "ldt_key": "B347FD5FDEB8592B629795B73376B4FDC5DA39330217B4D6763A700EFF120BA7B81CCC2B212C15F978BBCF3CD52CDAB68CE9334ED59F9FB976E5B549E38AE162",
- "hmac_key": "BFDD346C88E410A7CE622A9BBD76EA1E17D8C0B2ABF99435AAB124CC52D5B456",
- "adv_salt": "FB80",
- "plaintext": "73FD04EE2340B9B90BB39A4533A8EAC1D6E79498E32FF240F657",
- "ciphertext": "09FB6F7D88711FBAEEAA9BE40AB489976C0F8ABC0676F7F7CCE0",
- "metadata_key_hmac": "4C8CB886B3A608257349BD50B51497ABB8FAF3F1343046991E283321939DCBF5"
- },
- {
- "key_seed": "C099343FD4A232B819F963BF52B5F1C8EB6A31389EF5E3D9E9136E13E4C45C05",
- "ldt_key": "88DB810F77BD9EDD223DFFFA1C030A222E4C876FCE7535E2F9F34087CA64BD0CD13A336FD968044C031234BC75837F5AE1CDCE777D1477DD063178911DCD30AF",
- "hmac_key": "D95134F685C48D23509BD58D8117FAA6A91640F4E08DB3CC45DB252FADA86B43",
- "adv_salt": "B312",
- "plaintext": "DD081FCCB8A5D4CF75822E2C5DAA2DC18E1F03AC881097223C",
- "ciphertext": "D7FDADA1C6F1308097BFC739AB1506EF5EB0BB5DFB7340EA1A",
- "metadata_key_hmac": "112865C8F64E18D6EAE178D59A83FD2C932D8D0B6DBBD0442A19BA01E85E5286"
- },
- {
- "key_seed": "8CE0F66327998E3F4C4DC7A9D2AFD4C96F8348716071E88C6CAE4E145FD9868F",
- "ldt_key": "474AAC78E2EF5A8256B5AF15131DAFC3186C8BF80A26A092924569834745B35E50EDC31BDA3AEDBC73474312FF65E6846A02C848C01277BE6BED34FB8AF255AE",
- "hmac_key": "C063797BA13AA07E77EDD2ED6AC7CC95B09CD318F2F57853DF9F621F5DA64D91",
- "adv_salt": "3886",
- "plaintext": "F438E75C0B6EC928A2D6446250613E3C",
- "ciphertext": "45110B3BAD0E10347F5507AD69C4CB0D",
- "metadata_key_hmac": "6919301B93BEA50AC96EBA3B14C93E995EB935B422AEF3572812D95139A20CB5"
- },
- {
- "key_seed": "BE71C52BC69AC9B79811B15BC2415C637E6A071A4A0DD2B8C3B61450960E3AE9",
- "ldt_key": "2EAFE088BD5C2CE73A7D441DF39CC7B75A8F8F9249368087647465DB4587F4A53841B7C22852723D8523AA61A890CC75C2E546BD579D4AE15C22061D35942A9D",
- "hmac_key": "5D515675C2E137AFBEC0814EECBA2C96DB4233AA0590C77EED7016978A6BF4A6",
- "adv_salt": "8B45",
- "plaintext": "43F7EDE6E21FF7A7389F0071A5ADD10D18ED3AD5",
- "ciphertext": "4AA9A385D2A9D46086B02411DB0B6CF0CF38F1E6",
- "metadata_key_hmac": "DB6E1A1D2B326E3761639FFC2D7CFE7D14340155EB93FE921DAF1742CDC8DF42"
- },
- {
- "key_seed": "F4FE69415D899F4C4BC785DA4EE1A7CA27A54623CF2F6E43D63354BE663CE05B",
- "ldt_key": "2BE6FA71806DF6EA92CA2ACB1DFC561732F88F80C429132B9E803CDD8EC1B3677D3A86DF6B4637A56C1E340D6A40B8977ABB4072600D73B76F8795299F5A848E",
- "hmac_key": "3AC4D4CC8A6D1E845E9566203E4448EFD72E4F5628CC7759E64071D47098295F",
- "adv_salt": "7CCC",
- "plaintext": "5348BB05E07CDFA4DE1A5032DC77AA18F8176B50D573D42A46E187349ED1",
- "ciphertext": "9403D67D0A27A1409CE20F9F8B7D54EA92705E69379370C71A4CF8EF02E9",
- "metadata_key_hmac": "0591E04F26AEF6FFC35FD1CBE405095B09D836A276A8F9E5DFD08820AAE41D4A"
- },
- {
- "key_seed": "6A408471C5B4AA6A83C759E733EC913838A8AB51DF41F6E5BBC6C52103996EAB",
- "ldt_key": "BE92E7B3230524E7D73E1641D7C17CDAB6183DF53BA9E23F2C06D27E0766D634C59D03E8352DDFFC3AC02FEFD1922525FC93A27005181F2B702275C6E5F58686",
- "hmac_key": "B30A4502CEFAD6C91BDB8AF890188223FB9BF632239F4F8543EBAB2F5D44893B",
- "adv_salt": "B569",
- "plaintext": "D301E83E71779D5A5EE57D2DD388F8902E40B7D42B7D005A73",
- "ciphertext": "73C7DA92FC745D6AF5366AF3C4629FE9CBB83A07148D049AB8",
- "metadata_key_hmac": "D5729AAD46358847132C4CB9BD09086ED6660098FB562ED5096E148FB197CF0A"
- },
- {
- "key_seed": "A7EB4F2F0675BB6B5EAECA9F62AF19858B8176B6C65DFF1AE6A079BA62D820F4",
- "ldt_key": "37FC03570EE05E7382EAE553AA4DDC83A9CD52E9838788D3F1A7F0E31E0F48B0AE60B5267331C1AA70560F5235034939264F77F1C2DCCFD7E5D8B21437230582",
- "hmac_key": "A0D12D31A7C92885F5EEEC124877D267488C54666A7483695C738FE15A0054E7",
- "adv_salt": "7146",
- "plaintext": "ED858374B2F63FE2295C03057FA1C608",
- "ciphertext": "DF2BDD32B531487175FD70B52EE04359",
- "metadata_key_hmac": "29E61C005E33B275034DF4D632CC745F589B41A57EA1DB3A932A3BA3763582E5"
- },
- {
- "key_seed": "18EFCDFCA16E365030A5262183C26DA73D04E7AB89174A49FB4362C66890E118",
- "ldt_key": "5148EC122339DED20615FB7DA30BF8BA2393CDDF53BFEB2BDFEDD013EC712644DC7C66A4EA0790088F589896900A3E4DF303E9F0BA07ABCC6005972A76EA7014",
- "hmac_key": "61954A3DA2BDC3F3BE2575E19A57795F5815BE95F7EBE0CEC73E61090A9B1F1D",
- "adv_salt": "5810",
- "plaintext": "00EC894C423C147AC4D010DEC2E9736D44",
- "ciphertext": "E9BE57C4FC0A029AB7B00D059E2B85F19E",
- "metadata_key_hmac": "DB51ECB68F815EDAC9E9224B092829809BCA51682683A6CA4DDDCD8794018726"
- },
- {
- "key_seed": "25AA14B16817BDBCED1E9694EBCA2F8BAE8FB017E55581DDBEEC6F0F68FF0F8E",
- "ldt_key": "D326C60BC14193B314C09549AFBCE6C16783B28DC53561480EA5377DB3F1F4A71BCE8D000C9366E4646D1BC463EBC994753CAC00C4D99886DC4C3DA81B9D09BB",
- "hmac_key": "4D3473A979B94BCE625FB3B6C0EADB1BAB813D7EDCE8CDF7B008CECFB5E26B25",
- "adv_salt": "E239",
- "plaintext": "97012D42AC4EC974B4B3BEFF19822A7CA44F26690F68409FEB0BA7",
- "ciphertext": "2119590810AC61AA22DAC6A2472331DEF9910F169AE9F578449693",
- "metadata_key_hmac": "CF8A02C467D95938D541EAA0FB11D88D8337B907DBDEC83C3E3B43252232F74B"
- },
- {
- "key_seed": "82B6E5E0CE0A08A2E3AFFFE760C8A1D2EC885993248390D4F5E93B9A04F4D758",
- "ldt_key": "A7E418C2C993648C90E6FACF91636DD34EA7D6BEEBCFA22C116B26AF2D5C2CD900B277B85A3E731096DF9A8A33CFA783FFA3A14EABAFAD6C1D117AB608A27DF0",
- "hmac_key": "9D8F7FEA188248A5104B1DF4F79A9F6A5DD96ADE0DC893F28FD5570E4AE28438",
- "adv_salt": "7CF9",
- "plaintext": "9BBD2A7D75DFF4C34DC90AAED6814466D9BEA5",
- "ciphertext": "5064BE5632989938326F75233EF85485C1AF71",
- "metadata_key_hmac": "85FC88E620E660A1F0BC705A7A72F04F908494EDE585C7890BFCB6E0074D4655"
- },
- {
- "key_seed": "4311E1E839B5C8ABB86378C3CD11861D230BBC9E6367184EE02A74B9BA73D0D6",
- "ldt_key": "B5AD803ADAC55B93943AFA73E9500D6CEFD2F3FB75CF4B532452C68E2A9C9CE4497E260A0F5991A058D7154A954BECC4E1B227240EDD9AE661C40734AC5E5289",
- "hmac_key": "444C68A622F716A29D1B042BDC2848449635C6557BB194CB04D4EBE9BFE3A538",
- "adv_salt": "5182",
- "plaintext": "74456B98E2FEAD8E389B4D4F032CB7A81664666C05C763864E523D",
- "ciphertext": "A5B41A2E1668084498477567EC9BE1756B32AD19E2AAEE2D7B0CC9",
- "metadata_key_hmac": "C5A709EE6A1294E887C68C4DBBB6E77BC7977C96667694BA404DA79B2B0D5BFB"
- },
- {
- "key_seed": "2A13635460A9710B09F643F2CD2C220B5CDD9F98F4953CB600997A0058E8A556",
- "ldt_key": "7E9D0633EA841E57B76DE4B61717FF2B31EF5980F1E02C52B0A41584AD47CAFE4F8470157DDF8314AC1471FEA14F4FB51A76B6D61A89AFA98C7BB8B8EEC0C92B",
- "hmac_key": "3802765D17628C24C6223D0E8DF9AD55D3B277DE4F85708B6E96F29319B0D718",
- "adv_salt": "6998",
- "plaintext": "F7D8B1AF30844708D179106D5E329C02D72A7CD6",
- "ciphertext": "5AF1C2E04FBAD114E66BDAD7530398F572559757",
- "metadata_key_hmac": "430A3A52FAF79431C1A891AA9C3D705B17626B829EBCA6F7AC095CA938D08400"
- },
- {
- "key_seed": "C2D25F59658A7206D3D749A794B681D12E6E0312DC1B45A8877A47BCD4790EE0",
- "ldt_key": "E62E721FB8BE56F5ADB52434D778EBEF25CAFF0E184D448548CF3DD5372ECD4F7B8F8157CAFDC71AB78BAC3A236BD4A36F7D55ABA6E3091B3FD5CB56D4F9E5AC",
- "hmac_key": "61B26D9D3FC8D6216ADECA830C1413590194FA25FEBBC84AF095BC314332E65F",
- "adv_salt": "36D4",
- "plaintext": "5D6BCADF581061C5CBBF0E6A40F17DBDADE5A7C7BBC1E8A1",
- "ciphertext": "5ABFAB0B064982F46175541B4265D8993E1DCA74120B3634",
- "metadata_key_hmac": "0EEAEBDF097DE3D854D3B0AAFD26DE8C2F0D96244C27559BBD6AD3E4F2706E7D"
- },
- {
- "key_seed": "D846015F3A085AFCB52243AF98B86D5FBC9FE00B018F89094F2598436136DA10",
- "ldt_key": "8C6B74CB4BF62487EA664B1CC00BE98A2077A0C6FD40A0042EA01695043C73CC3EE81D6E173977D2BE66AA9CC8236F299141B0329335ED5FA2DB77CD1FE44215",
- "hmac_key": "B96764DD552A8A498A71ABA08B2016C6A476F76D5973BF8BD726BEB0BB8DD765",
- "adv_salt": "C9A4",
- "plaintext": "D4447137F58623746148C336D14E67BD3F29CD7C2D1274E0",
- "ciphertext": "157292352629229CE134A70B8BD146C252EB926C4107AE2C",
- "metadata_key_hmac": "BA859EC74F1438FB9FF40FE44DB76ADB052B81E65610E327570463AB751DB0B9"
- },
- {
- "key_seed": "73FDD0C8E8FE44D996FA9180979591EA2448801AF4A355590F2BB563044E968D",
- "ldt_key": "DFF7BD9BCE632499BECE737F13E127580E93233151360A07981C7E6226CDF2061A4CC2DE0FD7FFB770E3CDCEE6888C23523088DE0E257C37E01D24ADE12EC869",
- "hmac_key": "6B997391B1DAFA341868A6F6F69F88A759839BD46074CC36D84A855E7EE761AA",
- "adv_salt": "C576",
- "plaintext": "6728C48ECC39EB80D2919A307C96C1ED4F1F760D20C75F690FA2C0687282",
- "ciphertext": "9FCE1D5340D44AB1FDC5915B9DF3BF6362F24A6544B3F8A1A7D4250CE751",
- "metadata_key_hmac": "0FFF129F5B044196E5188692B687CA74501D7D07FF649AD73B95DA3C22C36FD7"
- },
- {
- "key_seed": "6DFD6D92352D2B434AE3AE589CC7AFEB88E35F76B95116805DE340CD6E456083",
- "ldt_key": "A448803AFCBBC98631397AECCCF9F16723CE9EF37A9E94920260A15332B722329DEB61EBC8CB7ACF76D4AFF0A6DF60C159FC179E32B4FCA9A9237987699652C7",
- "hmac_key": "BEACF74249CB4AAC9A74FC2E817D8FF046B9279CD7D51D0816EAA9A2680022D0",
- "adv_salt": "A4A0",
- "plaintext": "24C60DBD7A43C2B9C7A5A4F17991FAEE",
- "ciphertext": "8EC524A39825365B8649D164FBDAFB9B",
- "metadata_key_hmac": "C28849E4E7C18B1E42279AFEBC21866DC63B5C6EF1041568029AF4946950F208"
- },
- {
- "key_seed": "5B556655C181D91F2571D072841B954622958A26E8B5FA22329BAF285EEC95AB",
- "ldt_key": "88367E8701FB603E6ED5BE0D1F6DE4C1AEE0E79C9196B52F8E84B9DD8D60C16F7724952762C6DC2893F8287DFEF80A55C49FB417D2CF65B2CDE617ECE0062877",
- "hmac_key": "0D686156F80AE8C1AA30706CD0ACA0CC860609ADD16948470CD4975774F55C96",
- "adv_salt": "E675",
- "plaintext": "712B448A4315C640379DE064133DE0E1",
- "ciphertext": "9E6DBA6F506F10E84ABA9D777D005919",
- "metadata_key_hmac": "E179FF8EC43888E59573387977A22EB28B5DB9BD1ABBE132836E63E66DD0EE7D"
- },
- {
- "key_seed": "7569FCAD04512A9022654D0C42FC09E5EB23EE8CCB2BCF015752DC23258DF74C",
- "ldt_key": "1EC058B5ADED8CAD6FE9E7C519CFAC976E464B6F1B2053457B60F0EDF67E9A69F0A3FFE26F9D9F1DB5F9E90CB5C44F765FD80E4B0D84EF0D20C3DC1CAA148B57",
- "hmac_key": "4C0B183A19276F6CDD389EF363E7B73D26F52EB72E360817458F8A355B6A52B1",
- "adv_salt": "ED54",
- "plaintext": "3F66104FD3E653B05F7CB8C436FDDE2830E743422C9FE2",
- "ciphertext": "882EBD21E8AE0B65901B274B564F6F7EB27530735CD991",
- "metadata_key_hmac": "95E2D4BAA5D346CE447BF0CAE77B3136D6EDFF7B73720B8174CC7FA6AB25C60E"
- },
- {
- "key_seed": "D734E43327907951231721D8EACF1CE1C67CF8344DCA240625044D41609B66CE",
- "ldt_key": "A2500D3D317A4D1FB41D65DEC6D308925D093E0FD1AE16704F85B53467265681AC76581CA18EDA7083C79EE61ABCFEF9C1E0E40D8A676C6A122D91C9691A00D8",
- "hmac_key": "10426F35CD6F93E45EDBF4B1AC284B0245F79126F7F713B82D8903C869989C26",
- "adv_salt": "A66B",
- "plaintext": "375C7E3373E88B579D4A4D87E5B8ADF9657180BBD647",
- "ciphertext": "1F88538743A5DD988CEA35EB1B60DA18D9A0DA08EAE3",
- "metadata_key_hmac": "C9B24D070C4E1D9F916E514D8E16CFBD749C2E788157E35B622D437B91423BEB"
- },
- {
- "key_seed": "75BA47FB5A778384C5C92159BE3D12E13DAB1466FDD200A2FAD9EE3E624392D8",
- "ldt_key": "12A62E7C37C689305D617E243172FC5F608B811B0F07C5616264BFF94715C193956D1D714D2E7D10A437B9F3B412F50E2C735B3481A4D857B39C7CD090277DFC",
- "hmac_key": "F1ADEB123E02F76FB0AE9CE759D0FB6D23931A806B9FBA3159F1BF0B5AC41DFC",
- "adv_salt": "3BD1",
- "plaintext": "1C26BCC5456D118D9DE9C0FEB5EEDA73F3BA16CD0914F9",
- "ciphertext": "B819FF5268145E99A8EECB759C776C426BCE55163047AD",
- "metadata_key_hmac": "CB31D51393D442A6A13518E02CFCE0F0301E8AFA44FC60B853057907F116CE68"
- },
- {
- "key_seed": "AABD54056C692FEA551A7199FC978C374D3CB32527CAA8920AA839B6F6670C34",
- "ldt_key": "A84809E217F9E1AAB6A3C11B0DF47AC0F7A15E8D4218A842299180EDF56FFBD1E71846C83622F7014B6DD3EC1B1C3974D632F3069C88E477A124180BE903BF07",
- "hmac_key": "F1A83D7FA59840297D52B05C679D66E40657402B0C501F0B8F139B4385F392D2",
- "adv_salt": "8E00",
- "plaintext": "06C795A1252A9BC6B8C71DAC3D856256F15BE1068AEA86E7BC68",
- "ciphertext": "0634B91779A563C03D70EAA14E0B0C7E6A72A32D5AA3F9D27D85",
- "metadata_key_hmac": "ED6417BF208F7810B9C4C7C504354EFD629A00E86B7CFA2EAD5B2103249C90D9"
- },
- {
- "key_seed": "28778BF659017AC84B559C88882D9B309AD2C92C4CCBF2F8E512638D66C91733",
- "ldt_key": "5CF94149484918D409F3E6E0235883118044976F2D9379C09AB55A875676EC6A9C80940DD890FF94407DE477EFF0F1F0A7D22BBC01592FA6AAA07188C02270A1",
- "hmac_key": "4F207486F2A8504F64705AED1B1D197A26F26F284F0E3A8DE44326F16968562C",
- "adv_salt": "E311",
- "plaintext": "32B3AF5757B29A5DD9802E6C2CDBC5BCFAB6E083F0FC87A4AD62CE85BFF655",
- "ciphertext": "7A4E0A1435A24A98005254F2C9AF92D3DEE98F8CE1B97C2508C1C0E3957E63",
- "metadata_key_hmac": "2ADC12BBE2A3C72722721D8C5B43A351CF2CDD24BEBD3FEF1FA186A9A96BF11F"
- },
- {
- "key_seed": "50A99CBB1FBB19263E42AC51D667C1C0B7ED680B43C147F0BAD56279722733BA",
- "ldt_key": "2AFE26490D490840CFE7332BB070E05BEC9D93981469769C2FF03F695180D828A9B7273F4B541DD329E7E9907A91571EBBB832AEE61D2A7FCACDDA689C7D24D0",
- "hmac_key": "6C2AA4D3940A672CE7ED32E0B0C67D7BCAADAFF90643618482270C86B2789ED8",
- "adv_salt": "5FAC",
- "plaintext": "DE38D1F851723F02BB74C7FF5FF813AC2DAF7880C08D0188F300",
- "ciphertext": "1844A6EE5F4457EEC3906B9430752853EE032577C425119F611C",
- "metadata_key_hmac": "522B09A18E7168063FCD85D0CBBB46E49B199D32FF1B853D9F5A2876D28EA24E"
- },
- {
- "key_seed": "9FC111AB46387C47EC77ECAD602AE550A411D4C433763D2FFDE06765728C86A9",
- "ldt_key": "3F05DC0D3297958CA2F3441821C02E48013C92059D85E43FD239B806086D73C81EAE6C02050169D47FDE796456A0F02EB595672C9A740091BC7705395D509B3F",
- "hmac_key": "F631CDB66C21398092FCE374365D385509B6F89C7AC5754AD931E622F8DC6B0F",
- "adv_salt": "1A27",
- "plaintext": "839A7F8CE22B6796D4AB453254A7E06DE4004A9F7F41FE",
- "ciphertext": "4EA1991ECCE09408C1F3E818B47965062AA73D2B105F86",
- "metadata_key_hmac": "4804DF0393C3AF50066C999B7593E9BD09C55F5D5363DA3ECBDE091A9A5020C6"
- },
- {
- "key_seed": "9085A08B9A529F4700953F9214136706C3AB56B09757DB19A733F646BFA689BF",
- "ldt_key": "4261798242A6419B04C3C8580D45BCCC14E955085F1AE04A528FD085725C1EA92786A33C2FE0361665EAD307F606B1DF250C879171518EF33E3876A37F694A0F",
- "hmac_key": "5C5D9187A1291CA90EB9EBA77F1AF3288FA1980332D874529AC94814B2E6095B",
- "adv_salt": "BD05",
- "plaintext": "5F1A621C4CFC22E0E4D622DAAA70E5178B",
- "ciphertext": "24EEDF908E842903668F2501CCE5B1C588",
- "metadata_key_hmac": "3769A0AC03460BA4A4D99F354ED894A292994B469BD225B91E852805227BB60B"
- },
- {
- "key_seed": "BE2D76792684F3AE542005CC584DEF72794882A9F239E8907F9C4D077A75753C",
- "ldt_key": "D2D7C518BC1295F1D0D11D19DAFD49220498F8942251CA0EC735710C3A4FB706B34EEDFFAA10E74686E1C2705BF5320645349AFCEC4391AC9F064A6ADDFC662F",
- "hmac_key": "CE7988AFB852B691E917B6B40DFB760AFFCB5E27B6C547F3B124A0328BD2BB33",
- "adv_salt": "F712",
- "plaintext": "5CF5B0B548AF0BC3331C4425025ECEFB910858B3BDF0AE86618AD11B72B8",
- "ciphertext": "CDB48FADA18E4F7E0025B62F3D052529EB4CEF8E5C0996A7C5CB9D3EBE9A",
- "metadata_key_hmac": "6C675B3B1471235F10B93BF06919328EE45F91CEE0FCD5262B08DE13FC1E0C7A"
- },
- {
- "key_seed": "A71EC15A86B5503D5B378EA02B12311B3E3666745687941782FF0E449DF555EA",
- "ldt_key": "52C143EE553514DE2237F3D32B571AFF36558EE58640BE1DDDE6C94BDEA34C59A694D2EB0E0839852AC2BE1FBDF288603178E0A18FAD133115E2CA7E6608EF2C",
- "hmac_key": "2E503289FEFD8B4E8B5E93ABBE92A031869D7D8914238AA7A31151486E5BC091",
- "adv_salt": "5A5B",
- "plaintext": "4F433B75A1FA22425FEFE0FD7AC8E402FA1431E7612EDC99347851",
- "ciphertext": "11B6FACB1B39677CB8C372AB9357043773FD32795FF08B4B3E3323",
- "metadata_key_hmac": "29D4D89A053A7857630AAF59E23121429E5F47F1269E6B83FC448AD00CBDCA1F"
- },
- {
- "key_seed": "F05EC969A52DB799EBC2A857313FE6176B7F2D555594F2BB4BAFCC19040C7AD7",
- "ldt_key": "FF591DC26B212260EBD43D17D08D6702732F5EC1E15A420EEA406EA2BF26D7BA1460F9836D0BA5043BA2B45AC62CDBF279B99BEF728FEA14F0407BA453EE12F1",
- "hmac_key": "9894B05916662C8EB0DA8ED3CFBEF4C142302D38DBCFF6B0137714398682D635",
- "adv_salt": "7DCB",
- "plaintext": "F001995BD1175042055FB5E9F65CA877065D70538B3C1A1C0466",
- "ciphertext": "C76A2812EDEB6FE15A71A87C1E774CD7D1DD8F0246ED5E95952A",
- "metadata_key_hmac": "7165BE02DA03AF773DADEB1107070A1E66F96426AB17624A6E535EE991D6BA97"
- },
- {
- "key_seed": "332FA48738B516DC5C7DE58C4922E7AB27912E44EAD434A3D758A57936606A9E",
- "ldt_key": "1F79FE122B4E585A898B53172EF5D29DAD6EEBFF7B620A43B79108083CADBA5E1F347D044CB87420003E5CCA8E9B7F2C5BD8FC91AF63924DEC6445A135BA346C",
- "hmac_key": "E4AC9347677DB2BBF6730D4FD7401A919E2356B5B130F0099648220F7D170280",
- "adv_salt": "E54C",
- "plaintext": "B66C2F1C04892188D338090EBB3B79B10184F8AF36785EF1BCE870E07A",
- "ciphertext": "8A12EADE61D558CAFE09354AC08484C3BB2309294203F009AE552E0750",
- "metadata_key_hmac": "F097551D91430B3FEDCE67D1B95A466D04AB1C361F8ACA47676387396C69EFAE"
- },
- {
- "key_seed": "83E1C95BBB9D0F2F5FF04C04135C44C74F7FBBDF0A3E954B083D28895636F570",
- "ldt_key": "406B4A3B05C30F607342077EDD7C0B1AB5A96861F38EFA221A804F691EDF82272AE1850C223890C1E2CA3624974ECA2EF0EEAFE92153D6B2A76FE8A50499F3B6",
- "hmac_key": "9AF63F1E511117BCABC058DEB685486958AEF0DC19C8627F5CD004FFF3EC0297",
- "adv_salt": "1B1F",
- "plaintext": "BF1144EF14BF286F6EBD79A890CD19EA560D12E0BC3A33",
- "ciphertext": "2BC58BAC575A72346D9198498EE020FAE15FF232AC5C8C",
- "metadata_key_hmac": "E6D8AE6D060801CFA0A7DE1953C82415F712BC3623813FDD79EA8ECE27441967"
- },
- {
- "key_seed": "B16EEE688EF2E975226581946F2474FE9471566E9D7BC198A4E1E59D9E924ADA",
- "ldt_key": "AE056783CE871C8F87BE39C0BAB58DA475E64232336B36FB7EE0CC722A50B015D377F75A5EA28D05E8DBD6A30D6D159C8BAB40DB8BBA2C7B65AB3CE032083C2B",
- "hmac_key": "F8CCA6345A63A86B3C98608B3F81CB87A0101C6D6472C8A233C33B14477E01FF",
- "adv_salt": "2277",
- "plaintext": "14D8647A5B948EF857869BBFC7C2A4386433",
- "ciphertext": "BBF95D28B4F8E944E60618FCF36EEF7987F3",
- "metadata_key_hmac": "D50F850029616818304DE732CF9C0F9E0C2E1B38052575B3CF3EDAB4E09F047F"
- },
- {
- "key_seed": "889A1CD66AF641EF76A24C80DF360BCD030B39AC12E4795DEFF88D9310937232",
- "ldt_key": "56C0941AF6C85BA3F6B4F2B66AEEC0E166B2EB1FB0DFD97F3032C9282145D311C44BFE289D114628E0AE0944A6FAD1DC6E6078B66659BF02E2053592731CF2AC",
- "hmac_key": "A7CD55C44A009CE9083525BFE3A2D5A183A772004BDAC2B7D41466AF1B71C020",
- "adv_salt": "35A5",
- "plaintext": "1101FFFFD2839177C6D1A49B34128840E506",
- "ciphertext": "B379D7F3AA98D8B4613E961EC0C6EC435316",
- "metadata_key_hmac": "8E04E11B52FF3FF2273C615F4B1E4D8E195D19B35FD616AA38E009865021CB06"
- },
- {
- "key_seed": "ECF470CD37ED8B48640531F3E7D4AEB728B6CBD8C9C0B7D2510C63D93FF0A091",
- "ldt_key": "4263F97589C7A435494E2A9F40E6F2B47B9FEBFBAD5C2A807AF56D52F88AE2487BF354179FE0DB947359D3B94EB7C251EE678BCA19F8B489693732A9915D9AA6",
- "hmac_key": "028C9C0A2EA89C0ECB9A9B96C4F1F9BA65EEA131054725E0CC5DDCAF203CA0D6",
- "adv_salt": "61D8",
- "plaintext": "DA4D5B503C04C69497E080CA76CBAD43A3",
- "ciphertext": "DE3610A2D12F3C5C41A1525E09D74EC357",
- "metadata_key_hmac": "A5BE078DA1268DA2192FA4463E3C954A97A85CE1537CB223C7FA594E74A4F0C9"
- },
- {
- "key_seed": "86E881B42649FE24CE05235C224632BABE8E1405A24C0DC28D24FF0AF7B60B68",
- "ldt_key": "43299E37E6E8BAAFF036AFD9D368E9B1F5CAA1424C22C7ACCC395C1F6645D31E5433E86EA21CA62CC115A2857AE12C01AA26F697845ED26FB484362E283E53E4",
- "hmac_key": "74D53B450E5844276EB6B1B54E3F39BCDC025F37DE4CFEC297704CFC5163DA40",
- "adv_salt": "16DB",
- "plaintext": "757B10011CA10BA4A407A7FB9C1F5E7BBD51",
- "ciphertext": "E2056AE97E26E7FFBC8F331EAA84B35F19FB",
- "metadata_key_hmac": "B8EE570FFF1449B35F26B19A4F2AB43CC26AAE4CFF79BC3170CDCC45213FADB3"
- },
- {
- "key_seed": "EE5337E8A310C7C94F216740C691A688FE8FF90CE183DAA33D7F042F4B50A1E9",
- "ldt_key": "F9A70A0B325C72700845305DA134E227959BF8F0521AEE38DDED4EBB93CCBC09F6C2113A5EA658480FCB52742BA7FBF104D0A93A0548ADB4313A7EE2E6814F4F",
- "hmac_key": "590CA973F27E2399B39D3E30B1ABCAE233C02B49D8E35EA708B322C34703C44A",
- "adv_salt": "CC80",
- "plaintext": "2C37AFABCD0FED7118EEC7DA89411F97261F4D2C84F8",
- "ciphertext": "D7BF38B9D878A4FBE06EF3DBA6B9F2FE0CE830366ADF",
- "metadata_key_hmac": "D9522B40F11053E5C57960A0D212C6A126B3AD67C5E12CB2DC85A5D120659E64"
- },
- {
- "key_seed": "4526C12D8ABF2B204754265B932ED65C1C272217F72F832D7ABEA54C31A0925A",
- "ldt_key": "76304EEE88BE11C0FCDC103F80E3079B25C7F0FDCB97520DACDE9E0E65C6F1A0C3A0A9DEBD4BD0EEBAC4D65F7E9EB1B5F13FBA910679FA424AFA95B5CF9739A0",
- "hmac_key": "71E41C3296E3C397C3150CB29C36875D4714C3321FCDED6E001D9EC65ACC9C78",
- "adv_salt": "D2C6",
- "plaintext": "B655F13794C279D54FC64D87C9594D7811D2841DF9A62D5A",
- "ciphertext": "57783E5836E0811E618A405063779BA35A909A1E50A0507C",
- "metadata_key_hmac": "22BE5456B855489256715A0931A5D686F5B87C6C9A0992E6A694EE3BE8FEF746"
- },
- {
- "key_seed": "461E80DCDA74BEDA35ACE9376E1EB05AA554771B9E5959EAB959E49A0E559300",
- "ldt_key": "7574CA69BED05806C13F6901A5BBFA80AB3CC00DBA0B934DA7CE94064D7B55952941E3E81FC1EE7C61EAF1B30BE2141AAC6C7FFE8D0C33E1114A84FCF15EEB02",
- "hmac_key": "152E43E82FC16A384EC3467EEE5B6CAB9A28CB31C7FD4E780989220D81BB68F9",
- "adv_salt": "4FDF",
- "plaintext": "773F77B30DD0BF7E16962FF93E85F3A0",
- "ciphertext": "39A008F72CB3011DC67A472316B1AC89",
- "metadata_key_hmac": "B41FC1515A21B25773032D7318A45DB772B5373B6E7BC7690E1AD7671EE98ACC"
- },
- {
- "key_seed": "E5BE2F0117C32F3E6476FE2D60F84EB86EC676468FECFBF0E5FAB83DA50DE853",
- "ldt_key": "1AF39EB2A3C9A7C385231A254EE36E9E2889ADF9908CEEAFF6E642F4E301AEE49109F3AFBD0E5A495F614D0DECBD3AC21C2246B553DA4320CB0C4F0C348D5FD7",
- "hmac_key": "898F388F7584FDF404382D080CD3F0F8164835A4026C3E9BFEA691BD42D337C6",
- "adv_salt": "65E5",
- "plaintext": "1E71789A9256C512EDE163EE6615BED688D90ACC293C",
- "ciphertext": "72814ED024666464596FD640C5CDFC070A122B0D5138",
- "metadata_key_hmac": "35F34DCEE430E78956E84CE300F70D8D16784ED1CA1F4E51D20FD0AD96D2AD64"
- },
- {
- "key_seed": "DEB8F3AB02D4CA40FA5DF4A8E0C755935C66113E49933EA39D5094AE9CE3C938",
- "ldt_key": "5C51E916F1A2E55A7CC4167021A12241070FB268C481C5A442A341A339782AC383CEFE0ED38BA27C5E0950CFD98AB131C0EEAC2333B8A881F69F7F540D4174D9",
- "hmac_key": "CD3C321F51017F76C486C86CE0909F6C1448CBD6356787EE2D8ED61E15993CB9",
- "adv_salt": "B3E6",
- "plaintext": "FDD913B0BA6F414E58EA34611CE0A4CF69B6",
- "ciphertext": "C3534F67F05E0158BF61250C91DDEE5CC07A",
- "metadata_key_hmac": "B68FCBA4A62F48821EE88DBA6C150ED4179FB22DBC355222DEF00BD9B7F7DD94"
- },
- {
- "key_seed": "DDE4DEB7FB1509B4B94BD641F49BFFE25216C7800BA49DE9774E0B3E00F6B1F8",
- "ldt_key": "F0022155C9FE86F00157652A1AF200182D2DF9BA33D569C7B047E664C8B675C6A3CA7BA70BFC9FB42F0EC7B4031860B33A6127F777F264E10745CE34162E38D0",
- "hmac_key": "EA0780167FC4307FBA5AF6E1E3DCDAC804E04E640C3E901ED314EC6168477255",
- "adv_salt": "9F99",
- "plaintext": "1EECAD555BBF19AE0466800BF45934049BAFEFC17F4422914A5E18C3",
- "ciphertext": "41E6559722EEF73DA8D074CC8F16928B2A9E7641C8DE05F20E8E272F",
- "metadata_key_hmac": "492F0C9C8785C62C7DCEDD1FAC417F955B655E155082E537294AB766B6C6D0A8"
- },
- {
- "key_seed": "44CB781146A3C78E6E8A208DBF6DEDC942DCDDB5DAE79B2AECA40A5D283E6958",
- "ldt_key": "7D05A9CEB622104C1C613DC798EA67747C15045BFACC75FE83E64D1E559E9FBE5F8BC1A929938BA5163104CAB88BF8C351C9A80B40B8647C350D0C259E196BB4",
- "hmac_key": "A876711C19F6F84BE72A67C71949E2E219334EA17808DE188C61CDF903E62888",
- "adv_salt": "A42F",
- "plaintext": "277FC7842DB8B13D285314F3970AC2F9C4566C",
- "ciphertext": "791F4347A4B3480761E0EFC3CE606FA3A5DB3A",
- "metadata_key_hmac": "019A49B77346288594C858C6321C99858927DC8244EC07980728F7898C53B9C5"
- },
- {
- "key_seed": "CCC6BBD4A930ADAEF8381C0452577F7E86C85F0C37F0F3F51D83BE608DAE9729",
- "ldt_key": "050C71B86F9E827BE2E90E0145917FB64185B4D8A999920B8FC795D0BBA3FD5A56D955E7125796A1D2F8E411FB3B98FDA9F23AD5BFBC0936C073105A9576043B",
- "hmac_key": "80D960AF3A480DA154E0B219ED87B57D1A16A82CC1156C4281F5EC2BFED99228",
- "adv_salt": "3A79",
- "plaintext": "CFC608FED7EBC2B62C40878DC32459D6CCFB3202787666",
- "ciphertext": "407709B5E4025C8F6850F820E542B2CA448A895A12C17C",
- "metadata_key_hmac": "B58D1908D6AEB8F13B67BAB587FCCF97CE502315F08FDA824A85C8B27106FC24"
- },
- {
- "key_seed": "8B179554B6C08F1CC2F308756ABE8DABEC0070D3B88E30A69A40CB7C0073D74F",
- "ldt_key": "04CA9C627A91E340C3EE0035FA320161CFDA6E3A98ED48FA7025276EB65EBC61293246F65C1A856DB729CA1B8EB8429F976D016FF9E05619BBDBA6B7AF6FEF42",
- "hmac_key": "F115187A05F7E99365B04CFC69025E64746C679CE382A5466030D2D36A84167D",
- "adv_salt": "950B",
- "plaintext": "263CBC2C39CE81978946AA45D2F80C4242383F",
- "ciphertext": "A2AB036CFD8A49A0D96BF0AC8CB8FC30321FB1",
- "metadata_key_hmac": "CCD14A8088B511E5D4391479030874AF78D51FDE0C7F3985DC91CCFFE7913A34"
- },
- {
- "key_seed": "23F0800D7FE07E42EDA7970AF9A3946ED4B71D4317E6275955840AEDB49122E6",
- "ldt_key": "D91C2E9862353F094F2AB6710A11BF6CE9E77D2EEFAE85FA0327678CBC6A50AB428B9A844911590B7836BBD61E473946FE412668DD720042C5ECC60910A013AC",
- "hmac_key": "5D6D0D8E2E3059E60004DFF0502432B3DB25E9A669BE95483103CC57179DA59A",
- "adv_salt": "09F9",
- "plaintext": "0EC8CA3BCF7D13FA317406CA74DD9518FBB4397DFF598C31929E8EFE5F",
- "ciphertext": "B7D68C3ADF3500F84379B71FDE36735042A5D1B82805947C61472FB609",
- "metadata_key_hmac": "10A7EC01CCC08C077A801221A6C5AFCBE2C7CD8DDC82EE6E3C7F7F0FD9A9C5C1"
- },
- {
- "key_seed": "E0C623A6D0CE4191239367A945BDB722BAA22D2E1A0D5247EF924D7C4CA68CFD",
- "ldt_key": "F0803A39DDBF4CD032EB231AF6C0074B3D44940FD54CC95469D47BCF733AF58FD3BF516F018D93646030DC80B618E1101179AED6865F77159F36811FE1C2DF19",
- "hmac_key": "E7D3F45040D509A1574A765B64FF3AB8C26A0FC6CF1D40F234FB09249CA40FC9",
- "adv_salt": "2812",
- "plaintext": "A72343C95BC54391FD228738D24F308CEE3D9A42",
- "ciphertext": "B881F58C261E0D8C45775DB7C7888E4A7A41930E",
- "metadata_key_hmac": "43AF65784B529CFF5BEC931118C36F7C70462D82B5F5888B0E78352BB2EECFF1"
- },
- {
- "key_seed": "0CDF3A201E6C43C1892D459351D83A5ABB549755626837458658615CF184DD17",
- "ldt_key": "5400C8B5A3561E13619F4C8392575A4E0150C46607BE1AE71C09A2ED031BFC2857679460EC9E4477F6D79C34AACBB8EB385E1875469010A14A3D34FE47210096",
- "hmac_key": "5C9A65AD78DFBE78506F6E39EB32D95783A760DBF18C65DDEFC4533AC2BB703E",
- "adv_salt": "7EDC",
- "plaintext": "3070FAAA1F5E0F689157D8E5BB0A5653",
- "ciphertext": "05837C74EAAC8D82208455C1F9DA79B7",
- "metadata_key_hmac": "058486F7D7262DC6162CD2680AF73522ACC29860023A7153210B2F17705C4EA3"
- },
- {
- "key_seed": "F4595E0315B783D09D0ACE96AF55E417E6B88EC9D6B019A55736C6BCBDEEEB40",
- "ldt_key": "95E4AF265D858FEF7F15C542DBF1E231C0433634EC6B8D3BA12D5116897706CEEDBE8143D4A9F186C91E22F6E8A9CE05BC0C867323888364D0E86CB1FC9F3123",
- "hmac_key": "F59932F5F489B3E304B4D055C368C851D0DAE57F82D338989BC2674B5966441A",
- "adv_salt": "1125",
- "plaintext": "BE0E27833763C0E7E4667BA54F0E3B2448",
- "ciphertext": "9A4B53BF17C69A1B39E72C9AA89074894E",
- "metadata_key_hmac": "A8F3AA49B8BA760F25991D609679553307DA29922A1AEA0B2CF57D1D7B28A6B9"
- },
- {
- "key_seed": "F0ECE6EC0A3DC55DF7BAB18C41CA0C9F5A0408FFFCAEF32D3081C9DB335C7F2B",
- "ldt_key": "CA3E68D26BE851EBA1782C75D10EAA039DC705B0A44091B93F1729E149D5D1783044D9EC2528C13F08AB5AF780160FB59978B98605C1B45F7482BD6CF4FE89B5",
- "hmac_key": "152FD69D75C30961E52263BFCC0CD5196F186543289A96D38E2D22662070EBAF",
- "adv_salt": "FD52",
- "plaintext": "101076F25A10920A37E5AA9853701CD94EDE8C46377923A8E7AEECF73D",
- "ciphertext": "E6B61ACE7739628E83EA5DEBACA6E815455A68F9ABF5F02BCC41AD7CE7",
- "metadata_key_hmac": "9BF6AC832411926D45BDBBCCC16DB131270D751FD3D77ED9928733E460740478"
- },
- {
- "key_seed": "6845EB5792CB894932F50C2CC19DDB0029A36F362318E85273BCD87DE2CEE71D",
- "ldt_key": "E467836405D7A1899ACDC5BDAD71CDE12B2ACFD9A17CA9B643B3BC5D9DA84D4DEA9BDF84A5C511E0F0CF43FE51636A6A4D466C299254AF609E4B5C37DD7F65FA",
- "hmac_key": "F47BF42FD2E4BFDB11832B25D360CE73F5DBAEE9EF9BAC9649B71B39A904D20A",
- "adv_salt": "2B57",
- "plaintext": "A411BA034E8A4BCCC3BB3EE9ECA169914AD28DFD2A621BC1D6AA7148",
- "ciphertext": "0AE76BE8E290203BDAB2562944FCEC168ABEDA17360E8F6EA47E5031",
- "metadata_key_hmac": "9F60DE167B3EF6EA0E0FB92FAEE7641D443BDB60AD83D823A485213183ECC301"
- },
- {
- "key_seed": "7DD79D618E3D46D6F2F568D4937F7293F0A7C818133A2A2624A30678EF97F9A7",
- "ldt_key": "3ABF1885AA6693AE77C62F9C6DCE003F923B371A17EA6994F35B68AE9E29B5652E829B340BC3CF455AF516E84FA29041CAD7F8574D842BEEA84B683F3D6AC682",
- "hmac_key": "7B672E9CF695CF0E3F4BE0C75D58FF7AFBC07E09D82B02AC609DD009520D13CF",
- "adv_salt": "D088",
- "plaintext": "209E53F8D180BA340A62BD7B6C13390A89E4851B520847",
- "ciphertext": "86595462A4F6018EF97376786754982C920474A985A733",
- "metadata_key_hmac": "AC1FA00AAE3DB0F94FE860812724A7DC602B29E89179D43253EAB0B1B31CDDFD"
- },
- {
- "key_seed": "886983BED2634BFDE5825B60E979F869091EFA35F4E4E48E1148F4CEA59E7EC6",
- "ldt_key": "8D01837EBD1EB28BA3588908337F9B7DCDFBEC0ADAE46629B43B5B909C4A54FB63C67CF6E8641482A8C40440510BF6DEEE6A646E213A6858F61BC8BAB15D92E8",
- "hmac_key": "410E201D89001A2308BA7395AF93031E09D275ECD2723BE229F0E241AAC79FD3",
- "adv_salt": "752A",
- "plaintext": "795B8C99EE3B8DA04522B32CCDF964C6",
- "ciphertext": "BC830AA0C3C07AFB73EC43C341B472F6",
- "metadata_key_hmac": "ECDA1D879E65F4C576C1B07C8AE57659F96863D1764A2D0F3D966757BDBEA59B"
- },
- {
- "key_seed": "3B6AB10F9814492725455760BB62BB7AC2DA22DE202649B8931885859B2DD567",
- "ldt_key": "C8960538AE52B2AD074BA5EC0249FD22F6E7AAA000348C59B522E3ECD6A35C9A324A59D1DC734CA0228A0D43AC9F8E809F65041F2F3BA7A8227335B0C5483CD3",
- "hmac_key": "ED3470CBE882DD7A2420F9EDDE8190C182BDD6F41A05A93BC7F15F70324DB9B4",
- "adv_salt": "3BB1",
- "plaintext": "9D5F7599D4B4A44B7B8B75E64B3371882AFFAE8F41B87238E1",
- "ciphertext": "1BB10248F26B45704AC0B1A02D0F700C6D4D10713442A15DAD",
- "metadata_key_hmac": "FBF4F33EA32E3F888FBB55591CE60BB9844C92DBFC9A8BD54ABE6AABA881CCD0"
- },
- {
- "key_seed": "1FCCFA2BFF7C4D711678145842EE6575F5AB575095C759F4D02AFE2EA8BF613A",
- "ldt_key": "F5EAD66A08A058B727CFBA95FF6BEC745AFD0507C7E4567547CD8C44786222BAF3E77CF5C1CFBCA0DF6035113247F7B55F248D78B24BACE71AB3FF154760F1C1",
- "hmac_key": "948A90DA3B1BCF09C1F363E92FBED428C25514E02B7D90DC1D58B116DC930AF8",
- "adv_salt": "2A58",
- "plaintext": "62C4B72073C76C3DAE8343EDF66F5C492E4978C67C199149",
- "ciphertext": "510260D7D04687D5E1E92A964360FC145FA20C5D360EE8E1",
- "metadata_key_hmac": "E030F6966A67F333E6FBCFF6439EBFECF6BE0D3BB7E9124B3237F1B4176F8BB9"
- },
- {
- "key_seed": "A00B6671AAE6906C1478CF7BF2F6CD018E0C93CC645A0F3A14059E820FCC6AA1",
- "ldt_key": "5A9C17410FF455E4C62E97605CB9FD196D5CCBE42EB9AF3AFD9B5302DFEC3CDD400EC95F5110CB95300E58CEEB85AB81988BEB9DA6E533AFDCC27C973F8C8592",
- "hmac_key": "8FC128773B31D7C6B0CEF342DB3B958504E53445CF14651B8780D90ED83B8EC7",
- "adv_salt": "F08B",
- "plaintext": "06645B1F8B0099E32FF1F197744E4498577A",
- "ciphertext": "685DFBBE76C2486733AD7CD5F11F1D1D0431",
- "metadata_key_hmac": "609702A78C0F810F05CD25E1B42D992F5162CB3348281E554E1CB2754D71C7A9"
- },
- {
- "key_seed": "9A1EBDDEDF77B01E0F9389D406C640B64F86EE57F142A8DBBC336B28CA9ED9CB",
- "ldt_key": "84A871D9EF570E2D4022DF76A346526FF77A203CA24F159E84DE68253BF42E52F73522ABD09ADC290690D3CC97824494FA5B7C1D57F1C9660529918A08F8663A",
- "hmac_key": "7451E1A8C1E351514AA3D427030B55F54A117D9D2E06CB53277306D8EE1E81AA",
- "adv_salt": "3AEC",
- "plaintext": "3E8EF057611BB2A24FA9A1FB6277BB5E4834",
- "ciphertext": "6747ACD188E8E81E68AC103B54B1BEB0CB11",
- "metadata_key_hmac": "21F87E9AABB821F059BE8428083A3E2D5C921D6E3C334EFD996AF80537EE2347"
- },
- {
- "key_seed": "02BBE706B5607F60E480E1B313751D9963D8D62C85B04701248DBEDBF2E95E6F",
- "ldt_key": "C674CB7FEA75105EE6CB2287E260C7D4F1DAB9637E4ABEEB9DE0201EFED078103408986A25BE5136349D9E9DE49651D73EA07A1834D5E9F9347177051E153D22",
- "hmac_key": "8AE91FD62D9BDB9D876EA454B0514C1280983A0D4FEBB5EA2D1E8D859D9A872E",
- "adv_salt": "00B8",
- "plaintext": "85ABA9ACA14B5EFBCC63FFA1E303F13DB2CF78D4D6124395FAB3F1E28984",
- "ciphertext": "876DE4842160DBCFC8E2FD5F18CE573060B850FF2FAF0E5CE2D65534B7E8",
- "metadata_key_hmac": "9560019ED9FC93D3D744EF250DA756AD5A394360E55C95E1AA786D484EBF8FE9"
- },
- {
- "key_seed": "4EA4AF5C49173C1B8AF0F28E15A1C539398591A2DD0D0179438A4A46FA1E397F",
- "ldt_key": "F452E293CD698F02560E44CBA21D124AFADB3E75290F915F41142A6EC7E0F729202F11629A2C7F54420B8A5D5E488C88C9303A908F7E398CA9D85C22CC124DBE",
- "hmac_key": "3BFE522958CA6DA64492B62B079736B32733108A743A3F308B3B1A2EAB6F526C",
"adv_salt": "189B",
- "plaintext": "8D054FBE40F231670A5E5001BC68B1852E",
- "ciphertext": "64398AD9AA2327DD94DD55D3B662261808",
- "metadata_key_hmac": "E4063B38746759C4C29D9D2DC0033DA320B107C07A778AAE5BB7E4F2AE096394"
- },
- {
- "key_seed": "F42A1BE211F5C2E9E2037B43CD68DBEEAADFE69EAA443F9C8888370176C8C543",
- "ldt_key": "002B3F92CE5D2020CB4F0E184A4AC41F5E948C61DE5BBA9AF06CC0714F9D9422B0C3E222A2DB03945BDD9451BCAC38E49A2B9C817F1D79F84683992DAF03BF86",
- "hmac_key": "E7C31AD4D5C82B23BFEB4B6E41123AAD54AA49894C0D7F2D6717538C75EC5894",
- "adv_salt": "B827",
- "plaintext": "6D2217B067C2CAA899D22621D6D4FF1040B20A59572E7C90CF5FA1",
- "ciphertext": "CEFBDF5AE9BF0AFC44758F0D16BF786DF0CB4A8162A2E4D37C7B95",
- "metadata_key_hmac": "859138DDCBA951BF2A1A55980EA925FCDA9D2C4781BE9F0EFC3AC5762145FE9B"
- },
- {
- "key_seed": "AE01D3D7BAB394780FFB0C8DFD142473558F87796539BA4FA6B02E12A886A790",
- "ldt_key": "7BC9A4C2BEC95850FE6DFD7BD9CEEEEBF0AE4FE3AC123C499E0B49D1CDFEB8F1FC72A70C8D7E764E2EF451DA3B5EF65D1B9467CFA8B5B4A958E882A8CC6A19AE",
- "hmac_key": "D25F40424B68CB9D6D6FBD421C90A1B7011281B90BDC624B506A797548DBEA5D",
- "adv_salt": "C420",
- "plaintext": "A1E9E22F5D43C023AFC9668C85062E89D811E169",
- "ciphertext": "DF37010A01172778F61742924B5B512BA0A60B61",
- "metadata_key_hmac": "F2A089D75A15F0D3739A51A2941C37A661546F63F92B9DC218C754AC4329660B"
- },
- {
- "key_seed": "70BEDA5EECC8D3DE9279AEBF08821AE91597C809492A5DBCC207D05CA24EDCD4",
- "ldt_key": "87E82E7F869CD2D4BF48A8E6002FA871A6400C14F4603C94B7A6908669DAB1A4491DFB74DBB84D807907A22CF88A334B5335B4011D864467CB555B1564903A31",
- "hmac_key": "1BBB2D77F26FE5F04DE6DE0CD30840FD5D5027B7851F9CCA2C7D63A0F360016C",
- "adv_salt": "770E",
- "plaintext": "47D9F1849D6694DF22FCDF35B98EA7A539345EA911",
- "ciphertext": "346E66B1735597E9F8D23195D009972A120D63BFA0",
- "metadata_key_hmac": "269F952F828590B58EC692CFB33476C07400989E1C1BE1534FC8FB905C47ACD4"
- },
- {
- "key_seed": "D507C742BA65C365B140AB279E7D5BAD07828ECA90E1045D546D4C4CE09ED6D4",
- "ldt_key": "3C68C30F21525DB68A56DB84A99A2B0050B64F680C7B642EA0D85DFCA3BF6B18D84BFE8661033FC77A3707F733CCC7FCE6D782BD139A2B722030F48BA0BE3D61",
- "hmac_key": "5FB552390E176EB1197E73C1474E889A2F85239B953FA0954DA8CECDDA64C020",
- "adv_salt": "5267",
- "plaintext": "9FCA0749B49D04C8E5B32A6DA1A9B52B9B1954FDB59CAD",
- "ciphertext": "AE17138F7C26808A840A009F38B2BE17BEEF6A5DB9F655",
- "metadata_key_hmac": "AA31DCB8A2C507B89209B1B37B19C136811C5467C61DC4D0D04EE503A4D390AD"
- },
- {
- "key_seed": "082C07502435C163C687BDF0D9C6F8C058125E6A957966A860C4C8FDE3BB76DB",
- "ldt_key": "0337020D34C0EAF110148BB6CF71ACF77DEEF96C9097AA0F90606C849113FC8A3E02E840FF6DC12DC4C9E8C27E2CCA6D6A5429403C1CF04198670279F1A27518",
- "hmac_key": "9FC12C38D43FA05ACBAB2A411E332B76274B0180BB670098FFB07327E96BB0FD",
- "adv_salt": "91E9",
- "plaintext": "2C40CBC0327A6AC756BDC545FC7656811607F325A6322D6CB0FC",
- "ciphertext": "4905857773E7C38F6094B77491AF04E07135A3DBBFD61ED63D22",
- "metadata_key_hmac": "745F00AA5C29AE6315E07C0AE2F7FB10C07C6D9F24E81E3F22921EE37159BDD1"
- },
- {
- "key_seed": "9AC7DC14A8E9F6E17E98CAFE93607A4A018752248988A774F3D41DE4CB7C254F",
- "ldt_key": "29DDAB2F42CA51EB35DF34053AFA8AD4304A5264C6E662D1882D91835AB747AE8BFA778125F3BC64C227FF8AFD8670AA64E546C12C6B094BB7080E0E6C3DD029",
- "hmac_key": "055323B77EAE387521938AA096C573535B24FE81EB659C9607509674228E5398",
- "adv_salt": "BB35",
- "plaintext": "47887D96343D6575BD51502D25E4D6F549B9",
- "ciphertext": "2051416E4B88A1406854EB29067BBF4692F7",
- "metadata_key_hmac": "6FFE9D0276F20DF381DF22F7FD691C94DD22B5CE0D83C2C7C10E92E55AF666A0"
- },
- {
- "key_seed": "A7F821CEAB3B6D1D7FC036EC3EE7D3F4417A5C404E16E36D98101AD14481E509",
- "ldt_key": "911E5548B9158AC32DBD213D4F13F38478D1D53B18E97E349675C82ACC9BAAC7332064BA5C46DAEDEC560D4CC61C23A82EE1D6EBF2E5034244A1CCDF32608B1E",
- "hmac_key": "ACFC4DF4EABE77E22C04E1D350CC8E68436A422B7868C0370CC3B2B308B8273E",
- "adv_salt": "E921",
- "plaintext": "F8AA31BC1DA3C4ED9A8D67D1231695174916CDA64C2EF1",
- "ciphertext": "ED4715C57B04B724A3931C0917325EBA202DEE87087658",
- "metadata_key_hmac": "1276F63BA4A898834F61208E74169B5CFD856DDF96483012D63B8DF05693E8ED"
- },
- {
- "key_seed": "05146E31D1D116189449455E6501366FB98EDA901511C8313F87B87851F50CAE",
- "ldt_key": "A336203EAE0CF9F55BE6C666C794B600E167F53F38F8386BFA167F26ACD924CC8D5C86CE9F5C87EFBE3EDD8951116AF5197809D0AF26FBB1BA6AE73CC3E87E70",
- "hmac_key": "666994FCE84DB1119ED4B98A3C7B8E90F3254B55762A384488B1102F090A2447",
- "adv_salt": "C346",
- "plaintext": "6A6FF037B5E075C69901ADF42CE1B49277DB",
- "ciphertext": "34893FB6D8DF991304558F1CB8D595B125E6",
- "metadata_key_hmac": "1FFDBD41802C5F9A5976342F548FC8B49015DFAAC72858B227B55BDC3CFEFFE5"
- },
- {
- "key_seed": "CB8368E78CF6BFF4E3F38E01C35D5EF9DEB72CAABD28173DC4DE59C8CB4D2ADD",
- "ldt_key": "A006ACEC50B59BA7B05C36121C3029E0D0C15AD9A644B189CF2B193B707856347D692798023A4E30B7AFAA3B94F83F1DE1C806CD7FFE9F94A95BEC6620136D3D",
- "hmac_key": "AF80B241E2AE4058794F8116C61E874AF7EB72E44521C1B88BF5D01B8EF89DAE",
- "adv_salt": "2DFE",
- "plaintext": "3ED1C991A0908D7D6A9F600038ED4020EFCCC3D9BF",
- "ciphertext": "C17E5EC275B2C3815E76C6993D2ABD932E3F931CEF",
- "metadata_key_hmac": "27347C08628562703834074132602FABBC18CF047E80B97F45D50B85348BE112"
- },
- {
- "key_seed": "47B05B1B7078EF2CD984B694BCE4FE8ECE2763F4BC9E5773DBCAE1E6CF907351",
- "ldt_key": "5B018A74552C4161682CA23AC77A96209F9770294B125754CA8C31BEA3E2587EBF599ACC841494CBCE2E87EEC76D7BCD678F637988A28AD2523E5BAF838D3D28",
- "hmac_key": "2AC31415141949B576D62AC0F09966823D4513E4EC90AD3BC1ED496B5B256158",
- "adv_salt": "286B",
- "plaintext": "2D12BD3EC6C4EF5F72116F3EF10602D1CD03463E3F8B",
- "ciphertext": "E18B3A18B6A506A10742ECAED5C74B5FA9A9008D0CA4",
- "metadata_key_hmac": "3A8207005DB61BEB73F1614EB70BC5D1BDB3C231FBEBEFDBA8D736C01BE563D9"
- },
- {
- "key_seed": "A731704EDABFFD225672895853D4CA8FF477C9D65A37552649DE0AFD5CAF9BFE",
- "ldt_key": "471AEE153C461CEEF36FF4F7ED324EBD360C4330EF9041DD15D87F36FD49BC142366F26C20A388E8EF31B19E3E503721B3039EB39EFDDE3EE0B1AAC921480AB0",
- "hmac_key": "BECD2B6C5469448FF69DEEEF6C603F1DE94DC9597A5F064BBE1F4C23366A6740",
- "adv_salt": "AE19",
- "plaintext": "577BCC8E5D86ECA8F738DD611E297E41ADF149F88CF396",
- "ciphertext": "4204C7C25C7F5F823B92B687FF977E1561EBD28227FE0C",
- "metadata_key_hmac": "00D88C16275FD4D4DFB56BD64A3344FBD50662A5AD408702944FF77B4D76EDF8"
- },
- {
- "key_seed": "755BC50C45FA7D7F512DB0251C28C61093DDA9EE5AC3444E5265AB773271D211",
- "ldt_key": "FEFDA5252816E78E13CD349E56C6D5C392606AA02E9BDFB50C6CF72FC4C728D894D4C6BB5E4709AAB0726B39AF1F3DF0C6D8896F16078E4ECB0B695F8E23BD33",
- "hmac_key": "7A732507A869D82418C6657721DCCBFFC49EF3AFB44441C93F097EE1DB47FA37",
- "adv_salt": "21BD",
- "plaintext": "851D152EFB5AA2A792221DD11836E2BB1553ECFA1AAB8B83C48770BD91",
- "ciphertext": "671C99E29BBD8AAD0DFAA6504229D28639C1D5224831FC056F72648D65",
- "metadata_key_hmac": "4FC52636E718CF7D85B429CB734EDEEC7559C5B7A136578ED05E4ACC9B6A4CC6"
- },
- {
- "key_seed": "2C9FEB9FDFABA657077CC7877C65FE30A257A58704E73F88A6CAFF9153790BE5",
- "ldt_key": "F85C764E4D4464D0DB36D0F0F463048EFE2089111630D8E9B7758657189730B9630B9DFA4374166AE2F79BFFC5892AFD560BA2196E219B5A2368A21DAB1C123E",
- "hmac_key": "F5289C28A60DCB53CC4278D34E4547514C61F504FE0F64F63F46340E3A759034",
- "adv_salt": "3FEB",
- "plaintext": "AAE2E09A0CB648FD9486FD845608F02766A9AD46F1CBD1287DC7BD2B",
- "ciphertext": "C060C326622F2E899B721E08B4B2E7713FD738911443CE134C882F91",
- "metadata_key_hmac": "DD496B4252BA8EE1A78DD00A3CB620CC29DF6D479B7F0B1E085EE1EC48AA4BBA"
- },
- {
- "key_seed": "DC0777F5390257D9662BEA2774088154796EEE18D2C6B6F294DA87A692EE590A",
- "ldt_key": "544BBFF963DA99EF4C467967375B940BA005DAF5C67407ADE630A000B7D49D315504457B5373A7987C6CEA690A96D5F7BD6E313FFE159300ACC428F3AB9662DA",
- "hmac_key": "3D37F8B0A5CE29C00D5295B2BB40670E9F08D51C020C722CEEA7CA0158512DF7",
- "adv_salt": "6643",
- "plaintext": "721FD2BCF08DD943D40E9ECA4B25FC810E86919F31",
- "ciphertext": "611522B0F0950EF619157C921ADC2D134F18B93C10",
- "metadata_key_hmac": "6A18A836A710EA43DC92FD5321ED90893EC229FD1E035AB776E7E93252C5EA7C"
- },
- {
- "key_seed": "6FF7DF107A419A8FB65097B6B2CCFDB1B92757E72A1538B9C582D5C05C839E91",
- "ldt_key": "AB2A2E9622BF63CFFA5592E1EC7CA491ADD64E594C7441D45CCA381B879CDD73F79DAC43824EBCE0831F4B4A2D9D8A0699FB11FFF3D650166B8353D0D86EC30E",
- "hmac_key": "C2730C47227BBB11ACE9FD69F0F716754CB0ECE8E7AAACEDD1C3EDF0A83E0A24",
- "adv_salt": "E652",
- "plaintext": "7878A0505FD09850B82EC2404E2847984026EC962F29",
- "ciphertext": "68C40846FC1269959427C29BAF7275FAB70FAA0EADED",
- "metadata_key_hmac": "AC7EA05D26A200231873CC00D02CAB9AB7FE74F736FB3136BC4E8770164BD89F"
- },
- {
- "key_seed": "6E12D74E582342F3308E467E5D702F3E5DF4240AAC170FE6DE888F3E0FE11EBC",
- "ldt_key": "2FD4BB618D3BDD54E8D6E6E2B15FB085C8C38A8ED13DB81C8268BC76D76D5B98406213F8BF6435F9EDCE9AF02CC9E62C8A1536A3557AB946899C334558D8C86B",
- "hmac_key": "72F271C80646ACDFB7D085B044140EC046910B5B707F0E29C0A3F9A5969A37D6",
- "adv_salt": "59CA",
- "plaintext": "7AD1A3957A05FD0FAFC434FED374579451F308F7FA33AEA7",
- "ciphertext": "A50CC7B88D02C6787B2ECD0EDE9EDA564AA9CA9A2319819C",
- "metadata_key_hmac": "8AF34F258AB3404A36828FF1CFB017D2044737F4A8D9DED39FCE9DFC83103ADD"
- },
- {
- "key_seed": "C8A294318414CAFF7BE91B7E8E671D1518B6C3F33ED3AFCCD0F48BE1E2C45D65",
- "ldt_key": "0C03E2C14C0E304D6BB4FF746FD6F9C1094A6F46F141BF85FD78963C536306DA08C3F8C69BBE4A6EB9039F6DD7F34E11D0727DCB5E4D66C59678C368BB9512D1",
- "hmac_key": "3495F1515C76C2B46FFD402C31D06C3BB13A4364268394830AC39F2003925A10",
- "adv_salt": "7503",
- "plaintext": "FA03E156319548EA54E252604D607B9EA4955D7497D0",
- "ciphertext": "7D94D5C7B8BBB8C9C180E6C61AAE454FFD8556E2B006",
- "metadata_key_hmac": "137DC239F65339791D617F036502BED994D27C084EF0A180FECDD9F8ECFB04FA"
- },
- {
- "key_seed": "B400D12BBA0D31B81B68983E87D7D63F768456601EDA03886E67C5C82B2C167A",
- "ldt_key": "CCE2C3E3855D1E0B5196B009D8AA7E9A33D9BA36AC8A0F0BC4F9D4417FEA6F4782EE02DB8856276A3D26B17DE25A56DB0F39B34A62789801BD720A64A97E731D",
- "hmac_key": "BAF408EA5111A8BF7022076F0C6A3FEEB11B88F7E106AD332F32A0395AA543F2",
- "adv_salt": "2287",
- "plaintext": "D0DFC032AE3A31B1658EB392B58A721CCC574A0DDE",
- "ciphertext": "D30E3212FD8BB0092EC05F5401685650A874AFB2EB",
- "metadata_key_hmac": "692398735A6A56DB92FE8A2DE308AA467B96B37F88E746C3DAB2E2ADD06EEFD1"
- },
- {
- "key_seed": "F9487077F24434B11148BB8DA3B2658108D2BF222ED246D527E40FB79B59FA65",
- "ldt_key": "282CDF83E5EE41D0949197EBBAAD19B28F02FE6F44DA2FB9FEC35EA40F2348C7E95FBE9380BD8F77695BBD471A97FDE3450372654EA78542A3663380E8298EF8",
- "hmac_key": "8EEC4840DE8DE0B81EDD07F9EE511117CD9A43CFE257FC01040D6DAF011F719E",
- "adv_salt": "A067",
- "plaintext": "7B9C8E0DAC001EB757759681787F4C0A1CB2B7030D",
- "ciphertext": "50F99FBA92FA54662392A5AE8D2F1358F1190C4EA1",
- "metadata_key_hmac": "35B5BBE5DA396CA036E210BEB2E03C9E7264EE17CDCB67160C90437055C61E8B"
- },
- {
- "key_seed": "94279528D378F37D783AA85DB718DA2941239400BE724FCC51DA86EFD6521446",
- "ldt_key": "2CE2FA8D246C4B62057946F530FE68849CC4FBE0CCE24735AB40A48745B6C70525B09EED434E4D474DB9017C9CA2D96212D1E7D2944B2EA268AFBD3C1DBFF81C",
- "hmac_key": "AB0C8B4EE4FC540883CD901E962208C3A679A4CDA121E3C3E47AC16A62C26552",
- "adv_salt": "FA74",
- "plaintext": "9D179C9EB9231E83D4902F87AFEAA97FFC82A8557D",
- "ciphertext": "50AED9A942CE93D8A1EAFF67F166E0587D64F030CD",
- "metadata_key_hmac": "777C2293B15142B27C7BB06C22B04CA63E98C4B7DB346D47A09D3EFDE8D57514"
- },
- {
- "key_seed": "C0A10BC69806D2FF28B5159E2F3F969A2B36F82E3D55DD99228517346A2C1984",
- "ldt_key": "CA9710D1304CBD14C7D22F410443386DDF2583A20797D8BDC5A5713A47F6061C674F3E13CAB597A682DA56469EDDECE75DCFF1526F63235620F93A876F5977F4",
- "hmac_key": "892C75A44BE2A7C54B36691D5ADBD115F0E1A6B020873896040A8B37E59C7EF0",
- "adv_salt": "E15A",
- "plaintext": "7B896CC8905C681DC6B1D687739184EAAD5C66C32BF17DE37E968DF5430B",
- "ciphertext": "B10E441FD7D946E45E10E96F418B38D5EAD75409720F61E74B33BD7FBEB1",
- "metadata_key_hmac": "9D1A04D804D3DFFE0F18C5AFE025097B72F24175EECF1FF4D32A9A0332A33CE1"
- },
- {
- "key_seed": "DC3CA750BA956949AC3389B896359142B0FC41CA5259676A4D974B627F355674",
- "ldt_key": "884D16B4BFBDDD846857C57B5CD1912207788A1B3F95D5AA7218CB4AA3E21AB4D0C9518E3DBF09CD2C1A31DAE2DBF04E96840E81D8FD9166061B1F761834E270",
- "hmac_key": "6437801B615156A92363D1D70CC37D8DBD1D5122F09AA4775C99402B29D97794",
- "adv_salt": "2A38",
- "plaintext": "565374DC1B36E89EDD90AE5CD77F9109819053615F590990D203",
- "ciphertext": "EFA8C9D21EF4E65EB7D398EAF277EDE24F9D3D4D4CCC3DEADD4C",
- "metadata_key_hmac": "CEC61A875AEDA4C3E1F4BEA7F5D5F48842C9677BFDFD3777ECB6998F412623E1"
- },
- {
- "key_seed": "1C3B8C1D9EADA715EA9E9D0309204228015824BAA74D90880AB61C110D17B275",
- "ldt_key": "6744922661B4330F6E0FFDE562D5CF4FB2D9A838E6FE17226FB9AD6DCDBD78BDACC587389421144AD105DAD1C5D5B2C0637A380C81A6AECCD5521D29A0E103F9",
- "hmac_key": "7D4C0C0252D8010FDD7F1D4B77DA012C9F3A8CAB84D2736618F7F0991316BBA4",
- "adv_salt": "8E40",
- "plaintext": "9989667868EEF966DE52DAA83A79F442257CBF18D27769F2FAF5BDF6B785",
- "ciphertext": "21A369488B4FAE255E9EC83844DAB5FCF3657BA593715570C010E1B3977B",
- "metadata_key_hmac": "53E639D5AB5948942DD6D9946F95A1A6EBB9B93A186E50E918E0609B8E3DA45F"
- },
- {
- "key_seed": "9829D6447C561A4BA0A5EC0E0C9CAC8E5DA6430FE27DB0D0E1D751FFA5D31F48",
- "ldt_key": "428CCDABE1FEC7368F57CD23F949E8146871678DC0A18F7566E29A07014D90524BB819332141592B70EE68833175CE000C9D63EFAC241B15720B4D19E0607C5D",
- "hmac_key": "F47C1E3EEB9A14EF81797EC8FC3A5BE1D886A5F25386AD8B7413205273CCBBEC",
- "adv_salt": "440F",
- "plaintext": "920B77B8367C89A08EC9BD91DAE8F57E808A8D8570EFB5DE56F7BA33A75A6B",
- "ciphertext": "6DE0BADF95B7EE68AADE0ABDAD0EF726C1584A80FC2A7965BEA2CA481D6A4E",
- "metadata_key_hmac": "EFB87B5515B40D8717C7617C2033F9150B41C29BAFE50A69BF0A2C95DE5B19C0"
- },
- {
- "key_seed": "E87CE30B3E8CA4FCCBD01458EB57F0A54E5F0A1F013F2377461AAACA9113A715",
- "ldt_key": "207F249256B15A443DC418BE6CFD316529266F030513B25DC88D7E86141543E0639A9F1480C320E565DC0C04DF83CBF630A418A79847B7FC56D2E68E0545A557",
- "hmac_key": "7BA64235DFADA23F35D3BE3CBF100A6B4BCDFEEE28BA79CF914400E1FBF5CECB",
- "adv_salt": "BD1D",
- "plaintext": "3E72346BB0A79E75F6DCB30AD5CDB27758BE405D615F7CD931CF468F01A6AC",
- "ciphertext": "D9DE8FB0D2DAE8863511B3179E5CC7E11E77603AF625DE1157A492C6ED6EB9",
- "metadata_key_hmac": "47E0AC2BCC093E9DD4D617D6D12697A7A8E6EF7EA3153C85D6E6F8B1F5CDB73A"
- },
- {
- "key_seed": "0263E7AF4055525AE31D64FADFF6CC1295A8034432020528BE6E56D69CC2B681",
- "ldt_key": "A8BB317A8086B5DEC813237497EC12C897D1621E8D60C22D015F2E2AABDFB504122D22843E26F4B2E9FB3E4D0A491473D13D7CFD604B9D51A6E06452FADD3E3E",
- "hmac_key": "A65B8453EAF6B2783E3AF93D3102F4FA8CB2BA378482E83F38182FD064D007C3",
- "adv_salt": "A10F",
- "plaintext": "0EBC9C6404682C8BD3E9AD99A1A3D7618CAB6114FFF6C875958049C1C5",
- "ciphertext": "8E75136143E94C631C2944DD32EBB9F0696F346EBB8D7444686BAF02C8",
- "metadata_key_hmac": "AA9F58AC9FFD706330B4EC958F101DB57D46BD88AB2DD265F70F5250D9915A55"
- },
- {
- "key_seed": "7876C9FB9FB4F58A761A7C6CC0B04368C93DD0E955AFF705C013D59AC5051896",
- "ldt_key": "A300A6502E3001A500382DB2A10FA6B8C8C8CE2CC52CC75573E140B45FF7070C17CCFDD48BFEE0E72E18E41A46C242514620462E9A9860ACF1B22C16A4C2A125",
- "hmac_key": "58559479522C1832647EA8F24714DF9D91FBBC27706E50BCD2888D8A36F46325",
- "adv_salt": "DD6D",
- "plaintext": "A4719D72E2EDF46B58D89ED9E8083306F5411AD487AFF4ABFCED8947",
- "ciphertext": "8C61A76BBB3C1632037E5F20924BFD1801801C917741AC2A59DC16FD",
- "metadata_key_hmac": "0F395A1B09F0A4F5060FB521B9EF59796339A9C8B70429960676748E07A777EC"
- },
- {
- "key_seed": "6FA2BC03F573158EABAB35B48390E46B1D4070C09E0B3EB762878E8DEBB5FC07",
- "ldt_key": "9BD667DAB846D7A2DBFCECA1ADAD48A933A7C75256B71221925C7B14EC127BBF82F4EED25B83589447F3685A6A2D862504AEEFF120D4B20D2538E5A03909103A",
- "hmac_key": "ABA1A56B7051C0344F2BC497B5AB2A1D7037D7040C821C13428569A3D1BD6FFB",
- "adv_salt": "B9D6",
- "plaintext": "9FB0C213C041D1D1E134EC482C0CCC80FC",
- "ciphertext": "C8D19DFE4F8C99D1026AA6E3BECE8A82E0",
- "metadata_key_hmac": "E8593E0D4C29738FF3752BC5E905AC21DA793328DB599552BD86B71334E92C58"
- },
- {
- "key_seed": "A55A9CEC40E1E37FE8BFF5ADFF4C68034F4589064D530388005F97715011AE02",
- "ldt_key": "75797008482530202CF7BD71CDB51A9CFE2D505A393FF9A0849178239EA6E739FFE58B8153EA5749B6B53F37C1E6BFEE930E5BCD97C9E470DCC6EAE6D3417A07",
- "hmac_key": "3C6162C6EFCA96689B94E84F714C8A00D99789DF7D3FB8E06774C39C73BFEB7B",
- "adv_salt": "5EFB",
- "plaintext": "9A05585013112CBCB6716344AF4CF92C3764CEE150430C4A8B72B1B0303A0E",
- "ciphertext": "D9814AB92D016981018F136C02107D819A27F3A2C0A2768D4AC36EADD7D672",
- "metadata_key_hmac": "AC1982323640547F148E7ADFF917DD087FB98AFD3C3139645A2A9620907D00F1"
- },
- {
- "key_seed": "5BB19F6715A9BF3C1572107C27104BBC0E6D6AC4F984BD4B96931F79E6C585CE",
- "ldt_key": "626DD569F79E1B91B42ABBB45C4686895563370718BAE54A6955FFB4FF9A93058183CDDA102A870C2FD53B0CB0172D46BC037B3579FBFBA603639B705383BE0F",
- "hmac_key": "5F4B431121110ECB86B89EE8FEF343E07E4BAE63452320375C13109CEDD98EB2",
- "adv_salt": "6DDF",
- "plaintext": "7FEAD68893990AF7CCA7E26E94D0B1FBFBE58BF130",
- "ciphertext": "EF57EDBE41E2AEDA8F8CB43DCEFD5B6367BA5E8B92",
- "metadata_key_hmac": "BEB64F4417ED86EE5C150BD546970894AE6C7F48F931CB980D454E91F5ACBC38"
- },
- {
- "key_seed": "A6663A8EEE1EF41B70E814267C9F2603C8B557AC51DA181A69C9EEDFC5F19528",
- "ldt_key": "DD58948746753E17912CFAD8BD69DC9ACAF20119AE60BC41AE2A6A1C4CA53B33F65922EB92C116E25D27B6B377BF4635C907106418291023444B0582B622C5A2",
- "hmac_key": "1625F8FF5C659C118993078C731330521D63785B51E5C0A2A0BFF8DA6F3E69B1",
- "adv_salt": "810F",
- "plaintext": "1F326F6587D80675DBCE9E0C56F2E95663518BEE5E",
- "ciphertext": "251F2687ADBFDE3F4163ECCDE0380D7746538155F7",
- "metadata_key_hmac": "E6AE6DBEA57A83A5AF7A2E7AFE745D477CC39C10264B0B30F29CA846E6128E4A"
- },
- {
- "key_seed": "00828953A1AE0076B75DA512511FB1A429C25A0F1ABA6153368267A44FE960B2",
- "ldt_key": "71F2A112C0956E80955B3577E51D44C41B1AEDFA74745AE617326FD6FD826985CC466AA4249AAA64AA122C4D5AF7129411358876971D31F875F969925529167E",
- "hmac_key": "5BD823CFAD624CC841C0C714E08F1A919F846E0FCB8B125FD08761825D9087F8",
- "adv_salt": "181A",
- "plaintext": "9C048A6138808DDA7B467085DA77FA1ACFD07A3544DE",
- "ciphertext": "AA663B104A0B7159D99C7C1576499B2A23FDA7A567E6",
- "metadata_key_hmac": "37EC37D5308D056454955C51B93E4150F2C56416EA7C6C948B9076F3C573A187"
- },
- {
- "key_seed": "D660CEB399C3E0E51F3C491444FF6516D5BE55D6EDF620998B7D30ED0E80A7BA",
- "ldt_key": "2FDB0A3BAF8990143F8D70F648C4727675C5BF066DF7757FD6AC0F2D4A7BF3A3A10ECF1B66264CAA29F0FFAE99048FF0FA7A646E78B1EB78C5C1F2D4DE6AF2CB",
- "hmac_key": "A5FD3131713A68D6BB887EBCF083ED873373959807431425A388F3AB8239B141",
- "adv_salt": "FEB7",
- "plaintext": "EA7CB59D1E9F4203E2539E950D60EE1DB77861FB",
- "ciphertext": "486BB7E2D495B8A5980D0A4E1C9CC9D9B3F23F55",
- "metadata_key_hmac": "0789ED2ABA65D4552A7CB7B9A9959E825F82FE5D9DE7AB9514655DF3AC873F11"
- },
- {
- "key_seed": "4312F7F5892996C4CA4342A3309FCD0EA601AE94845FE91DFF56A95385F3C60F",
- "ldt_key": "B8BA8FC9BB5F78EA07F0FB9FDF9FB8842FF334AD67AB8EACAFD415A4F6E085D5D7518A7AFEBB6E5423D62986FB039AE8FD792A8E285F952E4A7FFEAF7D134EC9",
- "hmac_key": "18D8409206BC997C599263D62CD44380B44BBE22004E510E2B29B06C6AA9A506",
- "adv_salt": "0FAE",
- "plaintext": "74148EAF740DD87A25DFF9285D1FBFDB19F3F950547A1E453949F6A2D8",
- "ciphertext": "AC7873262675D66AED37E19730DDC2B36DF22A68CD8B1E1F08E6B3BD30",
- "metadata_key_hmac": "3BC5EA33917B1A9B4FEACF43AED93705A47F96016DDF7DC4AC8707ED10B8433C"
- },
- {
- "key_seed": "60936E83FEB011BBDDE2C861564F8B349DEFEAF325FFD852DA601D5521830C1C",
- "ldt_key": "B6C7D5FBF879C182B491B13BEA3760A246A7D49052EDB4AA0B22E099706FC11F5A5D70679617F1B56647B1B5EFA7544973CD60A5007CE966BCDFF8873EE10C65",
- "hmac_key": "3708BF9E9C2EA13AE58F00102B2744794614687B50D08560E22A09427E26EBAA",
- "adv_salt": "0749",
- "plaintext": "D647802D5DC37E30A795DF344746F51B5EF7E94549",
- "ciphertext": "9C8E99384E6926877C9F02B22A2BCD219EBC68BA6A",
- "metadata_key_hmac": "1E510537E57C913E1D20C57C8D21AFB54D5ACC9839D66B398C9ED2DAC72B6BA8"
- },
- {
- "key_seed": "AC3CD644EA7AFE34435A1F11546FEF56365C4BCC580F95447E03D5FE12AE230F",
- "ldt_key": "6EC72CB753BCA51C05D3A6B4EDF1B34E531E0932565AA7B771C79240759F4BD0EA290CD8DD1C6EFC07A3F8113F4F58EB6A00979F8D3B7B855D9B665338F3ECE0",
- "hmac_key": "5971FC82754E0EE3CF5A79D67535F9B6CA5DB532471F30D01CAE7484DB8EB33B",
- "adv_salt": "4558",
- "plaintext": "5C0343A00C399C9862B55BABF4C5D94CDF243989433B0E",
- "ciphertext": "CA47DC24D0D1E4F976C5A58074DD1D9FA218E487113DE0",
- "metadata_key_hmac": "A1A0FB564882EDA231E4CBB9AF4F12E674CA51ED56CE5C251933AD3BE39BEA2B"
- },
- {
- "key_seed": "901A6F048DF80F4D09E6D15E793846E86A62529A17990A9A76AC394C2949FCC5",
- "ldt_key": "5CC9EC33625EE5283826BE48DD42DA644F4224411E31E71A834CB241C8D56C442D119310956B7C096E6BAA30E1891E199C06D8767AC2D4C5B5D6B7B4BA096975",
- "hmac_key": "0337A6DCB3FC021EFA02EDA3ED5399B3627771194F77D6F21E5C78D234E54221",
- "adv_salt": "A8B2",
- "plaintext": "1646727763D58BE646D4070BC80C4E5FBF1B067691A5D21229",
- "ciphertext": "59E2B0C2BB88D5EEAD5A8F733F2DFF166556C36A115254841F",
- "metadata_key_hmac": "301C5DEEBA0A29EE04DB005A0831D0CFE83B102DBCDB7323615E0CD986B4F735"
- },
- {
- "key_seed": "7FD07DD39B68FA5AC3B28290D300A2796061CEC41885AEF1605D3C420F4BE7DD",
- "ldt_key": "CFF848B80B0E57D8B2A692AF7E8876CDA6F720E4E52566A4422C3F002835F0DA2B76813CCC068504CC78FB07BFBA602454146F2D76BD3EA439305FF2B7E5249C",
- "hmac_key": "EC4070A926535FF84E397CD857DDA2AB8F5413DBF9F78078CCAA44EFDFA8449B",
- "adv_salt": "EBCC",
- "plaintext": "6C1E0BC720D2B60D5950D4F83FCD0AB3AA52CB",
- "ciphertext": "2BD9294E740B0E86C0BB41A806A04A549903B2",
- "metadata_key_hmac": "5EAC027DA7F61F2BC016C0F4B186DF3F036063DCF44EAD4527A05EB58D7309C8"
- },
- {
- "key_seed": "C68092CCC57F93CE005FFF8EF45F5B880F58836E6CE859FDE3E21811587541F4",
- "ldt_key": "710B9E649C1594026187E19EADB0AA6879F7F8C0CD2C447C95143EF0F215B74F39DD092D87FAA0956A38028A6B1EB487209947F6ED26581B8770BD61FF41F313",
- "hmac_key": "9DE1EA3B995E7372264FC4403F500FB1109F1E5E04611C22A2AB66012D04938D",
- "adv_salt": "A212",
- "plaintext": "C4FFCE44E03DFAB9C6E872306336F45D392B56890404FB",
- "ciphertext": "FB89DCC92612421F8E738F6842757207D0D9B4F4A6C945",
- "metadata_key_hmac": "16E4235205524E457427C43F40D1BB19DFD5AC2A5F8F0832E9F299AA1167430C"
- },
- {
- "key_seed": "15DDA0D93BF9B9FB9792A3916A0639E52AA8F9880CFEEE1C98F9D0C940104F61",
- "ldt_key": "92F261A46A17E4A7CE4BEF7A817D79828DAB297CC5FACA83790EB864ADD70B935FFA1D2464469FD655988B0118EE931AA0FAE77F9521CC8CF35F87D87D4CCF4F",
- "hmac_key": "FEE8B413DF5ABF9D109AC9CF93F842EC0739603CD1184F8805C5B488B52FCABE",
- "adv_salt": "61BF",
- "plaintext": "EBB8E7B325AA42A0450ED5F99A4164DEEC5A056183CD101F6A1971",
- "ciphertext": "9A388163E462B8513A6CF4B333CC8F6E809B69E69C24E1075AA990",
- "metadata_key_hmac": "66F0DAE501CF33F770BF920299390628952BE096C9387558A50CC0A754DE83FA"
- },
- {
- "key_seed": "3B085F2421533E56367A9BE398D88BE12345D3DF2BBC7A6EE9803B8D734F24C8",
- "ldt_key": "8C20759E8CE3D70DC11C3B80D6CD8317ECE48F49ADF67D3D65D8413CE3A5930AEDA60A8D91757F521714D7E245406EE7D2DFB309CD20FC9ECB339B6AAF30945D",
- "hmac_key": "4350D0803416BFB74F93F742066EB1EEF1ECF72D9B7FAB2C1BE8811F80843D31",
- "adv_salt": "42B1",
- "plaintext": "1530D76F0258302D0B6A844DCCEE6598E31801D8EF2821BA1C",
- "ciphertext": "8FA43962DC2A1EF3D107134EF59373CEA2BF3CB005ABFB0E5E",
- "metadata_key_hmac": "F5575D9501C401AD0A3585553BA70EBF575306BB4BE08CC12136190FC1B0AD4A"
- },
- {
- "key_seed": "257947BBFC05D08F0F0FFEE03A2C2273A011A5F7EF9B9746158797420754095C",
- "ldt_key": "17BD3B4365293E6061F40761C60443B80D6846CFD48820442E3A3B1ED58A9491397FE74C3379DFBB9A06BDF0BA9D95E1CF031E40F70B3EC96CFD344D7A945E29",
- "hmac_key": "BA79FC2C050E725C90CAE0DBE419913AC645B87D79D9B4C3648EE306F3B2FC22",
- "adv_salt": "98D8",
- "plaintext": "7BD9593ADD66E8B0EB23C00ED62EB2EAC32C0D7A8803DE1D7CF9A864BD",
- "ciphertext": "35D739708CAB44C53CDE37BB97F95396C5C73D7378E315FB2CB7E4D777",
- "metadata_key_hmac": "3FC6C015D7154B5096FE63226A1144C929809D4F5A0D02D5017A35B8C441529C"
- },
- {
- "key_seed": "5EEF0225548AB29601E1EC1C274F5E6B5B6119FDF0DC5CEC69D0DEDC02DACD24",
- "ldt_key": "00243E2ED2C291E58F0242AEB46C6FE0A54B0F71444855ECA6E20F977071896501078D86A130D90D593A3F977C99F8EACFE3B4E7D4CD8E8EC410C23833078CDF",
- "hmac_key": "37929743724C60521295D912605CD5C215294F4B55F9A667AED0FE22A94B44F4",
- "adv_salt": "BCD3",
- "plaintext": "1371B4C2F32F11B5DC9F9AC4BC41D9EB6CB821",
- "ciphertext": "5C3E8770D2AB1EDE58BF72C45A63F7AE6E3006",
- "metadata_key_hmac": "8D025FC2390405E609B15665E54AE5F912E699C6C14C16B49ADFA489FF78C3A7"
- },
- {
- "key_seed": "4DBE9FAB35FB53FCF1B799B62FEA1FEB808A88C40ECFF20065A90F0F603236E7",
- "ldt_key": "C2E3CF1D90B60532AEE73CE8AB1B37DA4D290E74A2AB309D3D93394945EAA28924D2CC1786D75A9AE0FA260D23EFB66E776BE36ABCA8B878F47072DF26EB2F52",
- "hmac_key": "C863DD8C616E84252ADB5C42A45954744EB762A21D7FAC9A7994B45C21E4C677",
- "adv_salt": "56E2",
- "plaintext": "A55F99D538CD53D1E18270420BF27FDB20CC7C949ADA1332A547",
- "ciphertext": "71AC20DCE1E5E1A81866DE2A2128C4BBFF2984D94387604C366C",
- "metadata_key_hmac": "11D7DF11FE83F6F1A64A45EB4D517C750BEA1B1433C1649DD4A2A7021F09B0C4"
- },
- {
- "key_seed": "D6D25ECF88E2502B7671472B6A552B36D67B9CB9321AABD1F806ECD314FB9FEF",
- "ldt_key": "DB7A65F320FB5013BCA14C176A00F8C1DC73F49ED05BE2C1E378DAAA33FEB5F8153C201C4E82A6EA6D5224D10781EBC271547640C85E55FBA24A3620A79D341E",
- "hmac_key": "6C6D5EF7242CE23D098FF85950E838E497E18450067AFE46DC58E937D909C484",
- "adv_salt": "0E30",
- "plaintext": "4F4AE5C4AB5DC7FD4D3E8929140FE83D32C59D9EFD84",
- "ciphertext": "DA443DF8CCA50DEB682E1714095280857CA6F4AE6166",
- "metadata_key_hmac": "3E602FF8473A4AF98A4AFA779C69B468099DFE47A6CF5DEA74E24974EDAD64E6"
- },
- {
- "key_seed": "4280AB46666D4D72EF2BA5E4F09F4A9B515A6211A5594F5B432E16704C06B65C",
- "ldt_key": "5A3ECF4BCFD13F57049CB026312CBD9A082A84BEB0D5B8BED4A0958D890282E1C42198FD2DDA2C567D9040F6B3514D1A6DE327D961AB398D2C5E5B381F2AE297",
- "hmac_key": "3CECCCCF1E22B4792EBC15075ED2119869A066427A857B97B2B3C048642902CD",
- "adv_salt": "EF02",
- "plaintext": "998488E3D3E1D033E6E11CE1BD83DA51CA2AA4D22798126218",
- "ciphertext": "19ABE26D88D0358B9E2A4F74FD05849025CC0D8BA531F00DFC",
- "metadata_key_hmac": "B2E23362172A282DE1058FB0349F897B0C346917F45FD8D9478A28E0230454D0"
- },
- {
- "key_seed": "29688FFC6D8199FB3150EB61CA566A52F4DBDF34C91D4D8F30722665C7C2C8C4",
- "ldt_key": "163A0881FAF42FA1B43EAD48D7192487C6DCE42F819A8C9DFA44FF71E0EF830793D9155856491DD6B6CBF44ADDB002465D7D6C06D9F43ED0DFBE5979EA3EE6D3",
- "hmac_key": "C55C11DB9F8DB61E96D276E0F27A6451173095D3CEAFDF78E4AA824ACC39E42C",
- "adv_salt": "F215",
- "plaintext": "76DC9C1687E162B8A6F5305921E25D4F2309404CE35F570603",
- "ciphertext": "A9E1B8BC917BAB6914A69E94564B04073988A489ECF2A8A545",
- "metadata_key_hmac": "C3F4F141C6B6B251DA07F07B1BAB1572E6A41C08052C4FE50C0DADCCB5898F37"
- },
- {
- "key_seed": "DCCB95471CD9428172C964CBCBAE520CDB3914FCB751EF98EBF864796729D8F1",
- "ldt_key": "CF452D0A9AACA5C57E3D84937AEF3730F5EF28C4C2209D836629E9DFB32F40DF7F0C8524335C3FF39EC6091CE07BD720FC232C3910C93559335B98CD9F2890F8",
- "hmac_key": "321262ACEC4F28F2882C4D744EEAB2684933B3954E4C1D33C462FC28C0FB913D",
- "adv_salt": "32A5",
- "plaintext": "0DCAD7F90214D1FEC607125A95BA4A0FE8A4",
- "ciphertext": "AB0DBC14F08558984BDE7772AE0D88C01E47",
- "metadata_key_hmac": "134A10970EA11BAB8D2BB41B253D91B488F0F34ECFEEBA74C5A4D314D39B386D"
- },
- {
- "key_seed": "602741B32088CB24744C42AE8A04F4FA1D8AAA395CD14BF794785AE906EA31B5",
- "ldt_key": "9E5ECC1A36F9657D73D7F3609BA66A102DAB5D0343D641A07C5019CC86B813C25EDD9B6363BDFEAAA3403C061C8E84C6F334E4485A5EE988404EE98DF2F90CFA",
- "hmac_key": "546DFAB1F8DCA2B85752D25B5C5AFDD1ACD8CC9B380920C529C0CE70C0B1BD55",
- "adv_salt": "49C4",
- "plaintext": "1B9CE96F10D577C41A523A2D4D75F2820FD811E14A3AA4",
- "ciphertext": "0317B287D59B35AA1873CF36B3403A7F9616FB0943BBBE",
- "metadata_key_hmac": "47FA521E23291DAFB3DE6121DAD692496392E939E03368506F66D701B4C64CB0"
- },
- {
- "key_seed": "C43B0C050E0BEAB285191146BBA474189B253D78411FECE31AB5B6EE60253E19",
- "ldt_key": "9BA205AFD03BF4BB04AAD928C7B6EC29D2DEDE9C98DAD5C5E036E7223D450BF3DB6FDE175317A6A1E26AF0080E5BF6A637A9C1AE0AFBFE15DF5454E0D454F138",
- "hmac_key": "3D97AC87FED97DF4183ADF57F341159C847BE13712B82491C8C426A0D5AD7B3E",
- "adv_salt": "9F08",
- "plaintext": "F2B228C059D4CB0F7100D8C0B5C78EC9DB7E8F141E0BB9",
- "ciphertext": "EF71E826D9243560EB3BDB751BD5679872A821C2DAB9BF",
- "metadata_key_hmac": "C255EA0EECC08AFCBB47D033DCBD78F7E30BC0CC70F21754A8C523BF17DE3E9B"
- },
- {
- "key_seed": "E3CB42EE350C452AB1D96DFFAE79F48F8BBFDB72149C21C803A4B50B8E1BC4FA",
- "ldt_key": "F5836F573D7FBCFE83CB42451F1A50A535BE11AE71F9BE3DC92A430A144F3641F9AD55B29420F09AE423D6B2B64BB57AB4394EA8CBA8C2FC294E419D80CC61FB",
- "hmac_key": "17B23A47EFEE4FEA1DA852F13EFDCD928E03C0E38BAB4F96B6643DD975A0ADBB",
- "adv_salt": "0950",
- "plaintext": "5655DC1EECAC7CD61B2DAC897DEA832EEC27",
- "ciphertext": "82A8293E6CC28C0A185145D1077BEBE76EA0",
- "metadata_key_hmac": "D97EFE52AB79CB84682B1AD131F1E46370986C1F24C819FF7BC2598FFB911051"
- },
- {
- "key_seed": "DD858E3C02C5381C800757E996D2FF45ACBCB00A01A21DAFB07FDC3005348E11",
- "ldt_key": "BF41D6D21D47EB610362613179227B851BDAF8F41DB4D82644CCCF0D1B2AFEEFBF91B3AF386D7741CE4535C6219C05C89FFEBD4F8C796E04744386736F9C277E",
- "hmac_key": "7CA36BCC67F15C0DDCF071873C230F50468E3AE48F87F82282A83FBFF377BE55",
- "adv_salt": "ED85",
- "plaintext": "A9164F9B6C63C4C34E3DB34DEBD9BC6237",
- "ciphertext": "346F3DCE5DC5778E368546F7CDB1295BB6",
- "metadata_key_hmac": "B953BB4678BD924EEE6C47505817E1E31EA0FCD21995C66299EB43053DC0F753"
- },
- {
- "key_seed": "2C8EAF66387544DC932D47E665130C17AE350BF726A1378ED17E08DB17E32019",
- "ldt_key": "C1615130E0EF37C63115F80E8821C5306657E9886F37D606E3F6D4A21FA1055513D759E5F0F9F8B21EA215F690A23B7BA4BC78E56767E05523ECC970D5A7FC10",
- "hmac_key": "090843CE6052B02B53F4D1B479623014360C9EBD3112FD72301C2698AE55087F",
- "adv_salt": "B698",
- "plaintext": "5CA984CCDD4AF7C3B24C92E8D23A74446D1E647E",
- "ciphertext": "4784388C98FAED88883F171E2FBAB3C3D078B573",
- "metadata_key_hmac": "9AB7AB93238D92FE02DEDAC29C775BF9315F3C696079DD72BD88C39EFF7AD0F7"
- },
- {
- "key_seed": "BCC181A2A53F1E9A2B17DFFA213BA37BF056D2C1FD74E7F2D81A963654C5840A",
- "ldt_key": "7B06F03E6964E98D68FD2D03CCA2F029E8A355DDC944132B4B36CB254F975A5B10DE495AB16919493E202B2D74924776DD675A33DC09104EB7CF3CD3094A6E31",
- "hmac_key": "D651C7D566DDB461C7CDF0D6D0744AD6178658EA4A118465DA88052D9351F3D6",
- "adv_salt": "FE1E",
- "plaintext": "2EF24BEF273B15A558A8C1BBD415432AA4629D7A0CDBC9512F3DE2",
- "ciphertext": "F51E9690D234726CF856428AE1373FF1940B778A8ADA54C2B867A8",
- "metadata_key_hmac": "04F92ACD86FC2ADD7D1DEB7FD53D7E051F8E3E72EBED64515C1EA83DCDE19982"
- },
- {
- "key_seed": "85787F8AE79A46639CC2C9F2B4B15956C7B92684F5D0F76547A7290AD87DDED1",
- "ldt_key": "9396EA24153EA5CFD00969F044045B8665E89CE9C142C64B7BBA8C64D27C8A2069479AB3D69DC7D01ABC9DE07AE02343DDBD06379A297B83FDB8AF08F846E425",
- "hmac_key": "E651170724729345796297608F276F262898CE7A66E9E948185818039783088C",
- "adv_salt": "4D4D",
- "plaintext": "EC0D0628250421CFA7BEC2EA26A7B435B4BFDF4B",
- "ciphertext": "31CCAD29DA8E68183240107590089717669706CC",
- "metadata_key_hmac": "EE39C3235CE44E3C991025B26E1159B784D46AC6F1BB2919BDB1E64759B7F478"
- },
- {
- "key_seed": "808A56F86617F0A36E403CB6448531A6C9A41CD37008FF1CED445DD60C6E806F",
- "ldt_key": "5841CAD4189E1396E561800917C835959E27378CBDB2AF33EB85116A1F1D4B1F9D2DCE40C5B4C5C12884E3D217000DFE1EC74B1AD17F34AEAD8DA086BCF3EB27",
- "hmac_key": "ADE211D812886EB8D68406DF336CF870056343BA4F100948EB559AC4F917D2B3",
- "adv_salt": "F7FC",
- "plaintext": "85528B7B4972632BEFCE2D7C620747C0BC4F7B2C7008A9",
- "ciphertext": "09C2D98933F2A751F548379D134CBB090F982F524DA2E0",
- "metadata_key_hmac": "E561E0870430A5DD125F5E07A1852EE41E11F2344618A0F3268CD3A9CB7A0CD3"
- },
- {
- "key_seed": "CD451867F408CE5CA056E3DDBF393B35FE2028992C896AB15B131FDB146A4769",
- "ldt_key": "B3DD3D25B37B532E81979CC31C569399F098955E20E69A066D2533243AA32BCFC2D632387A63340D0646B227AA8C7CF03FE2A73D7DBFE5B7F3EB61C5453141BE",
- "hmac_key": "E84ED8653B911533417D6B408EF5BB2025965C9B9291104BB44C00FDF19A3829",
- "adv_salt": "EDD6",
- "plaintext": "09E16923D27569CE6DFE8B8A3180D942734D",
- "ciphertext": "7DF216E4FF81D7A86A064FEB71B54F8892E5",
- "metadata_key_hmac": "15DCAED4AACE7F57D8FDD76921E60C110764E895FEF98ADBA986A239D98EB18A"
- },
- {
- "key_seed": "7ECE23377DB5101629A397DB13EE9238DF6A707B63E59C214574DDECD28BD77C",
- "ldt_key": "E5EDEA1C2057199A79C34AD5F16996927FDF147021EA2900732D8D90FD061EBEA850D755584DCFC419CC3AAA48372BB63C555EDF7B414D7AD5224F252E77BBA0",
- "hmac_key": "A8BF38403D85F2D77B8F96B01BE5C2EF2E35B0CF4482DB66F5672BA407B343C5",
- "adv_salt": "6390",
- "plaintext": "9D6329A4603170AAF549CE2E49FCC674B9AC131898FA14",
- "ciphertext": "0BD5FE354CC50817D766DA59E359BF06833FA85595DFDA",
- "metadata_key_hmac": "48B79D27909917BD5326C04E7D22546C8777276179B70B7F0C8C818EE067E06E"
- },
- {
- "key_seed": "15D576484E9214D9FAC931EDC67E091420EBBB7BF019AC4855B758E85D3E9412",
- "ldt_key": "308E191F21847FDC8319EC46D49FB4B5593D351187EBA1C457EC08ECDE1234B4512A73082E845B307597E2758DD05A2F159D95C309DBD7E1BBFAF026E9F675F3",
- "hmac_key": "705E54F5C58D5283231ACBF76CC81D1D602D1400AF5C1B6ED88B00E972BB995F",
- "adv_salt": "95C2",
- "plaintext": "5EE8F009FDF3707221F764A57B1797FBCC8803652ECAC995F2F422B65E",
- "ciphertext": "C3F567F4CB422B630E520FE921E10176F3DC751FA706AFF159DF7D16E4",
- "metadata_key_hmac": "089803428F05209A06F2DC80ADD9B708AA3F590C20164914C42A3F1E8F3D0A91"
- },
- {
- "key_seed": "C1332895B13DF2ADCD2F87EF068BF9ADA96BD121447A2083E85BCC430F9D1680",
- "ldt_key": "46BC3E82A6192F62AE5FB0DF1F84D690432D9A3883B6E755E5F2BC40A20C56E4E699DB37C5B2DC7552C58DEE84CFCDED48EB4FAEBB2782835F9432CC9F19BC96",
- "hmac_key": "F75B7EC653D60C812B580405DFC9286E79A673597DD68AFA463CB8EDFDA2A5F8",
- "adv_salt": "AA7F",
- "plaintext": "1385F3E5B01E7667A39491CB78323792605041CF2AC8",
- "ciphertext": "13A0B7C490E8C88160A80F667EBEBB89B6867CB7010A",
- "metadata_key_hmac": "3526AA9EC81718F0A7354BA0C97DFC09F6151A1BA94B07C9088C2DDF6960CF89"
- },
- {
- "key_seed": "C8FCA816F18F73E3F2CDA9156F5FA2D92FD91053ADE867F0230DBA4E2BA1E3D7",
- "ldt_key": "8D820238E3F19CBC416753FF3239099DC5985EBE202780EDE7B6E920BD97421ED97D1FB2DC91321E2A702BB32DCFA4EE8E064B1B949C6EA21E828DCD617F30E8",
- "hmac_key": "AB4E747A286393A9A8D4D2F54F8D4BC3EC07B6268D47362ABA14F037B80338CA",
- "adv_salt": "876D",
- "plaintext": "A16A9A2052ADB3E6AC2529CFED7EE211E58185647817E697A1570D",
- "ciphertext": "48316F94CCBE262DF3FCF476CB8A0AAB475C9936B5DF0055738684",
- "metadata_key_hmac": "917FDBFA129F192BD9616B44165D2202F063BD466DBF9B4E3C3B75568BF76282"
- },
- {
- "key_seed": "639D87014289A8E028BCE63B1513502616ACBEAAE521919E91693F1357E62E0E",
- "ldt_key": "61B7EC75F4F235D492F3AC35C514E0CBB6E350F85885E6FFD2297465958497E8EADAB8A6183AFF23BB69271F4500B8B1BEF9C6F7C9696588F8369664FB79AAD1",
- "hmac_key": "4DBF3A9E6B37A014DEC9A15C73B000F10F7A1AE631BA76AF7DF3357E70980669",
- "adv_salt": "2E76",
- "plaintext": "45C44EB1CE23718F084A97F47FBDDCB1",
- "ciphertext": "A0925BD133932E2467CA67274227FA55",
- "metadata_key_hmac": "1F076DBE5AE63F71D4D5B23D99FCCC2BBB7CF73F22EDEA0B1C6A58035867D519"
- },
- {
- "key_seed": "773E33067D43FC523B4305CA3578AEEC24F8427C3B3959A347EA4B7E50A0CA1A",
- "ldt_key": "20F2936DB1EC57420FB7F9C24702CAC1706EB3E2BA44B80603A1511A32A29379A78E8B96A532D1A02B83590CFD2295FC5E9E327E9ED521A47103F9B934AF9AEE",
- "hmac_key": "FDB438716D1EC94C1E0B704160BDB87C293DE9ADD5D1C1370A91BFE6FD2426DA",
- "adv_salt": "D9A4",
- "plaintext": "377F605140CD99F7CFEE12D57478DBEA648F55FF925E0B",
- "ciphertext": "B0D28A4B39A01596EA5363374D0022BF17CAD42B28F175",
- "metadata_key_hmac": "7BAFF574972DD155FD382CF6C055FDA328EE16C6F14552E4564AA76165AD9EC8"
- },
- {
- "key_seed": "9043994ED8E3A349A66399E3D047EF6AEFCE13DC97D3BE218306B2B2C74F1838",
- "ldt_key": "BE0EB7D950AAA7F181BB8354D988AAD2B7292F0DE1D08DA041C559443615D13D335ED6094EDC03F96765A4793213F64378EF6F3B59B15F939FFE095864CAE903",
- "hmac_key": "2D1204DA558E5D4CB76835307D85D27A2515AA6841901EED119CD54571F17235",
- "adv_salt": "0247",
- "plaintext": "CE4A19AFDE5A8B0D45AAA57D63F43AF2DACC59",
- "ciphertext": "65DA4E964B043D38A74F9C9C50AA3BD0A52AFE",
- "metadata_key_hmac": "651BB173EB8AF1477B3FE8497AFAE9DBFFB6F9A782E8789BAD2945F229B0E96C"
- },
- {
- "key_seed": "33EAAEE040953BA534409FA76C8E1007CE3E96589AEFFA84CFA1074FFA796C8F",
- "ldt_key": "F4691E3AD571F4D034CF12FC1926C35A238A125E6BF1FEF0A60F414072A9374654C98368EFA72F43E1F721984584343839C3F773D2BE2D7EC113D5C45FDC998D",
- "hmac_key": "489876B3B546151944E9BF68F313FF85A57E4F0AA10AA937AA01E5F38629D8E7",
- "adv_salt": "1FCD",
- "plaintext": "CAD15F38FEBA1822DF2FF59D9D957A1E45F969BA2CD6EBD9B21E1A77ADD5",
- "ciphertext": "374BC96155E859C94B54724C63EAD5AA48EC1EAF80DA58645CB67D1596E4",
- "metadata_key_hmac": "DA193D7A30A6A1BB378086C7268B588F72FEAA7C4D55E23BA6D6D8370D0FC6B6"
- },
- {
- "key_seed": "DED6991887A8DF6FEF86818BFA5BFC500EC26A8A5AC46AD0930372CA853171EC",
- "ldt_key": "7E450BF4E4FF15A0170409A3C9ACE09A56B68B5C767758E2D3C0092CB5E2496469381D9F672C7FB79A377B0B8CE1ECA3A1758AC53200EE5AF9B5840756D168ED",
- "hmac_key": "6F2CBADD9A623201139B518CD064B84335CCB95C51880FE1703D8165A9DB73FA",
- "adv_salt": "93F3",
- "plaintext": "415A1BBF0375F9BAEAD6C8F12C0871991D2B9769E0C0",
- "ciphertext": "C319812E0958DCB530583AA0F86708C5910689032E2B",
- "metadata_key_hmac": "608A1CE3B8549B766BC485325CC22A4AA35993D8258A04DEEE1B4D3C3A2E24E8"
- },
- {
- "key_seed": "8F06814937CC1CD3DEE445766BDA35802F1F90DB041696BCE49C9EC57A5EADA8",
- "ldt_key": "D10BDFB216C67FCEF131FFE348A709DF30FA6DBC3DD3EE24871D164DD2F57FD5F4F02DF7F2C3749C29C75C79D9308AEA094B7CDCD49736F44E178C9E000954A9",
- "hmac_key": "D21C39E1A8DC4CBAE82347B4FFCC25555545CC5FD81C6FA44C53A13E1DC18634",
- "adv_salt": "6C7F",
- "plaintext": "370B54A52F182467FE71B162EE0B7B13B820B6066F00",
- "ciphertext": "565661CB8811F9FE7F76050884763A1E18C3BAD52061",
- "metadata_key_hmac": "79B8C81795E9BD20CE806A3D043A6B09BD2ED0E60776718C70A06583E8123AF9"
- },
- {
- "key_seed": "F9BF622E0E202B09C7064578FE5D476152BC66E22027F9CE1EC93C3598E023C3",
- "ldt_key": "6ECE9BD2599C407B78833FD38EF430916958136DA9DC298899380DE639FE5BC28CB73A9422528836D7F4C4333083CC70B5B209A82817A9BC598EDDE465071A00",
- "hmac_key": "8F8BBCEAE4BA15C98BFC13FB9E6128546F8B35C21A0436F9A268F8E0B3C750D0",
- "adv_salt": "DE64",
- "plaintext": "EF149B9523C59260F9F1BE6E5F398A67462D148D54E8F736C53C8DE9",
- "ciphertext": "472FBC227FE51F9665473D5E4766EA430B19F8D41B4EC681ECDCE762",
- "metadata_key_hmac": "EF530F925480E6119B9756EDFF83D85AB8B9835B7C91B4CE73D09EEBA986F595"
- },
- {
- "key_seed": "5A4535D6C65E6F6C4331DAA9A82AF970C08EC5494997334E549B0BAFD8BD0EFB",
- "ldt_key": "A49522B39E6F1056481CAC2813290655A0E3E5C5D2B6690ABAEEBF443C69FCCB2C92E13358939D5BF76492FFBAED6597B4FCD1FF197C3C20E14F957BA955D388",
- "hmac_key": "A0CFB7E0D37BCCBC50338B76E303656B4AF45D1E4CC30D30D89CD457F7B203B9",
- "adv_salt": "35CE",
- "plaintext": "95928C9A06AEFBDA6A7CCD95D5EEAD60B088ECE67A",
- "ciphertext": "DA6ECCA8646CE06BD84BF18B112FBDA195C9096CE2",
- "metadata_key_hmac": "CFCE2919AB5341679FABFE8BEFD6855E4EFF443FF352872DF0F67F90B9543D5F"
- },
- {
- "key_seed": "A1114E41B51E081227AB06CDB0E5239DD13B0E97B31E6EF8F8701A4B91636E30",
- "ldt_key": "9441F2E6D59C21AE024DF96AC18A0BC769D0F166C4B68A5F1F926F53D2DB81A1D4B9414CFC365702A082F123F7E489EECA948E3DC8B78E7CC3327BA5C9AFB79A",
- "hmac_key": "ED4D3D7846C36C9A7A29A55E304EB86DD67ABD8C42DF57C7F2704C15F450F782",
- "adv_salt": "2FDF",
- "plaintext": "59788107CA48F947B2855B1771A09C45B97B4C024198679C",
- "ciphertext": "75928E663962012B017FC65FA716FB2C03AF4E6767650348",
- "metadata_key_hmac": "7732C6810745DB6910FC1E4821F965405D9E48EA675AFC93F893EDBCA04D564F"
- },
- {
- "key_seed": "4DB0975D2F6D6B3EB12BB3BAB460F4386D5E88AD09E0B457DC3A1C55D94751D4",
- "ldt_key": "BD51281E7EC90564A5A29F85C8CE6244035D29261DAACD4D81400FEFB365A43B56AA8FA651F83CCC314B6B84F8FEE157ECD56AADF1ECE204015BB75840FF9348",
- "hmac_key": "E2DB87BB9D7223BC2D71EAFC91FA66E11CAD6EA0BBB186839333FE4279F466B7",
- "adv_salt": "4E0B",
- "plaintext": "A91467F408F444CBED194AC5307EF4181646",
- "ciphertext": "B97D2305E905784DC692289E2D64023C0D56",
- "metadata_key_hmac": "3861175C0B2B74A0DE6F1F39CF59C8FE678AE79B6253BC48E008C140EF10C481"
- },
- {
- "key_seed": "BA648F4E0AE9AF10F05104F2FBFBCEE0BB1FA0355555680C571132181D05F1AD",
- "ldt_key": "896ED7242321DE997A3401BE142A595016F3C54642C6274925208BB790C6CE89F2534BC74B5629A147A2990E5CCE163CF1242AA5D3C888B760A3091653C8E1A5",
- "hmac_key": "73E65E7E0EB5B624AB34163A2FEBD7388786D74E4E080DA8D2D292935183F058",
- "adv_salt": "4653",
- "plaintext": "BC2FC7A078DC86A8511D8E332380EF95A839",
- "ciphertext": "FF06B9495E0F16393DE9B7B64F409A582807",
- "metadata_key_hmac": "5F55D0F79D6CE882DDEEC1ED316E4A1732CA9D3DDC62B6B7EF38D005DDED3A26"
- },
- {
- "key_seed": "6FF5DD9A8638451D09EC42FE83C60F743A4F14049C3EA102184F8192EA0792BD",
- "ldt_key": "1D767FB92E69710B6D0FBF602BDD07F78FA4B6C8B32AEEF1433BAC04C55ED6D0CC3F96D2843E6A856ED3210B5AA1B243568A8E4A66B947AF4C73C0401EF57906",
- "hmac_key": "CB419433BF50E8EDBB7D99757E4F6B44C08F1B34B39F43ACA6DBA1F1E342687D",
- "adv_salt": "431D",
- "plaintext": "208A5B5A5E3FBD6B966A48450BAE7BC142DDDBF0E406BA0373F1FD",
- "ciphertext": "0BD3ECA5EAC8A1CE354FD6673AE0FD4C5FAE891D17D1243F89F16A",
- "metadata_key_hmac": "2ADC08969BCCCFAD5CCC65C5EC5EF23E153A854AF479D82A26A68442BC40C682"
- },
- {
- "key_seed": "007179CC6DFAC2206616506969B8B4523DEF33A7484A8422420387CF517EBD6E",
- "ldt_key": "6547DD1C3A839BD25719F7086A39416A2A5F2127F04578F7116654A22B65A20229A2C89FCCF1C5A3AA90FC1321A393517C05278843B0D01996236CD747EE2F0A",
- "hmac_key": "A93B1379F258266D371399EC911827037CB0F1A896419FA50F66B638D8B56498",
- "adv_salt": "8CED",
- "plaintext": "EFF413EC2429A863FA47ABC38A679DF714D7335F86E811288F82590C90D1B9",
- "ciphertext": "8F2C11EFAA18DA47CCE6BB05EE70B7F4FCBF25A51CFF41F440A0B938ABF006",
- "metadata_key_hmac": "1C8910D812CDE5B90D80615B93182708BB4E32A6D29DEE96590DF47B9AD5E2D5"
- },
- {
- "key_seed": "8EF6C0B1B0F45A0C7A3DC587544D5AA38FFDA1E4486680CAC2570A679ABCC80A",
- "ldt_key": "07A9127089B82445D88A4F5503F909654EDF75D5E56B5DA358F4C0A3E45312D84CEEB8E4DCED559DA036DA236352116691442CC07967A79F73CD47EB510E755D",
- "hmac_key": "9C64EDC9C36ADB8F20601DFA9DD9EA6D116A19C3CDCA6E69A5F0DDD4A0B6D31E",
- "adv_salt": "1028",
- "plaintext": "2AF3D2C7D0CDC8EC583521C17400F4D3",
- "ciphertext": "5D92FBB35A5A032ED4042E3803A646FD",
- "metadata_key_hmac": "E376FD42A95C169E444B04AA336053445A3B29FE947A52F0F907982AF03CB879"
- },
- {
- "key_seed": "45AC70DF90E61ED6FDE2BABD2DE9DE4F2B818D9A1D52CE8CDC56F53F0D6397A0",
- "ldt_key": "BAFC221A84DCCA1B5ECFEF66DE66497547131E8C4548B6353B013111E76E02447429A86A71BCC50F02576C4E75FE789C5D0226B979A97EC8FC63600F14AA281F",
- "hmac_key": "C30D9ED8BD299EBB5CD23F86EEAE1068635347D7B5061FBD17C34CE9A14382A5",
- "adv_salt": "830D",
- "plaintext": "4F4B6CD3BDAD13388F03E295A29734F1AEF1",
- "ciphertext": "F1AD9D75E6013C892EC19A466BD346732C35",
- "metadata_key_hmac": "3D042C46EC4B53B9BF2C301C02BB137179037B09529F12A816D04A8DBC94863B"
- },
- {
- "key_seed": "9C5113AEE454EDFFCAB89C356831E822F76FE28154990FE13186438663D75A3E",
- "ldt_key": "24FB6B83E745E019E071368C902F2ED6762D87498A4E14AFEEF4210BFB2A9E0E9953389C9D5E0D60BB337801C1DE1BFB658BBAE4E87FA943BF6FBE824E4798F6",
- "hmac_key": "AA068CC06CDED1EB64ABFF4B28DE707FB2EC585231788F3C319B7651563CD17C",
- "adv_salt": "A65C",
- "plaintext": "104736EDA44F39305A5CE472049989DAAF9972B35DC8",
- "ciphertext": "532D6EFA1313457BBA6EE436609DFC11DB7B4343B781",
- "metadata_key_hmac": "ECB5D9170FE03D317E5A3EB11C4BC5F8F8123A7A3DCE3E68CD4B547707DC7C74"
- },
- {
- "key_seed": "29C157553B7C46F058EBF29D6BEBF05CCD33C943AA2BDCB5510B372861CB5F78",
- "ldt_key": "A3544DC50715B43F8EAE5A307696C47C061CB518BA11805A7161877FAF26D1F2854FEE2D0249852FC2D93699C945A74A6E007ED2C33A3B7054869BB2DC951BB1",
- "hmac_key": "B9701768F5AC2E7FE0FE2784412877AF4124B7AE53E68B4CB849F81683E3F057",
- "adv_salt": "D44B",
- "plaintext": "BA6825C31151EE0722F26847F99281307EAB86791A9C61C2DF7A7E0C",
- "ciphertext": "43635813DD9653DBF32DF9CB0469065CEA7C6ACBB125D3AD9EEE658E",
- "metadata_key_hmac": "7E27C5D993C851B84ADA7F432D513C36E8F6D491CE47FD1B0C06825F04F932B6"
- },
- {
- "key_seed": "B0EB2DAC5710C79EE1932CE8F17FE4D366547E7E2175C1A712E1F44D4C2E2108",
- "ldt_key": "6F74ED8ADF4005EABF1E018BC8569185508A8D954A7607B68CC3CFE98832D0B2210D4C069C0F5FA6AF7208287C2B068D67730B8B8D82B95B47AFFB178677A9EC",
- "hmac_key": "FE7F4D7A058B1D6E15A70EA481C34AA0F0D6A44FE36382EA4BFBC3C7E43A7298",
- "adv_salt": "B2DF",
- "plaintext": "EF23D6F6A1CADE520DF4C25B4A2ABF6779A9DA4B361F6DF6FB",
- "ciphertext": "0D79F1106EF4E722B2C8AD1AFC5BFB1F7ADE166221AA5F8016",
- "metadata_key_hmac": "B721CA7742066F65D798FB714CBC55B64E57C9BC7DFF464C2571DB78CE88280F"
- },
- {
- "key_seed": "009A9F4A605A66554743DA0E493F9A33C48973888D68FEC628E449393E5FA3E1",
- "ldt_key": "415C4DD2919CB1F8285604FFA82E5FAEDE8A4F186F77370A509BA6FD4E3155AB16326C8DB36FDD685252530D041792A368C092DD9F4F020CDFA8B42487660188",
- "hmac_key": "734CDADB4DE10FD4F9159C523B0B62DAEBE653A982693071520D6386DF4979B0",
- "adv_salt": "46BA",
- "plaintext": "87D22D460F1178F26FB8B537374856825563264F3908",
- "ciphertext": "7FC280353C298F5AB2423B0CE4C2E756601C4A1C395D",
- "metadata_key_hmac": "6DE60DFBBA508C7A30059582BBB6D74C2D4B14AC6C135016C304026FEEEE21F5"
- },
- {
- "key_seed": "9E86CA768B535DB61C0BFDBC1FB5D0F28B5499D0D954DD90FF3DDFDB90084C07",
- "ldt_key": "939105E8DA13970026CFC2E622D8880829FA89214F3DA76A6BF46A0A816DFE2633877871D2CF4F093BCAE6B40DE7E9F65D0522F2577943B040BFCECC44BE7148",
- "hmac_key": "B68B131100130CF46E88F47301774490B99DDA1E397C09D791FCDB0F5B3F4CA9",
- "adv_salt": "D581",
- "plaintext": "8485BFC1ED2472C01D6AC692C7011A92C5E4B11E",
- "ciphertext": "35B09B08491CB095260EE18F971B42A7EC8408A9",
- "metadata_key_hmac": "739FB784C50F16B18DD48417E91447AE7E5AAA085F217F3C32CB9070ACC0AB69"
- },
- {
- "key_seed": "DD5BF59A0D1FDE574C417CAA8D9B154A16A70310AC9ACD548F01AE6F48AF0A2F",
- "ldt_key": "6A8139A5BD21C918C47F00DE8C711A8E19B87DF67BDA7AC3F91613222365FB2ED0248D574BDC0C6CDA67E7BCCF961944E818DE916A3DB44F7CF75FBA2D339255",
- "hmac_key": "C0F6FE0B6811C5DE637B0F775D7388F12A6AF805C9E0B962C21513C4A6519891",
- "adv_salt": "C7D8",
- "plaintext": "5C155BDB14AABAEDA8506B901F62BFC06CD1B24AA2C9CDD2C224",
- "ciphertext": "5AB031D04796DF77F2892C4926E90D2DEB1E317642161FE53142",
- "metadata_key_hmac": "D1F6F0E2B8D9F1760FD3E76B5952E56A1442F2FDFBA2BC6ACB038A2554D0189F"
- },
- {
- "key_seed": "A9302C3763D1B55F5F1086D4255088942B2AEA3794FED75D9A02272AE2A460B3",
- "ldt_key": "A909626CEC0F439B0AD454A66CD0748355DA03D56D69309E86B89D34C06A021CA7DA2A55A5AA86373484C4B110019C54C84F1D19E2CB7CFE3309F98D24E9F78D",
- "hmac_key": "2C67C798D5F2DB996C6409ACC8E3C712FDC2735261F18155BF9A4F2F23ABBEAB",
- "adv_salt": "4D48",
- "plaintext": "67C49EEC0D0B2189F7F57AB202C70ED3BB573A",
- "ciphertext": "BA6C447C9DCE15414014E1F6EC1175695D07F5",
- "metadata_key_hmac": "ACDB3D18AFB857EAB7E9AB74C72C8B8C0796CE5AC81793E7B1AFC29B8ACABA1A"
- },
- {
- "key_seed": "4FDD1EA1F83E8C1E076E152841D9D7060A25C2CD08886D91AF5407A54837782B",
- "ldt_key": "C5384D76C40CC48114BAA1E2D7E5F4260F8D9E8324C7D358316D2045C7C3F50DFFFAF41DFBC8A6B5D8D5E6B3A08B85FBB1B6054256C5066522C027C7E9501DBF",
- "hmac_key": "66FDFCE8CAE843E394B3B2DC07359656C07E5013D7CE65A75B62458288420A88",
- "adv_salt": "CEF4",
- "plaintext": "F99804807B744EF30BC27605453B918A0CDC314B",
- "ciphertext": "9B6568B0BCA8AB1C8D15AEB5D97DA2740CE94E01",
- "metadata_key_hmac": "D31CD9242164684A1A407B30EE1ADC1440AC2D57A8DAA4FE16813AB58AFAED65"
- },
- {
- "key_seed": "18039C5E631E718706E5E4D16E9743774C3CA224827B14B831DBF73E3B0BB89D",
- "ldt_key": "FC4544B4C389D90E145ED6FB0AF7B65598A72305EB6CDE719E50998A54846487794B7AB83E065A488EEF049FFBC173BA3C46FE61D41B8C5D1B8FE8D95369D691",
- "hmac_key": "26A5EE999C16AEE67BFB7D0C99CA798A7C336210A464D3873F81A194ED7E6EA7",
- "adv_salt": "09BF",
- "plaintext": "642530D92AEE6E1FFB643141611A54063799B2B2FA3BB0612749E11C1ED2",
- "ciphertext": "6862DC411093C22159CD52C078892BE2B44DDD51CA80271D3AA86FD9015F",
- "metadata_key_hmac": "D83621ADCB72B4868FC98888436BBC1CB298B8189196062D8C5481A1D0C36144"
- },
- {
- "key_seed": "07E84066C58C06C51EC8B808170FE789532CBA93C6582D0E754BE6B22B14FE71",
- "ldt_key": "A31BF22254E1AD18C8EF1D435BA3943568E9E5D20BDC4D4679F34CDDF0931DEA62871B0F8560AFD4EEDB81680720EB3687D8807BB621251743415DCEB387CC10",
- "hmac_key": "9526730144BEE056A80AC643CEEA02CC05ADA715948BC5D9FBAFE7CE57A241F6",
- "adv_salt": "45DC",
- "plaintext": "049476A522B205FA1A4FFA1D11B72371188596BCF23675EF339B",
- "ciphertext": "DC896B566CC1F42ADD142657DE80FCFB22120F7C5A38564E3F3A",
- "metadata_key_hmac": "E863A720661C1E596D0DCFAEF4E606B5EAAE99AE7C1435EF2705A5819D0542C1"
- },
- {
- "key_seed": "3129749A31A2D287D0847A668253135CD00CF0313F65256BAAA0982B0916742A",
- "ldt_key": "8B8CE49C6467A653BFDA93865DE10B97D5618843E5107B7A416B4B841150A45356950A78DAD9773C40A7F342B341A04514EE6F37BC822D69915D01D423D863CF",
- "hmac_key": "1C4D6B48E9E6FE68ED0B83EDF0AC11B1844C8EFAD0841FC6066BA8180F1FE42F",
- "adv_salt": "BA10",
- "plaintext": "F1FFEE839C1ED6B21262C0DB7408BB26BA",
- "ciphertext": "8CEE4E47ADF425F010C2C5FA8FBCD33E2E",
- "metadata_key_hmac": "0309251E455622EAA04B5E54736068A8A1940C868788FAC2C205A1209A8277FD"
- },
- {
- "key_seed": "9FA2A639EAA55D338CEA530C924BD191A1CC99CF727E9427EE59E291F679FFFA",
- "ldt_key": "6EB3C48821C6FDB8ABAD5B676CA872912CEE0DC934B0012841D0738C5F1D751E1FD9FF27903C48BB6B1495D62A0109DA5BA1D594AF894CDC93FFEE5E7DF9C36B",
- "hmac_key": "7410489E590776BC309BA2C538835F0A7138C46881074FE3D89A0A34B8DD964B",
- "adv_salt": "0E73",
- "plaintext": "D9B608B87689E69393CBA7045CBA2675D5210FD650E8967A1200",
- "ciphertext": "395248FEC028BEE9FC2E94F0A7DCF1DDB14C0D9160F93B27BF44",
- "metadata_key_hmac": "F880F33851F564CE5FE2D9C99CC3E75FBA95A52BB44755D6F99B8B00FD9ACC8D"
- },
- {
- "key_seed": "EFB1AA2A2F7D37EAAA53416A15B0F595C1B1785700C33685E30B3BA08E409C6E",
- "ldt_key": "2DF7BA528C2E07FCE74117A645D060CEE32F2734E1012CA4CD57E2B97F7B5C168D70060296B2FA47B664E040CD7ECF4590058503D3D24967AE0CE9FC6901B72D",
- "hmac_key": "36D64D8224129E300781C7256A05956BC61F6488C2966DB79D75E50F02E22DBA",
- "adv_salt": "F5FB",
- "plaintext": "CD7050E3B6568748C6D3B1141651EE8FFB74C58D67",
- "ciphertext": "DFCA49BB63A411FEACB0582A548E80C9AE030DDA58",
- "metadata_key_hmac": "329A9CF2F51A7F8518F19CB80E3DB6C2157D8F4BADBD466C3510196D91F02F85"
- },
- {
- "key_seed": "ABC26C4EDC9AD2E8414156FFDBE43DA525724F9C5340E0849F8D884CB52A76E6",
- "ldt_key": "218CE9DFDF7D36F52A79A69D06934526E2FB1B23F8F4A2BB3191270B65642D9D81F959533DF0DC10D9D9D5DA482B2AC6E648662A15A38A5D7E551D791C8854A8",
- "hmac_key": "694AC6E4B3626FDE141A592D658D917C53CE135A83DE39A7308C6AAF5D800F4E",
- "adv_salt": "CECE",
- "plaintext": "400F3055B755F217E37B1BDA6B9223199833B8384921",
- "ciphertext": "86D1030F1E356691F1FF69B5E11EE37A7857F540B482",
- "metadata_key_hmac": "7AF560570537967A5110F475B8AF8D085E452523EFB58E2C5665B109527CF752"
- },
- {
- "key_seed": "27AC86A165B6C6170123EB80412BFAC95B4F14718F7C8B73F0EF84140386A9FB",
- "ldt_key": "B23836E5CD10B4AFF120E576F51827952492634C12E8D8ACD63B3173EB2B2554CFB9A2879E9ABE990386064FAE52C6AFA4C5A62AB6B7A3907791C962AD458A5D",
- "hmac_key": "C17707BA5D666817C2C95164E5B048AC816E65961ABB53A2709937E3032133D9",
- "adv_salt": "F5FD",
- "plaintext": "0F0B5BEEAF33D297A944115A4D1C06FA2FE6E3379A",
- "ciphertext": "B729C506A6F6DF9C07EF46E4A29164E9B6A1D03936",
- "metadata_key_hmac": "31DDD00AB86582E2664500B7B76A1797895A508341B9BBC20A20AE3FF72ADC44"
- },
- {
- "key_seed": "F578B69AF49988BF7C2FDDB5C70C65A99BBFDF435D76E195934CEAA6A7D9E724",
- "ldt_key": "D627666F52B99ECAA3A7CE145F1DA0FEE74EA601B263A64E5336A3307EEAD2D6CDC241DB163EA08B70A0B3E6C0DDDD846CD5925A0087B897E96E1477E937CA78",
- "hmac_key": "7ADF86C014B307C4C76D6AA545F34C885CBE45586CCCA91BA444D9D839EA0657",
- "adv_salt": "822B",
- "plaintext": "05D4E637910F7636BDAF10C91C8EF92B1D0E6169",
- "ciphertext": "43C0010F5154A64828D869C1E8D78AA43C6CD6D3",
- "metadata_key_hmac": "99BC82BC668CF625E2AE0C57BD87A5EE34DD6C4DB06B47D64DC734CAE3C51FC5"
- },
- {
- "key_seed": "7F5230AB4FFE1F84F9CE47EB0552A7C3EF609D1022A8A63948882F4C01535229",
- "ldt_key": "FC342ACD336EE593AB577321825B3692D1D3D0784DEBBAC1F4FA23C98C5523AB04203F86122BB874987062DF9F94F91B875C2FC505998D07779349C7811BB475",
- "hmac_key": "D62D38D7E3DBC68343AF3053E872AA59D2AB568627ED9DBFB84E1A5D29443F0F",
- "adv_salt": "403E",
- "plaintext": "C57CA7E2F5136CA9604C96D8EDA58DF09E78E58087A5B07838",
- "ciphertext": "C330D4F9C93587A1CD30B269654FB34C113D4AA0254E7137A7",
- "metadata_key_hmac": "AE6B59CCEB9EAC49D550FC756FBE278215C92CA503D72AFC6BD5D7887B5D4868"
- },
- {
- "key_seed": "417D441008248EA41F90273D48874CF56A9DAC55270F5959E210D28D77AB0857",
- "ldt_key": "2C28EFF0F105DF2ABB5EF097A1DD3B7266582761AE4BA1413A3C1C05203CF08E5D9A69AD9C7F0DAEE94BFEDACB926F0F6E6C1C460B3257FDE29E53FA637FA3AB",
- "hmac_key": "773DEF77549B95A210F4CEDE4A0DA2D819A1A744B1BD7DA83321199DD11FAD62",
- "adv_salt": "CAEA",
- "plaintext": "0AC0691AF4BB582180C62183B345B241F6F1",
- "ciphertext": "A6841FB64E1F975B1E33AC1115BEA5C54731",
- "metadata_key_hmac": "4EB36FEB8FC7D5B3C1594FAA66837FE74CAB1EAB5805B40C68134CF96BDA8D91"
- },
- {
- "key_seed": "D8BE2DEB66079C2A189BDBA5ACDA0CE82C52E804513CCD7458789E38BA81CB06",
- "ldt_key": "64EAFA3B3394895597807680DB7F1B8AC7172495375C0547577415110C8B021902C6A31AAE1D288594D0BD59396072877633DB1F3A794DC9F9549609CAB703E9",
- "hmac_key": "7B74179C3AA756E8A538CC1692F943CFB6FDCC89C7B39715042DD210D8333580",
- "adv_salt": "4073",
- "plaintext": "B7E33A6E31B663ED161FE93A7094BB3A6A",
- "ciphertext": "B57378C629B1C32A257E6686E8DF988F8A",
- "metadata_key_hmac": "02DF9779CA339B433AB29E36E81DF868CA95BEA952ADF8E2E07240CD63783510"
- },
- {
- "key_seed": "6EA44D999C40873243BE45A05C3B9018F4001829341067BC146F4DEE92DEF40F",
- "ldt_key": "34B9DF4B38CC3D8092B944C1A53FA957F0D655250113BFC82E94E06B2F1631EC9EFCB8AF36038B6289DB7D5EEF67BA75EF358007D3F6A1B0B2BA0C836326E6E5",
- "hmac_key": "ECF156444A6B6DF4206076E4B90CEE5A6F97151271F866B7947B2B816D8BBE33",
- "adv_salt": "8130",
- "plaintext": "EF938897F1CE69ACF8682432D676D657C03A49754489B0",
- "ciphertext": "E788FCF88F97736EBF9FF8B33A3D05698709C053977EA3",
- "metadata_key_hmac": "A24356616C577C504CD564ED753E73F513F770175265DA809C90DD8C98B60766"
- },
- {
- "key_seed": "B5FC1961F611B50A2A9953E7C36D271D08220FEB4986421A2549AB1100418F5E",
- "ldt_key": "A8E12CBF2C0BAE68EBFED064BBE586247ABD2116CB5289E6E98D2B2ACE1FD48109B9877081766330136895F1FD6F585FBE3F5F0EE36E8D4F4DB64511266EC732",
- "hmac_key": "851E5CDA65FCF29727A9E964D35A65AB682D2E05858C25FF70428719BB572531",
- "adv_salt": "D8E9",
- "plaintext": "8E1698000B95B7B6FAC61F5DB07049F00EC8D652304E94EA",
- "ciphertext": "E5ECC2FDB01C052E5A666A131F160B263FA48A2B2725B56C",
- "metadata_key_hmac": "3C54F7FB95594654F7EF39804C9CE54CE390A862C24921781B6ABAF34E960A20"
- },
- {
- "key_seed": "FF14DC92A2C83279AA4E8D766C754026842A66A881E03C11A56D25ED84C1BEC3",
- "ldt_key": "690D6F6D509994CA4949FB7ABC137B34B1BE1FE69DE6730632009DDAE117E345A693D3A579F781D1542CFE2F09C03D6FE5444B5408D612C38A3FC9636E39030B",
- "hmac_key": "B79E2E333CAE27B5B2082ABE06F9CC314EB1A6D6D5D2EF70CF63E4B7E30C579D",
- "adv_salt": "31D7",
- "plaintext": "54A39E955424818A57DD2805AEC1498E4AEAFCB811F7674DD8A6",
- "ciphertext": "88D16368537C2BC70D734AFB07323AAF37D51E3995BEB444FCC4",
- "metadata_key_hmac": "0B77F68966ED8A0E76893CF64C90BE597268F8FB56412027D2BD7B765FC87BBE"
- },
- {
- "key_seed": "C4473B2E6E2F31C7736B118AB5D9626B78CAFAB5480C64FEF40F6EA23DBE7A3C",
- "ldt_key": "C657825718A2C746EE1C90C18A2CE9B6991C634A1C5828BD45510B8A6BFEF7F204EF2EC7C1402C5193F94691F0D2B2FAD84BB4BACCA761C72B1874E289210B44",
- "hmac_key": "96BEC806C7FC3EEA8B19C179DED4A2EB226B1E8B3385066CFD24FD9A837BDEDF",
- "adv_salt": "FF46",
- "plaintext": "A3841B00F0220E916B5ACB7A71EBC7B833108A66618304201F22C7AADA",
- "ciphertext": "9E0960626A61097A1C4AAF5BCC94B90898FC14D8B51FE0617E4B6BE251",
- "metadata_key_hmac": "53E4FBC415ACFB8FD438618F6D815B6A8DE77344922DED695FA12BBC9B5FA44B"
- },
- {
- "key_seed": "474FECC88AEC0CFFD59038B1E48667A15F1983EED00388BA3321B78EA28758AB",
- "ldt_key": "9EAA8D17CC67A89956041175D5171BB0DFF028C5E8416BF6E822DB5BA09E2BF20A45811DF8001CA0214523292EF22370C91957CD8A5EC05F5103730AA13E1CBD",
- "hmac_key": "FEEE6A7BCD8411A7FB71A8EEDBE9CD0684C44AF977A93807878D340A001DFCFD",
- "adv_salt": "0C48",
- "plaintext": "9B1EBA3BD9AD1F7958C66E906C8DB21F5AAD8E358075",
- "ciphertext": "D50230DF83D87F0CE0F37B41DAF6AAEFB1C6441E270F",
- "metadata_key_hmac": "A2F7759E8193B3AB8EF0D76BBFCAA514C9C6096E81FD497C08DB5098642A4CF3"
- },
- {
- "key_seed": "6FDBEF4C15EAEFF76DBF6458FD5B6C15D6A1CE68348B0CBD7820AEED7E9A4E35",
- "ldt_key": "DB7EDA05A1DB8DA743EA148B1A6F0EDD0130D966881DBDF830581DE9F5222E78C7459F0D3C3A0E9D73F1038B6D23BDD7D64BCE352F3FF2FE115AE5E65F31729E",
- "hmac_key": "2E60F73C97AEDCE38C36582822BDAABB612D79845F7724B0BA576E2DBEB8A2B2",
- "adv_salt": "E99F",
- "plaintext": "D60F851EC8897A4B8DACA7DEFCE0E4152EFA9C54",
- "ciphertext": "2E16D4480367179CCF871E14E38CBF2FA2171134",
- "metadata_key_hmac": "B8BDD63EDB687A7B8EC7B8BC8967A799735AECD7E95553B6D32D46973177D3E4"
- },
- {
- "key_seed": "F516557262D28E66F09960BFE8564A8E1CADC43DBAE7CB0E82C18B2BB004ABAC",
- "ldt_key": "7CD3494F9870628BFED5FFEC6E621C94B7A1ED4BEAC89C64168CFD3B7110A36F2E0B3CFA1C2C33644859514B17C5DBC7254E177ED5B4D4BB5526355C84EBFBB0",
- "hmac_key": "5396B5EB45B5BC6E30BD4F1D7D692ADD9CE70418C8B4C5C3B2194E1BB3327E89",
- "adv_salt": "C01A",
- "plaintext": "F002C1693EECC0C20F773241EB3FB3C4",
- "ciphertext": "BFD413373158A3D367C73937E9737405",
- "metadata_key_hmac": "9F5F641CB02A81FE6D997A87762E663352988DD1A09A093AD2CE61C0C25AE325"
- },
- {
- "key_seed": "1985D7F9F9A11F655B3C3EB9A81B9E90A1C959CC1427CBFD618316903A51DAD7",
- "ldt_key": "A73191FC81DB46662B43A789A685AAA43390AE39CEB11C0C76D43F2E6B6BFF0DB177736F004010561FEE902400904A5315A28402CD7444AABCDC82581822BD14",
- "hmac_key": "F44B2E47D31D57FE69C622110D03ECA496B3AAA6D69A590495A6B905130E5244",
- "adv_salt": "85E1",
- "plaintext": "465B4E165C848033E2E2EC74831ACB11B9EF",
- "ciphertext": "E135AC0571809DFA95E34512560A06BE1947",
- "metadata_key_hmac": "DF267B79E8A22CD628EA16C01A64D93603C900D2B388E581340042FEFF746B19"
- },
- {
- "key_seed": "9AF3762CC76A2A6203862DE8D2FA67CA0A73C01075039185177DF0414D56D421",
- "ldt_key": "4764968DD0942D35868079E0AD4A1BA71C8BDC5D256E60C8E57AD84238BAFCD2277C80BC1EDF683C7BD26149680314A79FC319FBB4D90F1537AE421155C98B71",
- "hmac_key": "EA15DB5934168ABC0623D13E74AA98097BE49679B953CECBE96A50D02AF9ECBB",
- "adv_salt": "89A6",
- "plaintext": "B134F7F24998FF5D1AC5A2815B0EA229",
- "ciphertext": "53A50DD852AD8110D429CEAF2FB3EC97",
- "metadata_key_hmac": "C69C88641A083EDD5659788CDD5D3A097E12A687200B84899D8681A8F7678653"
- },
- {
- "key_seed": "76FE0B927C490E294DA486F85AF5DA0EF5CBD230BA8652BF3271AD0E8800B5D7",
- "ldt_key": "CE41FDAFEC4492D121A51419118BB84B2ED584C4AC5F8FB0FEAFD6C89C8E293D74B1241C99F53994254753751F486F013BACAEBA763C7FA90E4AEEC759A540AB",
- "hmac_key": "64A57BDF04F5C58FCC5BD089DF52327FB4BA704C1340E9DA91E2AA8C81F33D6A",
- "adv_salt": "4A90",
- "plaintext": "E29B0C659BD28FAD0E037818E6A8932799C2276C6E114F5F7DA2",
- "ciphertext": "99DB117C981C745A22C8E2650F5A900E2FA9C97E65511F1D9E23",
- "metadata_key_hmac": "3C362A974C82E7449CC0FC9DBA40A324879F98E6CF7BA38CA3698F27BDDFD426"
- },
- {
- "key_seed": "9DCA3F0D2FFC32BD5C68951801F3557549E1AAF83A21679C2E6C40EAA0DBF6D2",
- "ldt_key": "56ECF11E51221557A982192A8F5A3D36F5C29A536FC878DDFE470EBA0BE41C53C7B8817C24EF68EE70017D76EA7E44455438FB14BAE69B224ADDD6A3FDC306AC",
- "hmac_key": "3B9A4A380E58FAB2442761DC37F6F59DF05CDFAF09422CB48FFAA6383C6F3361",
- "adv_salt": "A4A6",
- "plaintext": "CB6409DC49FF98448C088D4A85CDD6DAFE00C9",
- "ciphertext": "613B69F24FBFF245023185D0910147158051B4",
- "metadata_key_hmac": "648100F3DC460E5ACF5B55EA93724C3A6171C7AB188D9A90335E1A28D96BC43C"
- },
- {
- "key_seed": "25B06DB454B451879690D09CA4ED02860760E1CDCBEE695A61A2B81C3F386C31",
- "ldt_key": "A3CD706DFFCDB4B801D147E9742833947FE9595A75A411DB407EBE5CAA84CC669001725060D6C29F50004242DBB49E13A14DBC79662E253943CC1AEAB6612297",
- "hmac_key": "367818C87FBEEDA9AF02EDDF6794A4FBEB24FD1889AEDA80614AAAFDA0F39E0D",
- "adv_salt": "B7FF",
- "plaintext": "91D4E70BA0BA41B5168A89BC88C7BA1A42D27EDF4AECDEB29E",
- "ciphertext": "CC6376D78FCD2AAB7F2B3C288BDAE96938C69BA2E17E82C7A6",
- "metadata_key_hmac": "EE553F38B53CEFEA846416F90466FCC2C828FC549AC0CA22EDBCCB3664B58EC0"
- },
- {
- "key_seed": "1A9E7CF67D957D6C95C4911B7F13B51B03EC8E32A6452E8AE0F5CB5C237A9F58",
- "ldt_key": "F0628474832A206D611FF26047B9278C20F051B814C304ECC3C965C9304E8899105C85C2F8AFB290E0331B884D2CD6E7F4383CFC2214810B3DD83BBF58E6EF58",
- "hmac_key": "A0DF5EF1724CB80A2486FA2B145535EF01451A42AA5A62F10DBCE6C55DA055F7",
- "adv_salt": "54BE",
- "plaintext": "26C389453C0A3456D8D18CDAF04CAD2FD8BB3A0D2528113A3BD0",
- "ciphertext": "1C1540CB04BC79693A9FA3CB3B9E8B4BF415BB327D92641E7204",
- "metadata_key_hmac": "E52635CEE4261B063C3D8C0DF1C0A0F040CF72464DF03924051533BFDBC3C1DA"
- },
- {
- "key_seed": "DFDACBEA9B418D02783890D8A66D81061C9F1F09B7B0E5FB11D9C7F9AF35F4AD",
- "ldt_key": "DCC6C3DBD5EF8F7AEB877DA03BDD7DC945063E79A5280C5CD8EA518721EF2A4AECE83076F17A6B38EAADA6987E3C556B3AD1FB7D8E9BFBF63A2AA84A06AE59DB",
- "hmac_key": "73E4E1ACD47A14115E5611804F7FD90B014DB454049FA6D5257B0B2F96292046",
- "adv_salt": "642E",
- "plaintext": "C3462E884C31AA6FBBAE14F8122B770F8EFE2CBB268026B283",
- "ciphertext": "E2FF6E14DC25671EDE98BE654CAAEC991D52F34DB57A7662E4",
- "metadata_key_hmac": "1D1F7DA5CE37C71C6FE067FCF8FD3BFCAC432F9B2F2D06C0F5E62483F9F1D0C8"
- },
- {
- "key_seed": "5FC38477B52B0DF63A72767E8C7F84486589B37F310E1C81D6AB646C557BE94B",
- "ldt_key": "26313C24B59A94E324988C760095C13AB03A75CB3410E047530177E9C999B76160D699814FA4CB9D800962B25805CA910EA3870A5347230382A2069DA5B87A77",
- "hmac_key": "59ECEF5646AF89D199016B71BA556742CC361C3535E1B076818E474CEFEC306A",
- "adv_salt": "0683",
- "plaintext": "53FFDF24B36D08AD8BC90CCE772ED7167116F2AAF3375C87",
- "ciphertext": "FB2B693185BDFB21DBD3BCEBDE0C88D057C8058500D2258A",
- "metadata_key_hmac": "39578AEBEF9134108001199C0F5D99EB698986B2546A514EB95021E9F545124E"
- },
- {
- "key_seed": "7BC0109CCCF62E83C50895C7E43A4E571DAA7AE8E65DB1D1EC6B3D0933A71AAC",
- "ldt_key": "13F3CB016E1B394DDC3FC5EFF350773995EB6141F9CE4990C908817B901BED2BFCD9729D3B798929B23FF752F256505315AA79F2284E6A1B07554BAB192A9654",
- "hmac_key": "84A6B032A7FDAAE377AC1FAF708107D765FEA8F9A050D8F8A412A6E2F3F08D87",
- "adv_salt": "29BC",
- "plaintext": "7A2F9C221913A54540F9386C20594B8B807C0B411DFD",
- "ciphertext": "551EBD847E4F22D868AD37F1694AB7D5FF0A0114A4C6",
- "metadata_key_hmac": "7ED99D0E49848BBC2A423E5ED9C3DAA1C29F1A9222A2FCE31FE19133214781C6"
- },
- {
- "key_seed": "6556168FF9D91B457BBFBE45618C6066EE1173ACF423277876D0803764B378A1",
- "ldt_key": "F6346C417BAEB4E4B83205503F81995AF980B546725B5AF8BEF3D66E7BDDC4C9D10C9E6274B2BC37F245D32BE9816494575D33735D0E977FC0D808589DEC51C7",
- "hmac_key": "B685C810EF6A30FCEFC6B94560CD351586D534C98822A48882411B01D77AFFE2",
- "adv_salt": "2EC6",
- "plaintext": "AD9B7773A268252FB51D78FA76D1CB67A116FEF859",
- "ciphertext": "0326A51220BC1AA9AC4CA940383EDA8F52F7EF9B68",
- "metadata_key_hmac": "8D417A9AFF37F839EBA324B565BAEF9A46E8313ACFEF69B286E5D61F189DB28B"
- },
- {
- "key_seed": "F6D1B4EB6C21BC252E825A854DABBC246E330428BB06FC8DF5EFC0F5B5889389",
- "ldt_key": "0B96F3063EC9E34A6BDF15AE7B674815B5B17F56ACD7EFF47DA2A5AE7D689154BF4E59955A1A79CE2F456286839CDFDD14B4A0EFC1C2BD3460DB8315E3C40D6D",
- "hmac_key": "368E36531A75F11087698461D3615845EA409507B6C9A119B6D50D632F6D7BC8",
- "adv_salt": "CF7A",
- "plaintext": "9C4125F3175168B367DD6EA3538D9D9EFA41",
- "ciphertext": "5E890D2CD7595B8171E7C50CFA3097E69C5B",
- "metadata_key_hmac": "7171FB1B8F2158A50DA45A423A42BB72E3233F3D8C808D8D0C6DC2E1E2D6895E"
- },
- {
- "key_seed": "F6C5D8E0D76A826F04E4DAFE0AACB059BB5940CDCACBFD101FEAA4172A140AA3",
- "ldt_key": "D790D1A0D421EF9031D83033B2A6C7A1C6AFD7AE0EA9B9900BD6BF74E7038CDC5A36FB04548C2C833F3458E4D773092356A1053184C0A10B67143713A1208F06",
- "hmac_key": "12C5A42D2BE721E5BCD7A5C374EC4789720DF2D5A6B71157D2D2E6D23661CFEB",
- "adv_salt": "34AE",
- "plaintext": "50FA211D4BADCFD3E6965500B45BD4EECC2E8874EF45FAAA8938E7BF",
- "ciphertext": "BDDB582623B1B58C597D42F549CF3640261A5D6FBE88C5A2AC2FFD5E",
- "metadata_key_hmac": "BF2C041FB3CCE7A04AF3425E6ADFBA23E30543C7C1D928028652FDF6F2DDACAF"
- },
- {
- "key_seed": "10285759BBA3CB207EC111088EBC49D081092DE814F1C9D890E11963475BE0A3",
- "ldt_key": "B1A6F6EFBB88624AACF468774C77389B97A49D93481338B11D679A3F1702937EB044BA5421D81EB2027489DD73DA13E45B10FE29792E7F9530AE06DD332AE0DC",
- "hmac_key": "361C19E2B28C569B81E998F28D0CB80FF5BC914737FD335A045F5CA01C721C80",
- "adv_salt": "5EEF",
- "plaintext": "218A25CAE4B4D5BA6C12641906C9AB50A51D2323E71B2D9B464D43B5",
- "ciphertext": "2F934A6E4466228DF0F4D652F95E5650A4B9B9789CA4D78B949B7919",
- "metadata_key_hmac": "9AF6B6E76D98AEFF48249DAD198B2358512A10C8C2EFF566120FEF2429DE3955"
- },
- {
- "key_seed": "220BA7962D605685F38568E09EA5098A19AB872E170583F910379EE94CA6DA1A",
- "ldt_key": "93F036E1B7F015A73B47F8E6C16AAC1D5C6BC179FE6759C453BADF5367F0619A6FB1025FE0CDBA7745FE83492D345AE5024431EEA1EED8218D1E960B54CB4278",
- "hmac_key": "17FE7160E653F4E0FA0F09DD66AAD32CBCD9F9F6BF83E2CE40A99428079ABADA",
- "adv_salt": "8110",
- "plaintext": "4CB2A60F7C9A1B845D1680C8B9375C51E6CB44E61886A3D0306F",
- "ciphertext": "7FBEE40B608D1D7052CF17B65323050FB0DE90DF6B38A8DA5EB5",
- "metadata_key_hmac": "59F2040D895282A92F6531596BD351A41E717D5CA1764C8CCEA8983E905D0708"
- },
- {
- "key_seed": "DE213CB6D5B8B7129DAA8E26E27E6A0CB1930A01CDF9704F575DBD76413EAFAE",
- "ldt_key": "27B7F2836600D37B972D9A27280B42FCDC15CB731FA1F4B3A3F0C374E5E4AA9AB5FC246BBDE00F768A8CD5E304B80297A20EF9DD499531B3E2C2CDED0D540FAF",
- "hmac_key": "BC34959C3219C01512CDDD44C862CC9F011AC0F23C3B272224FF02724EA07D52",
- "adv_salt": "8B44",
- "plaintext": "9B24865ECD76F202D8153F696C04C1879B1E3784D6D49E972CBB3A",
- "ciphertext": "9BCEB06CE8AB8F2E72FAC2966B523640C37D76DB2B2F16AEFD0F8D",
- "metadata_key_hmac": "94FC4163DCD7FF3EBA6856784E89A291862F204A7D08E6C32F9B4E6DB6BB1DDA"
- },
- {
- "key_seed": "0ECD554A2A723FE725CFC2705C80CEC856C0DE19FB6BD7538699B3C24DAA0E58",
- "ldt_key": "FC21A6BCBEADABB421C2CD1050D49D6CB3B7CAA2948E08948236624DEB01C84DAFFB364E6FCED0D97A554697EAD8F1F9B10B691240E874D123C6090EF591B14D",
- "hmac_key": "F77F5C04535B91E72F42C2FBB9119D11F725485C89CD00101B54C11620B1D859",
- "adv_salt": "6C04",
- "plaintext": "72D73F9B2B97C231B84767F800F208F40FEE06B86872543908BE2C",
- "ciphertext": "756D7C6D7430162D032730E90CB7C5EF67E512943835BC96511406",
- "metadata_key_hmac": "8DBAC803E7B33983AA84C8B4E46C6166DB7EC8FB9945C42B322FE3EF5293BC25"
- },
- {
- "key_seed": "D7C8847C7E8FEB4DC442983177006DA3175CA0BFCE52F0D985F96031533252C7",
- "ldt_key": "BEE93D5D4B768CEA9B85A7E8CCC16FE5E00DD641CC5B705D87B45460B2D6D5AEC3772808DF95BD3711C3B5820674B30F953FF79F90F5CBC5228412CEEFDFD381",
- "hmac_key": "9FD237BDAC010B287790CFEE3E8B68D398155C7F0949160E0E93AD7A36F647CC",
- "adv_salt": "9A38",
- "plaintext": "8E559E7BF8732B31D60C3EFA73223EAB696FF05FCE0B2B0DC0FC9ECCC374",
- "ciphertext": "165A73C30278CA40D354FCA5B7FA2F59B03C8C210034081C2DDC18FBE930",
- "metadata_key_hmac": "95EFBA62585B0118AAFAF540AD9BB9D6BE0132D5156307BA67B1FFB0BBDC107D"
- },
- {
- "key_seed": "B00C7848F767F1FBB5A0225C372BD51669265000F7EBA2A9D625D067DC1EAD7A",
- "ldt_key": "7EA6F36DB004694034425D297C579A7DCC33D6729B139E77461E65C774A94120FFD58EE9D9CD0044CE0BB288C3B2793323DD7EA112ECAACD788B44E28080D70E",
- "hmac_key": "ECE14011D70AA79E61490480DB5AB1C5ACB53EDE41A50A5A225D6F90E2C74521",
- "adv_salt": "4E1B",
- "plaintext": "BC2DBA155EEDED7C96977A0B0CF5FBBC79",
- "ciphertext": "78C1642FE8C19833B2E7AED931A293B292",
- "metadata_key_hmac": "F7B56B39CB7C6B3F9D3F2AE89EF989E2F664A1C25D2731429CC27B21EA59EA56"
- },
- {
- "key_seed": "EFF15E04EDB3E9CBFD83EAE7F382157FF3530FD7E3F8D8A54A0A363C9C6470FD",
- "ldt_key": "DA2189DCD00721E778F6AB10606D850FAF706A5559ADE0A42325AACCA290C70AB6B33BA9EC9E306EB05ED7C663112D269ECF3826829C1065E81C66ECDF583AB2",
- "hmac_key": "BB5F27D52B36BE2D25C86852447F4DC8C2E2DF177A09C824A06C1AC5B88CABB1",
- "adv_salt": "A192",
- "plaintext": "5E87F5E0390DAA539CB23D30FA108B5E5E",
- "ciphertext": "81B198280231AE878252645A008ABF41E6",
- "metadata_key_hmac": "8E0FCDF5A803ED0A0FE5C9AD1AC804021AB639DA0A9FEB446AC92C574C42C65E"
- },
- {
- "key_seed": "7A5B7C7EEF6FC42ECF811708D4CC50937D1E8E34A0731872300A7A345A401DF4",
- "ldt_key": "8684BDD009C393BB0D75BAE4DFEE01678E0C47E637280DA920A07C2AC22180145DE8B6417635014852252BCEC39541C16B61D7A35626313DD3AE55F700959E0C",
- "hmac_key": "9BE6EF13D2F5DF52362C5BFB12EF09100F8813389F67E52C667C20FEB919EB7B",
- "adv_salt": "A942",
- "plaintext": "F27F913224CD9BC58030F048018DA4B3667B57CD1CC1ECF458A927F5D0",
- "ciphertext": "7B99EB504853A634337AA496326F73DDEF2D3ECB167CF63296978086EB",
- "metadata_key_hmac": "3D3BE659C937DFDB2C6A4F46F9442C598E0D9B40E157AA13DB32173ACF3DB2C7"
- },
- {
- "key_seed": "5553AAD088C78EDE5E514B5E26661460D80D08E01FEF68B405B739563FDE1EB6",
- "ldt_key": "2A5057B7BCFB1B7C0CAA2EA015D4E12FD89265FFF6CE3823646A00C7A08935DF5E5A29840BD122F63F63C18A797B3E9602335DB08359CE05D77F2FB6C57380BC",
- "hmac_key": "75DFEC14AAA30E575AD765878A7C176A6BDBB4161BCF290C9E43C7318BF22995",
- "adv_salt": "EADE",
- "plaintext": "5365B2E71530B9C234A892168628B7DC9B311EEF7C1BB4DA30",
- "ciphertext": "C51ADD62C74475554288701418DD7D452EE98DE6167DE974E9",
- "metadata_key_hmac": "C01B4C26909491F1F5CCE36C1F1C1B2D9D016D0733A03A4665FD8199C77832A3"
- },
- {
- "key_seed": "342998189AAC53997615C11612B54678E8E9473130526C8D5CA96DEB4FD09952",
- "ldt_key": "90D25EE1ECF1583D205C967D9261ABF68992DE0D764F839B146DA4F4D602BA585E41BB6BE6D5B2E9E84B1D55A99D54199DB03F46658C29D7721745F49BC0659E",
- "hmac_key": "8DE8826FA0A83FEB3021CED9328AC6A0C524359315C07DA092A348B75689A693",
- "adv_salt": "978A",
- "plaintext": "57100E74E9354591C38865EE216BD6F484",
- "ciphertext": "AB4AFBD82E5DCEC98D78F2860778ED9F59",
- "metadata_key_hmac": "A796997AFA2C79726C851F15DA52F09018094BFCA62DE9BEF97459B291540D57"
- },
- {
- "key_seed": "9B1AE59DDBE239E528F9F5C55AFDCDB149EF23D969139E7862DC7D218770DEF9",
- "ldt_key": "9304F19DD2FBC4F32A385354B194D7D218CBCF179969BD90D16765ED59C71B6D38D972747455A19D148C6EE16029AF512338AFC484189774FC95951610A78C81",
- "hmac_key": "8DA66E56659443CF2E7B91DAE76CB36FFD42CBBB10ED13B210E86574FE19497A",
- "adv_salt": "CE3D",
- "plaintext": "66F3A9EBB3C43FC6CE838B75129B30A6F85665A4E9029582F91C18AF",
- "ciphertext": "6EEF47363208CD36D82B6602061296A397DA03CD733BDDE5E9DE1F00",
- "metadata_key_hmac": "1DD6B7C062D32E173D8CA2E67F67582961852179ED024C40987B5254D7A50E95"
- },
- {
- "key_seed": "5A0477CBE783AC090752F8394AB04DCDB79D999E1FEED9E5695172A345BC541D",
- "ldt_key": "C6C3F4BDD7B4A036F7953DFBC3ECC22CBB8C55426AB21AFEB6CA45965663482EA97EDFA5A9045D3128726CD276054689A9CFB150C55953DDBE197D52442DB16A",
- "hmac_key": "AB97F7D5A5C3205AB01FF7BDF493E2362974EFFF5A651EEF4F2ECBEEF18A0FC8",
- "adv_salt": "61ED",
- "plaintext": "EE7981B54E1C17379A9E232ADEF0AF0354FC7B49610F7430360385CB",
- "ciphertext": "A6A5C88FE8864D61EEC83F47B2DC37F053BF2E5968DA36EAA7A187B3",
- "metadata_key_hmac": "60193EA52A588B2E96B48771772318274A150485B12E4390A30F603612514DE6"
- },
- {
- "key_seed": "8378C9D73E14B679A3B3321F347D185ADCE9AA1824A1D9C0DA1089B6B663FF53",
- "ldt_key": "F9D2090BB4CBC921E7AB7D7C37D9D988D53DA0562256353002E753E28FE473DDD7327EF546EEC5BC81E32C6F074DC21E9B901BA23A2B1B66CFFA12452669EBBF",
- "hmac_key": "E7099C86A931996822238596F0755FA6F9AD36AB1D79A56A7B1DF9A100ACEE66",
- "adv_salt": "49AA",
- "plaintext": "E7321E12D949C101CA8D7724C1C739068339EA83C6DF7FF23B6722",
- "ciphertext": "DD266DE58B819279AA5B6DF6C815718FFD9F90B3CE1B41CE47FFBF",
- "metadata_key_hmac": "895995674304845A63AD2FEBDB297E92756705A0A4AFBB6D63A8201FA9433419"
- },
- {
- "key_seed": "6519CD0C608E0C26F2BB415F84DB1C06E38040908C1AB1CBA3107BA723803102",
- "ldt_key": "FCCC5250AC180FE5DFBC6367F20AD7D01D9093065264B9BDA4FEE93BD6FEDB4CF975AAA2370E26BC5BB45922DEB7D9F70C1774F3C99663C6C7361338750C93AD",
- "hmac_key": "5B859752B379C6A0F6DCE584EA8D269EE0D05EA427D2273F477938202C21410D",
- "adv_salt": "1BF7",
- "plaintext": "B9B0E3752451B61EE55191B06F132CE2B820E6C2B7E3E6E79EF9381EBAE5E9",
- "ciphertext": "5283C33EB405CE3C446F55009EE7C2B7437278AE93053E4A485802110D90F0",
- "metadata_key_hmac": "1C3B91B68D6D3877942FE09D81FE14B8194E81DF9F5BE5D64DB48E5CC6483AD0"
- },
- {
- "key_seed": "3080ADB8C31C7E86F143516E7AF784F5C8384492484DAE622EF38165F1D616FA",
- "ldt_key": "C315B24FB8D12074330B44B79E5D1A55AB2FCDF5DC657F94C668269EC6A1B438F43CB997F2EA99BBA7BCE882BB1599EEE2186FED20F3B2E9AC060900896D1FB9",
- "hmac_key": "96C5CD3A6F2E1EF2F4E4E3343130D3D6E8DB4E42EF827A9F18EEC1CF3E55D4BD",
- "adv_salt": "1A2F",
- "plaintext": "E6FD8B3CA9C82B8D1D0BFA1442BA8426A821C6AF8498FCDE337A0C190CEDF0",
- "ciphertext": "7431DC4FE965D7FF3F7E24C35B373AD9F0E62151C1C7F659660B3918E00D2F",
- "metadata_key_hmac": "88B0C48D71E99C49B7D4E7DDDAE5055EB9A653335F3A9D0BB11B0654D18C7833"
- },
- {
- "key_seed": "D3328C7913B9871305EE82CB1F2C9041B870A2E13DDE9DB6875301A14053B417",
- "ldt_key": "7DE72172FBEC90BC3B6D1EA3D8337C61CF4507761BB0AC07F65EC0E78F9FF0C5C31873F917146FFF7B0896E051B3BD91B9EE6BBF427D95457E5AE321480740EE",
- "hmac_key": "FB780A0BDF5D9984E087F68F67EA5623ECF76CDDD01329A56DBCACCF26F73E40",
- "adv_salt": "DCC1",
- "plaintext": "A59B5F0D5EAF92089A1730DA4682A3496E54B64CBD9A807EAA3B",
- "ciphertext": "AE664C161DB820537E64F09C548B69C3C092F636E21389307114",
- "metadata_key_hmac": "A2BC9EC43EDC2D499A6880FE4F27625FF49D1A495B849EA708EEA92304229BFC"
- },
- {
- "key_seed": "2803E63904B8A4E5AFEDE903AE77E6962E2E299F5DF01BC6209419873523596F",
- "ldt_key": "CCB93C500CD50E2F6CAB777CDF5394ECDA8EA693714846BBAE0E5E4A1C0E959146330C3E6CE82233768ADADEFBAAE9BE922CE2F5995335308B9D6A522A122FE4",
- "hmac_key": "6175BFC44BA2CCFF262B01E1E20FF8968E53B355BF670DF9D2C22F3174DBFA98",
- "adv_salt": "C73D",
- "plaintext": "9014E2E9C22C6D9E1AF3241E6851B353850E390281F5483171",
- "ciphertext": "A143626231C3DF6F08A1F7C0916F3DB97F7195DFACEB8E9728",
- "metadata_key_hmac": "139205577C16628258160C63520323131D52C4979A308243EF2C6533C3E9ABE7"
- },
- {
- "key_seed": "C3D424CEE12CF6A80292FCC88963264DA1CF1D41F88C7B4CFB7F38A18BEC123C",
- "ldt_key": "EB9ECB3EBFC49B2BF206542BF49583168756650160DD6416FB31BD31BDCA2EF5920E803DB5B07A51637AAAF6CEF151A7A14AFA201C9B5CF56BA645B1D8D19282",
- "hmac_key": "23559CFA05E4ADE5389657DD8096ABDC8A790AF1CEBA0E17EF5A1F8D033FE6E3",
- "adv_salt": "BBF9",
- "plaintext": "B90FC627E9FFF36DB6A5C238504A501F8C247B41A433EBAB",
- "ciphertext": "BCF8E38285A87704A542261EBCC3992C66CE39C52901103C",
- "metadata_key_hmac": "80DA7A5ACB7DBDB8F107925C892D9C09F1E56296675637DDA3601A77764489A8"
- },
- {
- "key_seed": "B459A0BDAE3FABA1A0483CF35E2521751D24409F2216B1C74E5A19650F3A3949",
- "ldt_key": "1C9FB660F68D61A43FDB5E8129C8C37ECF3DD5D0818FFBBC58C6E531C4810F4D49ED5D2143CB52C23328DD20A721EA8079A93CC3396EAA3AD2B70BC441182ACC",
- "hmac_key": "F527F4313DADA66F7A003DF492947D52C0D54EE49FCF5FE48D5F8F5FBE9C1D78",
- "adv_salt": "730A",
- "plaintext": "EE2F0C9FB9B2D4DB8E0F531631FE8BCBFEB927F025",
- "ciphertext": "442EB7DB8F4EA34CE86BD8CA8EA4C65D94E6E19F8D",
- "metadata_key_hmac": "2599F8E42889630E883BBF901E5D531AB15EFBF13426B8913E07031673B7BE07"
- },
- {
- "key_seed": "49C0D2390E790C20FDC10E43CE517F7E3C8D41153C73A579C0EC74FD4C395941",
- "ldt_key": "9BE90C02466954980B34A7D1DBF89EDA5095F2F68E917E0FA69F18FC62E74C25AD79B613F24C870B7CC368790E2877D8CBA2B747BB4F0678D615B58D6D5189E7",
- "hmac_key": "87B2B86C8D1B86B3A4C01F6EACF91621ACA29AE73E4DF48CC7D7712C701CEE40",
- "adv_salt": "EE34",
- "plaintext": "950744D835729C77480148DD09D69EE20B162D8323",
- "ciphertext": "F5955F45D7BDB42C320EC3795D52F2F72CF3B044BB",
- "metadata_key_hmac": "C85280A1BF73031514C82D70CDBEBA53B415724FBEF00A8168745F2237128EAA"
- },
- {
- "key_seed": "0E7BCEFA797736D9F91BDB8293FF51A538D665CA79AF62AF4893EA83A2C600B9",
- "ldt_key": "8D5A795EF8E36C6D7A943F3B171B98D5329796E1C2D535459744E85149D1D81151C19A04C5C38C2132A71F533CFF0DC5DE15F803A1AEF6FE1598534BF2A7B542",
- "hmac_key": "53EB6926B56AE6EA948729B0196039EAD92AD9564A7D1F7FF31B4A4F5CDA35C9",
- "adv_salt": "6A26",
- "plaintext": "3E94D9314FD1E2BD2AC61C7CF03DD3EB5CC516B0679C",
- "ciphertext": "6B6CFE9BB8345ACB4B6C7402EBAB6F10CF9D2C930033",
- "metadata_key_hmac": "9A6F3EA0B48FADCE594AF0351DFD31859F9DE01BBEC53B38A6B4620D86195F73"
- },
- {
- "key_seed": "DC310BF157F0378144A7DEE76F5B95ADF3A7A754540BA7312553D81624AFA1B0",
- "ldt_key": "44345912C50AC5A7C244ED31D7CF8FAB80590E4363AFB307255F0FAA5D40DC8A0E777E3B4BE153232F9E8F80355814933362C60F90A4D33368CB86E1665264AE",
- "hmac_key": "A046F6ABE8E0DE35BDBF9B574E97A70CF0C61D98A731F81B68FA79B497602768",
- "adv_salt": "342A",
- "plaintext": "84195311841AC7F5544E44C7077F7F76E4",
- "ciphertext": "9C3FD5C099447E92B60CADCF012E305008",
- "metadata_key_hmac": "3212463C6B39DAD5EE0581870F9EC642E9D42CA5C70149149437857331152AE2"
- },
- {
- "key_seed": "8B7FAE7704B7EA2C6136FB5D18217490C65900008CE4317A75842613BF3A072D",
- "ldt_key": "EFB0CA7F9009F3A9EC5776847A4DA88A70DBF28D16C6B7A2EC121C0F7F45E88EB238BD2481D21A675F97C0F0876F27FAB5BD5B1B7A69BA7A70F332F19BC3AA37",
- "hmac_key": "821FB7E321CC7F3BE691AE146665D3AEE0BC78EF7230B0F1F6A3A59336C6C439",
- "adv_salt": "C70B",
- "plaintext": "778CEE9F3BA2EDFF226F4726628130293BB4",
- "ciphertext": "5CA6A77F633C09055061928ABCEE07C9FE65",
- "metadata_key_hmac": "8853181CDA041C90AD6ABFD39943FF206EE15D52D49A165968B0EBAE3F1E9949"
- },
- {
- "key_seed": "72ECBD3EC62AD51645F38FE2FCE9417602C5C0F9F0CA738A35C41BCC19EC9C5C",
- "ldt_key": "67DDB32739578926E265C0C58FAE0A0DE3C790760C6DD1FABB8B5F24CD862A26B7AB84AC7847B65787339C444B432EB7525F73F2EB71108AA9F0363885BBD742",
- "hmac_key": "72209D27956478D557A5A75E2F22D76152365FDDCD0608C5B79ABC0232F20856",
- "adv_salt": "762E",
- "plaintext": "247D04D1501578C3A2DF020E3738C224AB093577E2DC11F4EA2E",
- "ciphertext": "4FC96DA6EE8388A22EDEA71A0B6E24B9BFF4E22092B13E02E187",
- "metadata_key_hmac": "FBC931FE290F92097F690A02B11D69424C4325216AF2EA7A65168658FB371A1F"
- },
- {
- "key_seed": "2D6D2DFE7AE6EB7FCD45DC6F56A6CCFAA11F2C8AF5295606C715850F1271A5A3",
- "ldt_key": "F8C3EDFBFD14F23CC84FCE85BF5CDCFF54403F25E936CBD3022E55C00EE27623DA0BDD8FA74BDA3278371073A4E72B54C3774E014A905BC5E98E58F884DF9240",
- "hmac_key": "3985FE8E243BD65DB0AE4AAF3185E705B75AED530C02A20B45306AF640F34B01",
- "adv_salt": "9433",
- "plaintext": "267B1E7491E02C1A2CAAC5AD4B7F322CA63CAAB688",
- "ciphertext": "28190D998D15F1D090EE151710DA6F0C7CEC7891A4",
- "metadata_key_hmac": "B42BE1A6889A7C28348D831673BB02370B54115B7C67A0B5E374ED1E2BE38217"
- },
- {
- "key_seed": "9ED92E9E5DB3B44FB6567FF3C9C3458C4FC3121735035BF8E22E6E5A4D8666A3",
- "ldt_key": "CE3ACFFCE7613342408FA6B3E77B1B87C820DB54D6A01DA651621F98BB4686D85D7DD6DA7D7A1B365D2AF53F35157F87273A4B27047EF7F23B38FE878FAF0012",
- "hmac_key": "D262223CF5C87749958EF430B6E0A3740CB5FEBBA47B0946AADAAD739C344CEE",
- "adv_salt": "9AF3",
- "plaintext": "AFBFDB0819E093AB27853D2BA662D162DDD2C76115D29395BC34CC1D235661",
- "ciphertext": "B702F556B5C400CF72DA68CF031FC048B609EE753549DCD0BBBF3A9870C2C7",
- "metadata_key_hmac": "C775E00854CD584161F3CA8BEEB489C49CC3FCA7EB072C8007989A12F3EF0E6C"
- },
- {
- "key_seed": "29160E56B32F35828CBCB90039754D42E8A95514068C3760F8A63A4DCB32D030",
- "ldt_key": "DFBBA94D4CA6CAC685ED90B8C11EE6BEABB2F508A0C3AF0A9DBA8505A24E9E97B1D5813A79AD5934C1E5030EEF56663A6F98D0E5B2E2F2E1DD9943DE7BC0B021",
- "hmac_key": "1057562971FC6D0A0D2E07333530E41FFE50EBFB48119DB8A5C3F827464C2841",
- "adv_salt": "5EE1",
- "plaintext": "57867C339A963B8A5E271B3E8C3ED9C4D5FF42A9DA58A2",
- "ciphertext": "D7747A26F1AFFF363FD8B27ADB19295DD633084D1303DD",
- "metadata_key_hmac": "7FB95D5FC94C8961A95FB07BE8128524A847EA9353B1F1CB585B38BE60F30137"
- },
- {
- "key_seed": "B07121F9309C6A32A3937D28CB73FC80DDCA48F937CC9819E437A14FEAEE564C",
- "ldt_key": "5BD101F34BA505417DB39696B39705BB2AFA5BEBE4BEADBB0FF26B4244940F2B34C28E8B7E95087751F00D2A72FE044906FE536A07A846EFFD67AA6771C6B81A",
- "hmac_key": "8DFDF658D3BFC4E482FE25C11FD81F3F9B71C20FCAD59CC2053EB3FF23BCA90B",
- "adv_salt": "D433",
- "plaintext": "F46AD7D78292E7AF94603AAD5615B42F8FF117F9CA7AC56C55189BF30ECC",
- "ciphertext": "0BA3E268A0BA62413AE63A2DF4DF4465A3DAB09E7D87FE5FEC79B515FC52",
- "metadata_key_hmac": "91D65198349B8D5AAB4BC20D5C5EB55B8DB1DBBCC8016390078343108DF48CE7"
- },
- {
- "key_seed": "16EB091B388ABBF530F7C3DDE8BE8A4E2F36FD738B0C520B2B8873D5A39D7EFC",
- "ldt_key": "9684092E2C949D1FA7BA03CF5EFA43926743761DEF9200EF0EDEB1DA82945F052D4EB19D262F10B88AB19FD853FBE2A80B14AADD8612CC46F6A95E4EC33CBB08",
- "hmac_key": "7E6C9673B48E9EF9E18DB6F77FAD4A66C564A5981BFDA6481BEC0B941266A879",
- "adv_salt": "836C",
- "plaintext": "A51282B8D1A391F93CED3997D983F0B3397DD22D82F1998D82",
- "ciphertext": "EE7988BFC2E2F00A293CF2BBBE1F3A059AE22C376C68CC070F",
- "metadata_key_hmac": "98E45E977982DE8232DF201C239353A289A3CC74016924AB5DF2BB8AA766391D"
- },
- {
- "key_seed": "593F713B1CEEE1AAD58F05B739FB7D09DC36217D2338EE5A685295F7F084875B",
- "ldt_key": "6E8604E1E78CC0FB19B84913691F26CC1C33199AA539B8FB99496D5038018B57CB67761DB438FD50D7ED186E215E322B536C8BD948F0769FAB910308CC54C5A1",
- "hmac_key": "65DD06E50DC75C0DAA4C3201E0CD845099DA9405F61D4B471EB94812F932E553",
- "adv_salt": "396A",
- "plaintext": "DA236C79191CED8BFDAAF9EF4E4B0BFF4EB5F2ED6A930937D6B573E77EE1",
- "ciphertext": "A52ABB15DA485DC6E1FC850413A875D79D3CB9C8BE1891A5837ADEA54B33",
- "metadata_key_hmac": "C3B795131B2C970F92BA425666FE389CE11ABB52291F69D723E75BDE1D9F5064"
- },
- {
- "key_seed": "C19D74623B265D8D7F07CF5B9F099B76899ABBBA1DB819747909F2190EA25EB5",
- "ldt_key": "797BD489E98DCE10E524AE9E1164A0F68FEAA98B0F4F97CD0C84FD3D2AB2E14CC276F3818CD565298244A13D3A490DF5974B72BBCCE294A2EBD0C1E24C5A010F",
- "hmac_key": "A802F477F587F9D821BC493ECEE500B1D887119F1EBB1886284748D36F84D15A",
- "adv_salt": "676D",
- "plaintext": "D85AD63AEAD575E455BBDD8B2E5A42D18E87A8",
- "ciphertext": "D3BC41EF27122C40B3D7CEB7445BCA3B3ABBBB",
- "metadata_key_hmac": "5D220323813E77391183BDA887549D48BEEBED35111D6893ED003B7863389F68"
- },
- {
- "key_seed": "7BF3623220392AC5B804A005E6DC96A6EC32108FC22EA371325129A3B3C0934D",
- "ldt_key": "484901A37BF4E872385A32AD47652A4289ED23BFBECDF7DFEC7ED6087F57FF5478E7B16323CCEAB9369FE99F43EFF332C1259C8C5375B2B274557007538AB73D",
- "hmac_key": "3CE9A2B879697EED758D331DB9FA887478266041FE76C377C7BBB97C1A2841E3",
- "adv_salt": "7170",
- "plaintext": "570E91C5673CD53E569555B65DA830E78EBD6D7201DAFC94C899E1",
- "ciphertext": "805DAEDCCE7DD993B5C894241FD07A7B6FE0227F8249AED9960D3D",
- "metadata_key_hmac": "D741CDF71C6B87C90934C5C69E50776E9DA12A7046E73AFA8B9DA4E39B6DF366"
- },
- {
- "key_seed": "0B4244B762772BFF2D25B6AB24C11E1CBB862405DA2207F5261FD00D3FB2F41F",
- "ldt_key": "652713E03311A04E642497AD242CFDBD85EB76CCAB1D0514F0424D08CBE5A24C4860B09142548AF9F27F54C060A8A3EC352ADEACF35D92582500104F27A29590",
- "hmac_key": "A6E2A5880FB0A55EB630DEC32097D5489EF19F4CAEA7B63E8FE2F6020FB454BA",
- "adv_salt": "9DA7",
- "plaintext": "EA154B7C6378AC3F7F73B081DD747B98B23C17352EB1ACD548CE78F124463A",
- "ciphertext": "79F1A617F91E96AF2BEFD5E94524EBE8CE632E385926E69AEF006C46C26155",
- "metadata_key_hmac": "E5BA00E38C5A01E28EAC7E969824D76A6F34D8ED7F9EA8E20C9ACDD3FC4EC3D5"
- },
- {
- "key_seed": "F8E333AF5E871B1F0854914E14544C9F2697CE374383911C73C8FBAD8C3BE5EE",
- "ldt_key": "A38E2E39FA60B949F1297FC3527926963441FE5A5004F0AB90BED92D229488C9EBC12C27B55ABBF8D81E10C2318677A81B1490749AC3FA23034395B8897BBF82",
- "hmac_key": "F9BCBA55316A4DCCE7B2410E2886C5BC8E53DB210FC170BC53297A1823F78CAC",
- "adv_salt": "D4B6",
- "plaintext": "C749BA7F2512B6A7259269C1610770ACB14751298FF767957055",
- "ciphertext": "FB01C67DA9E157F9291E28D33815DAC5C3AE12E7BA2FB0C5320E",
- "metadata_key_hmac": "0C05F69D3E64ECA65B789FFB4AEA169E967C25C55B389D743A83737F66EEDCBC"
- },
- {
- "key_seed": "E5F9C362D4FD10E0DAC2A4BE4BA4EAFBBC5C4AFB3CA9820A70CC498B0734D4F8",
- "ldt_key": "E3A1F5E8028DCDB21CF5E3D200BA4D728A36602E195B282B12FA5340EB4811EA336C6FBB531C28405B9994B9F55616C8C70AE3E9F5B0F2AE9C3FF5844BBC411A",
- "hmac_key": "3D5980A8A1F905A098834D4C1E65DE9D3B341A95C10FF34B2AFA0C34555FC920",
- "adv_salt": "34D0",
- "plaintext": "394B4B158FCE09D1C525D965DE57A7A2707E",
- "ciphertext": "66F01992CB72AEB6A4AF3AD8B29D752933FD",
- "metadata_key_hmac": "02CDE2667F28741DA9CF4DD2A315AA088631012B142BC93B562A1E5F93DB6519"
- },
- {
- "key_seed": "BFB715370C8047D29D04F0FB33145DE2D623E3D47CD0C939225FDD20E5180BC4",
- "ldt_key": "A93BB3594B683FB42863E88C23EEDBE0624DE923B1B946639EBF81288408CDD9CB25F9296C73885CB316E3EACDAC80666325AF8FC79386B8BD0BD392B02BC62D",
- "hmac_key": "8CD11B7D362BC3134AFA622E973B831640BABB28AA7F2552A0C8DBD399348C43",
- "adv_salt": "FAB1",
- "plaintext": "BB4D8B51DE4FDF3AA54992151E6F528D",
- "ciphertext": "67948062505D79C2BE4245F2A500935C",
- "metadata_key_hmac": "6DA14EA7C97FAD70D6A274A279BBBF5784A40EC9226B2CEBFFE2F2F780C57607"
- },
- {
- "key_seed": "33BDB4C8FF7F5E4EA8FF024D8B50CA23BDC925F469D196C7A06F572E3B1D5B67",
- "ldt_key": "291ADC21691BAD3974A8B7B9898D0D2A0B9EF76E96B5B46B762D447C3D42151DEDFF7A1E34F3E0E3309F0D377CD12AD2537ED00D951DF8D99F969FE04979D55E",
- "hmac_key": "906C6E4C7DDDCB37D49B7989FDC034B00C858CEFC6E8CBD95A2E42F2315691FD",
- "adv_salt": "EA16",
- "plaintext": "072287B39625D9FB3C6251B5E4F87B4E473307BFC66C4AF57AA4DBBEFB0F32",
- "ciphertext": "6AE99A8C1F11C308918297820F1E98ACDFA7369339553A95B2CD44C5C6E039",
- "metadata_key_hmac": "41507F00272A4395C00B1F1F95A3BC62F2DB8B397D508D287BE1546472BC997E"
- },
- {
- "key_seed": "1DE7BE2135369F3554E58C0AEC11B28EB1082E47E5373BD6C33E27BEC88441F5",
- "ldt_key": "8DCA3D017E1AF638901A7EC4F3ABAEAB5042AD712821052B7C9482C0D132C189BD8DB3CBD84F4683E948E5B0ED5A57354012C1C1B2BABD63CA2A1740382F3926",
- "hmac_key": "83D9696758DBA51296E7F7CAF9A883C5DD29C2E228D2639B8DA4293AE5166ECE",
- "adv_salt": "D9A0",
- "plaintext": "56B94B01FB85F26DA07AC9871EC0435CB0BD2EF592AD8AB2",
- "ciphertext": "D00C10110C4CF9E10294C41BAD9E4B2F656B92D437E6715D",
- "metadata_key_hmac": "78DDE51A9D2B4FCF329ACACCE9996D4151B9450843A5B6FD234EC7FBAF76F15D"
- },
- {
- "key_seed": "8D30198B0BE682C467BDE246C0B5D17F269F5A5CAA1BE03CC91CE53DB89F2065",
- "ldt_key": "9CE88CE3DE410005309A2F8050E65331D2DC2F43ED63025975B1B5E11CA00EFCA4E800B8454B578CFA426721666883FC49C1D828B34C9FC4D359F2ABB8B0816F",
- "hmac_key": "8AC75FB664DE0D535B1649598A0933E07B15CC23E0CF20EC3DB58C67F2BA20ED",
- "adv_salt": "2383",
- "plaintext": "3AFA3B57F287BC133C50753860727341F8C76304",
- "ciphertext": "5EB125210C7F4A434AA65F37061A1D17EAA3E3E5",
- "metadata_key_hmac": "7B387B56051C2A1C0E7DEA987B3BD41179BE3594C94D3B2C16B54B8214E6B3E4"
- },
- {
- "key_seed": "938B3FD1182C66E7F3BD1C57C79FF3FC689ADC74582EFF313BB088C7D35E29F1",
- "ldt_key": "553D293651004B38DC2DDBF30B4C3EB88BB2B52BDAF2A1D16E9A59197B41CC2F828D60448D693CDE6F269806F1F0D7E6926BD7E3E7256A0A54B440E1F7E6E765",
- "hmac_key": "0A6D801912A13D138DE7888B57D5EA2A6B09264EEEFDBD2D0F90A4D838CDD98B",
- "adv_salt": "289D",
- "plaintext": "395E83ADEB08B0B351943B05214342EEFF8C58A9A460FC86",
- "ciphertext": "B28472A8655F6ACA528FD326BF78032749159C02E67EEB7B",
- "metadata_key_hmac": "B54FF0C1F02E244D283D30518DD29F39628C7261A33E4EC73E23D45BBA271637"
- },
- {
- "key_seed": "45A3FB6F4926BB2CD90E9A2219AF199CE6E22757951F3C534B97993049439BBA",
- "ldt_key": "D5FE7EBE602FE69EE6C4CE161216B379C2E1541E1AEA42AC7180D0CEF246717E550A1CF18D2F9F36EF68450CECD38F77F8BD7E98851BE7F4CFE89CAC8343456F",
- "hmac_key": "AB03BCE03F01CD10ABE61101BD662EB2052781BEC469A8797983D11A026621D9",
- "adv_salt": "6268",
- "plaintext": "FB8071BF75C87DE11ACB1A66B98CC640B67A6A6BE6059A0B5C264F",
- "ciphertext": "F35F1F36EBCE7A4564D5E1025EFF20EC05EBB683DE5A4F0E066C43",
- "metadata_key_hmac": "11C4918F0BBF662778B74461EA270416F54B0936168E5F068BD8BA605257D934"
- },
- {
- "key_seed": "BC3C628222F52DAA7DF389745DFCEF6C9FE1A4348B0260259044D83252229F89",
- "ldt_key": "1EDB931C068100750CC1A2003C8EAA1B395DD61F0DAC1A19A6D2C5CA743366E082D392A50B5D338816FD9EA5D683ADD2EB8052BF360607D164ACFBC380A56F24",
- "hmac_key": "8AF7E33DD9A1539042CCE8236479A8C209D24CDEC6FA46D8602497092339F3B0",
- "adv_salt": "96E3",
- "plaintext": "12E5FF905D0EB084A17EE6203F7A041EC8DC5D65E5EE442E84EB11FCDFAB",
- "ciphertext": "297D54356D7DC53C6B52185E92E810B4BE02919BF84C7C60810007660216",
- "metadata_key_hmac": "E4C26C3280B1198BA1BFB3AAD1E93D39B45B38DA0E14649EA32F2FD1B6E3575A"
- },
- {
- "key_seed": "FE59E191E1F37C4895B5CB9A6A2BAAF4D3759A4806D41B04710CA1B02F134BAF",
- "ldt_key": "D510EB1353CC86205D7B400536641509974D44F6B90D2F9FF7F4969DA495EBD2C27AD260017AD1D5963ADD51FA7344BA1B6387DB8B33BEF7DB773853EF45222D",
- "hmac_key": "E02610EA8A327590E20764D2F4EE4D84584459AA674235D01DCFF39AEACB1BB3",
- "adv_salt": "30FF",
- "plaintext": "04C28324AEF8E9F7ECDCBE90DA9F44B3C421F663C13D5708DC57",
- "ciphertext": "6F3CC44F51BA5A13EBACBBCE7F01952EFBEA29B861F5FF9ED4C4",
- "metadata_key_hmac": "561E4B55FDB4D3776F1F4FB2EB285CBCB059EADE18CEBF26A0E432DF712CB8E0"
- },
- {
- "key_seed": "F1BCE3E694D3E705D4A2A19F75CF82695E21ECD91A46B299DC84E2CF107882F2",
- "ldt_key": "CEB2A23ED176C85C2FF7BE55FAB82496F7F164CBFE4C7F71718CACAA83B14820290F98F20BBD6B935C3DB03B85C5B86F464D309B171AE489A265E78A04D92E1D",
- "hmac_key": "F1558C37EFDE507E43211379F127B673EA7F071A82F371B0B2D2A21D7DB02B6F",
- "adv_salt": "8972",
- "plaintext": "2C1751CCCF9D86EE6C90876C8242956A5CD7E1",
- "ciphertext": "E09B67166DBA26E96852011D794F7E25A8827A",
- "metadata_key_hmac": "FEFBE1CF5264D0065B12B300E33D61B6AFE1B1FA45BECDD0EBDA3B8599CF2F41"
- },
- {
- "key_seed": "EC22763A7622C4DB44CF765844E3F4760B331F56B9E1FA18F503252D2A83E4CF",
- "ldt_key": "00EFD0A14327AB1565E25738ADD19A69ABFB7F198A5F9D4BC36321955FB1AFABD9D542AF0A1D434A714B984FB3DF5ACA6FF55C866D277398D76D7646AD6F60A0",
- "hmac_key": "BDE86FC86156010C74FC6E28B73FE6381FC7D6BEE356ED3CF7A0CAF1D6D4AD8E",
- "adv_salt": "3818",
- "plaintext": "D8741C307DCB11972F993E89824E3CF4",
- "ciphertext": "30AB89B502BEEB1E117AF6F150AE422D",
- "metadata_key_hmac": "17A5E8E4F289549AA9C4C168FFC52B4334D4BA5642DA922D72192872BD29E54A"
- },
- {
- "key_seed": "6BFB5D9559236AA523B36B188FDB1AE6B5E38B73D40DCA7A5C3E0054E78C56A2",
- "ldt_key": "A603FAEE39356225A060A05067944537F0259259E3ACAC6A1CA7D07AF1956128F1CB92D2F8A8DCD03F94665C685B8567A4BCA039BB3DEB3CF6550F9932A9FD90",
- "hmac_key": "9CAEE450D7E3384524E699BA71BF89E80D5C249F4E096FA6340075E146AC50FD",
- "adv_salt": "FFD9",
- "plaintext": "75D5BB5845EA6038750E5BAD00FEFE436CB36B7779E4ED882EDF2B",
- "ciphertext": "BB4E1D807A49C43B70D7F44DAD18B34F53686A8398B5BE42945B2E",
- "metadata_key_hmac": "07B6D518CC5092EC628DCDFE72372741C431E01E333E6E51A1E6EDE6135030CD"
- },
- {
- "key_seed": "2F96CE3443E163E296F7E8788536B253445D253C0DE5D259B6FA79E6514037D3",
- "ldt_key": "7BE961F2FBB8EC6CF4F4BC3B08E3235584E359DB19B38664675946F0D6395CEA72B0784F33FF429D440319CD3A3C019C84857DA0323B2AD556758A84714BAB91",
- "hmac_key": "1F12DBEFEF1940B31C3C8DD86A1AA321FCC017D291AE4EE7329CE5D1C77B0118",
- "adv_salt": "1A9A",
- "plaintext": "C9B01829CBD1D71BD08704C914737721FD5A68",
- "ciphertext": "325FD73EA2805026A763A2B38E2E73CD0A1A4A",
- "metadata_key_hmac": "6823AB7F3B05C2DC43FEFD1B0841914CB66039FC4DD4378D699EEFC8BC2F987E"
- },
- {
- "key_seed": "4A88D683C9602276811F22E8A1B1A386C49D18438A8774EB68F9E1F47DD60A4F",
- "ldt_key": "B85C7730669DBAE4E813FA0D1D317DCAD6B3F44BDFE79ADABE5C3B1EBFA21DC7E1E100F88EFEFF99DFFB221095ACFC73808F223416C1998A3602D7A7D22F8C1B",
- "hmac_key": "92288B7DF8AA76139D235A58014F5328A37A508CA793AD52259CA5134F964078",
- "adv_salt": "956C",
- "plaintext": "2E22E38D3352091630AF0212FF2E8E3B3BDA4D73980DCE18519C935CF3F648",
- "ciphertext": "DAE85D75F2E9EB829A0048A28A21F08AECF692E4A7D2C664681FFE7B625C77",
- "metadata_key_hmac": "4FFA58C296880D6C3D3307D3EE0E1642CD6B398EDD36A44B68FAC60CA9F8A307"
- },
- {
- "key_seed": "107C2FBD9699F8A8D5CBFB34A595B168F01C6D84E4184D267B2A557190CBF3A1",
- "ldt_key": "D07881A7CA0E220CC94CA8C13DF3942CBB7531C669730C4025BE564BE06D9400D01BF6EE08FB0E08F9398A8ED88045BED02A606D5CF51491A4E30724F4CCBAFE",
- "hmac_key": "88FD72F6574A0CFEA7DB62714C03865768526A226F9A0349A9D94B692166CEF5",
- "adv_salt": "C970",
- "plaintext": "86DB18B1DEE5FCF1C62B6EB89418D31D0E8CABF8BB59DB42A78672BEAD",
- "ciphertext": "B10F0285EB9FA1FEA581A130BEF5266F3574BFD8411D90762847C37595",
- "metadata_key_hmac": "9BCA0211FB695146728CA6F0B1ABD243527EC9F577F4CB66838677C89FBC9F09"
- },
- {
- "key_seed": "B669795FC94A32E2CCEBE3E8CD7636A53F37C7AF7E8F03811E5C50E507B1CEF0",
- "ldt_key": "E7BDC44FFAC5A842DB4BBE84955B3EA95F7652C7FE388C206021E592A4E63ECB09B56A790261AF1B3F727160A2A8CA96CCE9CE751B8CB97B570DEE4E8B904846",
- "hmac_key": "86278DD1C9BECAE43AC378AF37689466A281686A75D0793705856E39132A38F5",
- "adv_salt": "AC11",
- "plaintext": "32FF82B1BCBF2C8D2DA1986FFA6C909A0EB4DF17",
- "ciphertext": "507E2FF5FC4C017695228EF12ED482429B5F4483",
- "metadata_key_hmac": "4F1F2CB7BD8638842DAC9277DD0F498874425EC26BBF113D7D499B078846096E"
- },
- {
- "key_seed": "60DBFE2A1B840B7B1F04DD9980885D8537ACC25B2FA210F5B494A81FE54EE81C",
- "ldt_key": "C8C8DD7BBF2430EA3EF2F01C3259A4E6D89068D5468CBCD063485DEFD6A7011D330F461BBEC8750E02FD1C297D344C80F22F41898C9910CABDFE8B2DDD9A5A47",
- "hmac_key": "9F980970B706235E2969A181D14FD7BD1EFB44BA981B597497B2686C9CD8A16D",
- "adv_salt": "2385",
- "plaintext": "6AD53BD901C67A9478E365A42943E2CA2DC6A41B9CBBC0B44715829965B7",
- "ciphertext": "46BF32DA2A259572DBD41BEEC104ADB7DBFADEC7B0B8B0EBBFA2455A6AF0",
- "metadata_key_hmac": "94976AF3312558D902FC77B7807386F1D163270522A285C14FB106C2A890EECA"
- },
- {
- "key_seed": "9653C6869668736549125E0F043308C09C33B1D8680932CF879A651D250D92EE",
- "ldt_key": "EA277E82879A79A2D8A0F9750EB54C8743C75E3A1F9CADB6BE90E91DBD3621127295198F9A40EAC2F8949DA1F2BC1AF15C91F5BC64BFBAAA58FAC71A602DED2D",
- "hmac_key": "4E25E4C1DBC0C4AB3C35AF2CB71F2F49B48A4E797E982A69DD008BCC63288A22",
- "adv_salt": "42EB",
- "plaintext": "7FC211D923E0FDEEF1A133CC4C8A54D755FEC60086122E18A2C4FC6C",
- "ciphertext": "56830E1D523544F48C60A79F7DC2658D4711A69BA1021C49801F2F8B",
- "metadata_key_hmac": "CB43679649B990619458219EF3BBC96FF58D01AC04453D84CA55111A1FBE51A9"
- },
- {
- "key_seed": "B660620A749423B87AB51CE3A9DBF52D3A49C4B4E9704CC491420F3C02673D84",
- "ldt_key": "1C45A44A706B7CA5144FEDEB205E763EF6FA2A3D7C8C962EB4449458F3CE84D074CCFB6D64CADA87ED3D2B1BDDB915B04AE9A70E0732424A520AD2F2912EC148",
- "hmac_key": "B19D5B3A46DA48B4A9C5BCF1017AA86BDA4D89AF45789DB90B3599DC72FE443C",
- "adv_salt": "F778",
- "plaintext": "AB7AE9B7E6A1D1C256E5E4F44E88FD638C8D4391",
- "ciphertext": "36892DA56C467D9E87CD96BCCA33C17D1AC36715",
- "metadata_key_hmac": "42036409DACE84B0FF0AB021E649191A92F0B383421F48F77A86D229FF722279"
- },
- {
- "key_seed": "58F6B511B4E669AEDF3701BCE8BC36F84BC6128280EDBA2889C9A20D482522D7",
- "ldt_key": "83BA91BEEDB08613F78D4AAF4B285B0F8568BCD26F0AF5DB966F4D940EC674F9A77A22B3107EFB1609F8B558458C70D78193709AA204D5E62016F200B9B63E6F",
- "hmac_key": "04041ED30C1FF71C51727DF8A6929257FC8A4E8D4BAE0E67B45153F598115579",
- "adv_salt": "F166",
- "plaintext": "11055806D37FDEE2634CAF81B6772788",
- "ciphertext": "3154AB15C5FEF46C91504C32F561E925",
- "metadata_key_hmac": "340A5DE98A25C36590E6C9FD70E7F33FE29C00DCCDC875F596E3870A3F7C1D6A"
- },
- {
- "key_seed": "6E37788FB48A39C046E2026A6433E1D223BC90F1D4BEEDFFCED9F266B6032906",
- "ldt_key": "D522AAB7AC074824F08F5967F322522447F794188A439BDF931CE1EB13ED3A3AECC757A68E34B9010B5B86F4E10D60355298570F71C9E714A8150CF167156CBC",
- "hmac_key": "5F74717B967AD6B134546677FA20C3DC05EBAFB9748A3B7E2369663B11DC2AB8",
- "adv_salt": "9DC9",
- "plaintext": "916091AC15EC4E55EBD5BC22C613A49B659EB19A5242211F500FB2F67E",
- "ciphertext": "29796CE84C4E554E97ABB5A0085772D067AE41C2AE256C894CF9ECE691",
- "metadata_key_hmac": "7B20F19C37450647BFD03C7F3B1EDEFA93E8CC0CFFEFF346BFACB12B67B58D76"
- },
- {
- "key_seed": "CD8A564B17E9FAD9A3BF046EB56359528BFAA8FE18A6C0E1A9451846D94E515E",
- "ldt_key": "5F4D152E81F2E076137B43C6E66FA2F2ED4ADFFBC12488212DDC81436AFD3E77BD57D0AF7FB3D12FD989D31CF74D983F1C5EF02D998B2BFAB6699B94964DCD42",
- "hmac_key": "FE433641EAE1BA1B4B834AB8D3F0C34ED903A48F566439A0F4D0AD0D5A54BDAB",
- "adv_salt": "F138",
- "plaintext": "2817177DEAC6DD1D7C30FB23CC2100FA734BE5D0423B5A53C63ACFFFD0382D",
- "ciphertext": "5773C62B9EB57C23D724706D93F7EFD8D8ABE7FAB86591760CDB93D9303882",
- "metadata_key_hmac": "68A929D5927F49AF93CED5072E52A66E99A5A2E51B371A7E1781AA6DF44D6B03"
- },
- {
- "key_seed": "AC1D4BBBB9C0922D3C6FA64E52BE3ABEC411DE0DA32AA066D2D5A60F6D803A0F",
- "ldt_key": "78A2FE1A5CEC40E33E35A872FEC2902EA5B2E3C99C32FEF0500B6FBF082FCE661D2C52F2499CC3888FF63065AF79C3508DAFB7C0F911C746B95B5AAE403B6054",
- "hmac_key": "82E9718FA9261F37D7D6729B4C05AE1A046182EF3B5B3D430387E6801C805E82",
- "adv_salt": "296C",
- "plaintext": "3A717F2F0568518635B3E2851BCA6D151752F1607F02588E8E1F77",
- "ciphertext": "E05DB0E55C5FA750E7A2481A44E1080F9D49855523FEC5F5C01D35",
- "metadata_key_hmac": "E395EB74DDECA7699C112CAA848EE2124558843F44C5E1C413121A47B563334B"
- },
- {
- "key_seed": "8D531389F16845D838FB65633C53BEABB14EDFD3F46B4D59866EE13E63879D2D",
- "ldt_key": "F1B16139D909BD76F86B2AEFBFDF035C0EF7D5B5C2980DAFC4824A1479D908F8CECA968A14AF6C659E47C6A10C3AF22A3CCF092E7929BF764158105A25874F6F",
- "hmac_key": "DEBBED4EF9C2FDC50AC25E977FC3250ED187CC8AD5F067DC01635B23A9E93FB4",
- "adv_salt": "FFDF",
- "plaintext": "38430F14331A2D48355A1C9F56A1AB0BA7A27EA132A7071E09",
- "ciphertext": "C3F9DB294E6A735FBE527B0C79FBA8ABECB00B31CC7A67B2A7",
- "metadata_key_hmac": "95DD1FB3D3A595FD72C041B3F79074C3214BAAC2C18E483CFC4206D64AC4B64D"
- },
- {
- "key_seed": "08C051A56A4026807F185AB8B1F9D6D988B275FEEA0E407136108C707158964A",
- "ldt_key": "84FE0436136F9934A17ED5660A270E6F54B4E24F0969ACC5B84C6078DA720BC103C84EDA3B93C466EDCCFEF85B5D4C462F12423125B05324856CD6C784E086B9",
- "hmac_key": "72BF447F5C5DA8D513080157E7676EE756ECACF346ACDF9A1D561DA359CFDEE8",
- "adv_salt": "84F7",
- "plaintext": "AA39C2A62A38B2B0340CFBB3A5C4E988750DDD",
- "ciphertext": "49C146946B7A2D0A8A71B5E171BCB36429256E",
- "metadata_key_hmac": "FE8DA88D4358BD47959B23268B7770C1322E1FF1E6E8E1DFEE90ACE685260E57"
- },
- {
- "key_seed": "83F48A68E7947230E032BBC32641F52278B85CA39CDBDECCCCB0F4BFE7F0E77C",
- "ldt_key": "2A2012F1AFB7EA08CFA3B81E6DEABB492850F7E411F4B7FF0588CBC94B2E0D47C10A267B846996AECC466E81AB9A26509D1BB8139688CAC1FB7DFE269B92A2E5",
- "hmac_key": "AAC0D02AB54DA3F59EE5165D6267BFFBFA441B4C038F2FACBC8C47D09E7B89C6",
- "adv_salt": "59E9",
- "plaintext": "1E1099C949E8833EC2EEF7FB9114C51F48FE",
- "ciphertext": "F8E229DEC34641ED97C53AC106B9D4C10C16",
- "metadata_key_hmac": "6A14F39AF418A9E90CB72E5134B9E192204D6BD4A014A73EE4B3561D69F9996C"
- },
- {
- "key_seed": "25ABF61989684166CBBF871E353B74F53292B922D3812BC0FDB23D13CDC3C280",
- "ldt_key": "311EC9F125A3987903450884C49DE77E27EA7A476F95128CBEB2D2EEA928D081BC8C7EF80B3CBF62C3227F6E56450DDD2DEB355CADD8884B96A0F72C874B0500",
- "hmac_key": "23989F83F9D09F23D2FB15EE7C52362D23616C1266CB3397612CE7C11B6F5E54",
- "adv_salt": "6094",
- "plaintext": "3A9CA922DD4CCC25367907942D630BF0C3E7",
- "ciphertext": "3BCB1D893925FC1087E97ED294D3346791E2",
- "metadata_key_hmac": "348BBAD5CDF30488980D723F5FF74221168432D8A7D6A068D4AAF6CE30B92EF4"
- },
- {
- "key_seed": "7E870AEE530314D6A7567BDC977EFD10A88FE5C8FBB4BB36B930B3AC44165DAA",
- "ldt_key": "C2494B6FD9DF81656BB26A24012A63606365F9A8520AEE8B83855556AA16FC6B7AD913EB71F5CD6EB2D50BC7FCA736AC397FC5086985AACEA81C81AF87BBA281",
- "hmac_key": "E2099534726B7394D79012E3184611784E190FF77A1D1BE5725EDCFC869ACF6A",
- "adv_salt": "AF79",
- "plaintext": "66932F49484D0F989AD55599DC2169EE311FE20E38B9A16C6346",
- "ciphertext": "01358398248454C6B1AEA844D6CAC1758D2ECE788AF8455055F8",
- "metadata_key_hmac": "61B14A3C1DE1BD60BA060735FA8A36EDEAFD8602B1A0832CC29EC3D2945B9BD8"
- },
- {
- "key_seed": "C7BDCE87471D280868EFAD6BE11D01784A17DF2E21B2C42F40E645ED53515A04",
- "ldt_key": "BE67CF76B8DA9C1CA61F483E516640060C7E6AA6123BB96EACA540EBFCE809DBE7121C7B2D7A8F836C9FF8E937EFDBDFF949BA8D1D379F8D503C428AD80B62EB",
- "hmac_key": "20868F5516F580BC39A7DF3411D4BD749CDDBB4C8BB5E1012E94021BFE89464A",
- "adv_salt": "7DFE",
- "plaintext": "69CEAAC45F821278B72E282177275B8E9944FD6754D437E0F3D4",
- "ciphertext": "00A52D33E34C2DDBC1CF8D60957EA3E4A8A2F1B9EC96DD74A5C2",
- "metadata_key_hmac": "8D1F86151A921843DB626DAD5A8A6025DF69817DAD2464BE3B6BE20A978B9339"
- },
- {
- "key_seed": "E486CC16E8200FA38014D822284E1DFD6FC672DD76AA30A15402A12868C456DA",
- "ldt_key": "5FA855391F68B0B58C3E5BEC9887E39A3D7C0EC29CCAFB7647A5A91CEA73803F3419CCA956A4D03343FD65F36EF520FB888590ED2B6B2EC1A16B30870431C5E8",
- "hmac_key": "DAF4E7480BA7C1DDBC5322BC6B7814B2191114E963DDEA50B16A831451CEDC6E",
- "adv_salt": "0E60",
- "plaintext": "1C3FE453F872B66095CD3CB88BB6FAA77D59AF",
- "ciphertext": "ED89FB6E6FAA21974A4A403E7E40EF92ED5F74",
- "metadata_key_hmac": "31463EE4DB1DA018FC809A8B6BB6A36F151219C237F8ED8C10E0460DB666355A"
- },
- {
- "key_seed": "9AF41893CDF256D94F514EAA0BA39FB189D8AD01205AE4110A398C0066C9A7E3",
- "ldt_key": "9FC81F3E1159A25C0ADF56BDD16307F2AEC45BF5FB4B10A8B4E31BE30FAA6915C33BAA7CB538427B63CF4831EF87969931B153381E734E66160218C55C53E2F3",
- "hmac_key": "55E88B5DE0531B144F06E1CC8625DE501997BB6B4B77E31A5136EEBD18ECEC3A",
- "adv_salt": "CC47",
- "plaintext": "7C0A44ECB3BDC4E0BDD02FB438F4BAF2C449ADE8A93930",
- "ciphertext": "DFA844BEBAA59BEE88E6518DADDF665B28953EA74DFF50",
- "metadata_key_hmac": "453356617CBA9A6A7C211B496BD7C12D0439E906160AD93988242B85A20C5C6C"
- },
- {
- "key_seed": "982013E258D8D4CA7E3F932B3B4EC4D9D0BB4F59E773BA088C5DB261993DFB64",
- "ldt_key": "B812087CC7F516F63D744E5316BA2214BF3314D394997A95B334F364AB3268792807C57EB1BC6944EAA19A3D168BDB15A2E9DB6FFB026DE8A58AB61211A806F8",
- "hmac_key": "3D0188404BDAB7F999076EA9321A4EFC39A55002DEE7C622AEA1E8E1F7BD0115",
- "adv_salt": "19F2",
- "plaintext": "4D21D4A45BD54B82F33ADA83DDFDCFE38AD3",
- "ciphertext": "5AB2669B6B5F3CDE17B853DD9CBF9D8E486D",
- "metadata_key_hmac": "171BCF753AEBA62AA690554ACCCAC49DE5C7C4CC4BF95F1A6639D5E7054BAC6C"
- },
- {
- "key_seed": "4831215C060EC4416486BD0D06BBF8AE1C87CBED2C686FAF78FC143BD4854A8D",
- "ldt_key": "FB4A94B958A53E8E81232A2288C9B50ABDBDDB405BB9FB27FF61BB0127280557F4462FC907ED63021DA56E5048D3209E495A8BA674423522E1DDF8EFD2992074",
- "hmac_key": "C17765625DC10B9915731342DD4574429C87DD3C6EFD5022C9C4C34595966C96",
- "adv_salt": "37C1",
- "plaintext": "30A6E08285A9DFF8D5732E12986438F3A543D88751",
- "ciphertext": "5BEAED03F32825CA05C6AEEDCFE8650E80F98ECCE5",
- "metadata_key_hmac": "F363C143814A9C3ED6236DA6F712E936C32A9E2C6D773F2D033311B7EF9E39F9"
- },
- {
- "key_seed": "BF7F333ED03DACAB5398B5E68607FBA1B84060860A11AC859686499D199108F1",
- "ldt_key": "76A979188272D1A0DFFA3E5F4C6D6BA6ED03259AC3AD0548CA673FC6758627E5276461C18FCB19871A7E8754FD248CC68107F73D788A08783B8C1A335B742121",
- "hmac_key": "57B20A2325977E08DA51B649FA12B5E15043951DC941BBCAFDB114F544F54092",
- "adv_salt": "0BB3",
- "plaintext": "F903ACD0008F8DF45ABF1A73BC406622ACA5AD99EFE76AABD2CD608E08EC",
- "ciphertext": "8C9F277FC17D2D44FF96D9D961685DEFC16ABFBA5D13FB75C8ABA0FD3155",
- "metadata_key_hmac": "24D2D21C385EBB9097D0812C0A184E7B01A27490DBC30F95E1BFCE7D7C00FA6F"
- },
- {
- "key_seed": "AF8CFDE1ED1EB5A6819878AD5899D5AFBD9F0DEDD87931A919CE4C562216014B",
- "ldt_key": "958930672D654C4591C793752A25E8EE363249AF86488B8031725527E9CFD878C6931B44A219B1B7DD7DCF53C8529E024D89F4BCD5086C009DFB79E130F4BB18",
- "hmac_key": "77C306B7F177F9158CAD803A671871CA22C2C1CEA9A37B71FE79794E1D1176D9",
- "adv_salt": "AC72",
- "plaintext": "8537018520FACCFCBEF1AB47A942E1B0C8A3D0",
- "ciphertext": "0325C312805B932A9316EB5701099E54FE47D4",
- "metadata_key_hmac": "60148175D0618530DECABD4799ACC71F171B6D354691E97D1F75BD6DB8F6D475"
- },
- {
- "key_seed": "3F92B8CD12296A93D972407F6874A9B0B275FCA1D7128774716B9B44AF0D93C9",
- "ldt_key": "C082B62526B0354A6EE8C73D673EC64172C43072B43D47CD43E78874ABB5FE678771D852E847B07029AEF65C61C10CE82A927C70EE9FA5D00BA91711CF36091F",
- "hmac_key": "53310D7BC015532A1EBAC43E1B0F0897D85547A8A6086807FE027F5928607FC8",
- "adv_salt": "649E",
- "plaintext": "2CB8AEDA871C03D1BA51DC69745046C12C650EE6A4B22D12CE78FB",
- "ciphertext": "59FC27853BB2E2E4CBA1FC875189DC73CA1D33B3A2DE23A8EEBBE7",
- "metadata_key_hmac": "110111ECAFEA433A6FE6B9C48B51F84301B286E7723E8F42ACE24067C3669FB0"
- },
- {
- "key_seed": "A6950325CCEA52FF5CE7452355FBD77AC51821A2C0CC6659258590C8D92ADA53",
- "ldt_key": "64D45B4CEA1B625AD2966C1670E4BDF0C7205F2A959A6DBE009AD340DE5627D41700E342BD0C1DA21F46656F570ED1230DF80E84A365391167160E2860B53CEF",
- "hmac_key": "A6146EE57806226CF7B8B108C52229AFD8CFDE8ED4432E32C9BCD2513BB90A55",
- "adv_salt": "B6DD",
- "plaintext": "FA35612EDB49394BA17595F222FBC2754E0A419A7AC0C7688CBD9E9B3C767F",
- "ciphertext": "C9B7F258E25073D5F5405D170036933D949838E7308C3BCBCFE6DB6E8F67DD",
- "metadata_key_hmac": "A0D791952CDE3A40D7FF5621A00DBC148776B7837E97C588699B5B319504A516"
- },
- {
- "key_seed": "617DE18D574E856674621B463EAC834EA2CA1DDD33B62EDE6673EAC03F48DB01",
- "ldt_key": "7A824C14B59C7B7684BE92648CE9DBBE893226A3260E00A3445D9EE1F8ED795C53C013DEACCB49D55A02CE84A317F5F22DDB5DA33BF2D716C0B7D9F6853F82BC",
- "hmac_key": "285B5A229E5F0699D14801BEA4BC6165778054C8E693A7436F235ADA01041BCC",
- "adv_salt": "CAE1",
- "plaintext": "4029B5BDE7AFB3C50B047A5F601BC25DAD35C329A36D",
- "ciphertext": "3DE0E528CBF25CA1AB98C6BA250EBF8CE00D06F0FC61",
- "metadata_key_hmac": "BE3E3849E1C920A170CF6168559FB9B197B38109858F3EFCB68279C21C9D2685"
- },
- {
- "key_seed": "8E2B98943C6C16A32693C58A1161AB7BBAFAF00CFEA1097B5806A317ED13A813",
- "ldt_key": "8FC56B5C11558E6B652F8DBF0041C2CF4593B81E155DA4CCBE49609AC0E09486AF6610FE6E5ACBF0936D8D0EC534E96AB10CF4775F92B5053BF2FB9D7F5EE7C2",
- "hmac_key": "044BBD941C6E6C0EEFF8A0C555E93473D19F6B4898AF5A9BF70FABF23F93475F",
- "adv_salt": "8CE7",
- "plaintext": "B92509CC62B827A735FA5775218564BB",
- "ciphertext": "67854E6A4DEDBC3ADD4EA4A0E853D0B1",
- "metadata_key_hmac": "E560F853FC05FF7EE8EBC9269CE0B49C0491FD73E29322D575227615064044DB"
- },
- {
- "key_seed": "36AEB76E3B45B994361A35371FAD52DC728A90FEA7963A9408FC6ACF70F54193",
- "ldt_key": "D30E4FB3D1E5401DF4F4EBFADA78A25DEEAE3C19DC2B3ED09415A2FFB48A0B6DB39F23462FF87E29C6D9AEF763B3E32B99C620AA8E8D756EC80B404E557082FC",
- "hmac_key": "F3305A1FEBD6801AB41206A92142CF84F2B327276095A94006375B2B1DA6E224",
- "adv_salt": "9B1A",
- "plaintext": "C26F86704676F7B25CB64001686B251CB9",
- "ciphertext": "907CA3B495D61F3826956618D65A622B0F",
- "metadata_key_hmac": "19A23CA6F848521C7DE11588E1765466B0F2851262770322D5B9B83AC582A242"
- },
- {
- "key_seed": "389075E418B6A1C619DB81C3A25F768F8C33BB8E5DFF09955A87B6A32B715B35",
- "ldt_key": "44E79BCDEB998525CC68C15C0D379C913C99E6880B15B80EED54B820ACBCF6041B3B7DF4270FD0441CEC05ACDABDE9A073EE324F4E9E1CA26D65F46CC379535B",
- "hmac_key": "9CCB4BA78D70D25D9053213A0E1748C994CA38CE5A42F7A903BE6350B4828B0E",
- "adv_salt": "B201",
- "plaintext": "51B6999CE384C3C3A6E8407FA2FA3781B54A3F3EF6C61F47C7925CAF",
- "ciphertext": "703417211EA1B58674D06DD811327227337A59C751AD4AAFF37A3380",
- "metadata_key_hmac": "A1445E361BDC3C7A737B3BEAC511C6D0FD9782B6BC0EF2254CA77C1489F0F3D5"
- },
- {
- "key_seed": "F671C931D88D78D9CC31118092D123E86926D025E8B3695926B7D0876B6DDDA7",
- "ldt_key": "18669548D3BC8236C019C944B6EFB8B60BA8AF3DD1F8F7FED3151AAFE4D56070EE99AF0685CAFA72EA60761C65E753885D77A889B0290F554875B37F47652D34",
- "hmac_key": "D05B047B4F212CCC5A392378611522722A7B062E65B188F6B3B44E6CE391B477",
- "adv_salt": "B347",
- "plaintext": "D5B5C84033C34A70EB023395C045D649BDFD79775B7E350F021594",
- "ciphertext": "F0DAA688C904859AB1DBAF8B3AA833BC13F9A6056BE9B937414DB6",
- "metadata_key_hmac": "932CF0BC690A307BB5F02FCC388EA94DE58441BB8B132D16815B522BFBFEFC0F"
- },
- {
- "key_seed": "DB1C9AC98E541C8CC9C72E6C7F66238D343A91A6A3A33EF2F7546AB4B8B7107A",
- "ldt_key": "DD98D681661D81489C2BD6129E6D7F667305F808D3275B66342D6A47FDE7473A60ABE1666C177383C4C45CCF0A6823E79F269F8B491E8DFE2D0306046C3A0848",
- "hmac_key": "1FE0C9FB0DCEE2D1B95644C4B2E4F88C9F72611AD9794A5F18F05BD726E103FC",
- "adv_salt": "E878",
- "plaintext": "3FFC81E390AEACBB5966561B6726C6949D1E11367F870513DB",
- "ciphertext": "F9FC49595EFF1AB575F7682526CD036824C06AE6402880695B",
- "metadata_key_hmac": "7E52B09D92F882B675288104C25E17DD8070CFD78CAC299BAB4A903367FBD4CF"
- },
- {
- "key_seed": "6E76B182593F7B2DD6FA658E31CF5DAB5F5DDDE891A4585B6372FE6B3FEB57FC",
- "ldt_key": "01DEBFAE8E615BE20A0C581A3C68A03205FF0E79D148E1402D5D5FD1948A7D26FC5AEC1DD9F0BE409204BDB9915EDC01F738882F4662322A4905112C1B2520A8",
- "hmac_key": "EEB2093740E790CF3A0231BC06701F97BD9FB3F1F4EFA5E4F4E7771C8A97C7DC",
- "adv_salt": "56E4",
- "plaintext": "FDDA577E1B84979DB007BC7A3FA1A6D2E68539149C88204FB063",
- "ciphertext": "905DA74F695F60AC01DB7B83AAFA2108CACDBEBB534ECFFAEB8A",
- "metadata_key_hmac": "1EC6EC98754BADAFFD56BA5684A1C6066589BCEF6E3E8B073DBA049E6974F293"
- },
- {
- "key_seed": "06633F915364EE7DA5032267B80CDD9673C1307E0629BFB5172EC4BC1890128D",
- "ldt_key": "1E807E019B269BDE087F7394D73647C1082FFEAFDA1ACEE060E24FB80862F3117E2A64E93549A98668776A2F0A693065AC03818F26833D7D8DB5AFB14CCD5D6D",
- "hmac_key": "8A4F56C0A75EFF12CF5035BB934D29D26F69DF10368A7ECBF6E930EE42254397",
- "adv_salt": "9BEE",
- "plaintext": "C24669C503C8F725AF5002AE03FE3FABA3CA1328B902FDB174",
- "ciphertext": "FFC10045E9999158B05869CB81391D213C0BD179771D42DB9C",
- "metadata_key_hmac": "85BDFA0A3290DF03B08DA1DC895399D4261EFC63CEB3B9535D001C1E8D9745D5"
- },
- {
- "key_seed": "FDABB479A313776E95440648BC65B72394CD844601074628D4AF98A9FE796A10",
- "ldt_key": "EF6D7D9DBF5853F602AB40088C44EC77BD960B19B89977610D09EFC6966BBC8AD1D3D01C529D9AFD9C6A098F876544C4EA3075ACA78FE48E7F440BB62AEAFA5E",
- "hmac_key": "D64C0D5308A0464CAC76D3D4E3DCC2189653ED32C0406283368822A76D7DD8A1",
- "adv_salt": "60E5",
- "plaintext": "082669393BA15D7929EACB4AEC506627DFBD37",
- "ciphertext": "C5E74FD9A5616AA14D03AE2C6CBB236AE58644",
- "metadata_key_hmac": "93547F72D6E299FA2FA0DD443D94418F3DED56ECE4D9413C5426794621778057"
- },
- {
- "key_seed": "A3707E6C0C7947ED67E1FD8E47CE9B43A0ABE539E5ACA5DD056A9D940C612E2F",
- "ldt_key": "884D6D9CE55DC275244B39489B386352C4ACB6C73202F274E8B1E68D1614CFBD61916E72C93B5369EE0669E5DC15110C4DF8C3BC6E74F715C0549D26112F5974",
- "hmac_key": "E3144304EA455E4CAFB2B0B92FEE7FBC5A7063B80D7881B08C405573487733D6",
- "adv_salt": "3594",
- "plaintext": "3DC2614ABEC46AD9245BDFEDF3E90AB5DCDD54BDA57D591AE41B075C81",
- "ciphertext": "0966FDF24C0774A04FDF4295AC2FD6085CDBB83A2FF13265071A57A914",
- "metadata_key_hmac": "270AC4FCEB6A68B2AF9E453355E472F3A826F86880E7376B9428B8A6568E5CA6"
- },
- {
- "key_seed": "9FDDB21FF1B2D5EE2B1C70280757C1AC4B0AFAE49C7451D1BCDFA2830F272910",
- "ldt_key": "0F8101DC92E00FA2903774FE987214ECEA4D16B036F23CD2A5344979983D6F2BB84898CC466A2A65D05F336CC8F7252EC48965E4D67CEBBCFBB04B21B48ED143",
- "hmac_key": "066010A645379580554905B125B611A2EF57780C27C6F3628A2DC88AD132D9F5",
- "adv_salt": "7BA0",
- "plaintext": "82A976792715216048435D7A5E28263FD2B458C407449014",
- "ciphertext": "071D6F551533BD63BA43D8BDAD6E530F7F377FAADA3EAE4A",
- "metadata_key_hmac": "DBFFCEB7CD3896814DC58E17A466434A2BC791046C0C4E01B1E5EDA3D000F8D2"
- },
- {
- "key_seed": "AB4D2463F367B5BA727CBBC13FA9C72AB706F201BC64DE192DE1BFDBC219B7BE",
- "ldt_key": "E16D3C6A029ABB4B7D5163A6A25B0ACB78E7971B5F08C3051D3006474D509743F88ED8833551E255DF3968F7F24E7C51124E2E87CA67F73AA4872C3880ABC470",
- "hmac_key": "D826BB876AFE81B61F6BA5C3393F6A4DCF973D2D926280A1573008218983E8D0",
- "adv_salt": "95A6",
- "plaintext": "607FB840E8B048F4D4625FA0E5D743F3602EE464D43BBE14BEBFADACE2B7",
- "ciphertext": "5B784C3857B316026480CD50FE8C5B3655CDF92217A2DCFB66786BFADA50",
- "metadata_key_hmac": "E85C2D425E9227FA22516AC78E9517D29C48EF1CA281C1C07BFBE0BAA415CC2F"
- },
- {
- "key_seed": "8D20F9697E22B91CF93AA7C352B089D9A3297354589CE1A53B9B40F879C72C48",
- "ldt_key": "D2854282B9675BAD6E79BB1D65FF19A6B2E0B7308FBBFB0C5781F4735D6C707C5514EFE445EA6854690BED816FE34C1B47B38372CD36849CADD1764A0BD24ABD",
- "hmac_key": "CFD97E20543B0E9AD692E7381B1B42C774C70B91BDF39072706CB97ABEB6C5D6",
- "adv_salt": "CD47",
- "plaintext": "1F2F14E5043E6A530CB820C2758B9D448B74227A97BD2E0BEA934564",
- "ciphertext": "580D1F5A222A20031D2D3F44B763EB815DBAEFBDB8C457B323F6D933",
- "metadata_key_hmac": "A44A6C8830FD0FF0485B590EF0475B1F5448C5DBF7E13F7C20F68B13C8F64697"
- },
- {
- "key_seed": "F6B71D5239CD5AAA18564AA774D7B2628877D82BC68D6E0A13E624EB9451F2E1",
- "ldt_key": "60E1C3F87F89B8EDBC2B45FC64378D01F4449302B84F7BF7FCA2A3012BB72FB3792CF55EB840B8843A84908586411B3324AD7BAF42E6C2EC40BE1F4F412B98F2",
- "hmac_key": "C081F2666BC84CD686727A7431AD0CEE91179AFB22FB828624C52D1E0789E521",
- "adv_salt": "48EC",
- "plaintext": "1813610387059591A293B9D98FB30D9D0D",
- "ciphertext": "FB831DF209BEC56D426A05EE003A2FF34F",
- "metadata_key_hmac": "9FB36CF49F3B795E939B77A007BAF7FA991B98C8DE1B7926F809E2642C92B2A0"
- },
- {
- "key_seed": "10309B258D701F43599041C06DB1F3CE87D4A9B4CEC36414EE0D7CE255F58442",
- "ldt_key": "63B92505655987A94A7E3BB6A36FC9141D94BEF3072A77D414CF0B05A080C1981C4FD35BACDE42DBBD6EEF20ADD063721404C921CBD13AB29AF6C614DF559130",
- "hmac_key": "8C62F3E01B2D15A9BA355AAC65A1A687FAF4ED164C824AEEE528FEDAD2D15814",
- "adv_salt": "4A5E",
- "plaintext": "A70A217C659E6F0B650842272DFD5406380D2092058B758A0DB610E89256E2",
- "ciphertext": "D0215D41075D0B1B0E4633FA7329268E0D8F0C4712EE8C3123D102D680B3AF",
- "metadata_key_hmac": "D71636B40DCD5A88674C1289064092F56EBA10FF80262C0D4060D75F5D03C9AC"
- },
- {
- "key_seed": "319AA8669DE0409951869BDD8E187364B5E573FF4E9D74615651A3888E5B56B6",
- "ldt_key": "69E63159756AE45791F9759493EC1671E7CF5945829E5D41EDC375220960F6B46E14D1BCCB5FCCEA476441811492F0E70492574047B8554D0FD5EDB134E42410",
- "hmac_key": "5564DF9C3C2B6096B6A38F2AF78A1A663D9941D67732D36D172ADEF63B69654F",
- "adv_salt": "28E3",
- "plaintext": "39F0F9DCADB181522561E84FC46D34E3FCFE00BC12BFAF",
- "ciphertext": "7B0F9B1191859FCA946F4721427C7BCADBFB5C0A2D23E4",
- "metadata_key_hmac": "4F8802A57F2E9F82F7FE647CC1E30890E8881C7EBB2C8986BD87944013E78CC5"
- },
- {
- "key_seed": "17F3FA6C10FF6A77579CCD13E27AAC691AF8FB37D6CA844EC670BBD3DB03D155",
- "ldt_key": "CDCA67E54E546D5C8B8AF84782568C9DF533597BCB808102CD1F2D62C6689AFEC7D3893D52BAA826C7B263936635F89495BA755F899A434554B10604398A954A",
- "hmac_key": "97030022D81816F751E0FCB0EE9DD05839647DB0750C938EEAF5AED0AA3FB00A",
- "adv_salt": "242F",
- "plaintext": "8074DA96478FC4E9ECD3F59BFE13B0EC573D",
- "ciphertext": "329F0E00D0F2212614C251CA8A8C50EECDC1",
- "metadata_key_hmac": "C8F96DEE6E11AEFC53199F00FCA91E314CC1EA713DE70F05A775671C12C36A9C"
- },
- {
- "key_seed": "964C27CAA6BF2F825E41EA1F620E71F758E1D36FDF38512F5DB0BDC52AC3736B",
- "ldt_key": "D3D8A93A8922B4274ED6A725F5669AEC307F523B0F6DBC778002559512E9CEE4883F8F30A87083D8F060F1745D6E4810E576C45ACC4D01DF0CC4DDED984C8713",
- "hmac_key": "DABCD3EB3BA36EB49A3DF8FD227CC3E85180DF2896B19F12ACC33D073E293516",
- "adv_salt": "B068",
- "plaintext": "AEA44E41A42514CC1D6FAC97E781A9C407E1565F484FD077FE47",
- "ciphertext": "75A0B45E8DC44D1861000EE619F8C14E3F412CEDD553231F5177",
- "metadata_key_hmac": "295ADA83D819E4525AAF23E04BD2A6DA0B13E1B77661F95CD005CB9561C004B9"
- },
- {
- "key_seed": "4131694084A0F5262C980FE2906317562C10192185D04D1B75C26C22E686BF7C",
- "ldt_key": "C4C6D1438EC865142134800A830C8A9282BA65D23E02BB3DE2AAEC36CB0D4B7615C1E0A959D70646FE9870F2900FCC56CF2AAD47E49318CF11097A4DA7193AAF",
- "hmac_key": "F9AB08C53D16EB0F1276D256864F7062F688AD79C476BF320911444567B7C0CD",
- "adv_salt": "884D",
- "plaintext": "E842B40BB94678DEB414D41B60FF6056EC62598A",
- "ciphertext": "B90D4049D479B7413A7F197C72B26F31606A6744",
- "metadata_key_hmac": "AC26DB08DACCB7C09831E60A0D35D32992A3F87C736FD68D287776476E83EB6A"
- },
- {
- "key_seed": "67221C5A236C00EA542ACBC5F8B5E1A80B26D0DD3D0322F811165E58C312156C",
- "ldt_key": "38F913FA317282391AFA810437BE8416AC2E3046F7A156D36E857D4C016F68F0D89A1F0162A3A36238EF920648033322ECCFF6F5535FBD7E9A673E3CA17F2D38",
- "hmac_key": "45813BD36DD6911DDE03AD1C7897302F9D289731D15CC7A96A15C23ECB1CDA53",
- "adv_salt": "B19E",
- "plaintext": "1C5AA1067AA3B115EEA5D3E3E84BA2B11FEC946EA2A3000DA92CF9",
- "ciphertext": "089C8CB3869212FD06AC69C53EC3AA1BE6F05418FBABEE91A25095",
- "metadata_key_hmac": "3CA1371FF09C3ED2863D8CDD8DB242D8BF7DA729A9AA397AA41E13BF5F1C9110"
- },
- {
- "key_seed": "12F66691E13976E6EFFA1052C7CCD589063B3E3958489DEBF28C0B978F7AEADB",
- "ldt_key": "BE49ED6D0CE4F218AA43FDBEDE9DF1DF61F4029ED04B47715B35EF39AF58A0C2D53952DB7D5D382F2ED481B3D1AF2650C17E03E0D360394D4730BFFD18CB9CBE",
- "hmac_key": "D70E3A2C91CA7BCFE12F6E399849D798E06822088351038C8AFCA2B9C88C4184",
- "adv_salt": "D093",
- "plaintext": "DACFD4AB31F83481E90BE4A24D5D1DA8AE9AFF",
- "ciphertext": "36411E0DCF60BE64F20AE1B3CE78D04FA1BC33",
- "metadata_key_hmac": "89D101967A03B09679F10FA8180F0B0C93FB4C304DC5B43052EF416BA712C245"
- },
- {
- "key_seed": "14360985FA56AEEA01295504B697CCE71CA97F320AECF67CCCA057B3E6B8E1CF",
- "ldt_key": "6A9161F3DAF50D1852B6D076B015C07469A92ED8A098AF98360D7D651CB3763262ABCE1F23308102CBF72F358D15C2E36388004BEB177D93DC804F835DD165E6",
- "hmac_key": "B1DA99E46F5C4802DC600729025BE877DB66BDB0C2CED86C42B96FA89949EB5F",
- "adv_salt": "E3FE",
- "plaintext": "522C385C5BE019169734BC78060CB9BBAF",
- "ciphertext": "69C9DCC4CD2AC58FE60463C786268385FF",
- "metadata_key_hmac": "49F80DDAA5E01DB556F9C675558B5733DB710B94FC545537F9400904406C87A9"
- },
- {
- "key_seed": "5CAAFC9531517CA3FADF7937D4E3BAC96A3B927EC1DD30E44E55F7F781FF6675",
- "ldt_key": "081F4D3B01082263E3C72AA40A02979FE308D2D46BB182FAA58790654E7D72AEE16054400EA773530D92A2195A037DBCF47D48E59B636C530BCFF99BA72F2157",
- "hmac_key": "056363C59E47FB4D4D9CF0D7BE8796696A2B91070DFEA7D7FE197B63F0F623AD",
- "adv_salt": "456C",
- "plaintext": "ADFEDE24989BE8C725A2DE6A6EFC62EFBCE7C155",
- "ciphertext": "F7E6DC4F7449E2C77D62AE1EACA091C8B2A0B41E",
- "metadata_key_hmac": "C3516A1F01D8126FFD22918F85B97E7BAE27E511BE13AE1BB248F93497E09649"
- },
- {
- "key_seed": "0861E13FDE5F610055D2FE92F147C7792EED119EC6787B375F91246E583F46FF",
- "ldt_key": "6C5711C97FC4B4E2565C9186DD0D01E91F9661BD92C408EB7048C658CAE9E32FDE306E62123C4708D340FD7C6FBCDB35613854457BAF42F9B72317325D0E99AE",
- "hmac_key": "F35750F1B6C786CCFBDC8314B46E4393DB5D8D52A799340FE8D4C74A74CAEB3E",
- "adv_salt": "61F4",
- "plaintext": "25A29E046F7178A54B52CE7AE9FC5C5D6D4D",
- "ciphertext": "722940807F6E2311D4BE22263489A4197672",
- "metadata_key_hmac": "E9282C0B3FEB515298D39CE65680CE0CB1874D01378122C658705682A6B9E2E4"
- },
- {
- "key_seed": "824F5BB7A6DEEC43DC784F1C0D2BF162FB9ECF77A8FA0B942030AED0AB41CC3D",
- "ldt_key": "18733F13E708B6216C5F3826FEA2A82772B93CD8E2E40B620082DA32683318B26A6D41740CB11D2E7665F7439D4D7FEEF4B4BA31E547F5A917BD48872FDE198C",
- "hmac_key": "D5B67686860DA34EDE5A5F1FE0A7999FBCDEC0A7E7F4A3CCA7E480F65DB75976",
- "adv_salt": "80FB",
- "plaintext": "18D3BB1FEFACF5318DAF518BCD53F679B5F90CA3D245745687A31A316EAD63",
- "ciphertext": "DFC2B0933B9FF52BEF254683FE1EE7D4B7248C8573C6267CD0BF44D193D47D",
- "metadata_key_hmac": "407CCA730FB95A64283777A363CA3B43AF9478CEAA52BAC4907FCA3B783B460F"
- },
- {
- "key_seed": "361238F7C3CC6B4CE9612E38AC7B139208DD3AAA50E39AF703D68D83A2C2887A",
- "ldt_key": "FD5B076CE5A0B6C5DC5F5EF0C2C7F23685ADBD429504B24ED906D0ECC4B1A6DAB4382532086FE35C9B7378B03D3B69C7DF7F29C9822D9050D3B8F40F0D98D3DD",
- "hmac_key": "B8EB344B03FEB7A27A30854515A7CF4DC42FBB2057023321E0A0E1DFB5199449",
- "adv_salt": "8012",
- "plaintext": "E12A66BD01BC858B59D808EFFFCE87B6FF2DF3712B41A11A9BA323",
- "ciphertext": "2F50633541704D77A97363688D071395AB687B26AD282CE39CEEEF",
- "metadata_key_hmac": "7DA0CF023BE8C09B06A086C99850D691F832F4B868874D87BA74F50E0ED3457A"
- },
- {
- "key_seed": "A104A99A4AB90E10ACEFFCE0D51828D25C06EC0966E9FFD9EFE51962AA26C739",
- "ldt_key": "A91E76856009A8EDC71E653E4F4A9BC0BB78EC5E429DECA5CA7A073B09FF40633D03487022876EAA6E757F39BDE654BA386612470F4CA01AD9F47A137A190DBC",
- "hmac_key": "E4500584AC08831C48B62C58988F3BEA6FC8D03C4DB4E4B7C17D77C54DB63114",
- "adv_salt": "1579",
- "plaintext": "8E6054C4B53E03581B9B1714BD22593762B165048E54C0",
- "ciphertext": "7A48138BA8B2562153E039E2B45E29570F7311A073681C",
- "metadata_key_hmac": "403CEB92D349AB8A4CA0A6C8C96760232FBA04C8401F10BE308F1ED364542ABC"
- },
- {
- "key_seed": "493BBFAA9C6957F17A93E4097DE5097DD63E3EF6BCD1125CC358F9A6B6E1DA14",
- "ldt_key": "D21A883029B60B08FFC5D4EEC08ED47EA86578EB50D6812B1928F9FAD1BB2FEF253426A1F7D84913166F76ACF82CF6576555E1CB42D976910B6F92C165A48791",
- "hmac_key": "8060C30A4D7DC672626461653788B56B73C2F8C035FD061FDC7817F3523390F9",
- "adv_salt": "A1BA",
- "plaintext": "3E99E52496E838A70A5B57E7DF237E58DF4557E3",
- "ciphertext": "77798A6827527FC66970CCEBD643A08E3CAC090E",
- "metadata_key_hmac": "1735F7C2BE88BE734F77043D1F1B613A84824CE21FE0A4CCF1E71550E0654841"
- },
- {
- "key_seed": "A1A1BC939762245C70223C8CE227B61F3DFD89992E8464F22D3DBE0D498887A0",
- "ldt_key": "3A7E084A470EB974216E6180A31E5E8980D9FB5FEE342AABBF41B5F8D6A6525B279A0D5EF8BEA8C315C5B8C4605DF4D69F679EB5419C8E6C99DC85AF6AC67876",
- "hmac_key": "9CB48820D7E8D680E256C48A7C7A021DEDF1B7F02B7A9094EDC911639250F8CD",
- "adv_salt": "98E6",
- "plaintext": "73A7B437A17454C8BF34A1FB582E45A8162E6A36C788565E7948A3B6BF",
- "ciphertext": "8BC2F1EF3CB36AD65CDAD1B35388413375807E65AC2416CC68D20A8574",
- "metadata_key_hmac": "13164D584E2A4F86A3E3AE2F0DBAACAC9C4164311EBCA4EBC583B63E172E5E4D"
- },
- {
- "key_seed": "121B7BEFFAD0D37500C1C822E374996E019EFF17838FCEA37D9C58AD30136BC4",
- "ldt_key": "5A656392D62FF8F0381F14A16D6441C68B5EDBEC3B119B59FCF464C12CF27606110A296B837420F8570357D3EFE269321B72D75D45C344E10B4DB2C8E248EA2E",
- "hmac_key": "B000E9A48241937E4559949A02B8FA78FD46F4190F4297814305CF1A0BD720F6",
- "adv_salt": "9759",
- "plaintext": "5247E5AEB960892446421DB1015BBDAB6E2392D88E",
- "ciphertext": "D110708EFD5FE1C0CC82A34E980923A02AAB7103F1",
- "metadata_key_hmac": "52133F6FC1BBD9AEA4805C3BCC76666A03D23EF58A5E3BE81D6A6BF4EDAA2FA8"
- },
- {
- "key_seed": "3283BA6E329F70ACF8ABD7C63A2FC7ACDC80EBC0E1737BDC65A6B5B5EF5D86E1",
- "ldt_key": "DEB59C6003F26311905F0CAD108A9087A736828956EB2F928EF0FB92402C02F5EA94589A0607DFDBB392B26FE9029C1E11AF5E40B799B72397B76A09825CAEB9",
- "hmac_key": "A3F0B2459D0B7B8DA6F3961E927D82352ACF411C7EE14AAC215385EC091276E0",
- "adv_salt": "61DF",
- "plaintext": "628F6FD1578E761FD5AD0AC525371CAC5B41E72677E8EDD97745E46369",
- "ciphertext": "05A924C5247E2CC787B704FBC6966449611CA9E5D61FF3A7BF7867F26E",
- "metadata_key_hmac": "B31D61D1CEE354952A519E19E92DAAE3ABFCB3320F74672C19C5736CD280A63D"
- },
- {
- "key_seed": "EF919FA12B5B15BFC62D5586AE1ED5323DF4470782AC548362F9C62181D1C9EF",
- "ldt_key": "53BAB9765840DA3CAEBFFD5422146BE1D566D9698920757B1B5378F93447DF2F1F5BAB7E2BEA7A97718F4F1D323141D5E3EB3D1682CB6737EFEE711C9E353DC2",
- "hmac_key": "BCA9DA4053E80799C743DE5408422E28F990582BAE83F81FD7CACD9814B5D749",
- "adv_salt": "2AAE",
- "plaintext": "3C67FF1DEB70CED949A6D210A5D979CFD3227299F03E385E4F415CED374F",
- "ciphertext": "C8D8E5BD8F0D49762C35A8D4259C64C35D5C0733CD6B370D9DECAB955EE2",
- "metadata_key_hmac": "89F1F8BB8859DC5956FE742C2855EEF0EB95F57C174A80B1499547EEE43E587C"
- },
- {
- "key_seed": "B0526E489787BD01FF7664E3F8C219A71C3DDA7B3DE7AA4509E6A3B01508D16A",
- "ldt_key": "9C9A9D6844FA9678C2F839A339E038CF6DB0A1E028239D67BFDB23FBE84042CA7E1FC8DDBF19B06515CEA2DB2437699CF1F8CFD6C45E896317BEF67F916A8519",
- "hmac_key": "0E67540AB6F91B30E6A41BBBF26A406213AE98C1A247242D0113EA3701A3530E",
- "adv_salt": "373F",
- "plaintext": "0D5EB90F9B5B2EC2647F11762D58571E426A4852",
- "ciphertext": "37C284E4194ADBD968FFDF4E966B01B9ACEDFF8B",
- "metadata_key_hmac": "07EFB90AC463F9193894306983A81E8EEA260D451B9F572EF03DA6CB5A50D94F"
- },
- {
- "key_seed": "BF0546F7590534B3821388F8F5961F0554C5138FE4C6D0FB185BB2AB01F7D215",
- "ldt_key": "50B0D627DA5633BCD173D0BB243B4CAAABA8F8ED9319719E78FE32F3319311829472C2E5B4B951D7E2EC7F60ECB29A191955A062B07CC7DF0E7D7CC27C478A31",
- "hmac_key": "3D87AAB29C200A92B4DB66640ED7EC91C44E7A1C79D8201EFDB4E11036572566",
- "adv_salt": "5DD4",
- "plaintext": "1118063B217817AA0FE146259D46CE916808710589C01D21EFEE9B3D",
- "ciphertext": "8F714851FA0EFE27F18257F518E67FEA494AF899C2843FB485F1A301",
- "metadata_key_hmac": "4C279037AEE50554B7C88A6A418415D14471E5D667D66682621B3C5F2C959979"
- },
- {
- "key_seed": "5B05A47AB82F86E8E555BA28C93A2B5BD3919EC88B8FE13DBC3E000B11BDBC7A",
- "ldt_key": "1C4EB7C214F4673DA1D789A054A96081F0D52C064128204C5F39294CF95BF89B42F1D537AC992F23BF40B3BEC22FD2D757FE8B6ECB3888D2A1D171F9B2A688F3",
- "hmac_key": "32A5D4ACA2FDE2F18544A0DE369B489F36451E75A1BF54EE2E30982D0EF63A07",
- "adv_salt": "F8F0",
- "plaintext": "DF3730EF735DFF609AEABB5880EE44FA1860ECFB971C6B24",
- "ciphertext": "BCF079AC32C7FFF6C2C1D8F54CAB35EB6B4DAD8C9ECC7DE0",
- "metadata_key_hmac": "0588473D41C7197589AFC3EAF61FB7C02C7EA8FBF25CB7AB1241DD2E78F8B145"
- },
- {
- "key_seed": "016A954E67167DD3C6EEDF2201F07C51A95DB91868753CF2FC4AD3BE0EB58CEA",
- "ldt_key": "6D269972E508187094ED221F529A9B6C923BFEE2F35912BBFD3C0E1E9A97F71766A2309603CD63CCB85DD369A30A88BE54D3372100860ACE92014F5194A32341",
- "hmac_key": "CFBB2DA33EF9F573C5094A572C408719148B7CF31A2CF927F682E36F025670D5",
- "adv_salt": "18EF",
- "plaintext": "3C000A877C960594EE99C3F5D8AB04FB5A56CCCB3A0B7640",
- "ciphertext": "C7AF1071460C8C732160254E1DEF4766500C37EE246AD71E",
- "metadata_key_hmac": "F01F98FCDA25180AB59437E5508422B04498A00F987A5DF890DFF83342CB16E6"
- },
- {
- "key_seed": "1D45C25E8C05DF39422A8470B062E3D3602750C31BC987576FFFE8F416F6BE2B",
- "ldt_key": "470FB25C112AD1E5D5A7C23B028A83A53FD3C0A49C94DC9FEA62A6C8A6B44487352A3084E9E321A92D21FF6B5CDB5BCEE8D20C3B342F1EB79F7ECDBFEF5953FB",
- "hmac_key": "66D362DC79BE14FCA6A867D0F57F511097E09A520D2D4661F2AED055429B3D4A",
- "adv_salt": "02B9",
- "plaintext": "70FE775E7053C4500E1E09546871E8C56C83D4088855C1E2BCF79179",
- "ciphertext": "61FAA929A050FD83C356FE82EDC6B256445BE6AAD4DC59AF79C3B778",
- "metadata_key_hmac": "19138BB4447855BCB6F5CAEF83590BD64D3CCA580139DC49E642D924860517F7"
- },
- {
- "key_seed": "4079E48E0C54A9DCBAA6AE5D3D5E1F637BBE715645070F5EC8C6223C099FA200",
- "ldt_key": "D1F346CDF8D5BB69C38905FA3063D32C9638D2A68CFA2D6A0FFF2A58F860490DA2C251C147423A8F2F4FCE252985EF27B730E637F5C680935938EAB954AB9CE7",
- "hmac_key": "C735DF5B94B8FA5B5A2ADA614220F92C5CF8E0FCA99CB3A4D750E1ED2A039291",
- "adv_salt": "A397",
- "plaintext": "A72410DD92A65CCC4888931049EC0468E015970E",
- "ciphertext": "009257F0EC78B65A8B72E25E0E3215A0831C3623",
- "metadata_key_hmac": "7565AF05C99D2EAFCEA91CB916D423FCED6C8162D41304CCDE1968FE408D6BE0"
- },
- {
- "key_seed": "88A424FD954EBE8DC69E9E30567CE77BB1B53E1E41A50DC4656C69A15F0850C5",
- "ldt_key": "4B5BEF639496BFF747FBA58EBC073BEDC5D039F46A521DD2511478751242A90C1C830647CE0892DABD501E1E7BB4A710E795822C6BB20EA2536F0381810BE55E",
- "hmac_key": "C6D6ED6C2334032ECF3A7EC2CCCB6561D3C7B537069F036BCB97E07D4479B41D",
- "adv_salt": "315D",
- "plaintext": "BBF8E1F2B005730BC7674EA7D1DFF3AFF1C5E4",
- "ciphertext": "48B50ADB7E937959BAA183739D0A89F4A69355",
- "metadata_key_hmac": "A2C6011E155A45EFDF6138F038042164AE016E498A143283691D79C5BE32DBD6"
- },
- {
- "key_seed": "863275E1E0DEFF0D0FD958E6DC5A3761E147270C8C8F7CAB31A03D4616F58B89",
- "ldt_key": "35D4491ACF0D60D7163D9353A2CD150085CDE38B613BE14774CB0BD21D4B1A7424D3A2E9BBE5E7386E471BF0BA9BB952E3AE23A7073AC2C639B73A885E0AF543",
- "hmac_key": "E1443390930FE359DE459A8D1DA38B2991D47C5F14F3AC6C7AA030608F579B69",
- "adv_salt": "E0AC",
- "plaintext": "803CC93E2E79028A2F7296D4FC882806D2B430CFA407631662879C50",
- "ciphertext": "694088F041A81951B222EF17CE1ECEB37D3AF87D6B380BA0A70F2BED",
- "metadata_key_hmac": "2F435D6B95AD5C0EA3958A58EC6F62BF04971DB04D3ED8B8C0ACB041FCF6E592"
- },
- {
- "key_seed": "93BE31C376BF990F9B7034BD9F47529F30F697EFECD4306E3696BE5386835E87",
- "ldt_key": "0A406E34A9837F09EFCCDC7F39BA22E444BAA886B4DBCFFD4766BAF934C66920D29D7B3AB531CAA4A6986A29919968608610C3DF26C075C8324762AE7FD90B5E",
- "hmac_key": "D5CF9D473D8DA0D9A9109B94EAE16476165CCBEA5FD233349E0DE96BDCF8CCD1",
- "adv_salt": "66B1",
- "plaintext": "0F42AA0A9FAFA18886917149BE8B3C714EE062",
- "ciphertext": "CBD82E0A520ACCA985029E0AA1BF189F382355",
- "metadata_key_hmac": "19A86C5A7B51805E382AC7708A57726FE77C76BCE55DE91D936BD027BD2B1689"
- },
- {
- "key_seed": "82F95337DF211FD4E70D1CC2C368AC599A34D09FC0B83F86A3F8B6D6E8653BD2",
- "ldt_key": "4BFF8FCBDA91DB38F96E500E2CA2F4579F02B14AFB20D97DAC5CFB0EA36C4BEF68A1D3A9F92720845DF021DA8D2696F3C68C3ACFDDDC5CC60A41A8F312E66C4E",
- "hmac_key": "9258C9C8CD52AD8716B4DBD190EDA023D2D4F4D4BA98A5F43A882274B06E2E97",
- "adv_salt": "3502",
- "plaintext": "ECD5F6E936557169BAEF1A1ED8C502396BE78AC5FF41DF18",
- "ciphertext": "3E61F4C2260310F5E7DC3D935C7AE90912ED45CF5F60C8B1",
- "metadata_key_hmac": "E0549A2681AD6FFD30EC26541F650A2E7644C78C02AC6CDBC086CEC3F27C845A"
- },
- {
- "key_seed": "D08D49FF0EC2457AC2B47DD5E076C243DB9CF938EC63EE0AE9F4D0D7BC43AED3",
- "ldt_key": "293A8606CD8E064A2EAC787255B00BB3662A42127ED09B32D660B10341754388B53B6F17A7621FF269B27B2B780DECCD11E66633D461D29EBCFCA62748BBA705",
- "hmac_key": "8BE0557DA21E1F3B747B3EBF15859841F629F44DC30DEDA8A9A586E5D976FDEF",
- "adv_salt": "D0D0",
- "plaintext": "B1F527E6C259C2781855C2E1E297A01099C0F80D031705248936BF20",
- "ciphertext": "AFAAFA362084E8B77486EE59AC75A7646EAACE5494ECDE40EB4411B9",
- "metadata_key_hmac": "B3C654410B5C661BE11298BE63ED92F4650A691D16A7A2C313854FF26E2BA9B8"
- },
- {
- "key_seed": "521760699E3BCB6251021ABEAA830B1F67DB167D20455B19AD07F24BE483EFE2",
- "ldt_key": "3044BB7DD4CF31C278DB63F877A10CB5CB81766AF22CD129896D0D62162730B50ACD56C5063972C6A9BBED8E01DE0B6C7B3F766E91AF73B851AE44B18EF972FE",
- "hmac_key": "0213386D6DFBCA6EDD2DB08F4EE70B887F004441A54401FB83BFED71938E67C8",
- "adv_salt": "89BA",
- "plaintext": "84D603076EC41D5B6BB74189C99D746FADF7A6555D0CAA0B",
- "ciphertext": "1C8AAFD2B9737BF33D62EC516EE7FD5BC1A7DB3E2D6DC45B",
- "metadata_key_hmac": "CDDDAF18EDE36FFE9598CFA4B20115C8A0791326DC4A33414B4E93B405620583"
- },
- {
- "key_seed": "11B8B00D034B9DF61299B2F29B03A0B08124D1A937AC31FBF93CAEAA8F85CF98",
- "ldt_key": "45C93BA189AFB8E02399E779C4B775E049C9A63930CBAA189FB84E2C224FF1E440B751DA15C380E4FF8C044DB43CE7E833CB096266B3368316F20416DFB57A7B",
- "hmac_key": "B86DE2F36332C247C765A22CCFED050338CBD95D514893790EB9699C4203CE4F",
- "adv_salt": "DD44",
- "plaintext": "8CB48D8D29E58610F7F6AED0E4A214EAE07982DE45",
- "ciphertext": "26CB68CC2DC942CE7A89C5A0A78099AF417FFC0C41",
- "metadata_key_hmac": "F49A777771265636ECCD5D341AB712955D86171203F789DC6081D7B3397D6525"
- },
- {
- "key_seed": "517CCA5DBB573E8E9BA3061ABF8B971308A13FBD0AF869F8A5FFB74406E38DF0",
- "ldt_key": "01AC8A445ECEE85A7E47397D9E6FDA83D2EA705E1920739FD94C96C82FC50E2E0B0F9DD26E06C2D6622D0488E3D9241D33D70EA125D7FDC901B4355B7AB5E05A",
- "hmac_key": "1EE05ABAD13ABDF7324515B027A3703BB156111FE3F7062815FE7CF8364716ED",
- "adv_salt": "9971",
- "plaintext": "718AB14FCD50872E689F89FCE176581FE2B521BDCB85E0667583",
- "ciphertext": "7F1FE50239B5FE13E098D9FA928B617A748A81C01BCD74FE53EA",
- "metadata_key_hmac": "BC53EB7BE36084F0E5C03123F9D96828F3182E035A20C877F9B91A837E383FC4"
- },
- {
- "key_seed": "184EE744A6A2D5F85E2471FB75CE2393550AB2BD625D45D0B626B6A328802453",
- "ldt_key": "724A5561CA95F06957A90573F334A24C35C757F0FD6474E377A68B01BDD6D3C99C8569BD9D073BD78ACFA7BC1D49D0069FA345D38A01BBEF1EF566174702F9F6",
- "hmac_key": "7155DA1938B23B4309E3A8219151EFE732EDB4B2510E8EEE5331B4849D1A10C2",
- "adv_salt": "39DF",
- "plaintext": "40640644862F8D4C5F12E848B749EC94C2A07DD182",
- "ciphertext": "E6DC4A99E93A734B6096D626088FB5240A105B7894",
- "metadata_key_hmac": "4919CAE2BE79680549C55858B16EEDEC91D531A88860BB4FA2FC4B9EABDAA545"
- },
- {
- "key_seed": "CCE8B060344E2C562C6BD07C3E61D14AB33350FE7C9ECAD8DD932A1C4636659F",
- "ldt_key": "4A9A66237239D55FD96E7059DC9C6B21AD9D6BB7019C352B62B210FADF9DD6BE6DE8469E9235BBA9A225A29C3CD82B324019309D93324A14A56E56C31633C4E6",
- "hmac_key": "327D980355945948B4673D9110FBB960F5080FFF9E9FE2C0CCCC9CAB17016C3E",
- "adv_salt": "6A85",
- "plaintext": "F862FAB1CA3D9E87CC9F168CC747A81AF9B4044E07730FA6130909E9E6888A",
- "ciphertext": "0900AEFBDE843F82F7B7CB9B80B5B3D3A3C724EEBD2A296C782B80FCA0BC5B",
- "metadata_key_hmac": "7A370EBF0C39BA95A9C4D86FC67DF3EA2668DAAE637954A7A25ED2D3E8BB6F89"
- },
- {
- "key_seed": "BF2D1F6B6E0AC585BF3ADA122F9E5EA2FE0FC417A2318EEAA10237A87E636487",
- "ldt_key": "F0C23320CCA42CBA4DF4FE33F09D38AB98EAFE2256937C38D6A9207A43122535133B407842CF2E8DDE687018413C3FDD7E38951EB858060C17CE8E2760220324",
- "hmac_key": "02F49A21DE768BE1271597C2264EA7934C062FC34FEDC559E94CC7F2937A50E5",
- "adv_salt": "842A",
- "plaintext": "ED816815D9A9295F02B02086C743C9C451FDA84FBF784A49FF",
- "ciphertext": "FC09320F13D88D9217DFC63256D97D3CC6C324552D06625594",
- "metadata_key_hmac": "AC4017FC376EE3A0B8BD0C4EFDAC9C861DAF8B8E2358C04F8D4E709ED2E7387C"
- },
- {
- "key_seed": "C93683C86F62EE4BC02C6D7492677DE0DD018635FB42ADB94B2EDC9BF2530891",
- "ldt_key": "8FBF58A09E057DF5FF33B00DDDF53A1CD1A59F2C79C8E34DB7862EC87849D997AD643A3FDF0C6A6A5C865CBD82CDB9DC9AA4537AA4D97516B7DAB71A4B604C2B",
- "hmac_key": "A629688DFA58DC48BC00E9D2551F330CC215AEBE1DD870C1845F9986D205972A",
- "adv_salt": "3E7A",
- "plaintext": "35C533E05B6729ECD42F50F788208D2B6718E3185B33",
- "ciphertext": "9DB621E8B9EBC90FA7C3510FA6BD3D3D1BA260FD6906",
- "metadata_key_hmac": "A09A9FECD04BC4BB66C47317538F49657CC932CC25B5E60643DA5B14E064892C"
- },
- {
- "key_seed": "61A4A878EF91F9EA94C700C94849874D3415DE7440FC15B7884E227D1DC1A5A5",
- "ldt_key": "DB3339DDA7CC4ADE9F2988DDAF92C9FC1DB2D0B87750D5435A25C5D0ABE27C4E368FB68D27116DE07A198CC61B3A31D7D0BCE5B8A501C4C59E6025FB848BB6E9",
- "hmac_key": "76990316DCE0BE4F8794DBB52842B5437D96E5DD3D49398D63D862F68D1014DE",
- "adv_salt": "33C1",
- "plaintext": "1DBE8F58098F3A06F6F6CBA2D7A6E65217491783A5D4C59475A7C27B40",
- "ciphertext": "E60BFCD9FD955F9D0DB1D524B758490C213971ACEEC48B149B048D87BE",
- "metadata_key_hmac": "535971167ADFC167E91D11ECD8422739E7A15FA751BCF173E42557AA1578CFE8"
- },
- {
- "key_seed": "A298E4B46350537A38408F0FA075D65E8F81E9BEAE562D480FD9664E98CF8F2B",
- "ldt_key": "8978D10F567CCEEFB6D0D19D5E72EBE8CBC3053F917EB6E4E2136DF955A492CE250B9B3B3D0107A80D2F68B75D7FF7532223EA174CDBBCFAC9183F9025CFFD99",
- "hmac_key": "8D165A6DB03554DD46483F915CFF47001853973140DAE9D1BBDFEBBC56577135",
- "adv_salt": "50DE",
- "plaintext": "EBB25578833B3D7B24457CFE8BF06B0B382D",
- "ciphertext": "033263D9264CB66C088DC9A10CD9CAA1FDED",
- "metadata_key_hmac": "BC7FBB0A989FD95FDC28A4354FF9268C726A53E7A759DFD7468077806E1A47C2"
- },
- {
- "key_seed": "53B80C4691384A1D479EB68CB55772096EEB11CA2E1FA35A2ACE999A7758CB6F",
- "ldt_key": "28543FDE924317016A04FA6B43CCB16BA5C97DC322A97C041842549D909526FAD717969B8BFD617C32ADB6C184B8CF167FA25727C7BCFC3E91E18350FD86AF2D",
- "hmac_key": "A5EA03BAFEDE6525860E63D548CFF9D712527D1625698626EE30314E78115819",
- "adv_salt": "E0DD",
- "plaintext": "0EB1D50AABB50EC745AC8A13E8BA0F0E132069F0339C8A6DD7DA",
- "ciphertext": "236D656E4FD7F3C08EC6BB93923140DE5A1B12400225E7A0D5EC",
- "metadata_key_hmac": "BFFA3A512F9CA607352BE92335D02EE1273CF008F8FE1F1752654D364B2E1307"
- },
- {
- "key_seed": "0DDD8C420432B91B6DE1A2D6F0F78235B0D551452A50584F07AF5D198CAC8BFA",
- "ldt_key": "E8F608B4A2B2C992EA1BFA82D99EC4C6339B1ED050AC7B9D7EF0A4FCE806947685DE83EAE9875DA1445F5C338512E677E30589DA7A8C3684DA48018AB2F68F6F",
- "hmac_key": "D26A557AD5FBF38425DEA0760B1E8C5909A6D4B8C204AB95CE7477E531E03354",
- "adv_salt": "8B71",
- "plaintext": "B048E510CBADC24B14539533BF5494FF49F2C3",
- "ciphertext": "2F782D87EBA2E7E9C4A0F77DC590DD19745E58",
- "metadata_key_hmac": "ED761A5953DFA5A8FA6A005F96E94EEE234C2ACA6BDA24138C0C45BDE95E1FE6"
- },
- {
- "key_seed": "FA75CFACB662E891B6414794E0DB2FB4BC655C34525A23CDCB0A2E0E85F0D3B3",
- "ldt_key": "43FBE39E37AFCBE9675353529C7DA24E29747C8020570BA3411D8180F73AFCA4F990BA56F70B0F968E9417D7439E0085CE7204D6405BA54D5E13C14D5E34C5CB",
- "hmac_key": "4D525776364E2BC6F1C5496BA7870E5546844A2B903D5D755592178986657F41",
- "adv_salt": "F145",
- "plaintext": "795740E52EFC0116F7DB7BD5E06C941AB40F45B7BF43C30A1459AF3E",
- "ciphertext": "8222D51F1133C66F465C178C6E143405550419AEBCBD16F64BC42B57",
- "metadata_key_hmac": "5EC58B4CF605F3A8C2BEF6BDF6D5D433479CE0EB89D7AA94C5A31D6FA62BF7D8"
- },
- {
- "key_seed": "D81F137A8A592F5939DBD29612D4AD4C041D85F97D25A6AF5E2AA0732AD5BB7B",
- "ldt_key": "A2C2EB3CD286C292EE346EBA49520957F6E614897A8F62FED22825B85B3549509C468731A4B02A2A8DFCA42C06E80DD7B6871CEE493E874AE3142DB499E3DF8F",
- "hmac_key": "D1191674844A540B185E390DB8B54BEA11AA29B29FE368719AB0BE396AA26E55",
- "adv_salt": "5790",
- "plaintext": "1E0F660610C7DD20815985F7416C0A4FFDB6FB976FC5ADD58BF09A",
- "ciphertext": "F976BDCF23C7B104D73C9C0349C2CF39DC50798376D722B602B8DE",
- "metadata_key_hmac": "54B3AC82E8C3326BC4A32C28D58978A4AB01E5E565877C9A9BED7FBBC5BE4E81"
- },
- {
- "key_seed": "433500D60CE472A1B0412C1DB49129E8E3ECCB69DFDB2071BB213D79C032B649",
- "ldt_key": "42137CE289F09CBA88A147D3587CAE932AAE2CE51603AE5DD256ABD3A32829ADE7276E447FB47051CD23B5E3A26D0B12480DAF79EB0F67F74221A1B4E6A5941A",
- "hmac_key": "23C59E52C6EFDAA59C94D588BD0D9B08E51B28218E60508CE7B2DB8424C6FA21",
- "adv_salt": "E058",
- "plaintext": "7C9C51B6273C3D129DB1185E63E691D3BE2F34F84FB7E59E3BA25C4580A4",
- "ciphertext": "31DA8C38F317D49EE84696E3689DF4D7574AF0AF0935F181EB415359A0D8",
- "metadata_key_hmac": "7FECF203B6F8BC19C6220DF71CFEECDB3933182D59F13BB64690DBEFA4905B6D"
- },
- {
- "key_seed": "AA82ACD315420135AFD50956D58C741AD038C1CB4ADA9107E62C544299E8683A",
- "ldt_key": "3A869E32C2D2D0549CB585A85256C24B9E38066B4F970FF221B500E77ED87057FE0A312BE868D9B2FF2AA428850EA878D1BAAD7F8C484786A23ED8574A9EDA73",
- "hmac_key": "04B2AC14A413C82D59A7CB32AFF74A1A0286B35C79A84B6433CFE5B547B53D1C",
- "adv_salt": "7CEE",
- "plaintext": "7E30FA659ABC63016F9475E1A43F9C6BE6F63CFF35D5",
- "ciphertext": "7C026E54E258A22E2FB306FAEC611F3A27022D8B842D",
- "metadata_key_hmac": "BF8EB548A58FB84810D5F89985BBF146219A9F4B6D6A88976098712D8D14BC52"
- },
- {
- "key_seed": "AF2BD2E9B622AF968A9E28F2D01DC6125600E2F2C919AE48334A6BB334F50681",
- "ldt_key": "D2BBB15D29036398CB23FC21E76B3F290B2B6D8B35A2DA87D822BE554446AC37FF6E1178CAF3D3CE33BFA6A23C7216D21845F4B633DF1D886C27DD7848A00DA1",
- "hmac_key": "AC3D67D7B80CF27FD06227DCA2A866538CE5381F6D91C1B4CB02C63D67D5D391",
- "adv_salt": "DD61",
- "plaintext": "DC0F8D81D76F502DE49B8DA6CE0BC92A4F85",
- "ciphertext": "16136543D9435ABCE30BB6697D0724FFA2E6",
- "metadata_key_hmac": "50BDA48BDA68014C2B79912CB5A78496F02A7E9F53083E287F5F793F8B56C834"
- },
- {
- "key_seed": "59D1CF20DF00B037EDE35BFF9C2D81916C24ECA0CB2AF45F8D5D06771146CA25",
- "ldt_key": "435B0CDDFA496C3DA6E878E970ECB03199777DB9B550B24593D14B46CA0D4A5C97AD3F24EEAF69713D1DE1978D899E82EAB4582740C87E40D3A886E51BF5C7F8",
- "hmac_key": "4928D4497E1B1A6000CF7F5252828851FBDE7CDAE1FF94F120F7853CB8C5AFCC",
- "adv_salt": "80C0",
- "plaintext": "05E40AEDAB61D3640704C79A414D4A33E1FF26B0330F",
- "ciphertext": "299B3B353281727F86451A1AE59551DDEE62DCECF28E",
- "metadata_key_hmac": "A871AC9C5D5FE41100F24595F76264299737B9DE7B8AF0DEAD676EF9F5720B03"
- },
- {
- "key_seed": "2D74CAAE7632991E402C74162D00FC74E2265D4871B4C111EA8BC7C0E8FD2BE1",
- "ldt_key": "9765F667EE3F8B8AA71EB0E9C32E52E3B40543370DBACB49426DA778EFC5FE8F686B033AEF2D7C812D372864800466A213B3588F24757C1879BF542DBB8772A7",
- "hmac_key": "504E5B2C9489CEF0694226A8FCAD0C8063C2F036237BF8B7F0671FE38FC60346",
- "adv_salt": "8ED7",
- "plaintext": "F9606202547972E7B5AE3FE384B4CCAE39DB36855CEAE900F0F0",
- "ciphertext": "15232259C054006C5E89CC14639C5015827E4D4FBF55C8240E7F",
- "metadata_key_hmac": "CE489D80B643563798BE809C94D7A999FB9CA939F5AA5B7EBAB0EAB388FF54DE"
- },
- {
- "key_seed": "5CD613D109C542459ACA3951FF5F604189ED8CFAEFFA098C20F3ED079EB32BA8",
- "ldt_key": "6C0A9F9767AE7955820A782B8316BFAF9C19C0340BEF88EA56BD7183B3AD36EB10E6C68A7FB2F1777BDDCB33061E4EDB2D5D217888E6561A106B7CB4E7220728",
- "hmac_key": "57384357B50B14AD37868828A49C736E4BAD95EDB5383FEDCF621CC8EB573E2E",
- "adv_salt": "BD33",
- "plaintext": "2AC767D3A0758F2A3DC8944542C667E10A73",
- "ciphertext": "F570C912A712DC6CB04F265E5BA15EB02C37",
- "metadata_key_hmac": "C9C1040E72EA6FB67791E341E6719F2B14CBC1A8548F078F73F3A7A8D2C6FB41"
- },
- {
- "key_seed": "0A544CD0DAF4EF5DECE34A6280AEFF409D2051AB2AAFDCA7391B39B88C9F4C07",
- "ldt_key": "023581D6D30E5D936FA2B412197EAB6EAD5F0752F74E0D5CAAC57A5690108414235CFE0E34DF176ECA8518B4B9A3414466E73A9125DDF7CEEE546561D074EC3C",
- "hmac_key": "4FFFD0CFE5B6933288346DED3EADA6F011F1E8BAD400282CEB53C318710C4175",
- "adv_salt": "EE60",
- "plaintext": "46D08772F5BFED8CC74E63E416166F0870F50E25B3",
- "ciphertext": "C243A96B6F5C7BDFAEAE49DE62D0EB20FDEC8AF155",
- "metadata_key_hmac": "5BA8DD187189BE60A71EBD4EA87044E7D1459C529B5056FDFF710328ED8FD687"
- },
- {
- "key_seed": "FED59799667B62FF95C0AE5855BE981A03017356EB9DB2832DC61AD91D09C8EE",
- "ldt_key": "F0EF9BE489F809B06D8F63AA60D581E45569B97E891CA517AEAD9D7544992A0D3BF8460DF4C625B511FD21CEC7B6C4299DD8E3D4EC1E6C7C144148FD9286B5C3",
- "hmac_key": "D2E7A262787F60E9BDCF746CECC80753BB9AD621C293E151DD338B536FB5F237",
- "adv_salt": "A49E",
- "plaintext": "874981095C3E8D802B865229B6DE0188B794D59D",
- "ciphertext": "4F4D01BF0ADE89BD44EADC09F48D2CA2ACCEEA57",
- "metadata_key_hmac": "E65BC7BF3DC8FE3EB2C16B03C8EDF6A40A6EF40A3CA4C25F23D67E95E7465F62"
- },
- {
- "key_seed": "9F909799C002F7A7BD4D7334A13AF9D6E23D22D045624C8EC6AE1B351A90291F",
- "ldt_key": "8819682BF93D0863E6FFBDE350D390EE42669A293B08281C7C79655F440ED73132C145142B5BB4D25876B71FB9DD43CB6563820C61A968DD0E3646AAE284162A",
- "hmac_key": "14DB97DD2C418D68E32B59A92725F17EB329D58E700B5629FCAE5DA6E0C3C917",
- "adv_salt": "FFD7",
- "plaintext": "FB1701FEC5B4CBAFDF5A466BD5F03A8A55",
- "ciphertext": "8574791206F55805D0805CC8B55FA27306",
- "metadata_key_hmac": "3080E8846D6C5FE00E48AA116A69DA2B2A12A963A5ED099E193ACDA3EA8F85C4"
- },
- {
- "key_seed": "E6AC538A534AE767E973EE88870C99B895E64C90A4D35DA089BE222A1390A9A2",
- "ldt_key": "EBD509985542019467D4D2DD645E75A85510D3F80F13C57A2A3A93136345C1BEE714564F63D1B8A6ECA4C5441AA65F3FB90260FCE0CBE0D71A83F6487A935F7F",
- "hmac_key": "E9C658B89C127FA335B5288393338E425B10D91B0A6D2CDA3201E937DF005089",
- "adv_salt": "9BBA",
- "plaintext": "D3D8FD6F5F87E6495A1074BBF96893DD0FDD4D4AC7A646D71E6032A940",
- "ciphertext": "811F782FCF532B8CE2DD7D9BD4FD2E1BC53F3CE766CC806F5C22EA845E",
- "metadata_key_hmac": "81ABCA37FBE03E4A93BAF5B39E1E3CC0C5B8860CAFE27F2A2DB5941901151A18"
- },
- {
- "key_seed": "318829968E74DAD7AAEF1E0A38B75090BBFD615D498BB0D3329895B19A99AC0A",
- "ldt_key": "DC38FD22761C2AD95226DC62E59DB6B4F2A123E8B7F0B051190AD15A3D43FA615CF7EF343F9C71ABFA7DDD82B11B75F8A6C9CC60F637195E62549A4F901791D4",
- "hmac_key": "110B7F59B772E542CEB985D76597C3292E203A8F07C3B61BB16DA496A29287A2",
- "adv_salt": "6828",
- "plaintext": "86EE8C8CCE12728BDD3F1D4981AAE9BBBBFAB9B0AF19268B1C76D5",
- "ciphertext": "5FD08415921FA4EBAA96E5AE431046A5EA303644EB697E0130F296",
- "metadata_key_hmac": "F6DA270AB6BC300455B1B8ADF4E735D9A6424F3483282BA3AD7C6E5E6416602C"
- },
- {
- "key_seed": "280522A0E9A7D6B93559616E459677950385E57120976CB16143ABCD016B462A",
- "ldt_key": "8DF52AEC6B9151A538696F1A6D5C909B183EE5ECC965FF857E23B2053CAE6BD48A9233AA15168E1FE6E34BFED7C08A5143250C642F0D315D2BA3D6751B4CBEA2",
- "hmac_key": "FF0DE7047DE672CDEE76DA1F2AB7A4F6037C8056B87AFB01D23775154CFEE49E",
- "adv_salt": "D224",
- "plaintext": "8654C8C1662FEB3C4081908308079B533C6EB7C482",
- "ciphertext": "77749830BB6B9368783A0170D9A09923C0DB7215AE",
- "metadata_key_hmac": "2965D442FCD5C276D98973B74C2CD551F5EDF365691EFF05DF27EA21570A8AD3"
- },
- {
- "key_seed": "44E769CFDE90D9F3EF56A653F28ADDAA06B2CA60EC7FF422879ACAC2CFA46111",
- "ldt_key": "BBAC7B253EF46F3617DE1B9FAC5131135F2B213AD6A20ABFE422D9CFEC5EC85320DC4FEA089AB4D7DF679CD2507B9BEFD3A86468BE9E3929572F684AC6A320C3",
- "hmac_key": "E41BB366EA27E78220208EF81F75CEF9F6E462E5C2F981EF58811C60B9663499",
- "adv_salt": "3D17",
- "plaintext": "A155D6D26B2F127E2FE82378B341D2FDEF3E16288ED7D3F3AC60",
- "ciphertext": "8EDE7296186394BA203754260F747EAE8360480CCF21D0B6DD8F",
- "metadata_key_hmac": "74009FAFC9FD260F001569709C4295991C242B5A61E6757AC708ACC3353CBF5E"
- },
- {
- "key_seed": "AE66C35F7D04021A5C698C352F4F0E9D6BC341054228F6FB9244B777C31779B4",
- "ldt_key": "AA3F95B3A0E64A2C4C92DB7683E4A9FD6B5CAB46650C09BDCDECA9DC8767BA9813814FACEC94CE675DFC3550B238A069CD1C575B43754E86B1C2447647D31FF5",
- "hmac_key": "FEFFD7822CAD0ECD152DC7D05BD7E928F97500EE40995B30DB922489213180A7",
- "adv_salt": "7B92",
- "plaintext": "84F5E66A4A74125DBFF956A02C3803AC",
- "ciphertext": "D3DB7D16AF86E6BCC2B517D58648875C",
- "metadata_key_hmac": "8E2F1AEEB263AACF0282E9769916C5A265CA1F44BBBA0987D828410A1BB12321"
- },
- {
- "key_seed": "35B9E153848ACC7A635654570B9383281080B8534BDBCEED1603A6F8C6D5507C",
- "ldt_key": "9FE7252B04B742365E177DC551968D561DC229A579D5D300DDBF64F5AC4972CB1F68E04B547E63497A5356B34A34F73B1202BEAC45527423DBB839D218ECD30D",
- "hmac_key": "2B95CF79638C004CA750F26A19226A29697D1FAFA2B4F3BF8626F8678861C13A",
- "adv_salt": "6B57",
- "plaintext": "35AC4FF891D302D09A2FF9B0D79B690BB2C1C3C62ECB8CDD6C9BA116",
- "ciphertext": "9CF13BABFBD80C501125B19AD377B6257191404D3EFE5B41D9AF7F09",
- "metadata_key_hmac": "D3C52F6F990063859C79B0D3C92210DDD4B9CE9F15DC889CABDB87F3613F733C"
- },
- {
- "key_seed": "687532B1C30FC1EA07FC5E016895C91E6AEF0DDE518672CE737BD4DE49848C7B",
- "ldt_key": "1F338AB5C464BBBDB21C74CA46824422055F2D936E5C8E7CD9D070AD2B94D8C2B143BE8ABF4E5011B550F36C702E4355DFB2E2790B3FF94B77BB8DCD66EEBD4C",
- "hmac_key": "00AB3E77B01DDBFB63C0DAE4F3629D1D36DB38A80CB9EDC6D24D48A9FB2C22E2",
- "adv_salt": "3CE0",
- "plaintext": "CB64C632A684EB164D597CC76A77D37DAEB7BDC3CF0564E4",
- "ciphertext": "CC05C33E64E9070A0BDDF3EA43B3E07B20ACBCAF7887252B",
- "metadata_key_hmac": "DEA7BE9F28AAC7BCD020EB419A7382896B6F326D3EE31AB8CB5120FE17ACDCF9"
- },
- {
- "key_seed": "1076CF7AABA9FE8F884DC407AE488AFEBE10CBBB638D9F30171F1FE11CA9E490",
- "ldt_key": "6954D32D9BE52A9FCA5868AF05C31E99B23AFC57F35B5B85BF85E881884B6B0B7925AB1AF21C6F0B70D139558FEF434DC55A42190EAA5DED0903A99D101A79E6",
- "hmac_key": "EB95583262E1F170102BE84FA40A8602D81FF7F4284A81136BDA6C44E6421908",
- "adv_salt": "083B",
- "plaintext": "AF30C1BE220AAFF63753CD60888CE865C1AB3962C7696D60",
- "ciphertext": "49C25447783F57672C331C9CC44AB38BE9E7C08BEDB25E65",
- "metadata_key_hmac": "98D61316118887FFCBC232C0201D97C1B6F1F1208D46786349031081FB736851"
- },
- {
- "key_seed": "E540DBF513BA5D1D660FA9BB7EC880B13B9525D415909172C4FB6449E1091C3B",
- "ldt_key": "641FCED17EC3ED765FC414C6310A994E141E97FC01674C04F5686D48D33CBC92929734DFEEEB95D0461AE32043900D001DFCE6ECA701D9355AE713CDC3FC671C",
- "hmac_key": "44E3408B3F701FD8E22D0520B7B5350A7DE5623A2293AB3DBD4EEDE8C06F805F",
- "adv_salt": "0A21",
- "plaintext": "DABA28E713234BC8A65B5E6A9876EAF443985058E704E9D5E6",
- "ciphertext": "C8D35138CFCBB94F1728BACD1431A53F443715333D7EBE1195",
- "metadata_key_hmac": "322E76085DCE4370101F0FA295B2F7CECA5FF72EFD74A8A5D36F1C86ECE65D9A"
- },
- {
- "key_seed": "1A0258CB8FFCF6B1A4060754D79300B678395BECF87F7B291A81660A73A45DA7",
- "ldt_key": "F74BAB65280D7C964EE58219A8B03699D2B8B3836466698BE00264EA10D5193BB2193858AEDE740D559D60B0016D21F85CCA11E006D9587D5A56813363ABEFB9",
- "hmac_key": "7E74C500A645FE5992A8F5C72156B7A8E7E35E6FD8E24CB5B0F5E87ED928C82D",
- "adv_salt": "C93F",
- "plaintext": "A4B100A7F1EFFE4CFBAED727B0116008",
- "ciphertext": "FB3F0705BB236C87E99D98FD7ECCCB2E",
- "metadata_key_hmac": "B281E7B6C8F510047D3707C84FF05AC1B7DA7B6B2C90AFA43977608BC889E3DC"
- },
- {
- "key_seed": "CE96629C4259457DD42183D24D651A0954568EA47DA08BA41540665D74592BB6",
- "ldt_key": "13224342818872CBBDF1EEFB4E7260DD673CD601298D06705ACB56391FF6FC44B5F4F2F38898CE23538152192F54C9B89B9CA8BFDB6D144BEF24777F0D469DC4",
- "hmac_key": "C77A50FB84F7C0F35264E697CDD070AFC17452B08E5943A6F98A59539BA5AD67",
- "adv_salt": "EC98",
- "plaintext": "CB57670713089CA8EDA983C4C0212DC1F699FC0C6A5B",
- "ciphertext": "28E09ED5045AC92F7E08F62283908CA60C4EA8558E77",
- "metadata_key_hmac": "0B714038F04BAB7ED853780BDE53496BE9A883CDA8EC4B7CB7BF2E04E62C6790"
- },
- {
- "key_seed": "8CDD9F5539AF7EA7ACEC71C0D43CDB1B3358F7FFA7AF5DFB77C9796F9D108830",
- "ldt_key": "02123AE1B3033A2C4832936464714F4BF5DC16D641839B451FA99ED98076909C258244FDB7384361991C27FF34ED27B3C93AAD0E22B6E6005CDD7C8794145F00",
- "hmac_key": "9AB04D6FF1D83EA7C7D987F19595F9E3037856B3EFC34AA74C30273867850549",
- "adv_salt": "D034",
- "plaintext": "2FE3A1A36EFB21407D313E64C8BAC756A1",
- "ciphertext": "89CCCD395B9BFE3C0BA49F9B9DCB529B1F",
- "metadata_key_hmac": "C89507EF56672FC994F5FFBB93F099534D3201D6FA97122FBD5D2FF279525C0D"
- },
- {
- "key_seed": "F3CAC3D370DF389BA4E949320C7AF35347CE90B39864EB28F1BA7325966163FE",
- "ldt_key": "0FA705023E801CF9626F0B0B29446A1D5E3B7EBF8DC4228535565F8096D5EB374061C6AC89AB77F8FDF15209A49DA4162EC3A7731B695C8BA97E6A6A54AD927B",
- "hmac_key": "94509AEADA6A469B8AE4A4CC57771F386F4FEADF8E073A758DCBDB484C9C1472",
- "adv_salt": "B505",
- "plaintext": "C9CEA0BA6FF74A45345DA313F27F1E78206741AD1BEF",
- "ciphertext": "458A3FEA342BCFA9563FF419CB1C11CAAA18CF74E4CF",
- "metadata_key_hmac": "3EDF761D6F862AE3C4D6AE1932E5DEB75DF16D060A3413F3160B859EFC8C2335"
- },
- {
- "key_seed": "90738CB1AFCDBAC6A9A01C668340AA0C5E388E38F4BFBBDAF3A2F1E4D00230A2",
- "ldt_key": "D470FB6A06FE70104782740EB5C10BAB3C19AB59767C5AFECE2201E433DB125D2D4C5672596242445D829EDBC89019E2AB449E87C0A9FFDF9DB15C228D7FA643",
- "hmac_key": "24C9F3B88BE8BFB2AD54387CED3DBA80B470BFC04A0F1FC38D3C1D818247251F",
- "adv_salt": "14D8",
- "plaintext": "6938B0CEE011BC98046AB7D8D906E9272A9A",
- "ciphertext": "5329FFF7838E166A72B5264D9426BCC777DF",
- "metadata_key_hmac": "D58E27099B581E6357CFAEB8FDB74750646C4EBE1BC8BB756FD7A2112482C12B"
- },
- {
- "key_seed": "E167A2FDD3D194B125091811557C166B51286A0EF07B428ABE7491B1F7D4B95C",
- "ldt_key": "A857775D84E7E944A0D8646FCC65A1F68D5F9416711926C426DD13C870B345AB51D5F5C67602E326A52C02AFE1AEEEEBA6FBD5B96DFC684FF672BFD7D48BC0B1",
- "hmac_key": "A13BD102F4DEAABFCA6A7EAE6A8737CF2003BBEDB67636733A8FC1B477D7578C",
- "adv_salt": "D1ED",
- "plaintext": "4D2D74C7B1FBABC53F276E2054229FB59756B13BF8",
- "ciphertext": "C8DB5D3877EC446D84D2D4C2F5BDCF725F573B82CF",
- "metadata_key_hmac": "FE8A0D0AA4586C3AD93556FD260ED5FABEB0BCBE21B656A09ADB7AAEC13873CD"
- },
- {
- "key_seed": "C2D55EDB8F61B628A694759CD39B5DDF3D0AF8D728654BBD7E2EC1641E30D584",
- "ldt_key": "260CE6B2300C74F630074B946A98A12196EBB271849396523E75C777F5580AE4F853E7C462B1C5E95C14BF910EF567E5C72D69DAD21372EE79AD1B567D0673EE",
- "hmac_key": "AADD4EFE6EFC77D76690E95CBBB7F9D8FBE78DB96BE4279099933431CA7C0CD6",
- "adv_salt": "549F",
- "plaintext": "585C510BC7605EACD72E32F06C634937A2BAFBC7780963F371",
- "ciphertext": "BF2F3C7F84088E8F718AEC12C03B0EEEFF0954262B98A8239A",
- "metadata_key_hmac": "1A5F73FC9A79547EE81832EA25B3C13A883CE2E1F6C9B4C1C8EA00A2C5D402BB"
- },
- {
- "key_seed": "3B1DDC15E0631966EAA4E68F314DECB49E0A08F2620A4AE7B824D60181DF3BE2",
- "ldt_key": "5B03B2A87E537B8FE4B0C0898FDE2478013225B121F225EB23998694073CFB1099944096368B5CA7E3750A0E12278479FB336155F4B128A810DF04A100486A73",
- "hmac_key": "31A368D150A45F2D2A61AB1C1A10128AAAF46D1F6C55F370BBFF9894CE0C453B",
- "adv_salt": "0B30",
- "plaintext": "D01BA2A3D3791D476ED7920D9C8C9FB59CCB09D9726D81B18103E7F53BFC",
- "ciphertext": "13FDADB34B3EAEE768A31FDBBECDF1B9D803C5A0F3503E66C4DDBB566A66",
- "metadata_key_hmac": "10F474C052FD27D591BE50A2258F749AE1C322CF31A577F601ED10AC92F0BCDE"
- },
- {
- "key_seed": "D05A40EB2A490AFFD6C9080FF0B246CD746D7EEB1AD5A989D2B70E82AE1AC245",
- "ldt_key": "7AE2D1B2E56E73D68FB690A93180C30062CD08506A455D5940D7C0101F03EF48B91077465FF77AA0BDC56F3ED4619D0A126A2C19FA77315F24FC42CD56AF712A",
- "hmac_key": "D26C90D9A22DFCB2BA4DD1C2FCF846DC6D34DBDF5928AA0291FC86C38BEE70EC",
- "adv_salt": "878A",
- "plaintext": "E41F56B7469491404C9085AEC86C8E818D",
- "ciphertext": "791714106233445CC920E4B5E04BC78800",
- "metadata_key_hmac": "850BF2B0F3F4E4A20CDD64DFC2E451A636EE3FFF64CB58D035647FF41F316127"
- },
- {
- "key_seed": "C1D8FB7C8AEC3E472182033DF3C22486D85D0AD814A4E66ABCCE536FB2A809F8",
- "ldt_key": "86A0CD0A7892C19CD539045D406101699423BE2E09C0602936C03ADE82202CD377AEBA7C13E8252CEC8B7ED2692F9F8618144C117E3EFBDCE16C34B03EA181FD",
- "hmac_key": "975C3E0F9F7A935042ACC888C27BAD5B372C5744D8A70886CDB89633A947F4E4",
- "adv_salt": "E796",
- "plaintext": "4C632A0EBE20C353422EA7E6BECDF2187061E47B27D00FEDB5D237B79DCE7C",
- "ciphertext": "DFC203F3CBB6BD68737632B76A889FC2B4137EABFE15FF0C89AB78226A4DBD",
- "metadata_key_hmac": "6005486AF7B630BA2A910C872F84005298C66ECA82E52646C719B42A6E049ABB"
- },
- {
- "key_seed": "7421221A0F0AD0E1E40B807C29FAB0BD3ECCE688A7AEE3B80E758BD19D4D59B4",
- "ldt_key": "F455AFCDEB473EB52482C1B91CCF1934B6F88EA0E730EB9F4D0C0A843DEE28913E20ACA037F0E074F1B51295FDB94F3B5808A8D19CF88BF3827DA2838830FCD5",
- "hmac_key": "AF1A1D886594E6245C51D04FAF0B6A5806D1E9B43ECFEE7D49EEDAB531BE6EF0",
- "adv_salt": "E14E",
- "plaintext": "4601A3D31452D93823C7D559AC189AFEAAA9F088AD02",
- "ciphertext": "07E5F4AF8FC2C0EA45D1D2B87CC41992BC7D296D0A43",
- "metadata_key_hmac": "D7DF9CDCB61C8C362994DBB895FA97A7D5D072CC203F4BDCB28888E884F1A4A5"
- },
- {
- "key_seed": "2CD8CD00A308856401C0145E13A9CED9CAC6EF683BC3844AD943D9A5880D87B2",
- "ldt_key": "50B75DBB72D50FC8855416F54131002F29B443DFAAB3B04D65562AD79E52E983D452359C85809D9CD5296D36E0C961A97F0903623C3BFA8FD83AB405FAD1D7A9",
- "hmac_key": "30650BF4F161E2C0C3889466CE63FA9873EBB8E3ED44FDA2694DB232ABA80097",
- "adv_salt": "67C7",
- "plaintext": "FA83732566D4C7F669E235EB65395E9EA20CF710182C1C91AFD56E4F",
- "ciphertext": "D5FC0C956FC70FE612244BCA166E0F7251B4985FDCE2EB37ADB9492C",
- "metadata_key_hmac": "ED4DD7A65B7A9395E06046252B259B01E4FF4DAA5F31E3B4C887CEEE8BD8C422"
- },
- {
- "key_seed": "961EB7E66755382EF32B91C881D1B370CE8C84472AFAB8730CA72431CCF5709D",
- "ldt_key": "D20A6B1DCF00991DC6428BC18539DFB54CD4C7139D174D279A184E7124921E52AFA8203AD69E8C344F8DE98AFF20A46F7ABD784FBF7282CE8E2ECDDA130C0616",
- "hmac_key": "BD12138D7A6759FE88B57A2ACAA3C2AE059FD223A7F768FB14C92247480F45F0",
- "adv_salt": "6127",
- "plaintext": "C2EB434C6012DAF38B420B10886DD4FD0B4F47A4C46248B3647E9DD2FF1337",
- "ciphertext": "68B23472CC617EE2524CD544553E372A4073943EC98578209189E80CD972E5",
- "metadata_key_hmac": "85B4C89F930106E07EC02C74C6C9A367FBF755D81C3FF360D4DA4F29C33EC151"
- },
- {
- "key_seed": "EE97B09C86EC831939381B61A2BC9A8CB54D7D6687F7FD500DDA53C04504C400",
- "ldt_key": "076C50D225AC3DD54E785DA9C10B29ACF481868A590D6E11458A68253039E32D99FCAF2CBAD329909D411C329C0F2BE7B03E674294BC983F5B1EF24C1386734C",
- "hmac_key": "C602826941014B984F279A3BC71E938B0A2441520777F9CB904D66F4FFDD2686",
- "adv_salt": "4707",
- "plaintext": "07B02E871111A6AF85CAF0CBF4D2E2A6930C405F535641",
- "ciphertext": "31F1B4569BF4830BEB16FF2627E27CAF73D100241F2D26",
- "metadata_key_hmac": "3A0B7F8E3527682993B7B168A8B6C81C16CC6E41E90A2395AF25BDA99A9DE9B4"
- },
- {
- "key_seed": "90B1F3C4E5E3563776576A41F54FA8F8FEC39ADEFD7151930A6F71F5CDE1EAAC",
- "ldt_key": "23F9BC3BCF20BC098A85807C8E645196E4414E7A1087752A0E5616F59ECDC1BD6A773368D51E6CE75D1BBCB761201BC127F1A7A23C6ED791DF3BBE39C2498A99",
- "hmac_key": "97A26BBED95B16D4292F5191C6A7B24E2AD2A2A1185BEB3880C0168578E8708D",
- "adv_salt": "A852",
- "plaintext": "4E97A89CCBA3AC8D5C722F06C6DBE3AF7F068FD7",
- "ciphertext": "0887E7F846287FC4E1533DE351FB7806C036CA89",
- "metadata_key_hmac": "F60321123B682D9E8035890BC2F00EE7C263CF198DA707B639306EFBC7F4E625"
- },
- {
- "key_seed": "E0B3093E67FA08DE9808AE03EADE5A2F6C52C64E6C1D24D209F8BF01D5C3B216",
- "ldt_key": "71722699582831C8E407B0E8C2D55843747E180920EBFC05EFEFF2FE94C57B9514F196E6F8C837831580F721242E60232819BEC77C50E4373070D38798CB066F",
- "hmac_key": "A8FDD59FFFEA81F66F03E18071954CBD48697DCD56D61B38DE5F0295B04E0A76",
- "adv_salt": "CECA",
- "plaintext": "C228D2B9F0483026D26010ABF7EEB54FA60FC0BF607F7F3C73721757C13AB1",
- "ciphertext": "8DEDA4974DEED69DA408D36C85AE1753DBDB8E57DE92D6DB419C9DA4C359DE",
- "metadata_key_hmac": "78EEFFDB4E52ED95F569AFE6CBEAF1152BFDE33FA4082FFCA081B50E1E1EDF59"
- },
- {
- "key_seed": "3D0BFA5E1D7958861EAC95B30C156F8DD930F2782F53E5FF949A0A403B423DCB",
- "ldt_key": "C3FFE404D89D676A1914E50DC99A946AE7A7DF295593617A8C57B75BE73C5633F9C6511921D17217BAF92FA5561548031CEC00B060C431A5614E3F4BA52F089B",
- "hmac_key": "70A971751BFE0E714DC85968C09FC4DAC29CF9142500AA4BDDCDCEC85DE0C4F7",
- "adv_salt": "CC21",
- "plaintext": "4832A069F8CFB5B21FB1D82E7CF9BCB42FD58580776795935F638B42",
- "ciphertext": "EDD7669796B5D75F82B7FD1463DC1ED7FFB188ADE2DB85B2F46B5941",
- "metadata_key_hmac": "1456E2336700FAC9ED4BB80EE85CF82F70A1A3BB72CBC34E420A17CB7F1B1A92"
- },
- {
- "key_seed": "BFE9774B7CD737A03FA3AD280C1BE486CF0C83F3CCF24DFB01EAB69DD95CD6C5",
- "ldt_key": "9EF46C8221647475DC974309BA3DA5409AA911207CEBB303E47639CC8D6B9CF15653B9676D7E93ABB82ECA46593156BA08D25E903417B1D221D1963937DF5A24",
- "hmac_key": "E164FC152DBA6C35F277A5924A156D25FA10099DA607E318A43447B1DDBD0691",
- "adv_salt": "F508",
- "plaintext": "169FCF6B075E8AC5527E5B632EF377DF7745DF0229B788664B52F0",
- "ciphertext": "67287D2CD908E7A0DE65253DA8B6B9010AB975DA5D97E0E85B3E69",
- "metadata_key_hmac": "CB23A8B0C9823C44C095FEDF0BD001EC65C33FA0CDB6C3A27835527157195F9D"
- },
- {
- "key_seed": "FC1B9AFCDA4B0DE4070B4865590D99C1B51AC16013F746F726FB00FCC490F5A5",
- "ldt_key": "3DA1E02171D7612CF8DFCE3164158ACD84E53B3A798CC6E211D3D8E3A38796C4E632B1DD1C33939DA0191C55D621CFDCA72E21F8DA33BB90A71AC58847540930",
- "hmac_key": "FEB10E4A8F5B536345299B277C636AE33EA21D4906D32B517FF9D84F86525C03",
- "adv_salt": "FB2F",
- "plaintext": "622025C907045A293B6927E386B727F592388070",
- "ciphertext": "E68F9246E8E9068958F10322F77B066EBE0AECBF",
- "metadata_key_hmac": "6FBC0B2F408A933F4147485BF8C1EF82C734AEA63E586337F6BF789448EC8AC2"
- },
- {
- "key_seed": "82DAE4924C598235701F58712FC1EB2FF71064EA21D77A497ED141C4739945E1",
- "ldt_key": "CF5C7363836BDAD761955D40A5F4D2603D6EDD0929DBA92F13DF876355F7AAE043D41D3616047A03043E87DBE3025AB6A9244F9A4CA23DFC85FE68F45537458D",
- "hmac_key": "7BFF0CA343B4922CBB930FEAF6383D3CED9B2D82F5A20563F5D7D3D876881BF8",
- "adv_salt": "7048",
- "plaintext": "6FAE845278FC72DB91A23582318ABA051A6593DB2294",
- "ciphertext": "62821D5B511ABF78E0EFEFDEF3C1B9D077C488E94F26",
- "metadata_key_hmac": "B46CEB074D0DC925BD81C0A9C42DEB23FD601D9CA19D751B9DDCFBEBB477C828"
- },
- {
- "key_seed": "AFA2295B197A4F7B02148083E172EAC8C990D103EE110E5FD59D46A63E880A4C",
- "ldt_key": "706F784A5BA178B15D0E73CBC5CE3AD0BC2D804AEC44C80A6AE7AF3826884F1DEDD40069E1EE47861D1FA8F33E810D02CF1056FA35837B1D617326DE56865CED",
- "hmac_key": "9B460C083DB1DCE94932C59CDE980C91AC6DC325D27C6F58DB472B3C73C68A59",
- "adv_salt": "33F1",
- "plaintext": "DAD0F021D7D6EA6CDB5727BD07A47772EDE47AE057",
- "ciphertext": "41703414EA3DB54FBF51F8B683F251A390B9007312",
- "metadata_key_hmac": "BE86C7E61CF3E9B69CE5F839A383D0BE36EFAB76607CE6A9E114C23D752DE7A4"
- },
- {
- "key_seed": "E77B0126661C7427A10C7C2DC888E3588499A4E608312189131652ABEF068378",
- "ldt_key": "7C87B6BE29EBFE7C98879A755A4961A92CBECB276A4D5470EE270E0B39A6498CB605D254A3F51C9B050CEEB26F612E1033998A8A41ABB945F04337450E03CD62",
- "hmac_key": "F34D7F614979EE2B0152D10561A8E8E791513D5CCE2715F159F472793BFFD6B6",
- "adv_salt": "B04C",
- "plaintext": "EAE41891217622C50954AEB273E5D1451A8F7DD53436A234",
- "ciphertext": "1510060D88AC5720279401FCE44F6B6D669DB022191DB4AE",
- "metadata_key_hmac": "6873F823783696ABCEA38DA650785FA304F9B96459280463F9889974AB4F318F"
- },
- {
- "key_seed": "49CDECB2F2B9B4660142A86CE287EBF3004E94712D109EFBA6B7D32A3DE0BAF6",
- "ldt_key": "B14E48697D6C005FB9C3E40B2054FA7252B7367E5E2FBE288858338C455DAA0B597DD27CC8E889C110549C7F98B40E93FC3373432D84F64C383257693F4CDBFC",
- "hmac_key": "BF3A3BA5CFF8C9FDBF352704520304ECE0B2927D49EBB6E70FB83270C541F934",
- "adv_salt": "0257",
- "plaintext": "C4C77214ECA31A2095CDC93B97A4859FEAE4EC057E81CA5B1B",
- "ciphertext": "4D69A78B88829AE1F21D402F00098D4D7FEBF07BA8FD4EC570",
- "metadata_key_hmac": "7B136B9A716FAE1B92F66C418526B9B4606017CF0888A3A3709D0BF367B0BA15"
- },
- {
- "key_seed": "5EF26FDBCAC90F504A294B0C18D077ADDA6D28BCCFE9E6D9E1019144E63E82C4",
- "ldt_key": "4A2C98CB7211C55079CC9F33E150DCCD00EB7E1BDCBF623A1344C341D733B71BAB51FDDCB7E94C98B83C736F501C39E383AF7FED8C7E24575445E0251688B71B",
- "hmac_key": "10C7C6D54416C6A4B9A016200484D256DFBE3238E3DE89015756219CFCDBC9EF",
- "adv_salt": "6012",
- "plaintext": "0EDBBC19BEF8ADCF812FFCCDE89FBDF9BA2734CCD97570",
- "ciphertext": "0CF336739B9A76887A5CB3056F895DA3B071B6942735B7",
- "metadata_key_hmac": "59335C71AB60D82F6CC8C7439BE3442AC17E3756CA3F2AC0C0F5F3C74C975BE8"
- },
- {
- "key_seed": "ABB7CAED17658A7808C8D1BAE9BD851BE8F6B3E0417529F717CF7544FBF19CFE",
- "ldt_key": "77A9EBF2D3C0ABD4762FF5404627CF0C73ECA59308C36B889F391E49B36AEF94C12B7C6B594261F94B217AA4D0C9B91B1ED382614245C4F449150C82CF39BDF9",
- "hmac_key": "FA4707B6E99215DF51D4A1B2A5CE6BBB2BD820A0AC3C7D0223F47A99B3789742",
- "adv_salt": "70EC",
- "plaintext": "F4D6F632628DE2A5E863916255D5C91D",
- "ciphertext": "92B542A685DF2636F0CDFAE8170760B0",
- "metadata_key_hmac": "0B1D475B89137AF6861E8F5BF2C3EE730665A8905BA670E892012405E2D316EA"
- },
- {
- "key_seed": "D6E12F6F00FAEE25269FF1ACBCAC2D63CF6A7ACD0B12A11BA84BB00F259F9E64",
- "ldt_key": "08F4FC8579D835028A44BA9B384DF30CA5442C46F0E12361AD827D966B50C9FCEB7273C06AD0D389E634A6FC42DE00971F582043C43019EBB8C180957FC1E502",
- "hmac_key": "78251AAD644F9D46BFA4FD665DC4E0061B6443538E064D1337C6B80372796351",
- "adv_salt": "D06A",
- "plaintext": "6EB100EB8083DE9FB18D83D89E321FECEF1E116C92F156457B3FF6",
- "ciphertext": "A79B09CB86570BAEE1A9BA8FC3A54AFA49D5315092A35AB8B40E02",
- "metadata_key_hmac": "158DE0182C312D6AD29C85DF0CDD61E4B41283339D33F44F71BB86F39AEACCA9"
- },
- {
- "key_seed": "33FEDC3705F223EAF65C20AF5859C6FE4BC2BE03A76FD233CB3B3C755C19EAFF",
- "ldt_key": "73832B0FBC059019CC3B69B7C01402297899803228C3BFEC0FEE44E4A8CE9362127FCABEAB35FFA99E53E51CEAFB52AA2ECDD98DADC68E11FE32B2B691141B42",
- "hmac_key": "70BFA7E804F711750BD51A8ECF716D8828F34642C8718F3BE3AF04BF45D39E3B",
- "adv_salt": "CCD0",
- "plaintext": "83A3554F5BFEBD3AA5CD63033F1F84A188428FCE31E28C7B",
- "ciphertext": "F61245C747B02E8A31F20C5C418C100779F3304C4BF35D00",
- "metadata_key_hmac": "E42B1FEF138C0BD47792602506037A6B6528C6396E2C25EF759245D88BA9C4DA"
- },
- {
- "key_seed": "B8FB96C60B745FF482A56D79AE96C2011CA53EE99CB4EA416D2081341AF6BB97",
- "ldt_key": "5281D0CBCDDA4B9CE9649DD4C20CC65D21917FBF006A874774CC9BD2BE5DAE538E7AD25C7AEDD24D25255F5BF4335C1C7101FE475530BEF3FD34A599686A2EB1",
- "hmac_key": "E5001573DCB0E863FEE47F4477AF9CF601C1488DBC8B18A1048F10F4C2DF96B3",
- "adv_salt": "739C",
- "plaintext": "4C01C0FC54C46EC894E31CB7A3921E4A1C61647A1DE7",
- "ciphertext": "078A0A557B03E5B08D34CC068A228BD4076C35784D62",
- "metadata_key_hmac": "5E65DD3CA805C6592404472BB10A04370D4E9BBC131E8D91F1E8EC7872C81819"
- },
- {
- "key_seed": "3E336BE86F7158546D178E5D3745865476DE850174E4EDF93C225CC5B127DF59",
- "ldt_key": "CAAF5ABD33E017967D0F86484CE494E76A00E7FE1D481C851133C9711B95A4C397DBCCA43DDD69A90DA70CF7DBC9C86385244968D640A93AFB1DABB14A017712",
- "hmac_key": "A74F14F57A80A12D95CE530A4CBC0443F9A6BAFFCD0E401183134C773E3A19EF",
- "adv_salt": "1EE0",
- "plaintext": "BB1B2619872088EA0E3D47536E4AFE08E66B",
- "ciphertext": "0550A3CFE54B801588F4B99477BF29435529",
- "metadata_key_hmac": "CAA1272218E865B040AD16B0CC155CC29003372C513D41F291ADE90F32A7E2DF"
- },
- {
- "key_seed": "C5304C20454F1AD1EA6F1BB2AAD90C32B21BABF043A8CD5F8AEB5806AF9DA30C",
- "ldt_key": "23A194FA43C5CA91E5CBCF05C0729568F3E0374E2DEC7D124973498C16134645FF48590CD4B05F6D3C416AB95F1EA5005755D57DD8FBABFE2E20C731E29B2839",
- "hmac_key": "5E4F9CE97D3DE51E2E0D9C20C2EB528286B259C12C311BCD67995075EA5230FA",
- "adv_salt": "51A3",
- "plaintext": "91FA8DF0FAB24EF8A69CD3DAB86C5833",
- "ciphertext": "A960D8AF967257CB67C20C5BCD6604D6",
- "metadata_key_hmac": "E76660ACB28395EA5E88DD38D585C7C1EEC29D107F3B5F6C5A8980FF63EBB7B6"
- },
- {
- "key_seed": "7D8E85630617FA51F2A6620B7B3D6C82CA9CC9685DD1D0A29E659A3397D871EE",
- "ldt_key": "744289C1913C05990FBA3D066A88BE2BBAF45241AC470A57A37E2077058B048CD9183C89D61CE8E4CCE409825760A121C65B9D2F5A9368E2A88D53340B0944C5",
- "hmac_key": "A54E10CEF8ED1EE553113F7580767CD833CBF02A705A92DAF322D696B2B91F25",
- "adv_salt": "AF3F",
- "plaintext": "6FD2A80E81A51DBDB404188DE0D92FD57AAC5B",
- "ciphertext": "0ACC3BB8B7735307713ED4A17BE8B78CFCB729",
- "metadata_key_hmac": "A159B44F3DDBE83987AF66D786D8418C7FA0AD036F4150FBFA2581AF26540400"
- },
- {
- "key_seed": "9EDC5C552240AE0B1DBE3546A9977AE1A78419E88F0E2ADCE71588A9AB771D15",
- "ldt_key": "E15CB36AE550637055BDF0B0C1AC3D090F930531BBE11561C3EB79D291EA8DC77011933C945C3931DBC6C06F63DCC14856CEE2456CE836B97D939E83623A8859",
- "hmac_key": "96A7C51657FEBB26B5C222633509B49BD0CE08657AE6F1D22462722C02FF6800",
- "adv_salt": "07D4",
- "plaintext": "4C7EED55AC91676F1345CB2ECAF18CE2EF16FA26378C63E6AAF973EAF055",
- "ciphertext": "E964835FE749A6EC67CDD7C8CE659DE998AC244999D0BFB9E1101D222FE0",
- "metadata_key_hmac": "BB41BD052705D128D72974CA087A286AA4D71823912477821215CBB7E344E39C"
- },
- {
- "key_seed": "2F0A7502AAB91AE51E454AFF3C9BDD456038C067927AF5A1F59A42B8AFBE1324",
- "ldt_key": "27F7A0F3E9BEC8576855279F97F447F14277670426B033D098FC177690F4027D532B4194E21804D6F6BAFD08DEFBAD8E33F981BB9848E3A18BB8B8D30A143106",
- "hmac_key": "5C54CED6C94657A9FF1B83F28CB18A42C3A7F64FBD8152F32FE3EBB3B5F7E982",
- "adv_salt": "83C0",
- "plaintext": "002F8117AC623541B57404FDC17FBE7A7A",
- "ciphertext": "5D463DF93F8ACB5A855AD559A4A64709F1",
- "metadata_key_hmac": "BFDF51FEAD1958FEAB8F9804AE00DF89CFE09F404E0A33DD3715E966B0FF8122"
- },
- {
- "key_seed": "E9D8098A1D31694FDE114CF400F7764AD8C0FF66C489CE968DC9B7F85BCB6F29",
- "ldt_key": "1A795BB7754A1A31A996EC6030233FB84B4181BA661B57AE7B260C319E5EF336F221481412F840B7AFF5465D21EA64123232826F14F826F10ABA4B6AA44D0ADC",
- "hmac_key": "0BA616BF14EB74E612C6FCE4FBD88F73E95979D4A44C9FBD25ACE1C4E0868161",
- "adv_salt": "6092",
- "plaintext": "1A9CF3075EA6BDF46397A57F0A41A95B860D171CCE953DC8B164",
- "ciphertext": "839AC0809777EEAE830F82C8A1AF249362A88A8AE04EB602A682",
- "metadata_key_hmac": "BD3DEC90EEA8EEA938D7B70F3E4CB03985DBB8A4FC429820E7D04AE44355F3EF"
- },
- {
- "key_seed": "DD22C884AA53111113EB1871AA76F4AB1E123AF3DA235AF41E26C2761247035F",
- "ldt_key": "119CFCE6CA9EC347F888D48DA820672E76E950EF1139DE4E1BDEC1B16F5FE07CF7A1CDC71AAC4924A2A261424559D8726D9AB07056E1561F76C36CFA06B2B503",
- "hmac_key": "EB93CE75F37A29618B11E4BDA7840627AF0AB75A9E506B248881A5E5E3CEDBBC",
- "adv_salt": "E99D",
- "plaintext": "A566BBECAF6B53D98F48E3768E3C4FCD17FA02AB734ACA89CC55E8",
- "ciphertext": "56AF055A77CEC1CCD64731453E9F51A3A240CBF7956C8D6EA4A7EA",
- "metadata_key_hmac": "785124888A2E5C6C91F1168F85ED5C8948709203D55913992DE0753BD5A2C424"
- },
- {
- "key_seed": "72027EE164E7FFE5B33C93DBA101C199FF334A23BB8D5FF08CA90246193C3BC7",
- "ldt_key": "1391D93AE442808B2C6959B795E4758E1110A2AD154339B7519D48756E95FF6B9CA7FA77E3A14262D7C6972752C24EDA69349B67350EF8C8290E4FCD4162BAF3",
- "hmac_key": "8BF72986ECCC3C76AE633DEE05E1216F1BFAF4DF9AB01B251F83DF6AE8D23EC1",
- "adv_salt": "36E8",
- "plaintext": "2E6C1172AE990F9ABBC99E8D6AA4FA026081AE7B3777C8",
- "ciphertext": "DAF3A5C9929D8528CC0FB806AB8FF3FC12FC5325068AF7",
- "metadata_key_hmac": "058AAC41C80C05F1EA135B0DDFE1C045B63D2B374546BB4727AD58F7D5384209"
- },
- {
- "key_seed": "08370BB7E2746114C0D804852CD16233CEBE79649CD0894BFBD90DD8B2466687",
- "ldt_key": "A71C6B8922C28557DCF3745959FC18304B114429210AA9D1D35F447A7B7441952D051D139C0A56A3E238C8F28165C1AD54D5923652B105FE1EBC96DBC0D9A58E",
- "hmac_key": "2BEBBB42C76CA69E1E113CAA7F8C3F69480E37EDADA82906CF262011F246CA41",
- "adv_salt": "3265",
- "plaintext": "2C3AA9912DFC6FCD751F022456E01D93107F3C5D4C",
- "ciphertext": "7602E0B3F97FFA39D8B3D65D2728AA181404CAC20B",
- "metadata_key_hmac": "6833E4FE6D719ABABDB8B174B6B3555F85398AB47707B213A8AABCE2416A0401"
- },
- {
- "key_seed": "F5444EC6BA43146942B5F030F68C17C2FADA2E254301F17D4E5D49D89AB3BC48",
- "ldt_key": "3EDE8097F486AAC75C15A0EF41ACBE4B03BFEAD57A0A4672886BF2A4BA34E9A969FC36060833741A9BD789C39356ED413885EACDF6A0428362BCF7DB7813628C",
- "hmac_key": "22563337EAB8375B41EF2C7CC64BF7601EB3078AE2D9D9571BBA4141187F825C",
- "adv_salt": "F10E",
- "plaintext": "18B2C0DEDF90B749FD5CE7CB01F3722565",
- "ciphertext": "3E753C44334CF07794D7873A0CE293A415",
- "metadata_key_hmac": "83ED296180057DD15A77268FCA4DA0D37EADAE91131E16605827337B96318A66"
- },
- {
- "key_seed": "B943C8D6155B53C203E332355CB329D31E28EBDA8C6718EE6280D366E89FE592",
- "ldt_key": "AA9A6DF6D3FB6739804D6A34DE6B5155E9FDEE5045328CB9288D8F6CC0D1FDAFAD6C778EF2A5DC054046BFACBDC5B7A135AD89FEF0AD7466AB509F8CFED6FFD3",
- "hmac_key": "DFD05D449A45276E5338E23059A4234B73DDA785BBC6CF7C2878FDD22936E7E0",
- "adv_salt": "1C2B",
- "plaintext": "ACAC175BF4ACBEA53E878C9830040AF5122FE5686F2F840DAC45",
- "ciphertext": "B180141F52F59E2F8A3584395AF96F189A3538BC429890A9844B",
- "metadata_key_hmac": "425DD0A91CF7BBFEF03FF25908BC83967D978B4A4062FBF9732767986D6DAD85"
- },
- {
- "key_seed": "8CE06788376B0F29A61254B3947C09B169D6A3DB105B1ED640A6876B6B5CB18E",
- "ldt_key": "17B8CBD01F10EDCBAA9D94B82487142FF22899A3B09C76189737DB0A31CC8778FCDE98EBC90512A9998A8C113B01C270EE46C9A19221413F844E0068169A7C81",
- "hmac_key": "A09521F10A21C680D426A4C306A6C6C283B7CFC8B935318AA425C1181B940F66",
- "adv_salt": "7AA9",
- "plaintext": "BD625EAFA89F56091A5EF8B6A8364735785C2109895CB375469BA3",
- "ciphertext": "BC94290458636AC9FC480582C6DEABB5AD4323BC4D10362A74FAC9",
- "metadata_key_hmac": "A4F3B70D27ECE46376EFBD49394A464EF561CB3BA46F044D3D2CE55297E19DE2"
- },
- {
- "key_seed": "0B04668FADF3FA0F73FF6918544470590955FA30D551139990047F1BCE8838CA",
- "ldt_key": "DDEE63D033D1EE3EA7F109E65CAF7324F10AA2CF311B085BB59F0F256231175CDBA6D9BC1C0B81DD15549DA5919915716066342FDFAFA2C9B7E3B5F0791D6CCA",
- "hmac_key": "048FFA66EDD1C4DB6657273D5FEAECD80492D1D00250F8B0C5DF4B56519FBA75",
- "adv_salt": "7266",
- "plaintext": "90C3E1BB82CD5737B438C91BDF8B0228EBDF6BEF",
- "ciphertext": "988DA579499FE0736D6D5C251E051612080DA671",
- "metadata_key_hmac": "92A81B7CD801716C336E9E5FEF64B7EE2B2DFCA4D53575DDD76A3029CA2AC9D0"
- },
- {
- "key_seed": "49C8C4A431A2E01DE854151D3D337DAB5F9C9D8D8AD3B2C775FF94FC570D27CC",
- "ldt_key": "09C2E5E543710567B739C1ED0B4358B0CCEB8FDFBEF3F59B97300DD1B0B4E7F29E4D0C2F1E0A129B21CCC9BD34490B693309C6E1EC6FD8EA67D21D52A07278FA",
- "hmac_key": "0E01AEEE004555F1FEFC9CE595D8B63368EA1FAFFA2042E8CBB54256AF666018",
- "adv_salt": "1CFC",
- "plaintext": "8C5639623074CA6E565855F80E57B78B1B63CE0DF851A0EBCFAA",
- "ciphertext": "B4D655F34DE514064A496A3D72DB5E1D9D68B0994BAEAF308445",
- "metadata_key_hmac": "D93C61B9DCF9754D406E93FFE8620E5AB31EBD2C1FA736FE60EE8D67DF5C6447"
- },
- {
- "key_seed": "3BED7222AD9E096EB49C6D0710BF028BF2267F53A9D5724E31F470848A627669",
- "ldt_key": "7E7F49AA201451143832E3B868F2C71CC3FA37A92A0D39CB401EF1DD1DEFC1CA4E16E72CE72D04180019EA02847EA4D537DB90C6C8761FC8CDD3F5346D4EF0DD",
- "hmac_key": "CE7D36E89FC7F46E1AF8AF08C2D3263B33BE88CD0634F5256635D3083AA3DC9B",
- "adv_salt": "F3AD",
- "plaintext": "A7189A5E8E1BBB745424823F2388703E75D4DA0B0A52CB4AA26A855F3F93A3",
- "ciphertext": "5617A9ABB6BCF3C7D4C2265BDA4FE80376F3FA5830E1664DF53FED228AE275",
- "metadata_key_hmac": "14FDB3DB7DE52D2622FAFB810545E7D92540E2F86B6536F926E2AA24DCD2F8C8"
- },
- {
- "key_seed": "2192A18C6776FAE8AC7D9D9121CE294CD21613A8647B9EA1705A6585C550C398",
- "ldt_key": "DEAE697B586F054E174FB6120981945C2B35F8B2A488493E7F6394181B8301D1CDBF14C4063D34DA2B86ACC5D83254029F04DA91BDCC8D7FB513045067106274",
- "hmac_key": "53B28F7F5496579FC377DB08740E197A515356E9C39D1334CCD5AEE6B693EE77",
- "adv_salt": "AB44",
- "plaintext": "8FB87C83B36F8FF88F70001C78117961EEB97F10072C722995770A91FB22BC",
- "ciphertext": "7D8AACB23ACFDD7ADA8838956AE109D124E45B1468A1570E2F81D51A18F534",
- "metadata_key_hmac": "1224414289B1D981F35D8833DDC9C2AABEB4EB2578B5033A784CC3E7F21FA16F"
- },
- {
- "key_seed": "690895E0A5EC222CB659058323865FA32C27C64B98FFC1D75E2A1F8D216C7454",
- "ldt_key": "AD3A82914B649DF5F4FE58F221F686703BEC6F3417AEF7A6AD0B9939DDF82EB8FD928387FF09BF0AC06A61DA60CB3CF947157A0FF1EB36165C67748229D99F0C",
- "hmac_key": "97FA5FF2E8C978FFFAD438E3307C2A3EC8E8F9AF37E2E943562BFF9FFBF9F353",
- "adv_salt": "CA89",
- "plaintext": "B7C8FF50A1B64418FC8907489B0AFD76C9D6E0E746D6",
- "ciphertext": "DF168092CA200F9439B3D2CB65CBFACBF94956805999",
- "metadata_key_hmac": "BCDC98AADFD5DDD75B655888ABDD084623BF9AA657553218B02243D0D72A094E"
- },
- {
- "key_seed": "6EFAFC8A2B67A573D8386B82219B1DB6D1DEC72A684B2AD08F38796790545C7E",
- "ldt_key": "02D510206C3677918DCDE9581AE6C979E51BE47ED70E6119A6837197619A5F8251740D6E1FF383710C24032A7AEB21E7D46ABB18E47C74F1BB64CA714D311035",
- "hmac_key": "57EA566577E2CE06CF55D79AFA153ACE4B0B39092A89225DDC91760AB92346E8",
- "adv_salt": "3858",
- "plaintext": "10E157598521A3CCE5CFABE235057C7B569592",
- "ciphertext": "4AC6741D891D0E09D9E0DEFB81FF2421B9A9AB",
- "metadata_key_hmac": "081CF6AA6FAFD27C0E27CDA06796FB5B160B03575F8B1820EC6B2ACC68ACF57E"
- },
- {
- "key_seed": "240D21616C0322C8A79E261FB1B06C9EA51ECAD4725C9DF014112B42E5070963",
- "ldt_key": "3650F42E5787CFEE207F2B786DCEE041AE1DE12484E81CD09A1BA49DCEAA7B38C797A0B1633794CB9E611471BD78D251FFC2FCA2B2491C73A4695E1CCAD7213E",
- "hmac_key": "F7B6BF48015AF668EDCC0A85DA1E33D446E201C15A4F70FD539C30EC7ACFE6A8",
- "adv_salt": "1D17",
- "plaintext": "CDA7CDECA0C584DF9E2F9864C550460BEC6E1FCF63B168DDC62D",
- "ciphertext": "DDD038E31B2C3E1C6DB66DF4F7B03CE7237D744CB3909ECEF225",
- "metadata_key_hmac": "8AED7FC5A7A63BB8C91C89A3B6F7D5DFB0AE983D82C3209155E9977C13B03DB5"
- },
- {
- "key_seed": "60D8D4726733DD96CC9E5FAEEECD4196E56FE78D3B9AEB26F177B089712ACB34",
- "ldt_key": "475E701D85BD3F4A1908F7870A4E39B78D16A17C6F05F203CDB8CCE8FAED2D8A22052F9FA6B4231DFB7ABF2DAD7634BDA0F0F8EBB59D2C4067772B89B2B5D443",
- "hmac_key": "5F8DF4E0D61820FD18EC2B0434982A3ACC571D8354E2FD6F4404D1AF8AC822BC",
- "adv_salt": "41DE",
- "plaintext": "3D8CC8FFFBED83787AC49AF00BF84C5490B9683F8161237726",
- "ciphertext": "CF8B5DE010250E4E1A80527E158E3826FB48849405EA452D08",
- "metadata_key_hmac": "F28EB59F905CF8BFFAB4F23FB0FCDC82B1AB924C8FD7CAD0E6CFB879C62749EA"
- },
- {
- "key_seed": "0E8C64270A07290A9DC0EFA078AADD96E9D1A43D103B856AA1B8DEA976F8F772",
- "ldt_key": "7BA2957697E3150A70FAD3B30DDA9F834155AA7EF40D3903DCA5C886E363276EC5A9A93658A3E664614355680C7D5A79094C2B3E83A1C41DF2D8477FEDE9D69B",
- "hmac_key": "3CA4A27153D5191C0DF96409700FB8732AA5DF9DE2167DF8B8712BD29B3800F3",
- "adv_salt": "6B0C",
- "plaintext": "588EB15D532943DEE637F9DE79C2BF96FA65A60FC5291EBC09128B2C",
- "ciphertext": "3D07E71ED78098251B8459EB228DEC462E5E728D86F3582C4F539072",
- "metadata_key_hmac": "FAF4E049053E3C4F0EBF797D9A7472F2712540764192AA8F433D4AFB94B22E09"
- },
- {
- "key_seed": "42F8351A1D69560CD77080D521CA43C5AD2B24D27511B4789805788AE0BCF490",
- "ldt_key": "A05B8EAB1E8C8BEBB7A9DCC2D77D10808228D001E04CCFC2632492CF03A2098C17C84F963447E8CE52D0AD502E08FBD110B5D95A119A857F100ED0125630D68B",
- "hmac_key": "AC5AF0BC153DBEF528AC24830ACE0B353D2AD747FEB6CD6DFDDA28D9FD73B6D7",
- "adv_salt": "978C",
- "plaintext": "AC987AC3A3845214668FF091FB092D7C9C6872A8C6",
- "ciphertext": "651FEC99084A6219E9527C06A25A5DBD96BBE1D9C1",
- "metadata_key_hmac": "40AE7AA8F795E8903D79BF5EC589573EC14EDF944A5979C039E0767278B4B416"
- },
- {
- "key_seed": "5F516164549CE07A61448BF6EA3B67E76808EB48AE9E23F5B9E613B3BBC45B01",
- "ldt_key": "2F4638A5887B8C79A03E9F9A70C8F180521E1C89C296C6C0570BC30F9E209939C925ECA0A27B98BBC3598C0D643F2769B57C19E388FAAB1330D51572E919807E",
- "hmac_key": "E83E459818F888B5FFE944CE4F1D1756D2A085FAB3792BB9797D235288CCCABE",
- "adv_salt": "EC6C",
- "plaintext": "E0A9E1D478B779FBED7E380BDDE984AEB0776CBB94F1C708",
- "ciphertext": "EF04BA529DBC8203952A5F2AD743A41B676A0DCFAF6CEA76",
- "metadata_key_hmac": "76AE54AA59CFC319AB05D759871CD008336553942FD2A642CDF3F45F8A42B81B"
- },
- {
- "key_seed": "91F1D07519065501D139BA56F55F6C8CEF8C85233516B0B936E5899CF72EBE71",
- "ldt_key": "1A82F91509DF4EE2E741F3F924AA7C62328B93C16065C0B6079881976B9DEF32D41E4CF1F49659D7E1AF844CE256B6CEA3E7D0FAACB9B97E2C6767D2B8E40A6F",
- "hmac_key": "238A78E2EE24D904B795861B48AA742BCAA972F243B83B7B2F1158830A793ED2",
- "adv_salt": "7C93",
- "plaintext": "9C0C8F74EDCBCFB5E649542B4B04AE09",
- "ciphertext": "ED697BEC17E787A69B647720206A0032",
- "metadata_key_hmac": "8D787A4933A982DAE8C76C0B8F04E4AF6EB045C83B93D0BB56F8A4569C5CFC3A"
- },
- {
- "key_seed": "7EB08E042F563BAB1B08C337FB5E14F4F0F354250E971BEE538001B0A158701A",
- "ldt_key": "57DBE2259A6768BD83482FAE8DBCD1E31AACF13D5022AB6624DE7D9AC4DC998F89BD40B9CBACEC52CA3ED1E32F850DCD7D54DBAA7A5578AAE432ECFE37883168",
- "hmac_key": "0F1FDA0693BF6EC9E80520CD9806000E5783EA4E09E53A708703FDF721ABAFB4",
- "adv_salt": "46DB",
- "plaintext": "581DFF6D784E78297EC25706288487AF",
- "ciphertext": "3B911D1850819B6BE678262388279C4A",
- "metadata_key_hmac": "97D98399A449715181459285F5392DF0293B06B50E5215B59EC59D0652092FAF"
- },
- {
- "key_seed": "BAEFCFD20965FCB31EC2F5CFEBE82A1EDFAEE89B05C8E1A311F4CB704AFE12D6",
- "ldt_key": "BF8CD1566616D6B4035F0949793763D15757E349A0C94117B36B984D94D222634D3ABD0B1833DDAD4B40B0B2D4DAEA7E74E841E615788FF41EFB4C327E72AD1D",
- "hmac_key": "D40E45D2A0469BF466683300C941CE16CB1D87A9F5FCCEF01D2BB820D7E60B81",
- "adv_salt": "BE51",
- "plaintext": "25F8CD05696A1F6099E6B2DE452268F075",
- "ciphertext": "7B10E66E465C2C1A39E3DCC44F0CE7D488",
- "metadata_key_hmac": "326475EAC59CE0AD57577BBD956E70B020992BB137E49DDEA8881A9A44171AAF"
- },
- {
- "key_seed": "F2CA31F350654CDE5B74EE5F935C4A89D0C1A0DAB7EF4C940F45B3470B42AFE9",
- "ldt_key": "A1F1F050B609110C19AA8235E15CC371677CB635D33E3C957F6AC1EEBD669055E2AD6589D1E5B866CF82E15CAF7110E68E6383064DE8841CD6B3FFB1F17C6C7C",
- "hmac_key": "6415731461E9996D3F9D0D17048C174A063C68B0371E7DC7C6BAB8D82D87595A",
- "adv_salt": "A847",
- "plaintext": "242FF7536CAB0CB695C3BDCD5AC4E1B362CAF4",
- "ciphertext": "BA117E5881029A9B26BD648573DB9B4EC36678",
- "metadata_key_hmac": "B86B1FBFC83B0847AC8993FBB4FCB0978D6EF2E18D163A3961D9D2A9B32B2377"
- },
- {
- "key_seed": "764FD24C13DD413756DCFB503B37E896009615A12AB362ABA3516898D5449E4F",
- "ldt_key": "E34DE7A73F91507B51E1E0DD90067D1D32B10359EC5B23FBCC01FF7BA2347C845F2F2FDBD34ED4F5F888A8266FA9324D979089DA3CF79A8DF7EBFF33F8E5E5E3",
- "hmac_key": "55A7F81A9A3FB890D9BD10D02353DDB7BC2A9414A924F42B43C23820A38D9DB9",
- "adv_salt": "A1B6",
- "plaintext": "ACDC0775AEC80CBEE306C5F36F8BEF3F66",
- "ciphertext": "CAB049A35D67ADCF8BA23FF998ED67EDA7",
- "metadata_key_hmac": "E61FB791788A97BEA07650424CF5C897CB06665D96F8895AC7D3080E352ADC26"
- },
- {
- "key_seed": "A7ECE890512661E1BCAF21F66F733E7C06A12498DDA70EC36B72C7A202B2883B",
- "ldt_key": "D70CD4BA93ACDF5EF1B6E2D20EBCA2598D7D1CF1B22C3122D680C97ACC775BD20A927C4FAD167C8EDCB0F0F995682DBEB0A411321816BC849B71A4A969A4473E",
- "hmac_key": "F7F38B6400532458E17684828BF6D9AFAD7A9177B3EEBBA1227DA1933FF0EE15",
- "adv_salt": "461E",
- "plaintext": "0BC11C317D3FD1948B8783C9C00A7C1E37E7027DEF80AF892CEBB3",
- "ciphertext": "5A59E809B78706551C63F32A0BB3686DBE0542D7881DEDB605281E",
- "metadata_key_hmac": "9F4877F0F0847E54B9FB0E571B57BE77C86B3916833006A11CB167490589CC83"
- },
- {
- "key_seed": "5F6A6CF006136009DFADAB2F093FB7F136D765DDF5A2C81162D5A1B0DB978EF4",
- "ldt_key": "31461D55765AB8296F890040A8B496EF8A11583CB2A65D985C89B8C07B5692E1D74005C621F2DBDFD9999D27A931E63DDAC0E647DC812AE78AC6211D365CA6AB",
- "hmac_key": "6BBB59A6D1741A403106DC173FA2D7138757FF2ACDBA25BE9F9AFE83F3CA29C3",
- "adv_salt": "49E5",
- "plaintext": "E176DB23CCF2B4276F45C0A032F3EC5CDE",
- "ciphertext": "EBDE72956456209FF27F57FCE5539FC655",
- "metadata_key_hmac": "97F3DD6FDAFA648CC9372BB4D58F1E5FD763F7A79DAE21725351E577016BB302"
- },
- {
- "key_seed": "DC42457FCDA6BC6238F94F141544401DBF37CCF75D171E0424B9E5A104C1389D",
- "ldt_key": "5F5BE22616E1D10A50C7E50D96E7CDB312AAA3811AF691ABA49290AA4653F95B3D8C95C989BA527C07CED74993025BD2BAE5B963A7AF88B739DBA504F5E0F7C2",
- "hmac_key": "C7C972C1800D641CF902DF6D742D85A07B0879EA9F57CEDD461211F408066EC3",
- "adv_salt": "5D45",
- "plaintext": "9827D36FD0D50EDBBC84430D4E6D459019E52C6B53265FD085FCC03BB5",
- "ciphertext": "5DF869641548FE4EDFEA08ACFE87AB3AD0EECA666B14BC3741553C6417",
- "metadata_key_hmac": "3CB01C6B898D25C2AB6141B05F165C971DD03D283455417D590EFCB119091824"
- },
- {
- "key_seed": "6E02B012D2C249B2B3A8A187AFFA634A3D696814165D091294733CD0927CB79B",
- "ldt_key": "15C6536795D92A5C8CDF035FB945B095791FD54F2D42E0C10A7A544B58D03E5DC9FFC82E90B925A7FA906E588BCCE1BF022EECBFC8BA5ECB534344448DE2EB2B",
- "hmac_key": "34E596C2F8FD02E55267B6CF77FF6C9C4BCD70C4062E164518909773F648FCED",
- "adv_salt": "377D",
- "plaintext": "DCB1F0DF300EEDAB51F7EB13E7B1A34ADC87",
- "ciphertext": "56ED8FFFA1F5B5E8D14FE31151D9B9FBCBA6",
- "metadata_key_hmac": "B30E6439D5E73BFB2575201D3783D56D16A55F14E531ACBDDFDF22A8F50ADF68"
- },
- {
- "key_seed": "6E7FD0556DF2BEE0A5E8248E6BFA09777B09ADC99FA9248AE0A203BD5E72D546",
- "ldt_key": "4E13BF3B07D851A2452215C0BA7DC3680A81E75D9740D2ACB7E423EE16499DA8F9AE0A248AAC834870A83DAD8F556BF3E7F7EAA84F3210F7BF88A87B1E2CA4BC",
- "hmac_key": "FC9B78FBBC96AC247F87109C8DFBEFDF72FA5DEB5E7EF96ED32C5060E5AF4C18",
- "adv_salt": "F269",
- "plaintext": "6009A2AC45C0D72067E2590D93D656898999336182A9BCD158D6A7D4469AF3",
- "ciphertext": "48B5502ECD3B4FC6D5C55EAB2CD5B7C598B69F8E052C13177468E28823BE96",
- "metadata_key_hmac": "2F7A1BFCA065947FF4B5A3727E56AC1673F7FAF45144F8FACBA428E9EBDD2691"
- },
- {
- "key_seed": "74D951408C8BDF525D1D122600DAF1CF13379E219E8F08719025ECBB4E958823",
- "ldt_key": "25ACA926D0CFF03E3E4035ECF250927610D16E65E78FCAAC886E252053C85F3D819CBECCCDBEEF9EA9FC7286B51EBF945FFFC7AC1666BCB0DA6FFFB3052CE3B4",
- "hmac_key": "E519D08BDE2252F9E3DB11A175D8E2501F4F2C2744D90D585B35253EEFB7C254",
- "adv_salt": "8EA7",
- "plaintext": "F429B81E6551A1DFE75B69E5005C3442",
- "ciphertext": "DDC34E29EF3EE45AE97EB004A139CE61",
- "metadata_key_hmac": "986AED3A4CB8E42128404558252C29659C0ABB2485C0EF58A91944CDE00C6EED"
- },
- {
- "key_seed": "5015B6F3FCB89171769E165F0E843830DE54F1EC1165A7D263DE307900E90AB0",
- "ldt_key": "DB2DCA12614D43E732D4B086967E15C20F673B49BCAC18F49D51889D90B77FC9A0C3CEC3CB1E9F7B0747829FD48B3E7A8FFB5540E02DF4A4F71EF7B70E03BF55",
- "hmac_key": "62DE7C9DE3694C01440F1C3556DCAF94342993B529EE67C84DAD118CF09BE050",
- "adv_salt": "E58F",
- "plaintext": "AEF9ED706F57423ACC0E1F8C1BDF842B5CAB1596198A75BFDCB0C69B0936",
- "ciphertext": "371B68A65E93153D072B54294E661A02B5F9F4141C698EA7AFC948F5DDF2",
- "metadata_key_hmac": "64D84E07263743E75FB9B7A3E87F1D52E76204C6DB72FDFF4E5F809A66AF6586"
- },
- {
- "key_seed": "D598D9A12E4F0A8A488856DBA25696EA28947FD029EC2A592561B857D1DED9FA",
- "ldt_key": "3E8FB54018EE15E884ACFD49D0240347FC603675F33F8838D105FF54A17B7FA2A5A7F4998AD8BCEC49910B3B0532445E4312A704FE3D84648844A688717E2EDF",
- "hmac_key": "2B93A7972EFEBB2E34BB47F1BB10A5B4EA6D31BD2D674203EFB254FD0BF6DC46",
- "adv_salt": "D530",
- "plaintext": "D28432AA51B8AEA7BC1BC033DDD4BAC4EB9CC293E1B491720E75",
- "ciphertext": "7C30ED5B699760EDFF31AB48D13623F248A2DD3CD6A361B5897F",
- "metadata_key_hmac": "D41699ED342A9CD6E34CA6330747693D704A68D22FD46CE3C75133C97669121D"
- },
- {
- "key_seed": "A9ADB74C0E8791A68C9092989F1C6C0DE5D614865FE5C7DE91C16041556E09C7",
- "ldt_key": "B9C152B54C4BFF46C2D352D1E071748B4A0F0D6FC22FA9ADA2A88837294D4D6BADD4C8C13F1A52EF55F5181CA2104B9DF6C3A5B26ED4D4BF45905F93E9BCF51F",
- "hmac_key": "E6C27FD7B3731A0337A8931652EFF05B95B051EBADF4CCD4276061018F290582",
- "adv_salt": "47BC",
- "plaintext": "540B9EC366CBA5BE0437722C0ABF1A30E3CBC81DB3729689B6882A6B9D",
- "ciphertext": "2BE37903CC20ED58C5ADF967AFFB4AAD095013B527F61DD5BDF89F920B",
- "metadata_key_hmac": "DB5D13407A407CF26BF0313C0F11867BE773FF7299291458BADD747F09912DC5"
- },
- {
- "key_seed": "BEAE67A8AA47199BC2626358AA92356D7473F60A73DC30265DB47A707005498A",
- "ldt_key": "D8CBCB1562E9946CB438F42AAFC07FB595EE60793D00FC0681D186A005097C80F95DFA32FFEB82DB16C9FB1BFDB9D5B9BE160FF3738C627D9757AEBE7AF8D91E",
- "hmac_key": "0729DB3AB37CD96D1661EB3DD8116CAF20A260823CA388A67B04F471701E3ECE",
- "adv_salt": "2950",
- "plaintext": "8861EFAF5A608F48DDBC8DE9435CFB36050B912A183F53310496D5EB",
- "ciphertext": "043AE474186769BE54CC26C25475F48B09ACC8FD108B95840E20C564",
- "metadata_key_hmac": "1557A1A917F983968F88466017507F840F8E388D3913F438D73A02ACA566B48B"
- },
- {
- "key_seed": "4C20E2F0BD4B9341954EA544D3C1BFF1BC1AED34D9EFF6255E15A33D3DBE670F",
- "ldt_key": "2C6E9939B31CF4765BDA652A30EA2CD707D5F72C15BE420D2F63CC0DAB2B00CD6302FE19994394E7B693F19BFF9152901CAAF18D28C4BD1E1951BEE884BB254F",
- "hmac_key": "D94029B956FB35034E791AA9FB9766E397A2C57D3C5E83D74E48076DBEBD55B3",
- "adv_salt": "2793",
- "plaintext": "4D8315DE8F870E78BDFF588C7162616AA8855F",
- "ciphertext": "0A861982E4B1ED29DD0A3C779F8A0B8AB5BAB6",
- "metadata_key_hmac": "F4B14B89F1BC2D21313F1EA5F5D244C2FD6EAA53081FDC09A0902AD4FA44A2A3"
- },
- {
- "key_seed": "0428D107F0FEA47B7021417DC1DF0607572FBE3EC7B97D1FD8F3679A926D6C27",
- "ldt_key": "22691BD03AFAE4FC52FF1FDEF7C671E60F4644675F27F9DBFB28595BDDD81A8FAE784C70AE2112057AEC12D09F20CBF5198CBD53525E78DF313360C3D49FEB02",
- "hmac_key": "0E5384D5D2241FF235CCCFACD5919E8879F70BCB7A900B42FDA0E3F03C86EBF0",
- "adv_salt": "FE63",
- "plaintext": "4D3D218F5480049B1918C912A10ADDCD3B",
- "ciphertext": "587268C07E7CF0FF60A3FDA6B108DAF9E4",
- "metadata_key_hmac": "9072E1C59708E079DB8B3789ED79DD90406EC0D9EAEEA56DC75DBC6A13AA9C32"
- },
- {
- "key_seed": "EE24B4EC86854A85DFF752BD1270C1A920CD205E87FBAFAD14AF978B5F16756E",
- "ldt_key": "E427890B5E32F9043D248E8728F3BBE1BF5339409793805BF4344F911E3348039FE966EDEDA82BEE3ADB02C4A9AFF042DD38E4E763A6A2B114460FDE2D5991CE",
- "hmac_key": "57C8FA94E9775407CAC93D44CDC7F716B8A959C9AA3C6FF88299B516E2F74B75",
- "adv_salt": "CD71",
- "plaintext": "84066CE197807B83FE2B2D2892E4098A0425AEE5F4FC90AF4A94D358AB8CD5",
- "ciphertext": "4A6BE739FA649F638A3A8094EEC4AC50D11A327366D05B5767DD604B787883",
- "metadata_key_hmac": "88D3FD6B5D9EC9DB66B3155A1F7B4DE660BCC60853661658E82B549FF9AF2669"
- },
- {
- "key_seed": "7D21D8BDEE373CA89E39EE7C9DE191DDFFB0992918AACB07EFF882084985BACB",
- "ldt_key": "6BB9C764A30CC4988B129DFC2402550791B6CF5099BEC18BAF1B19F36BAFF442BDB96053F7B987C2D882ADB049EF28ADAD7358DA038D85B7417A2F034800E157",
- "hmac_key": "3C8443399346EC1094135DFE58EE65658D48A8B93F8DA066F09A435A70D31DF7",
- "adv_salt": "CAB6",
- "plaintext": "B33DA61D07BAF9B8F5AF7E504297BE12C79C938FA097B31A41297E9165",
- "ciphertext": "5703407565A8FFB6EED122A705C9AB9DDAF22541DB24D261F696716B4C",
- "metadata_key_hmac": "DACF0D1AFA10BD4A2786DBDCC290FEF7964357D70855DEE46981D32ADFFB2D57"
- },
- {
- "key_seed": "C123E2FF68ECEEAC94D594907CE6974A36F4CC631A0BE0CEE93BAA6C15FBFFCB",
- "ldt_key": "316F01C153E839FDF26FA0D74C10A13D18E8DD7581A58C4567211F823E8911EC7AB560E67A504C5C48EA79D9AD4662F32EF10EA2ABD72C09507A3DF0F3E4EA8F",
- "hmac_key": "5490A44983A6CCFA1DE2C76DB797E37E60A09AD702E7F86A77340E3F5987C5DB",
- "adv_salt": "9023",
- "plaintext": "9B3E8B549CDBB75AD0A6F090979C6E24AD",
- "ciphertext": "975D0BBB41386C42FEAE347B54242D7FED",
- "metadata_key_hmac": "1EC47F888CFEECE4E291E2D3FC3B6F87E2C11DE9DA47199788E0014392E79B72"
- },
- {
- "key_seed": "2B2C67B7D89E349E24C4F5E1AFD45FF95A1B2A7B830E595BC20C1A46068BD07B",
- "ldt_key": "A883A57B567D2E962423204782D9EFC1DB4641E5293FC479E81417CC4EFFE4FA0F87C3491967C895D516E3B66EFDFAAF4F26F918ABD4FEC56EF3E62E0CD3ECD3",
- "hmac_key": "D39A023C47FA40C496B4EBF2C1219561ED71C66908457A5997C775BB1E02FF29",
- "adv_salt": "0F89",
- "plaintext": "00F4A71C855F57F6EFAC2E7ED25214BCB1C15284",
- "ciphertext": "6BBE11EBA309FC866465D350F25272BF0EC444EC",
- "metadata_key_hmac": "228AEF9DF006B5BFEC0A9FFE3625F6B235825BB6EA05A507967A29B942AB3ADD"
- },
- {
- "key_seed": "91E81AB6F70CF4121D6FE686CDE42376D55F2F174C3DEA72A2946183EAD3B5E5",
- "ldt_key": "37B5CDE4F6F72C3F218377D2EB79D0F0E294FA1CADFA8F3A8F172D54EE8D88109466726D1CE45BB6841A289C32E425531D6F924198995AE792EF588C42058C9D",
- "hmac_key": "C3C4D8918CDB5F9EE2B35467EB69E13209C688EEC0BF63DFD899ADF6DAB03B1D",
- "adv_salt": "D1C5",
- "plaintext": "7B1365B8BEDE25B035574DCA9808295253254E37D6AAE8DBA1C4A581",
- "ciphertext": "5FCD025698AFA623C607C407E82A5C98A2B64C79D43013C774FF1423",
- "metadata_key_hmac": "25ABDF4C2383532C25A1AC8E806E05EDBBAA6FE842C56FC7F88D2CE75EC8A6E1"
- },
- {
- "key_seed": "EE6A34E568DFBF3A5A9B32D70D94B9EE942ADDA00686772B82917093A86C5289",
- "ldt_key": "41DC0598E99AE88D2A79CA87260734BA5E57DA6C90348EC54519574C9ECF23333B930D3EEA7F7FA9DF2587BA1A06BFC2DF380FC36B7A4342F8AFA6BB124B4D97",
- "hmac_key": "CD4642B18BE5FECC7B1D921D47F2D554C55B5370A0D78623C432AA8A1048CE75",
- "adv_salt": "96CC",
- "plaintext": "5464BE51555FE377829DDD56FDED674C593F39E98469899AAB9700BCEC",
- "ciphertext": "0E9802D69238507017A128C0F62CA5296C5503B9D7F733179C4DEED7C4",
- "metadata_key_hmac": "6166BD27C01EC510EB4980665D1EBDA18B19681449E737D01E638A948CFF1F8B"
- },
- {
- "key_seed": "A1C4F866463ABEAE3B89695876BB45C99D23E3ACB1D068F87D8DB31F341D895D",
- "ldt_key": "0A33418E578DDDB639E805FC13C86B0C705E228D51826FC24B9FF4BBEBA22C1EA83FF06ADF09A447689DA0047BCEC8314831BE2101C3DA1CE73E0AE02F202720",
- "hmac_key": "E5DF138BC655A647097FCDFFFE015F537541B9445CC940E4D641A45514F3DB82",
- "adv_salt": "888A",
- "plaintext": "5FCCE80B66016827725911C5ABE47A390BF69D",
- "ciphertext": "5415633EDAC291005852AF1CA6583A95906F34",
- "metadata_key_hmac": "7BB6CD4201900FB4F391F6480ED3AA2A78A25DFA7BA8A16689CA340C07CD305F"
- },
- {
- "key_seed": "D8A4255015CF363A556B381DA4790049C061ED7C11149F0AEE1E9141CE03AC6A",
- "ldt_key": "B1190DDA0098411D337011AEC09267B11E68405370DD91D351F6BE67C824363320D2DD23A0B590CD20039A730A0BD6F8FA90175DFDF1A5A98603832F4B5181F5",
- "hmac_key": "6D1B62F94A91438C33F3273F207C59E0AB08ED0EACEC4F1418926866B5C861BE",
- "adv_salt": "BEB6",
- "plaintext": "9CFE0C86BB50E90886500A72FAEA88323B26E7386BB4",
- "ciphertext": "18777B2C7370AC03333F5A05B9DBB83C0137B9077347",
- "metadata_key_hmac": "F26F84D886B914A646923108D1A392EDDA0EE1BCB56D5E899768C3B2A335A435"
- },
- {
- "key_seed": "75578C951F23AE6C3CCF311D68DD3C524D65644CF9A82C6398ADB4727F5ED46B",
- "ldt_key": "20C0116F5AEAC61C6C4E3CA4B7700EB756DA622AF5F4DA51D1D65ACDF9370A0476182DC58348701B99A2DF4A0E9E07EF74DC19C689DC147D11ECA05F8B0E34B1",
- "hmac_key": "69619FBABE43F9E9CFE6B64D9564672B729671046F5A78769B29464A64F111BA",
- "adv_salt": "C570",
- "plaintext": "1488352BC697DA5C71582EAA21B20BC9998C31",
- "ciphertext": "84B518932415BF7E07C2A2460B2F36446F6FEF",
- "metadata_key_hmac": "9352A755CD0A8064C976391DAEE7EC78527040090E87B32F17B3745311C36257"
- },
- {
- "key_seed": "83E1A954689B3BD8AFBF0AEC3EE3EC1B657BF743FE76413874035C7995F2F960",
- "ldt_key": "FD0DCACD090CE274BDECE08B0BAD561A49208E0B3F3032470DF8626933FCB130C4E852DCB4AEAF52B1CA2DF3A0069600BF002CC3EF68A26046A10AD2CFBBA3E4",
- "hmac_key": "CE59C98C8B3AB7AFAC5257375102F2305D8B4F00EFB3E7D40E7623923141E78D",
- "adv_salt": "6D48",
- "plaintext": "F97B454F80F09422EE81B8FE503A326EA5E54AF6A462049B3D8AEDA0",
- "ciphertext": "4F10B0C217DB9F00CC5F0691244AC05AAD9F08475BFC91A06C6E5A0D",
- "metadata_key_hmac": "21CA22611549B11E465BCA95A74DAEE7B93DD317498D51594C7D3D9DD45D8289"
- },
- {
- "key_seed": "05F9E0BF2EBE1CB1E20EDA23E96A63F4BE0D5B75C011C4C8282D927B598C5263",
- "ldt_key": "F7BA220C37CE316DFED9C7EFC4FBD2FBCC492B0270FB6CFBC1BA52B8232BA30DCA53DFB98A66D0E4FDDF1125BBA5D5C16403BCE3F1A48C2C76C3088ACAA3DD5E",
- "hmac_key": "F221E83C2C2EC96672FCB4F15D9012D6584FD3AADC3D4B8401AD18FB058340CD",
- "adv_salt": "3151",
- "plaintext": "1A1B88D288B24E30B539BC482CE7FBCB087989FA263BB67C",
- "ciphertext": "9EB0EFC18F8160CA53E3C2F6969709CDF95FC41BB0EF1053",
- "metadata_key_hmac": "1B7C7D810EB0F2812FC676E0D26A6968E0532F11CDA74674207C3E33DD08C4C6"
- },
- {
- "key_seed": "B06D3B5E08517380C5D05E74D6C2CF9064E1330367FE57E32069471297EED707",
- "ldt_key": "6B6D3EAF8576B12C7E48499F0D8F771425A2270FF97517FA515B83A546264CFD48DC0D87C860606EAA033E2FEA773822486C18954EE6EF850DBE20332C1A4AAF",
- "hmac_key": "1EE07B7EBF0D85AE3CA14AD3D9050B399A33E8F692915FA6F7C420D5A3664E0D",
- "adv_salt": "83C7",
- "plaintext": "55A8E4FD6C23ADF7E289A49B71A654DD8BA050C922D89CB4D2A3EC1A07",
- "ciphertext": "5C4539AE4FEBA4D4FD85946B6CBA331573EA19AF2828E61F2291CBC39A",
- "metadata_key_hmac": "11179074A88D201DE936BE9ABB924AFCD791F7DB800FB9251A4448EFA4BEA4CD"
- },
- {
- "key_seed": "C9398C533D870FEA8A29F98EB8996D2BA92AAAFB077106232365AA5E4EF0646B",
- "ldt_key": "16FA6B9971E2EBDAB2E8BB92A081986E010C7F386D6DFE60AA7F220EE795F87F59AF06FC0CB5D5B7EA75B8A37C2C5FE993B17395D08870011A2FAEE733978F2E",
- "hmac_key": "C2282F638AEBDA6B6CB83AE8B1489BA2C3B20552F9123D459A348E4F943E2A0F",
- "adv_salt": "33B8",
- "plaintext": "B56E6E43F2D788B6F217F1663AB8514EE70EFEC7AD869AC5261E5682FCD9",
- "ciphertext": "35D05E1A88A98DA68A2676681A3495A6979E6944B8AD988263CEAFD2B618",
- "metadata_key_hmac": "B6F26E91255AEC398D66FB7EE1DAB398654E543A78A719A44BCBAADA7770A96C"
- },
- {
- "key_seed": "1A999861541652049627B5DCD0E2236AC38C4B2CA22290F43F8D998B2E9B4549",
- "ldt_key": "A8A813AD61E173CBD1724174BE86F41F7359560C27BA4FE3DDB99FAC7D8F9B135D7D6346D15725767B1E90ADC11F0801925728298F8850A3DEB6CC05EE0CE337",
- "hmac_key": "3486787AE01E544A40F361473BDD8A0DE037E4EE38C2F0F1EEBE2878020342E7",
- "adv_salt": "C8A9",
- "plaintext": "0728727CB69CE3B4D08D099D34D6B32E398FBCA49FA8AE",
- "ciphertext": "6B8108D9BFA4C1FB7F8C2FF38DE3301B45C35BFD2BE5A0",
- "metadata_key_hmac": "A9E4AD26DEE22F766BC1966A4C493F22BD3CCE921E460A70ED08A4582AB9534C"
- },
- {
- "key_seed": "F005F6CDEA5C4CD79FA5CCADF94BB2232E42B65EA39F5A9081922E549B6C0415",
- "ldt_key": "0628D0A94B9FEA0AB7E70961E597753B5C9F957933D48AE4ECAAAFABCA46636C30AF9D3C5E193DAB854C1FF98FD63FA440CC5FA4E7343E88385C1BB2D928506E",
- "hmac_key": "2F9B3BEA74B33186D4423FA662131C8D3621C0018B9797629D176F9E58023190",
- "adv_salt": "CBAB",
- "plaintext": "84AC4A1F18981A7FC7280E72841618C5C801899E",
- "ciphertext": "B8625071F50C5B735F2CBCE1732C01FA68FCE684",
- "metadata_key_hmac": "C2D54C7E0890506A757511E66E9B49FC0839A35EFABF430A3B793AFF68D0CF2C"
- },
- {
- "key_seed": "8F6FD538EEFBFFF826070841DF3B7A574C085F294AD59AEC77A3D761220F1347",
- "ldt_key": "CB48028D27A83F82AC955EB015C2427F250265160FE720F498113A0356DF38078D11BF84866995185F8C89A6AB2347BCE54D56538DD3B58DD72B4D4C1DBFB109",
- "hmac_key": "95D248567D50E175A6DB7300C0BDE8DCC9B58833DDBA791F458E8656249F9344",
- "adv_salt": "7D9D",
- "plaintext": "E5B8D20B29C2B14898568EE81763EE2D7733A6FBAF95C0A3FB345816070259",
- "ciphertext": "4ECBD65B155B3B8066FA968CCE9FE28499EADF27DC7A9B8A2B0F072A10B704",
- "metadata_key_hmac": "9420F0E1AA0390F1478EE5AD093CECDC77A545EB0A3CD32CF9681525000F5E3B"
- },
- {
- "key_seed": "777E054E4E9D47B655E8360B43F29604614558622F0BD3C9E2D45B0A7D9D9B61",
- "ldt_key": "9A93510F97B92E02C654232F2D22EE5A460EAE5115B27B1196016731B0E1F3F0388226805CFFC8EE744856412F866F7E9C090BDE960DD100F489B978CF3C50F5",
- "hmac_key": "15E2921C229F0F91BDE0A0C87C1965EBB631D1E8E39898DCDBE8532ACB5365E9",
- "adv_salt": "4791",
- "plaintext": "EE7A2F25F8E682EB2A9AE573D680F3935A40F3F5F0C09849",
- "ciphertext": "D48581F2B7F2D96D8223A947E92EE90AD058663CDA950BDB",
- "metadata_key_hmac": "952CC226F4A9893D59C4E306CC8BA738D8AB37703FAA4422982CB656D1CDCA61"
- },
- {
- "key_seed": "60837595D85FB629D9C94564C683F91170D9F1120A126BE9BEF9FD198E712E81",
- "ldt_key": "9A53A09457D566A1AB52E1B73F7F005C3AD82D8C9B671742C6658C97E794C84F2E84ECB034EDD080C36B5051FFA8B948D25291001E5AF5512EAD90FB54AB1555",
- "hmac_key": "5EDED01DADA1BBC98C7596D5D299C2D1C902C8B63831DCF4E7668BD7B8AE02E2",
- "adv_salt": "D105",
- "plaintext": "46832328CC47013E8EF24208CB027B2031FDF89A1A1A",
- "ciphertext": "FCFA6EB4D3625B7FFA881388C17F6A6750DF527C4C9E",
- "metadata_key_hmac": "DB6F8E7099F77322B98AA90D085F2CD1229AFD4B5F9592D3C69F93E4FA6B0379"
- },
- {
- "key_seed": "F24BD20F93B9F0CDC351E890DEC97565B469517C96DDF73AE3120EB1BF34844F",
- "ldt_key": "66F36CB0686BC1972703A65C16A3BB8DE8E964DFB7E22B2B5C871BDCE870E46BECD135B1867687BB3865148ACF8D4EA4F8217941C21C657E1B51825332AE3B3A",
- "hmac_key": "8B073262374BC7FEC473CA681B3AD64C3AE244168806F8B3333D7B055BB63993",
- "adv_salt": "36D5",
- "plaintext": "13AD32D79E13E89FE6068C2639D0A979DFC817ABF5EB65218B",
- "ciphertext": "EE6A0C64E67A56416ECED8212D26A8973D9B7A96749E470F77",
- "metadata_key_hmac": "FD13068038BC515477E7E3D01AB86CB3E93884A4AA04DAA4771AA702A38869B0"
- },
- {
- "key_seed": "74F59D94AF08B4B8AB90E8D5BC160F5DF494E3BD34238383D0BD18703CE07F80",
- "ldt_key": "E5A98C82CDE85C7AF8BED6D7D95AE2968A182AD81A06834ED3AD6FF8849CC2FBE296C6610018D7DC7040CA1B553A10D00F730A6419E26BE425F4EA060436F290",
- "hmac_key": "ED1FFA052E38A9A0366531AB6E25E6102B67362B295C124A308AD3D0E98B1C94",
- "adv_salt": "7CDC",
- "plaintext": "EDC98AFCD4EE6C877AD7066092E9F605FD37D5",
- "ciphertext": "1756BA7EB250C8B22473B5F417FF130059B965",
- "metadata_key_hmac": "BE98F9AEEA113198E2BAA617F5A3EAA65B96434B4C3B6C7B22270F08D03BA565"
- },
- {
- "key_seed": "50A876AAA9F8292147A039FC3E5AAC00D796DEEA9690EEB7A1F866056B272041",
- "ldt_key": "9664B36700A5B5B0A04D6C3DB8E13E283793CF0616C5ABE0C26B87BD88DD6399959F7A76621CC66A9DB42868489C22EAFAEC1C739FA279CCEC7167DF9936C2A7",
- "hmac_key": "8219103E7D149FF294B8DC21413AB8A711565C32F10EEFD2BBFF5FA39DBB026B",
- "adv_salt": "F185",
- "plaintext": "3B01D21EE1335C2961FCA707B9CB8AB6EAE05C9F1BE9DC3E65EFA67D6623",
- "ciphertext": "7BF18402B2AD55BD4375E3241FDC995EBF8BCDE50EB9AB53ABDEEA883A5A",
- "metadata_key_hmac": "C225A9BEE2A7A1C387D6E531685A93A3E63DE2AC0FFED415FD20AF973D6A2021"
- },
- {
- "key_seed": "7D0093DF47228EB2691A090BFEBCFCC8F9E0B3E43FDE8BFDA95401F77EECEB8A",
- "ldt_key": "8C59879B57A3DB8FC0B8FFDC4A16FF67F86C4A9F3F9E9183070E063B6CAD120AC97DA26B458391B2D25FE65625578ADCC26552B03247E7502986E10FBE347A9D",
- "hmac_key": "6C66B9EC7C0D201CEBB547E46E641237FD3E7398D7D48B751D981C100C700B26",
- "adv_salt": "B84A",
- "plaintext": "669D7A54C2F14B36FB548C832A4A059551D4AF17FB591A68",
- "ciphertext": "11089171A34F04BF56AA50D68C05BBF6C8363D6713E26920",
- "metadata_key_hmac": "BDA541B3F1A92DF61CADBFA8E6044F40CF5C4E9B8EA9E2D286CA3785E63D8EC3"
- },
- {
- "key_seed": "8927B5F048DE267FA27E92F311E6C3BCB1194BF61D84C254928BAD9C0701ECD4",
- "ldt_key": "D1784B9250789EA84E380FBCDFD22CC056083D9FF9B7FD5B121A7935D33C01FE9A754024EB157F011AF36F1B9C3BA7910B802EF800052D8B01FB5B6DA0F5E1DA",
- "hmac_key": "AA2C9402AE194A0840C2633BCC36B92EF14C18118C5A16FB6F9759FC03F1DFFD",
- "adv_salt": "A406",
- "plaintext": "76F04514F35F08065D95152315BE28AB78199784",
- "ciphertext": "F4EB95F4D9ED24BD4F09377FF8E346E835E71E72",
- "metadata_key_hmac": "2A34C9D12BC1C1A3C042AF24C62FFC724A233547B25183A890948DB0ED410E99"
- },
- {
- "key_seed": "AD74C330596E696ADEAB9A2326F4868D96BDF091E1F627FE9C8DB408302860B8",
- "ldt_key": "EFC11D296B8DE9BD0F9938AB79C082F8A1CB70E99BA23868C192AB18BDD7335C38353046E9F9E170CE1864929D7A26E37686D2D730A712E3E1EE01997C8618F4",
- "hmac_key": "527C98ED723EB94CB2553F3A5BA140EAF6185EF41BCB277081AC1F5B31346EFA",
- "adv_salt": "0F6A",
- "plaintext": "139503855EA1C1B7F2CE931658F7C14B",
- "ciphertext": "81DB57063A383C64545D8DB9AAAC3269",
- "metadata_key_hmac": "A78BCA4C18924966424CD15A2171FE6C8F03CFE528DF26E91DDC8DB7AD23D9B7"
- },
- {
- "key_seed": "7649A2379FC17BCC384ED99312C1C8D0AC41E5A3EA5A360AE529E8B2261E0D9A",
- "ldt_key": "198CC9B6D844AB0A84720CD233C7F00453077CD1433D393D8216F2B9174794FBDF3CA972F46E5F2AF67E9F3F4D2E5CE62A1C90B6E44FCA21FAA116DF1C0813C7",
- "hmac_key": "2A2F072409F89924AAD7AFE26786BDB94AE2E2E7800EE70F02D92530316679EF",
- "adv_salt": "50D5",
- "plaintext": "0745372B0D70EF170B7313CD01EE17DE46C5E051A6",
- "ciphertext": "5CC44403295D7076D6AC112FEC1157603489524D32",
- "metadata_key_hmac": "D91DD2DD184E0488F50A410775CFBF3ECC71FA1C937080D2639AB85922E72A3E"
- },
- {
- "key_seed": "53C687E04BFDCF68AE40C325A93403F6015B5018D8760E1087855EEABECD19A3",
- "ldt_key": "B062AEEEDFD4B60B92628D7A86FAF9D5D4C4E5D9690767B149EBC67769EA0BA1ED993A6A3FF8EEEBDF6180CC90EFA68D1457EF15AFCD6091F1B16DC1B9CBC84E",
- "hmac_key": "02089D1F302A82EDB1D45A2025924FEC0BA8D5BDFD20DE67E7C7447A24A0106F",
- "adv_salt": "1B8C",
- "plaintext": "F3AA313737A8A88B621E16B5D1B69AFEA0C0EFBBAC97AAFBD9",
- "ciphertext": "7EF8464BD3C38BEFB7D7F02B01D9FA021785D5B0E461D74F47",
- "metadata_key_hmac": "219AE24B436C915BB07CBEDEC1CFD0576E9EE9ED89F6C07BDB66E0BDACFB1C3A"
- },
- {
- "key_seed": "5EFE256D37F99059E05CCE98C91D8FADBF0F061E9BD3B376E80447E6C25E4248",
- "ldt_key": "0721773F9CD5316A17C039BF9AAE52DF2A9F4AACE58CE86EFD1DE6DAC555C1E787F22470F3E5464B8FCC518BA2D80D83FD966B2BC45EBDBF9868DA5EA6C28AE2",
- "hmac_key": "59BBEC4E253D0FA3054C9BCA71EBACFB6EE42C05E0E6C1A1C14C2B0FCC7E2D7D",
- "adv_salt": "9536",
- "plaintext": "92B2C0A7DDBC3FAF112B39D70150DFFA5AF52E9B4ADBC684ADE2821F32AA",
- "ciphertext": "CC47D95B5A23C5FD1F052642291E8D6F33F23B0DC1169122DC1ABBC2CDB5",
- "metadata_key_hmac": "F23C783AF1CF6A0A95FB2F5717E09F50304E76E0655E5E6263B84BD1D359AACE"
- },
- {
- "key_seed": "64590CB65521409A16FA0142F16C2350D4E178C24FA77BEA5D14A7DF4D1D7B10",
- "ldt_key": "93FE8120B98DFC948B4E42A883EF866E3BE29557B54E9CF37271731973FFC8FE0601EC6DCD1883E6B7912041545407E047209D319CA4C57BCC466589317649F7",
- "hmac_key": "4B28172CD3030B80276ADEDAC85869C4482C5287EC1F01E36A22751991D31BEB",
- "adv_salt": "305D",
- "plaintext": "F4821701BCF875B3BEF2AE661F71D1A1CC8EA1A6B63E8F9C",
- "ciphertext": "D127ABD7C34A2332A4786A1FE59A5D9D210A70F88441FD6B",
- "metadata_key_hmac": "50A682324878F91C2116B8887E20DFE9FF9093A1FD53D48D58A2FCB6C4F37558"
- },
- {
- "key_seed": "7979DFA5770617C48C39D48B1FBD64696A74AB82AC17847B1C13538DA1E6C234",
- "ldt_key": "2F494794600809117F931B90A7E7019D6B253CFCCB3E8C0691BF59213C3772F75277CBEE0CD443C7B6B68052A2E3D139AD3E7C728A23452291EFDB348C47D1AC",
- "hmac_key": "9DF39A32A8BEDF4E8BFFE09AAF61C0BAF2A1B2446877C5BE70AE79BCFEB089B5",
- "adv_salt": "4644",
- "plaintext": "9F814D4BBE16AAE87430462F1A7CB2897839196C7C",
- "ciphertext": "43A656D2E2ED336A6ADD86DA0F841857E3267F5F0F",
- "metadata_key_hmac": "D49688B199580C37CD2D67D62F81EA7C18B41A3815EEA2A2D415CFF03E884F44"
- },
- {
- "key_seed": "BDD0A68D2B25032DB53FD4015B182F6590F95D92316579AAA2549DBEE309436B",
- "ldt_key": "CEC5F5C2D9671A6B65839370E07DC7EC9A069D4F36169A35D1002C869FA70CE2A1DF1DC3B5DC94F9F9C3FAFB37964539CBEEC38B59CC202D2693E21A7D424EC0",
- "hmac_key": "0D3A4DAF27CFA08B3E08F8D4977773DD5002D5A3DBF0C73F5EE43439655A69E4",
- "adv_salt": "274E",
- "plaintext": "5223AFF8A98FE589A49520C98C37E6159D7BF41B73C697D6287E",
- "ciphertext": "1E90493938BC297E539DFD4F11B0B4CA17F7517A2A1221289CF0",
- "metadata_key_hmac": "04782BC0AF49D03FF62B08E5DC656FF9B764178C2E1AC122E2079C2424FC97BD"
- },
- {
- "key_seed": "8B3DFE65D57FA3333A13BDB5B91AB5D1F6D18141AD4ACC3A508852DE8C161046",
- "ldt_key": "F4BC7BE52635084EB8D416E1A8A56DB127EE7D01B23AE935DB485963141E46D2C08DD0F7D571FBC679C60CFC296AA223DD7D2737F4AB16F974D951D20B32FD6B",
- "hmac_key": "AB56C4D61C11D5D44F6AECF314E2C1007ADE2442293F4C0F62B4C66EC80482B2",
- "adv_salt": "D03B",
- "plaintext": "FCD4F39FB98A19E96556EE968278F96BC143BF4E2AC5EE3A7FF6A4",
- "ciphertext": "46D9E7E7A91A891B8A7BEB61FCD19E2BCA61DD807D29286D529ED3",
- "metadata_key_hmac": "145148C46BC3E355777C7BCE1694FA6D930ADA73F828C3EAC3D756F1A519C884"
- },
- {
- "key_seed": "86026B320DDDED39A605D69D60617C6B2FCA91C3C56FF331BF05F6C51ABC431E",
- "ldt_key": "999B5C2E8EDD3A1BA956D046A697F47708D45625076FFC1AEBDAEDF7919681A00834BD8A9E5F47BBB13F7317D0D8A27BAB632BA60598074DE6AC132BCB93FBE8",
- "hmac_key": "BAFD9A03AB8D977CB058CB99C742EDA9E295ACC9598A08E05AEB9AFE4D83AB74",
- "adv_salt": "65F7",
- "plaintext": "49562E3817E27EEC4218ECF02737C5591EFC6EBA7E",
- "ciphertext": "8AA5E712B6B68F6BD8E43C66AFC092F7F70880F654",
- "metadata_key_hmac": "2B602D3DEA760253D2D80924E6A83E7FF48C1C0F31A635EF8B8A8333B1176354"
- },
- {
- "key_seed": "2680FAD88620C707EF5E04C0B0AED68379F9CFEB108A9FE86E38756F3AE82B14",
- "ldt_key": "2305211BA329041A58B9E7F7D96DC136FC0A81CA566480873175F39279EFB0583C2882403B38FB9B7BA1F3DE8C0B500C306D9DCD1AE212D93260A4A2EBE42037",
- "hmac_key": "2DB441BC80B1EE16897F77EFAD57BFCEF638B756EE0681E20D865758B0785D23",
- "adv_salt": "A53B",
- "plaintext": "CA22F3F10ECC21286044F85308DD1A36225EB06F318A62E2",
- "ciphertext": "1B7E3D6EC50515D17BEB4D11576F51DAC3F52E84FBC74DBC",
- "metadata_key_hmac": "7F3DCA60378438BAFF2D2BF529EFEC3366864382C1022E6530A283B0B964CEED"
- },
- {
- "key_seed": "DB2AD3D8D94E698A43AFC03F0A81205D6C6DC80D08C05CA80504D2E46FBF0B6A",
- "ldt_key": "7F73778DDBCC4E86EBA264E9865ACEFFB4ECAD01BC24CEFEAC2615B6F83D21849E976751818C280C06C446B8725B456DB9B9DD88BF760A12596D438F15BD75EE",
- "hmac_key": "C4A64729CA08DFFB6E8A7AB92DF03C295DE7A34762150EEDB033B891A9E12660",
- "adv_salt": "DD3A",
- "plaintext": "0D9139631372A349ED682389B37E6CD4C753A8ED6C6BE8E8E632092C0C56",
- "ciphertext": "BD97B92A8EC5AA9A64EC22786538D1A4D101257AFCDC2FEE94A813C95D09",
- "metadata_key_hmac": "47BAC1161AFEAB767F0D9E4C31E65190D7D63B3A652923BC844239B7A65CCA10"
- },
- {
- "key_seed": "6A8E2419B9C33CB50277295749BC8416BF5BC53734ABFC8C3FB5835DB750C8EE",
- "ldt_key": "47E8CB93888664EAC1A75B677B1229ED52F9BD57C9B23A6525D497560D831D5873C1AEF57152F97DF0B11712B037924A4930A989ECC715BB69735B7BBE1040BA",
- "hmac_key": "F1200A73068F7F97608065FD0A63A531F12F0D5D6B316A009AA3633FC06BB622",
- "adv_salt": "0095",
- "plaintext": "BD8463AC015ECC567E98298AAA43B4CF985256F430CE40",
- "ciphertext": "F23D667AE8F34C70FD5E1A60F7E76EA32C756910B2DF62",
- "metadata_key_hmac": "B8D9EBC74B2410C22236AD72A06276C9873D876575D2A8B166598826E4BC1EF2"
- },
- {
- "key_seed": "447CA7AC4EC4AD1D34D077FAF0F712F32490A5F175F6686B7CB279B0D1EF6F59",
- "ldt_key": "69ADC0054773C67B2DA71B39FE755210EE5902EAFDD5C459AC9F0BBF4C670D104252A2939ABECD63F651BACBD4BA9CD2F7173970522CB9DEAB4CDB55CC77215D",
- "hmac_key": "7E2A0336C7D5D1006779D522D840DE08B623F42640F28736DDB6C8D9683213F1",
- "adv_salt": "AD8D",
- "plaintext": "DA502E834EE6CAE72683CB69EF30635AD24F59851D60242A0C071FC1BC",
- "ciphertext": "741DDA4BD7C7169ADF907C71A31908D0A2E7150A2DACE4AB6B820A9BB1",
- "metadata_key_hmac": "832E565CAA78115F1CB3EEB0D3F445E58115AA02E973CC0C1DBDFE17B5E84BC0"
- },
- {
- "key_seed": "8E61ABF357541542C882AE154496B26F9D372B3D10C08EA89337D3EAB5D1E19B",
- "ldt_key": "D259C70B97BC97B53A69A2CAA8AE29A14E00D9052B023CFD0FCB51627B23BF41BD73BC345D483D55E3A96986E83702AA9F921B0F13E916FBF916F84AACB49103",
- "hmac_key": "3EA948A39CEC88FF2D445DFB5EE0F59FA43213C646072E01752F8582B8616CBC",
- "adv_salt": "673A",
- "plaintext": "D416E8684BADF6C6E9F8EFACE100CAB859FB",
- "ciphertext": "BFCD5685E421AF7ACC2C7F598297620EEDF9",
- "metadata_key_hmac": "8E7A56D294210B30A1B4A251A95F92CD752EC9C6CDA3065F5B4A991768F215CC"
- },
- {
- "key_seed": "449A1D16EA9ADBC4A2AF44A53E2473C99113CFE66DDB93E351B0E14140B83881",
- "ldt_key": "40650D278B91D804BE0D9EA4F5D4A89D5CDF9175765A84093F36809B4868B76D08A17645540867143DF93623DCFC38B1741DE2D9176EB1D45DE70F5FC339F869",
- "hmac_key": "2A5B0EEE434721352A2E9806DBF5D4EB7A43E5DB3AF54D9A47CB7BFC67BF0330",
- "adv_salt": "CFB6",
- "plaintext": "8D328EB10CA6160ED71F0EC159931F939826FDD2378C4BD6F974FD78862F",
- "ciphertext": "A6B2A8084EE4A30AC6DF3274E5F120F0B978E7DDBD087A71091842E63830",
- "metadata_key_hmac": "8FB61E59723D39142DA9C7E143DF2EEE5D759171615AE0B43CF2C3838C660716"
- },
- {
- "key_seed": "BFE6A29D7441AC00C35E682669C6B2325B4CC367986A6EAF480DDC41E739BCF1",
- "ldt_key": "51A8536DA717B0615F8BBB4B9FD283645483432076E404E0CDBEF17F44C695001207F5E90F9BEA9C7620A592B1A3A76BF3A48D50D290A6B8DAE18DD049B52911",
- "hmac_key": "74266AED9E569E3B4FE366DBBAECFC87B0433D556483D8781A1DDBD93C383D08",
- "adv_salt": "A2D2",
- "plaintext": "6C8E5D0796E02C038C6D25A2998C9F9B",
- "ciphertext": "A2D8DE0FCED3FEFBDE44D26D9B33C366",
- "metadata_key_hmac": "998AE16410607A68B197B084A724D4E8B645EC2DB46F532A3B268B41660A9780"
- },
- {
- "key_seed": "14675C8D509F1C9BA8F21B20FCC3F3A64ADE514C855A2FE9D40D30F0528C39C4",
- "ldt_key": "EC3D89187D94A21BA267BAA8A31D73762A7E5E124DFFE9E9C63AAC620A7E74E6F97099E8C882C6D3FD02ABB30185E70305672C889A5F61B5AC10D4EF3549519B",
- "hmac_key": "EBA940DD1649A200EB310340EE57B004F61C2FF41F59456FD103A56FC53B9D7D",
- "adv_salt": "D9FE",
- "plaintext": "F8A1CE521C4A43DA283B7B9D08F665A9EE31",
- "ciphertext": "BB2968F8E2861639629136B31AA471926577",
- "metadata_key_hmac": "803B4F21A55CAFEABF53E090F0F79F0A4DB71723214AEED719908B905B26E483"
- },
- {
- "key_seed": "4BA996FEC8C6A4017A87E3E32DECD8961DDF206C4555E1501216C10C804BA971",
- "ldt_key": "F07212C784C6D6FAE257C889BE9BDF9A3B1B35979ABF0F722FF490E95CCCCFE26EB91F6429818D49DF1C67814509A55046D670E379EE3FD26AA11B40F663E017",
- "hmac_key": "85BA2AC220066E09866A29B2452078651F28CBDF3068211ABAC84017218D9576",
- "adv_salt": "D9D9",
- "plaintext": "9D5E90E9B4F45BCD4081E08332788BF804",
- "ciphertext": "47B069DEC4E944CBD1F52E8BF5BC20A2AD",
- "metadata_key_hmac": "9B8AC2F67DA6B24B163FD82323A71E822B94F9DC0D75D43472FA89AD46DCA753"
- },
- {
- "key_seed": "55AF213D2853178F29F6C8F7E6CA2EAB13B5C8D2C5FBD156245F9106F34A6FCC",
- "ldt_key": "6AC9F5AD053645993FE1FB8BFE62B92F6DE5FA72C5ABEEC3026B8724D0F0E37FAA79C93B9D5D22FE304E3109E32C720483F26706F98E0371391C94AD32010706",
- "hmac_key": "48F8258BF98C92A3C15AB67FD073A498E5B8F17E7208F57B32A72AA790FF3E45",
- "adv_salt": "3E3C",
- "plaintext": "01A6023AD07DDB0117B7178994D571B0D39ADAFFEDD6A5",
- "ciphertext": "B07EF173F1E9DF3C893705C3842018B4CA49BFA1C3CCE5",
- "metadata_key_hmac": "6A26E7663F0260C89F32B1F903AB1B8720C6932F524A8BFFB774390CAC1AE582"
- },
- {
- "key_seed": "D30DE8937872512C3C1AF385C79CFC51DD692C27EE0D114A980D0639BAAFE585",
- "ldt_key": "1DC7203241B5887272ADE390EC10F413EFD566CD676B4BC2A53E6621E1570CF6B401E2A76C0F827FC7E11FC496E8E94362217CBA881538945A0D59FF4EA84AA3",
- "hmac_key": "6CB4D5700E6C923D393F7D4A12DB26BB7297405C57FF69DAE7539874A1A6C847",
- "adv_salt": "E77A",
- "plaintext": "EA8F563093ECFFF7BF3C751ABAF402B3A1B6",
- "ciphertext": "5AEC616534C38A32B5746D9C85C388575BF2",
- "metadata_key_hmac": "93F9F68320220CE723583C25E1377EFEDC315016882382D55B366B787BEF3EF4"
- },
- {
- "key_seed": "75D1FF8290AE38CEAA8E14710994CE07BDB6377A77D86A93699127D7D0D5D240",
- "ldt_key": "E0CC15D3F2438F44E4ED7F6A775EF97A1274AD1CA4109D31406FFB4B7A59D65A5F928286D2E3884111CA15586C3B803FAB77249AE303DBE136BDBD493382BAA5",
- "hmac_key": "39B17C433601AD44119FA3C54825CE4BD4B2723170F4863F67A1E941ED8AFDBB",
- "adv_salt": "6611",
- "plaintext": "78E14770A3E0C8D21EBB6EC1A0A1335B7E83",
- "ciphertext": "1246E5060DE56AFCDA4790B9E13E14669CCE",
- "metadata_key_hmac": "2F603AC08134D5E3DF511B94DFB5EA82FC52D2270B814CB280B765E6A389B0B2"
- },
- {
- "key_seed": "6AC0862C64F27E75C518BEF4573E063617F0A1E1C581ED11111338A16FBC1717",
- "ldt_key": "2BD89F7DA6984B44BA013B9BBF8A9A5C5F97FD3C9DAB15A14F5B03305FDDD1807B08752F72AF883B9EBEDD57E93C764581508C768928DBA04A3BCE11354B60BF",
- "hmac_key": "63C68D4AA358B9890B34B55DA9D6130DDBC518B2E7760B00148B4DA56FBE6361",
- "adv_salt": "3EA1",
- "plaintext": "34B32B27597BBA55EE23E7AA8E90712C277D2C4A9B6DBB92E9657C",
- "ciphertext": "28302F2D55C4DB0D9F71318D886C094F2F6FF4BB8ED6EFABB1774C",
- "metadata_key_hmac": "7454C2E431FDEBDE6A5C1A2BAB3BB7039D87A0DD030995C6664BE378D8A0F2B8"
- },
- {
- "key_seed": "88FDD77B34197BBDE3CC14C16303251D9181A76536C29991863EAAAAF1F40721",
- "ldt_key": "DD7A188B0E94BBE1EC023D8B71F28E9D8544AE02ACEA30FBCDB0303D2AF56754AC5ABD2169915DE2B532A5DAAEE4B13ADC24FBAC31CF05A21102D58B724BCF95",
- "hmac_key": "1E12D7838F469C39A3EA9282405349BCB68399F280AF213811E57D52F30AC81D",
- "adv_salt": "B482",
- "plaintext": "087526DFE3D3334962F8CA4B998009602CC37057CBEF619F8CE914",
- "ciphertext": "F5D4509D6078D1CB847095474BE5BA2046D9856E27DC32B671D5B1",
- "metadata_key_hmac": "E196214CE72F93298AB49C41BF123B9228302456C8274D9C5606BC5B2FE7BDFB"
- },
- {
- "key_seed": "9E6C0A2179AE92FC60D643993C9B5542AE2BF20E919CB45925CA78CC35A9D940",
- "ldt_key": "965F3E30B055488732FE7ACC205A2746231536C2A388BE05B49BBF0D8E0C6E5FD10D5DE8E61AFB9A8E5E380680494AA521528E394FDF128E95544C2AEC9C9570",
- "hmac_key": "52DEFFC49F6D304EC1AE2148A42CF48151FFD84327A992038FC8B30CD62461D2",
- "adv_salt": "5C2C",
- "plaintext": "7B549EFF6E1B23E801C4A7E86B1D8D6C",
- "ciphertext": "397524005B8C859AB7437C03A7969D87",
- "metadata_key_hmac": "86C8DB2A741B5F4F4877776894D124180D8843C9F7B11F32981685797A17E105"
- },
- {
- "key_seed": "01C7B5FEB270C8B5F67F7F798039301E50FEA859DA976BAB451478054F61E60A",
- "ldt_key": "98E30FE5DEF052FDB673E2256CB5E5D6D77E9BC4474C347D57DE5064B17A20542C747E624D4526E711694A6FD0C93C6C13A3071B0DFFE5F77809D24D3EF616F8",
- "hmac_key": "E246C2771C7B6301421D4C899C112EA5F7A30F44CBBE4BC2F9F051470FD68036",
- "adv_salt": "660E",
- "plaintext": "4BD3CE67C5F2ADC18ED14B684670638A85D3BE",
- "ciphertext": "7AAD2A9F5CBCF1171D18BFFC4EE6401E844FD6",
- "metadata_key_hmac": "C67D9C1B24F31DF322487D0189CA4D8315C6A4E2377C4A240987BCF0609EDF72"
- },
- {
- "key_seed": "F4904DB0CB13270DCD9C13DC6A14B2E3B503D4B9FAD0B1A8C2770B2E05090E9A",
- "ldt_key": "97092F492BD2239364727408B91712492483EDA86875A326D298DB66BA205E2117AA6DC9A8FDEEB4473EB8C460BB19CB3111C8BC3E149ABAA06B90C64999D7A7",
- "hmac_key": "1F20AC6B6E2FB0471E43E4B1DBD285315E50D4C11A269197AEDB76CC06DCA8FB",
- "adv_salt": "CF5E",
- "plaintext": "2EC7E99BBB3A704467843FA7664C8E148B6C59F6DCB00CF99CB070315A01C6",
- "ciphertext": "BB16B8B67492AA2B227FBC4261F880D2F5598E582E7F304CFD213BB84A6E1C",
- "metadata_key_hmac": "773FA4CB401A01F5BB395A1BD6C3124B8B4273F2CFD12C07C7EF3776F6CDC61A"
- },
- {
- "key_seed": "EF08F824062BEF0A8379885E8A2531D369A7F77FCC52DF981CF45C8975BD803D",
- "ldt_key": "2CD67013A053273F3290E94327DB3779F8D72BC0419925AE248EA6DE838A2A9169085166365ED0726F2520920641860207A65C2B1776D36AEDA0FF253B6390BA",
- "hmac_key": "4F1673171A760C49728C6D42623D440630617659CEAA51F4406F4200BD0BA554",
- "adv_salt": "682B",
- "plaintext": "DC728BFFF7D9C28C04C194CE8E655DE5C72A68C709C1EE",
- "ciphertext": "9FC226D05CE13D4CDC6675B453124C58CF21CCD8A6686D",
- "metadata_key_hmac": "5F0BD38A5FEE13E89C572D3BBCD59D6906A8E2A02529E78160B6B0B665CA745B"
- },
- {
- "key_seed": "516D4CA6FEF5788DE764D7829AEA6CD87B66F3DC677E440391A39C2C75F5899A",
- "ldt_key": "FABE68B1BD045ED62A42A478983D0B5496BE7094AEB10C579FFB72DBE52B432A91A4BFD1CC867B70D8BFE542AAA1F70B1D1890A96742B60C3105D0DCC26DCA9F",
- "hmac_key": "84B1A7D838FFCD52EA99FA2CE46540C1A49473DA47D865A4859124040B3DEC3C",
- "adv_salt": "62C5",
- "plaintext": "5C262484CE732258C7C97EB7CAEF655A5C",
- "ciphertext": "5ACCFC002B86B8EC3E23879BFA4A2D6A23",
- "metadata_key_hmac": "A600A7048E963214232AAB951D5BD884833B6207433C26B07485591E332EABE4"
- },
- {
- "key_seed": "758C9C6357A68FCD50EBB014972FD60D66D0C2EA6E30D982AB492DD313A36FAA",
- "ldt_key": "C63861C29A721E1464BDB8099AE4429A9E4A6A0AF623A9BD22E2A72BB6EDC52ED634DFDC003C1C03BB39123A52BBDC32430AF54B6D5B5A9BEF490047282864C7",
- "hmac_key": "5E3D6B561624A72FE89707F9F95BFA7863737FA85134C14026902D24FEDA442B",
- "adv_salt": "D2FB",
- "plaintext": "89B5B7B59DC93D5568823BC33E0FFEB5B020",
- "ciphertext": "5D75ACC238F0501D30483E07AC68CCB5E4C2",
- "metadata_key_hmac": "0CD25D3F2762C2B5CA1E46EED22D39B4C97F08EAA4AF77FB40AB952A4C9421EC"
- },
- {
- "key_seed": "CF7B614C39F7C9D809D10867B102C69FA1F0BD2EED5E1C26A1D06291839AC194",
- "ldt_key": "E4F98D2A202F1396D39B2B5A97CA978E2FC65ABB12302A06287E48975B0CA92BE0F2E0C2E4E978E4D1A1D83F1DE80D588AD3F246BC0D733536B3994700115110",
- "hmac_key": "5496B1E574C92348AB6703BA4D70AAEF53466CFBAEC879B972DEEB9E27523EAD",
- "adv_salt": "183E",
- "plaintext": "298D7EE333860ED9A72CEC1E6EDDFEB923FB6EB48BC484B085895A5DB8B762",
- "ciphertext": "B1C3E51BF8A181295157919A52C60DC02B3F4E33F072F7BE486340F88835A7",
- "metadata_key_hmac": "3DF8E873299A132D7D0B5A0DB1CFF485CA89ADE72C8A8CD7AA5ECA4BFEC0B992"
- },
- {
- "key_seed": "A8F3550C8371089061BEE8B8EDC64F09B0F58580343FF879A554882DC9FAE616",
- "ldt_key": "342F4120DA408811C9ADC0A7F85C331C30B55A33E7D425ECD104C62E6D52F716DCAFB9F44EE29BC4EC81559682572030EA32A42237F3652F76648AE6E345D53C",
- "hmac_key": "DB63910B29395E65D5C5DA1A172F8246BED6B349E22F4B2C963F9A0B09E8EBC8",
- "adv_salt": "B16D",
- "plaintext": "76F91DFDC368BF8312BDF3AEBE961C817A41DA1930299EF6",
- "ciphertext": "8F0CD899DFF12A11843D48288E066F22921D374C38C44B66",
- "metadata_key_hmac": "6EDE5622C333A0BC90CC266F7DE76A5F3050D36B59844F78088D916E43EC9D11"
- },
- {
- "key_seed": "CEC4E08D1497E1273DCD56114CE693B46C5E883C90369C4D544D4BCF43E1AE35",
- "ldt_key": "427044439ACC208943B46E74C836E35E370C5FA45C51451FE51A372AB326B2BDEFE92949B6A6B9F23D865AF1CD08688740E430831CCE09F44AAE7A51A1D1B874",
- "hmac_key": "BBB2D08F9A8CB36DC8C4D2444080592B79F8B0F243A474E53DB36A17F1E2D757",
- "adv_salt": "205F",
- "plaintext": "3B66942104FA7299AA5FE643F85B3BC2084203095386E06AF42844AD",
- "ciphertext": "063BC36BC6DA593AA7DA9D271293A4FC9BDB23F7A50FBEB55F7635DD",
- "metadata_key_hmac": "B1E26FEC1DB4CDB1AF8AF4CE130E6947ACF8627C4BD253D2A90FBC8469321A9E"
- },
- {
- "key_seed": "A938967874DC769310EF18AF3720212C1A0C317C4BF2B9259C5D0F25A974782C",
- "ldt_key": "190AC6E0427292B54E2C8AE522D2FEDE65FE7EE51B1030B282869C243B253856F720713E5F1D695A9FB84F1B3B41B5B03F414C39A744C64EE084AB782A7C8737",
- "hmac_key": "FF4309DF5A621410CF29A79D888BB996AA6A1A8DC97317654500D02B959DBC1C",
- "adv_salt": "B0DC",
- "plaintext": "C653B412457A1E824D35A702341C62A6158B0AF17416DEFD26C45AD4B68685",
- "ciphertext": "F904FBA6CCC73F8678BDB66FEF230A1BD939CEE951CF5F0A309C80CB7D20A1",
- "metadata_key_hmac": "3E0EC6995B3CC21278583C36EB3131CD286A914372FDFB8BC60AF6A4EB21CCBF"
- },
- {
- "key_seed": "C4A063F997A8BEE12EF03654D5AB2103701DFBC06178CF024813563D60376D82",
- "ldt_key": "75F588B1D0CF0E6EBB36AD844FC64D70C095E1FEFC7A08FF6D6D281D0DEC16A84AF0122FB5F9AF194087E48539394F8F045CD3E73D9BCA8B9D6E81F56B10B40F",
- "hmac_key": "7D410DE31312FDD5BD22C27B5AD5406EF865981A55DBFF7CBF9C50814533C8FE",
- "adv_salt": "BAB2",
- "plaintext": "A9A15C93195D562D93FC862450B2CB51D5713FE1802A352D6A7FDA",
- "ciphertext": "32EFACD41EAF68E171FB5B69EA53E8FCC448889069DFF470274EB4",
- "metadata_key_hmac": "29FB7A5F82F38F5CDE0BD87C3C0C9F4F5D5C0FB3E94692CD85FFD9DA6D986CDB"
- },
- {
- "key_seed": "C59CF43DE156A32EF85FB2947202374AAD3A105A173C6B1B50D59498E7BDD500",
- "ldt_key": "E82A096577F720A8A992118378C10A3C7F770A7199FB5DCE9D479827F83B6A9B2654DDE018A56466E4DBA5BE06A052282BC05673641B91A37A1543843614B9A4",
- "hmac_key": "0B5E15435209FF9070BD66C848518C86E0D2A062ABCA4260ED996B902E8B3F1F",
- "adv_salt": "D85D",
- "plaintext": "60DC2EC2E103235C23884E45A9C2EF427A2E98D3923B576F0C1BB58A",
- "ciphertext": "9C4AA1A4604FB62790576EE6031576C8E9FC619A2F9E0D4349663839",
- "metadata_key_hmac": "DC075B77FC337232DC9395A38F3EDDA35A822000B6784231D7CC23511333DB2F"
- },
- {
- "key_seed": "A4C12AED69924E2223FDB1D8450A0DC6F82783E01521CC0C3C96E112FE000FF4",
- "ldt_key": "5C526E81E863FABAB12F1ED6CEC79BC2A79239BA1E2E53270EF9E5C7B5F11C5ECB94DBCA6133DA2901D32481ED0CE15FDD1ADE9856B1889453FAB4DCFC57345B",
- "hmac_key": "CD5891750C1D996F42B1D8DF01757164A8CD8811B36EF3057FA99165DB369A81",
- "adv_salt": "457F",
- "plaintext": "563AD9669BA177ADE51EE76AA74606746E3830300C43FBA4C6127F",
- "ciphertext": "9F725A80C60503920F816FE26D86C020AF959DE72819C389A274DB",
- "metadata_key_hmac": "F78E71F1EEDA9856D047B6C5B034AA4911121C24DEC49071F3FCCC9D56E7A239"
- },
- {
- "key_seed": "50EB78011D344239B5A672730375635028EE53B4BCF39F1EBEE2AFA0C7FD4DA7",
- "ldt_key": "C9EDCA4D84F83300442259B72C913B2352E974EFEA735984509C7C3C89511140113DAE1D6592422CDDF1380A4CFFBC2EFC547ADD64226F4725250037CA7AEFFB",
- "hmac_key": "A7FA7FFF75FB13F7CC735076BC6639EAFAB3B2F7A3876055A5769DA10DBBAFDA",
- "adv_salt": "FDF1",
- "plaintext": "4C9469FA5E6C3E423D991170E7B115CAE5",
- "ciphertext": "54BB9C1AE09F6369A5C02E5EE582A5DEE8",
- "metadata_key_hmac": "08A663EED16372DF10CEE203C8472FADC1B3A082ADB5F9EB54D1680389F2A7D2"
- },
- {
- "key_seed": "27D53BCE7DACBA568A39A1685F1645CD36AC503AA659A83EB0559F7AE9F33C14",
- "ldt_key": "3A4FCB00294BE8BC6913C53D92C13E51D9C871165526F32187E555B31022C3BB26A60AB46293C947CED45165A6FD08A7B8113E8783BC7555A5E883F65F5E76DC",
- "hmac_key": "66F9A512346EDE252444201B7EEE77E2A2BE2574F97092971DC1C27DA3812E4A",
- "adv_salt": "9107",
- "plaintext": "2C01BEB9AB5896B9A0FAEBAA5498C5B9A11938379AA709C386",
- "ciphertext": "E52A5E350B96CDEC882EF5557A3B35073A01921E8781D24CAF",
- "metadata_key_hmac": "4C8DEF8F58FD02CDDDE33615AA6DF31DF5AA06F2C44B6F7AA15512B4ABCE2A07"
- },
- {
- "key_seed": "6D33CB29D83E251854842D7C5FDEC63D72D40A5CF60535E663350E79DBB3A25C",
- "ldt_key": "F713D6D7957387932E6AFB47128E764DD8147CEC7E4222BE94BDF7FCF36AFDDBD735C5FD7841BD965800F6EFB7FA81F3514C58A536864B4864056824AE5FC9D8",
- "hmac_key": "8E1668B71BEBA3F0D410DFDBF89E21AF816A5A2D0020D81001A976BE50380401",
- "adv_salt": "3E90",
- "plaintext": "C61353BD81EC324DFC41C3A1B0388450B94B19DCAABE01515373FDFE3BDF4B",
- "ciphertext": "4BF8452123D8077E6548298DDCE40FE81CDBF7CF6E71C42EA41D3E6B8FBCE6",
- "metadata_key_hmac": "2A8B59911F0B67E1B2AB133F1DF940CCECEB7D2149CBE6B68B7AB61E9204BFAD"
- },
- {
- "key_seed": "E95A2C13227685460E6BBC7D00BAE0027F3BB83C89A8D7D9DA75EB2E7BE24C5F",
- "ldt_key": "07DCF561EB4F767F9A1706A5F870C734461757EA1E0B053767605FF97152C8014C23BFBFFF875ABAFD43E2900F813F212ECF21768970A768B0DF3530F2473FAF",
- "hmac_key": "ADDF6476780C628CBBEECCA568634C08A5B7BE6B8A50A67EE239B6C33E4EE994",
- "adv_salt": "693A",
- "plaintext": "7C73167198F8892EACDF490274257147BE8DF0E1387E7AC4",
- "ciphertext": "D6B8DC7EB1701B7C44ADAEA9CCDFBED04AC6708ABD1A0C23",
- "metadata_key_hmac": "440D97504963E18A99CCDC247B74916B80FAF5BC350872BF6365DA6A5334D23D"
- },
- {
- "key_seed": "7B7F89ED9698576B9E30CB45E8D002EED1AC98346BECB30259100C730C51B289",
- "ldt_key": "E858AA16B55C883F9BDC8EB94C25D17792D53D701844319FA1B854439B66FE8B199E5B78BA0B4B205F9D3170F2D6DC82333F8007680AC4F4B8E835C5DEEEE981",
- "hmac_key": "997AEE99FD7C55377EE7217B5929F8DD078F68D8B2ADF87FEFF1941954F7BBBF",
- "adv_salt": "5D20",
- "plaintext": "4C87F23FF747A320E0F23BDFF990DB02E944AE75B2F04EAA4693C7",
- "ciphertext": "5CE9CD9CCD7F347BBF6D8058AE3BF6BD9105E0F5018076515A40F8",
- "metadata_key_hmac": "605AF3BAFE459C6A3BEBD895692BA73FF7387CA41E8F600862853EAA1C09D92D"
- },
- {
- "key_seed": "6735B5573164DAE91ED565C002E77FB95A4C1113E9BBA940C3C114FA7D35CFE0",
- "ldt_key": "7815EA6D91FE6E2AB65CAE36A3EC31057E7EAF0CC9985D83D582DE9AABAE07B991A4A4E1361C163B016FB779D8E06034CB638F2882691AE6E098F6BE8D493AAF",
- "hmac_key": "4E41D32241A202F0C4D4E6E57492BAA3F2BD9BE277707B49790A028FBB83D26F",
- "adv_salt": "B94E",
- "plaintext": "DC766ACAFC7839796FC4CB092BCEF22D57C2B3B934CB17976776C582",
- "ciphertext": "DBD0C3B395801B837F3DA56962386491455E741F9009608E12B67F58",
- "metadata_key_hmac": "1BEFEFC89AAB43D2B10C7255F503307616980A873520C758DDCC7D1751E53A0B"
- },
- {
- "key_seed": "B5C2FAF80689B16BABA1F500BAC5A0D907836B2C2BD48482FB52CAAD13E93B99",
- "ldt_key": "0F77697600CAA022B28741FE42D64F32C35FB5DC4E766EBF3CBD75EC0ACA564553C7A134BE4CC8AC1A5D150B6AEC18AE1A86EFAF14EA3F2E837C0940D3118EDB",
- "hmac_key": "F2C8D1A0A7A0AA4F5879E1980D30D38D5921B6FA1EAE8D37F589ED6932F0EDA5",
- "adv_salt": "93B2",
- "plaintext": "FE7D74A15EB5BD5E1766E76DE7BCAE615434",
- "ciphertext": "B13912720CA1F0F40F31C6CF76F9DB530F16",
- "metadata_key_hmac": "C6F8B4B3D3F3118C444C6905B6717880A34A7A9A15E46B1C94B9C8B2577C82EC"
- },
- {
- "key_seed": "673E1E6D508B013132C409CDDB225CE851E2A1CEEA62C4241E63D41B85BBB420",
- "ldt_key": "FFF7B05202440B7EDEB45E6B04D27C8651EDBBF2AF1F7A1EA28EFBE4059D80DF2AF1E8AFFF0522D0057D543EE9E18019745311C527B8FE9512D3796B7B90B976",
- "hmac_key": "073A222A4DB5FE1F62B73C76E023EDA3EC4204AF7677543020998F454C4B30B1",
- "adv_salt": "0C07",
- "plaintext": "69DA685B42999676CCBE99073CCFED628C0376B125F6B5496B78B788ABD380",
- "ciphertext": "E35B1BA68A8A40B8B9A9CBB2F145862506D4FACCECEE38FC37DC4EE0B7420D",
- "metadata_key_hmac": "3E22A0BAD2D95A023EBC67CF26FA7774F60F0A9587DDCE0C50DEA930D1221F41"
- },
- {
- "key_seed": "2A473F648120ACE551296E5F1266964BC978D9CF662CED89DBBE897CF97998D0",
- "ldt_key": "F1D9A4C4F389D899357445A9CDDD7AA053309395801A8C85EE1AD3485E7C8D48BEBD36DF5531E8AC18F248744DF36F30DDB5F27109EAE58005587F6A662B5529",
- "hmac_key": "0FB6CC7B6DA175842AF6B7C17770F74026EF4DA2369ECA21153456FFCEFBA0DE",
- "adv_salt": "81C4",
- "plaintext": "2FA0659EC174DB284AC1B07274E862BEFC38",
- "ciphertext": "76F551451F9ABFE686DF305375C2522A7F79",
- "metadata_key_hmac": "76DF23DFE3A042FED827F288D8BEC0C85DFD48955283864A1CFC80DE1410F314"
- },
- {
- "key_seed": "0CFD4B3DF60D86C2D5CFB127375A5E709FC9A1D38BA481BFB708832059D07060",
- "ldt_key": "DE876355D785107000B445C72437B19F594ED1319482701CA67A5835A2B82096EA1B7E906F511CE8DC115EF8275B3519744B0490F8C60B2FE2D4A91A488B2669",
- "hmac_key": "7A7490CACC3C85B6E928E05CB34E3B42BDBAC5F51B2D200E846AA79382A36757",
- "adv_salt": "8535",
- "plaintext": "F60CA2F3F309D84720DD859265AB8C0BF21B21A7B4",
- "ciphertext": "712A8FF93C2B67E2CD5CDF78A77260F58C8C409F5A",
- "metadata_key_hmac": "8F0CEB0724D4C9689E9EE0BF071BB8286F14912EB8ABCCFDC666BE235978CB0F"
- },
- {
- "key_seed": "637E997D7775FCFD647ABC97E5F205395081FFA752CFD8EE44DDBA22DF14C00E",
- "ldt_key": "71A3170FE7684E36FD017B8490831E7B5EA24009D6AC494F441D85006C9C7076A47586A6BC43BD5A31E1C70EB9F4BD2F186D935D10345E4F006DC400845DEC79",
- "hmac_key": "FE7F91371BB8CEEEA765089944543F3389C44431BF670A2943A6C9657C9CEA85",
- "adv_salt": "44B4",
- "plaintext": "A1CBAD09790C0302AB3CAB721094A285E7A6",
- "ciphertext": "700A33D436DF6CA3D1B1E55CA1011F7255F3",
- "metadata_key_hmac": "163E8E307FCEA7394D487D98F76039AF24648CE14200913C4CDA3DC4E3B7DE4A"
- },
- {
- "key_seed": "454F7C4FDD05C3D7EA764FC8E988E836040D5AA71E9FC008316A56947C20FD9D",
- "ldt_key": "071D5BD7EBD02F9FD0A914B726A055EC3174349EA6D84F9DAD2E1968CDC754D2953CF003445804E2528F8A3E17BBACFFBC095B09C4E7ECF361EEBC8FCD03FD88",
- "hmac_key": "40258B6551067277782207D800EB3DB47059EDC830FE2A3246C82800AC93E0AA",
- "adv_salt": "E880",
- "plaintext": "A7C046F982D9FD6B21D3A46924570B90C64494",
- "ciphertext": "0301037705FD66CF960A4C81FDCBF5C8F8DC73",
- "metadata_key_hmac": "C278DBA0E3C2442469306211A58517E65AD0E823F887736F72ADDDC72E8EC47E"
- },
- {
- "key_seed": "D093E0138C4A14E63567A46E37BE38A95A933E2B18FFD593BEF05B85E0EA68AD",
- "ldt_key": "90948ECD6E3F08F28779605A62AFC7A4E12597C169E77E0DB269DB251A5D2BE6227A49974B79F3CCF14CF8F635ECC3EE79DAFE98AE4305FA3E7BE4A693040208",
- "hmac_key": "AEEF514026B55FBD72224A96638493F83808CE90BDFF8499216CFC2D42DBFC57",
- "adv_salt": "B1A4",
- "plaintext": "858A256357724C43E415C3475B165A34C3AC9D19423B2506C53B",
- "ciphertext": "7FE1D27B67DAEC6829AAA383A8804E73E8A7F30C1EF8919ED380",
- "metadata_key_hmac": "CCEB348AC6ED5D37DB1820EF0E088213A71D94BC32FF93DC6C7826BC60C61B4A"
- },
- {
- "key_seed": "80F2AAE12395E3C45FBCCCCD4CE458571AC2D3B5F3C9105298A0DD4AF317D879",
- "ldt_key": "2ACC8ABF12B91584285D9217BEC51965647BDC25C38E17AD2ED19E139C656AAC431FD0E469EEAD559CC4A801B3EDF474A207E2FE57D5471F96D37E8662B77014",
- "hmac_key": "F46746E3E06EF3A7FAB7005C249AEEBE9539E3F4C264CFA90AB61D956B00D430",
- "adv_salt": "5498",
- "plaintext": "E50C9E12135D4C7DE7D8F2C2F9A16658D01884",
- "ciphertext": "B896FD364CEF99762DB1650370063F805A8840",
- "metadata_key_hmac": "BEBA925F567BA2ABCDC3B9F5C92D04A0D7BFF3206448C15623E563B7FCCFF276"
- },
- {
- "key_seed": "C96E4191747A3C54A5CA948B13CF3684CFE72376C48A944792DFE1CA8D68E49F",
- "ldt_key": "85E7CE34452DB08C1092DD77849B13EBE15914A40660C16A91B2B26C21452331594D68F8920900E147A6899B7CFA63779F9D96A8E819C1F6D4611CF3D0EFE974",
- "hmac_key": "AFA3822EAC8C7129315950CA2548DB5605F2CA378AD85E0C9151ABFCA816B7A7",
- "adv_salt": "03C2",
- "plaintext": "596D0202882999D31346C62E5DC1A7AD4F30427473E99A144BE43A",
- "ciphertext": "BA8CA0694A4B92C46BCC64954BF0F0B77CFA8D071FDA015F98E39C",
- "metadata_key_hmac": "76A8F3B97E05C47118B56C5EA74CE0BCCAAFE05C758B8B60D388DBD425309478"
- },
- {
- "key_seed": "BA7ECB1E5C504F05039DA4D49A249131E5ECA00048F5B167F7BE7CB0F157C1B7",
- "ldt_key": "D7C9D80FB954BF225624BA6A5AAED8EAB9A0DD87E08F2AA6735E4DD820C57A6832E7996FEC6885BCC768878B7180561DF95A1507832C98FA0378141DF7247764",
- "hmac_key": "1612AC7D901DFFAA784F653CFE72C860F07D02D9AF3944E575392342EECE8674",
- "adv_salt": "7C01",
- "plaintext": "2FDC4609B6CE14A81DEBAF4E75410614668FA832",
- "ciphertext": "8F726C4754B0A4063F66C3F17403B6F205548AE5",
- "metadata_key_hmac": "7124713D3393FC2127DD5807AB32A4FF9387FC413D6F09E6FB384BD93663F125"
- },
- {
- "key_seed": "6A262CB3E191FC39C51A0E668E86559FF5921C45343023E7453BDFB00FC666CC",
- "ldt_key": "DB977C5B5D21458CA2C443EAFFD6166C8747F3365329BE64E1A64B65625E976436F667BF1CAA6C37B8373C2CA668D3F0605C50146610D0C192CCA0B8FBC40255",
- "hmac_key": "0747CFB1BFBEFC45F41F2789B0868D6C01660CD37F8006F40AA2004372A05546",
- "adv_salt": "3913",
- "plaintext": "2D9A7F0A1695C480881FC6E090D39257564551",
- "ciphertext": "8FFC40566A06DA6BF601EF2F7D819E3F1C6B8C",
- "metadata_key_hmac": "2AFE4B48FB0D88225DEEC8067C47ECB280CC3B82D05CC3A5A200D96112D2BA5D"
- },
- {
- "key_seed": "76CB008E2E1B57DD9874055C581A63FC92D9E9800FB63A0DB8749448A6814E1A",
- "ldt_key": "B5ABFDB94FFAA9933392FD04EC0A79FEB1F12082FB14D45927ED495F33303BAED6FEDC64BAC2FC6DC39E3F96F79B21BF759B6AA8A28BAB7E0C12D0668A796BFA",
- "hmac_key": "35DAECA2FD83A07F6081812821327972D968BF5642CE9081BA08B5D30706DAE4",
- "adv_salt": "3AC5",
- "plaintext": "548886B7B5D63513CAEC671632ED252B0B3D31216A60E7F1840F36EF",
- "ciphertext": "BE79E939E021C2F93978A03220E2E106B98C2E1AB7C81F3E8A564BF1",
- "metadata_key_hmac": "9EE785528D80D745CB0223E4BFAB2A72FAFF9C6AC999E81DD82567C42A093B4B"
- },
- {
- "key_seed": "734A5E8CEFCE9DD5EA33A0D218D22B591BCA71DA64279936D33BC06572CAE44A",
- "ldt_key": "3C2BE602C84B67E195D251C657B5488C50F6B683E9EFC5B6691148A53C63A2C237A833805EAA9875E8DB1D97A746D22E9933F21FB7D84F8140985280D1D3DF1D",
- "hmac_key": "BB98542D66C10FDD4E6FB3A5230D4369B17A48C60BC14D717BD542A8A131DFC1",
- "adv_salt": "DD2A",
- "plaintext": "AB1C28BD51FCE36F10D09E48261359FADB02B0D8FCC01E53423E25",
- "ciphertext": "677A41B92A745B7B6EE2305D6D2DC67A9D68C61B0E1E09AD12DAE7",
- "metadata_key_hmac": "C3C99E314D2E8073F2D2E6E77A65FD8CA966D77B3ABF8CA3E6B119A0F5E980C8"
- },
- {
- "key_seed": "AF06B6C79D84CE617AB5F2B490BF47B9B004B9B22346973BCD28075F827ECF99",
- "ldt_key": "3F9FC45F4D363DAE68DC68017CE6A50379969FF80C95043D3F1AD7D164EB3A22EFB0A6BF5B7C5F32F27B8CE48B9C8C74D4751EFF15A5A3F366A83092618707CF",
- "hmac_key": "8745D4E53B92E1BE50BDCDFBA6BCCACEA494EB01B9E11D93A5CA20213B1FC24C",
- "adv_salt": "6D2F",
- "plaintext": "EFACC5C8CEB14C77DF12BCFCDA089B28314458A3763415E50F1736",
- "ciphertext": "D46F82F4632B5D5A87A1EF6AE88F1E988121EE919BB0AFEF8F368B",
- "metadata_key_hmac": "28CD7B159662B6BCA85C1A88194E807287813E3A865A5DCA755D27DEC02468F8"
- },
- {
- "key_seed": "4C88A40586DEF1E66FA06B376E94EF9CB0FECE6FF56D7D835CD5CA8633635E3B",
- "ldt_key": "B084E839128D948FFDAAC25A10504AE6903899794FA31B17BCD301A5AF9496D8D74D231C07578A81D76FD43E7F133804462BED251DD562C82C8649322DAC37DD",
- "hmac_key": "46C76D514FDEE225F7DF352BE4EBECC06EA9B981FDF241D137D77AED1D2EFD18",
- "adv_salt": "E728",
- "plaintext": "741215B7CEFDAA6BEF56FD3FFF8D12E9758BA4DAAD649630106F673C608153",
- "ciphertext": "5315772F06F221277DC651FDEC639507132A13CEB75B181A455945BC3BAABB",
- "metadata_key_hmac": "6C508E562A98C11B851A7451D55FD588DAB288EF91A59D74DB3EE7A75B1F7928"
- },
- {
- "key_seed": "24F6FC4ED7E0A9738F9EB21B3247E49F5395A97A824108C5A962996691D51D8F",
- "ldt_key": "836B00EBE1A2F5BB21B2A893ED31682E04AC369CF0963D6C0770355CBBBA37342AFB958C4DA2639D0C6B281F624C592BDE21727C16884D7BA21711D1707069CC",
- "hmac_key": "29FB41D5F99AAFAF3860D7BA28AC448B388E64D643240E442C254D42D6AACC13",
- "adv_salt": "E44C",
- "plaintext": "7A698C0F1BF667DC0DA7940D5AA0B4276FF729",
- "ciphertext": "4BD450836E530D172B9FB13F39E1CF154CFD4C",
- "metadata_key_hmac": "03D0668BDD212753BC833AA080F209A21B5D8132747608D753ECB9CDC774E280"
- },
- {
- "key_seed": "5C450E249D3939EDF8CBD3139DD3C432EAEA58BC15D812245D4FDC89F4219B10",
- "ldt_key": "6D34AA5E251A577541F23A7C8B18ADBEA94E918DB1ABF496117F273A270C6EFE1143EE0FD89A3B29DE381EB692084DEFF9C31E82D90E52C8AB9079AAD4DA65E5",
- "hmac_key": "335B67C2D915D37ECF2F775426571A389DF28D1E948118F944B3818A54C46666",
- "adv_salt": "A823",
- "plaintext": "BB455DF842180ACD349CF983717B03FC124FDACD16FFDDEA",
- "ciphertext": "E7783B07DAED46AFA5776B676241C523CADEE551D7F5BAC0",
- "metadata_key_hmac": "B10C97AB9FA38F309EFDB36E8C33F70DFD0398CA311EC8E5C44D16FE57DCB19B"
- },
- {
- "key_seed": "0ABBD703E3F87A84F814A82D0775EFF810D0CD766724AD253B5D2A7E0E684550",
- "ldt_key": "59D3BF27B0D72DB394BE06B0A758512997D3AB6C66B57F719723DF2B399AE219156C2AF670B261982010A8F8A91F7F359CF9DDCF5EBA20BC8D91647FAC28AD39",
- "hmac_key": "D66245FD1EE63399A3E471ECB420796AC0D8C1FFBF67AF6F7D055A3EE32F7EA1",
- "adv_salt": "D866",
- "plaintext": "F2BB657EC7E3F7583B3BA4A8BDBEDD26E3D7699FFC2E65153E847AF0",
- "ciphertext": "460F6850A542CA64A68A727824B9E053519EA01F399CAEE9CADA3024",
- "metadata_key_hmac": "75D5D1B05A1B9B43ADDD5D9E1FA00FC76CFA56CAF94EC22FE3445A0BC60A9AF9"
- },
- {
- "key_seed": "16C1215117831095E9B4721996091C58C9240A82FCF2062BF59ACB4A5AC02AED",
- "ldt_key": "116D8E1C85D0F4F32599D636BE3F57DF9DD0F08B102930206E6EF8ACC41D86EF868CB4A4E08DB482ADEAE610E1ED6A36F3C1C5879B88E786E03AC29047A4F1CD",
- "hmac_key": "FE801751B81E2DC203719AE83F773CDB5123C60E2F32F18CFF22AE1E945BD0C5",
- "adv_salt": "4805",
- "plaintext": "711B2DB12CB10ADE43838D7838DFB2A7735705",
- "ciphertext": "D299FA3B8D21B0FB0DDE2FF30AA5CD1DDC8D1F",
- "metadata_key_hmac": "09FE282BCD62C2872FF1A2A40857E55198E99B163A8B2E74C5956642A1CC6303"
- },
- {
- "key_seed": "40F4674089D8D8F56CF4293BAF5F0FC36E55908623542080765E7FF5CEDFF491",
- "ldt_key": "E29BF5DA37D2817BC44FAB3DD19333BDF6A455986C81492DC0E217402BEC6E013877620758F795BD41C8D1A1F89E8B72F3C42E9ED6705BFBFEACCA6E95EB9781",
- "hmac_key": "016941DE37724E5066144373E82DB9BBD3D71A7912F889F68C3FD9CC4D534605",
- "adv_salt": "0DB3",
- "plaintext": "9EC1F5AF771E22F48D20249F90D4D9B62DFEB1321A101E9D73DC6448E4B5",
- "ciphertext": "1F5D3CD8EAB5D8DACC42A839DB96C0DA3362FFC11A8ADE1C59540BDE4FD1",
- "metadata_key_hmac": "FF37DC79D505C2628601DCFED56CF750E00A3F0C9DC2206CD8918AEB2C991EE1"
- },
- {
- "key_seed": "09A1AE393888C67C96792918CB3736DC2F8FA41387DEDCCF512D971F42ADE5DC",
- "ldt_key": "907C4CA4714B49BFE50A05C48FA228F40E1181DFAE1362B9DE4AD5CF705EF627B6CBC1B8D8AFC606864147C38BDC986F99F1AA21BFD001A5297A5436C4218C61",
- "hmac_key": "ED09C00530E639C727F5EC52CB9F8EDD68A754E73CA44672FC4B52A242187AD6",
- "adv_salt": "49A2",
- "plaintext": "03E17167B0304F9FBD8DB82B8189842DB3AA3D8681C3",
- "ciphertext": "1891DF1BBAFBBE2E2F4C862C22282018B639A1603F2B",
- "metadata_key_hmac": "AFA4D96BEFE2E957E0E914946301729C029F8957CF5AD5D596A902627EFA188D"
- },
- {
- "key_seed": "AF9DB6A25A8A5F0D23600D835D7111DE4E9B63B4864E65BED255EC2919C36E74",
- "ldt_key": "B6B6A945F85914EE11E44665E0D2BF71714FCD49BD8B71B0DBC88B3A8301070B6DCD33957F9CDF4A7006F0ECC02D4F943F697A1D2E39C6825B0DE4D8E279F45C",
- "hmac_key": "E63E95AD895F7C47DBBBDFE0E9F0966F68FF38DFD660A7D01F47C9CAAD32FE17",
- "adv_salt": "71F9",
- "plaintext": "6751240C54EF004BC3FA9C33E9DFC119055AA739F10824833625CA4E0216",
- "ciphertext": "1364EBAD093E6C99789FC2B73F4E94A4CE02EE86434F44D630BB6D1B80BE",
- "metadata_key_hmac": "683BF80D592878CDF4B44CAFE3DFBEC8290E549665A8036B5B4D079C1855D27B"
- },
- {
- "key_seed": "379790A3A16688F9A9B467CCEA5F7A326C24C943FA548762927D262357C2A4D0",
- "ldt_key": "1F02E51C252D4F0DA772E048AB8D1F1940E911D7074876049F2748BA5A2D5E0366D4534280C5CBBCDE5D9F3A5AC2B6C7E4BDD971491E34E37CC7AEC003E2C45C",
- "hmac_key": "70B0D103E3A17AA9F9C654D0AE9F32A7F24BA8077EC1B1A7EC946A73E78D11F8",
- "adv_salt": "7AF6",
- "plaintext": "39D25AB8EE2ACF8D6B925DB13694B813F6E9E3257B9D6E623FFE3BED8000E9",
- "ciphertext": "5E54468B2DF8BE02F18F51BB0CCCC0CDD188C2DB524BC48AC0C8AB7E546F2B",
- "metadata_key_hmac": "B1C909F56C97606FD765A2307EFFC78E083152BA417D379BBE45F65D53E9605B"
- },
- {
- "key_seed": "7244E9537F19F09B9E0B3B20EB96BED6DFBB284C6C1823D249A81D644181D41E",
- "ldt_key": "46C45C77471DE10B1FC096AF2F1B4E50BF91E70A315E9F1DF80930994AD7B28887C991FFA51926E641FD0885DE7DD716CCF779CFF77111444B2DF878484E3A8D",
- "hmac_key": "327900FAD35E7BC55FE085C6C1E1AAACFBA57B7D87E7D009BB1E216A64A829C8",
- "adv_salt": "4428",
- "plaintext": "76F9D208707E3576C1DF5B960E9A554FC47BB2D1E616A0653B2827B3D13B1A",
- "ciphertext": "038B6EE79D23F216B980895560F7287144C4B355014560DABE07D32119FA35",
- "metadata_key_hmac": "FC4700ED6C39BF038DAC105AB927205E6B4C89219B1612E61D109098E2178F3C"
- },
- {
- "key_seed": "A6D61C0AC7BCD56C6C66199C2929A1389C1878EAFE63076FFA36409A43BA1622",
- "ldt_key": "CAFAFB9562C5A9F387F0A8C03D0E8AE3013D806486E2793CB4A76DC646F391CEB4F6DC28313C102E3414005414EB60664E3B11E93BC222ED1B1BA9594AAEF59B",
- "hmac_key": "810F8F1379452CAB6D3FCDFC19D70C2EC1EF166009B5EBEDFA1924D39DAEA3D7",
- "adv_salt": "03F9",
- "plaintext": "E0DD037EDB87219B892C9C5A6E87C53BB1B730B8139D6ADAD200F7E4E2DF",
- "ciphertext": "B3FD41D849FA82E9F3A0B32DA870ED2098290B5AB6EF5AD70260A9799C48",
- "metadata_key_hmac": "0FA6709E1302364486231A1107AC491627615536700B48C314610D70EB4A6ACC"
- },
- {
- "key_seed": "E1D2410675097312A2DCC79F898D619E5334FD1CEC801C4C92598C2E481EF1E2",
- "ldt_key": "AE7B6D9FA16122304F87C2C188ECD2397096236D2C6A6C866C92590012DDC6B56144B67B67F3C6B3443AC2305F1996C1525CD2E2391D6217DD98C48AD3F5BC0F",
- "hmac_key": "1B7EEE453F9EEC77FD0CB9DE5EB1A62423B01A5F7158BF18DCAADE4BC1E9D3B7",
- "adv_salt": "41A2",
- "plaintext": "506C68217AF1FDE8240A5C581499647766061D845D7959",
- "ciphertext": "4D5AE7562E3F2A08B8011B7BDF9AB1BEBDA3B292735091",
- "metadata_key_hmac": "3C85C985FE3CB1D007A6E006E9FE0ED392F6721D460A14CC9F4C45D94CA26F11"
- },
- {
- "key_seed": "4A2CD5102101DEE0B9C7A5A0A3D90A17C6EB62D9FDE146492B1CB2018AB73F66",
- "ldt_key": "AA5DE1D69FC58B0A102AE2F5185B57FA4391878B929690AE700A108CA027F9E10853E8CC884697364343015DFC5645743159040FCEC57C115B768155F7F2011F",
- "hmac_key": "734F591AB362AF84FC1ECB2F20AA3A5B898ADFD8262E7BF51D4AE31199E324D9",
- "adv_salt": "FA7E",
- "plaintext": "F0DFE7532B16B3D85B31429FC849FCD5152CD16714770C0600900EF2C2",
- "ciphertext": "3098A07ECEAA126C8D0CF51A5EEC21CFFD4EC4D87ED6D370F3249AAAD1",
- "metadata_key_hmac": "69E5A6EFB346E39B928B380EFCD0DB3C12171C022CDA398D241E7FA75F3E7C2D"
- },
- {
- "key_seed": "AEDF65C5101442019724D8BA5A19770BB4E4B42ACA063CBAF971EA9D389F3055",
- "ldt_key": "05D0A74C199E27F29192C6CEC7DC956D87717A96EF7DF42E61D6AEC1BEA892B406EA16336F015B8C48BD7D117C224D7F5D24E9C52B1D2741AC3FF19ADE5BE38F",
- "hmac_key": "FC77044E4B28313A8C93DCDC6C94429ADDCEB92DB790D7149B5C78D277E18D5D",
- "adv_salt": "BE34",
- "plaintext": "FB1E97034125E50B7DAB98B5FD7AACC7EE06E8CCF7F44C77BE3009AAB4",
- "ciphertext": "D559FF803F17B537C041D522CAB6E8CF6B72C2FCF217ECA62267582D15",
- "metadata_key_hmac": "702E274ED9C9066C50D0E14B33F3AF6A3437165A3EE58F253334AD0A715DF5FF"
- },
- {
- "key_seed": "F859152456CD31A181628E7C987F1FF81DD5063757F5AEFDF3996103478EA458",
- "ldt_key": "A719D3F4B3DCBB6ED0A9A64D85041636DFD5B2932A08E4B991D98A11E52CF26343DF496B055FA67E52971FB76AA634E8525B4C3AB49A770E094279F257CBDB9D",
- "hmac_key": "3805B71A01CC6F4F3F04F5A855DED524B1AFAAA992F25AB6F58A67FBAD0D3410",
- "adv_salt": "3AB0",
- "plaintext": "190A6DEBA8A10730B7FB590DF7B5643E5EE5AF0FCC3F216549C9678B99FB0A",
- "ciphertext": "3A11A58519E7550E85D9FC159FF99FC813FE0CEF7A81E4726DEF8E758DEFAB",
- "metadata_key_hmac": "B5F0F0476D7875FECFF4A81A465E32FA42DDF11DB2DC7D56CC43A3010EE94231"
- },
- {
- "key_seed": "9BBE03E7F339F608122CAF6FFC7C42F84F13E2E60AB8D35678F1186EA48C73B5",
- "ldt_key": "D20DD49BBE002E51FCC736BEFA614EA57798AF503AF91FA49CE58752556DE744E8BCE9417C25A14F4A4D518D6373FD6DDF46A9D1E5C9C77EB880C65672DBC2F3",
- "hmac_key": "61A3E0DA748DA8C6950027C5C88C2DEBF730D34D363F2689C556001409B81B25",
- "adv_salt": "7A02",
- "plaintext": "DF9154B8C961A5F6B5962461C96CFCCD898F4FE1",
- "ciphertext": "A7228D2DFDD4BB799B82F0B0742079AFD404EAE1",
- "metadata_key_hmac": "6272353CE4F74C61571A21A536A1B3F72693B318865DB9BDB6234B755C7B89C9"
- },
- {
- "key_seed": "3379C24083B6D7F1CF2E19BEC671062FC16B05D05C0316CDFD8125B52685BA27",
- "ldt_key": "28B693F96DE35E98588FF911C4D7033D495C150116786E2DD2CF0A65F61439DF2C28ED20D327537159C9770336946F92446337F448C28D81F00271871E557D22",
- "hmac_key": "E4E45C15C730D3B65994671F11EA6AB78ACE91E79CD546948AB64CC74CC70CA6",
- "adv_salt": "7042",
- "plaintext": "B906E13C3DEE4CC03203C7CB8C320524CA",
- "ciphertext": "C62FC94C2BCE15064DB15F6E10E40679D5",
- "metadata_key_hmac": "A6A1F42E3B0CFDC4B6328F759DF98E8CE576C2B858E477D616C32A02907D0F67"
- },
- {
- "key_seed": "D4B7DB2FB9D813475FF7C49910225821DD841A82C42A49E7AF938430278AC86B",
- "ldt_key": "656D63EE5608213E2D2AD2EDCCC84228D1139649BB0B5288488D7532D087526DB70454FEF78DBA5C69CA506A0385D6F693E6128F8EF0CB5A01E418243CA32E1B",
- "hmac_key": "8143D313C451175B1AC1FF43C8EB95BA4817F8220F890D4D2D971D9192115DD7",
- "adv_salt": "F65D",
- "plaintext": "690114D595228CC8D7DD1C575CA072EF3FD5",
- "ciphertext": "E1D6D17653346FBAAB461DDA2632C6528D72",
- "metadata_key_hmac": "64B76FF204DCB39B7074281894CC092A016234E7AA68BCA117183A67B4D82D92"
- },
- {
- "key_seed": "C05773CBE32033FAC35ED3E6466C1323AF867CBDDE0A694937F2BD49E7F43328",
- "ldt_key": "8E6838C833AD2533EC55858956B731F32CFB82CA67541F9B5C24D3B39EB4DA9D4CF01B1D9BBF5599CD6745202D02EE6C482B93B87B3011B0BB95497F25A9BD98",
- "hmac_key": "C4CA1550C81ED8EF579738AF75851AEEC86B13F55C5DA9963DBFD0B076F37F78",
- "adv_salt": "2237",
- "plaintext": "ADE80DC4D6A916B09DC82B59DDA7712AF85B522CE3CBA2D52C255B82FE9053",
- "ciphertext": "87A0404911184E56309EF8F19210D4044E3001AF15F6E33B60274159CF62B0",
- "metadata_key_hmac": "9F198C89108CAFFAD798C53DDA166D565B5C3047BB418115A8557F797126B308"
- },
- {
- "key_seed": "5880FD7D91A93417C1FFE405EC94A19A6BBCCEABDD48D3BC826C6F279F104AA5",
- "ldt_key": "066461A5D072A0EC2858792B929F5876301CF7C6145811E4EB6FF26A391C183B5D4574C0C13C6F87AF7C40C8F79F7D3B89575B6FF9465333530FFCC1DE68E34E",
- "hmac_key": "CAB5F8751672EFB798DC8693B2C967CEE74C5586582B9C8F2948A18CA32CC2B6",
- "adv_salt": "9CDE",
- "plaintext": "1B24CFCE639A3F09B2018A7D96034474CAFA49E28E08",
- "ciphertext": "9404526C7DC6AED251615018A8FD5A39BD552CF88689",
- "metadata_key_hmac": "F09654197E670DAC944E0C3AA8885A40DF6718261841CBD4AEDF28A47CB93760"
- },
- {
- "key_seed": "103C51037466A5C87BBF1922B48608F383B454B711CD37002A7D37431557BB17",
- "ldt_key": "6F4868EFA86DC84B1EB724C958C564324940E3B86D7A22BDC1892A7B61D4B6E79FF1D2BDDEF162EF61721BB754E30B2494B053B48316BE7908A5F296C4D0F61F",
- "hmac_key": "018E9A83ECA054D5AAC2C71FECFE7B3352F585D0CC2B22C2854E85387436AA33",
- "adv_salt": "BC4D",
- "plaintext": "7502EAA2616A58982892655C4E90C8BA677D1B2BA6",
- "ciphertext": "4C47A408ED86802FC9EBB5451E495095F1E967FFDD",
- "metadata_key_hmac": "00F05326596F613BF8618381E00908494CEE2122AA57E96D5579356034B6BA6F"
- },
- {
- "key_seed": "19DD07C711165600E890266BA899E298CA1ED1B385A4F135493A7862DAA791FB",
- "ldt_key": "7EE579175ACC9B076AA964EF815B6D34A4557083747349FA3853A32819859FEC9581C30AB2D8A520881F2DB1496C39B15EEE9CD70C81EB2FEB0D823CE5367694",
- "hmac_key": "7B46AF4E0821AFC7260427EFFA2176F5D5F9B3DDC04D7C6C62F085BC1B8BA38D",
- "adv_salt": "94BA",
- "plaintext": "4F558DBED51485869A106CDB17E9209277314015D078286106",
- "ciphertext": "335C337C57589E2CE14AD2D6A62588DD87B12D1ED87D399728",
- "metadata_key_hmac": "BD6DDCFDB96F3033E408133E9F4649F69FB198191D7EED711021079FCD4A0732"
- },
- {
- "key_seed": "4C24ACBE8DB04793E4C1C930EF7E1699343BA6CEE1A77F7A3A7080F7E251B12B",
- "ldt_key": "4AB3E205D5616A66E3DF018A9E5097833128C778EDE59956AB0F1FCBD971102ED3DBB8EC74C775ACFFBFA71CD0826703414962EF6AE830865F03F89730CEF8BA",
- "hmac_key": "DEB362F55D37409F8994BC140597A2B3B869E97AA2B3C68C887EC4E92C979E5F",
- "adv_salt": "49A1",
- "plaintext": "1E9265A4D08FE3087F99771E6F0E2F15E30A2F7FC13229AD7FA6",
- "ciphertext": "96C260845C844E2F9F97A44178961FE54B1C3D0B5D486B438CBD",
- "metadata_key_hmac": "9D264877E55B60AD23B434F43BAF63F413B4E7D819AF86B782C9C7025695D367"
- },
- {
- "key_seed": "BD25F6AB07A65C22FF54D1F5D756483AD58531A4B197A08E815FB53EF0F18646",
- "ldt_key": "82D32A9CFF0A74480A64F2E11ABACF8FFC634D88E1691B59CB4196F7013288A8949C9A3A937197FB4DD75FD0610BFAB2AF596A87129C5486E6BC9DCA39CB9CB5",
- "hmac_key": "005333AC607D1782F4C15D328559F6A7D77A12EC58DB0E5FAD697056EF7B44C4",
- "adv_salt": "446C",
- "plaintext": "E80A906468574CB89BAFF8E52A1D51667D7FEA6F99",
- "ciphertext": "D16305F7524DB1C300E6F54E58A23D0702E991E8C0",
- "metadata_key_hmac": "73F68E09B0C66A2301CA983A0F97BE2502775A4E6A0FC079D27F7B0B098BCB02"
- },
- {
- "key_seed": "FC418978C0096847756F5530F89D00063F542E32B79579C002C07951435B34D7",
- "ldt_key": "E73FA0935EE81321345637014FC3AD59363999DDE09627A7BB3CAED9032A268A4AE1D087F8EAE7D78AA1827541DCA66F99B5B310CC228E7F6E7A6A999A4E0940",
- "hmac_key": "1B15832662B35FB725833CAB4131A05485B7AB975CE42D6D23BC2262546D6A97",
- "adv_salt": "BE70",
- "plaintext": "0450BBC8C51A4EBC692A4C23BFF4D210C4DF13769B",
- "ciphertext": "0DCB71960A1F52C03470830C48FCE8A465E3A581E0",
- "metadata_key_hmac": "E8E6DCF05303891D8B17AAE678FA58FCB0D368B7B7322FD39A98CCA0A7BF24AA"
- },
- {
- "key_seed": "2041180A29376678BA3151D8147C030511A73DBA688F75B9B8DF5CCBCBC1C0C7",
- "ldt_key": "35BE7EB20EC673E9C12424863CFED35E91126EA77DAC8776256F0CB12918397FB459714F4ACF35CB3F69E0BAF7238934E556D6B7DD0B5A11803DFF5E1A48488E",
- "hmac_key": "BDDF2F2E9052098ECC8D8367E57A3ED601AF07B300EA24D5CDEA34EC7BEAC3E2",
- "adv_salt": "3B5F",
- "plaintext": "794AE946285A473064DB37339A086869BFD1715597",
- "ciphertext": "02F228E175B8771467BA176E1033E1420168B518CB",
- "metadata_key_hmac": "E7031B66347209249DF4FD89D8DB2C106C0DE93343E35EC8043C1240CBDE03E7"
- },
- {
- "key_seed": "0DBA415E4560AE4A11EE9EA226E8F0557BDF49FC3087551836A41B45063B7CD8",
- "ldt_key": "5F49DF5973924250986B9C0C1DAB8A05A04E37A6A19FB95588D93E93678A5A1AEF02A3D22819C0BBE403EB2D69B87F71CD001C22EED3255B966F771839EF4F19",
- "hmac_key": "CEC27E2CA4842BD6BEB45A338B1E4AA9A4A3B4C218A365D9EB6A6653CEFD558C",
- "adv_salt": "A23B",
- "plaintext": "0D83837FAC4E96453C6157ADCEA227E3FBA12EB208D8D4AE5C",
- "ciphertext": "BAE54EC7093C124986CA0CCB2E946C87ADCF4EA04E715DF0DD",
- "metadata_key_hmac": "7AD8ED9CBF46444E8425E3A5D1C3C1CA4A1BE1305C337000BAF1AC9A177B700A"
- },
- {
- "key_seed": "BC06E8EC0BA473633FED05A99FFF8F319B5F39390062E1A8E214ECF89960BEDB",
- "ldt_key": "23EE6EF691DB54DCDBF43692677C8081167AAD38A64B8E00394A86057186FA816F4377F68F268AD5EDE58120BBBFAF87F2AC58ADAFD9DA6FE04FA698466E4785",
- "hmac_key": "1D023E11431A19ABB0F4A998F7C63737345FE05A93C94F05D984BC35A9B28FE9",
- "adv_salt": "A8E3",
- "plaintext": "2692F054D5BBC048E1FB17C93A3A7EB7F8D395C4AEC891EA62AF",
- "ciphertext": "7C876CF1FFB1A4B8491D3E2D7568C4051EA1533FD1402F3AFA99",
- "metadata_key_hmac": "B0A56DEC8D01319E85DBB0F11EB0D83B9786C40F586B6E8E59323D4D92272057"
- },
- {
- "key_seed": "94729F5E0F0DCC59434B93A0E0C873503747FBD39EB607C2ECC157A624C0FF71",
- "ldt_key": "886E23DC1E672ECDC4444D462A9C7607022C9F049F312B9D56A4F7A80016383044549AC8F0D8B39F09E6BE341B9ACAC094176077C11A8B4AD9498888E744DA92",
- "hmac_key": "17B67DA2B4BB2A3492A8412149B28C4608B97B58937D319A638F97D5A04740D8",
- "adv_salt": "B2DE",
- "plaintext": "C22F66F44DD1F346D53A32B3B86F73D1B6F8CC347EC6BBDEAC",
- "ciphertext": "2ADD9C73EF5AD3A1D42DABCD759CC8BBE6019500A723D50A30",
- "metadata_key_hmac": "FBEB951F1751A8912E7BC9BD30DF3650E14E0E44932F6931E81BD9D4EA82D796"
- },
- {
- "key_seed": "97853552152F9C635D179E68B151CEF51DAD18179A908D0AF77E431A8FCB2A4D",
- "ldt_key": "655B2CD6BEF4DF670E969A9719F422662BB7550D8B81E7D7E47815C13510FA1AA66D8D2D6884EDD3FA0932E664A726D0EF8569888250B933EB982D0BF8F5CE01",
- "hmac_key": "56BB22A258C6853321CE093F9DF6B2B09BE4850103197D46963693B468A3550D",
- "adv_salt": "16B4",
- "plaintext": "6E7BE9F6C7B5E8DA736541F6DFCF3B192A3DD80673534A285EDE",
- "ciphertext": "1AB71BCEE930128847F36B784A8DB1A29CD98B4A39822697CFC5",
- "metadata_key_hmac": "5C5BE24BB0A2C79196CBF3E24E309C139415ECE1548D91AEBF8A319B1902B071"
- },
- {
- "key_seed": "1AD10AD3882870D10712A9984F92FBA3CCDA6029A5473F90B62A3FF9DEE4ED23",
- "ldt_key": "00F17B5F6487F2376F19196B905330C9CCA23244D6A0BAF3CAC724BF19226A0185B2783608DBA6A31CB4A2FA8C2C51B7D9632763773BC9CCCB399D69A62DD1A8",
- "hmac_key": "9AAA6EB7664A9AE3C39469753CD27E3A28B1BD55A9BC2986497BFAB9DAEED6F5",
- "adv_salt": "0910",
- "plaintext": "747E8ABA603A3694061C8BEE2CB0FB665BCC4577A8CD87A5775B6ADCD30555",
- "ciphertext": "51D689AA9EB209955D24F77402D1887D73AB0C64F8AF44B161ACF87B8F915A",
- "metadata_key_hmac": "0E61826D0787C0B56CE2D4EC6412155EAE66CB475CB5E0EBF28CB9B433B59483"
- },
- {
- "key_seed": "ADBBD9D7DC78BEEB41DA9F651FBBC63900D3710AB350C7BF6B86B105A9529383",
- "ldt_key": "AD2E0EDE35E70949CD1BA26C33E2B6D2D74E13DF583639E7FA90338847CF7DD4BB23ED634F9BCB7B9C1F882081525ECADD25E010899436B0C57B5FAF626368B5",
- "hmac_key": "C270CF2D5C108729101561D8649B97A83088F639ED0B735B8405F4A1F2F1F9A7",
- "adv_salt": "6C68",
- "plaintext": "F7C24D90CEBDDD06238F4C21F925C3E7AD0F66E2D8FA5F1DF63A63",
- "ciphertext": "0E22356768057409EFB7DE829ED923E4DEB21A1727DBABB4D7AA28",
- "metadata_key_hmac": "86E4A13C61362E747698A54267540422C5DDDDB4A7727FC09812F2E521A30E69"
- },
- {
- "key_seed": "1A47B9AB0958B40D404ECF8DAB40A5AF0379810CC7ED13423355D7C4823993FF",
- "ldt_key": "FE177A0CFBA6E16C413E3C9C5C92E73A8E29AEC3B1B80774F1A4DA648F88C701BA4B6F0A02B4A7AA85113610F21A3912A33C9D1A3F9D1A4CF4E6177ED7E334CD",
- "hmac_key": "C03D5D6FCD0A6B5643DEDB532E36F7E333F0E39552BD7D7108030D04E3072920",
- "adv_salt": "3FB5",
- "plaintext": "98915F57FBE4928B727441B471351C0DBC8CC3AC7D9DEF47FDCFB454",
- "ciphertext": "82EC5640AE09757F7C5EA7664D7ED8B7565D828D299D39F43FDF2D58",
- "metadata_key_hmac": "5C4AF378097BB2BEFA10AD9237E84C0EFAE9C93C39A4CA9F57D72DDC67AD5076"
- },
- {
- "key_seed": "3B58E5F94544D95B3125D50E3269F098E8A6EECD22159F6FD87DF83C43B9B926",
- "ldt_key": "00AECC8B7B786EB7115033A26DF5DE7D4E58172546C8F6F3528B58A4EB4FF0E30277C5DA73FC1F0F5821CFF61AB5F4E2E6BBF769EC9BA049DB4D489CD9ABD0FB",
- "hmac_key": "92704BD960D4947751CEB1B956AC1E091F8F0867ABB594F701105B734998959F",
- "adv_salt": "0887",
- "plaintext": "893ACB5F973D542AA82494226310077D7F2E7E07ECC3489A",
- "ciphertext": "FF2CB47ED8E2856634C93F8073A392339721195200EA5137",
- "metadata_key_hmac": "DB37F8521FB8B20B0F27075A3C55BBD41C82C81B535B3522D6F93417EFA0B3CD"
- },
- {
- "key_seed": "0034249B125C14969C055AB6E8AD4BA5C84E22C966B5042CC0016374408F1B6B",
- "ldt_key": "A54165E007DFA1D1222F8561023610E65DE26F2F3D61854A0E92E94C029409201CCB3DEB76D9F8442C1BD016AD9CB5A9D0818A95A7F64073BF265826DC8D1C24",
- "hmac_key": "79E59673CC35398924A8C083006BA047919F097A1BA2BAD17E6F52435E7B85A3",
- "adv_salt": "DB1A",
- "plaintext": "A0C671ED2604B5714119F46780F0B954676E4A68",
- "ciphertext": "D8621C93EA8E48913B6A8CEE365ECD3CCABC2B75",
- "metadata_key_hmac": "6736A4C00A729980D08669F2E82860F0C3F9B5FDED7E1E74B0F83B4A0EF475BD"
- },
- {
- "key_seed": "55457AA6F640F046C1895D40A87D376907E8893CFFAED109DB1F4A30D001435E",
- "ldt_key": "41B152812D750C330B6547B0CBB733FBC5B09D0F114ABC7D16B05C6080D8CDB25C838CC9727DB7AB15A50C7CFC09AEDE64AB0AF097E262EA08F97CA21CBDBCEC",
- "hmac_key": "F12AF2C68C4D5442675432C3869B910A60A202FEDDAB503023B3B8EACF06ECE6",
- "adv_salt": "560D",
- "plaintext": "4253AE1DAFE28B8E50EFBA15098B93532BE965EC8AF86CF8DBA72363BE9330",
- "ciphertext": "703A4D5320918CCE049D980BB7F8D47EA381DD2DBD65B5B83D4FE73CC10BBC",
- "metadata_key_hmac": "F3346173FF7EB6EBF58DBE71DE9BCF946A1EE4176DDC42AF5641446846807C44"
- },
- {
- "key_seed": "FB650DC96511A841BED5A1E0E2354A588E776BD7753ACB1F8363941F93602011",
- "ldt_key": "B73FC2649AC4BA1FB8A85AAF60395B10B473CE3473CCD7C13E0A8531E4DB43D5ADF9A501247FEACB8467C3BE6494C00687FB482392120D66589669B4F53B6FF9",
- "hmac_key": "14343C6976F4CFA3DDFBC4A0938EF962E8B98AFA05E9E1508043497220E8CCBF",
- "adv_salt": "AB18",
- "plaintext": "837B426E7DB843BB0846492BF2DA7748E916",
- "ciphertext": "C23C23A0EAA4736D6829B2DE63AC71B0BEF3",
- "metadata_key_hmac": "EDBE5C4406A4A0EA52DA4DF82B1B024C515BB664879D3A7FA291E48349D0C759"
- },
- {
- "key_seed": "A36881200B80C508BBB899780C65614070D8E0997194EE3F6D98F23421B4FE49",
- "ldt_key": "9588F448D9E4B82C81F4847495EAD92E4109B17BE5B89132A0AFC7625E5486939AD5B0347B086C353FE84DDD27019415915BCC9987769E77BA49D7388D43536B",
- "hmac_key": "F83C76FC45AF40B179119FC6D048FD78AF5A08512AAA20C5F0C206463B35F9A5",
- "adv_salt": "6750",
- "plaintext": "A207FCA9EF439528FF350019B680F75BD4C7D8A4",
- "ciphertext": "68D0D588C7E1552B306F08BC8D7C74E24933DD60",
- "metadata_key_hmac": "E224004F5FF136FD43E448BB8504686E05C25DB926D972FED62645183FCA4C5A"
- },
- {
- "key_seed": "3AAC65BEED446CECC1127EB05936F9F99E68F6C30B80EACE4C8164FAC73CED77",
- "ldt_key": "2ECEA9B27E4CA5F34BA9FDF2D4FC470072B76C9A679169731B568E8645B35486FA2FE400C2D4FCB3487A52391C5D7EB3130CD6495043350C1D5AF8BD2FF6F5B9",
- "hmac_key": "81D255D34D3158FBFEAB4A4BE471456E9431F01A191E3567B86B7DC14494DB75",
- "adv_salt": "AACC",
- "plaintext": "8FB2EF0D058113BCD6CA3A0DA4702430FBA623CF93DBEF3815BD167328EA84",
- "ciphertext": "8D638D964B3FA5DE2282900DC6AEE6EFBFC2762E4C64038A8930C53F3026F4",
- "metadata_key_hmac": "CC4A52B10E528A93D651FB9A5A631AECE7F19601E5F7ABC86728CE849B132134"
- },
- {
- "key_seed": "86CED9BF7C9A488FD2EF946CC901876DAEC7AF7F0C74A09B0379BA12F2296CCB",
- "ldt_key": "B3E6E90D7759351935D01D50E1873E124F731A1FC3BBAA9DF8311777936399C8A08D3C0CA11813322FC74F9916ED6617E66FA63B312718BB1E8D7D0A8E62F4EB",
- "hmac_key": "E5968C6F4A11E1D4D9F54255636037C12143F1B500D9CABD99FBAFB2745D5367",
- "adv_salt": "ED2A",
- "plaintext": "E5D96EFDB293CF2525230EC26215671D9ED8FB8F2FCCF68937308B679B9F",
- "ciphertext": "C4D352D54F8920C2704BBDBAD3E32BC81BD826FF9B2C329A9A5BC4A3BCD0",
- "metadata_key_hmac": "163F4A8C5AAC4F380D601C6C233A886A22FCFA8250DF9D778FA5FA3B5EBE79F4"
- },
- {
- "key_seed": "5844A8BA6923B40A13266B3A5C87C0B3279B6B433D4A7E7B4A67146E0A7584B9",
- "ldt_key": "E1AA576C09DC8153B64DE1DE9995E3A0B653EB33F397E66F85CDAA798E020E65BFF05D312CB5DB8F2664F1A6860545029C92A6D16973B62D25E43CE54904888F",
- "hmac_key": "AEEF23403DA56577CF8D6CD29A19F17BA7FAF98BFF21A6DC3F6D5DFAE3A66BCD",
- "adv_salt": "AEDA",
- "plaintext": "099BBF9126A7BF666CBDAB15F16A3AFB6E096FEABF8FEC7F96586F58",
- "ciphertext": "EFE54E8B8D1D4929365420D4F1B00BE2EDDEC12084AF888B4C25A349",
- "metadata_key_hmac": "780651B63468124B784530D35C24936A6E59EA5727F616BA10DF38D0C0640AD1"
- },
- {
- "key_seed": "18810CEC96F7CF1DCF17F785FCF6E4B851C259624F99887BBACF34991B0E4029",
- "ldt_key": "DDB1213996D3E8DE633F438EF570A9CB023DA04333371F34AF35754A43C5E511FF3D018D09F7054A0BDD6571C654A60768FABBCB09FA6A01BE98DA735D74D560",
- "hmac_key": "6DE18531295E609DC755FA12D98B44AE58B90301EDDEAFB4DEC8A3C5AF306F35",
- "adv_salt": "4F87",
- "plaintext": "7465CCC4D2D461F0589C54D41243657C61D880",
- "ciphertext": "7E40DE8C7319BF5895234E15EC0E8D6FF97DB1",
- "metadata_key_hmac": "5ABB0A9776B5706C1D60B2DEEF4FB311E1F7D4BCCDFAAA5FA7FE56963D7857CC"
- },
- {
- "key_seed": "48A447100312BF866C96BEBCD04AC87BB6988C4BDB7F8DB12AA05BA4CD980152",
- "ldt_key": "2048C23710EFF15C8826D2815933822ADD0EA25AEEAA3862FA2D491425B02A7CA64BE39B8BD0DD91547E8C4BD8094DF1DAB8D8F017FC5BFD548C661A648283FC",
- "hmac_key": "572A5B8B8B3FF304F9FA05B67597043925D6EC4E74A00A12CEDE2ED9D1DF79FD",
- "adv_salt": "6F55",
- "plaintext": "7C37B54E81BB800BD98BEC561505036D43",
- "ciphertext": "D7E3EDA6A499FB6B809C94CE9F36E031DA",
- "metadata_key_hmac": "C2C54F1B79BC288D97E7E4ADB83091ABC7D3B400F2CB9B1ABE08650484EACC44"
- },
- {
- "key_seed": "6011B4A7C0618AB3D4E89DE71FDF5B6A9B0701144C954227BA61C2D0998829A5",
- "ldt_key": "6266D2FB2B8CBE45701D1E170E12111E6FA07CD31B6D833104263122D9938FAD1044B8F727111DF64E1F82C79C097D544924EF61DB1683B9201DCDF0B5BCA8CE",
- "hmac_key": "12E40307418404F91E740F274F79180DEFE22B6C42EA1D14DF6BB94BF142F85B",
- "adv_salt": "095A",
- "plaintext": "73373AD60B09116818EAA23B76315CA202A49D1A34518ED3A1685711",
- "ciphertext": "B426BC7BA1E9554E07FAFBBACF6AA73D9D1D469BFF5DE009B7C8124E",
- "metadata_key_hmac": "8E1E55E57883CEB2736DBACE6C04DEF4D280F4B9A8F69DC52504A55A8E381B5E"
- },
- {
- "key_seed": "B5BBAD9EFC6E2BD7A0C45C35042688F482CB873928C18AEB5D942565B18E759B",
- "ldt_key": "80A136841226F9BF8BC1ECD3622189EF736067D622337F8A42C6911F85F99DB5A2E6D9850763F7301BE6CBE4C19AA7BB47CBE228E09877C97AD975906B7EB109",
- "hmac_key": "4B92067CCDC4E3061C490DFD54BD67DAC1C0D51B397A55D22663E3ED1DEEB88A",
- "adv_salt": "4099",
- "plaintext": "A6095B50EA5DDCB5CC28B33F418140A81BE5CD072C914A3DE2F415272478E8",
- "ciphertext": "EC0C166253B01EC19BE4D9C0B74B182BF7653D3611014BEAAFF77BEFEDC6C2",
- "metadata_key_hmac": "9F4338DE4B1D6EE486F6D11EEFD38836C24FB5CD94F94278DAA469B57786C303"
- },
- {
- "key_seed": "136BBB96D2AF5550C57ADFB430735BEF3DC3ABA097D5140DA03D9303B1C5F033",
- "ldt_key": "4DA15F9EE91E5B1E0ECDD1ABEE7A20DA93906CAF1D3265A4E2FA965AC038A7D52DE8865EF45135F22B1D5802A27775621EE6E9377D16DE803D6EF9A6201F5434",
- "hmac_key": "43155F21AD97A0863DDECCBBCE8D4D7C97BA460C4BEA7825E889B9D3FE3A609D",
- "adv_salt": "1022",
- "plaintext": "C9934998AC1B1C055974618CA5BEF8BA67E31813F3CA8FECB6",
- "ciphertext": "83BD9843A8944AF4FDD07F31B4BB591831B66B190B365199D4",
- "metadata_key_hmac": "9B267AD54AFB8C9AD7DF31AB6DB159939660BE17FBAD1102EF760CC824906875"
- },
- {
- "key_seed": "A72ADB129B57EB50466073803CFA5F228799BCCB56B51E1D1308ECFA978209D5",
- "ldt_key": "F8DB3117A89F29C02378CD6C56D8754C2642AB68980BA6CB473052CD5885142CA951278EBA85672FE178DD056DBF8EC178E53C8265C568D2DFA86D5C0C9351B0",
- "hmac_key": "332086A93EC05DBE56A0B368B9AA9D71EC5F893B8979CA274C3A8CF18D9CBCAB",
- "adv_salt": "8B1D",
- "plaintext": "2E6425A8E6C5C35EAC94C8956389BE6C428E6B71C2DF89",
- "ciphertext": "28CA4987C93EAA81A0AD725FAEA4997050A59F1D6FCA9B",
- "metadata_key_hmac": "6A344E851CD0D2636CAF0B63CF336F266C42B0D63A1BD9A19AB9B9D37D968350"
- },
- {
- "key_seed": "E1A6C0886D409A10C782DAAC6AC3B092A20B9AB6848D9009833E053A3B32E2EA",
- "ldt_key": "0B2DC44E38E77542766EE7DEF544505E362CA34AE2AC000CDFC631D1D5DCC0A20182936C8893B785A58B644C3F1827744209E747368DDFFFC0F4D6CB81CE7B76",
- "hmac_key": "994D2DEE6B51B93F382BE2967D26D2883FA53D004B4EDCDA753340BF4816C1F7",
- "adv_salt": "E9D0",
- "plaintext": "AD5045A208D68370264DD1870E99FE894A",
- "ciphertext": "C9B2470634D743A9C262D6B91DEF47FFB6",
- "metadata_key_hmac": "5AD0D6BBAC361C553505ACE3AED2AFA72448755E07D5534513F0ACD5AC1D777C"
- },
- {
- "key_seed": "B4CB7A1612DC27664F812D5583A84514B522D8F4C8A67F315D0FB738B14C4840",
- "ldt_key": "1B8DE912E11FFEA471EFE665C8F543A45AC6F94D0EC3C21FC562231AE116E6AF05D0AA66EB3AB02D2137F93CC62C6AAB88946E7FAF1D8B4CD7EF19B45A24ADC9",
- "hmac_key": "D04F4BE422D7138EC4C1BB479CEB2D7B5F0CEE87A7ACD675B2C96F00FFC33C2F",
- "adv_salt": "BD20",
- "plaintext": "0528D4433F11A53C94DBC6590395F05881E7",
- "ciphertext": "A93D5E5DD8873410CA0A828AD818C3211B77",
- "metadata_key_hmac": "0B4F88AB71A780B90A54904D868C33F33B3B7FAED0B8C3806E051D0169074C27"
- },
- {
- "key_seed": "4437C6B000E28D91067704EDF087FBDDBA235DC00DE2815469E0E6899CD04BBE",
- "ldt_key": "61FB5F999BA7FF93FA2A9799C888660F9324661DE1DD20A732D467348E5CEB451D222C6210968FD139BBB1E803AA91D315D1B2087BB2ED867E116C74BC9DAC90",
- "hmac_key": "83CCF0E05425F30EBE6D9FB2600B4685630BBC05FEC12E72F79388EE4BD063DF",
- "adv_salt": "6317",
- "plaintext": "8D2461F68BF4EEA399297E97A23BDD000B990D42C68862E38F0215",
- "ciphertext": "F062CB1F7552C6E703C5407B934E74BA1B4D365F7068E66C1EF4EF",
- "metadata_key_hmac": "A3FB697D608EE59E62E21100212139351814D09A3BD6E173B2EB15D5B619BE14"
- },
- {
- "key_seed": "3500228F5C517580C4B666FCF0012A701EAC7CA13F0DD3B52DD9CF825B3E6AA5",
- "ldt_key": "FC214F58E66050E9F735C368F791D36D5B88C81C8E5E1F39BD90E6F60A2C97C939368B80EF5A3D5AA4EEFF271A98D5FB9B4CB35632EF9B40138480E846D0F000",
- "hmac_key": "EAABBA44E248C573DAA041BA3E3A8B55800274BC7EC0F0D562F65AF46713F491",
- "adv_salt": "998F",
- "plaintext": "1F63EFD8CA6C056B2DEFC12F3D7122754ECC8E1E",
- "ciphertext": "2EA554485BD49D859EEB73891E3971158C8700BB",
- "metadata_key_hmac": "6ED873A30DCCD7C7CEA004F7502B7F45930DCD0E214666B71EA0FA218F201530"
- },
- {
- "key_seed": "7CA62F11ED9EF8B92887FEBE67A18EA5DA89967A8F9F62CA53ABE599D7C6DDFC",
- "ldt_key": "5FFD5F9530F6D75B096DC0BE00E639366C85CC8B67713C4B3820A5D4F50D46CBC8FE135F2FEBB00FB25513E8EB8799C57C2950AC302562545D2B44C3B688B56F",
- "hmac_key": "47851C20EB7C6FBC5FD08C71967B08C287297B8A45E184A317B9B1832CC34707",
- "adv_salt": "DB0A",
- "plaintext": "B67A0D7E898411E0C116F810579DF4AFE2DE4A4C20E039",
- "ciphertext": "317FCCA9F5A713E8F541C7180385B19DDCDAE9F78E21B1",
- "metadata_key_hmac": "78D9F4E9A50F3D2E7A24E93FC54668AB1FDC1EC23E41AC3D4CBF724758DB4B0E"
- },
- {
- "key_seed": "BF598A4A835B0A7E9A17222757A2E8F52986AED0789886D10A05ADBD27959A38",
- "ldt_key": "A22ADA1E227D9EFF9393C31B800B907E3910DEE1DD72D3EC39B1EC4844745D6AB4828A02F2762B2ADC33AF7EF94BEC8F0C9655536359980E342783CA31647FB5",
- "hmac_key": "5D336540AD62E8151684EBAFCE140BDAF1ED1A7F84BCE7A866E413E13F5B9EF5",
- "adv_salt": "452F",
- "plaintext": "00BCECA59C0DFE0079E540ADCAECE3B7317D6A",
- "ciphertext": "68CA2F327B8A61372376B265B92676C8213334",
- "metadata_key_hmac": "843F297E787BC13E9528F4FF27E8E02D3BD1DBB7672681B1A0E563FD652F1470"
- },
- {
- "key_seed": "D9E312575EF085C178C53FC0FC07C8A36DDEB8379B8B7FE8DCA2FE4A4FE66459",
- "ldt_key": "3C4C2F908DC0B34CC58D49F032F1D797EDAEC61E3BED6FA795952429A304285B1BA56B1EA4ABD562930B360574B2345C4A49E5665DE5B73704BB83949111EF65",
- "hmac_key": "BEA649F9A160DCDA5E8DAF03D0920E7C7D49EE19235C77745A1AC007274B7F62",
- "adv_salt": "6C92",
- "plaintext": "A0FED2ABC74D08D3F5F67E342438BA85F826D6F27A9D1DBA",
- "ciphertext": "45C95EE58DCA8BE9D404422B47CD050CBAA44B6D6F4B2D61",
- "metadata_key_hmac": "76630985E02B91012AF9DF1297DBB2E57B251F098656874E2799E62DD49CE5CE"
- },
- {
- "key_seed": "0977BE1D83362E1C9E9C19085BBB1B9D8B9B238B9D725A534509C8B141F5D952",
- "ldt_key": "CBB12180142008ACA58F8DB2988C0808B26500035EC26721681AEEA2A8231D00E3BA443204921E9836CB1325A8C872518FAD3E950F0C634B7A8B57BFFF280C8A",
- "hmac_key": "925FFDE1A489C7602FCB4E0143099CF854E1164561BEFC5E267398F20168D586",
- "adv_salt": "9205",
- "plaintext": "DDD43ECCB002CD1A6C8472484D0D8256B3237C01",
- "ciphertext": "D06F11B545EFB472BED34A7F95C57CBDA8BA8834",
- "metadata_key_hmac": "9DFF4D616CE50665B79B1F921624A97DB55C8DBC40E0378E060A60E55A9F46AB"
- },
- {
- "key_seed": "1C4F80B40B6F1322CE743AAC976B7DF1081A512E8648DE8584263A45713BB4C3",
- "ldt_key": "50AC714979125985143D95393F55AE570F680BAACBCFABEB064190673D78A46068729076E60AA03485DB1F5134C7A466EAFE8B31C10316757D65991893EC5693",
- "hmac_key": "7013AA48E9A3574810E1D53B78495D37BC41443B95C38D2A22124325511D46DB",
- "adv_salt": "3424",
- "plaintext": "5E047CBF75F0492EC057B9222D56AF8B0228908BFE857EA349BBF3",
- "ciphertext": "27177F6AECCD598EA2F1028E037EC82C7FC172D94640288D9FFDA0",
- "metadata_key_hmac": "40F70383E050A746CF70B8C045E87B8CBFCD61F3A0578C2D6E54118B24C77D52"
- },
- {
- "key_seed": "53487B4FE763937DB3B5676D3099A65B47E8C7769760F9DE17CCFAE477688D9B",
- "ldt_key": "4125C4AED983484DCA9BBAD115F9726DE8704F60AD2605813734DFFDBFC04B5C3F175796E6BF869D4F0C1B71DFFD8767B855631ABD951FFB5F682146AA110E9A",
- "hmac_key": "5504B15B0D6A5EB2BDCE2379CFAF8B0A79F393C3D706B02E2DB0B8FEE5ED5630",
- "adv_salt": "5985",
- "plaintext": "C7AA4F926925E7C32B0097852B43BBDC6EE657E665B5",
- "ciphertext": "00B93FF52C9B252B26292837735FF51F08F5AAD71D87",
- "metadata_key_hmac": "33ED2236B3FD60FFCD79D0D0FD2BD7615522B5727AD01BFB4482E2E9C071F95F"
- },
- {
- "key_seed": "96CE52083A5A57B3EE83B2CFF216EC74B4D543CF348531B5D2AF0F22C5337938",
- "ldt_key": "8C8A19C50EF15ED3F45E45B901A26B1EF2CA2F735B64EE56590561FBA6AAA34E3A01BE98BF21D0BB7F8C15B0CD0FAF673B9881EE46EA3BDD96CC179F3FBB75C5",
- "hmac_key": "4E13FE8104E508E90C40B5E6798F8D2C7C66BAE2FB7D72172CB28C671ED91E71",
- "adv_salt": "C9FC",
- "plaintext": "9C5AA3363518A76FCA6F78A9A04ACA721C7686A5129E",
- "ciphertext": "3A4720BCEAA132E763130979C2B667895D9A7144A43C",
- "metadata_key_hmac": "E85B555DE907FBEE223ED40EB3ABB951B622348723F9C4AF1B857AF652518E43"
- },
- {
- "key_seed": "09914153EB8FD12E76E4C688D472FB3AFECE9092A5E569E95EDBA7C9CB060CDE",
- "ldt_key": "DFD7A41FCD2E25C3CA25D5705B43AEFA82AED9C012F8B9A8A2D3CF4124420C79CC6F307A05B64A6DCE03D229DBF5B6F04751B117140F8258FE02605D5E16CB3A",
- "hmac_key": "89B1507C021A21B16515F6783CBD811D194466B91D2204A80A93681B5902A92B",
- "adv_salt": "49FC",
- "plaintext": "367C77FF79ACE756BD9D6AAF719DCEFF2FF487E94D0660",
- "ciphertext": "C9A57EE439E3E15FE5104DE3FFFB188C5678EC18B88F80",
- "metadata_key_hmac": "D47827E3405E97253B2FFBF73DB2A4D974BE5D1AA2D4692794056A6D1EE409F9"
- },
- {
- "key_seed": "FE6B24AF4BD63BB961BE9E2028E915EC18B74F09A787A1D2EC09C8500D35A2D9",
- "ldt_key": "AB86D686F522FAB3834EE921898D1BADE9E1B301C75623C1E30A12A7E50091224F0010AEBD1801FE111E48D8F99FC3C44C0268277F5B0CEB55CC5A83231FCB50",
- "hmac_key": "C2BCC8076C7C57E59313E29393D54786663FD545D695CB369A6F91CCCEFA49D1",
- "adv_salt": "BECE",
- "plaintext": "E9D0C502DD9A6A82040EAD81BC9DC8A5",
- "ciphertext": "8EA434C4F4DB5EB8BC863299D85198A1",
- "metadata_key_hmac": "DC52B449E596BE9897D7676C5964CF0E6FC5DEA7E95C5FC08731AAA26EAB9F79"
- },
- {
- "key_seed": "D1ACBFF135447C0C8CF94717523538467947B56195529569A4F8A169B36E6AD8",
- "ldt_key": "4E8B09B73126C3107B2B66B8785B6C71BBB0FC29C606B3F641E439C5EB58C0EBF356024097B3F31288124A757D663EAA21A677272C50CDF8D7D64CB5F05DEF45",
- "hmac_key": "0831A40375B7C1612A606FA8EBCF8125BC6E19B50EC94F64985397FDCDBB8BD6",
- "adv_salt": "F5B7",
- "plaintext": "27D5412177348E37C3B1C89CA3AE4EB4",
- "ciphertext": "8FF6C2131447193EE02CD925E1048538",
- "metadata_key_hmac": "EA25CE77A100FF07AE5D3E13AECA7E601A8050C91077C7519941A45CAA215200"
- },
- {
- "key_seed": "8DDE63E8193F2C54E07E30D63EA79005B64C4310A31502A0C6EF724A7D005EFC",
- "ldt_key": "6D8BCBD0229FAB2007EF3E0347CD8414FD59D62CE0673575390CA674AD4F243A9B918F34F892AA7A1CF352C7503EACC9AC2ED2330108D12525104C73A65423BC",
- "hmac_key": "04B016619CD33C8D5C645E581CA9E8E2F3BCC9934401B446D7515099464D0D1A",
- "adv_salt": "2455",
- "plaintext": "B86C750825BB8631F571FD09AFF714832BE98F6FEBE9BF25C43E3D4B3F",
- "ciphertext": "A83995D9FA47C31EEE6945ED27CBC122D4A50A7291EC9CA8C6CA6AE666",
- "metadata_key_hmac": "5887DAFC1430FFEBA2A4540A36111CE6948EE1B4AB796E668949E8B67B27CED7"
- },
- {
- "key_seed": "B70DECFD384BD1CA6DD39DD7D6569A17C00AE084BBAC82A2497146D8E094B84E",
- "ldt_key": "E45A75100B04409B36070A5ECB2A0F11BF1216FFE8803802C25876FAFAF8C68A980AE757C6B070FF9E300B6B14E86A727412BBBFE6C421E4F3E8FA6763C4F7D9",
- "hmac_key": "6C853B742EEA1EE539CBF4290111711B8233A022C246C3D1E3026461A2DFB0CE",
- "adv_salt": "03D9",
- "plaintext": "FDC02E629DF6CABED313D140211D94C0D89D0F287CA7E0054DA2C8",
- "ciphertext": "9F95432869D3DDF9A1A1F7FF297401313C9F25E2247C1DCBC64E75",
- "metadata_key_hmac": "D0A899C00E9F2777FDC3E1BA7CD9A8E674F1263D34CC3A017E8C2B1FD011E425"
- },
- {
- "key_seed": "6F2C0C5D3755C70E2321BB72BAE671C57A32B66BB6F1EC65EFE4EE20B12C8449",
- "ldt_key": "A8A0DDA015D08740BCE112EFC189DF6DA001327052636304B1ABCB14F1C93D54D7C1A6FC5CA4D0746D19816F7E563F7F0B7B03ACC92FE1557F98C4AF6565C673",
- "hmac_key": "9AC72A8585BB66338301DEDA6DE9631BA1974BB8FD92F11B4164081DD5C9AEBD",
- "adv_salt": "76EE",
- "plaintext": "C04B935D3CCE7731E3770E51173FCA86650B3AF95276",
- "ciphertext": "EC2B82DC913347C43BF8CED67FF6CA288751E853E7E5",
- "metadata_key_hmac": "9394740B566FADE591DAF32401485D8669E9890CFF76F6F2CB96606353986BFB"
- },
- {
- "key_seed": "6EDDE96FCDE49C9F543C58453CBCE54014A53DF604C013AC8B8E56DC416308EB",
- "ldt_key": "364C570E73FF40F476373829A6E9290F58C1930104524DA9C248B2FB37277770693FD3A5C234C87DEA87EF4EE972BC3F024F3654079D4CAC9ABA633668C3C707",
- "hmac_key": "59A3A61F03ED79AF2BBA9B1EEC46CFB8126744B5CB92847E26635B9B21DDEBB8",
- "adv_salt": "FFA5",
- "plaintext": "B4E6EDDA091C2BC88DA3037ACAD65FD4F2AD",
- "ciphertext": "819533A059FEECB490CD1334F9CDAC30B716",
- "metadata_key_hmac": "A6BCAE247D01F70F76C69E7AD0C39DD108D5CE8A5CD1D069B0A2D5ECA33D9E96"
- },
- {
- "key_seed": "2FB448C0E6F94054D90E6923760D11AAFCF58A340F8353A48B9B95055E9B407E",
- "ldt_key": "575B5B0E20F5FC215D445A8555A4D10B2F347021F52D373B8001FF3323A0395100D0C25D3F1736D80103495321C0F6DA15C2AC9AE2563C6D701CD81B09C6CF57",
- "hmac_key": "209B89A340DED92EEC8643D979B1D5B5F9AE65DFB65B3DF414B10F1AF8AFC4B3",
- "adv_salt": "6437",
- "plaintext": "6BCBE18F9DB6D133FE1C7B21D955C464",
- "ciphertext": "18783A571581F8492AA852E5185ED1BD",
- "metadata_key_hmac": "A6E52A9BF231AB8F04EC4949CA45C116896D36810843D1EA630795360A4546D6"
- },
- {
- "key_seed": "3641F0DC64B45C0D2485367984CCEF2CF174ABE0E6D0BB8666518D4BE803FAB0",
- "ldt_key": "42EFCC4880378598D34A51398759AFD9B0928E165C3AC53DCFC93792E5ED2C9DBE6ECA49A24B0D7CBAAB623D294DD082936FCF02F4044023FD2C826D1A41BBB3",
- "hmac_key": "4A5697C22CDB879341AC594927CEFAF420172C4C3F29838ABF14280F707C6392",
- "adv_salt": "5AC3",
- "plaintext": "235EC0B6D300EC9CEBBD98755E8CC323",
- "ciphertext": "03B020336DF0BCDB2511CE9AAEAFE8C8",
- "metadata_key_hmac": "583FF8AE8062764675C513674CE42794CC2D3EE086E51BABFC565BE9F3BBA133"
- },
- {
- "key_seed": "685BECA6B5014A5DBB070913A8D614BFEB6525BF352EFD3A7BDE7D0ADF0EDC50",
- "ldt_key": "6388A77AEC7CBCA7FCA99E7157583F4B7E6BB600E257DDFF4092D909F28C5BD70F93E68F707DBD20EBBF881D8A2EA46F4F2A1DC9492115554C1D5573A4A60081",
- "hmac_key": "CD361086080117E9E28D669FABEB67F08A1BE234DD04611F62E84D8CE2F6C6D9",
- "adv_salt": "DE31",
- "plaintext": "2D07DFE1165CEAC2EA713707F6C36C3C6C6546A79BA91ADC05555CB2",
- "ciphertext": "3F327602B2C3CBE5F8642975AB5A0784D2CDB2B8BF1C27BF711BE5E9",
- "metadata_key_hmac": "9BE6EDC04FCE101B576A36F8F4AC314167EFE50ABC237AA0F9C9ECF01C3027CF"
- },
- {
- "key_seed": "0019B7D1FB73E265ACAFBB59FF225BA9C94108CBDEFAB4E0289E3F1DC8FCEFDD",
- "ldt_key": "3F1F214F47956344279BAA9F7C65A59641B27B2E4590D61B5E94A7280A8AEB6842EB5544B0A2A4F53EEDFFEC35EC0C901C77E8E54787D8958542D0A718809DF2",
- "hmac_key": "13D9A2C2C917058A252851D47ABCCB004A5F8FF4B23CAA2AE98859955AA3207F",
- "adv_salt": "678F",
- "plaintext": "03FC57DDE4A9650C2E5A7295AC8161C416FF51E674DEDC4B3DD281C0DC6A",
- "ciphertext": "B81F9283A26F50E301B8F7E9D5D913DB1AC3880CADF9E0ED6921BF4B68C5",
- "metadata_key_hmac": "0EA5A3D7BFDCAB5340C756D2BD6ACC70A3735C090C58E7699AB37B7FB4C58DDE"
- },
- {
- "key_seed": "488D217A78E794D2564F491ACBA28B0ED034A6541906BD375728E914D95D8AFF",
- "ldt_key": "BE46614BE993DE7D226411658345B391019BBEB2D9A0DD0935FD34B0755F330BCC1D0CD1BD61FE81AC111333398BFDDB29B7D6ED2743CEC687F0A6A583FDE36F",
- "hmac_key": "67C099001CB579A20688FB102A37B73F0465FB60BEB6EEB775ACC00804993065",
- "adv_salt": "E73B",
- "plaintext": "A4F4CBB2D2B5B8A19CC04723A6C7703F829D7842C57CB239DCFA0D5D",
- "ciphertext": "9B72548B9E48FFF51F438F8B10806555E15F25CBD8663B24A34A06C8",
- "metadata_key_hmac": "F7679F19AE53AC432FB8E869B7CA73B716A8FC5B541A0AE2B8372533F96457CA"
- },
- {
- "key_seed": "485D8F445B7B2C5E745B9B609CC0D244431579C7970060DC19CE8EE7A7426BED",
- "ldt_key": "F075E4B12A85ED273AB7172B3589F86E6DDD5748AEDCE7C3EB4E51C5471669CEE271FE0DB894C93AAAA3B4C0DD724B71CCF4FA2B71F2BB74B1584E936C023732",
- "hmac_key": "56232640F0F1DF1D3A016DD36FCBCB653078657118BA89CDD642D0AC167E53D1",
- "adv_salt": "DACC",
- "plaintext": "8D23CFDE6FACD0CB652539D88F7FC4E2C423DC48C4941C7B0EADBF3926",
- "ciphertext": "508E83A2E42DA37DBE1691DBCFBC8A6BCC82C89EDE451EB742F0E39444",
- "metadata_key_hmac": "ABD51FD47ED471A1C3E1330AE968D50114829FE177608AEBEEB32285C122E614"
- },
- {
- "key_seed": "716163538E5A30BC0B729AAAC08414840FA0670026770932E959D024C0E5D5F4",
- "ldt_key": "06BE7195DA1F38BE149AAB2EAC68B0D696B4AF445018D24BA5E6760D057D8A9055A594F561752F6155A06697865005C0C75DC7B4B0BF58D457E6540270302426",
- "hmac_key": "5A5D09412CFDAD3A5D45E5380A523F294657770770A44BBC35CFFF414B46E39A",
- "adv_salt": "0FEF",
- "plaintext": "535A76826D569EB754425239A6B06442FA6F2CABC86E9D75",
- "ciphertext": "51A5426141361858F37284EB7063B9DC72548CFDC08746BE",
- "metadata_key_hmac": "6DD2E45094D6B3EBAD158AB704650959A1B540AA3487E3A1D502B29F3C3CAC18"
- },
- {
- "key_seed": "33BB71AACDF4DAC6C324C119930DC5F2998CCACC71F6FBFB0D01B599718A5379",
- "ldt_key": "96D9303DFB67749BF813230BCAA0A5D47155774C4B60676AE25BEABE0A0956B02F236066D8A31B0A6A76A50030A239A1F9A9BEEABBC1AD88BFF752F8E3479009",
- "hmac_key": "9E6F8014FCDD1907BAF7904F0A201F47C1BDF4BDDBD1B955418E1018427E02C3",
- "adv_salt": "6BB1",
- "plaintext": "47AAA95EEEAD354B2B66430652A98841E98BB3C219A48043",
- "ciphertext": "9EFF3A52E1B8C1E6A8F1C8BAFF20D44A5ABCA86138BE92A3",
- "metadata_key_hmac": "DA5702D6A807202BB8E07E947DA8B0193F2457F5D9461D02EB27206B7199F47C"
- },
- {
- "key_seed": "232013418F8B9031EE4F9751505640DD4CB234EFCC785DE93F52CD70BA444162",
- "ldt_key": "788D8B5EDAD8B6C5D44B7F1B28B2A06DE2D5759FB27D7A7648C53DB87B578459BE0265BD6F6A32AB277555D9702EEEE2BC49C5F6042C45BD212598A8897792D5",
- "hmac_key": "BFE3BE2425415CA34F28827BC365DCE435417B7CF7DF7F1E803288125EE094A0",
- "adv_salt": "F31E",
- "plaintext": "E07EFEB6550045244D9827CBFB89891C0FD08029B56B",
- "ciphertext": "320357CFFE46D4547F4853066F795596C2082091FD43",
- "metadata_key_hmac": "A5B0D5F6C746A49C9C07ED720E2C701054971EB221516553D4D5856880C59E50"
- },
- {
- "key_seed": "23DFC8F778AD70A4C0C884AC825DCDAC443C1E579813E4603B38A60792411439",
- "ldt_key": "1FF1F7C52647855CAB71E7863BA7CFF87892279FB3565A434BCFBAE75974987744A4FBCC0452E61DAF3D101BA4642027A31779215721470FBFD42431B4C1C6F8",
- "hmac_key": "7188060CF40F2AE1C6C1299490C40724B1A457A8D35C092B724F65BCEDEE9D95",
- "adv_salt": "5542",
- "plaintext": "1C6D4D247AFF8238480811001C5AA4B0067AB30C389046",
- "ciphertext": "757BEB6256874C7B2A98B3DA67F55B86C80E0136F1E220",
- "metadata_key_hmac": "A6A0FFBBD2F80EF58F9EBAF9ADCEE83427A69B2F05997B5BC072121F036C932D"
- },
- {
- "key_seed": "875DF83728064FE79641949D18C2C61C9D34C13F3FB7AB8F239419058E9F9374",
- "ldt_key": "684E1C82DBCDE7A034C4C5823AB0AF4F2FA9ED2F9A43065E5EB7EC17BD51FD1044FBB1B1C3FF920BEC1952F395C5061DD5AB5AE3F99A8998E69BC45827E61028",
- "hmac_key": "8A50A84361709FF3BEC15A32F90385C70AA220F3B8809EB0AF2191DE941F36C9",
- "adv_salt": "7216",
- "plaintext": "5B2893F2D895E7BE7129100F96032E7CBB9D1161F2888F7A376EECEF4912",
- "ciphertext": "639A0589557F3B11A52ADB7407EFBD77BE8250EA6DDB7E333B0E164609E3",
- "metadata_key_hmac": "18CB527EC194B70A260DE822B875EC91EF25024A31324E43315F3A3541991898"
- },
- {
- "key_seed": "65219AE898F2F96E915A029F7E6710F4CDB346EC316C12219081351FEF7A8281",
- "ldt_key": "B315231A39CDE17C33755E1FEC5B1DBA05507E4F7D11B90F4EE47767B59ECCB57888FCAB4AF8FF8328320A023A18ACAA516C88786E0ED28B6C61262B4918AADF",
- "hmac_key": "B433027A9F895373BBC791DDC0B8B497D1BF04837A65998C0EC10436B52044AE",
- "adv_salt": "C0F6",
- "plaintext": "CF1955300119D84EA6F973DBAD44A200B174A9BF3A5A2149D1",
- "ciphertext": "597DF4D1EE2A6E7EFDDDCBC3E0C7AFC6F025F53D8590C59169",
- "metadata_key_hmac": "FF981CECE4C1478EE589AEB939CED3F38E2F29D34F7D09F62B492B7C9EC45204"
- },
- {
- "key_seed": "BAE9126590BE96CFF06E1544A2E8F48CF6B4A5B11CCEE12E2444A2C6BF741C85",
- "ldt_key": "BDA2F3EB007F968A0849168D8112F6B3E792136501024DD838AB308A746D79FB5EB543B5EC9E3A2DD820E198885B847564B513BCE03EBE51C3FD4737E1B63D3D",
- "hmac_key": "E878372A53B7BE8D20FD7E103A2643825772595FF0B8C5AC978FD5367B4DE35B",
- "adv_salt": "0390",
- "plaintext": "28FEEBA8F984FF274C540B0C5D2F2D68443DF3DEBE43FE5B",
- "ciphertext": "6832BF61CDBDDB038AA95005792E058BBD2DA9C2E8CC64D5",
- "metadata_key_hmac": "EAE978A7DABD6320E3FC862AA71C9D6DE9628FBF3881EB33C78235F5E4C2A34C"
- },
- {
- "key_seed": "109C2F5F20AD4F553C85F83A182A9D62851C95E69491C53B557A5BC6D90AF8D2",
- "ldt_key": "8A3AF1C3855297D53CA1E6703A3F7CD5CB15307008A6DEB41FF717923571A75B678EBC74F0F6DEA14841A1B2B5BDE921FB893BDF6B3B1389AB4348B9B077FE9B",
- "hmac_key": "1EFA63683DE03AD5064A6EE69A703258DDD915266782ADA713B40F621E97A689",
- "adv_salt": "BDC9",
- "plaintext": "9AD3F734157C17F1C829CBBB7B430190FD9B180BABB4E195CDCB0BB3E320B2",
- "ciphertext": "DF537630E902866F6A2073E52064B2209BE1222419F11F8E7C477B0C290D25",
- "metadata_key_hmac": "587C7ACBBC8EF7CCE44AA449610D88F203A5E2FA1B5CE9457F89238C7CE1F2BD"
- },
- {
- "key_seed": "0BBC490848590D4E07973036F913280A7A34E55EAF14B878C07B80E9D484AD3D",
- "ldt_key": "E6BA55F41BE5D38F1570F4561602E02B225F99D122B433B4C90646AC2017CE07C8864FE1B36336E2E40B36FDD32F2D3F21E84BE10878200E352E326F6906FA93",
- "hmac_key": "11D10505FC70D15013A546E32C6EC475DD5F8E9C6BF1AA9DA1BBFF20A703C039",
- "adv_salt": "7D9C",
- "plaintext": "1D83A3FF4BE2AE5BB09598EC28E77D63E73EB465DF28A4813D",
- "ciphertext": "B7D30ED112ABE6435B08D936BB7159AE441B6B9367CBC2FE33",
- "metadata_key_hmac": "CE7B627C481737ECC02486BC6C128609C433EF4E73F7CE150B2BF80437353A47"
- },
- {
- "key_seed": "CD96D439FE372D567D9F0EFCA420D0A2B32118BD30A8079A9F3A62190CC1BA0E",
- "ldt_key": "9DD30C9B7FD8A11D9278BD1E6EEBA4A0FFB78B3421C38BE0F10FDF064FB498B66D1DD6EE7193B2E3B05E96D9AAD6BE3BB089F29155A740B26A9F73852CE7965E",
- "hmac_key": "A56F9DA0A354559145B13427F306B6E2E6EC8393F158838226EF24149B4B015B",
- "adv_salt": "5132",
- "plaintext": "F00F56084310A93D97046C66F0ED55342C1440",
- "ciphertext": "3A53A5FEAFA24F76BD376E44E55863E97C707F",
- "metadata_key_hmac": "91F37258D9F2B052E80EA96DFF9257D36D8D6E59E0F0F42C86070C132741E1E6"
- },
- {
- "key_seed": "6AC0B7FA31FE70DE036B27ABB6532F3E10DADAA08F0AB48DAB6FAD53A0F931E1",
- "ldt_key": "129862E2C4DD74B83885F72AAE50AE59A15C92EAE9E709EA79BC9E1EC1A4DE0094F52B790F08296EA1451A440A96B3161A0AECFF0356AD2C5C0C7EAB3D079131",
- "hmac_key": "2A425FE28BA08A90BDDAE9530D99B1EA68EB50498FA5CB4CD1F66F7EF96305BB",
- "adv_salt": "B882",
- "plaintext": "936CB92494022DE43070F6DAF16E1D7DA2E3CA",
- "ciphertext": "2DA153F11E24D634FBB51FA745836A59F94F04",
- "metadata_key_hmac": "3A9B7D8F90BA011B74F7B8040C00DAAB738BB6FCD37DE15F3DCDBBF1E63FFBA9"
- },
- {
- "key_seed": "09F39A3914C684F46C5F06578671766E978C50FD36685B81E3D642A656AF40BA",
- "ldt_key": "0DEFC9F52C67EFCFFA6FE18E769807594A4E42855E7DC5F753A389BDCABD97E73651D4D5696CB353950303C5F82AFBB05BC2CEE2C2F70A85D694D14863086D23",
- "hmac_key": "D3534CCC6D4C50C7D368F917DAF9962A12B997D4C3D06C1DF663D4B79C36F322",
- "adv_salt": "5A17",
- "plaintext": "5A662BE3A033831FE0B8956E1A762A8DD614",
- "ciphertext": "061BB8DEC19F63C11FE26D5632C76A5A5DEF",
- "metadata_key_hmac": "D3957BD4E2CBE0846BDCAD8ADBE67FC48CD21C6FECE10FBF84C90D0CD9114BC6"
- },
- {
- "key_seed": "08CC65E59BE9634B5936A72589A61C008BF420A274F34430C50A1B838BC01CEA",
- "ldt_key": "F92F338C61FF4F9F0CB3A1DA8C106A95BD361B0224D960175A6D09E0EDBB21F3AD8CE85169226E1ACFD7FEC5D7BA3940806725CFBB3C1050A5A0F38A90E9AEF7",
- "hmac_key": "CD1C3B1E2F824475577CD4D15877A2A76EBD0F837EBD6BB9BCDA6A704CB5AD1E",
- "adv_salt": "5970",
- "plaintext": "A5E1068684761A0D70271BD1FE3873661B932B",
- "ciphertext": "E2C22F7FA98BF2401A70A034FDBD4562B8A4F3",
- "metadata_key_hmac": "A69562623B2C229FD9244BCB74521FFF607BA4A9E4708EB43E4E5DE96AA62A46"
- },
- {
- "key_seed": "5D05F0C3C565C04174FBAD35825C70EAAA93EDCF6863D63596A9BF34E52364AC",
- "ldt_key": "F3FA9145A23FF47C252F6E000A2FAD8A238944C72935C095579A615855A11C1A8AC8ED5E0266DD24A2CF1741D9BAD88CFC40519D28B8DA06BFFBBB39D4D7C7E9",
- "hmac_key": "85AE2EA76A1DC03FF6D159C41A156B4BA8976F74F1265CD6905F71FF9917F247",
- "adv_salt": "0A50",
- "plaintext": "0A129F5CDA6ACAEE1BC5641A71A4568ECB5CD5",
- "ciphertext": "6B2BE584850E7D973B1F516A6859C00F455456",
- "metadata_key_hmac": "C69F4FB11E701E21096BE0EEE182BC1743A4D863A0F37953C64439DA1C9D4AEA"
- },
- {
- "key_seed": "17FC70D50F24295D49A988C29359E028B6BA3B75EFA77DB8A3B23FE2B03695AF",
- "ldt_key": "E7558B69103897B40C4569145D74E28AE29A96AA79BB1E487A7160710D82373A5A0F1D8778DC1FCD240A5D5EA93242312FE7D752AFED80B3E70046BC960C9B2C",
- "hmac_key": "C1A66841CFF728515AD0B8C9E77AF42264AF8BA0CD1A9C3362024CDA68B4C086",
- "adv_salt": "11BB",
- "plaintext": "6FB7AF0C98551542E36C8EBC5D4C25D476B91E0ABBB39227DE",
- "ciphertext": "0E847F778E48B88FAE811C2AE2BB51246036B2B51CA4F3D0C8",
- "metadata_key_hmac": "0DC922B4E275B3782046CEE1927E1C4A0D570AFBD9FDF46973D7653AB6505E27"
- },
- {
- "key_seed": "83A488370765A337A4664233541ABAA97BDDDAE319D27B5C1E04E98DA84D4749",
- "ldt_key": "D6ECAD695D630564E9B1B679365173F5B7FEC0E8A7F9C08810DE19C7EE3D69398C699912E1C4DD750D0A216685D6CF3E537444B929816943F768594294DD29A5",
- "hmac_key": "3F5E333F6AF76CB35D472350352D6BA8657BBC96480CF7DFFD44F15815C9E622",
- "adv_salt": "8FC3",
- "plaintext": "3410E19366142F47480308BC477D2218",
- "ciphertext": "7FA427047525AB940C045A6C0DF92866",
- "metadata_key_hmac": "61E663BCD496891A9343771FDF3C4C563D47C7DC43CD11FC16C1306948669986"
- },
- {
- "key_seed": "B72DD63FA9D8252BF9014F95D839A4456DE0365C02823AF867C95A39F77FCF55",
- "ldt_key": "4D4643E0743CA07CF45F61C8497409B46623C063D2669A34096BB81CE15652EB79A94AAFF31641ADDBF6509C705F6FBBE935A6C3F6A9A7819969A1CAE8A9950B",
- "hmac_key": "ED9C18B859184698BF0DC9873921BF728541E2A2FC6AC1557683AC7713276A61",
- "adv_salt": "3A6B",
- "plaintext": "C8DD3D2910AA498BEC6F06707D6CBA6C06B714929C69D663",
- "ciphertext": "FB89683FF049F0BC29903547C231A54CED45AB35B9DEB5B7",
- "metadata_key_hmac": "927BF5AA80EA9FA2A1873D9A6A656AC9BC75368520D88C458E64B7715C0614EE"
- },
- {
- "key_seed": "950CCDBBC52B8907EA6A3826F08F5F7AE9B7460CE0796B2BAE9B1E3C27536E58",
- "ldt_key": "D8AC57AE1F4F96C166B606DCC9D5D161F29DB96611EEF8AB10B6FF43718CD98CEBCA0F29BEE7BDF2CDEBB43630E0E9D40031290A7791055F8DE4FBC657251849",
- "hmac_key": "923E93AE40F806A497C9D9AD1C047BACB1D96A10ACFFA45F90D2825B9DB81016",
- "adv_salt": "EB6D",
- "plaintext": "D6C6DFC0C7AE5CDCE58830B1FF4869FBE79DF2B61A63E700C3C0",
- "ciphertext": "E92E58BDE7FF8C5817601FA3324F49FD981C8ABB3A3DB1223643",
- "metadata_key_hmac": "6136016E27B91ECC645ED2A5EFF0E4F2C39464D56A462234EEC9A162F6004417"
- },
- {
- "key_seed": "B83A0EE452CA424AF473112778F4CA91F5CC4F86A4D3DF69C48FF5D125F20747",
- "ldt_key": "2D65D82EEDABB27501C1645ACBCF2BB0B4D1D48125B179A20444984C0D9449FA779F70E82FC8CA1AB1F83E0C7CC2774EE589A36FCE75BF907C601633942B87DA",
- "hmac_key": "3F837B23AF92192D5F1AD978A1331224CEFA584F0B22B078DF43E8DB7CBEE483",
- "adv_salt": "9621",
- "plaintext": "2243131E829C96967395D38A43D04E0080",
- "ciphertext": "A2CBC17881AB92B05FEDD78AF267056AAF",
- "metadata_key_hmac": "8DF19D5C532747BF2E6144C422456F44802ACC9C701F5E40ACA30CE72DB674CF"
- },
- {
- "key_seed": "087F657C20994BB468B4D1A0554DDAD7F62FFCD626112104BAA5EAFF2EB32A04",
- "ldt_key": "71EF74B6B1485D7420F59D0FD9D9193138722159855D1750AD3E62467DC42FFA156A7E77FE1A7954FEEEFCD0A3872F37AEF600251FE5816553DBB0F978D14961",
- "hmac_key": "7795AE62264FF7A8706FBB81C309C912FF248CB858BCAC99E1443BB7F1D60294",
- "adv_salt": "67C7",
- "plaintext": "5E2042B43DF34018929A46527B4D822B4AA4C60EC638",
- "ciphertext": "A60C54419E962CE4C7AFC12047939E3FF219D2520D58",
- "metadata_key_hmac": "67047E51091EB0927B2C98A442A95233B289AD364842547038EAAB94D7A1A55A"
- },
- {
- "key_seed": "22740ED4FDE15B558864234FDB558B107BAD955DC9A7DB8552E3080CE3C27C95",
- "ldt_key": "B9B8C45E60AF71A00F770DC18D9E9C5452D52EFE41E217AB51F6DAD6169D756FA58AD7D55447D16B5A72CA20F7BC584CC033C0B4DB162267DF17CAB217099F51",
- "hmac_key": "9DAF080402575FC679A9683740FF68C2467DCABF70570A7C32D5BBC8F538F697",
- "adv_salt": "FB59",
- "plaintext": "D8127D2968378EF5C353ABED92710C430749C65834AAE01C",
- "ciphertext": "8B834EF490189F091F2E92322E80686D0A9514D84D8D1A1D",
- "metadata_key_hmac": "28DE764F1F61C810E2B99F5733CCBF683DD7264587C598CE3F586B619716C555"
- },
- {
- "key_seed": "83B9B1B616864B6F5FDA22E1EDC9F8D21306B67F539C03284A17A6ABEDC6E3CA",
- "ldt_key": "B34074F91686F78A6EB198B07695A81B48AAF40FC88CE86C7BAF0F224126C714EF4CC26285F582DA58C2B7B32A58E92ACC606178C7408AB5061DC9B31CFEBCDD",
- "hmac_key": "1BDAA56D0E5CE06940CBC8EE9A3CCE1ED4C89C72E95ECD56B0941DC099BEDADC",
- "adv_salt": "2349",
- "plaintext": "7B18E0F8718B3F8C48E70709B2DA75011838E48A3D2D9252D7DF",
- "ciphertext": "A25A5F69E9E0FA7F6FD44CB4D0A222A8E46869AECAC407391811",
- "metadata_key_hmac": "D9825A3CB4DAC96669E1077E32262DD8172553438BF9661F68ADF497ECC35F8D"
- },
- {
- "key_seed": "0C54D42972E04ED6DF6AD67D7335CF041801FEEB27D4C1C4295D27CC39F97E44",
- "ldt_key": "5420CB503AD81D477B3809899E5A776766926D60C06DA894A2DA06A0E898E19294F78921BFE7115688D34D389DE790843EEC2E119E075768F434EEFEBCFEBCF9",
- "hmac_key": "6346DCDC7DB968D413C1F25532E4C813428B858C835E8DA3FD3ACB56A120CB01",
- "adv_salt": "701E",
- "plaintext": "4183540891E4E06BA22C7900ED93E2367E1EFEAD7C6E56552422",
- "ciphertext": "7F8E10450986178E2A3D7F0DC5F5B9A61B39062BD4AAF7756581",
- "metadata_key_hmac": "877068F263B8A8C4D1840D11690D47DABF1115EEEA3DCC04ECF8D901C8C5663C"
- },
- {
- "key_seed": "53DA12943D8D712ED58F30272C0DCFC5701CD65F0983430509338AC9DA9F3EDB",
- "ldt_key": "C0902A392612ECFE565D8BACC7D2EC977CD90A205BAEB0CE6FB172BA7313E4D9E90029D80183475005462508200C698C0064069BAE43BC0FB79F6966D24C74EE",
- "hmac_key": "3A51250C6BB80349A408338D6E71605DF2E2A81E5C33FF44CC4417E5E0542BC8",
- "adv_salt": "7D6F",
- "plaintext": "9219E2FF4234E8FD54ACFD6707CA2F01B14466A615D7BB4CC2416F",
- "ciphertext": "D6C18DAF849217FDA4A1DFFBD04E35700DECB6F45D3B7A0DAF4AB7",
- "metadata_key_hmac": "4EFB7158895B1118259C54CC78E31BBB248052CB7AEDC48EA3DBF9FD39296A9F"
- },
- {
- "key_seed": "1E6AC45BBF875C46F03D16BFA541F3C181FDC51C8F00277CBCE9735A04496AD5",
- "ldt_key": "D1226CD808D45E56287BDC9F6F5C45118A83E977CEF98D5BF35E39D736ED9E8A027D9D8F91CB87EFAAB5875A76EAF426674D0DF3041ED675EE487B01B1C600CA",
- "hmac_key": "DD7580EF1D7F8D122F5432B33E4C2911FB521597592DA98E417214187A445566",
- "adv_salt": "DC95",
- "plaintext": "A1E76EB381C8AD7047F9B2E67C2789EA93EBF172",
- "ciphertext": "E16CD310310FD8457ECB96D1450FC0C096387CDE",
- "metadata_key_hmac": "67AD4504949AFEC5C4B22146D1303075AD944E8EFFD79DEEECAEFE07BED7BAC2"
- },
- {
- "key_seed": "FAB8E36C5FAB89B4A67C62A5ABB644DA927D761C73DA1CB752BFEAE067A26285",
- "ldt_key": "236FEFDC6DFD2A5005E380B19E29AB9C381B352E2BBAFC96EB39256B4F895E8251D6A4F8BEA0A37995E44B6C3F590D672CE8834588B61DC72442404D4A782F50",
- "hmac_key": "85EE128C20AD8BDC2438B9226AF8D63B7299C430374987C9BA4F4ED377E5CAF0",
- "adv_salt": "E201",
- "plaintext": "AE2615F362002880DF066101987A5A247FCF0142FE6F4FF62A8B3659EB",
- "ciphertext": "A51E655F1F9529D04969FAFB37B2D210C6B0100F5AAF7958617EA36A64",
- "metadata_key_hmac": "2763E57A98D0A8B527492F8D6FB15890530F1825D6C8059AC0876A42A0F84B70"
- },
- {
- "key_seed": "8CF75065654AEDFB02C685D64A1CC210E762407359B6DF694D97529AF486374C",
- "ldt_key": "E6B41278D53C9E476A4AC0590D6EA278E575796F1BF2F3E022F34781712214ACC076DE96F426124ABA1FE86C8B01B54C1F96D98542584A20C0D8ACD69C6EB64B",
- "hmac_key": "BD06283AF2F0E776B88A753F20FD137A9CE1D213D6A893250E87ED014ECD8B54",
- "adv_salt": "BDC1",
- "plaintext": "4E63C5C8671534EB2B4063213D826D63C3E01B0DA9D4300676",
- "ciphertext": "4CDB57F79D08EE51054B7B444F73ACBEEBEA44630EFC68108F",
- "metadata_key_hmac": "EDE114A439EBEF9746C26641F2B4BC245FA140729FE3D405AE3CACD21F1722C7"
- },
- {
- "key_seed": "17730EC3D96E1263359B9CA680A08D56D3FC5056700FCF09F798163A250A4EB6",
- "ldt_key": "8906DC897690FA9525907A8615412B7EA3398330EAADEF9E81E66EC60C57B06E278247B555260F9FA08FB8DCA30B029CAF2824F0FA3BACEC9286AC86DE6E781A",
- "hmac_key": "AEE16B10773600CF83DF5438C878C6C6C2B88F800C0A86EF7C33D612230C2B8F",
- "adv_salt": "F273",
- "plaintext": "D1753D0D1C946B0675E0840CA9959B48FC",
- "ciphertext": "837B7931396D61BFC40CCC3EA214F70213",
- "metadata_key_hmac": "128F337336B15BF3217DC2E70921DD43B7187E72F9EBF20F3B078D76192F95BB"
- },
- {
- "key_seed": "97FD64DBB28B443B0930485D40C765613D56E0CD0A4644D2D99A9067483C3633",
- "ldt_key": "61091495FD4558096DE0C41BE4B1A9813DBB412CD427D98F01E78394264ACCCAE582A3BC844AF73E959BAE7046833EE1C2C4CD2D6B2AD8E80232E18A2D286961",
- "hmac_key": "37F9790651A5AEA01F66202839BE7FF6FD3C7220A5A2B4A37BB58A1CA6582502",
- "adv_salt": "8EF6",
- "plaintext": "57D3ED36ABA8C351D67AA527DCA7C765F34C0C9305133BE1",
- "ciphertext": "5CAC5FB471CE1B42C971A05759BEA52F8EE020D3DE4CBCD0",
- "metadata_key_hmac": "E2EE7CCA97C67B77EFA1649079D9232ADAF8E01FFF19C481B15EB4B48D4D2E03"
- },
- {
- "key_seed": "CDEEB09CEC920BD442BB0B3C38E1F3D324C444E2516D701B454C60B35FEDCA44",
- "ldt_key": "320A5EEFABE36D8B311F5B25CB697DD0505710A21E342EF27CF81D3DC7C3AEC5AA64404DAA559F14782B0C9DE40D9B50E1334683E3224C248A2C243871C8E3CE",
- "hmac_key": "6798896B6D3FE3A4D4E1F3078D3CE048B5C7BB14502A5AF467315D591414F34E",
- "adv_salt": "D554",
- "plaintext": "D5B92B58F17876513109A4F9A51C046E595345F87FBFE6054F",
- "ciphertext": "93F45B6957AA4E7F99E5A5D6E2193111459644D663C8DCE02D",
- "metadata_key_hmac": "BC2B7855C12150A3AD611E352006FD420F6AA49D490E131D41F4BAA09554B2A6"
- },
- {
- "key_seed": "546F7254270CAC17DEF49C7B77BB84A16957D5EEDB95A35C97EC05F9A1CEAA24",
- "ldt_key": "92DEA1F347BC8675FBCF547C12C287B04DA4B40E93E2A0907FD0DD7E341E5BFD2312D343345C3487357632D956CDEE0F5375D5BF60A0BE9E6207ACAA23741467",
- "hmac_key": "2D331256BCE9432E34A97DBE670523A778FBF614E1099698A5CB8F5D07198BA5",
- "adv_salt": "73F7",
- "plaintext": "66F72BA85D73126D5BAF9C7A0F79D2E72D9937A63382F7154170",
- "ciphertext": "AF1BE54DEF9C33E2911171200C169C2CE377A7A8E61570DC7F80",
- "metadata_key_hmac": "BDCC86C3E7260BDA5044A61BB60137BD2250D0CF46BE119E1D416A891319FFCD"
- },
- {
- "key_seed": "C0EBCD9AB79CDE3CC1ED4431AEEFDF545248027DCDE79188B88A8C00BD62A93D",
- "ldt_key": "A0B70A0D9F9F19EAEED65C8E39CCBFE3FC8DB8D8A9E3FFA5AB27A2553F6DECA76652E481B77B6AF88A05F715444521F277B4511EF5D632B72956089EE728EFF7",
- "hmac_key": "CB3236217C641E142F6B5D2DB1EEFF7CEF884071D75C71B4EAFD3836375CCD4B",
- "adv_salt": "4B03",
- "plaintext": "0314C8AD613D415F0381128238DD4D4FD43B",
- "ciphertext": "A850382DF4F4B9C09518AAB95EF8E6578FCB",
- "metadata_key_hmac": "0B0A39987EA7B620008F587D5E89811D3F7F72F0E7F015AF3D7B0985D62B1A68"
- },
- {
- "key_seed": "7579F96F2D8375DDF0E1CCC2DB73000868593D17ACA3F093091905EED1F9909F",
- "ldt_key": "85AC4E459B6D5CD94C0FB8D736F7E83C964BEF9503809AAAC9397E2D808E12716A4F15E31134E6B4F845B70112BE998A0D1F89A1D3C971E83AB976087FA81CC0",
- "hmac_key": "216D2C0FDF58F6D59E1BFDF1B008FBDCDFD1394D1110F79A75D4EB7D49ABE671",
- "adv_salt": "AF8B",
- "plaintext": "4E97AA3A8FC3BEE7E767C1FF9EA619006493CD",
- "ciphertext": "9026B6301989334B38E41EBA57516A311EAEC2",
- "metadata_key_hmac": "2D0604BD8450F53C0F4BD6226497F5A9344A6FA5D913D95901C0FF58984AF963"
- },
- {
- "key_seed": "B36D9182A1048F7C73E3BEBCD3A7B3A124C9C0ACE373DD4B59E0A16C71FA77E5",
- "ldt_key": "356AC88D65AFD472CFE5E3F91AB0A6573404D3920C56A51636D0A5309B1B354E73915D3A9EDFCB08EB0A16BA997ABA8E28B3D0E977F57998C6DD2EFE5466C8CB",
- "hmac_key": "A305DA096E08319A4803A625C42696D4FC295361B609493EDCF77381C43FE834",
- "adv_salt": "C0B4",
- "plaintext": "FE978ADA025F90A85B881AF60A2869C1",
- "ciphertext": "7E71427B133726743A2E25301EECAC81",
- "metadata_key_hmac": "83BFB085184BB8C36F59B8BD3E0C9311E0938F727942767FB0E071376DB3A517"
+ "ciphertext": "2A178D14AC6AB43A4D4CE5518DFB18812AB5A775A92C53DF",
+ "hmac_key": "A4EFFFED83FB0970C2AC5D129E96559D2CD556DB229CF5B6577847EC214370C3",
+ "identity_token_hmac": "95E77505F78C78695FAAFB6073ECB7A19CDBC343EB3111927613E21A12430A08",
+ "key_seed": "3DF510C1EC101D1F4A41D20932E9503571EF92898C34D6A291D6AFBCA96D5982",
+ "ldt_key": "CC2E135B687B2D841810F96B9DAB9A6A8F32335A5A9A224FBE6ADB6FE742F157E91F2B397D4028F9F0CE20FB760F8870AD295E29A1F9DB4BB85CAC876E220560",
+ "plaintext": "DD2832FC6623AA56C4BD9293B036B5194D676566DE94C3A1"
+ },
+ {
+ "adv_salt": "4568",
+ "ciphertext": "471CD1F0BBEF830CAF51C91D58FF285107B27FA6E3A7BFF2C747D2",
+ "hmac_key": "EF8EFD105D39D95ED341D23C9CFBF1F946C894D9E56FC1E2D42F0B6BD91B37C3",
+ "identity_token_hmac": "16EA251947E144EE1FB14C3233A90E5165CFF4A35A2BBBC778FD1927C05ECE2B",
+ "key_seed": "FD10C04D5266C0629A5591F158B94F4F27F362F7CAA0FC65FA9C45B15A368B11",
+ "ldt_key": "BD876915705EAF5D40B71C13DD21DA541443165C3590502E8E833831C6DC987C86E6052FA0F46133AA9446807CE761C337711F6572D80F02F3F0F7BD7F399351",
+ "plaintext": "7C5456D3085F9292D5B3A4C74FB3A94477E91DC4ED6E34EA36AABD"
+ },
+ {
+ "adv_salt": "D733",
+ "ciphertext": "D34FCAF70EE1A3B16F39DF081F2B1E18BB6BAE100BF9",
+ "hmac_key": "E2CD0A84E585324F74B14760CED8FA3E749230B8EB52D9482626A2BC79C419B7",
+ "identity_token_hmac": "392EAB5592B90BED1C6D8148324B6C6A54A2970A7E6E8AD84F9A1E35B00C7FBE",
+ "key_seed": "3D70F1284B2007EAAAAC0107E63A5E29DFB1B951BF67F74A9F454C1540397466",
+ "ldt_key": "E2C0B7987BC05CC4FF3AD406421FE70F65682191708A7C8BE2B0CFD35AC7EB6A014CA36540240A83C202E1F8C8F64DFB201A85A38FE0DCDEF5C7004DBB2BC6CC",
+ "plaintext": "DBC428E33858278C6190505B43357EAF0AF3569BCEC8"
+ },
+ {
+ "adv_salt": "A601",
+ "ciphertext": "BDA9A063CFFA5DC94A6F079309148F736EB30730EC334954ADFB96",
+ "hmac_key": "073737D4AD528AF8DF09A400A22F9354732340D628A910A7ED2DFE439780D37C",
+ "identity_token_hmac": "752A241BDBD62ADA62B55DB137A812A81530F6945B347A72E10C9DDD3961076B",
+ "key_seed": "23D63C05009E3370B196DA6FE4A96E3E38594F3BA0383FE19B727C682839ECF8",
+ "ldt_key": "CA7CF088A8165728DEB146ACD30061FB7B5C5F17ED53445FFD3562F4D520AE4FF933F76774DFC0D3CFD4E4385FE57092B92D0AC4CBAAAF3C16483D12DCB12BF2",
+ "plaintext": "95A5877E5F58B6D995B2084E4F38EA8ABAE4BC83AAADF04DCFDB57"
+ },
+ {
+ "adv_salt": "AAFD",
+ "ciphertext": "8803E1FD58511E33AED43339A9E0077C7012",
+ "hmac_key": "3AD326F0FD9F9E3C6216293F046E8E3367A218A0875555B50792368E9A7591D2",
+ "identity_token_hmac": "EFCE15BDB07640F9F2B81A42DAAA8F5C5580FC94295E154B8A41713CB89F27BA",
+ "key_seed": "DFC2389FDC8647D1C23DD7121A2DFB7A8BCE9CC9F69F50629D5338528BCD79FC",
+ "ldt_key": "4A7D987807CAD0F173ABD53F0A90D9DE1F365EE14CAEE6611CFF3FF4430C07EA7607BB3B7A56AA3FD4466541ADCE1BA06B7B55D4570E7AA0E329B20A307A5F3D",
+ "plaintext": "3905F15E8C081BCC6C9E5467578785CF8DC9"
+ },
+ {
+ "adv_salt": "6063",
+ "ciphertext": "41A468606A9285661FA1A0E0641A1235",
+ "hmac_key": "AD9E86FD3ECFF585047BD57B84EB6B42B2FB6E6F6851F2B23C4D6F45C5F93989",
+ "identity_token_hmac": "BFC8B274D5CF97006B0C393C250CF9BD22FA71C26D8ED1301BB4E7F8BB4AD034",
+ "key_seed": "6C45D420A250B3F9EF075B78CF04C274C0C45CC0C8ABEE8D54740A4471628048",
+ "ldt_key": "13F9A8A679153671E1EEE4AD451DB5A32B2FA72FB57855FF99CAA454CA68910D27C9B7F7C99E1D1D16C4D3D07E7756BB822948DE982B322E6D3F536BDCB9C364",
+ "plaintext": "E8B1174511617F08A79EBBB2D4E324F0"
+ },
+ {
+ "adv_salt": "B09E",
+ "ciphertext": "66BAE514FE9FD3D4FD03943B731DFAD4186410673A19",
+ "hmac_key": "2B631AD159E8B1D7C4712A1C1D2E453BCDF2A9944181251928B2F88C069EED97",
+ "identity_token_hmac": "6661D3B31A9CA7A32994E35FC3DA8247B0BB26CB70FA76A91E69D271D365FA6B",
+ "key_seed": "A958898664C9EC450FAAF215FED0AE4C08E7A9AE8AEB547200687BBDC4F2DD6F",
+ "ldt_key": "34F34990D04CE8CB5B2CAE7B4CC5C772F7F3074B8348133BE384E5A40C179E91AF3C46231D464071757ED5343B27797D82E15D8D4651CF65ACD2D371F3F9D06E",
+ "plaintext": "3A87E4A4C1F450753A330CA5A2258810222C38337143"
+ },
+ {
+ "adv_salt": "E6BE",
+ "ciphertext": "94DACA62F2E46079502E34FE601A765FD9",
+ "hmac_key": "0028DA5E27469A75C6CC83B6ECAA730F4D0C967107B3B1FF7934D8AEAFF59229",
+ "identity_token_hmac": "D13D8500C5A0B2E2B102B66D0F9DA33A69515F8FBDBD7972B456E101D921C5AF",
+ "key_seed": "D201C792BDDA73C0ED08AFB789EE1BCDCA1EB65784326A053AA860913FB01109",
+ "ldt_key": "7679881D455CD5811BFF61F1641D7A98E9C1EF6D29C27FAF6FAA39A0B5F5C473A5A2928EE721EB74491E0265BECDD88B67EF14E180A7F2387067113D32C0B607",
+ "plaintext": "3A10B1E09860673681B97E613F83A31EDA"
+ },
+ {
+ "adv_salt": "137A",
+ "ciphertext": "6661D85579EA7F0BB4236F4970226B920BFE9972",
+ "hmac_key": "18F7FD0D50302C2270E2B064E774C3F29C7F8D70D97B508E4B8779615C38A408",
+ "identity_token_hmac": "9DE247481C8E8522A87AAAD086780BA8F41C3A77FC9D8DA0BB640BA33BCB84C9",
+ "key_seed": "5DDA71768B7558FA3C98B3A29B47FC356B6B6DA5754D75689AF29617CE80AD1D",
+ "ldt_key": "1401881423FB090F773116675B1D5D3DB5380A30CA6342210E4BF415EEC78CBE3503049F2B6F6C2224324246044358467BC653FC10816153B30637879910EBF5",
+ "plaintext": "0DFABA7AE42D7114DF5FB4D42050BA1CA477E806"
+ },
+ {
+ "adv_salt": "7A27",
+ "ciphertext": "FE25721548C2E4C274F522F8F074743F9C58D90272DD81B5C08BBDDE7392",
+ "hmac_key": "A697350A4735005470C8D00E436DCE30D93D0EF7E1320EDE756AC076EF155BF4",
+ "identity_token_hmac": "CB23C030952822E5164C08ABC71C02E79C84EB317A952F42D8CC806C3677257D",
+ "key_seed": "B53B8AC84CA27A918A2C79425215E934D0E1AFB20FF246B5A7B5F2212CB75D03",
+ "ldt_key": "BB917A8EAAF7C391CAF0FF971AB3C8D2506C499CAF697A4B1F4C9761756998A3C9C752B535B957AA535B9849024162B2816E833F71E7ADABC568E384A7D166A3",
+ "plaintext": "77FEC4D2BBCEDBEF542E144D26FEEA7418969B2013A34F48733FEB89DBC1"
+ },
+ {
+ "adv_salt": "631F",
+ "ciphertext": "28399DB082C882B5B71AE5F57220B2FB10BEB0E317F0BEB0F4FF7B",
+ "hmac_key": "FE628D81C280912E866EF534EB73D3D26A2791C4E0348A3B735D4F6A58A276A8",
+ "identity_token_hmac": "87DA1BAE46083903B09A26D07D33D4E8A05FA6F766DFC16F5EBD1952D10CBAFB",
+ "key_seed": "9478B0EF762A5F474D2898CCDC23B2D35ECAC488AF848F204F18D65082EEBB49",
+ "ldt_key": "5E52F197C3EE72434BC12849DE8F4460E690F1BECDD676D7F5066EFCB5F2FED6D11CE8DFBCB0D5A44F5A10388756D0CF468CEDFF2E57EF37ECFAAF790C0A70B4",
+ "plaintext": "CDF16A05E3D0F01419E9A9E197CCEB77A94B8F0875A18EA07CC471"
+ },
+ {
+ "adv_salt": "3C06",
+ "ciphertext": "F3CB6C6E54F5404F710E395DFB745EBAD74532E3DB38CA69A77DE120EA2BDE",
+ "hmac_key": "97DDC5B9315B1DCE1F1B60E4243088953F35C485D20666ECD42E1ECF60346B69",
+ "identity_token_hmac": "3DCA4C5B3B8FDB8FAD3FE7F32C307D64555BE8ACD2447ED2FE95CC21990E3E15",
+ "key_seed": "D5C2342B100FB4C81AE3820F3C5B5503B089DC3FB065B4321D6CFC3D1EB82D1D",
+ "ldt_key": "983EFB98F5FA2DB96CA7D2A173B2CC03C926E09BE575F3514601E997FAFE4742B4294FD020914170E190EB3399470B90FC790ED7168A41DEE95738EFA119937F",
+ "plaintext": "4E1C99C2D02E2F9D6453224B8142FCD71515FE2838B6E7DDFAA7035D65B433"
},
{
- "key_seed": "CD09C135BEDA8C109B152D9CF7F88A9ABEF5F4481C7488B883849FCD8F2646C9",
- "ldt_key": "0D9F677ECAC732585B28759417855AF329A78590D49D9FF12D0AADD2B32781F0D9269746AE4B6728D2EBFF754122CA622C41023F44A23EF95DF60A0344B10066",
- "hmac_key": "080DD4F47372D1E2436EC9571D0FFD206F7742270006CB3BAAB8E792CA1FB3A5",
- "adv_salt": "D631",
- "plaintext": "ED3D4DB1A7EB9237FB426029C6D49E45F150F7D710",
- "ciphertext": "83E1F6AAD5F042C2A0C22287F3585F4D18E3EB0036",
- "metadata_key_hmac": "87F0CE7CBB559F477FCE464486ED86D6A6DB6103C4806273B34BBDBF0AA095A1"
- },
- {
- "key_seed": "C09DBAC2B1BCBAB3D28B1DB92FE144717BCCD1EDC9103846BDB26D990D9F4B14",
- "ldt_key": "68CEBB6BA3B08D27B8F47EB8239BA99C48C996283412830FDA984F5B7B1FA5E275748A94BBA20CDF3D85E046C6ED6DFCF2D30ADFACF3A8DA78E8517624E48D55",
- "hmac_key": "7D6A1F87DBAB2F7BD8DC3F8B14F23E8AB22A222C0EEB69BFDB03DB4ACBDCBC4D",
- "adv_salt": "F42A",
- "plaintext": "0A6105CDFAD35964D8350847A787A9444778DA54A8511B76DB5CB399E64E",
- "ciphertext": "903DD4A1499A7C5B3909EF18F724029A59739345CDA2A2C2561A6C2E4482",
- "metadata_key_hmac": "3A94E95316819B7E7D72DC130C48D04E341B2AA17A81C78090BBBF0CCCAE78EE"
- },
- {
- "key_seed": "5442790FF7A9FCEAB803FFE492A02C0A77673CB8BFD44FB492B8AB9B1904CF2C",
- "ldt_key": "402E8FCDCF7F998D019B831196814899A00F45F2D0C15A1BECB5F1229961B3F2E55DDC8FB99BC522179C84ECCC51670E97A301DF6DAFAB79B38E785FE5340EF5",
- "hmac_key": "E20CA41C6D208FD704092DFC6FE8C92AECD8E09DADDC881839551E98361B9AD5",
- "adv_salt": "9E11",
- "plaintext": "ABEB4926C4EA95BA3248E47992D1BCEDFD451CB61D916264",
- "ciphertext": "A3AED7A71ACA88CB7A88E192BE7DA37AA201B18D02E55374",
- "metadata_key_hmac": "9796EB7412E34F4E7F9BBA3A5472160322260C0D0DCCD2689BFDDAEF4996DB4E"
- },
- {
- "key_seed": "3B87F7C71E02C5C0F6A16F6AC78AA9521412662AA59B8392ECD75C491FBF01E4",
- "ldt_key": "3687A6075AD15455F9000009362B7E822CF7720BEA598B9F854F834DB5D304569C8B13E2AD25BC1B5C309FED0C21AA8AAE0E2EC88FA4C6615DAFF5820B0F7952",
- "hmac_key": "2DB6782D5EA8A24F379E388B3152D43E74D36D79E45F76F63E567D4B77580889",
- "adv_salt": "EDC9",
- "plaintext": "1125A3102BB3F1EB5F7EEFDBE0AA7F090E23DA8BCD08",
- "ciphertext": "4E44EF9D0E422340999130852A639A0135A7CAE80AF9",
- "metadata_key_hmac": "E13C7E584F918F202F96DB447CA0BB57433E9232D1BFCEB4B093DD2E4F9255C0"
- },
- {
- "key_seed": "76DE95A76BD4D22B185A05245FE756896C06CAC50172CEDECD251A6DCA14CB0F",
- "ldt_key": "9FA6AEB9EAC10DEFF68A8F2AAE2A10E1F6E5A749747337EBA2546178027508C402BA8C47CC1D97CA8B91B017EB00BA9056C15D1F008ADB4F446C00E13FE8160E",
- "hmac_key": "B331A07FDC05AA8A9100D4DE7914E1127BAFAC4256147A5419ACF46229B80451",
- "adv_salt": "2DEE",
- "plaintext": "F7D625CF3BFDD089FB96A5BD65CFDE75D354",
- "ciphertext": "174E63C64180EA078025CA9F65A7FC330356",
- "metadata_key_hmac": "DD891B35565C42F8968A28C059C20250476E90DB46A666F429D25C1706070900"
- },
- {
- "key_seed": "8DC435F28B2814A95817D20F82AD19929EDD04CE6174915A38A68D55BA19C456",
- "ldt_key": "8B6B64B8D7E041703D2D917EE972693DE9A8DBEF0A5846760F98CFE1E3641BA823F4803C2C2FD8C18B584D422192EA004D906FA232972231B21C5D7CA854C0CC",
- "hmac_key": "9298AF5DF70C371D15C4BC85D44056D082FD30971BFA8D5BBF8FBAAC502624A0",
- "adv_salt": "6362",
- "plaintext": "13B76A7869694AF0F30AF57FF629D4E68513C6",
- "ciphertext": "B12CDB5633D37650ECB922F1D1CA6DE2768BA5",
- "metadata_key_hmac": "CED9332E1A888F4C9EB126537A98D2E7DB795507AAC88D9EA78E9980C2906B17"
- },
- {
- "key_seed": "A750D50F6DF9AACBD29A7FF6AB3C0E4C35E722432A051657B6F10641867230EC",
- "ldt_key": "364B9811720C285488D1B613AA5DA0BCF5863AA1578F331A861B100830CF086B674A9C78769056C4B8D2FB2DE8E8A917F85B536C408E9AB86D2522E8728475F0",
- "hmac_key": "5D617FCB6A3B9F8A334297FD136F12FBDE1F52FFD7DDDF211320485ED0EB9F07",
- "adv_salt": "7A4F",
- "plaintext": "FD94DB89F51B5E009998489265849007D5D14114D6FD",
- "ciphertext": "E1A6627D1F2C464583BF4BA37B997DB7D616310052C5",
- "metadata_key_hmac": "EE227D9831233372FDD260B0CC08BFE9C17F186B53509B491113A676BE6D3BAF"
- },
- {
- "key_seed": "CE558F42E9C5EC0A24CD5E3120E94FADE5BB53AB08CD965F485A44483D9172C4",
- "ldt_key": "F93D7783046FF3A5B71DE731B7015E236E5E93A89DC6018B9D7B7BF8FB3BC6CE66BA065BEF5EBC2A8C0CFA76D85BD3FB77E12363A478388515EBD2AE737C5723",
- "hmac_key": "1FB0C4076FB67BFCFBAF262A52DACF1A8CF31E7DEF62E39CC58433C80418CBA3",
- "adv_salt": "6748",
- "plaintext": "09E3FA552BA39072C14F59A9C1D7560B4EE042F5",
- "ciphertext": "992C208FEA31EA2C09B1A27D20F333FD5BA02684",
- "metadata_key_hmac": "93CE4B293C12CADCD0B9BD222DC17F358A9F5873F124A605B571818AF7D8C771"
- },
- {
- "key_seed": "871A0CE542912BE9D05297BC11036DCCA916AAAC6B64226867CACE2446F93C4C",
- "ldt_key": "8C1D7F631CD9486D3AA58D6CBDB54BF9AAD43210347218F4681CDADF82E79D70387BF444AFCB3778205E9A460E9834D7284C921EAE62A079F69959C7DDE15564",
- "hmac_key": "EE64AFD968DCC9E5C1C339E005442B30F8A6124ECB84B0DF015AE5BD0B3F7F77",
- "adv_salt": "D9AC",
- "plaintext": "BC22B0EC3188B9F4E1C47235D1ED55C559CDC426CBCEB4C8CDF76C86E5",
- "ciphertext": "68FD17A33C0B395CFB5162FB41670C5AFF0914A2FA65D7C03FBA49E03C",
- "metadata_key_hmac": "4E6EA4CAA9E9DAF62D939AA3459D87FEEDFC7F5E3F96FE588A82201D1DE34A0A"
- },
- {
- "key_seed": "0B1834A1CAAD9A446B96DA719E4EC817F1DB6DE42649416D5911A88A91D8D1BB",
- "ldt_key": "D3F6A16BC42FB6E27CD897BC8AF9EA945D5A353BDC5EB781EDFDE6E16CA8718B4EF49F9FDBF2FBFAF8AEB7596A85EE288089AD445CEE74DC42579576710A5E7B",
- "hmac_key": "C6DA07445FBA6B06B5840456B345F6072DE1D256AAA0AB0BF1D66728E49797C0",
- "adv_salt": "18CD",
- "plaintext": "57B8BED51AB39E290888DD88A457ADE59E",
- "ciphertext": "B98ABA498DD64891EC4A524330F488A403",
- "metadata_key_hmac": "99BAB3FB6F027D2B8FD851802C210E0BD6381B74C7877D54DFFDCE9E74E4AFC2"
- },
- {
- "key_seed": "95F18F784A69A10B7A6F63AE5C29EEE3DE033CD592707B9321A94705126887E2",
- "ldt_key": "3F6F0B7E227A25AF15DA13F97B8530769E773D7B4AFD8B92A14AA7B75519F2B4FAB56767B6FCFC42151902542BEC23FAE133A79C6BDA3E63FDD9D8B041711F78",
- "hmac_key": "0E08C9B0AC72EF8AD892658736BD93EE2F87506C406EE1E4E63C73CD3B6F9DED",
- "adv_salt": "26C2",
- "plaintext": "D9D0E3A4C12E2AF88AF51C74A898DE9843B707E9",
- "ciphertext": "EEB57A21E15E485939975CA3D0D893D2B8E8E238",
- "metadata_key_hmac": "5032FF4FA4AC443962F57E271FFFBEAA3AF5D8E947F5A50ECE4F224FC0503080"
- },
- {
- "key_seed": "695711816115D8719F85408548466F0E02F00F787DB12927E313DD9AC6CDDF75",
- "ldt_key": "7F4A2174FFF86EF906B02ED7FA6146DE550F235A0D46EEFFEBDE6907AB094659427D5A5EA92302B62A669EAEA9034EFBB1A0295AC66F6906192109FC9858714D",
- "hmac_key": "13FD534B4FB1013D6BCBF51825E3503048729794FA4AF57A21F92930BDB22B5F",
- "adv_salt": "5987",
- "plaintext": "60420D199842E47384A6760B99625537073113",
- "ciphertext": "FD44230C154B407F203B4D068930418CE0E715",
- "metadata_key_hmac": "FBEC4C555DE7E1AE2B0947969D3588F12EE5057CE0588CC9A1CE655A1263CAB6"
- },
- {
- "key_seed": "2E3F37B0235FE80471FB00EB4532B82EEFC634AD2EF7524ECAB169E0C79800A8",
- "ldt_key": "5F1F00DA0AD4C64A8D0E59EC43B7DB6F6B14F455E4C1C27D1CFD81BF13D5C46F56A2CC80399248BC36E5B1774B8A02BC938F453C2E1B7D1B9882DEDF0B00C41D",
- "hmac_key": "D7C6167DC04D9EEFA230EFE173B0A9ABE905C2C86D5F9B11B9207A0742B4D8AF",
- "adv_salt": "B8B4",
- "plaintext": "F7A09923A8CDFB5C8879E8EF96566180E1EE1103C123669849BB06385343",
- "ciphertext": "A9E265E00D392435DB745962F8128C1C3ECB4B87D5599A985E420B5FE1DA",
- "metadata_key_hmac": "B4564A26589F605669E51B58E5A9F46E997A4D3A62650A60AAB1E8DB76820A50"
- },
- {
- "key_seed": "765465BA434FDC5F5A13723AFC20E96BC3B1D86887C77B1FA8030C254EB92B9C",
- "ldt_key": "8A7CFE1760993E348A87488A539F0C35D4B4F9B533DEC0A228211871D06AC7FC11F3AD456D8E0F108F27848711B2FB181112741B6E6981EC2709BDEB6383C307",
- "hmac_key": "4B5BE48B79A53E8E61960F7BCE547416EFE321C2D06788360EEB554E1ACD3E39",
- "adv_salt": "6F80",
- "plaintext": "1A0E0C6CFC3A150CAA4D4D61E8EB4F34AD9A3AD36C15DD1D77229B",
- "ciphertext": "64B7A5FE6B7C20F31A874AE148D4C97AD2E1CA693ECB288C864FEF",
- "metadata_key_hmac": "966A4E64102369E0AA75FFA0D6772C90D8D3C3DE3483C3DF384376EE82D760A3"
- },
- {
- "key_seed": "72381291A62DE7DFD1CBC6BAB00BFDC5B46C2EE09C8FA278E42FB8DC42F1E960",
- "ldt_key": "DA6715B676BAA8DB71D1F0775AEEF2390DDCBDE6ABC971899CAD0ADCE3027891073B76B94FA1A12CEB522085F78B3A0421003144F5D8B50AB8DEA5B69E696525",
- "hmac_key": "B889942846482EED3E216C47731B035C38B9CFCF46D0263B989DF6A3A2C4445B",
- "adv_salt": "9C9A",
- "plaintext": "F711B422BBAAD271F03BDB9BDE48C3FC723C2ECBA0F5",
- "ciphertext": "095B6BFC2CD29E3376651AF2EA8DED4460D4325B6905",
- "metadata_key_hmac": "5E45EAF3F20A15A6DE3436DA60F8DED969B0111DB634B1F11FDD662C055130E0"
- },
- {
- "key_seed": "8E35D1093AFE39355128F04C49803450F4543DB0537B657C69C222300C72F751",
- "ldt_key": "77C0FEDEDBBCE0D3E50987909D77BA4D70CC9C9C8B6112BCFD9ED4B8F5EA617CDF252E08052DCAB3B3D3C18F56C7413682838B32D415C55BB3F2B8039E01FD56",
- "hmac_key": "5339126F2411B984EE956DBF1A4C265403297D133D67605A9C29ACF897043870",
- "adv_salt": "DEED",
- "plaintext": "81F0B5FDF2B425AF0CDC80B93A7A624F",
- "ciphertext": "2312202B81C76EABE4E4B91C00136D23",
- "metadata_key_hmac": "605CA950B80BB0E1055FEA70C503B263D7C919003001C5B8B54B0D5815F4BFCC"
- },
- {
- "key_seed": "1B0749CD1E244D4DEE64603769A689537C26B50BE53E37E4BCE1D3E10F582EDB",
- "ldt_key": "89F12E3F45FE4B05B82D9CDEF43BC09CF87EAA058D0BDD4634BEFAD13D8F87B6F67C38C055AFC31BA2521947A8676855F757FF8C48AACC8430776F54E19341DD",
- "hmac_key": "229D2FC414AC6756483E0E00CA7CBA34D04027D6D489522A97BF5E33F4E80FEE",
- "adv_salt": "E2BD",
- "plaintext": "B94D6C9912F72912851AB750BBDE5927",
- "ciphertext": "486F60AC756B2C82E407232FFFBE7199",
- "metadata_key_hmac": "C2964971446F3B1BAF92B561DD49412268DFE419747C5A8465A3A10721A5C1D8"
- },
- {
- "key_seed": "E09A7417E9877F581B2CF38D11D8D42F2B733C0A905429CB3869AA5727E68813",
- "ldt_key": "96CC063FD11ECD5FF34B9581446AB922B1DC781CBF8A2A2494A9A8085F5354C44F59985797EBD94219BF3431C50593B65C19E1551F2BA6DCA2920495344C4E85",
- "hmac_key": "81A750CA4967F0518943225CA422440439F71B14FE49044D1AD02AFB0828C279",
- "adv_salt": "E60F",
- "plaintext": "7EF48C4B1E3EE85E663E8C091975ADF32E52E0A4B7B5B3D9BC279CA1",
- "ciphertext": "1760320AB9DA11842111E829802A0F85252CB54EAD7F12A1BABB616F",
- "metadata_key_hmac": "3F6487B3DB83085F97BB68E6D1BE556541909A650481942A0708C0100DB90A72"
- },
- {
- "key_seed": "0D7C20ADC3EE47B9002FEEFDAC1728E552F93390B1F8961869C9FA3E20D7F657",
- "ldt_key": "BA00D72C6D037D752B6E164FA60F060293301D22FE1106F8C921DB29ED31C05471585DC8B0F7D5C491C9DCFDD7BBDD14E7746F822D4503F8F65E95284115AE2E",
- "hmac_key": "B11F2F2E03F7673E79DA13653AF3A4F76DA34CF0982B8028B143BDB8D3153F89",
- "adv_salt": "05D1",
- "plaintext": "258428977375A4EF69D086F2B6966A43299421",
- "ciphertext": "C583A87CAC695D77C04319C0A3557DD2CDEF25",
- "metadata_key_hmac": "C63B92D769ABC05808E5AF0FB9820928EDE040FBD81374FDD87DF4391C1A513D"
- },
- {
- "key_seed": "377773727C5306FAD0604DF77A07E9B4FE95DB4594938FA5E36FD05C67004A9D",
- "ldt_key": "6F5EB812C88F1EA7A94D50E04AF00D8A818B231DEAB0D7A24458C8BFBBF5169EF5B79876C40867E1610102BD45D97B0F3CF5854B7F2808B25542F9F7C54BBBE8",
- "hmac_key": "E61CE07FB912BA94CE24826E99AD7CF8DFEB0A84A97119176DBF539C63E80C21",
- "adv_salt": "78E8",
- "plaintext": "2E0A8022625345195F6B93C3BE8F5295F1",
- "ciphertext": "AA24A9894EA51840333321662DE2DD997E",
- "metadata_key_hmac": "4B3E7C26BFA8081C3DC82B243DDA891D1CD86A8EA7CD789C00260CCD9B9439BF"
- },
- {
- "key_seed": "1ECDF7739B0CE4ADEFED5BD2325DD7539D0A872AC95C1A16A77E56E3A20CF760",
- "ldt_key": "1407D76C599A14A143446553628B4F8E3905872EDA141F245B148E69790CA5EAFAA7190B0C33EC21AB326EEA4D209914FD8D03E42E8669C04E5C1F7B60CDBE14",
- "hmac_key": "BBD069445ADC2C90A6D9625A148B7B9A42B4A0161F9F87576FFD41AA995A2C5A",
- "adv_salt": "F96B",
- "plaintext": "A933A95E1D009CF57F083C8244C5FAAEF2E2AE5414367FDD6FB9",
- "ciphertext": "44A5E01FC95050FAB258C1BAA50F115B10B65AFA5E309148EF68",
- "metadata_key_hmac": "9408F5718C1BC41B68DE68B38AEC980EEE7880FFE2C8DCB42E3721448EF25DDE"
- },
- {
- "key_seed": "0B5B97066B4F30208B2342D39589698A1510246523220EF552EA0D292C9B7C28",
- "ldt_key": "390E0246C707E055145F47522CC549AF6BA75CEEA06603002CAEC2226EC95FE54129CF95702C484BB3B09A80486E06E1A564825B3797A6419ACD5414A7538871",
- "hmac_key": "990000714F5E6696C8A1796C927A103B3C4EEAF3A130318B69F459E0661103CD",
- "adv_salt": "C8EE",
- "plaintext": "BE3196B51A58523F04D2897AB5530E22469A08E6A9",
- "ciphertext": "3B7C6736F04F41E0F80EB346E0F36377E08EC3C8E6",
- "metadata_key_hmac": "A37DB2B4480C73FA5B9E8663441A96C4B4FA1248A543CAC51BB26E5316E3982A"
- },
- {
- "key_seed": "D18D84D25E161E6C99F6B883432A2615FE20C0820E5B8750578F77028B69EB92",
- "ldt_key": "C08AA8161F484A47F912698A13246999AABC278B48268EB7DDB7D23DC6EA6462B3294D56522588D4F6F4E3E14CAE92150E47E8F9E009B6A33FC70708793826FF",
- "hmac_key": "6584A1CE18AACEBAA3E102D9BE51B36E2CB9D798195D4EB20DEBCC6DBD8095EA",
- "adv_salt": "E9FF",
- "plaintext": "8335E424E057F7366C7AD90AB69472CDD0",
- "ciphertext": "1FE2CACDC1ABA883BEE2F464B9DEBFB955",
- "metadata_key_hmac": "1E8B1B63873F20CBA369615FB029630EEA11EF14D4AAF430370CEAADDA9036DF"
- },
- {
- "key_seed": "E89BB8A66D843D3A7FFEAE2DF3D711C962D3D2D9E34DE3D3BB0A8287A4C8F00B",
- "ldt_key": "905307BCC3F3C82C84F12A9807F8DC1E7E419643A54328D1D5450D51A689D7264429CE85803E22EE21F0C167A010554BCF3C01791BCBEDF3BDC1F365350366AE",
- "hmac_key": "79D5113BAC3A1FB4EA76909781CBB4DC06BF89043C373C9964489D175284937A",
- "adv_salt": "D29C",
- "plaintext": "9CE911AF013A1535A373C84F32B08837F110A668593974492D64CA3B7CB8",
- "ciphertext": "1BF01FF3EE22F3FA0ED7C3FA6D5BE0716118937894FF2C0C5C0974BFD8C9",
- "metadata_key_hmac": "A0ADB400E1CA8CDA1D9EB544C148742298403157A73558D6C0384071172244E6"
- },
- {
- "key_seed": "F580346EB8AAD458E302FB36FB9AB5993719F0D2EFA51FCBD5DA69809D61FFF9",
- "ldt_key": "96C8DFBF3172CDAA12AE1E74DA772548B54A044F71E05642D954E1CD7CBE063F7C4BB3ED5906004A4B602C3BBB27AFD73D58891142D4BA2947B21B2BF269668C",
- "hmac_key": "A48116ADBC1C5E620C163D0DE9B4F6CF37EFC4181F38DA6F575BE6CE8B75CA5B",
- "adv_salt": "6858",
- "plaintext": "B46BA10703C5D2AB82FECBFD6EF00FFC75840927DAD75F2F75D134D4E4",
- "ciphertext": "6F59244143F1A032FD15F056B34A744EADB18855FC44CA83488C1D3C9D",
- "metadata_key_hmac": "FFE03B929D4B11AADA631FC9115E754CE31155A0A795BF43F85EACDA2990E566"
- },
- {
- "key_seed": "93588CF34CE0255B2D35E75C948FBDE8C9B03807353B39ECAB013C8023C66F57",
- "ldt_key": "84956017E5F5475AF1D43479DC65263437B3167EECB672F46169944062D7256880B99143B350C02DF23ACD415EEA6B5F573DDB65F399E25606CF0BE12CF400D7",
- "hmac_key": "0E1B448C6D28C2A492CC93CF32D9107A3E897E8044561DF6F2BDF87DF1C5DD8B",
- "adv_salt": "992B",
- "plaintext": "076FE4F24088FCCC07B0154009C5B4078C9784D0952FF95BF4",
- "ciphertext": "31796F1230A90B220990D0F10A209F80EF7A9AE01AD2ECD2CD",
- "metadata_key_hmac": "44C00FFCECCB08934266C91A4B7685186EF150D405C5A91842DD2C6E8F789E02"
- },
- {
- "key_seed": "2E86ACBBCD7FC897FAE73F3A2E9297DE135C2FBA92881E8004C24080E1DFBAE5",
- "ldt_key": "7E40B0C48425927E5789BFB60F323DAD9698AA522281A684FF92EABC311108DC3C6D957CC7C4CAFC2A9F19C1D59F6F11BCD76C7D464B0856CF81BC822834AA86",
- "hmac_key": "B5FA05B652BA6D2668196DA9B8D0AE6CDF2982503FAF000B90DC52A2473D98FE",
- "adv_salt": "D06C",
- "plaintext": "D0B9C548A65940C763D95C3A561D8979962E4BDB2C2E",
- "ciphertext": "625CF9643EC69F218278D1F2BAD2A0154BF6BB2A8A26",
- "metadata_key_hmac": "6CB2C2F544FBD75C3D875414DDEF01E2BFF2D1B40758C1672573A5E0213B8CE1"
- },
- {
- "key_seed": "2FB0EC5CD9F469174A96F1C14171A8E6C67BA0D56C2FC3A00628B713236B9E4E",
- "ldt_key": "EE3FBBA11905478EA1B1353DEB10634F195F38FA133D53360C25607D58AFA6FE8A88B9F8C698AFC45A6B429AB0F68A9BC6B56EB385715DB2F27129525DEC665C",
- "hmac_key": "0637BBCB8D173919C986710AE11CD6EEB83E46EAA5CC5C429CF46DF71A8F6058",
- "adv_salt": "BEED",
- "plaintext": "02E4A96808C95765A922CFB0D0D9ECD5C0B49ED3384DE6",
- "ciphertext": "4A690E995A954F7CFC7F13C5F5ED81EFEBB4230D733C2A",
- "metadata_key_hmac": "D25F03795C05EE864A4312CE1088ECE931116CC078FAA191C21657E256369833"
- },
- {
- "key_seed": "37C170756E293F3F6092FABD3EEDCD9DEB2519610214B7C9D7C417719BE5C6DB",
- "ldt_key": "FEBA46FBE1CB8BAD3AFC628E8A6A778863511EF9BCE2D652B9A4BA49003A76750BE30417558931ECF3DD2E636E7F2837437C094652F80ABC40BA5CE3EEF67449",
- "hmac_key": "1289ECB15BA013589A2226403D1635FEE9A72BF37D7FFA9F284E14C645EC8DE8",
- "adv_salt": "075C",
- "plaintext": "6391F65414678673BE8927A26FDBA669F3C256",
- "ciphertext": "7445D71AC6C0A8C838E4A55D5A4F6D13CE9FFA",
- "metadata_key_hmac": "5E9307F5F712F0F32699F093B769B8D2D84B2DC597F4CE2CF4E1DA0F171DCE52"
- },
- {
- "key_seed": "45619F5CEAE4E2ED2EFE4A90CA066D369AFCE0E480BC244C790AA37BA8E70657",
- "ldt_key": "6F19141F07631BE959AFE8192B43AD51F84F3531989F94FEB68A347CE1265435E5DBADC6B8C3D495780487EFE89AFFF7E585D26E3DDAC8CF89A34992AD4A4EC2",
- "hmac_key": "49A10BBEEAD8F2D1EF0847DC2312A02FE9907EA220440F265D9D976E29DB9CF8",
- "adv_salt": "FAFE",
- "plaintext": "AF17661A188E8D91698FE12DCD5577F9B560C562A3FAA88E134C30F17E",
- "ciphertext": "881080FDBEC85E7EF269CC29F0977B79C8386E848878531F3D11881945",
- "metadata_key_hmac": "9C789142AAA3372632DF23547C07A06FCA18B01EFC9009ACA64983470F410941"
- },
- {
- "key_seed": "A393B059FF76B55997A6428D587F0309B4AC707792D5DE91184B73C07068FE14",
- "ldt_key": "526DD74FC034373B40E162522C7479C014F1344136DD8B30FCA1E1D3AF92EA971951C6A1CD0D28B3097DE4E03E59053A77D7473CEFB31911934DB1B81878BA3B",
- "hmac_key": "07BC114B204E229117AEFBD1ADF520EFE2145D043CFBBDE2B9C5B1330EDA331C",
- "adv_salt": "2417",
- "plaintext": "92099CE78A30E61F84A476F509CD2ED46BE9F43D7BE338E9FD3EC406",
- "ciphertext": "6EDF8279E45D9FA0A4B76864BD69AED8E52601192A330BA9AF1F58C2",
- "metadata_key_hmac": "6009E34AE82667777158A2D51650AE2EA688867F0AD4B0DEBEBD3FA6B5E723A9"
- },
- {
- "key_seed": "67967A06AEDC8E27B759454391BE5BBD5BA255A2EE23C40A9891317646B0B4A9",
- "ldt_key": "47CAC71B39CBAF5759EACFCCE70D8644C0AE66E20F58A779C3C4AC6F10A23A9148C8755D25219FDCBD5D8CAAA8178606DB0A0A1C14F3EC555628CA4F4DA4C207",
- "hmac_key": "2C5976A0843A1B73A9EB4E223EAFC414808D5A6480DF301F7067DAD2AF4CA709",
- "adv_salt": "A223",
- "plaintext": "ADCA492DA05FC0B2A2733E94819194B3A34E55",
- "ciphertext": "4A946550724ACDE397E4DF825ABF8B4F7114C5",
- "metadata_key_hmac": "A0EDBCF865034CD43DF4A545D0F7BCA967C564ED9E22BA1BFF690216816D5794"
- },
- {
- "key_seed": "90E39F77C5DB43864F1F88A72F0C882BF78ADB49C04ECBC022467D612E283A13",
- "ldt_key": "435DA1AFE7BAC5D20D5C4C741CE67DAD6893EEB367F9D30E0CA0F09176A3553CC3E0DAA6F5A2C7D0DAAA8DCB2BF6F38E10C06568CA03C3F8315D7635FF4CA4DA",
- "hmac_key": "946F01A314CEB6AF1A852E70370C3072F65318D3A3AEA7778943AAE81B614E9F",
- "adv_salt": "0CCC",
- "plaintext": "A4F9CA00FC38B02FB88D441C26B097B7F27431",
- "ciphertext": "C835E4918302374E1346A8B975018D16051020",
- "metadata_key_hmac": "A6206935E82C2FA100EABD8306F0E5C78E17A3FE1F9D7C4387E9DEC4667A9924"
- },
- {
- "key_seed": "E8D9B87BF76DDC286DE441207E885CA36DBDB519CB7219BF540AA658700B7B2A",
- "ldt_key": "77275D5B7AA5E9BA852A7D3B09FAB7BF58A259EF133B794D444B6E69F8185DABCA140174BD4DF7A3EF0B3977E404ADDCEC8EB9E6CC9A8B4ECD663CDA32966E77",
- "hmac_key": "176FC5689F1FF116CE5E401EBB9B6D3EC4698A6340C97D8B96A6FF7E82FDDFC6",
- "adv_salt": "EB0E",
- "plaintext": "A5A56CE0819C10334DDE2E425F82655EF6D6F768901D81",
- "ciphertext": "365D853B73185DA663CF7D7D51A86436306057093896B9",
- "metadata_key_hmac": "79F8C788707F75963428C2E4771A906FBAB25F42704AD61C09129B97DF28BCF5"
- },
- {
- "key_seed": "7367018C066EF078B706CD8DFC2B4044DEF189682651ED9093475B667DB2439A",
- "ldt_key": "97A061889422F49AFD64C156588A0A81108932F885C7577CEB91D036D643442E5684806E3BA6A5BDCD0C11E54FFD820F1498C8348012A8536C5D1E99FA3EED6E",
- "hmac_key": "02030AE5A2A63059015E50725C29F7166E5BA1A4B97D80F0F32CF04308242661",
- "adv_salt": "86B9",
- "plaintext": "39C22AB75E16F11F539E3ABE96761BC4F2B17A",
- "ciphertext": "76E96E8A879E01D3A70B24E689464F241BFFE1",
- "metadata_key_hmac": "FFF91740C364D52B8C244B8AEB77365CB289A40E279F5497DE9098CDAE7CFEEB"
- },
- {
- "key_seed": "81C509C483D7A1C427DCC5EA2E05CBF4588FBD984B5219DCEAB11741FE761DC0",
- "ldt_key": "64C2A9364F5792E39D244B8FF3CB23F6F0593596BFD8CEC89FEF9BB2FD4772B4D708018427DC658A2E1855C7DEB9B3892B991ABC02F0273394BB92D4FC32B945",
- "hmac_key": "6493D527762752CE49DA792118247B05AD5DA653994309DE64BE6098BE72CEF5",
- "adv_salt": "E1DA",
- "plaintext": "3A1B6581737EAEF0D68EAE52E57BA1B989C18E59F12336F4",
- "ciphertext": "FA57FC03D94B1910FE96C7F303454BDC96C293BD1D80DA21",
- "metadata_key_hmac": "C8A153B4A0D12079F8EB03F44F8551AA59C25D7BF5C5CE25FB08883895887AE5"
- },
- {
- "key_seed": "98E720F7BE4AA07F9B457E53E87602FD10B9198A0B67194E3685AE69A6CD8061",
- "ldt_key": "007422437E2CA078E7EF7870E497B2F7DC9161EC79FE046ED1ADE1C29D26404113B70C2180CA36376D25C37088DE4DE2A4E7213CE1AD50C2D52182BE5FB80737",
- "hmac_key": "21FEACD34FF6D92AF01D10B2940F0E2DDDB373048CA9FD16E010C330CB31030B",
- "adv_salt": "A13B",
- "plaintext": "934B45CB11DD77578E4AE09AD554B4EEDD14AA1BD022EC47FBCBB0F2AD3CDB",
- "ciphertext": "8CFE890A7864CD65091DDC85F7E0CD9661474622EDF2C0D7D44A1EEB31501B",
- "metadata_key_hmac": "99CB7E7B8DA309853B0E34220D9A2B7CEBA5E4E5421A1DF459028015791BBBB8"
- },
- {
- "key_seed": "869A1CAF84F8C60AF1573BD15118E6C83711314495ADDAEB86E4A10FC9BBBD4D",
- "ldt_key": "CCFA059EC7059537D0C7F627331C54EA43F4FB2473CA24288C3436C6F496E3A403D1F31B4FAFA9AEBCEC663F82F0E54D8AF59A718CEDA93AA4687F79EBF1D52A",
- "hmac_key": "D09919AA79B853568687340D28461E8778C6450A03098A4634F196FBAEF9B3DD",
- "adv_salt": "7A78",
- "plaintext": "8A5BA566981761C530F59FF7A5B76F7358ADA54DDCD6",
- "ciphertext": "E2EF27BB3DBAEDA0CF508F9178E2F97A7DAC0846BC3A",
- "metadata_key_hmac": "079AB6E5A595FC2EFC8413F6469E6D4B286A0CEBE67B2990B3B6B596D04E9DA0"
- },
- {
- "key_seed": "5E114CBDD861FBB10B285FB3D995EBE57056240AE9FB87E3EA7868E52B9C6C98",
- "ldt_key": "CC05778C76198E180288195C60A09E3097BF4179D28014AA5F399DFABC66C7403999595D5A124B56E66669BA63817D8AD33E4BDF8A181E7BD8AEB5EC0A0630B8",
- "hmac_key": "71F06F85C029FC1D0EFA2F14B25E667140390C22681888FA4BE6565BCE65C0EB",
- "adv_salt": "5523",
- "plaintext": "E96582B1A180B733FAFA085DE5D6F942E6E55E2D0F6E",
- "ciphertext": "7DF18EE13B77E39AE5C29B4421F3A64B4E0805BB2C21",
- "metadata_key_hmac": "0122170D72BC714EE10582C5EECE1DA65BFE6C4FF396256CB5C122152DDF9C7D"
- },
- {
- "key_seed": "D78D1699F639D9CDA4190E16841C1344AFBB635D46CA61FCAC4145C8C53697E8",
- "ldt_key": "F950BC9C3E082799E7B2DA2130146AF309A4C5313B98659CEF81A206985FB06198AA034154D5E25FDA57237F522FA424D584837325FE0C66C06A80C6C8BAE57D",
- "hmac_key": "AF5BBB5BF2D84C7E88102222A95F7FD566040EB6E1036A78A90DA3370123D4F5",
- "adv_salt": "CE9C",
- "plaintext": "AE6430E1C1C8525D7B926B8D93186DD4AB643B55BD3D01CC",
- "ciphertext": "66A36F510CC0612AECC4864C98D42B5E9C304E0F3DE19AC9",
- "metadata_key_hmac": "540488D963352D79575337773009746203AEA174E4DE49F0A33621872723A4A8"
- },
- {
- "key_seed": "DBAB86015D39692FFC8B6EE1862F9BD6D2C8B28E4DA10D0432D1C0BD624511CC",
- "ldt_key": "796693310002DBE4379A3927AF6129489F49E76134175135BA497C6B3623D2A6A53520F53A3581404D234ABE4270921FDBC5C72048E0D55CB30022AA56E40992",
- "hmac_key": "9B95D807EFD135149898E701C2370411B0BFDF652C1D693C9759B20755909A12",
- "adv_salt": "20F6",
- "plaintext": "C5D10471EC644F0BE0C928CB0CE6504719F3839795F0",
- "ciphertext": "D81B09EA189F737EBB92978AB0CDA63655B4D21DF6A1",
- "metadata_key_hmac": "9751840D980E9B91097AA8DEF58FAF4D90F3913479CC9E96614348A892E6DBA2"
- },
- {
- "key_seed": "20BA5C3A8BE93060918FBFE6CB2EF94B0F32ADDA922132930351580BDB1C7B2B",
- "ldt_key": "FC7F8C9BC3B7D93DA88E0884C489C20A9BC51CAC2C195B3371A7F0995DA84AB9E528693F580A03F8F18F2DD18FDE0287A6B129AD695D9A2CB6631A4C85F6725C",
- "hmac_key": "0FDFB5FA8B335DED4681FF8E7D232BCE07199A19F2CEE581A388F09C7065C909",
- "adv_salt": "347D",
- "plaintext": "8636C156B78738A6474D89AE036CC3BAD7B2EA7D6A1C0918AECD2E2AF5",
- "ciphertext": "BEE77F1FA9DBCF3773B0B803BF2822AFA4EEABF610ADAFE4F69604BDBF",
- "metadata_key_hmac": "45362CD8C05D6C4A0AAF9B7A0D4D9E9B7F268D56EE1CB9067BA06751F414555E"
- },
- {
- "key_seed": "E1CABE143B819DDAF780F10E8DCB34557A110FCB16CA9C1208A9941139BC461C",
- "ldt_key": "BF2AFAAFBCF85CF13761CD4EA9768DF5932A888EFD7710E5DE11475D2A59E377FD1E86248FAC144640BC8609FA105A64325FF7B586065E10BEF1A12EA839251D",
- "hmac_key": "43C7D0D13D5A0665CA049A455DDAA10099FB9E0E0DF94EC9385D187254623F62",
- "adv_salt": "941E",
- "plaintext": "24CF3DB619D7E3BB10569664E2B2AAC98D7027",
- "ciphertext": "FBD875C04016599BF12B11DAA4EB84B538F824",
- "metadata_key_hmac": "147E5C30280A34487DBF757127CF1B38388A8D18D548E4EF9ACC86B8CC81239B"
- },
- {
- "key_seed": "19AE5D5D8287F089DD52E258C4E144B6946DD1C96D0365DF2756088BE98AB4EE",
- "ldt_key": "794AD4D1E28308C607A4C05DFB118477DF439D002CBC7CD0D934F0999E922C4D00911B9E6E811CE781EB95878D5CC25E15A503150D84AA701F2A6127F9480FAE",
- "hmac_key": "FD43AEAA7EA6A89D6A70E70169CE79C7790DCA6182609158D1A28E0E57744B2A",
- "adv_salt": "41C3",
- "plaintext": "315536736F3F2410448D02ACBFB5344E03E736B6B3AFF7C2",
- "ciphertext": "B0440FB32EFC893AC3285AFA470A682BD45A7AAE268B20D5",
- "metadata_key_hmac": "3F9AAE9B5918C539C94D9248FA88216562C0387B20946E85C167E758C07A65E8"
- },
- {
- "key_seed": "93CB8D5F88106CDFA7266973D06E3374948F29F19EE867AB45618375EFA7F742",
- "ldt_key": "FEECCB7CECB48FFCDD0D3D4790BE89A62A91075A163A6F1B7B49466CB35AE6B609477E9BF1A4D31490FCF05DD943A0AFB43BEA1544B34BB44DFB0186C16D7069",
- "hmac_key": "6CECD33DDF47CE8D66262B62EA863F797F6C94913EC9D9554819A50B747B8EF5",
- "adv_salt": "68DB",
- "plaintext": "3DDD2DB717B7BE43A4A951C4E324D0EDAFE15EA6A22AAFC96C5ED2B8",
- "ciphertext": "D0E16957DFEA62294CF7BDBBE2C05F84AE95FD83A9CECCAABCB2BBD4",
- "metadata_key_hmac": "52AA5B97F04C146E774BD92B35486C348A862F4D56535BC5EA3162FD6E8BC740"
- },
- {
- "key_seed": "B7CA1070E8A3BD952F7BE104D91A2C20F1D4796491DA3783264D50F6102395DC",
- "ldt_key": "FE724B6F0520D7C3472AAA8F6BAB9B10BF640F8B63A6684829619C1A0AA756DA372F638696656BC72517D5236118C089E19550BBB24A3686A8BAD9EC141CA471",
- "hmac_key": "9160364CC294664D46E19DE48143060DBCB5146A1F73287AB9491C2ED2A452AA",
- "adv_salt": "360A",
- "plaintext": "3C79AB767CAF65DC785FAAAC1FB38234A96DE51ABCD1676F5A09",
- "ciphertext": "86084B5E0879225A3E37A306ACC94466E7CB29E83585514D08ED",
- "metadata_key_hmac": "E98060247E9EB1B20EE37884C2BC30605927D75272AABCF543A728F0E31AE0ED"
- },
- {
- "key_seed": "D646BCB4030742672C4DA69C33CCBE4CDDFFE6F7483D784887775C3E265F4455",
- "ldt_key": "E0E59C6E1A3C0744C9E2C1B3EE23F04CBF1D858A53F933298F401506C5780D1AAA4874889137DAA63E53791785F64CEBA791C4BED505F86B039DCC533D8C1133",
- "hmac_key": "7934811F8EA0F86509A008C524D2F824170A380A1C254B5F9411CC1524C4FC64",
- "adv_salt": "4370",
- "plaintext": "6D6AE7D53207545ACB68BF4821A8A3CF",
- "ciphertext": "1A04AB81A47C7B24A17C8285197D9753",
- "metadata_key_hmac": "57E703B5F1867619BDA051C9CC319F6EC7A9BC7FA9ADA0FB9BA495ABD0C5C62D"
- },
- {
- "key_seed": "EA933E50C4F55A849B72E75DF0D0ED749E1BE736B7D17EB3F473C5D2FF8554D2",
- "ldt_key": "63678EF10FA39BBEA18869759D3AE0CCC622DE4020BA28435072EF06B87F7B64B563369578741C7A7F0F867979EE5BA3B826FC5C2D4D7C3C53C2F006EE2BEF1B",
- "hmac_key": "A57BB05DC2A606DF280DDE9F0C1BA63EC656BBC1C4D19BD25F0088B7E1AF7FC1",
- "adv_salt": "6E21",
- "plaintext": "3EFB804E7034A3D0B66E1E1A393E56DAB40700194C6443302486AD46DA",
- "ciphertext": "BCAF0F9355A703378CDD60C269E13D2AA533AB6FD9CA7EE4188E58948D",
- "metadata_key_hmac": "4639232C62E7507052B441900E23C8658CA36CF8630FF7C475275D169A187D64"
- },
- {
- "key_seed": "FD29F3B6EFE434E7211AE135BCFB24CB4731D3C9AF5A55BB40B097AFF8F190DC",
- "ldt_key": "4425DB4BF28AE5BF322D6493D0375532E54518F1A503A18D51F8D95DC72F554D8C0204486796210844002147E67F3F999CCB4B58BB571A7D53169F9C4A5E4833",
- "hmac_key": "D2B8B7B5B2438D8ED08B353A68F1CA27B5EEB8A6911C143462669E478F9B680C",
- "adv_salt": "65D2",
- "plaintext": "612405FB954646B9323C76E75463A6F5544905D16B84E01522F4201FDC18",
- "ciphertext": "F9F16E4FA6202A2CDAC267D6D93FEF1DBCB6BB1C0E9B7C0A6F41AE1C9399",
- "metadata_key_hmac": "A8D924AA9E363E0B272599CA171866B521BEC333E7BF1EB3C67C2602347D52C2"
- },
- {
- "key_seed": "CB46C2066E6C3FE16D1E8FEE5A0562E270F1783EFCF28D7EC8D77F53DCD0EDE3",
- "ldt_key": "C5A1D7F25C2A6EDF97DC26D4052239AEBFA3A08B972F4DFE6A0A7122532D8785E0C96895E8ADB0FA61A02A4D967660EF7E4DBB635711118E3511F3D8D697DF41",
- "hmac_key": "1D9C6580305F3669EAF24EA5A09D90A72C3F3AB9021A8D5426BF2CE50BAAB274",
- "adv_salt": "D18E",
- "plaintext": "3E74ACCD8A88A20FEA62EC733ED66A0ADF5268FBFC36D794D1A1DE4D",
- "ciphertext": "52433BE7AD16FA9CB74F12E69BB34124BAEE9517458A6442E09D5752",
- "metadata_key_hmac": "3316BF15CC1E4CDDD5EC092A88EF8154A6F43E725E71DC6ECB4A4CD27D98F678"
- },
- {
- "key_seed": "D0AE77D632C989982994F49442A58EF470A5BC5C526D38A3CFEFD94F9D160687",
- "ldt_key": "F378CBE4511806A8F0C519624DC553344BEDBBF61A474135B77BB9760F964C9DC33D63012A45D4A32F95979AAEA481A44C3F49D53DFAAE3849564F1AFC89FDC6",
- "hmac_key": "B078A96B7F1A4D5134B97C4BF3D436835F97A213C8BEA22D25BC5E4D16B78FF4",
- "adv_salt": "D68C",
- "plaintext": "6350114B94F70699EED4692575378BC0849CA57F8E30C3A1F4DB185D",
- "ciphertext": "54A9DD1E2C1314B9726F5A440F0A1C6361C479050138A687FE10893E",
- "metadata_key_hmac": "0BB547D578F7239770769E46E894D3EE3913D4BD819AE9DD21FE40C64473E9B0"
- },
- {
- "key_seed": "A65751FBC4AF24E2B9792263F001E304724EB37502F387F2EAA6A064DD7562EF",
- "ldt_key": "A4F7E615D946BBE528FACBA0C2745BDCBBCD0A16B46F060A555E09AD48311049EDCAFECF1E1F5D8D126B59F18E328C4E49D2056A4BF207B5DD8CB195FAA441C9",
- "hmac_key": "D5D089E402662DD1BA5592D0BBACB1996402B940E80D7504C5D6255A9A726BD4",
- "adv_salt": "C61C",
- "plaintext": "B4D35A9043A4C2F033731640321E6B7D1F66B39DD0177A4A0874",
- "ciphertext": "B9D9F57EE1F23EB4B73EC949EA9EF5A51A3518F95D8917ABEA46",
- "metadata_key_hmac": "B464EED3A47C4C83F1DF9271268C212B8528BAB1786C5F19E5EA0F4CCE9843C8"
- },
- {
- "key_seed": "DC35AA8B956AB62C7369FE1421C6C1DCF8D4A89D5F4062770DBC2BC7DCB8A182",
- "ldt_key": "98233C8B7F8AED0C76E1284EC42D7723A09D741E2547B23483C334CA7E264CD068EFAAB36345D28605A180959F5338C543E8CCA9B355CB8434957B102684831D",
- "hmac_key": "909F9BE62D6A59D87216426BABE9AF57C7160356C9885989D1A42D02181B2404",
- "adv_salt": "5558",
- "plaintext": "AC1EF76E499D137EC9F3191E9840CAA5BE5F317F",
- "ciphertext": "7C966901C5F317F736D64FC2A43E66EB5C49556A",
- "metadata_key_hmac": "C8E966D170968D075D59803E71933C049211876D1342B8F77F3F6FCCE9FD972C"
- },
- {
- "key_seed": "FCF4779A7A385AC0293B1B34D62755CEF4C5E88976E1A8840B3DA7D61A27D2DF",
- "ldt_key": "DCB2889329666B6AFE271AF8EA534F360DB5D59A670C567B87810FA0B9FEEED9BBFE453B2D70AF34B8CA71609A0B58E91B9C3D9FA4EFB4749C236DBEEE50C0EF",
- "hmac_key": "F6BDD41995C84BBA81C75B1C3996577523E671916B0943B89424370D2EC4D29E",
- "adv_salt": "4E73",
- "plaintext": "F6AA556C2F71E94D3F3DBC5AD7D1E2C27732797F",
- "ciphertext": "D8D3F3A5B4589D0E034F2710A81E81610EB091D1",
- "metadata_key_hmac": "DC3CA9D9424CC5CBE87972D1CE69BDFA77DA387CFD7158E07AA298CF245E2F3C"
- },
- {
- "key_seed": "F66DF6536DC842DCB7213E4B2D3BC65E7F339C44678B3065B84BEEE6875AD04B",
- "ldt_key": "15EDB42867D0B6E7BC3C46D3222EDBE502B9E720ADA1723BD1868D16BBD12CBEBDDD95CD9B9E2C840BE95FAAD953F538C36A698254AFFF92B3E067DFD3545B03",
- "hmac_key": "179E7E7E3040AA184323F846E19E829DDB11DD6B47637BF49783150294826835",
- "adv_salt": "F75C",
- "plaintext": "277603CAE5EFBA74E8521303A0CE661F34F344C4C0B1439EDC",
- "ciphertext": "9A5A44DB5332510C1B9A0B1311C052578A0AB5C4951AB472AC",
- "metadata_key_hmac": "4CBDD38306BBA9056CBEC40715E52C2CC83EB76AE733E371206134A45145801E"
- },
- {
- "key_seed": "FE1F1EAA8A3BBA8B446651897DFBA2005E2D8933DDE70E661D8958F858B1BE34",
- "ldt_key": "E9D189401214FD24087347E714F91542FAB76A65A40C4584A21CE923F5755CF6F7EA5554C2CBD3BE29BF550171604D2E0D56B6FE2CE37C726B566E60D4888C39",
- "hmac_key": "31A53453352877B96BB2124125315E6E0035522C2F44AA6FF1314D0EBC8F6615",
- "adv_salt": "DDB3",
- "plaintext": "0BFA0BD8D9D852DA66D1FA719B48E55EB333E05C77516CE2",
- "ciphertext": "031274D8E91C52956C573E02F8ABBF7B581788D77246A66B",
- "metadata_key_hmac": "A6DE740A9769FCDC59EE09FE542FB9DCF30B679BCF1E56499869AC1F8D71B837"
- },
- {
- "key_seed": "A41B8237B5EFA85322C6B295F9A0FD01F573C66F51D11C559713638860FADA27",
- "ldt_key": "9B7284B6D26A35D1823BF0CACC1761E9C7B77536142083ED2BAD82D7B7F90D3F2EDDA9755A4C7D94CA912FAAD3023B25A226361A6F6D807B68D21D2E3F172D95",
- "hmac_key": "210AA4A83DAA8F44AAB45C2CF45C642FC941FF8F9671F031B71B304C2EE64352",
- "adv_salt": "BFFE",
- "plaintext": "17FECC5D1CA89D84B293DFACC18AF52620691B2073576EF20F64718D9F",
- "ciphertext": "D897733DD7C03D8EAC294656243B333682AEA9EB9B9D4724DA96D95C7E",
- "metadata_key_hmac": "B7EA46EA057FBF194C154D2A7119826BEFDB6966B10B2B8F11EBF25873265BA4"
- },
- {
- "key_seed": "F21553FFD8917B76CF1A1E0C1812D5057B5BB37A420405BB13D61AF0D5DB0425",
- "ldt_key": "89ED1A2E28EB0BABEF410471BCF76040F0837A54077C21BA1A818C5760C3B21E2983A3A433F36CABE5A35B32864E1CFD95871E5A2394EDD304A86414B5042209",
- "hmac_key": "61A2C6FB83B556097116033B799DBB18FAF0AD9B258886B53089F7330EB49759",
- "adv_salt": "4D4E",
- "plaintext": "889397B6AC893582C8C35A266485DE160D1E68",
- "ciphertext": "5B5297F79DB633F8A39006CA8A3236B4C19755",
- "metadata_key_hmac": "EB33589BFB99F02DECFFCBF51DEEEBF44473831E9A5EB9BD4120E97944FFB85C"
- },
- {
- "key_seed": "33576D6CDC4B4DDAD12F5B0F5E3128DB8F521FC4489F8035BF9183A40DB97D97",
- "ldt_key": "64BC452BABF0E22A22A6D2BEA939FF1905408A62E2B2D4311CC2EA5BEE606620FC56AE1A72007E815985C1EC11D5867F2734728AEA3E7117596AD50274066224",
- "hmac_key": "8CF9B706F42010EF66E436D4F52CF07CB27CC39B9F64FF908DBC54BE3715ADCA",
- "adv_salt": "9F30",
- "plaintext": "F979E2241D6DCE47148EE498B74915D3CF3CDB87",
- "ciphertext": "97D6DE5213BF3F18730B4A416F1F5CA8A82F7922",
- "metadata_key_hmac": "C5169086AC1732F10BCE0171F0E6B6123F2694B9A54BB877350F0C5FB26A481D"
- },
- {
- "key_seed": "44455F60F506EE74FAF74E8DA03DBA97306DB0E54435E90DFB5417BC4AA48567",
- "ldt_key": "A6FBF80E245F9FEBD5B33A69BC6F7DC5FB376882679F24C8E684BAAE86176921284B46C61A5CAFCC04E30BEBD4AFD88ADF41996F967E0AECCE79E3C81BED5867",
- "hmac_key": "7F4AB7EAB331023CBDEE664A8C1427F7456D9B51D0D117D676A349F4E23FB33F",
- "adv_salt": "B80B",
- "plaintext": "13A2BDF201101D16B2DD1F67F8289BCB578AB83986C830B9",
- "ciphertext": "CC7DCA27606BC196908DB7829D8569038A4160E5C703D5E7",
- "metadata_key_hmac": "8E3B70B3C84F19A0FE164A78CFDF50ED4B49ECB053B1E7B41A8E3C3137748AEE"
- },
- {
- "key_seed": "620F0497C2E7C0923E7027DB0950298C44279CE4462C9A9FFC4EB5C0C6F24E74",
- "ldt_key": "FFE023195807235A48D2570021C73BC9C7AE961B7DFDA117EC4DE62FD6CE1CD184504B465CD06FC9684DB580590F778BCB6A856FE3DA1D000EC53BB0E93DC6BE",
- "hmac_key": "F13668CBA73DC4606600C72FD40D0286A9DE8802DE566BB66712D393F4BB76FE",
- "adv_salt": "5DA9",
- "plaintext": "ACAEC0B0773EEA127EFDACAB13904A4CB23557936CDF",
- "ciphertext": "FEC2B147A8EF9D8D72205DAA62B3551504D0E5E06EB5",
- "metadata_key_hmac": "14303ADB2D45E088A0BC2A96E9FCE4FA01B6DE35E1B494BF402B93805A6BF620"
- },
- {
- "key_seed": "1D5A56B6B5D8219556A5C5DD55EEA7C56E7A914960573963E78B7E36F8B49100",
- "ldt_key": "CE0A78499619B86F9B0BC17D223A1B531837AAF1AFFF3650DEBA84C752FAE2656F690917688AA28B70E818022161E917726A439A39E52A97E4B6E097406993A6",
- "hmac_key": "7056E12E07CD3F8A51A93D6E5A1A9A2907082A394CA39432B905DA0B48437C95",
- "adv_salt": "3651",
- "plaintext": "E416F4C78BB5FCB7761368B082E5E2395E3D85",
- "ciphertext": "48A4172F05FB1FC537151EE4A1EE7F7F37B42E",
- "metadata_key_hmac": "3E22CD89BF2D694F402A66D6799A087A03751A4E8AD3327B0EEE4E76E8C34BD9"
- },
- {
- "key_seed": "343596F917C924E089066303E58CF2FBE4CA7B4293AB79A71EDC6026886BED5D",
- "ldt_key": "A5A59E049A67C60802D0345E08BDE961601576B830F1178BA15B03F9DABA5A0019A25A5B146735FED83F4E9D3C01007D252F103B5C674D3307800094A6B6A3A3",
- "hmac_key": "3CB01FD40F194BD832D4F28620FB529EB142C1F51BB88241CF2549B41E192ED0",
- "adv_salt": "30F8",
- "plaintext": "774A7ED68BF415F37C54EF0061A5EB9206DF10DE14A8418E2B2D7DC8719681",
- "ciphertext": "DB8830CA6DF1F4BA6DC6718596A437F748D13A7494EAB1E7BC639562EEEBF8",
- "metadata_key_hmac": "2C791696B7948BDA85EDC4F97D983709A349CB9FC8AF2ED45987908D06AA064B"
- },
- {
- "key_seed": "338F7F5FE5DE001FCB7A5FF0D2A70DE2A3B3A3F7B41A4BBD8D73F87C2E73AB3A",
- "ldt_key": "277B661A492F908F7EB506DA5E785FB3D422F484B6A7DF2646525774D5C766590F5F5E6DA8F7216A15173DD91CD81A0970B0C49B0DF5339AA44B24AD94D3C0AC",
- "hmac_key": "691572560BB82F332962CFFA08E371EA0EA88F628883FA1A39332A5523093663",
- "adv_salt": "78E8",
- "plaintext": "D31824E9D4E9A438B561CEE0DABAC3500489C8EC01115A",
- "ciphertext": "15634D0F2FE02F4DDAB92CCCE4C0F3C6941A99141EDE38",
- "metadata_key_hmac": "8B6C181D751E8701ECEC1F37857BB77C4AA4A0DCE7751D9CA42F0E94AE4BB3CB"
- },
- {
- "key_seed": "F84F90B1D13F2A09D13EEE467A2B9CE7CEB236962791FF106A9539E967CEB625",
- "ldt_key": "1FE83F9813CF84AFEC67435B638815704799E4098EF7588FD4B0E14D9898256A1FEC424ED650BFBC0BA99C4604462450527DD46787A525A6213E41969F0945BF",
- "hmac_key": "55330CA8832B36F9B17CC2BBBBFEADFBD78A4BCDD2D9778B31CB79CCA690AE5A",
- "adv_salt": "BB5A",
- "plaintext": "E828F91058D295E6BF37115766CE369F199897C6E2",
- "ciphertext": "DB181452D79A03D1A31F94C3546917B494D88CD216",
- "metadata_key_hmac": "719935E3EB1C9DA6C9235EC8A0091BE8FAD0486AC081C96C7A31E435E145AF8E"
- },
- {
- "key_seed": "D289D134C02CDB24C28BE243556A71DF5718818A827780987FFEE928A7D5D1A7",
- "ldt_key": "1DB0FE1F97D7AB111652C98B580F48F134B71B967B0E68D00CBA3EA5DF7EE0530C9C127A064847816757903145D99A5074EDD3C18144AA156958799FB11C517C",
- "hmac_key": "8E61F0963EFEE787B02CE1C3A0E86015AA0D5CCC435310E6AD14BF1829E5AEF2",
- "adv_salt": "6E0A",
- "plaintext": "E87954CBCACFF97CE4CE2FA5F8384DA6AA2DD81A",
- "ciphertext": "C8802475CF6EA2EA71F2A7C83313E3EE549A2CAA",
- "metadata_key_hmac": "DFE63756EA5C4E9FF97A61ADDC0CFF0E07E9FC149F6274B80142155B614C2CC8"
- },
- {
- "key_seed": "63A44B4A2D3E81D00195D1C006986E0330ECBDFC05D3CA70530B8EF99137C860",
- "ldt_key": "7F88032C2CBBCCC894198ED3759E126B7809CB39F5116AFD63E3B4B83FAECB94B7D4688B25F73A6086E60BA550AD8053CCC70769BCAEDF1AB7CA112F46DA451F",
- "hmac_key": "CD4875290560D8E8F54E972627CD77F63240CDA9D495AD74B93D117AAE33C127",
- "adv_salt": "4C93",
- "plaintext": "459A3EB639253EFAB1F14F7B24EC036732D0994521",
- "ciphertext": "F10BACA9AD20E9525499E79ACD51B0B0CDF59C2D89",
- "metadata_key_hmac": "44B771C56CA3CB5187D712AB8B033B049F7239A5D38EAB40F1F8E1CA066C7B20"
- },
- {
- "key_seed": "0671E87D03B5207B3970DC43EB05C6E38D86BB9841010369529E2092C364C668",
- "ldt_key": "7216ED7C5FB156A854E4243A84408F34D1E9368C9399240E8E7739AE1AEBA335790BD2DE3D2B8D29627D1264C3729EB365B8540D447D1BD46C4078CF244E8B99",
- "hmac_key": "8B35F9DA6FA6DD84B646FFA132ED4A0380C9AB31A0504BAB483D6D1A96AFA42B",
- "adv_salt": "6F62",
- "plaintext": "CE6467A5DE9BECEC553CFCB1FBC314A5ECDB93ABA5",
- "ciphertext": "A63ADD1C0C87D2D81424397E0FA7AEDC2520EE8142",
- "metadata_key_hmac": "6AFC2447C731FADA03531F1289A776F2FFCBB238F6A35D238ABFEC74B6E14F05"
- },
- {
- "key_seed": "06E1781EDD38E90809FCB33CE7CC689EBBAE0C68C6FC66D58D3D7D4ED23CDF9E",
- "ldt_key": "CE2282288488EFFCC70EA72BB5942392433BD99F26B62A2CC7B98BF1685CBFB4B386D548007CDD3A071F2FA90944E59282B0D7D8744FD7F050CCDC2A789A3130",
- "hmac_key": "82024C7FA981ABC82F4E59C1DF298DCB82DCF2676E8D05B26C14078B7AADF06C",
- "adv_salt": "A351",
- "plaintext": "CB9440C3CEF90BB45C89F16A8B33478775B3C2435D",
- "ciphertext": "CA2B2069C89B7C4F24E5A9BFB5E91D02139FF188B3",
- "metadata_key_hmac": "08D9897B9E08AD1FEE910AA11F91EF1035CEB8232B7CAA00A5D55A27E1500827"
- },
- {
- "key_seed": "0C0C617B25804C4D513BABC7A4506CD66107181187213D6A9F229C13EE9B7055",
- "ldt_key": "F36A44BBFB40B88A43C039FC994EF3011946D120CE95D214DB65858664FFEF3684C5D42688E85610F02DFF9A4541F5ACBB10F8FDD537BED40905F5586A4D4AB9",
- "hmac_key": "1128F3C5F11E7E06B2812C3435DB3C6EBAA59CA91BAE4388DA10781E30A35AC9",
- "adv_salt": "6138",
- "plaintext": "04812107FCC326D0BC12C6A6F76C422C38",
- "ciphertext": "EBC81562653E5B8E86CE2B66EC69FC88DE",
- "metadata_key_hmac": "0561137A058B8DC63E13135E8A4F39CBA552C43245904CA500035369E7A7E7B1"
- },
- {
- "key_seed": "4F5E4D56119949738BDB7DBDF8158494BC073A949BD78075AC84859446F0818C",
- "ldt_key": "0371A5EC3C37174F96E063D948EA8C3AE6566DE2224DAB31494D24AF1DA81429B4CDBB9F90BC181052FACA6ED3FB594DC0D53497A8B550F8651F28DDCF8B5F83",
- "hmac_key": "D8251CCC9C4DA0E6B31B22D5ACAA460175F4B8DDC52A8346B7D6D3BDDB9E7937",
- "adv_salt": "78D7",
- "plaintext": "C211D8FBDB541B6851BCA8738635696FFDBC3B50D449C4B961A6703E",
- "ciphertext": "0B30410B1E7885E84BB5F1FF61A397D4A92EACD49770F6A44DA70370",
- "metadata_key_hmac": "4290CEBEE66DE312DA9974ACFADEBE7587207D5F9F893F2DC33C6FA50BF600DC"
- },
- {
- "key_seed": "0B3D2F948D597CDB11ADFC802E1DBA6827E0CCC4D6649CC459B1DB7C6CF976BB",
- "ldt_key": "A520D05C8D03859B4DC4218BF7E61F86CF5B4116CC959833ED158F64B4199F5E85BB8AE4FB72F8E18F67F991A7555D264F7D109157E7CA089489857C481C969D",
- "hmac_key": "831161162D181BB9D02877D4C8F048376B33EF281F7C2D3C57409106F68FA3BF",
- "adv_salt": "EDBD",
- "plaintext": "A78301B95D56985B6A81A69340E10AE872125BF8F76898E7",
- "ciphertext": "FE052157D4AFA6B46B19CA1EBF1CD1F500A844BC8C165530",
- "metadata_key_hmac": "021272FD20767E16F0222DBBA83562579F3F8A7A9A6B86D41C79C188D0F43086"
- },
- {
- "key_seed": "1AC2CE1A2FA2564AB3A0002858EA9E27D6341B5CC64FD22DA6C6AA07326D4E47",
- "ldt_key": "81DC06F871C1A1C60B9907F55D95582E7E48B82DA79C3006A9F2BC633976DB58B98121EF1E0E1CF82A78BFFB30FF80127542E90114AEB9955B908957B5F1A382",
- "hmac_key": "761B180FCF4DF2479C797EAAE1836FDDA1B173BBBEA7129E0F2A8C4B812476A5",
- "adv_salt": "3383",
- "plaintext": "ADD5480A412C9377957B9B515B3AF735F5C18CA3",
- "ciphertext": "67ACC73A744516A9FBF7BFBACB98CECFEEE00ECB",
- "metadata_key_hmac": "562C4505EE7EFC1AEC79474AE31BFA9CCED521CA5CCE16039E8A259010ADB007"
- },
- {
- "key_seed": "D158900DDFB6C7198932B9E90ED920ED579E61657CBD6FCA17AF281FD4391F6F",
- "ldt_key": "C5D84CD86F7017CB8147BA271AF2FB950D15CAFB36AECBE9FC7C51B1B32593DBD51503FD5C65F9E6E469FA2F4446FFF3262C049CCD0551B68D730C358F725E56",
- "hmac_key": "73F15E0895BBA3EF37191484FCA3D885A71566652E9E3BF6D81F19C493659BBE",
- "adv_salt": "6875",
- "plaintext": "E258A1888314766D42C8C0D3DE4024BF8F79",
- "ciphertext": "61B327579A311B0284B9083639640049A4E8",
- "metadata_key_hmac": "C445DEEE44EE21B8F567BF2367A3FC1956FB0F1106DEB7E05C50135260CE40D6"
- },
- {
- "key_seed": "10A7EC5CC4EB65A498706ECB585F880F833E243757C7462FBE6819CA6771ADA7",
- "ldt_key": "4DE3F63E1088B1FD84D5E86468FE11CC217756F1843E47D109C69C273FA0F59752E52B32AD57A73492AA7240B3F7DD934487FCFB3547DB1D8932373FD7F89EB6",
- "hmac_key": "142FA8A07692490DBE1B9E4BE43A7025849FCF9E6653CD2318D743E4EB8F904A",
- "adv_salt": "C61C",
- "plaintext": "F417E53F7D6539C14D7F5F99FC440908FC6FE7E9168288456551967F5A",
- "ciphertext": "D98725AA5980237FFF6975C31B40B07C4F9F12B89C30191EB404BF09C6",
- "metadata_key_hmac": "F0867138E739CD593334B0704E493E33511070A60E071A94B441F4826E012182"
- },
- {
- "key_seed": "98D42129CD845E7F14843B9D9CCED882989BAA2BC9A67038F1132A567D58A91E",
- "ldt_key": "C229D7C951FF00E05F670BDC877FC9703D1DA5C8D9DACA5611CB86A449D5A0714C54C7D7F9D8AF2BCC42B352D11EA1FB12107674208E972A38DB1B34ECB2B1B0",
- "hmac_key": "040D8A7A9AC888C04E097AB62CBBC0F0E5D69692F20F186C837D91683067CEFC",
- "adv_salt": "6755",
- "plaintext": "0501C4D75F74EC2BFD9EE99473C2339E649461",
- "ciphertext": "F6615A5B104736383A242938A9704E19E0B621",
- "metadata_key_hmac": "445BBC855FE10FF5B2CAE5F6416B7A6D698930EB9008FC54B4FA06F58FB2BEE1"
- },
- {
- "key_seed": "78AFEDA040450B152F85D4510FC718A059D6CE23C0794109B9362125689DEC61",
- "ldt_key": "3DC90A9717B472F082493CCE5760044401E6C0C32496863981112A9D1ADAEFDD79FD421CB11170CF12DC7F3EB7FB0B85018E8A32E7391D25773CC9DC88AFBE5A",
- "hmac_key": "890C9AAC2820FF2720611ED90B7E3DC4663F07966005F56A6EA9D167CF965E0F",
- "adv_salt": "B397",
- "plaintext": "951FF0A7A682651DAFDF47C0E19E1E56955B3877984D5D842A84133B",
- "ciphertext": "E4D79F17E817D3852E3F5E9FE41D020EFF984C39BB39AA7614664B2A",
- "metadata_key_hmac": "791D3A04FF1B72A68E9229F4D7E6CE4E771B01759A07EA940AF17449C72FBFC3"
- },
- {
- "key_seed": "3AAF11C94241718B0879EB66ABECB032147CD05E423EB3B534BC4E747605468A",
- "ldt_key": "757B05A0E86B9C0CF6BD13836C31BF66EB53C13A009E0C808EED2A0AE9AB6C55E580CC712DBD0A54C33CD8BDFD6F7BFC45580F49A68971A23B534F3A35638ADE",
- "hmac_key": "9462EB8DE0A29A937A227AA1345501A687810E321E0C0E7ED98D6AA80484E9D0",
- "adv_salt": "7ACC",
- "plaintext": "E4B0DD617B62A9F2F4367ECE4D70CAC7E11E5FE5CC3ED12083E9F4",
- "ciphertext": "B43DEA72A65B4C0D8E5F815F4F1F8AD56E1FF69DBF53CB7565F1C9",
- "metadata_key_hmac": "ABA6B185C97738E69AA2D439AAB09F111F9AD0B6625D8D9079873F9E5F1011E4"
- },
- {
- "key_seed": "1254B4969EE1573866EF96A4DFD1CC7CC50086AA06567279ED31E753A7512FF8",
- "ldt_key": "0B0F718654A1B737BDA6696B4D7E0E8F34E80A5492539A0D69461928E8FA6E0147C3139BB9D2EBD40E6BC24631EDB713332F83354B7C5EB585B15E2A31539603",
- "hmac_key": "331571E071186C989950281590C97134B0665B379E67BA173945CDC657EC8B54",
- "adv_salt": "3C44",
- "plaintext": "F59080AB834F6E10D2F9C2CE3FCA3FBFAB35",
- "ciphertext": "52EB13D24215021A96CA404C7DBEBF1285B6",
- "metadata_key_hmac": "245D7F20A26FA4A49A92C9E8ABD9BCA76639817BB2DE8DF660228C3129312578"
- },
- {
- "key_seed": "A09389BB1599359C1A54F852632749B2AE314FC097C91FE44B1667E66070543E",
- "ldt_key": "04548B847DFBFEBE23CE95E67407F5BC30AA6BE449E75499FCA5939A1FAF68EF8B495F65A6E043A146A4737C4F2C95B286B2E3AFE5A12EB78D9B9B6E58E729B4",
- "hmac_key": "0E52834761585DF6EF60F873232D74D72EBA8EB198BCE30B58FEFD63DFA7F758",
- "adv_salt": "8D41",
- "plaintext": "63D67EA2B4D8360069FC8935AB48C51703E018630B965022455810",
- "ciphertext": "BFABDE39D3F06CEA3408E4CB6596700B3E649ADB1472B615C23800",
- "metadata_key_hmac": "ADA13495722DB9288C7C082DE9D457E721E6722790590B7F5EEC53CA33807657"
- },
- {
- "key_seed": "CD9576EE16DA0AECD0BFD036353AA99F4F379E2F439230F38AE70E21A41E9822",
- "ldt_key": "5FAD20FB31538ADA9C445FC4D441D372902C0E1A84F589B728153AF13C19364F3F8B593FE6C2EC50F6B4FACF08DAD3CCA85B4EF8BF6B73A35BB09F4F9D1F2A8B",
- "hmac_key": "820F0F0B8B99D29BA6555703C39171A5CDF99EDFD1014289CF345EDFDD0FA8CC",
- "adv_salt": "361B",
- "plaintext": "8A4B3F4778C90DEA493EB2595393660C2A9A592D9635942FF0862D4E4FB0",
- "ciphertext": "2CBC9C9F19C243B20CFDD57A09C277DF84E939F7ED2AB63642BE7B68D5BC",
- "metadata_key_hmac": "F46A16718E7ADD5B1D72512F477D2CCA606E06588898524EBFE7E1B699DBA7F5"
- },
- {
- "key_seed": "5A8687465EEF1596E3780067B4583A7FC4C4F260CEE84AAA0BB5DD9293D6CA23",
- "ldt_key": "16A5125C65E844C3610DE38CF2E233121E6DBA36B33D3093AC737D6CEFF59C4BF998830E8FD0C52763AC09E80CE91CD8B5DF977182EAD82FC02A3BF00582936A",
- "hmac_key": "4AFAD4D6D875B1FD17EC0270AD720842BDDE4BE82DCE2AF4B8FEE608FB1E823B",
- "adv_salt": "DC49",
- "plaintext": "30EA802B38189A793EC9A0556C8120BDB323EA2AF3AA441C1B5BF3",
- "ciphertext": "B7977567D79D5668792212E0F1C4C4337AB9B354A17442E424EC61",
- "metadata_key_hmac": "8363FC0C8CF602B0F0880C305E5B6D59E056D9F4B62C523A0A892F6A652F8DA5"
- },
- {
- "key_seed": "1847DB43A3705D2EC3D22784612C77AF2C90E8C562FDCA4E1D0608D7FAF59044",
- "ldt_key": "DCEFE1116D69A3A14EF00163297A61D9E5CFDD7DCBC57A918C5D34695D6BBDECBD5860126BE689FF17653F6A78D1BBCE50FC2452090D5680DD90B3EB8A168DFA",
- "hmac_key": "4D2671B9F1CDC2688D2CAC6C713BD9B8D4BFAED2FA9C1C86CD0C1C89FFD07B0A",
- "adv_salt": "6600",
- "plaintext": "E0B7648B869F159FA32E7AFAA73B7FD2F8756B3773C0651DCBD9F0131555F1",
- "ciphertext": "AB5944D92E32F9315CBACE0DEF010AC041228712636D06BA88573E189050A8",
- "metadata_key_hmac": "1AC08918FDF79487DA33EA74523CDD0E31CA5D50657F75EB87BBCB5D44A51C18"
- },
- {
- "key_seed": "8FD04A9A906A7FB6747A682C0D86EFA3DC353148C038470AA201D009945428B0",
- "ldt_key": "6ABD509CC4CFD4899479DA3FD50F948941E6681943AB9A7D4B348787215809A1B5F38DA19DB1ECA132AF464D550703A3F21FB5DC67925CECCCEBCBED8DCD4352",
- "hmac_key": "59E7493AF6F7D9EC5A5A18B02DE1B69FA49BB4955D871FCB20D6B840E8E65FE7",
- "adv_salt": "E344",
- "plaintext": "FD465A3957F9186D57E9622CD6901A3B1CEEA86639BA01240186679C2160",
- "ciphertext": "D198B506ED55D44CE3B2B06F564EB41577E4A21BA56A4581897AA41E41D1",
- "metadata_key_hmac": "E17EBE7EA3E31442C9F77484B2412B93B21035A09D2CF2B7D302F5595B4C180E"
- },
- {
- "key_seed": "5D6901027D2CD532A9CCA83544CA250CE4FE48F6D2ED656D5F53E644693AF48C",
- "ldt_key": "23C4450CAB72981CDEF0AF4DE884B96F2CF0410072278DDFE17076CCEEACDA62017F3C57087C30F3D135CF7A7BFC07310B6EAF35266C3713E324C1A4503C3962",
- "hmac_key": "1F71218394C4A14E4E0DC8F35845618BCF661E43F7D94CD65649BFD7ED7F7058",
- "adv_salt": "3FEC",
- "plaintext": "055458BDB0922E3498E2D29BA1915BA2FD9E44BF0AF5E42ACF10D03263D42F",
- "ciphertext": "63A18209632293B8FDCEBA574565385C14AA076082D46C1D5465553CA97191",
- "metadata_key_hmac": "100E1E9585B0B63E231CC9CFEBAD3844F091F8B43B257984B807879BD84E036D"
- },
- {
- "key_seed": "EFE159ED6B66C394C457F074EA67F073BB21D9AE07CF83C160ED0C1A94F6C1AF",
- "ldt_key": "CDF76D8FF8E3F9C6E978067C0F4C431B394897682721234DAD7080AA095118CE1C39BCDBDB326E015B58CFB152DA9EA5FE064654DB8CC66EEF2ECE21491F7D94",
- "hmac_key": "3DE7A2AA19F99374C637DA91F16046168905BF370E9E359C8338D979D84AC736",
- "adv_salt": "0633",
- "plaintext": "7BE0CFB84C85FC14073BD06D8969CDEF193A6CC5B7E799",
- "ciphertext": "B03C781FE475220B173AB01853493C8ADD344868399711",
- "metadata_key_hmac": "C6D156F2D028C16472AA9EECF256DB57494DCAB97399F56F9EF30ED1809F994B"
- },
- {
- "key_seed": "A312E637DA32C34019ECF3417F6AAF45152A22EEA52E1B151616167C1B774F19",
- "ldt_key": "9AB49588EBF4E929ACFDDFE2E8FC1AC12A7BC31AF2ABB44BF03B7070E19B32A39B41BF04F1CED0895F5FD3C7FD4BE5DA33B90AEA97EA0591C6798E56D4AE6332",
- "hmac_key": "542269456FA4FF4D150008518B032F9C7D7864E907D88F367F85624C29BA1C4C",
- "adv_salt": "4356",
- "plaintext": "9D48B29E18CE314B8603581923ACC0228057",
- "ciphertext": "F577503F99D7D42623A6064383DCAEC22AC4",
- "metadata_key_hmac": "1A44E9E237457DC3D3A093EF67BB2B915A10F2A7A22386EF05B27FAF1005DBEB"
- },
- {
- "key_seed": "E8D47D10575C5D1E3630D342626BE5CE6812B2E5B671323CFF42FE76AD265F28",
- "ldt_key": "32F9CC9C4712DAB732229F54E0F2286B1EE5E10E9A19EC266C73773C84E9E86AEFEBE870E255F24964190D8FE49E90DB238FDBBDE525F9F28D7838490778172C",
- "hmac_key": "8415654B8B4205F056B2C189A280627EE5F908434495906809CC4D3C06046E24",
- "adv_salt": "E5C3",
- "plaintext": "F816AA6A681EBD851CE3BC4A56F93AA384132A42DCA7C04DF1731490C90B",
- "ciphertext": "2DC2F095CEB06C6E3081EC159FE13E97EE667857C37A21789E8714948C8B",
- "metadata_key_hmac": "E3E8881DFAA94F0F305D1F43374FC455C7BEDAD8B5BA797752FAE7BD08A14E3A"
- },
- {
- "key_seed": "4DF9A725DE24A1164A0627D2BE4BA6B8F3A77E47A635995A34089A5AEC6877B6",
- "ldt_key": "3A582C64633FEEF62D3CB71D403835CDA34FC5D3B41DB2370AE9082A0146B1E2300AB9517356DF91AD544E70951C2F16C5E0FE06CC1702FFF6C9709232DCF569",
- "hmac_key": "EDCC46D1F0A60F78E7F6EAF19B142A5AFE9F01C3F9A830CD2795D2246F93FF09",
- "adv_salt": "F806",
- "plaintext": "BC751733EB97C2E703EEF578FAEF3C437AFB4A434324DD1857",
- "ciphertext": "4AC979B439952949FBA52435B0598AC3BCFFF7B07D33CDBE20",
- "metadata_key_hmac": "21DF4EAABDC368D32D1AB8A0AFC56B6752CFDCF17A9DBBE4AF7C96C3BD7A6871"
- },
- {
- "key_seed": "01510C4FE0D9308543FDF8B5CD9A01C60A671A408F9D3E0F844799139A7C8DBE",
- "ldt_key": "08E67910642AA0B2EE1610F9B5EB7061FF8C7F1A94C61261C3D9A558C5E736A79F14381001657B97236B98BDA66DE7D914DDA4C860AD0E03439601A27D77FB34",
- "hmac_key": "0B94AB4C41BD67AE18A13963A62294197F17C6047FA8708DCD75900E26836CAC",
- "adv_salt": "CD77",
- "plaintext": "25278F8BD0FAEEBB70FD18F0A594F887C2CABF4A7A5533BF14E66042AE",
- "ciphertext": "87008C6E8EBB8215749717DA1F266528E83AF6FFE1E938FDB9B10BAC25",
- "metadata_key_hmac": "E14A9EF23DE4C90F7F3910B069A20549BFDF1E2FD351697C7488A0243FD04DAE"
- },
- {
- "key_seed": "03426AC28AB41BFB34BFC4395DB65D34CE1592C6637049BEBF285FCF6D4D752D",
- "ldt_key": "F864AB194A8EEDAA86733A530CB239A2C6C11B1EB86F18A9F7340C52BFE1D5D3D479103DAA18A830718029961012FF2822572FB2A38661B9EDEEB5531F1E438C",
- "hmac_key": "55F499D3D8EBEBA2D5849D86155D4EEA9010589013DD791109687EE09674539E",
- "adv_salt": "34F3",
- "plaintext": "D3DC2B17B56AF59D3CF9201681FBC37240E6",
- "ciphertext": "320625C1CE2D1345E9A5988E837DB38E690B",
- "metadata_key_hmac": "62F4232C63E05843ADF561D5FD72D3F9EB0F0A00AC94EAF67515271619F03C1B"
- },
- {
- "key_seed": "08C01D4D30CDDBB5201C54E1646702BA1FED8767C690D8C312EC05F961202393",
- "ldt_key": "117ADD7CB116BB4AD7C1873E41E43BBE115F47F9A089EF5DFDDF1D30EDA4D7397A8D86DBE1C21E2245A79F9E91CDA68F5EFF8CE68C18DDEF808CC67061709B27",
- "hmac_key": "4650BF6DC8969E8D8878ECA7559F54DF24B3A4980E45B10F2B40DF56E18374FA",
- "adv_salt": "3438",
- "plaintext": "3FA70D0FBBD749AD720DF7624F209E1985678AEA951A3C640C62215813A633",
- "ciphertext": "A732659057D8FD106AED3EBF8DCE945D16D681FDE67574532AA55B8F020BDD",
- "metadata_key_hmac": "2EBAEBFA7F0EBB889F269F00BBB08973D13C07D1C4BB233245272651BFEFCDFF"
- },
- {
- "key_seed": "294BDD21742BD87E8C031D4459C3C4D752A38893AAD3EA6589BD23D2572E6007",
- "ldt_key": "FEF9E32525787F8E8D3F6823E924272F74E7A7DD9803324A553C2DB542FEFEFF828760512C5336ADAAC4B78708E8A7ECD5329430947D7172DC39B1FFFD173C50",
- "hmac_key": "A72984997949D2A31D511BE11D857B39E983A58FF8D8CACF758D646CE1EA9D4B",
- "adv_salt": "3893",
- "plaintext": "E7C5D221E528F0A4076BE5F703B349804BD288A458B8B1FAB1D249",
- "ciphertext": "41E4F42E2928990BC1AC8D5F286A6B841D9CBD0C46CB0DC8F4386F",
- "metadata_key_hmac": "4D7718EA2A03065A867305D6D5608B295415953F7E051FE5BBC4CF386640AE3E"
- },
- {
- "key_seed": "BAD140BD7F5A746587950B769BEE2B86C001A2541DEAF6A8BE3BD89037624187",
- "ldt_key": "618EEDD9A044D8FF3ADF7E749B7C0212A6B412B617FD9243C13CD4AB1817165CE9994745CC4AFA37DB98896FEB0068C18E126E9A36D6555BD33F5F409AE64C0D",
- "hmac_key": "052BAB530B00EE214BB87D3A7A46470D373749AA78BAFEF1AD2A64B0C8728C94",
- "adv_salt": "1CDF",
- "plaintext": "74B1AB802BFE75EF1F1AC4FB8AF7DDC0741D6AB3140F4768",
- "ciphertext": "F51E89A9AE7D347B2CC08174D12B2B07247A40098348D657",
- "metadata_key_hmac": "AC6B3D12A30402663791B9CEA541823F99EAC95F21F2D495755FFDBA8F43A5D9"
- },
- {
- "key_seed": "AB936D1740465539A92961132253ABDE638C304135D1588F8157215CB291120A",
- "ldt_key": "DB2DAEC702ED084B1FCA7D9F4FEB0F140F12B22F5C194BAF069E884296188D627E1C5C798C9F38F0AA9F9999FB95F6DA875CF49BD07AD9365F4D121C27873245",
- "hmac_key": "0BB72516DE709C6403299B1800FFD09AA4B013A3948550654615BAE08A96CCAC",
- "adv_salt": "737D",
- "plaintext": "97BD94EC0E4C326BDB76403DAC23921D77",
- "ciphertext": "2E5C007FB9E59BAA4A6A538D32B5E9246F",
- "metadata_key_hmac": "48541FA93EEEFEBD8E36969957F326C1EBF9DA3232FD4288C144141D3F6876AF"
- },
- {
- "key_seed": "3E7487C215462E75514BAAA0C14A4DD71D6E2DA001A31BD8A3D9FE5C6D962195",
- "ldt_key": "6D7359744B5D4082F100A636F1E6FBBD0329913360B9947114B623E84F2C221BCE4D6219803FDDF3FCEE9EBA44C4630B852715671543AB241F497B2CC8C53291",
- "hmac_key": "CBD41B6071A3C06581C1B5B3EF442DDF6D1591674AC97A39695B27FE296FD389",
- "adv_salt": "7FCD",
- "plaintext": "E03882ECE4B6F113344658F383B03E441B57D33C9BA1E8146CBBA3",
- "ciphertext": "221C55F242986552EBD1058327D0DEB7032654057212C386FEDDBC",
- "metadata_key_hmac": "6CC53357EB70F5C56C1E856EE439F1583D41B7037FCB072B041E2682102E089A"
- },
- {
- "key_seed": "E9722D366DE0F0A0F7A11228E12434FEEC5A203EA4947555DDA1911A3EA0111B",
- "ldt_key": "A8B8C662D022A5ADB541CFAC69088998CC8101DAB078DCE30FB2AA5E2DDC7CFFEFFA0FB331925044397FD0C2C6147C6FB21CFC0D64295D43000FDD7CF6B1EA40",
- "hmac_key": "470953916FA2FA9EBB4DAEF62AA7ED658B03D25BFE529341F7B78204207CAE4D",
- "adv_salt": "B39F",
- "plaintext": "E918E8CC19B02D63DB53134FBD127C6255428B",
- "ciphertext": "ED7299FFFA71919FD7B15DA880B83C3442A087",
- "metadata_key_hmac": "A1D94715CEA145116325103C52F8A8D316FE51183BDBB132884B1F552320D96A"
- },
- {
- "key_seed": "657F721007F3A48224D51CABF73C85B9CBD0A2F029DFFE519634577AF244D28B",
- "ldt_key": "D5DCEDF527E99FD41790C0F3DE8AE36FCE74B789AE79A90F72C9D842CBE36F895DB93B0B2196FEF8B199C1622C6CB24BB5CE19DB55A0AF1E481E0B0315C0A2A9",
- "hmac_key": "F8A9D5E1C4B5AA2EA3841FEF56AC0C7B78E9D573B463EF8B073BF68304C144E5",
- "adv_salt": "0FC4",
- "plaintext": "B2DC5FE7537BF4D0EB7325E4835C65A8A35A4AD9F0AA933688D0DC83",
- "ciphertext": "D6187B040563C6307420E3B13DE6994962EB52974C82120A015E8CA4",
- "metadata_key_hmac": "7CF960B3272CDF434605907361BC2B50570AF1D6E055989F41C957A806339BB5"
- },
- {
- "key_seed": "292C5A123A43D0F42E90127B105318404DA371C996C4A17F5DD6C30FF7958406",
- "ldt_key": "987A64406EDBBC011AE42F1A3D9DE509CA4EBF10143F3D5279F096E151C43A11BAF20B7580811345D49B9B9A5E5E2CD726D72C9B0BA5222E1E265CD5E1BF113A",
- "hmac_key": "CF47390013455461037394AC76EC721743D13D853F3E9E44EF7B1D664B3AD5E9",
- "adv_salt": "B9DA",
- "plaintext": "525225673F0CC5E39A71CD89221DE13313BEA7",
- "ciphertext": "06CA5248993A16EDB9B2B17043828FBBF10B44",
- "metadata_key_hmac": "A3F213031DF32074A829B32C53CB7A518BCCB41A77FF2568083C992F457A727A"
- },
- {
- "key_seed": "63FC259C4DACC377FFA83C5338B5BB5F64CBADEBA56424668124DB5CBD0BDBFE",
- "ldt_key": "FE993C17559AB863ABDA0768EC49C18C5465257D8F13DDC39FDEEBC35F3B4359C374C8A011ED0985FD61B7179C89E3E91A04BE61E936B311FD783B81C8D068BB",
- "hmac_key": "63ACA66A9AB40DC5F040B85709DCCBB1F88841854F6738EA597F14A5D7EB0D0E",
- "adv_salt": "4054",
- "plaintext": "6A90C5445CB4D7F424B53CE0A5655C84B39BA050B00CC6",
- "ciphertext": "AA64031B3260E182AE8B0DB2E98460586C913DAE30EBE2",
- "metadata_key_hmac": "C192FE644E52388C10DB86D8149FE52A4612C3B735FE6E52BB1042DAFD589C1D"
- },
- {
- "key_seed": "A10EA2C864E46ABF4668DDF75213767674DF97C6556DDE65BEAB28329167A460",
- "ldt_key": "326548F1A422A58F79E50DF5F0706115943029F567271583F6155FE2F3380674BE9EECDA0F5DF4817FFB17BF1F6D93B2CCCF61339D722326B3400540367DCE69",
- "hmac_key": "9D34F06F4423EC5CA77EF649A9A1FD7BE435421AFCC624D23374D273E8DEE70B",
- "adv_salt": "7356",
- "plaintext": "0B6B2A17907494F0BD1929ABD84A0D63970A",
- "ciphertext": "38F245C019AD4DDCEF3985E17B3AA6F5CC23",
- "metadata_key_hmac": "C77ED847CF889ABAD73E5DE31D839E11F61B53D74DD830C522D7703DE9C935F6"
- },
- {
- "key_seed": "3A1128D12AE1D86EC7E38F7734D21A53DF90CAFC0F77D9E4FB9935531D8E092E",
- "ldt_key": "85F796AD7EA67077E4F37DD1E6674095E2520F678EF3C66ABFBA4A934B071694FE101384B7293CB5E0DC9DDAB6140D15BD0556A369780E4EB78D9D5F899177B5",
- "hmac_key": "BD3105688CD274A3D32733856360ADD3D0FDF9F8EE3A87AEC93361A0FF9C5BFD",
- "adv_salt": "F5F6",
- "plaintext": "BB91A063B68707B5EB408A9456FF0B70DAE42FB71D",
- "ciphertext": "7EF28CC2CB0FB35502225B878B7ED0FD3964139FF6",
- "metadata_key_hmac": "E81803DCAADCD2CF4594E3E70E1423F89BAE8ED72C225E9864F784E6E511E1DA"
- },
- {
- "key_seed": "99B92F70AC9546883FC032D413C7BA43251F5B1197157029158A273090AE4AF9",
- "ldt_key": "081F9E2C943245B9A217B1317B077BB702C54AFEC867EDE7B69DFC4426A1F70F4AFB90DD095121CB41C3FF3DF39E7D74778DF51002651B9E7231FC47BBDE10A0",
- "hmac_key": "2013269352BA181A1A8342DABA04615833B4EA47A1B7ED2E299CB4BFCD2C1C38",
- "adv_salt": "7750",
- "plaintext": "A9AA97C43D57268766AEE2E3B82CC3FE3F",
- "ciphertext": "46CE4D6A84BD43EA523403CD81F7299E2B",
- "metadata_key_hmac": "BC1AC137EA800966894058D6A4C1A3E68012A1B1D9AE67F035886E6E25A557E6"
- },
- {
- "key_seed": "D9B623A3217BC5B9CB0095102D02E35F06EB9386E3AE563F6011D1300A27F009",
- "ldt_key": "48E04C7769AD29A2D9F6CC9172E73ECBD0D9B8C21F1CFDD34D261C8F06AFCE890E36F9CC9CB7E4BBAD6FCAC8A6CD4F09D366E4E3D7AE0D6BDE26F8D0CED7EFB3",
- "hmac_key": "3A9009BAF19D54985BC734A2F8684EC06E043EC6B747138C3FF1B96C78C3482F",
- "adv_salt": "69B8",
- "plaintext": "DBA1FAA844FA6CF0CDAB8EFB15EA792CEC60",
- "ciphertext": "6762F4041339250AC4228C15E2564067A7C7",
- "metadata_key_hmac": "82D5B0A87195734D9492C38C51CE1FF8A7C957FC69402E2EDC7F88B8094312FF"
- },
- {
- "key_seed": "8540610609338C353920785A748CC82CE4BEA79838267C85E7A775B61EEC8268",
- "ldt_key": "84E1F7A0A6B332F9E0F1540322B455C4C04A4E2346CD5F807A3A4A195F609440E33525F239E297F5768AAA589E78517C94EE9418EAC35FD51DBDE9B70866623B",
- "hmac_key": "CA5EC32CB4FD314378C6BD4B101EA860674D00829E41D9F8388F064B894B90D9",
- "adv_salt": "F555",
- "plaintext": "F01F7ECB9DB990418271EAD6517B69D240F618291CA7E83A5E",
- "ciphertext": "BCBD94D94F3A94E231419E5918131288D0E267806A8ED1C618",
- "metadata_key_hmac": "7FAEF781D5087647F63CEF2161EE710F829CF9A6C3A3250F459BEA218921D4D6"
- },
- {
- "key_seed": "AE5859A3A592717E93B8718FD1356F25E1A37BE52EAFD8F19D5F01D72C8D5D01",
- "ldt_key": "2A2496A1E26EF4AD9BBCBA362C6E76F6ECFAAE36411F8C1EFB75ACA61475E52FBC6109980CFC640F1D15E1A6DC3185D72129D802099E8A435995176B20C8DCBE",
- "hmac_key": "5EFD065599480E3679211A8E9C6176CAE7ECF6464E80FDC9E69F484698F22856",
- "adv_salt": "F258",
- "plaintext": "DE7BA7D89F79FBA0F385E83EA06904401369432F116A52C65012",
- "ciphertext": "8B338B47491186F3D6E22D54D9D170BA86C7726818D37B6ADB4D",
- "metadata_key_hmac": "D9490422CE5E49F346A0DD3D0F747D7CE2136765D835FDCF36B3F535D76A3985"
- },
- {
- "key_seed": "92B9F22F44ECE464199FF2C3AAEDAFF3B7EBF1A25640216C4DC12701DAD31EA6",
- "ldt_key": "33D565EEC55600910B9ACCC0D577CB676CE3B32172F6A4001B3E0D5FCD041B6368BD650193E3FA4BC012522B98B4ADE3F450AB6CB8DE6DC255B437CAA2039D9A",
- "hmac_key": "47E3A833B777CBBD0435B64ACD5EBCD8180477E5865E23F7FB891FB9E9A4A9AD",
- "adv_salt": "C9BA",
- "plaintext": "62D57AE83E64A520E50F344F561DB4557331B60CC6F155E2",
- "ciphertext": "6AFB293C8CD05172ECB9BFC1E8BC2D042E29EFAD51E32B82",
- "metadata_key_hmac": "084E75DA1BF443CE36D659618F3169F76D105BF3EDD2D439CFE0D0066E3EF39D"
- },
- {
- "key_seed": "73DEED4CC7C9842A0DE8DACC70E8B4A556AAD079E19DCAD4F1A4EC0D844C4B9E",
- "ldt_key": "86FCDF0D697B181D82FFF10DC9E1323A96A4DB937477D863AA23E29B1E4C01450C5585B70F91EFE9793DBCD88144212C3F8BD001AD70B8E526DDFBC5B4C7AB2E",
- "hmac_key": "91B8956841DAC3C63EE9F0F1EDAB92B3337562E47E94B22EE9096EEBFB280ED0",
- "adv_salt": "0399",
- "plaintext": "C2940DD38E71C8AD0A2E03FFF6E36FBA",
- "ciphertext": "A51BAC7F36F58AE6B17D4F029C6F7D14",
- "metadata_key_hmac": "100599892D986891734D80390B9CBE2B65C7CC351BDB90C35B57065950A140B0"
- },
- {
- "key_seed": "D47D3EB118FC6310C7A9526DABCB0E4BA49588B357A98A8883142B23F0B47A3B",
- "ldt_key": "E0176A395D1ECE82B324D23D7F2EDFFD563E36B488806E7F62F28EE11F19709DDF8E2D83AE184EF30C0551ABD99FF30DC2998B6637EE98F9DDF0824D20365719",
- "hmac_key": "4C6C873F49F28AA342263ED3FCF9792815B4E08856AFF70BC4EB78E93AE950D9",
- "adv_salt": "6350",
- "plaintext": "B109D1014AE5F24A85D1DCEAD867672274EA7D6F6113C811696360",
- "ciphertext": "3EAB6A7C151FA3D7FF92C2FDB036431CE042E8B4827C609CB60646",
- "metadata_key_hmac": "1E0A2A08F07E766FEF889ACABA277D1241E5D745C903E56E97C6EAE449BD224A"
- },
- {
- "key_seed": "1B372B508A4B3F1F970F861193609B4EB3FD65C62A171A43731E9BB7BAA9F878",
- "ldt_key": "B304027A3E70434D7152342FED8164365CB874FD0EA9D4D9DB8B0571F876F4FEBC9FC13C2884FD76C8B5F1DDF9FE6DE9D98060ACC1273889B38C54B018C8949C",
- "hmac_key": "426D38B9AEDB2D80F2C4B3037E5E1BB5E676ABB286CCC1174C7A0135976C3C2D",
- "adv_salt": "A926",
- "plaintext": "EB7A7A86C2F103A2C960D1CDC0BB3704370A449D60C93E41A0C4D88C534E",
- "ciphertext": "51679BE7B8F588BCA4F7E48F9B27C6F8E97AAFFE76BCB0CBFE4BF198D760",
- "metadata_key_hmac": "0DA1E0F3DECB3D5440CEE3D0423C3580A0C1606F98DD6F3C3978499D1797C9F6"
- },
- {
- "key_seed": "754493F863A897595961A3764FD8BAD6E1E84E9FDA15246A47C4D133327B4C5F",
- "ldt_key": "CDA99F0F898B4B266AE899861CEDBA5BD129EB23ADF3F177135E0FAE52B0010C209315C69A478B6B44140C0FC9BCF375EE292A9808C70FF49E87A2EA7DD6CBFD",
- "hmac_key": "622E68EB5F4E2E992EB30EB45E3B35EF5E6DA45E529794501A272F0EDFA6E0AD",
- "adv_salt": "A07C",
- "plaintext": "F66887B63134A8B3E2C428F967FC28A40E2665187B9EC0F8B9",
- "ciphertext": "B218E6D728D9DECB32790D32A5FFF66381A3BAA9F214D14F5F",
- "metadata_key_hmac": "5D95EE76CCC49B67BBAB40F420D7A2ED2F59861FC2004674083BFAEE8EF09440"
- },
- {
- "key_seed": "A267D3FE83CBD62F70D1BEC104E66E1999C73FE878E1DCA48D532B15887ABFDF",
- "ldt_key": "39871DC7FA5144E3D0861B152DC43E8893B4B4AF88014275BD7BB64EA92B299F160623FD0A4618EB22ADBFDC1F99FEB9C7F967290D6894FCE4DEFC7B243ADF1A",
- "hmac_key": "C58AA858D6926937696EABAC03D17A1BB7D9E6ED80ADA6EA25F7657E6AED0794",
- "adv_salt": "F942",
- "plaintext": "4FBCF881713DCEA28BF500425DC5A8592AA03FF50E17",
- "ciphertext": "FD7E72EAF67E73448A42BCE1E55136145FBD5AB6A6B1",
- "metadata_key_hmac": "5B0F55FEFBB282687AB7BC04E51CDC5EAD2FDF944DAF9238CFD38A2519C51D59"
- },
- {
- "key_seed": "7590A9B827A09DD6BE252F2456F7700EA95BD03E3FBE909AC606AB6976EA5DBD",
- "ldt_key": "8D9B9E904A63EDE22683DA49C27695D10B84CCED446D27D817F50E5CB1D2A708AFE98551E9CB92D9C452E7EB2393B2DDD0327D24AE46024D2DD68EAF5A321B5C",
- "hmac_key": "91D3FE5D8A75F5A1EDD3D6DE51B8C0CAF0E6E579A6403C38C553F73710643AF3",
- "adv_salt": "F8B1",
- "plaintext": "54E53C14D0A4A72F6138A07CB9185C09B822A280",
- "ciphertext": "64B55EB264C13E34ED9B0D296A3F85884C18162A",
- "metadata_key_hmac": "33CD2E0D9FD1C0304E3EE973011B937EEEFA87C9C2BF2F138D18FEB1B5A54516"
- },
- {
- "key_seed": "89D2FD1C7D9BE6B6BC0EDBA1DB9C6C3F5E53BB141D22E0AF1FB2484D1E9DED73",
- "ldt_key": "BDA29601D9DB432AFEFD93B67F3867C9AA31C7CE75362684D1E6029EAAB2F4DC48812293970CC287241F3571BE3E3FE391163A0A2989CEC271ED16AAEE45B07D",
- "hmac_key": "0EC5E31F828B81589454F5D166242548AAB88BC252F5E3DDC283C667400ADD88",
- "adv_salt": "89EE",
- "plaintext": "89AD1A1A9D7FE6BD87BAE793FE161DA4004ED63DA608EC4EFD5E4F13955C17",
- "ciphertext": "70167D50FB6DD67C974857C23FA09168F9F984B0C36F91066181E4247EE5FC",
- "metadata_key_hmac": "292DB21E56B265F8DD3081DEFB8540906EC5C6276D16F2306D79B522A2692813"
- },
- {
- "key_seed": "FFECD4CBEF6576764BCEFCDC35D49F960F57C8EBBA3A7323E48359F045FD6C8B",
- "ldt_key": "5CC1784EDEC21D04C34AEA949B3993BDBC007DD49BEBE6D21645B230500184E04E33CA0D098C5B51E3FFAFD18C95DFC70630D995DE874DD0E1BF09A8A15114D0",
- "hmac_key": "66CB17DD1DD82408A7593463616D567B904107D2554D0750BF5AF527336A7545",
- "adv_salt": "CF7B",
- "plaintext": "F3FB937E5377F9DB4BD2D4EF2208165A6ABCE8641E349849F9503B6E",
- "ciphertext": "F6D8945B2244345013B9C42EF12E33428B08DE08B67D749245D315F1",
- "metadata_key_hmac": "5C8952B92EB8ADC934E67B68AC57A04172235C5803822F94F5A4D6EF02EBE042"
- },
- {
- "key_seed": "560238BF4D1284A55155B642EE1CB6D1F1259FA3E6E412D69C61832DBB0CC844",
- "ldt_key": "FE8A459B03738D1C600093921A2CF605BD9EF3153B80E43EC0A79B09544922482FB8633B7B5737C9B35D90273EF6071B381CD71D56F11525B57279AFF80D744D",
- "hmac_key": "86E0E51264643DE2E2935FE97A50724B2EDF9B9E9D29768B8834C7EB2DE168E0",
- "adv_salt": "C3F5",
- "plaintext": "095ADA0280AC300F54924AB297504E2C9E8E80258C",
- "ciphertext": "0C4540C7030EA877ADF9DFEF23787A2059D4CD971A",
- "metadata_key_hmac": "C253686143599E137D34B7B367A99351156427DAAF7823BCD78118FEFD172E27"
- },
- {
- "key_seed": "8D4A13F26ED5A961739C3EB2BFEA059BC99E44E7726CF1C922CF5220F2D3CDC1",
- "ldt_key": "65046E006C2A7AE278CE1C099D4F07A1AE030D210D9662784CC8F51B065AA2AFEA7D4B8580A17929080B070252172637C9EBDEAF21A96378F2751456034C3481",
- "hmac_key": "18CF2CF7420667D3A7FA6A479361A7F7E28161AAC5C6F84DA9C74EEE65B71EF7",
- "adv_salt": "5436",
- "plaintext": "B76F88C0F087756FC52FED378C69956785D975CA07CD6F56B5CE2564BCA4",
- "ciphertext": "9B767EF93B9360A08F2E984D617446EF0B360C0FE1207C547664287EFAFD",
- "metadata_key_hmac": "0114585B0BAC8F8EA1B88F01C3CB5B4D2F7A7059FFEACCF7A4F90505938D75D2"
- },
- {
- "key_seed": "C03CA925B56D7561DCFE958604A65C9A2AF5BD32901F4DB58CECAA9DDE86A785",
- "ldt_key": "35F77C5C186F8F6DE64355A6FAC478B0311097B18B7272E2175074B2CC6B8D4565D4B496383013C18C6DF23D84DA5A502CADE24A8393A519CE58CE9295DD7463",
- "hmac_key": "A9F3C2102306B52825ED579E454AC2D3C97043BFA018F9FD3C8E0A84ED22781F",
- "adv_salt": "17FF",
- "plaintext": "1435AE44951D8B30AF9F82FA7099789149A5CD704C292D09B56C",
- "ciphertext": "4E77C59CF06B94DDA606D8837E60E1765F2B832562DA329C4A82",
- "metadata_key_hmac": "0899362FB0F8C6D052AE49C70947C5BB576B0E7A03A341BD301B175C7BDAA185"
- },
- {
- "key_seed": "2DD921FAC7C94A14704DEC774BF3B966B6C605E359F8631B3F573AC88BE3A3EE",
- "ldt_key": "6FCBBCC9738AED48819D5F410CC938EA41C5011B7C32B6B9C1D7F9F1699E7C55C7893C9752614226A94CBC441726D94F365BE068E5E641D8DF51D2FF14F183FA",
- "hmac_key": "3FDF2E252A1D3DB8FC22F4FA3E4BB46E27FD9285F67ACAD4A3B18613C7429A23",
- "adv_salt": "C63D",
- "plaintext": "4E18456921ABB6CF637924DFACF7A9C3FAE58CDBBB9F",
- "ciphertext": "C5A7BFDE9F216CBA9971122C3DF85C0BDEBB287222AA",
- "metadata_key_hmac": "1C1CFA1B668CECE1CBBB580A84707E9B5CF30DD6F15ACF18741C52F0FE7767D3"
- },
- {
- "key_seed": "DCA956B5EEFDA5B3C69921BC348279470281A2530BC257E5232462CB1FC8B7D3",
- "ldt_key": "A5CDF7F81CDA770C3445302A6FAE352D8F7CEE51CF40D9CF2CE8B726187497F9BC4DA1A8B6A55F7895AE12032B6DD2FA9451382E28306E20672E0D0E04FBB63E",
- "hmac_key": "E5008AE8058FDF4051ACADBBC844D6C985DE056450EBD7146CE188DC5869307B",
- "adv_salt": "90AC",
- "plaintext": "384E8805B425963315323F490816717C9A5A",
- "ciphertext": "502B16CAE050677D23B192893E594D9E5F02",
- "metadata_key_hmac": "4BFF98CC40EEB672706674F6D21C8FDEAD9B52C90C7B2CF501633848BA2F5ECC"
- },
- {
- "key_seed": "40AF40B7FF79C424E70C7E054599A279C8431A8A512E775F0607726B13B3AE15",
- "ldt_key": "35462ABCAA42D664176C8FAEEE17AD02448447B15DD737B4B755E251AB3884CA8EEC1EF3D4DB171936E0ADCFEDCC69A9C1B3F758685D126C2A4C1C129427B021",
- "hmac_key": "E367639CB8320BF69D697FE3C7C0E5277671170E5214F4CA2352635242F6BF36",
- "adv_salt": "2BFD",
- "plaintext": "C5BDE767A457E7E723C6610F1C455F9DABBA438693AF9A642805",
- "ciphertext": "4A4173275F50DA2D98A22343D2DAF2CF9C61FF087A3956613650",
- "metadata_key_hmac": "B88209F17B55D83B71BA7980462B779C00424013C90AE9CEB12E0DBDFF064500"
- },
- {
- "key_seed": "FF5C96B3FD32837F21B5CC7F9F9EAB1ED11F89812965C2B28AA81A536441EB74",
- "ldt_key": "9893C0DF1BCEC6EA99CB4C8CADFC83A42030428E7E7FD396A63CCA339A33E845A17D17CFB321682897E5181DAB5815CE194FCF8C05B037125B1E81B02B89CDD6",
- "hmac_key": "77F7CE078AC8BE9E03C40FBCB45AB62713EC512A733A58DD3CAFD176EB8E3B1B",
- "adv_salt": "66F9",
- "plaintext": "5FD020213436384B7302E92E202AE739A20BF68394",
- "ciphertext": "838C667C5CF02A36FB8026DD2F3540F9672D3C1728",
- "metadata_key_hmac": "D3DCFE7C53089590B94130A04E76EA89523069EB225A07A734AF1660B2A23E6B"
- },
- {
- "key_seed": "6FAC7D59FF8BAB3DB3847956AC8DBD8B3519C08AF4C711F20D38CD3F567D2DE2",
- "ldt_key": "D903C89A12961C3BCD38A3F19C8441ED0CF8916BA13B472E12474C18AE5C455088190BEB14245166D53AA16F98E72EF68CBDBC35E762D7CACA8E60CFB3711DF6",
- "hmac_key": "AA70D3407F9776F3917982AFA2DD41029CFD07E819C4373C8FE08810DFC9D204",
- "adv_salt": "F797",
- "plaintext": "4C409543C6024CCA4F833B368B23E9B44AC6",
- "ciphertext": "D3C399978ED47AC0C6BB5B5E57596B684900",
- "metadata_key_hmac": "E530122F1737AB2C99ACA47BA0CE96F27291C34DD1F80508198F7408EC37D39B"
- },
- {
- "key_seed": "CCF31A1494E92113BDD49360A5BB7FFB31B8E0878FBBB40BC844EE5087DF5DF2",
- "ldt_key": "7CB2F134F970F0D286D67F2DFA24C286EEE2D83FB111238DBB86F0402651B520B14AC172E2E16AB5105213E5289F6D51566079F1815CB2C5F7A9E3BE57FD9F15",
- "hmac_key": "C7670A04ABB7A78F7BC2456E91C5C717B008E2B063EA9A6CD763189BE4484646",
- "adv_salt": "E4EE",
- "plaintext": "BA8F7B5E0099CB0254B6747A3D49C06EAA91",
- "ciphertext": "490BF53B189F05A0C937DE2D8A7F0D7EBD5D",
- "metadata_key_hmac": "0C64AA6E76896D4A4603A4AE2FE2EAFB55E3B3535D71FC284D835C031E55DB73"
- },
- {
- "key_seed": "3C77FC3A249EF67B375F97A0D14C4341236335BE81A955895CEB78BDE0E89BD2",
- "ldt_key": "C282CBF603E1886AE361B89F87FBD22213E8B596EC303DD76A9764D4B9702389DE15C0212AC2DBD5662771A4B4073205BD4B28C5ACB9D24ACBB71DE21A50672C",
- "hmac_key": "2CA4ACC4D15728C0BD9B97D9DED9C7002610BD8E7348AFD1FFE70A9EE0DD37AB",
- "adv_salt": "C399",
- "plaintext": "BB8B563AB689CE07F3AC5C836DC7AF75A150407E9AF7FAFD4A5E25",
- "ciphertext": "A0EB44DB1F915D2E5AE43A9379FBB8F09E2AEE75D23CB48C4047A0",
- "metadata_key_hmac": "35AD7B763E05D22D41BD8573CEF4BABB85640F8203BC944E50DDC193E44B2459"
- },
- {
- "key_seed": "8260021B76DD65A64D8BDE991230DDFC682B333C51A5B975E1BB86B5FDC45F4B",
- "ldt_key": "1019E0760F6E99414F88B799938456C3819A09DE88F1DD02C8AC46473CAF0D75BBBE3A9E974C67476BA1239913140C0F899B9635F72429855B9F686E4FEDD529",
- "hmac_key": "202513CEBD157D750D437F4148334114B1169D6B08FBBD9F4C8D9BCA29A65D3A",
- "adv_salt": "8156",
- "plaintext": "26B9909FD80BBC3E9C4C7498AFDCA0C6F4ECB6462E9D0F",
- "ciphertext": "BE9420D32E1B19109C6BC153773A4897EAD24FB543CF39",
- "metadata_key_hmac": "D9E9C1497DDA5DC914707D14F0D475B37991C4A97D6CBB412FE4295E30A969C2"
- },
- {
- "key_seed": "5AC98E6B28870A3B01BA153498F4902FDBC0841F3AA048262A82F6207DD95F55",
- "ldt_key": "009867255A86E609C46E67B290F648B7E6B99EBC836E8C57506647C0821663B8BEFB31CEFC940A12738301260F77B974EC782ADECFF6ED8E3AF3E457D8F39980",
- "hmac_key": "4CFB59FD5B32224CE9D5B20D7C5BA93B8A16CEDA3B1D44E1471425340CB2A61F",
- "adv_salt": "4E72",
- "plaintext": "C2664EDEA11131E747D4BEA585651ADA4B8125B3A38F5CA8FAEFD8",
- "ciphertext": "B4D1B01AD0C7E3C8A71193517B3176A75B81049EE04F6DB5B18F21",
- "metadata_key_hmac": "619272D9A524C2BD3D3AFCF8E356804A23AC4DF7FB041F1BEA35D77CC768A11A"
- },
- {
- "key_seed": "ED0A64DC30DD3247C5EA07A27BE1F02DB8057D663C1A4C88BAD61433E05EF966",
- "ldt_key": "924D5FAD57CE4E565F9054F4C22D028E8865F8378BF2C9135579086FFE45D305A6D1008821FCA9E83ACFFBFCAB395F55985009F1E4DCA4CDD45E331590BFEB2D",
- "hmac_key": "AB32E92C7272EE428445A5BF592228D59606C1D2E9EEE1892386676CF3D70E3B",
- "adv_salt": "E8F7",
- "plaintext": "3F3436D46DA3900D591FA3ABC6B2290DEA3F10A0AF",
- "ciphertext": "56A16B25B8267ED32C87B9334083581BE0BF1B5BED",
- "metadata_key_hmac": "BA3289FE992B1F99D0338293547506D3CD7991F7A4FC02818BF918B7A4193921"
- },
- {
- "key_seed": "C0197439FEC973B0DE7D6F6D365A2DA4FB4D50FE0D93888E6D734857EED03D29",
- "ldt_key": "716964EEAAE8083896DB7CEDBF25F8EDDA965C6187B4A5FCE71730128D7601A2947B030CDD6B6FABC268AA696883FCB81332945DA5EECA2926D19EB69C87F427",
- "hmac_key": "FA076FC072E2C3A3404D16A11285275D7F0C706DB3B9A73C4CDBE5CB6209C104",
- "adv_salt": "7968",
- "plaintext": "D63A94F053AE7F91C82EBB969894270D0C91A72BFA",
- "ciphertext": "FE4C5EBF299363DE9E8366950896FEC5ED67088526",
- "metadata_key_hmac": "43AA21A8E39F1B2B4AF529043D9C4585241DE221937EA81483457245D91DE00D"
- },
- {
- "key_seed": "697C43D66FDBD83CE464BEF25465DC1D8B638CDAEFA077A26C19605B4B682DCD",
- "ldt_key": "4542703B2CFF1FB68AA0C3D2E2B1DA51BB7FFDBF909E22D414A2ECD4C05B4CD569305B18F437A8AD38AF621624377327DB77E9D9E5F5A2AE1E5275410A72F399",
- "hmac_key": "79BB8B92830FFE7D861D7E983F00747F11B27E7E4CD894AAB98BFDADF2D85117",
- "adv_salt": "0C0A",
- "plaintext": "D1DCA4BBA2FF7D3AF46325F5CCD5A88702",
- "ciphertext": "FE0ED60EE668D3B17CB88D2092AA97D455",
- "metadata_key_hmac": "1AC786DEB74DFB2E6AFF4B6CBCA604D9D17AE479F0D803D15B8E349A3E0C2216"
- },
- {
- "key_seed": "06744EA084560A864AEB290170297DED5C75F501857C323BA8AFBDB98EC8A36A",
- "ldt_key": "D512EBFB1CF9FAFD53ED2BD36B95311424DEC109D0736B1EA9E1DE6B1ACFD4B8C97361DDC8BE2BD00A8981923191ED8442C7249DEB595C8581BD79184FF86420",
- "hmac_key": "D0855C61600EE6995650EE1CC1B6025A427A49797A3D28BCEC4C56F792A4FC56",
- "adv_salt": "EAA6",
- "plaintext": "A7305489DF9B70E57C6078EC6EC3929D08C2E25D7B3E3A",
- "ciphertext": "42F28FAD9FF09D8DC1EE7DF691F9FA1073FF3069E500BF",
- "metadata_key_hmac": "CACAE0755E5FB2B9252083B6E5B111974DBE8198E73DA9FA71F87CBF142946EF"
- },
- {
- "key_seed": "6FA27E2ACBF24626C245DAB2F9F0BA09F14D3CAD3546B04FE69DD0AC4A81696D",
- "ldt_key": "013516054A4C325FE76F96AC9CD773062A7A413C5DBAEDB9E7E52CDF15E4314DB9F9F9AE11FA4E958CD847F233AA9895D135AA9E39BCBBA416061D7F821AB7EA",
- "hmac_key": "F2DD61A7A2CA13301E561908FA0A4855D261E1E9376CFFFFAF0A0B1182AFDCB4",
- "adv_salt": "19BF",
- "plaintext": "61B445648D1A7DF53C2C4D2DC56533D0AAFA413EB14C4A8AC4F575",
- "ciphertext": "E6A0956FCCB9E2B9FE858870329DA6ED95EB05E7CDBADE0B738220",
- "metadata_key_hmac": "5F218B368DE8AAECFA1CDF6AF51F1FC8363F6EDF962F6EC73FFE46BE420BF229"
- },
- {
- "key_seed": "B38D67920F2C40376AB3FED7D17CE6A506113056878092435B2800F452FB3C73",
- "ldt_key": "2CBCC0C06331A4DA6A89D6D71896C2A41952F303464B3CD7D3D40AA4F8ED40537ACA2DB1B25DA39BCD0EA450404394DA3BA381055E624A1A955B395C8F0F044A",
- "hmac_key": "FD0ED8C3F2458CEFC7374500F1102AADC30C1E4B95FDE36B988B8F7CC21810ED",
- "adv_salt": "C585",
- "plaintext": "14BC22AB086A9C5CAEF9C8D017C7F27849324CED0C",
- "ciphertext": "94073101F480749B2542BED8E629BD7B7DA8BEBB01",
- "metadata_key_hmac": "1E8414AEE2B04DD29B49BE15DB713E63F0BB2D4733348E7D77CE8221D78FFE95"
- },
- {
- "key_seed": "6BD37AB62944CA4CEC25D73CAAC6F3498B34D6C2390EBE17E91B19863FBCBC6C",
- "ldt_key": "48961462E6646A3F481373B6CCED96BC20CDA30FB664597DD35CE6292005E5470CEF79B662CCE6D730765D0443B7AADBF5A419332FB0CCFC0BEA069F85A0A792",
- "hmac_key": "478E6E944FCCFEA4D38EB03DAE59EB00DE7EFAAAE537F8EE6BDE87DF5ABD8327",
- "adv_salt": "2751",
- "plaintext": "952910F1E3DCB83CEEA55422EF1C2CA4E46B1A04D970",
- "ciphertext": "D906530759DFCBFD38D97B09BB9DAB63D68A7B7B9848",
- "metadata_key_hmac": "FB65431090B30F67EFC457BE2A449D644BC83F2D5F1C717171ECFCFF82676F28"
- },
- {
- "key_seed": "A330634C116712EA137CE53722858AD6138F2CD90988BF158211ED5CE5182338",
- "ldt_key": "8B4C490D6365F4A5A97286743D283E062A83D73DBAB6EAD6DC39C494F68AEDC0C00C58FEEA41E566EDCC4C3D63BBA6C1BFD904318060E945C329CC6F62F63B2E",
- "hmac_key": "F25C43F900ACA2D340456D6840F1C3DC443DF2763091D939E93A53324D71E5D2",
- "adv_salt": "4A3B",
- "plaintext": "0355A87A074F53CD834D5F2238B0335D2CC277",
- "ciphertext": "B730CE0C75511611828492F865AA841EA60028",
- "metadata_key_hmac": "CB6CE48F7B1C5E06BB357EECFF068AFA13AF676DF66312968840E4D43037D627"
- },
- {
- "key_seed": "69605BAF6A2299BAB7A3117F501BAB2E153517A0575932A25CDD173C77804DA3",
- "ldt_key": "5BE1FAF5E9929EDAB360C5674506D8A931CD94C18EAEC3D0D411788B2B80A2C79814DF26ED3FDB3B125F378FA89411C7C6EA2CCD8A76158D9360952832E1F364",
- "hmac_key": "CC227C88EF67D8AA4973349DB2896027BB95C1AAA02CF64F0F8D5014CD368DC0",
- "adv_salt": "DACD",
- "plaintext": "9D04514DF277767EC7259E463B0F768C1158AFE8F98451716FD8",
- "ciphertext": "F6A099E137900CF08E4AE3C425866DE178D1C0FAD9E34AD5DEF0",
- "metadata_key_hmac": "C42A041EF294EBE5148260BA7B3E79C516D0BB68866F67DFC676A4C50A7CF17A"
- },
- {
- "key_seed": "A8E067D4DAF508F350A6053DD414B892F61022DB040BE37C41525E856042C043",
- "ldt_key": "EAA8C9DB71F86D712FB5F37017AE755D13FF856BD8AAB483C9DAF1E057BD0C0DBB0FA91FC6A6F543AB8904AB427CE7A74EA033C30D08CD7F7090E08BABC83594",
- "hmac_key": "BE0B4023C4F3EAF51F78C5B3FEC4265B6ACE0D1533F87800419CCE566FB65327",
- "adv_salt": "4769",
- "plaintext": "5A7359231F0D71558583BD2ED0A6132EE1B883A3E007BF",
- "ciphertext": "E1B783C4E61A5D7E9C0A1C3D7B9FE3C1B3A32EB00B8BC8",
- "metadata_key_hmac": "E77F1DDB4AB574B61ABC25A4A401D1B2D5C56208821C7969DBAA51E0AD8655DA"
- },
- {
- "key_seed": "33BF72DF056F642EF3ECE670B6DB89AAACEC79714C08EBFA3D67D5337B10CEC5",
- "ldt_key": "7E69EF6784947FB842CAC947892EB92E25998B4C351C52B47B1FF8BED34FD9B614E4B6C0DBC473B8403D9E83538441592A85A7DD623893CDDDBA93BA091843FD",
- "hmac_key": "F79E99ECA90D7B6E1BBD7A56D9D162E4C997B8C13C3EB67ACFDF6C45435BEA7B",
- "adv_salt": "0795",
- "plaintext": "8259E9342572AAE69EB853F4ED235A4E2B352042225064",
- "ciphertext": "AD48FC27DDACE86F2B30D057439BA73BE6B2481F801BCE",
- "metadata_key_hmac": "F81CDA4ADF43CFEE4FCA7B5504741F3BFE4C777FE27B5BC9911E28F68358B792"
- },
- {
- "key_seed": "23FD4FA8106C7B8A988BA2E9D7FF5960DDF21A93B153952F31BB1CD7C3D8FDB4",
- "ldt_key": "7DC8CFC25C60B5F3D0CC05B0CA4CBF0AE292F78E8B25CF18241E10F55FB86C7674242A42DC27BC252922D9FCB8524BBDE9146BE4F2EF5B1D20AE9473DE54F12A",
- "hmac_key": "81C08850212A281C3A1FCBED4E70A460A91A1A3C8DBBE77C5615DDBD3A1A0058",
- "adv_salt": "5141",
- "plaintext": "99465FF4B2E920F83F0FD5680C7AA33886C7DB872687069ECC7DAB",
- "ciphertext": "FE2E63AEE44DAB9E4C8FAD0DCD5BD8E4C770292E344B4D07777617",
- "metadata_key_hmac": "C8A25EC974F10643E7092B40A116667D302C459ACD15CFA531159E224A61D7ED"
- },
- {
- "key_seed": "7B5E0E72796A7CDE98719D8B0DBCCC6CFD636C6DBE476F8A206FC8F78B12BA7F",
- "ldt_key": "8FA267D43BFB36D59C970771A15B08651251F4F2DDA6CF223258469F883D1099BC8C0AF94EDDD649A4DC537E55A7782278150A442D516C61B561313787CB497E",
- "hmac_key": "90C88F0C2CB1A762C19D250F3F7E1AA217059CCAEAD8FE13649FDD9563846EE7",
- "adv_salt": "38A4",
- "plaintext": "F23D41E3C96B3EDD64BB32DA96E7127DDA561CE75690DBC84313",
- "ciphertext": "8D4479180E250BDCAF93A1C7254B12CEA1CAE90622D2C5617037",
- "metadata_key_hmac": "8346376CFE03573F9105464067C53CE38C712FD42CE6367B5DC019040EE66219"
- },
- {
- "key_seed": "FD6EF6225C64BAF3942E9CC8B8B2FB31333DD7C4CD0371D8E7A8BFACD67A5406",
- "ldt_key": "BD5ECC8DC600DCF4BB0CF4FF255406325329EEB2315E9AF6826E95C00E118F2A04CD9801B87C108F098F77AAB3A6DB3CF7D1AFA2A4A44E698C9B6C28CDDE387F",
- "hmac_key": "60D11CC44952B70588BC218186A89ED0F6C88DA4149C8F812F162470694250F4",
- "adv_salt": "8A82",
- "plaintext": "4CDD507A6EF676F63838CB94CD080FDC1FC415403217195FA2",
- "ciphertext": "8D4A363B48EC2E7DE7F394BD19C68863DD8B185209538A00E5",
- "metadata_key_hmac": "4A7AF9E6E406F73B01F669681064182BCF68F34EF4B2D7CF49B7A92E9BD847AC"
- },
- {
- "key_seed": "C7D86CDFD6C4CC20A6E02F16F141526DA17D2023454CEE6B49B7DD75FC023B8C",
- "ldt_key": "36CF3CF171CE8B6D96062FE3A388FA871B018880F639A19FA89B2012F43378C02437A2F1EE170EE196797897A88FB145D8CA1FF5F2220A6EE6C08CCCCBCAA161",
- "hmac_key": "7FC77CEF16D868F5DF038049B1679244F9A926395FE78BC4E30BDFF8815D2309",
- "adv_salt": "0F1D",
- "plaintext": "AC56E8D0B4BD95E907E79160B5C9164A9CB6D1B632052A",
- "ciphertext": "7507293BA55C77821BB0434B0B80F379E7E92230C5E714",
- "metadata_key_hmac": "2B22BEED4D9C8976E67972769003479B96D65E348C67765538D53D0BF13F1959"
- },
- {
- "key_seed": "B9EF34F19378FFDDCD6A037B700B7C1249CB8D23861DB2BE4A82F8B60B971232",
- "ldt_key": "22A3598D49087AEBA3EB405F8E2BD1F5D3B493C73C6F04A208A58E250DB094E9925F0F5597D6099501FBE3FAC9C5F352D1A50A7822A619F972298451CBEE149D",
- "hmac_key": "C20A8A2466913A13F5274B6ADC1672DECA17F8DCD93993ED259131B3D26247DB",
- "adv_salt": "128C",
- "plaintext": "3CB22D13BCF6B49ACBF0307C977BEF4AF024C5E939C1",
- "ciphertext": "658816AF0BA9938CC80BC657342405FB58B4F5C69A70",
- "metadata_key_hmac": "2C676E6FBA574FF9AF15F9E52742E43D677DE1EEAAE68F83ED265D62CB952748"
- },
- {
- "key_seed": "F6E2BCDE6535687F2BEE7D31CEF07C094A4291368DC9E0D29E4E7A84743E0617",
- "ldt_key": "F3EFC45D8829FA28138A943224D13E5DF087F4020ED84AFAA136ED4F8D1324F53F45ADA3F989B70BE718EB1FBCA33EC100D1FE2D84D2B8BA8FB2C862A4CB07B1",
- "hmac_key": "47A87F2ADC7E47B0E40110AB53721539CCBBD7E83FE51E9CB027C9A8B9399278",
- "adv_salt": "6310",
- "plaintext": "BACB663633EC8A203B8E47CC78E2FC3C57A4353D0D",
- "ciphertext": "2146B3391C532606207377D6DD7129C3BA2EFC54BB",
- "metadata_key_hmac": "D98EF41807B9CEF28CBEEB1471FE28D288952F8724577C00E71583185C490953"
- },
- {
- "key_seed": "BBFFC330C5116DA19A7C6A5E8B4316E6A5B2F1BC5F4D20D8C5860FD88DCEB878",
- "ldt_key": "E87D1C153AA1550030306A646114F51AD0540E09FCFF9FE540733688690D03BF2602466AF95EA855B8BED74433A033E3C299BED3A38FE0790C631B0D04A04EDA",
- "hmac_key": "62B2034BA3F1AF080C0669B5F0858AEE56CE7A8B33EFD59AD37018D5CEEED31F",
- "adv_salt": "BD55",
- "plaintext": "CFAD209C744144A5B30F993907BAE63FA71C",
- "ciphertext": "181A4E56F70F0430D21D0DD4FB14A1B7FAD1",
- "metadata_key_hmac": "28397F3D55EF8C0E29229EA51D6A7CE95C0803C5E149CD8C9AA550991D08A4EC"
- },
- {
- "key_seed": "4FDFE79A62944A011A72126D4E68B5CE66169C91CA7CF5F9674193623C616FAC",
- "ldt_key": "DD8C89D4416DB6F6A2684AD39BDFE617E37FB63FA61299A9DB89B72239FDBC977B0CB0602BA265AA59D8FCF97A89E0A0A51E0E160447358B0F44C62E187142A1",
- "hmac_key": "8678D9FB5D39557B280134284789042FA9C7DEDBAB36197381499CF53366AA47",
- "adv_salt": "68DE",
- "plaintext": "810CD81E8E65E2ECF1FB83BC041E94E7E873DAEF0B64447D59BBDD421B",
- "ciphertext": "3A1497277E3A3F20C43E245B947C34001CE9188AFFFA38F4FAAED972B4",
- "metadata_key_hmac": "B2552A6641B7922F972D62FE82637170920586808086357A48BA3ADAF9AE7446"
- },
- {
- "key_seed": "189B61463E970CFB7592E88303F0A8DC86CDDFCDC26BAF74A8D68D97C210E23A",
- "ldt_key": "393558113FCFE50A4730736EF9EA91C9D5DE4CAE137BE0FDCC1094C0A899DAED1C421895C90DDF843BF2575CEFAEE46F070684A6A33397AF93CBD9D7FC1CEBB6",
- "hmac_key": "D072CF232AD840B8E603F8E4714CB511117C0FC0BDE0F6A51C5F514C9C9FF428",
- "adv_salt": "3AB1",
- "plaintext": "97ACE46DBEB775F42AC8D738A254BEE3A6CA83062349861458F4B5745495E7",
- "ciphertext": "FDE78BE771E2174F182BC153368533F4ECAB80DABD8C18A3849E9AAF0AF60C",
- "metadata_key_hmac": "5B95374AB9E06D61E9C2FFDD88D28A9A78EF484ED7E2F3884FA10C42B82D43A4"
- },
- {
- "key_seed": "8099925AB4138B87D1945B94B5C38D8E409392A59A0B8571C5D6F2F9CB35FA3B",
- "ldt_key": "0A0E7DDC21515365D406EC8A51827740CCF512BB2AC70A85A9B14149706DDD62AC43ED590EC9A27E3560F8F9FB6B106E0F08ABA0616D7C5AC6E3F4F4B1D0F0BE",
- "hmac_key": "734EB396DC44EFC2928F7A19707231B7B98B5BEBC101CE7C6E9561D130C4D8CB",
- "adv_salt": "596B",
- "plaintext": "64DD65CF714E17B310A8949C2B171F1F931CE19AAB3A8AC7C6F0B7AF",
- "ciphertext": "9B8DA9C7182734B97C0E2BF2702689C95F593A61E60ED5B9FB2506F1",
- "metadata_key_hmac": "5C45C2C3FFEA97083F007F084EC0A8E21D9C827AE8C15B3ED895A99B3158C986"
- },
- {
- "key_seed": "27041C6BAC8D938489F45F322E201C7F77692E29605F162ABE43BC7DD443A922",
- "ldt_key": "DA4669A8269237CD04D1E2BA5077C988860F0AE9BCAEBE0F72BFAF63DA6825D5AF7A8E7A2AB8A607C0434BC618158090E476EDF87B7C65D120E1BF4ED98C626D",
- "hmac_key": "DA52FD9EF396CB4550143E011683735589D8D3B92FF6D1BFBFFE6E9B7C1E19CE",
- "adv_salt": "0D49",
- "plaintext": "97D24BFCA3E2414657302E6388E0CE5FE8DC8E5C",
- "ciphertext": "F90608E4C090D7A4EFC127295EDC0BFB863422CF",
- "metadata_key_hmac": "D1C309C36E66F33670D6FDA0EE05E0703669D7231A1415ABA0ADED32844F2A36"
- },
- {
- "key_seed": "8D6A7B1B75A42EF4D0D765FC5E349BFECAAA5F2F44FF401B69A9A6B3A592C5A5",
- "ldt_key": "7A0DB884E2DFCC2C902BEA55C4D9AE023A090226294DA6BDB13D6DB9EAE4AD4B836EAE4A76C1505BE7EB4C8200BE0E7671849A276A9E86AF9B8114B0C59A1529",
- "hmac_key": "774BBB9ED55FF7B5F7E7067A93D43EBF39A848C053A6F7CAFB470765EE051562",
- "adv_salt": "54EC",
- "plaintext": "D5B99BD450181B46608DCBE86970A4461676E3350493",
- "ciphertext": "72360EE5F4E00AD259BA7B27D44DFBAB8E1D7E87FFCA",
- "metadata_key_hmac": "B6874A01C4C4134AFA8D2617C0E12DC5E2933DC50E4965EDB516037D389EFC51"
- },
- {
- "key_seed": "8B35CEAED75AB9BC440007C1FDEB67BDE737C1BBC5A47151CED4AEC30E316A3D",
- "ldt_key": "70AD11208A009AC067C91BE445D1161555EF0107F7988334885ABE4E795F44B913F8704825396F3619F0851F5462CCCC378DD3B6E58527290D2CDC11C2CFC408",
- "hmac_key": "F86E2AC57F9CEF2447AE1861A964BD6438F3119032B62ADA5D3CB0DB426FA1E6",
- "adv_salt": "10A1",
- "plaintext": "DEC03FA063713924FC5D1B496C66188C73F61B",
- "ciphertext": "91E43CFCA71C439A7B3833F44643A2EF96F796",
- "metadata_key_hmac": "8DFAA644D383B7711E0915EB2298F50E68980374E82ABAD0BD6E748317CC2427"
- },
- {
- "key_seed": "4B6529FE3922521F7E60426FEA8BB5AAB0F937697887C0A419CD7689F408EF1B",
- "ldt_key": "DCB3850034660D35BD5653ABAC9B74D09312A129124BB088D987F2A226ADDDC6CE3C9083DDF2BF4E5F4C2DBA7F54EC28C7325DEF05B4A6F7701CD43E5A44FFE4",
- "hmac_key": "70BBCB078B01A2B5D9AE6DB6FD3FF814D6858E8D1884052526B3948DE0159E1C",
- "adv_salt": "1702",
- "plaintext": "06BF92FEBEE1E3517771754F6B9E6CCA43A6B466",
- "ciphertext": "1973E758175EBE6AAC496F454BA5E962620206B5",
- "metadata_key_hmac": "BD57BCD419CC438CD03FA8C2DD95880248DC114FF8B95272D2A79F1AC30AC1AC"
- },
- {
- "key_seed": "54E3854608122E139E0385AD5DAC9FE9B6632EE73DE765C15235BD2B71D54E4B",
- "ldt_key": "B3E9D65E8A2CD6CBDF96F023ADCC82D446C22774C2472C7B5E0042A095A12279606B03BC4FA9FBF42CE1BFBA96E972E27707E9DBA555EF011CED92C138792553",
- "hmac_key": "71929D03409011AC1217D222EED45EA0BE580E82814A00C03FBDE9BE40EEE005",
- "adv_salt": "A6C4",
- "plaintext": "63F169242519545BF6BC6C2B41F07D6532789928FFE91843F9197228EA",
- "ciphertext": "C18A5C4DB3C1A5365A46E2866AEE404FE12CC6EBCCA12BBF061AA83822",
- "metadata_key_hmac": "9E11391EA502FD1304D9C15A0FF8BB707571EE09E0EFB44A7D612C7E5216C9D6"
- },
- {
- "key_seed": "A00D4DCE27F6531056891C93C22D2A61830191A296B5BBE3760D3B13FF548F61",
- "ldt_key": "6FACCF6AA86CB8F0C05991AFDFD57C4A06C58DC6195E0BCFA426C66DE04A2779B62E7BA6882589B825F9192D31D3C91268D70D425F52F961EF3D1C9B045F01F2",
- "hmac_key": "E19B1E9F5C3355A52C6872225EF92CB09686F4B3CFDC883B7A01DA60D897613A",
- "adv_salt": "324F",
- "plaintext": "C103C7B8183BB72CF30A1CCCFF6E6774AA08AC",
- "ciphertext": "7D328033E813212D6DC0B577609E3F0696A4BD",
- "metadata_key_hmac": "407C1AE2B01585EDED1FC57AEE81D5DB54A2111DE3C131E4DD61EF8F22FDAEB4"
- },
- {
- "key_seed": "1CCF58E167E1A6D7BAFB4D5DBF7AECFE1A5B067FDE2F4FE1C6A7622980E39FFE",
- "ldt_key": "BD52C9294BEE6999D032FF607ADD946DAF8A83122C608C473133D778D35003955F2DFD35FA136053C24FB10A40408408F5011BAE86544282D8C02B2B050DB963",
- "hmac_key": "1CA6D8D35B2B32622CD6623F82476319AF0D0C2A59BB3AC9C9088ED78CD3ABBD",
- "adv_salt": "A659",
- "plaintext": "6F0371455A75B8874CA29067E946B1624AF75B0D2E77E569",
- "ciphertext": "54125A4C0B9084F8205FDBB573BA70FE3D75682066FE4DD1",
- "metadata_key_hmac": "174B80653DC7291F1824CF045B6EECEA5F66EF1FDE754FA3D42BEF0AE05CCC26"
- },
- {
- "key_seed": "EADCA313267A42211A53EC7EC955511AA3F444D68A3E4E57019ADFB7F10B94CB",
- "ldt_key": "D2461991FF65B9D300D378D6463D053CFEE4741F9D390249CC95382DED5EF5B26500BA102150750F6337D9E5EDF2D979B8BC0668C85AFF90DF7422512B6A81D6",
- "hmac_key": "59D8DFAE1D603565D17953FF0FD0BC2AB914564EEE42A223429B91C8313BA1A7",
- "adv_salt": "ACB2",
- "plaintext": "08EF1F46D78A71F319673E8B33E147DC",
- "ciphertext": "67390B3BB369F4B2E1997A2FB7D922EA",
- "metadata_key_hmac": "434B0A94E392E8606776968287F22ADD224A6DE23F3F8AB39874111777870EEB"
- },
- {
- "key_seed": "1A94D342C30CF5932A44139C85C581A8228B578AFB653F957BAE541DE577253D",
- "ldt_key": "8C5E585691A61F6C5E87ACD997CFC85ABF402D2C9A0266327B7BBED2EC75B324EEBE7BE2CD604BF9874EDF9B022088DD4717FA99B667D6E4160023F967AE3C07",
- "hmac_key": "07F3BDE3BBE5979FCAC7B96D93D596701454CCF21F569139AC613A74F9A4E2B8",
- "adv_salt": "3A6B",
- "plaintext": "8C83B122A29130586B7CE6E71EA61C2B7E2F274ED5A6B11B04B4B0",
- "ciphertext": "FDC37C036F089E4367E6447E69F24F3FB7D030E9CE0FFEC54F7F6E",
- "metadata_key_hmac": "494BD98D79B6A4B38BB78B2BF222AED6B7777786D39078934C17E63C5F9F2EDD"
- },
- {
- "key_seed": "81B65DE1BF1A9E9A601BC8F928ED4A315B9FAC0B0919EE1E8E3F01454658FFD6",
- "ldt_key": "0EE3259B8AF00CEBEF6D5891E1D5F658F90DEBAE478CF40C30DAE5199DEC7781CE445D3A59C9DC1DFEA5E19D5BEDB0E9A8BFC214BAF348E8C859B355CB2F2ECE",
- "hmac_key": "E956219F0B6C7DBC66F6E990D34F41030337F56A811DC39493EE2887DA7D697F",
- "adv_salt": "1892",
- "plaintext": "D62AF513F9018FD945DAE0B78C4145C38E",
- "ciphertext": "7D63B318D50A7DB01E3509E8911D4488BF",
- "metadata_key_hmac": "C9FFC2BE2805B4967860F7B219839125BC710AF1AFC971A08DD1721BDF5E0E87"
- },
- {
- "key_seed": "BE1097BA75EE5513684D071BBC909906C8791D6678926E7EE293742772A6E395",
- "ldt_key": "71DDF7824BA202935E11501FF5B3D33114B614FCC4649A18A9611F75E65E101D53AE13D6538200D77FC0477E157898B7A562BAE4DBC0E4693C6F3DD48D206EE7",
- "hmac_key": "E42071F1DE0ED1B358339C7DAD5697738973DC9BCF282FA5A182D3B86C1BC7F5",
- "adv_salt": "B3D0",
- "plaintext": "7749F4AFFA858AC1962C597E7323E5A495",
- "ciphertext": "799DD1320252E90B6A89DE5F83AA9F79B7",
- "metadata_key_hmac": "26CB000B6639FF02FE93A11DA57A2B2B98B67F450D46339BD9B21D693DEFEF5C"
- },
- {
- "key_seed": "5782D9EC66D31341A49021FA62B60D038CB04B653A1C1FC7F28A0ADB7CC89E39",
- "ldt_key": "D4FB828808CB8148FD1839E0274FBE3727A51C38FDADCF5C91D9F28EA0019A43E1A78E7BA1B4051A632A350A22A035668FF61EBB7D960D6426517954A556F940",
- "hmac_key": "A7020D0F20CCB3183355A37774B0983D28BF39409C4562EBC6D52056D2E170A8",
- "adv_salt": "2A1D",
- "plaintext": "2098F09B094B82F479402565141E670DA2CC6A06E2F06C910C",
- "ciphertext": "484856873B3465A14B86D158AA65F72E69F6403CB84232D34F",
- "metadata_key_hmac": "B5BDA9519DD3E98879D8B0627EA819913B6C4458E04CF3BB803A39559D73D55F"
- },
- {
- "key_seed": "FDC7CC332EB122DC5E3E2D2F8E45400636B4E7780FE7169004AA7E20C6B27130",
- "ldt_key": "7EE39F738F481B4FCB8DD720CBD46F9CB9F424B75C0C4C25B0394767C00A7D5DC4091F377828A5276C61FB5D2D25DD0873B4ACEC4428CDECA1EA8178C9E30023",
- "hmac_key": "8B27C2CA40A928E47B60CEE90E993CBD5E959FE471885A6C4717544F26276152",
- "adv_salt": "A815",
- "plaintext": "1EB3C2CE847B078594064E8A762558E428534448D3ACADB01C",
- "ciphertext": "E509A43D2204C464AFAD4B9A6616EB44C52E160B13E17689AF",
- "metadata_key_hmac": "0D25212C693FB0E67FE3AEFFC92E5328967F025A80DAC82BEA43A90BE46ED80F"
- },
- {
- "key_seed": "6A8660E01FB845F36CF850711077B4C826142E2A0169AB8321D6177FAC49315C",
- "ldt_key": "CC97042F35D91AB245E70FC2C6D5A5CCA40AC070EA7C8FCFDCEF1F9037C79B2B31D4EBD030F0C941AE7D29681A505340E8C8A7410A9A8546582A4BE7859657F0",
- "hmac_key": "A925E11A741C1EE11E49A604C5FF69EA7C4FAEAE9D0044F783B75872BA2D709D",
- "adv_salt": "4723",
- "plaintext": "B0675497FED81C60FC9E76654E13B03CFB",
- "ciphertext": "98278F68BF00BAF740642120B69AD28A5A",
- "metadata_key_hmac": "B623C6CF484872985B8DD0596020D88EF03FBD1DC7761C80648C66FCF40480AD"
- },
- {
- "key_seed": "B5C9178C083BAEDCAD97A7A4757B66C3DC64B03064D4F6686BE8C202DB1809AA",
- "ldt_key": "356145719EE39F953142FF07290DADA51C4B4F442BC6F5D67D086C16EC875D736AD5E2FF44ABB344D1F5B9F1254777AE5E86FB767F5441ED3A4F6262635E77E9",
- "hmac_key": "22A3AB00EE4741901558C6567F22A6A88FAF34FC7AC4C15EED7F6615DFC433AC",
- "adv_salt": "421F",
- "plaintext": "38A3F2DC36199F411EB565D12758DA9C51E38230",
- "ciphertext": "15247ACADE7CA745F6C37811B99870D418AEDEB8",
- "metadata_key_hmac": "CDD0ACC27C3DEABF89071CC2F2592C07E1009788B49EA7315208124250E4561C"
- },
- {
- "key_seed": "07DD86FAB6F73009F610F5F3FFE76BB8CA257AD8A5E9B8D27DC8CCBE948193AC",
- "ldt_key": "435CF9F5CF8075B2C227A9E95C35F747BD99A53594F96EF778DEB8BE8D988B901C4F98319EBD55DA91046E382FD5504F1373D504002AD943633896AC87A6ECB0",
- "hmac_key": "4EDC9928BA58B8287E0FEE3968310BACE74C344227A2D3AC4C3F33CED21B518F",
- "adv_salt": "4402",
- "plaintext": "BCB7CABAB0B4EB14638E60766A517E80CFFE1EAA9BCACBB1",
- "ciphertext": "36D2F9CB37FA4F45B373145A66DB0A4D3C89BB5BA39ACEB6",
- "metadata_key_hmac": "40222A55C432B13508AEB67112ED0945A8808CFCBD29A54BBCAF70DD9FB1DA1A"
- },
- {
- "key_seed": "B4D47064FC92CDBF3E0204AAFECA67DB2E1397189162B0693F59ABA9373287D3",
- "ldt_key": "7776476A2E73E102B3F8E78448C9663FB7D12692DAC2988F029ED52D904ACF2476A4B85781CCED68E8C444A8F402C496E2FCE6082243FCDA7425C642CEFA13EA",
- "hmac_key": "65F98BA0F2F2B46EC0ED7563B4955F9EA7142E810BF86F455FC86D1C1FEE492D",
- "adv_salt": "3C04",
- "plaintext": "63ACDEBCB100020E6BBE3E34E9B2A0F8EF862246E2",
- "ciphertext": "C5379E612483BDF2220AFCDE21250E167749B0F7D5",
- "metadata_key_hmac": "646B1C7EE957D187E4EC607E2BCCD9A6398241F8A7277677A3218F782AFB33F5"
- },
- {
- "key_seed": "B77F947E37384AD02CE4CB1A181288A1A80F3D3968E73449BBF3B9B2C27EDA58",
- "ldt_key": "621AD29E712745EF9821D30F29D1BD4E707200515F732E8ECD68A6BE6A0864E7E39A7586B78A679B82A87523AB0A02BEF3FE75275D4523CB269D591EF3AC36DC",
- "hmac_key": "B4989CCCD6DA89C58DFDAC6A6AF7428466E018C00AF396E62317B36EE7A6A63F",
- "adv_salt": "2223",
- "plaintext": "C571D5F394E9640B495A9BB26A938900F928CE45BE00C519F342B4DB3F18",
- "ciphertext": "DF5FE7389AE4D8A881AFEA097EBFCA7EBD81F8F507F308824102C316411C",
- "metadata_key_hmac": "CA1FAB06AA37630DE95595CEEDCE1D291F51C10C8DC1876DA29C701756882AE4"
- },
- {
- "key_seed": "F8D6F018EDF3CE25D03D13438A647E211277E1285D50F12F521FBF0AEF6C17C2",
- "ldt_key": "BEA6A0848AAA447CAE44D403B60F4A94C3731568A87626583DC43DF1A1241D8A39F42842D590FB142BF9A2508D5B767F184742A977D6B458F037F80F9CC8E4D5",
- "hmac_key": "D0E35F7B52D04FF1C8CA9F39E85FCA40DF6BAFD03268BA64FF12C51AA4C0BD11",
- "adv_salt": "CD19",
- "plaintext": "00985AD94B8D2C93EA3642494A5B0EF620BE",
- "ciphertext": "AF7A3074242E41A5735AC3E823576BD7F42E",
- "metadata_key_hmac": "E6D9B0ECD04A8D1C03DEF5F8AE5CDEF48B874D24DF5CC2937E2EFE0588ED367B"
- },
- {
- "key_seed": "A9C55D893A3A40A15929B967FED3BC52B2A38195D7340EBB10B99E1942782FA2",
- "ldt_key": "F8A20F71F22B6C1ADD9C5AC3524C618DD74EECE7B81BE0EB8D54F1962613C808252DE287825D49680208AFBC6D1D85B0E05B3602D58466158ED77DE09E6B2343",
- "hmac_key": "605B915D16AD2F783038C935003237AE59E9123F35B2BB13287BADCEBC18A289",
- "adv_salt": "934B",
- "plaintext": "95216F3A7043C18D63195513FCE1C7C1FDA6545200B6B5E2BAD1822476C5",
- "ciphertext": "FB4C08C4E8A1474185FD12274E5B04DF923C2E517035A54D74B5CD5D164F",
- "metadata_key_hmac": "0091FFC18E5BF1C1C22E212161955A2DC9BEFA4BE7DE3F0D10B3751F83E8E36B"
- },
- {
- "key_seed": "0FC8200E3516D1C17547ADD4496BA06202C7620EBCC06F8FEE5880130595D2AA",
- "ldt_key": "ACB2F0E90CD88B29993F162EA049077D24B15EE104F8252408BECA2B9CA6A83B9B9016FC763ACF5127EE6C4B0C477851A166338ADB8FDCB4DFCFFD56E6743782",
- "hmac_key": "FF74B5CD682C9C50E2CA77494394DDB74946141744A52CE6569EB61FE5F2D5C0",
- "adv_salt": "5FE3",
- "plaintext": "0662C83A21E9A604137ED3E4B476F1BFBF80712DA3F86A27647B",
- "ciphertext": "B78C902BE09389E33668773351AAFF1AF8065F4E08C10C5C5CFB",
- "metadata_key_hmac": "7F8FA03FD2E844C71B9D28AC291EA331DC1A25B242428D0F9C769CAC71FC4191"
- },
- {
- "key_seed": "FB04727819609193D77B0B6669BACB4538817C41F0D75C43E5E04EF2ABC307A7",
- "ldt_key": "D980A40193A2312B742441AA435A206CDD3381FB0BFDDFD5BC8F75F95AA0AE27563D43866908E1A1F7DA9B3CE4DC42EA0A93D167FF44995B0563925CAF798260",
- "hmac_key": "33B0446E8330D843500A02DA179C2624DD283C821405B812980B1BBC720AAE70",
- "adv_salt": "4428",
- "plaintext": "FE1BEAD3B9682E051481BD5C72B4D571A465DB78B96E",
- "ciphertext": "800C8077C465EAF7AC191D5C20978FA46B05B81F9127",
- "metadata_key_hmac": "7746FD13AA424EAA1F1CC6F05D195CEAE45872C3F822E8C1BB0487CF18E031CC"
- },
- {
- "key_seed": "3E6D4FF8DFD8FAC1AA76677789215EDC8FDFC88CF1143CA6DC1CA4D4A9E3F3A4",
- "ldt_key": "B881F04DDE3BBF8E24C721D5FE186565819AFF6C50DA26CEB117B15DA21949EC9F601C37C9DC51C6E92DEE3D31F46297764A3B6BD56A63B17E448E621F7EAD6B",
- "hmac_key": "3EEA351F7303E297DF360C4AC86DA755EE8724DB9D572A7516E8EB22561220CB",
- "adv_salt": "3EB4",
- "plaintext": "E54462C8E85DF7A358DDD7EF6134DF9779AED4",
- "ciphertext": "BE71CF06B610CCFFA653F533ACE83D8234C706",
- "metadata_key_hmac": "E3ED0DDFACA9D8A6945B83963C1EC4C49599BE0D5FA2079B34675AEBD21990FC"
- },
- {
- "key_seed": "E52D51F47DB88BA1E0A9585E119F45F7061C4ED01901DB63D1B068B77F2FA539",
- "ldt_key": "E81988DDDE4B0C3FC9A91E8A07FEFE43393FF0A74720E0FE06891ECB154E7F721D4221BD43E3AF18F6BD8645650B31FAF7E70BD7C52FF820202F57BA920C7044",
- "hmac_key": "C4ACDE87225B126700F0C9036DD2CDA1497655EE3DDB7F01EF411A51D22277D9",
- "adv_salt": "09A0",
- "plaintext": "09E63DBBDB48FF0D0B7D32A1268B200E6E1987",
- "ciphertext": "718657B2C4DAC9368253B5DE0126FFD5131C22",
- "metadata_key_hmac": "70576A2E080F91CAD7B4B3F9E45DB712F4523B2707DB196586BDF45946CE6B24"
- },
- {
- "key_seed": "B071FD22BE44144541BDEED68C9CBAEBE48B88FD6692F027F5AF1FCB15BB25EC",
- "ldt_key": "5676B0350FCBDA91930AC19BDAA988472218C1D9E1224FAFEB082C8E049CAEB4BDB11249C40DA4105FE12CD6B23C8DD666465CFC3DC350BE62A338F3658CA1F3",
- "hmac_key": "5F9A5EE4B1A55ECD54BBFA014DA8B054CFFFC1865E7B39E3359ABED7972616E4",
- "adv_salt": "E4BF",
- "plaintext": "1B9F88419F3C2CCFDFFF021113BAE89C7C232041D2AD85B96839E090",
- "ciphertext": "9926F08F0A1CF58A5F7C97E7F2D916ED9463B3E0F5DF46215A0AF4C3",
- "metadata_key_hmac": "751159135359FCC488029F43CB316B2FA26D0FDBED8ACCAA83EA2F4A8F8DB16D"
- },
- {
- "key_seed": "61AE93DBBABCBD1160D595F3692A078E6FFB8BE572DD11E19507CD7BA37EDA5F",
- "ldt_key": "768CE6268EA881104C3CDB24244DAD5CE28E1B96F78ACA154671AD68FC96C9990F353968506BC547A615C4A6464574C5EB52DB83429C5FDA56678E7B7A3D632C",
- "hmac_key": "E1E1B97C2CC8458D9812E692FAD651E125B08D281BF6EBBA94CD18A80924FCBC",
- "adv_salt": "6874",
- "plaintext": "BADD300ED46C1A6138E478AB27015381D26709694640CB649CE31C6D9CFACB",
- "ciphertext": "BEBAC204B309701E1BE26584C9CC920C5530FC92903E53E39DAF9A27049122",
- "metadata_key_hmac": "2E6B2BE8E00EB55E18D0E916CADD88B7EC4872EB487808096E7B82927E440C03"
- },
- {
- "key_seed": "828642B20291961F8938B4F80864C753CC18537BDC1EEF296D4743AC5FC042AB",
- "ldt_key": "D468DFD9CDF067F701C8818F4360ADAE108FF5C3937A2BA5BF1C6E23A61810C666E5366457D0857A66EB0A47DD9F644781F07CB07881E5E79779832FCB71C490",
- "hmac_key": "FE5F79F376BD8E8A38E774662F1C123BA9BF6FF210AE3D82F23741133ABF799E",
- "adv_salt": "D4FD",
- "plaintext": "A64B069FDDB299DFE6117B2B8E53550C576441C76A77BF6EE9F4AEFF",
- "ciphertext": "1550E8E7792D7918A1D2CFCD0A568EDFCA72B6581BE4B937A682800B",
- "metadata_key_hmac": "197295A9BB48590F804F2CBD75360B915FAEFDA7DFC2897C04846F35ED279B19"
- },
- {
- "key_seed": "64D4CF95291870854D9A64B132AF05EECE52527D2EBF7AA44E3F558990EA4B63",
- "ldt_key": "FAADF11DE2EE8B2428E8702E17CBD16118D153ED85BFD82EC0384DB687B86EAD71460E7617C7C74D7F87A4FAF4BEFF85EAE680D81480612932E28EB22EC2430B",
- "hmac_key": "B9335023F73FE5D226EC79BC61F766A6D2D2017D3102E62C9701EF659D31123A",
- "adv_salt": "2B55",
- "plaintext": "FE39093AFFE36BCF5A70E64B118385C2F23C5E24",
- "ciphertext": "3378DD86C535A6A57F46BA3337BA3FAA4143B40E",
- "metadata_key_hmac": "D54EA66B4B72E8B1DF134AC6DF84885732EC3E53D3B1897AC22387E90C6CF937"
- },
- {
- "key_seed": "29390F48881DAC83417F7E93BAA98F6208AA9BC843C4DF2770DD0A7717322524",
- "ldt_key": "C7B6C721BC055963A631676239AAE3DC4B56355D93A79EF20DBBE08F2DB23632CEEAE5B3AB86663221773D2F9CC2652E7633B27D94680585DFE588A8BF0CDB22",
- "hmac_key": "BD74E00EFD9CE8DBE2AF8C33108BB6E83538BC93E87889B46173D3DD66FF19A2",
- "adv_salt": "166D",
- "plaintext": "F165CFCD52972DA6EE83086FA4C2573A8EE36905A6C6F5",
- "ciphertext": "7A23C2430565E17ACA32F8506E67E6619D4F2B5BC546D9",
- "metadata_key_hmac": "B7CE26107122B7EC595FB52B8E54A9261A05E4BF676D15A7F4464E8F8867D255"
- },
- {
- "key_seed": "817E52C029A497D13CE38EFE8521AC3AEDDEBF825300E35861001595FEE5E728",
- "ldt_key": "47808ACA04AC4AF0DA650DE8B7D345F0B5CA8D779552ACCECE1BE594DD28A11BBD2EDAF4CD17A3D311DDBF4AA30040C576793A78EA4CC0CE2C5169FA48414464",
- "hmac_key": "7D2593072EC564982C10773DE9617FA320380B0F35380E330E00236E83205AB2",
- "adv_salt": "B16E",
- "plaintext": "979F741F6384DBD02E30EB848AF58CAC0E825E6ED5BE670E08625B049D6A",
- "ciphertext": "6550B23E88ECC6734F22A602592FD6ADEF21D52D40C125E39615D2285AD5",
- "metadata_key_hmac": "27A60C66C3B48C98AA7C2A77C7F4D5CB249D0D690A4FEF0E674D709A64B9A3E4"
- },
- {
- "key_seed": "9CBB82D9821CEA8BCF66833F7E187D3BD7630956FE85AD1D54326B50DBA51F5F",
- "ldt_key": "C476A6B0C6D7465F848684657595E88EC794B6C5B19966C8BE00F623D72923B876FFE39B3C798016F5C5B3D6CF90B5F828FABDC78DA7677948A9CD3152CD0DBD",
- "hmac_key": "D842D04C078DFDA7103E682CC220AF4A52218EF20E225A20E4610C53241B2730",
- "adv_salt": "B6C3",
- "plaintext": "B69874B965C6181E34A12E9FDCFC15A44867B570759878A1EF27",
- "ciphertext": "F144E75EFF80AD96863BF5A0C478D04425347A6DB670A6B1C2D7",
- "metadata_key_hmac": "7CA78DCB2E193F1F9B0E104A04D8FAD188CE31A5E6EC52BF274A9F38A01D72C5"
- },
- {
- "key_seed": "59B092A37A79B0D1A427020B5751AEFBB19122ABB2DC451B54575012CC18E781",
- "ldt_key": "4737ABD41647EFC55B97BE5C0E992D6C3D0D9A0444F09B816F70C599197C7A07E6DF7AB0AB790F250D2EB1B626B6E522A83BFAB38E96ADE6582CA90E556F7853",
- "hmac_key": "CFA5F64B00040C786FFFABE5B634881A7E6D9957C1097F99522EEC4FF3B71186",
- "adv_salt": "9F65",
- "plaintext": "41C098BB1D6420043908C638126CD7135F",
- "ciphertext": "A8DA29B3072AE8C85640C7CD51FD6D5928",
- "metadata_key_hmac": "5F4A8B2F5DBBEC14CA0AF02F9D0C0B1BE967F4A8071F5F14C18131BC0AB3C583"
- },
- {
- "key_seed": "22AC202ED8FE097C8825CA079D0DC58A648825FB9250E6D52DAED4CFC015937D",
- "ldt_key": "28BAFE4E9174E7BB5056F9AD78308AD4745E49FD3C3CBE89AA670AB31A32A69E443E1AFBB9E497C2344990EA811C68FB62E34E176966B092C0707A5BA353FE89",
- "hmac_key": "9A13EC5450F600BDDE1354E11FB54B65236243EEB2D012F2E3E21B909A8725E2",
- "adv_salt": "5BFB",
- "plaintext": "CFEA46F97492EBA0BC9C41F90B8A36F05EE5376D1BC5121B3146918A",
- "ciphertext": "AC5659B294F628673E36B39BCE2A0FDBC7F28FBA2816774D58258A77",
- "metadata_key_hmac": "E011B8F87946924EFE20FE9CADFD807709E67CF333742489E666901045A7E294"
- },
- {
- "key_seed": "0587DDFE9A3C16BBF2B7F3BB29D4972A07FB1AE18387C20B4BC9C256372D97F1",
- "ldt_key": "84DB60AD6EE51CBFEBFBFFE655A02C03810758DA394F892DA0817001021B2A9AD332C47DA62D617C23781D5BFFA21095F4F5D7BBF18ACF4CE96B4B51B90AD0D6",
- "hmac_key": "5C39C26C51B027C5EB7921D4180CFA58B0BB65089712BE04F8C331149028C75E",
- "adv_salt": "F5EB",
- "plaintext": "4F5EE0490F73748A075556B53CD3CAC423D9E8B6557954F4974258",
- "ciphertext": "8DFD658BB8D7EDF55651487E699760DBB7E0EA26E333AED7B915ED",
- "metadata_key_hmac": "D7BE988EA13261746215EEE6A9A4328C04DBDD23FE1BAFB6CBCAD89DC5E31C0D"
- },
- {
- "key_seed": "353356FBC0A7D3072B95CD06EF161B2E2671A5605ED895204822299DADA077BF",
- "ldt_key": "3E93C47CBD43759FE750931CF658E2DD3FE6DF1BA927FA1C1A66D6E96BAF30BE6D4CDF5E1EB41CD797DC514B11379C4D6AD71A2B8E98494B94FEB3810B277908",
- "hmac_key": "AD8FA4913963644D7C8F94C8A81CDFEE117F162BF34763F6B689848BBB8DD6E6",
- "adv_salt": "6BA1",
- "plaintext": "EE4D1B30A0DDB5ED135BB94E5DB5AF6A",
- "ciphertext": "484731A93C8B923BB8A53DCA79E4F045",
- "metadata_key_hmac": "DC75417B873E665D06E0C1A597BCCF9EBD945FA77918710C9C02AAFABA57FF4A"
- },
- {
- "key_seed": "7FEDDBABBCA5FBF19085EFDF7FA449069C85BAC7F42CAECB8835EA6001064B2B",
- "ldt_key": "B74C33B6186D08E721B87B613E0C918CD42DC3D2462EDA5ACC6EE1BA393DA2CA381C696575E6075AACF233544A05AC4D8A344D62AE29FE5699B909D1474AB1E8",
- "hmac_key": "4410A7C075922CE821A7E32EB73F2594BECE696507EC3B31DE9A784685A41548",
- "adv_salt": "CC8B",
- "plaintext": "B90E090048412D9AD15738C13B42DB98E431A752278750",
- "ciphertext": "4E3757534A4F9CF015564178C2C757A37D78B1299E8C3D",
- "metadata_key_hmac": "4A09CE5BC6926AC6058095E3D8CF9E027CF3D34B50632BC22BFDFA291DEA5F22"
- },
- {
- "key_seed": "7367DC37CC19142159373804965C43E9CA28AE843DBF542F2273EC8352CD4090",
- "ldt_key": "3DE9CE878554D735593D98BFC7E6AA0CF8077AE0C79BF9D4D218D07595F3A3FEC332FE9100F95D7543DAF0DC9B48F931FA698ED2AC3D5D16D15F78CBC9BC61D6",
- "hmac_key": "A23D66ABFD8EABE9660635249025DAD4D76E7D3B9EE76B6E03FE7383B8B2FE47",
- "adv_salt": "CCF7",
- "plaintext": "604310E1BA7E0921F0741CE25A0B3BC630822BEF8FA95D282A2B49",
- "ciphertext": "94877AE1D36AB555C94B0DE4C12E6D07DC576302F5A4605C90F150",
- "metadata_key_hmac": "1C0B94FE2B78CDDE0CFCD5C52FAC37288CC8F31D6502F0F0A8CC9B46136FB618"
- },
- {
- "key_seed": "82D6B3CC208096CDA562F2A197EB0AF48526AA537FE696E7A5906FEB6A9D9BAE",
- "ldt_key": "D76C5731D20F46709B4623DA5176A18362D4FBF31D0050209ACA5EC226495065734A1E5E4CB7279B9164736A68758154569AF342361BE36472B91BCD6357F636",
- "hmac_key": "5B358CB9094F9A3AACC942A6ACD8B429ECB9CA9806245A53F20FD90C1DD7AF86",
- "adv_salt": "ECB9",
- "plaintext": "B614CCF667685C509C1E6F6007CE910ED3F4C10489B78981",
- "ciphertext": "4087ED2E3DAA9CA529578A8D9BF7B82801B6C2F9993F9E01",
- "metadata_key_hmac": "D3F2E705C732A1A40F561AE5CA652CE90FFD57F096BD0DD8693DE60E430A3850"
- },
- {
- "key_seed": "C4AAF69D55BCC6809BA8047E46AE2951F9F9D1C2DA4D2EDB4497EE422449656B",
- "ldt_key": "0DBE3FED8D595946E396085D37627D1DF502C62837C19E0C637378D7B113FE973039301AEDD1ADB5826454759C253194ECAE2F51AF658E24FF53B6DC0CAEBE8C",
- "hmac_key": "1BA4C65445037AE9BA3E0B4DF02DC7284444724F01F046D1D27B55A373A26689",
- "adv_salt": "BC66",
- "plaintext": "02C2762DCD029C77B3680528879E928F2F",
- "ciphertext": "421D0B4D61BA0E851D8C988ADDC1F7106F",
- "metadata_key_hmac": "D41AC03BD3757F5722EA9178CB4A5F159987FDF4C8ECCA81019AF42430215704"
- },
- {
- "key_seed": "EF6E76A452714F136B4BCA5E451532130AC5D54BE0F3E92BA400E822B5D5F663",
- "ldt_key": "DC186901F3A8C80EACAF342B9738322B2DA0DAC2A9D120FBE5A5EA23B3CDA8DC84B169BF555A1FF97DF8401102A5A158B09A1C6D69736481D5F346749C64ABFF",
- "hmac_key": "5BBB6C5A93CA93063E386F8DD215568F2F0D9F0204FE379C1640463330B4772F",
- "adv_salt": "5AD2",
- "plaintext": "1A4A986327D60F6DEA79523C538B8EB65ED0B98C88F213",
- "ciphertext": "D7A1014E0F028131D1B68915AFFD4D32654B3F58E6B4A9",
- "metadata_key_hmac": "994181ECDCFEA4919BEE1A1653F5A28B0B5EB6A08428999608C8F8CDCF273AD1"
- },
- {
- "key_seed": "1FD6A210A15F7BB8F621BB455209783C7C3F97ED76091B5B73128A3DA89721D0",
- "ldt_key": "B71CD649F8E878F541E26DFC7E9D2A268ADD1840CCBCF18D0D6D490C3C8DA1F1D8D757CE85AF2329A0FF6F00857637950A8D6CB150185DFACC6E7947AAF40565",
- "hmac_key": "20066BCBA3ED8B17A8196406F9CA0321FF4E36D5869CEF40D5162641AD680D43",
- "adv_salt": "B019",
- "plaintext": "FC3A04D7DBE4298E89F2C55B9152C354DF3EFAB17D",
- "ciphertext": "CAE8DBBD312ED58B62F3B0B5F2C3766C979B73F5AD",
- "metadata_key_hmac": "5BEFB5B32828A6040761FED70437A20666E73E438CC6DBD2E2260EA08C40FA82"
- },
- {
- "key_seed": "40796B04A81037C8DF0A7EECFF2A564D86918948AEF73824039E0502DFF24B9F",
- "ldt_key": "D45D2B372108DA4BAFD1DB4AFA1E2A072D265A132AF2FAB10BB5DEF4923195299B21513BAAE0787AEF897DC6C4E3DC834E8B5B36650AF054724343B4A212D905",
- "hmac_key": "02328122714079A49DD34A85287A93A70700DAECD16CC2EC334B35F92939FDA7",
- "adv_salt": "1C7E",
- "plaintext": "A7AC225B57D56BC713194CADE4C14DEC",
- "ciphertext": "A09BC1E6E33B6D94DA83DC15609EF00F",
- "metadata_key_hmac": "D8FBB71457FA8BB077DE75736BE088389F6937EEDEC83FDB915DE02AB6B73B1D"
- },
- {
- "key_seed": "9266A6AF4A9BAC16EDE23A0991ABCF1BCBFD207B0C75EDCDC17026AE870E5AD7",
- "ldt_key": "202D04E5717E093F366325B2D53C7099A21780208C164819B53A7408688F6DE1FA0FA9911A30CDD9C8DA9FD0D250D66D501AB085671FD3CEB49ACECC4F3FC574",
- "hmac_key": "63C4A734233194AD20BA4B709A866B53FD8385A1109B1874B47C55D8A199026E",
- "adv_salt": "B230",
- "plaintext": "CA1EDF7C35B80DEADAA7F1FEF5D1E8B80B62912732",
- "ciphertext": "E3E5FE59F681508AE5E89D4B4CFC0E1E2A76E864D7",
- "metadata_key_hmac": "42D6811C114796FA032AD60EF690A55243BDC9F47BC033969C99A713CC8D6F6B"
- },
- {
- "key_seed": "E9D71D9263432A4979FB8A909EC1EEDF8C5263BFAD9D0AB708CABACCE4BEF1A6",
- "ldt_key": "D41DF680DB01DBEA500644D4EDAA1BFB2FD9C1E5F09CFC50B0669F9290EDAA7234AED1D2832E6A243DB22346829DB191B1E0B106573708E77ABED4EB2B937CF8",
- "hmac_key": "9D067E24A5FFA79EB0651264DFBD2C16DF96139DEE2F4182DD93BEA3B43478AB",
- "adv_salt": "17A7",
- "plaintext": "D6418E0E2C7687F5F4AA42CA2A0702153B9F642494",
- "ciphertext": "14486CE8E4401C765E9404A76A362C76E8D91AB48D",
- "metadata_key_hmac": "93CBA7F6D5C459FF4263AC2E64ED865836A8897C11F20A09F748F39320A78ACC"
- },
- {
- "key_seed": "182A610DB1B47A0E4FFA62DD17BFB4EDFD12C746B400404E3B08DC381970049A",
- "ldt_key": "8A78B7701B7A0D700133A7DBFC5F887CCAD49BCAB67C896E32202C7DBE775215C6099EE9B0866DED3FA587937FA94F95B35EC100B42F749B8C7768264B00C586",
- "hmac_key": "8C073133C495EBCFDE4A2F112531D9370DC1B29CBA2CDEC96ECDB9C3F90D4965",
- "adv_salt": "E2A1",
- "plaintext": "A27CEADE8B0B5F62644EC0D70DDCA0C826FEED598510F8",
- "ciphertext": "3041284AF4D331E864DA9C517D4FFC04290281F736FFC4",
- "metadata_key_hmac": "243CFC7A484FFB6862B69538B2CBCB1E90EDE91E594D8C25D9ED548B31D9F549"
- },
- {
- "key_seed": "023B2309325EA8A81184CD8B43D24D43C24B09BC7C7736284849E688FB93AD40",
- "ldt_key": "2B6EE387E86FBBB54E3F1AE88C0CD531806C7348E50551F90E857B5180E773027EB995378DB02C0F36F3F03B0F861E68D6B04793BAFD3C8477F9AFFB05701D4D",
- "hmac_key": "1B91A69467B552C5F7504B2DCD0788F29AB7F7FE6112D96B529E5603C1F0A65D",
- "adv_salt": "8302",
- "plaintext": "168ABCFA4543F826FD99B738E0DF53F6100301E4FDE4760F37",
- "ciphertext": "DBB976C88768AFCFF70E249EEC7D3F804EB57101C2CD0CB355",
- "metadata_key_hmac": "243054355CC2D631349C6CF5451BAB3D03639A6DA36B26CA8682932DF5BE6F1B"
- },
- {
- "key_seed": "C2608A5ACB87C16BFAF8F2AE92088076B65AA5987EC3637592B8839F38C9DDCC",
- "ldt_key": "056EBDCD4E682DE1FA9C43BDA3F8D715D0B1ACE4295C2AF455745647420618416FC7FB0C7D86C55AA395740829080A91A45FD9EC82061F61C8D810C31638F300",
- "hmac_key": "6FB4476757DBFFACF34854BD57FC6414D459951B6B56D15644806DA8DC0FEA3F",
- "adv_salt": "D93E",
- "plaintext": "A17DAE592FBB6C3DF1BAF7D14668F1EBB6DA919F67696E45B1C73F553BF4",
- "ciphertext": "75C758D0640454385A60888556A185012B5923817D0524B5800EE15642E2",
- "metadata_key_hmac": "56203005CC1F8542A56AB79D6C4DA6AE7C666D16331EB05D2CF1DF6DCF3899BB"
- },
- {
- "key_seed": "EC99415836A71CD018FE253D06936A592CCD14FEE0ACC78057CF245CBD9BF69A",
- "ldt_key": "29486562867DFAA482CFE845052DD28B3034B0522CCC6A0883B286EC41F52C6388FE7EF143962A8630604D0E4164566E920ADFC2AD950B281F9277FC592E99E5",
- "hmac_key": "9BA951CBADA3DFBC74EEA42E622C6CCC862A64C71B3825B7CE266D87213668D2",
- "adv_salt": "6365",
- "plaintext": "9823CFB0C109E44CC231D89A8EBF12B6FF6A03D579",
- "ciphertext": "A81B2F8688C563E0F918CE57BE04BAB25CBE6E3B08",
- "metadata_key_hmac": "C98A745B649061123E20AD2DA609683FC9BC67AD694CDF8856C23D22DE6C6373"
- },
- {
- "key_seed": "4A8000E1FF9A8DFDB1EF0A04D6E9523912E0E5A0FD90F4B8ACE2712B4D693944",
- "ldt_key": "B19BEFF07C483C25B386EAB6C22C75AABEC196B16171D0ABC561610F2B9030F6F446236437D1E4F8E398A4DD1F08F01EB58A229AAAFC0D11F1F6FE5197BCEEC3",
- "hmac_key": "C74FDA2826E06259EB44F16479DFBDDBE5294AB6C8208CC0EEA1F6AC889F105C",
- "adv_salt": "8E59",
- "plaintext": "B15F269256F5D40F8E2ED220AD6B8DFBCBCA7946A313C7B15FCB250FFA7B",
- "ciphertext": "A520E9096C35B5AF65EA0288E4D9B5E0DC59E790D94CFBF3B88BAD4AE108",
- "metadata_key_hmac": "9C25CF530ADB0054D44F4BD955050746CB7E937F3CD3104AAC530152973002D3"
- },
- {
- "key_seed": "3DC8E89B729D04C912D224CFAEE6BA147FF4EB46665F2F68262DC42665BB6546",
- "ldt_key": "5CB7DD6AB6443B38370CCB3FC5A618377A9917F725FF8C9B76239CA9C6E376054BE402BBDCEF6BB83F3DA8ED51F606D89C7DF6DA85E954D949689738E052B0DF",
- "hmac_key": "3581EB8A202E79901AF0BCAE667AF7170F027927BA27668427EFC2C6024117EC",
- "adv_salt": "D335",
- "plaintext": "D4CA99804BC9A910004201C8B7590B95038C17",
- "ciphertext": "BA09BD3FC063C81E3F72277458A7618EE900D1",
- "metadata_key_hmac": "AB1ED3B3518AFC23B788549F5BC0B1FD6A201E97E278F817EA329A6BAB0309CC"
- },
- {
- "key_seed": "0006CF5225E174EF822A30AB0529B69C108475DDBAA1AF43A44BF51C5D5DFA8B",
- "ldt_key": "D92833285EC8FDDD39EA543E270852CF1DFEF74AD515E031D043167404A9A5C5C76210183496CE26B57AA958F5212C04CF316C5B124BA2CEE19FDCFB3A4E6F65",
- "hmac_key": "CD5956A898365B6414ACB0D638EBDA608CD04FA59FDDC3A7CEAB493D43EE303E",
- "adv_salt": "21F9",
- "plaintext": "D8CA79DB9522E28903F1776A9671084425A33435318796B61720A5",
- "ciphertext": "9F3CBAE4EB6F96B2EAB8435D9DDBEAB355EFF423AD14E928D55EDD",
- "metadata_key_hmac": "4CB0388CE318A093938482D9708182DE20CDB1F501B9343C8FE24B2C2ABDBB0F"
- },
- {
- "key_seed": "A35C0F85F77FE542D4DA5BAAA7E4C192E43F2B4769C9CF77C3BFE43610C31A89",
- "ldt_key": "820DACB1C131D804BB7EB5F88F9C4424F6DDC2BEC47822DB14444AD7D9456264028FF618932076C1B127B221DE4BD85509F5B16C66AC070C113E94CB0C810C56",
- "hmac_key": "94A5415308D1A6CF92901CC7169A16DF66C35DC04E79728F13EF8DD60AAAA97A",
- "adv_salt": "75C0",
- "plaintext": "97C8F490FFD81E751E58D14EE57320F87441CDBE7AE1E7F704",
- "ciphertext": "778047CF7A20B43156AFDF2F6DB68A9354483CAB803E263473",
- "metadata_key_hmac": "5F28CBB5A8CAF83F3C859C430162F1007E9E122FF3FDCBE1A5E9C7D7345E68AF"
- },
- {
- "key_seed": "648D28EC0F235C056E19C50560E20C1C9153F1B1FD575ECBE61EC63C02946D48",
- "ldt_key": "9F97C570D9EF9654996F39C42004E87A0DC1AB778FB80A6464018F809BA3C22CBB31C718F60CF337B4F3EF00A225E7F79266030EAB256718287A1375839420A1",
- "hmac_key": "77D747DED1BDAE060B54AB5C14B2C505FBC1628ECDBC8A5403041EAB31B8CA35",
- "adv_salt": "C47E",
- "plaintext": "FB7AA8BFDEB67973132225B6628E590F06507F3224",
- "ciphertext": "82C3DB57DDC5A82132950666E76FAFDE78915C525D",
- "metadata_key_hmac": "76F3737220512662CBC506645D6353FCF625CB28D7F4749FEA2DAC66AFDBB4B6"
- },
- {
- "key_seed": "AB266006BA27C9B8BDBC348E2F233458A47E1D081E2D8A7F75E1266BC3194A71",
- "ldt_key": "FF0C1D83127BD01BDCA768A290EE460AF5AB7194713A8416C8F2B71654018174336F6947B3B65278D99B1A84F1FCF52EDCF69D54778F143EEF8039488D1E5444",
- "hmac_key": "F0EBA62332D70ED32904E006ECD15023C74A2B31C6DD97FD71FAB9864B1254D1",
- "adv_salt": "C6BA",
- "plaintext": "C3D3FCEA6BB15407718A79DDB6E250C3AB1E29874C9666C9B9",
- "ciphertext": "2ABA6882B6E4C2DC04DDA8837AE7526E4AC32182F245C5EF31",
- "metadata_key_hmac": "0856FCC0CF22234B88CF87A3B28F9637B3F3021D6832ACE0831551201E12A18C"
- },
- {
- "key_seed": "39422A1CB95CF979E27D915BEC424576212CFCB22478ED1DF6748D61001AC677",
- "ldt_key": "04CA78ADF1E2A09A1C4DB8B3DABB5614DF1171A1908D1572AF42BAF252DC01DB76075F21F9DF2B2B1CC217980EEE430A5D2B699C34473D9B1BBCFFD21187F673",
- "hmac_key": "24416CCC591932474B8CE26593952FC0B39842DA2C2D4496A24C7C18CBA078CA",
- "adv_salt": "BEFE",
- "plaintext": "992519171843560D593A00650010B419",
- "ciphertext": "9289780CBCAD21A63B1331F4211B6CFD",
- "metadata_key_hmac": "9C3383C57A759CFCEE5FDE6CE412ECDBB2F4B991EADCA608EE3D428B37D7A61D"
- },
- {
- "key_seed": "AEDC72F40D1713CFEFC695094277BF4F09CD3700266DD5044B9AD4A30A4A7075",
- "ldt_key": "B95B709E61493E41793C2BFB7352DFA905418AD306EA8D9EDE3CC7E0D751D91F430CF8821F8FFD291275CCF9ED309F914B74204608495CC9A011DFB04011846B",
- "hmac_key": "7948CE0D76CA3A9885F14C3350111853030D260482D0A17EE9F5CF950E3FA7D0",
- "adv_salt": "93E9",
- "plaintext": "2CCF403EFC2BBF63CE6713CED63E5C722658B211",
- "ciphertext": "DA024ACF0DBF96DD958A2B899556F7ED522807AF",
- "metadata_key_hmac": "172D657C3C093D1171968D917EE56A9F18709C21E04B4864B5933BD231E1B24B"
- },
- {
- "key_seed": "55F79B5A7A22E805336CC8F2910BB291FEAD07A7B85D88CF1101E652B889A578",
- "ldt_key": "CA54FA3548DBCEF6807EFA9804CA53B382EA05CDBB7334846810481FE9F327639CD561844165EF1047DEA7E9AB90C7F92F4ABBE01091DEADF71B02B443868CF3",
- "hmac_key": "44691723E9B6B50F4E5D05F8214864E7AFD29E9CDC8A29B593FB38D1146D86A9",
- "adv_salt": "731C",
- "plaintext": "7AB0D04C39CD376574505C3CDACE42FBAC93D00D9E63E918AE",
- "ciphertext": "A1F451AE86A971B40C3EBBB301E1EC142B2B116C1BB5A7B4D9",
- "metadata_key_hmac": "8DE18D0F719077ED04E28F8C83B6AC7116CD9FDC76AEC4B127092A17B25F7A35"
- },
- {
- "key_seed": "E0E8F2C704B79101C4AE1AA6EA66DDFE3595442C77FAB77B08B5702796B8C80E",
- "ldt_key": "4C3AB6C363C96574DE798F9297CAD532E2E4708ADE76D74465E09322FC9FC3A6817AC940A10ED4D0CF14E9D3435932AFDB7ED0526AE0BEBF47C81456CA9A6CD8",
- "hmac_key": "C54A736A79A344E66E7B83F95FE44F858E7AC2C2E2AF79F9C346CE0E481E0AD6",
- "adv_salt": "82AE",
- "plaintext": "A9184787EEE39C0D471DE8EEEA9E1E7BDA0DDB37",
- "ciphertext": "97F5675D53AF0BFAC6A58F6114C9DDFCE3DB0608",
- "metadata_key_hmac": "1B6ADF08B7DF306C346A74AA74390BAE8DD23BC224EADFAC50B35182949D305A"
- },
- {
- "key_seed": "3E045EC0E569AB8656C45B59F512E5B03DAD427D750F98DC6C4C4509B339A959",
- "ldt_key": "6A5466A4C6A174D8B35DF32C2A08BDE5D4C5C9B1E779BD803FCE50FE190D82C327B50481B4E62D2C3902BEE106C6EE1946EA32B022B6B6557823270BC6AFBF38",
- "hmac_key": "0FB3C7F3100261DA4420D5EC5B94C3855C82A7371D8A8F75C7E921CBA1154D81",
- "adv_salt": "121A",
- "plaintext": "40DB07B6329E6EFC10B79A004C8C544666FA13A81C96B37343",
- "ciphertext": "CF082BA8DC959FED33D304CB5EC66B028329BFB3B2CA53184A",
- "metadata_key_hmac": "E469FA33B76547861B26F80FB68FE60251E904F5997686A42C2ABE6E45AC6A7A"
- },
- {
- "key_seed": "807DC7E3EBEF3B2797636D316401D339909EC63C23F9AF142BE19D7A5D4E9B31",
- "ldt_key": "07709D1ADC769DA662876C45C89477D941B9C706CB11CB1FFB789BB3FA9410398321DC404CDE4CCE10801570CF3D83C2E88D5E8E12E5694CEFBAF6D67E9AAFAB",
- "hmac_key": "23C7EB3B019361D502337C2035C571ABF7BCFF36EC2FA0B1B14CE816A6874E3E",
- "adv_salt": "9E75",
- "plaintext": "FAD1DE90363C6C1413EA1B1461CCC43F",
- "ciphertext": "28EF13E59A2DAD573B0A1B0B927DF629",
- "metadata_key_hmac": "8475DBA0DD7E6FFD7A1D9D0214B4A8EC4004BD7770422F37E68B2044569E1AD3"
- },
- {
- "key_seed": "A62BE1A3BBDB99C67A9E0B9CCBDE92D581BB491A9332DFDE3A83D4DC8C821596",
- "ldt_key": "9BEEF268C80A80BBD8B5151CB8BC6DBAC22E543BF65293E49864461AF501C9DBC56B84F3DC3495409D6D2D0F84329DB2A4A3F95F2902F46DCBC4D77FDCAB022B",
- "hmac_key": "BE69A6D4391A1B7647D2A261F6FD19C807C03D7E873DC18ECA6BF7D7571A3881",
- "adv_salt": "DA0B",
- "plaintext": "C1F1DC66329A41743732DA0B5EC6C87771168427E60B",
- "ciphertext": "65D9A77973EC29D6B3BC3E4A84E388DBEC013A63B8A3",
- "metadata_key_hmac": "047094B27579869C1D81EA857627622B2AC6751E4E4F708FFBDAA844E34231C3"
- },
- {
- "key_seed": "8225BC81B6A95E41A5FA6BE7BCDC4013C15B9F3E673EA91C99E4B8F9F9641F18",
- "ldt_key": "88FCB6677A3C2565C40AB907496A5BD8DCB60195D4D5947826EFBA2E4407A2FAAB56E6ECB710ED440721BDA2E8CEA571AE28DFDF2D8AD0A0971BC21A853F948A",
- "hmac_key": "F54EFD7864BF2FB87EDAAC78B187A9717AA7CE43BD0BDF0D6D83315D7D3CBD96",
- "adv_salt": "86C0",
- "plaintext": "8101E73DE0C94BA78E37CD8EA9CC6D0B3E52221166F1F3",
- "ciphertext": "E5EC5C5A5BE3ACF76751F6E5C45910A3FBBF0A1039A8C3",
- "metadata_key_hmac": "FD9FD785E938AC6719CCEA7AA30AB6B0AD34976AD53E902CDC9362F9DF978E9D"
- },
- {
- "key_seed": "AE4BE66731EEC0ED59CC7F8E6A616D991326AAD5461806D9D8DDCC673FB1E74E",
- "ldt_key": "7BBB3F3BB47613EAED7AF01630013423FB8FA2F0BCE3266D4C1C3358230B99FB5CC8C09D6CFDC712EEC9A3F8F2FF2915B0383B8CD2C21348C626F057F4F315AA",
- "hmac_key": "8D6B94B9BD6DFE59C525F196ACEA419344A02954B274C0E4CEE516E5123B1E46",
- "adv_salt": "C968",
- "plaintext": "6BE1C9FD4B45E62BF3F3CBCF5A281ED900B1EF002755F201CF524F",
- "ciphertext": "3CF6133D11238E9139329337EEED7E9C529A6D46C3506F7384295A",
- "metadata_key_hmac": "73EDA04796A798B1D0A401560F8F569F1D8FCFAB1D1E4AADC404C02108D5C9FC"
- },
- {
- "key_seed": "60763945AEC69521699FB1393024D7A4CA97FA63AAAC48B5507158909822B49C",
- "ldt_key": "4624393C688256207C58D4EDF09234DD60754A7C11C5B6443BCA04CCA8194B7F28C02BB1A03CB0D51B8D57F53EA8A2DE2E2117C89E52B4B550EFE82437D32054",
- "hmac_key": "7CF03F2124D4062F65D1F413E9A02CF91FD1AC9F4CEBFC2BCCE079EB3EBC902A",
- "adv_salt": "78E7",
- "plaintext": "0B9DC49C436D188F5E02A2F7EF72AA9E057197FBAAD81156DE40",
- "ciphertext": "71C56A1CA97DEB8438D2BE29BA27C9D5AAB05810670EDF9B8FA3",
- "metadata_key_hmac": "4DDEFEE27C077AED36492E7E9B490F81BBF921851BDD50E906F5E50E3538BBFB"
- },
- {
- "key_seed": "ACB1D851F960017B5DCD5D2AEE38CE6221D22A2070592A7E1F2D56125DDEBE4D",
- "ldt_key": "00B3A0B7A6017A6D4711257AEFD809A61A497F56D9BE053412589B284B3F8780E55D6ED711A10B6AF63CCEB8C493D59128460894B91CC07EAED4388EEDB90E4E",
- "hmac_key": "F61FEA59CBE3E50C7570918B91C0C79C83D6D8B49F4C722A1A2DAAB7FEF93B22",
- "adv_salt": "DB05",
- "plaintext": "FBF9190FD2C1C63ED84BE2BDD4DA1878DCC922BCDC78478E25947344E58E",
- "ciphertext": "BFFE6DE27A2648CCE6635A8DA00A559D7451F44BC1F92F10F3B55293189A",
- "metadata_key_hmac": "708591407C24D5E37ACFB67A85E216D889FC6328A8371EDE4A48D6ACE2D38AA0"
- },
- {
- "key_seed": "5892D24DE35450EFBDE91AB2B899337DC0FEB3E4E08F12AEFC21290C3BB0F5D1",
- "ldt_key": "16B5A4776C7EB3FB15C122FF3C441B1216E8D81863D8DC22FFCB1606E9CB90FFB01205BCEFB026ABB6637DFE593AFA3B4DE8E5F67D7FCE8F7845C50EA73FCA10",
- "hmac_key": "6B87C3F28E0B837A3642D3EA89A5AC66B6406FC6061B2A1230A6957E573F62BC",
- "adv_salt": "7E5F",
- "plaintext": "C70CFC105673CC008117C84C3B0B8B6B",
- "ciphertext": "E7143E3EB9B085FE6CD8830C1AA85825",
- "metadata_key_hmac": "03119A6B609DCC4A1A0671558F26408776CEF78962E84E0C264BDF71EF8A4C45"
- },
- {
- "key_seed": "FCB53B88C29480D31C61C9A26C1FDBFB90F0C1E482EAF41CDCFC46C106D7FA92",
- "ldt_key": "90740E785F31C6FD23F30EEF5A1BFB0DE75A1EE6D88CAD8FF84154132B6E41659F1CE14B28FBD09B671D2A2F789D33B94F3DE2C945A032EF8FD47A52B53A50C5",
- "hmac_key": "F66E97715C702A60245C1E091082BCA6424B309C34D0A0267FCF41B2DDE10EAC",
- "adv_salt": "F66B",
- "plaintext": "024FADB6EA3D3841BADDA0030BAE72906B5E8E9A8B830CBC",
- "ciphertext": "71A33F0C9E407FF1C68E25CA56F4D37B34EF1CF9DA2A05D7",
- "metadata_key_hmac": "BE3C7A90CC50BA0426903025ECB40F5A1CB860C2F33D94847A5EA122AA919B5D"
- },
- {
- "key_seed": "A3DE67DAD089DBEAA66B19E86D2FEA6687B14248838D5770243FB598F3C4A7E3",
- "ldt_key": "3603B2E7AA69754C0B8D384EF0B23E6237556ED876310BAD17E1FD2C8F65B1AEBFC6769FB9FABC1EF97808591B9EA3E9A1720611F0620979ED3DDF1235E842D6",
- "hmac_key": "7999C39246548C92251A110796666EE1889F756DB0EC6DF6B49D5A72699BDFD6",
- "adv_salt": "337E",
- "plaintext": "41D76111DD0F330918F3AB4E84B51EB9A2663C7D6F55B85DF58B2CA7",
- "ciphertext": "72DF51254FFD1950A98ADA8075F6A93C442F1AD8CA7CF6C78F5CF237",
- "metadata_key_hmac": "73442151CD271EC8795096EB3272ADFE33D86A774283D9BF209DC291C8327201"
- },
- {
- "key_seed": "FC47F82D1CFDC44C45DBFD8B50FEE2550FB10F4C501A43F37F975F375169DC46",
- "ldt_key": "8E92BA0192BF1CF8A7526A868AB03DF7AB60460C90890E9E3D5356978D7718249370906D430B548CDDE38CC79CC8A433997B656113D5C1449E5C92996B181ED2",
- "hmac_key": "31B759712241DCD1B9BAA2932AE5E09D65FC7A8F61449E54E9732677D03238E5",
- "adv_salt": "FD7F",
- "plaintext": "0D83E137CA7BC4200B5158193B54FD0AD2EEE5A15A61F58E5402F326E30A",
- "ciphertext": "656BB517EEBE4F2B48600DB4FBACFD5B188129BB288C34518A2CC82BDD42",
- "metadata_key_hmac": "6120ADA9ED2B4C9FEDC2DB990924C33AAC3410E41ED41487C1CD7E52059434A2"
- },
- {
- "key_seed": "75CDD577C4755E5A0740E8465AD380F178DBE0D64C14FBA56AEADCC204520F33",
- "ldt_key": "68760B9FB6C651B1B4FA00EA2DD39FFECE7918B16C37C8E1AED39144178DFECD864450AE55F4F43C6EECF3354AD990A01802B2F16CCD3BCA5B2FF5ECE5D1F889",
- "hmac_key": "8363C9EC9B08C3F5A36F81FBE6355B3BEAD57FDF534BC78A241D8D5EE09C0A55",
- "adv_salt": "6639",
- "plaintext": "58B1E6FDC85A719780CE6E55BAA86B69EBD383A9BEF3A128CB",
- "ciphertext": "424FDA5EF7C74F2CCA242C4ED06CDF7F018C5E66C7D0D0636F",
- "metadata_key_hmac": "18EF8AC0ED8CE9CCE1172BD4AED6236F0A4E4F1EE639326BB4D6B4E83512F279"
- },
- {
- "key_seed": "964C1500301CDCC623F5CD0B1D7EC3D766A6409AD2D7C2380D15CD3D3A59C081",
- "ldt_key": "0173131036E303C6BA39AB157529683888D4A3483ADC6C593A96F73469B4964EBAE07F195DE49C14453C962F197B6F4D302D0D9DCEF98A20B102FA99945CAD5F",
- "hmac_key": "B7DA1265038925CDDB1C66C34F58B4ECDE531E4DEF61FED637877830FCD67B0B",
- "adv_salt": "2D05",
- "plaintext": "558A23FDA9CDFA4F8C4DA733C18FFD3350",
- "ciphertext": "29ED3F11E844F8C5159597DD712FA7F005",
- "metadata_key_hmac": "B914542CF3E6EDF434B1937A4EC11D792A487E0A2A2407D331262ACCDF23AB56"
- },
- {
- "key_seed": "C98EA0AD4508C49C13886FC1F64FC531BF700FFD4643D1871AF50073DB70F7DC",
- "ldt_key": "D0E28992554ED4D20875D2F18B3B0B6A3980C257CEF7C30ECF33DA9ABBA2184A2C6AE292D1CD7DB546D10B72837949B7AA066FF2AD20D341BDE483C7BBCD9333",
- "hmac_key": "B4BCDAB34821AEBF3E5F62D64B89DE9B6EFDE9DA321BF8A7282E9BE1B2BF7487",
- "adv_salt": "2C2D",
- "plaintext": "6568B8EB33EE307B2D17E988F070425E433012FD2D6926",
- "ciphertext": "C0D072E782E8657D4D1A3C94429555E05A96E508E1A724",
- "metadata_key_hmac": "C575DAE69E903B641D0F065970B90481835F080D2356AD31F90851D0CC60F1C8"
- },
- {
- "key_seed": "5068BA6E60D27009DBCF17FBBD2B4FB16F8E39BE8E08EC16655691C25791FEB4",
- "ldt_key": "B574914DEC464D83F7FCEC28772C1079D7725E3E50B7CAD4B848908F0DB2F0C99DC89540F2DBE75BF010EA3251737EFDE7E673CCE08AA14273D50F3C0430B8F5",
- "hmac_key": "70DB70FE8F8DDCD7513415F04E56FFEF713AE86B42A38AA324EA47F220D14E6B",
- "adv_salt": "9E90",
- "plaintext": "E725C15924229E8D3CB7A8A8B25BFF978A0887EC398CE0869CBDCD1E",
- "ciphertext": "A168E685BE69D7A404743421580C99F3FBF3516D5605030BBC2B398F",
- "metadata_key_hmac": "A7D3C12100FD3D35426999301D916FE8802BD87624224C6246DF64CEF1813E34"
- },
- {
- "key_seed": "5C79EDCACA1D21B0994A45DAE06542883BCA0D8C04421A3809B11BEDA8DFCD54",
- "ldt_key": "B786B17A1C9D89100AE1A4A624B291F60886631C85C5505C15A94754A03235D3D24867D08FAEFFFDC170052398BF78C52372A0670F90266DB4F7FFC866F80215",
- "hmac_key": "571C8E8914F72F5A3A2D9B737FD5A090E42C5E1BFC1C9DCAC05635D47F8F31F3",
- "adv_salt": "26FE",
- "plaintext": "5D510AF1F8CB70050ADDDC19A504E9A8206A",
- "ciphertext": "3956DA7AF1485B5CAFA372806FD0F0826A8F",
- "metadata_key_hmac": "2AC2100526394E809ADF463BAF1639AF2C0714D5BCBEDDACAD557F8D5AB67638"
- },
- {
- "key_seed": "EA2BE502D69156253AF8FA64E65C7039AFD10A5F3967E3BCD8803683E5A56DC5",
- "ldt_key": "8C0BCD6ABBCCB13DCC92DC2E4E389E394A2C986DD33F1E11CEC0C53F9B4A75E70068820A7934376BE3F1D44320071E0F70A5FC828516088119CC90A59EAC7B46",
- "hmac_key": "9CA3FD68708B906D46776F26CC37339E2F8CA5B2047E160C67E28CDC514B457F",
- "adv_salt": "1DAF",
- "plaintext": "ED01E3CDD1F0084D2B53904147FDD9DC5D8E68F7BFD8CFE5",
- "ciphertext": "6735AA07367CF00FB6BBDE6C16CB0772589C64C0321AB78F",
- "metadata_key_hmac": "C08A893EADEBC7444220E5B2C00076BEF31F0DF0A85BD3AAA571877247702AFB"
- },
- {
- "key_seed": "70E69D3D65353E3AAB37DACA6F7E7619FB11AF47EA41F1801D0444B53A1EC877",
- "ldt_key": "1D3CEE942FB6ACD5560A203EF5A22D6AC0A9DDFF66C4C6242B1934811E0CAC892247A258945BA677DAFD020AA2DAB8CBCF23B6594B9688F7D29830DA4107B49C",
- "hmac_key": "C63FC0CDEA7ECAA9A05D0578DECCA5E3B539B892A44BF81A35665DA69DF46CBC",
- "adv_salt": "A596",
- "plaintext": "A6AD6912786A8F2413C2B71CF45060A419F3F085CB8F60D3FA20F033E1052E",
- "ciphertext": "00A498DAE18DF3447AC0580A0E5D99D88B5002AF00E17D5CBB456BFD437D68",
- "metadata_key_hmac": "7BC73A052E356779360968BF5785F5F24E429490C83B140263208D27D544FE16"
- },
- {
- "key_seed": "95AC44DFECED7848D2BBDE48AE3644C643C159BF5ECBABFA397D6136C5A3BA00",
- "ldt_key": "DE4AF5DA6B970F7990845837D06EC746C9833F272771F087E51E58DA39CA0C27EED3DA0F45432C0EC07D10DB1D57AEB0133D3A28D6B34FD9C4299852121C4CF7",
- "hmac_key": "4EE27FABCA00B9C4DD92B94838B35F4BA456415F68BA968407D2D38FBBF86AC1",
- "adv_salt": "F644",
- "plaintext": "62417CDE107AE6A89F15BCF09BC2D56CAD43DBD6C4",
- "ciphertext": "964C14893E03762FED52557949E1E67F3E477B7FF2",
- "metadata_key_hmac": "EED2F02F9C579E936545F950F56B95CD0C033BF4359C1BD23224A37F3C8A03C6"
- },
- {
- "key_seed": "9A1F41B0AC6959208C85B084EF2465CED116E845BFB3318BC04D3D4AFF2A91D0",
- "ldt_key": "0963F3B352BDAC400086B79A8A07172E1A3D452EA85B0955E0D42923B13A6FB04EE16765FA9B001438CCD7799BD8136DC01476BB4D85BE129EAC71BF32EF0212",
- "hmac_key": "A83A584B03BFA85341FF4148DF3F75D044BD4AB561D7F5363261E01DD5D59D0B",
- "adv_salt": "716A",
- "plaintext": "5BCCD691CC31878A7A557C688952D6641E9D4A8F37913E768C19D73197",
- "ciphertext": "DA0845C303EBB48347A7F9C1F854721266C00574A0145EB099548A2C73",
- "metadata_key_hmac": "01C60FDA43D3B64CECC9F05D3A58A43C464D4ACFAE8A3DA9161D40D7F94AC494"
- },
- {
- "key_seed": "53BDBB22732643B193FD8CBAE1783519733E6598912E4AFE84F6E75122C4BF29",
- "ldt_key": "80EAF347106A3FCA0A2159854923D4556307FC165F9097EA09CC356A00FB7281168B221318D0C6905AC614275B7E5405691EFF99BA9B751C2DC09155A4EB54CD",
- "hmac_key": "F7347BF2808A389CD9E6DA5718AD89187E42F4D113B011B7A783F72814E9F852",
- "adv_salt": "20BC",
- "plaintext": "15D8E5A032CEE9A426F4BEBE1319B66C88D95B733103188E0313588DCA",
- "ciphertext": "86E4B33EB62F4940FEF661B7CE8CB10F4F6FD9826ACC07BE615BB95DB2",
- "metadata_key_hmac": "F172FEE4274F485FA6009EBD0D62F17E74E921BAFA79D88899E3078CD5751DB4"
- },
- {
- "key_seed": "F5ACC9DADD3D04267BCAE2082578EA61C0F6C0267BE7EE187422E194914D5DE3",
- "ldt_key": "BB3B714241A446A8DE5CE4B961911BFCD5EA42CEB785BF5FDF47F922107A9204075BA02AD360D5011598E697DBF440FE73BF8146848AEBBC4B5845459ED07EC1",
- "hmac_key": "5737EE23F36ABD11975CA37D444409392E033C2E2951EBF569DCBA60EB671DEC",
- "adv_salt": "8696",
- "plaintext": "6D72189AA757296072E1301D281C2EBF2CDB589E9C7B4E4471E15DF3",
- "ciphertext": "51EC36C9BA729F0C2DF4BC0ADA2C3B39359B408DBBE209CBC9EB8B09",
- "metadata_key_hmac": "2485051451D77E97559C3E1518AD86F1F4D10DF855151F49DFA4011D774F0115"
- },
- {
- "key_seed": "6783C15A78CE744C8C11306B938C660B291B59DE3BD36A39DE3DD467657F2FB4",
- "ldt_key": "C84D751B752C5AE7399D125D081F1040FE416FF77683DBCB87481543401F8E59FC699BB0DF7CDB600DDEA21AB6B85FA12C8FE28A19C0A5891AB89B5EC8CCF848",
- "hmac_key": "B84C3D612329F25B127FE18284510A908F6C1C9ACD5621C1E37AED36652B3398",
- "adv_salt": "65C9",
- "plaintext": "829452230FEFC15DB039063D2318EEC8A348BB1F",
- "ciphertext": "32E19D511199B05E9812089BA1A08FD5986EA2B3",
- "metadata_key_hmac": "870D01D40A6B8DCD39A7B638DCA32BC8CF7BC0E90B1641BC0051A7297103C3E6"
- },
- {
- "key_seed": "68570C52852FC7954F372CC6B4552872AB1509F50A150523F4BA306B4C50D780",
- "ldt_key": "CC660A62F836054EE66B265D8764F5359E3417AEB489E164CE7FD1438D77AD27611A861D5C352C1BF96337A3841A7016CA4985BD0D1BAD188EEF30DF5A5E8133",
- "hmac_key": "4FA68AB3FBCF3529EF05CB3FEEBCF858D61004269E8F75ECB3262CB34CAB269A",
- "adv_salt": "0E8C",
- "plaintext": "6F4398291481C729C9ACC626D2A639DB7174",
- "ciphertext": "CAD84F3CBCD28CE8AACA5102906E1BE33872",
- "metadata_key_hmac": "84BC6A7B827C68E38858E2DE1149E8D939AF989DC7040C4473F7E03ADE429671"
- },
- {
- "key_seed": "39CE44538302053859A5644BEFDA73B503795FF85A5E05E9C212C8806911A704",
- "ldt_key": "1B58BC23C52F71AD309723B9F5D446F8D88194C80B316A9B0C9E9C78644D4771E8BD6DE52550673D95E551212C55F374F842CBBED5A10C32F241EDE1F4266714",
- "hmac_key": "5F5790FC03CA669C92AD61A877D5CD7E561DCE1166A62FBE92809240201FA3F2",
- "adv_salt": "2AA6",
- "plaintext": "2D47FC43E3306D318E3BC1E0560F0E152A5C",
- "ciphertext": "732124627DEFCD991E6D42ACCD8A370B2323",
- "metadata_key_hmac": "0E8A0E36877C92BB61D8F4F85A7E0D02D973945694455D45132F83B806E8D9B2"
- },
- {
- "key_seed": "3E1E131C0BE3413B9A98A219CC37B6CFBDE4653F758DA88B106402E3664ED94E",
- "ldt_key": "63763C5633719656DDBF4CE8B941B2A7F3CCD952E63AE31AFC7C6985862984D0A427A605B8F58F9AFE0ABF992CAFF2DAEEFF2CDE5D12C29C1783C1D4DA87ED15",
- "hmac_key": "CA5BDF30180EFF4970F82A5A8FF23A5C0C8D898FFD0937CB9F100E7F7CC09EB2",
- "adv_salt": "0705",
- "plaintext": "BEBEFF39A02B34F3B0A31CB9922D8B8967DF58175AD50626",
- "ciphertext": "5DDE9DC2E6DE37F90ABAD3B3C12F38C3FD3403963E2B41DD",
- "metadata_key_hmac": "461971F6E4AFB07BBA4D854E26125B2A84FF08A2BDEE9DD18A51ECEE070B8979"
- },
- {
- "key_seed": "0EB58683B5CF94CAE8F55A4EA52179C034A9BB5255E8844F7E81B23F32F6A5A6",
- "ldt_key": "D747228FF6B5FCE4C7816F2F5485673CA5948495DE0D0A786FB5AF66EB8231D3A001201129FB9C2E1D59E37AFB706A81B2D273A6AA790E259DDF223697111E11",
- "hmac_key": "CF421B245B4927C7C9EC547DBEF2DE0FE60CB8066B4B48FD2D959DBE3BE5B135",
- "adv_salt": "46DE",
- "plaintext": "9677773693DCBF976497F1D627BBB69BE7B57433A2",
- "ciphertext": "A06D673453F8920F82612ABEB9105C5A372EAFD6C6",
- "metadata_key_hmac": "1C5B7FC597A70EA96879A4E355A328021517E8A52DB8E05CBEC6C2F210EE0C9A"
- },
- {
- "key_seed": "703512A357CF1F2341B6EDE889D8307B5422B0387409BD8734267BE3840F33A2",
- "ldt_key": "F75C2D1F0FA77227817F27D2BF50646A17E7DC139D0C139402799FCB990B8BEBBB11F9795F010A7407FCF2C5904F84B057099A8E00060A14DC46D27CB0E9B5D6",
- "hmac_key": "091213A5ED437436F5CCFBD9708D95FC63103C737D187EA83054B159A9319DF2",
- "adv_salt": "6CD6",
- "plaintext": "B3A36BAAADAB47EB3A888C886CBE82DE584A860708523A47B7",
- "ciphertext": "099F8D46E4FBEC2B2A480C496CFF3BF2E3464D1AC83A8ADA26",
- "metadata_key_hmac": "D241EEF767BFD7695F0C7A2A93D847DBE4F79E2FE10A1E427DA5A7A9C81FA171"
- },
- {
- "key_seed": "BC6D6CC4D0C775448DCA55337BBB16CC950E9BB1F537BF379C9A34153E1FCFBA",
- "ldt_key": "7249BA6984ABA597609A304942255EA45D175E7E630F22071D494AD85FD500198572EF1B55061579C8A60042154832B664E9544B284245A7809F7E71634E6862",
- "hmac_key": "AF1903DF4D7DD4B6981FAEB7668261DF02856934B72B23E21CB5F32F9940071C",
- "adv_salt": "7A5A",
- "plaintext": "B453B47C75FE8165ADB9A9C794BC91422955BD62",
- "ciphertext": "229642496B0977C5EE5339877EB596B9A6112828",
- "metadata_key_hmac": "68E4D0A891F049F151110B0897268607D117CE04E7BE86AD30AA65EDE1B76EBA"
- },
- {
- "key_seed": "1D1B2722F3CD7184F7B55ABB2D5DE897048A9DB1AE4F53923646074FD651ABD4",
- "ldt_key": "8FA39DBC12436D4C22EFB15B8071133F95E30D159B5DF923DCB56556F6C746DB83B5D2E397C27A8407633B6BD97AC5C09844A5F6FE63EE504E59C02153B9E379",
- "hmac_key": "49EFB2DD19EC55928BA2DD0055290887EAFB81EC0DC8E58F7F9D0B4FA428223D",
- "adv_salt": "890F",
- "plaintext": "8D4030A8672074103B63D025CE23EFCC378DE5C31E2BBF147BB69BEDD90FE9",
- "ciphertext": "EB90032A5802D2B1B863C1F0504D89C273718C567A47EF02AB1CFE0473DC43",
- "metadata_key_hmac": "85255981481522F4AFA9D008A6307D34F52AB38DEB145C60F2836580725137F9"
- },
- {
- "key_seed": "0EA7BCB5DB506CACD5FA1699E6758E7765383FEF79D153A6CB67C18E3EFB1F97",
- "ldt_key": "0EF0AFD7C3329C05A941E5D062B9AE59841C2DA999DCA8999F4BEF8B1B9F8CE51ED9AD7CCB69124E0A85BA2FD9634E928AD96C0B81FB55B0D1D929C8395E2228",
- "hmac_key": "F35887CA73B89610DC0CAF6E9C05F925F057FE0151C70F0E89FDE542ACF9F672",
- "adv_salt": "E557",
- "plaintext": "4213CA09EDCFC3C34DAAF9E1D624DDDF7E34EA55CEF20F57260A",
- "ciphertext": "9D8E79B64F10A3763022A5CDBA43008D583B6EAAAC47DF64F429",
- "metadata_key_hmac": "DDCDDD499DFD4A909FD66A26D420B627E4F8F9F855D870A774639BD3876FFBA8"
- },
- {
- "key_seed": "94C0899E4868DC85CDC3DD9CD1A65BB1AB6BB7AF886733E04128528B7A2A465F",
- "ldt_key": "0E9E6552B91C674F422EBB10DEE6172341AA1C7878C004883FF24E06C4F90475086AD232704B831A4012E8F60F099D250D53C9507EB232B734CD5246C3D35743",
- "hmac_key": "C53A0D4D789182B586D67C128491E049E8A6B70D74ADAC5156DCCA369378CE98",
- "adv_salt": "163A",
- "plaintext": "FEADAC57B3E1C708290306BA8F657E1520C8280C",
- "ciphertext": "3CE4F4228E22C8AB9603DE7D24474DE8A832E1AF",
- "metadata_key_hmac": "B8482D5399DC21483CFCDC8B061722DC7E7A25A9EC22BA45891DF6663334A9B7"
- },
- {
- "key_seed": "F370B420846D05786667A8860FE89A0106FB52BB0C14A10A9EE26F92008C85A9",
- "ldt_key": "C905DE5A4D9A71D42DEBC09CA3551456B86692AB157637FFA69626D880791891C34F54EDBB914AD5799E4B919C43C205AAE659D391A6A48A01D16362F35E653A",
- "hmac_key": "6F2BE000125B82A2E33DC8C9E43705D60526645724BB0AD44B21DA54B3583BD5",
- "adv_salt": "E304",
- "plaintext": "71CCB1045AE70B3006C31956BBE79C0A8DAF6CF384AE2641DF5AA56D",
- "ciphertext": "36CCD64BCF938CF027FB6AA76F22DF8E15313033B2B2ECA5D8C62CAC",
- "metadata_key_hmac": "656F0A8E99EBACA3C4CDAFBFE368CF1F7B1D6D21298B353588FAE6102714D3C3"
- },
- {
- "key_seed": "F1F3A8615F2C5254F5705ED9C7B8DCC3E54EC6E26F976022A41FAEB58833CCE0",
- "ldt_key": "B2F43E1E0EF3AC754BC7DBFB06150A03DECB6C13B2D59D372D32D1C4C95E12B17D05E104519226C34ED024AA42F35F97DF19228C7A960B3366FC81DED6D6067E",
- "hmac_key": "46721F7126357AA3E1E1CF333D87CBE25D53A929EDE142A0B171661437FC65DC",
- "adv_salt": "7375",
- "plaintext": "5B457B5E1B1EB0C033A1EEA469BE0DA1",
- "ciphertext": "0ED8CCF5D13E17B19C27E7E3E74547BE",
- "metadata_key_hmac": "1A113F03BB294B74328BB167D3F86698BCEB4795D42F6CEF08463A36E0343E5A"
- },
- {
- "key_seed": "352DE4E9A05C50430F06E1F5E7E305DC268154FD8B4474C82E11CCF326480B2D",
- "ldt_key": "FC1A43A901581AD08C41BDFD5717ACA525CD62F284AB836FB162B7F201C4B88153DF23BD6E6BE90A1551B3F7C0BC4F21F764F4846C403972F6E87D5F50E776F2",
- "hmac_key": "11F04E1C99267F9104136A72CC88F46BE4413596C562F9C26BEA27146C19FAF5",
- "adv_salt": "7F58",
- "plaintext": "64790AADB293C27C49D18289226FED7768411D0A22",
- "ciphertext": "457C6407FC9CF2E7C1DF8FC907743A6002AF353453",
- "metadata_key_hmac": "0CB22738098D7215F402CD5AA6E005FE47F72505591F93AB693EDF5FF9BAF2AF"
- },
- {
- "key_seed": "66B6FAE0F6B0484EB7413DB51F7FCBAD1187BEFDDA329177ECD4B418A7CC557A",
- "ldt_key": "3560736E3B71452A8935EF44775D1EA955B8C63268AD3A3DB58E4DFFCB9B3FD3BADFD7B71417BA845EA5EB88B2F5DBFB983CCD3AD3F39351C86294842660F489",
- "hmac_key": "9095B581BE4680389A9281FD1FF244DB28BCA1F872EA4E00BBAE467D16B5683F",
- "adv_salt": "E87E",
- "plaintext": "C9374B60A3ED97BF64ACD5BF4CA75EBCCF",
- "ciphertext": "9A0132A481D66099A9B5BF783BFE6E4616",
- "metadata_key_hmac": "4A3ABD5626A0D2263CBA0259057FBD537B04B135D5674179516898AFEAF8781B"
- },
- {
- "key_seed": "46F24B770B1ADE0340A91C81D3693BB5AB1900050912279F737AF059CE02C9F9",
- "ldt_key": "36C3BDC7A4BB377CEBB55F60E9E7B49CAEE166968492384F1596EDEA86EE2EC9BA2EA6B52C5C7564028C9057CE6E0938DFE4935E0AD02D44FC98050675B7DD06",
- "hmac_key": "D01263CED254613D29A70B1A64F0989C574F08125F27BBA1BB1AE2EE68634348",
- "adv_salt": "FEBE",
- "plaintext": "0C9E2CCD8F9790D33FEFD640621545F6",
- "ciphertext": "812EE0C2A14C097DFEEAABD5EF6C387F",
- "metadata_key_hmac": "7C7747CE38CFE5AE657EF6AAA504C47B5447E641B19248C4F3B67180E9D3FAB8"
- },
- {
- "key_seed": "E71EDBE4DA0EA9CA5B4F083E56DE60643B96742B61C5948FA11ABE5FEE024324",
- "ldt_key": "3F2DA23A6EFE5492830C82437E27FD26ED83BC22F573A4FA0B69129DB2E4DDDA60FD436DA8BC74F4380B740449AC54AD0E4CB963FB36C247216F3D2620ECAC2B",
- "hmac_key": "65C79B5C0BAC21D938D560875098ED1CF44D198D765480A0FD9712FFA69536A7",
- "adv_salt": "39DA",
- "plaintext": "A6B6F2B67D86207B75568350E024ECAA971EA337A452C64CB411",
- "ciphertext": "70A0F0C5798AA40E33E6E13570680070E185A862729EE27B45EB",
- "metadata_key_hmac": "403423570D444DF6F0E23D5278F6E32598AF944DEB45119D10373C602E7EF470"
- },
- {
- "key_seed": "4E72EE3AD7EEA1800CC1FD0FFA52FFBC956AD61B610E6D52D172151550CA3EDF",
- "ldt_key": "017F11C19586862084AC204AE3F2A4E6CBD0AF118C500691B035DE40E34655750E60261AB3659F38F4F2839B1707D1A1E18B4E4BA34995030889DF3E42A16CAA",
- "hmac_key": "DDAC2A8278227BD24601C4E7A60E5EB5202C6E08B3DB91163BFD8398C2F115E0",
- "adv_salt": "11A0",
- "plaintext": "E05B79A5E3400C9620245A24519EB7C644E1F75D3A7E661EBED2A7E05B",
- "ciphertext": "316D773ADD8E7760838511133B0494F1E53E5C376206924BA988CEFA6F",
- "metadata_key_hmac": "1D9EB4F8E2B8C0FF61A768F9D4DE38C50441ABEFA389C5C896B800B0010E54CB"
- },
- {
- "key_seed": "29C4C4ACA1FE347FC57373BAE7B1608285BD124BD5D2ED1BCBE096CE34559BFE",
- "ldt_key": "79BED0C41422EC9FC7FCDFD1A82F05FCCF4E2452720B22214D72C6B9832060C7C34FA7AF4203A5E71973EE0DC5FE4B6DEA39B2ECC4E6382CC227420B7A08C3A4",
- "hmac_key": "74F0F33354E99AB617EF92E19126E6A23C5B7986274EE42EAE047879AABAF6CC",
- "adv_salt": "CC68",
- "plaintext": "19C23720321DCBFDA34B7CAEC42044C17C10",
- "ciphertext": "C8B673F748D75F10860FDD68B0CECEAF628E",
- "metadata_key_hmac": "DD707F9310D9F4F50CA323123C005021D62B18CD44DC1D2D7010F40E91BCDF6E"
- },
- {
- "key_seed": "8AC90D32CFFFF80DD40A0E9DCB9126CC68074D963E2C6D9B9094B897867B891F",
- "ldt_key": "712BE11E8FFC957C1AFB7889E7F26836CE216F17BC5833DB37FD18E6C184F48EA4561A44036E3527E5845283C00A88F29DBEEB7C92D11AC8049A83400C60A7C8",
- "hmac_key": "61B07AD48CCAC2A71B1684EFE7E3D1CA142CF20CA8D390356AF795107D3F215B",
- "adv_salt": "DE3A",
- "plaintext": "F686116AE03B1982F591A80C702F5E37CD9767FDDA1A3D18629A28F5102E49",
- "ciphertext": "7B9046041C3D232BF1A0513FF1CDA1AC4AA4205664C3F6DB560EB8BE668A60",
- "metadata_key_hmac": "5A0EA84490DAEC977401C1DF0BDCE4D7F69A15A082943190DF6D30B456BECD67"
- },
- {
- "key_seed": "A8CF63E3795D263AC7ECA88C9646EB1C20A0FB00C1A5DA5973C3D30687823311",
- "ldt_key": "731278582AF984AF187232BC44EEB9C297A2DC0D54FB3948B2DF3ADF7D295AA1731BC316A1C95448800E2EF3604BA30CB616021ADA5AF671F7BCECE8D11B7FEB",
- "hmac_key": "EFB2FC72054D63B14CB2966B174F328391B41D1B823F7A45598258857121BF81",
- "adv_salt": "A42A",
- "plaintext": "926736CFD879B5E15B5274341FC48863CF803CF0CB78CA2DFE",
- "ciphertext": "EFA206EDC33DC9B6F294DF7FB0589297F3C70020326216759F",
- "metadata_key_hmac": "88C796D31D909B1A958199EFE224524CD20ED2EF7F1219FCA961BAD79042A429"
- },
- {
- "key_seed": "6CC2DB3AA70FF4258F8DA394570A07C6D7C62DD97200F9272EF3C504DDF663F6",
- "ldt_key": "C067AE2090E91FD5FFD9BDD87316638266123C1DC15955E42C1485A93B857660236CE6C91F6EF4E781BABE5FD227A3269A8EAA77F97B41761C4F2484554FC302",
- "hmac_key": "B83AB0B2AD00256C8983CE49D6A76B6D3028D64889E8EBA67DCB9C08F8AEDBD7",
- "adv_salt": "BC3B",
- "plaintext": "D54AB6B6A4BD0152C6AB414F8FEE8C44D44237BC5A1F",
- "ciphertext": "3DD97FD1611D5B3D0579D9766E4C5D607709BCD0CDED",
- "metadata_key_hmac": "F5C8FA8870CAE6C2C48C59478942DADF5E08A7CD1FB872613A78DCC69085D8C5"
- },
- {
- "key_seed": "F3C4F33CDCE131D5DD270546F46E986717912EE27D246537CF7776C4238A04C1",
- "ldt_key": "350EA4B98C555B9AE90900F547552580FAD3DB4C297FF3295602413FA7D6F6D905B735291C7EB4FFF834DB9601F479E2074F367BFC5D9F2F87B24489CBA05030",
- "hmac_key": "1F0D7683CAFFF276AF4E63FD89028D69EE034F40CC5ADA7739ACFFDB712E24DD",
- "adv_salt": "BCF1",
- "plaintext": "DA459AC904B3634D1CDE2CF87ECDE60157ADDCC7F2F6C5",
- "ciphertext": "45A3A3EC391FDFE6F56A592E0B428D9A200DCBA3866868",
- "metadata_key_hmac": "FC1CE147E7A2C6CD10D9E52D4803C7C01F8874ECB52CB1E817E9C2EEEE9AAD3E"
+ "adv_salt": "0A54",
+ "ciphertext": "216826E89337FF9C8C86A88A7F9610700886A36AD7CF767DA31A15",
+ "hmac_key": "C2B74FB5BAD82E56CCE52FF1E11F513F32528CCB480927EE74E5BD7CAB3FAC62",
+ "identity_token_hmac": "AA72967F9912971CFABB6C9B17C9A7F6C87A37EE2C239EF17874D00B1B5DE61A",
+ "key_seed": "0DB6C6843FF10D5F38F7809CB20D4D9E46497EB1F1D2F0C675021EA734EEDE03",
+ "ldt_key": "62513FCD2578DAB8D8C234E893EA8A1B6079D8034607F2B0C1DA3C062D5A1D8E40FCE047E785E3EA31287CDB59B27E4F86A35C9231EF03611BE8CEC4EB3EA511",
+ "plaintext": "0A17149A84904755A19D9648902C10CC407A7B75E20AD94B9524BD"
+ },
+ {
+ "adv_salt": "8BE3",
+ "ciphertext": "388AA1AF4F579F96D9EE856BB4F6B3E17A242BB8A3E65688B1DB069C65",
+ "hmac_key": "4FCB9A35A2D7B4DAF8306AA49EBA5381B4B4B06BB304CAD1D2A038A7458C6A2D",
+ "identity_token_hmac": "3C6FD647D8723484F82C9A5030B020208FBD0719BC7D3D442B0D3144F0F91471",
+ "key_seed": "0DB07D210A15768D1570BE426E0404A907C6DE2346541763011C190939FFB3AD",
+ "ldt_key": "A402A13DBDF763065057DA78E634F46E7AA40B5957E4BC1C50A22CEDA9962C6A7EB4EB1566DD4A0394178F2B295E77AA044434AE2484512AB3D1EB57CD4554BF",
+ "plaintext": "D806CDF0B1B96817469D15A96448262DEC4A6BC167CBDA5AF46DA97DDF"
+ },
+ {
+ "adv_salt": "7F11",
+ "ciphertext": "ADA4507A0043839EAEFB25E918F35BC2EF9C802AB9",
+ "hmac_key": "E45BE5793166A4AECAF49E88557A396772FBBDA6991CB7DF747C66D35C630071",
+ "identity_token_hmac": "664EE5E73ACE23F1C2ED4109B1A790B5D79CA3D1199F72D17325B4773CBCFAB2",
+ "key_seed": "189EB21B47BD26468B2688EF969AE3CAB335F851751754499624BF2ED101DD0C",
+ "ldt_key": "62BE54619E90A085C9033E75D0A0E4F80803CF8B21FF4E0BDDA00C91F9B65D1E8F689299EFBF3EE03758B182D0D4C81B3A37B181AB3B342686F3202552E25D36",
+ "plaintext": "1ED2E4DCB9EBCE51D81DE2440A88F8C4218EBA7880"
+ },
+ {
+ "adv_salt": "E78B",
+ "ciphertext": "2750A1DD26974816A86F25D21A77BCCE7D0F162BB02A9E",
+ "hmac_key": "A6ECD71B681206038FEFE976CA6B480B3EF9C96F97614BEA5F97EB02F6F9FE0C",
+ "identity_token_hmac": "E233B0BB2E2042D6F097325B9D56EA1BD328861D76F670107FA18B46E509BCAD",
+ "key_seed": "060B02CC1ECFA8236FCC5573CB4900AD652913947000F1062571AECB42DCEE3A",
+ "ldt_key": "D2849561C2C8FA1A50CAFDD0CA727EE277732E942148B7BBA670F92C8AA53C42B71E332E41182EF28CA75285AF0692992E49A5BF049BF775181A15E2A458169D",
+ "plaintext": "C4D8C9B754A01732C3CC63D10E27CE3461F5551E7E43AE"
+ },
+ {
+ "adv_salt": "EA65",
+ "ciphertext": "57856CB60C92E5705AFA37A9831C7E2C0A",
+ "hmac_key": "38E27F67F0D0906DBDED17915739EDB44269B0CE9B20A0F9581F1CA16611D766",
+ "identity_token_hmac": "5F03FC11FD378E7BA7F0F076EBDD920A9227A7A011CD4B41DD6DBA50442D1A9E",
+ "key_seed": "BEEC1F791F0F46D638D543B13377B0BD8440EEEB8FB0B0609EC973EF694E5AF9",
+ "ldt_key": "9696153B6F0C612EC4C651751B4A236ACD4301DE680A021BA123286344D26543ABAC4905F32272333D1EB6C34E336180CF1EB4BF3BFD49DF1E856BC1B6835FC5",
+ "plaintext": "52F5AD3522DA1CB6CFCAB587B86E9A3E30"
+ },
+ {
+ "adv_salt": "AD59",
+ "ciphertext": "1F00BB7B0B050E10774747616B67004D03396ABFA0D8ADD0",
+ "hmac_key": "552017B1A0E047B5882918EB3A438A5C9A4EAD2A38353A9C64F71527DA419BA0",
+ "identity_token_hmac": "DED83CB27AFA8D5CE08D8D1C05C6385C9F6B96972351EBB8C9694894DD310537",
+ "key_seed": "11A1E82D6BD216E080F4DA502D4F62B406A99DE2296F83657C2731AD0F7A9DD7",
+ "ldt_key": "EAF9C2AFBAE16C0D32FBF91FF969D1EE7E009CDEF0084DC884354AA623A32DA581776A4D5E58FF70B17DD532482C1CCD63EB9EE362869E39EB79D7B305F3DF82",
+ "plaintext": "1BE6306F08E53128A20DCD8949CABBA76FB5B70937677545"
+ },
+ {
+ "adv_salt": "5F05",
+ "ciphertext": "D1144B782E41E9310836AD8FF4ADCDBAF4D50AFB20398880BFE01F40E6435D",
+ "hmac_key": "C3FDE0D1EE5DB2A4C4097C61212C85582F00A30066E8E8B2C189BC12AC313EB4",
+ "identity_token_hmac": "57A56DD881C931DFEF3A0CEFBD018DAE449BEBF6102F49CBFEDFEA4F349C89BD",
+ "key_seed": "6AE0CCD8C88341021FCA2AFAB8CF9A26F8213761C33AC1AA792C37DFE8DE23D1",
+ "ldt_key": "5ACC33C3EE28218743E13C94FF17580DF5373C66B31F058AA1891D0279B29248963CBB61908DD3837DA8A969354AF6FAAB90198CA8E9C25F99AFCC3F4E09F7B9",
+ "plaintext": "EF1667FA173964C2409BBEF9575B14BE42E55EE97E918B8C727296C3549C60"
+ },
+ {
+ "adv_salt": "E50C",
+ "ciphertext": "04DF1A3FFA9E13D0AE1247212515D2C874A3BB1B8FE95C9F",
+ "hmac_key": "35BFB86404B08157E7F7EA6AE76554F3B0D3E3729E76D239EF1D07C05B1C7751",
+ "identity_token_hmac": "42DF5349261E6B238DB891D50ACC180CD9B29D925644CC4DE2A6C04192A2475E",
+ "key_seed": "A457F41ED883C88BA95D1E5E7DD69BC4D7D809793F9662944F7CE53993BFC62D",
+ "ldt_key": "0C3FC621712AAE7F53A36882BBA9BBE89B593751F357441E1EF2A41ADED4D3C86CB4CD9A495EAA6889C6EEBE7D8301C04A1B079FC6C511DA8A4690638B8F2694",
+ "plaintext": "2C4AFBCAA759A02727DC48C8073F99E3B0F8E19675938653"
+ },
+ {
+ "adv_salt": "369F",
+ "ciphertext": "D57B58FDE1F1A9FAA283F0F667EE82EC38C7FA83D2B5D58758570B85C03C25",
+ "hmac_key": "C07B61EB61B1E39F831A27481E05A45F646910DD10BFA3B9D4A9F2246C87C7CA",
+ "identity_token_hmac": "DC969C3953FBAE39F574ACE5D32636648454411B013A4D3F15F6CC03D6503116",
+ "key_seed": "0B70FAFE46D165C61580477BF0F8E95942E0D1313EF6DD38531256D331BA8EFC",
+ "ldt_key": "FAE613854ED28C718764B2DECA45FFB038D12ED0B8F4CF8E410CF664135CB9AB3F928CEC5ED9AF6EF05F4BC8A5B802112898DF299C8EE6D7B53364207FDCF802",
+ "plaintext": "BCAC01D17493B2EA537BD4D0F9E6A81A3C5FF21E2A9CEEA2B5A39066396600"
+ },
+ {
+ "adv_salt": "4270",
+ "ciphertext": "77E4E229422367E0E3C29826F7E586DE3813C9F22D41",
+ "hmac_key": "CBC601994BBFC3A47C23F03A6F55B265C76BF5B3D4DED01C7AB3417BEB970321",
+ "identity_token_hmac": "E1B64D12ED7836E3303F99A545F33DBDA58E3357AC39C5AE0B5CB728D5585510",
+ "key_seed": "4C0F2CB9CEDB8BB5C6B91C0DD7F769D2C6474EF2788F45DA8EE73CE1536E5BAF",
+ "ldt_key": "14D27C8012A68D40CBE9C725B1B20573F8BE0CEF409826236150505884B27D0DF25356EB0CA8E9E6A6247F563B4950BF76F59A491A56F76784C041C49D338C95",
+ "plaintext": "88189E5EEF3ED4711CAE61B36CD3C544997F28FA46AA"
+ },
+ {
+ "adv_salt": "0784",
+ "ciphertext": "8D5E6C77684770924C1A4A491ED92E63EA149226865EF70260",
+ "hmac_key": "209530DF75729473CD56AE03E754CA630B979A9232BADFE403B87D4271BBB80E",
+ "identity_token_hmac": "9BBE2CDD6C7318E218D6E9C7BCC7DB547EFCC275440A2BB7CCE82BACD6D777EE",
+ "key_seed": "C5E3CF6049EBD3BDFA10743AEE32537C75BC8D973C808FF955AD0EE4066E36C7",
+ "ldt_key": "AC229422EFF9F36205FB996C070D3115319F2A94A4C01A0DEB1094D3C56AF7092EA77EA7F8FDF879B22A42A9862610724AA8CF1FFFDDD7809513559534EB70D5",
+ "plaintext": "DD3E6E54270CD303B0DF06A5777D3AA7A82A855112A2925001"
+ },
+ {
+ "adv_salt": "FE5C",
+ "ciphertext": "A1C75E7100B6E524141E97A24DBB7071",
+ "hmac_key": "FD0776C73BC6A5B79D3E3FBFD04C7C9E3E137D82E9F5F426B2CDE832BC7DD6FD",
+ "identity_token_hmac": "A1C8176B483F1D6DBECBA76AF08D7E62972F98B78D0712B9AB1298BB08B890D5",
+ "key_seed": "1FA8E31F66CEFA5302493A7413EAF5A813ABD73BAB089BCC2E2B25DD5320F8B1",
+ "ldt_key": "862229764161E53FA6D8CF8CC6A3D56DCEF546483118DDDDB10A6C22287645B0375799197C9DC42DB8D7A96FBBA551B3F4BD28F908C8EAA7F177EFFA28D4BE59",
+ "plaintext": "AEDE409688E9631E14C183F57789AADE"
+ },
+ {
+ "adv_salt": "1E23",
+ "ciphertext": "D3015A7E2D2486B1D7F07E17F68C5E43A377",
+ "hmac_key": "248F166010A6A85ECCEDCCEC056D32104A7882D0BB0036ED5D5011D2A1BC9C6A",
+ "identity_token_hmac": "0D3B2CD8E7706A893755D6749924AD5CA2F755B427CA8D51786D578B0BF11F54",
+ "key_seed": "DB335588CBA2795FCB41A6568A4D38945E07892BBFA462FE7016D3CA1DFA8E78",
+ "ldt_key": "9EC0F76BD542B03159B10EB6F375D8F02C93D1243F434E4356A4D52714D42A6E7AFCF2C63D462FB2C45256E696F5DADD5AF5C8CFFFD6B2BB7D758EFFD8B82247",
+ "plaintext": "9FEF46046655876C4A397550BA23C069C869"
+ },
+ {
+ "adv_salt": "F60F",
+ "ciphertext": "72D6B0C1EF949E0C6AA41084D952AE49ECF7625E8ABA6C",
+ "hmac_key": "3F666E45E16F4208066365B7BE13BF730B5432297816FACBF4F0F42D68B7B330",
+ "identity_token_hmac": "44FCB520188601A392A46E78B799EED60232D4C34A60FEC15A4631FD19B819B0",
+ "key_seed": "34BC6654E79D5DFB031101C6B9A0530A66522BB053318F1A890E7659AF457FF6",
+ "ldt_key": "BA0872DBF9B506C80911EF96AC938DD5FC2556048DD8A0A6E09D1B16B1FE89948D892DAEF7ECF438F24020AD19043330CF88E9F951260D2764875C0D8CFA30FD",
+ "plaintext": "2671280D380269EFA4AFAB7F8AEFBEA3BAA546A693226F"
+ },
+ {
+ "adv_salt": "6245",
+ "ciphertext": "1FB17D4DB41ED8A69423D1D00E70F1468A6282C4E46EFBED76",
+ "hmac_key": "842A046AA27B15941FBFC1ABA675D054ED43AE4A774A621C0D79E669BCD759E7",
+ "identity_token_hmac": "301488269C15C06DD58C63D9F32F3EF5F1F25FD5824F5BBE3A075A0294E2DE8B",
+ "key_seed": "7784295CB941C0EA8CE99F532BC4356BBB70D6ECBF7AC8AEA9092111D04D769D",
+ "ldt_key": "86D6FB6D2D96A3B0EC141A3D6A97B7F40DB56E2C068B735ECBD106E34335DDDB350CE5EFBBD76DDE01BD4C5BC8CF5AABC1C2144793C9F30417D59D3CDE0C7B77",
+ "plaintext": "8F1813881C5F60FD25124FE0EE83C7585D64B028989FEB6C71"
+ },
+ {
+ "adv_salt": "0647",
+ "ciphertext": "D1DC1D59D804C6F1066A153C50E6422A1F2A7FBD178DF7FC68DD2A80660905",
+ "hmac_key": "07BA5F868765444FF645C2975B1FB48C940C7372BDFBAC405E567C90165E8210",
+ "identity_token_hmac": "CEEB6515F58C53E6DF672636B05AB55429B8AE86224F66C8A812CADBB3B98277",
+ "key_seed": "D52DA32B6F65746B70EF2E6F99935D94DD3D60C34F1A7B5876BF829E5C67982A",
+ "ldt_key": "5BCD26A319297E8C1456DA63E5B88650905E2829238078D6D7350B5A6F4F955389C62DA84D47152845FE19BF4FF79EE81326833C8AFBED1CF2ABDADB5493804D",
+ "plaintext": "B4AB4964CC3C08873D0EBC40C929A6E4D0D52A0B3FDC70D4F93D1432DF2D46"
+ },
+ {
+ "adv_salt": "7560",
+ "ciphertext": "896F81B391D7D6722D9C3F13BA3C087543BDDF119DC6",
+ "hmac_key": "E517606145DDE8EB4DEEC1F3565AB4E85C7E1D843FE1ED24F54D4C582E85545E",
+ "identity_token_hmac": "89A947F96286E8EDE8FFBCAA51CE708C06F712E09A8EBEF024E1905F07F42058",
+ "key_seed": "5EFF0828AC1743AB1F473CA562FC647B9A95558E737E8E2FDBC3E05C15BE441E",
+ "ldt_key": "BE3BE0C9A041845831A8AE86DC23F8F8EFC935FE231D7D812AEAA1EF47D59AED776C8DD7080F9FBD00DF74D5D9A4C1FDA8ED1F141DFA1A2CEC01CD09FBF50805",
+ "plaintext": "A73CDA171E2ECCDFBD71C5B2BBBFA33380A79F91F5BC"
+ },
+ {
+ "adv_salt": "7CC3",
+ "ciphertext": "047C631815B607C024C28D89330ED7CA7C34A1F84D89A1F0",
+ "hmac_key": "54016DC977C59CDA4DB4386813221AB2A2461E27F762C9EBB414C5ED54699820",
+ "identity_token_hmac": "2E5F828069877C3C7D35754A773EF067AD4ACF6DC0C6F1EA38C981459172993F",
+ "key_seed": "09078590C19AE6B515DAD5F2739D35BBCE6BDFDAF3BC348C9E54D8DAC8131B28",
+ "ldt_key": "34D97B145B530111A67723BA9CD3ADF0A588B83952186868EE050758D29F8D486A2364FDF5939D0C9B1418507A68AA52FAEFA20C7EF288435429C638F477BAF0",
+ "plaintext": "020F95368483CBF3BC0868E3CC6E0439B117323016414726"
+ },
+ {
+ "adv_salt": "2A62",
+ "ciphertext": "6260B62E7005E2BA06B5FB3FAF71920EB5A3A579E3D1",
+ "hmac_key": "2CC37F55F21309A6CF34822F88A121989182274CA8F5CE4DCB462DA1B40433DB",
+ "identity_token_hmac": "7E095BB480D774682CB8E4729D69713685FB39C907A0806D448C61D1F779A9FC",
+ "key_seed": "8786BE0DA0D4484ACA7EF0E0045B376C411AEC27B813EEA3A2B7596F46179433",
+ "ldt_key": "E7965F807E1D7E93863736102985B943A5C88621B560550C5288B28BCAAE6BC223B69EF2CAD44BDC5C2677F901F2169CD9E62850EC690DC86040925F4E2F9420",
+ "plaintext": "6F4AFB850CABEBA63777AE6424EB517E04D494CF3ADA"
+ },
+ {
+ "adv_salt": "C856",
+ "ciphertext": "CF420AF892CC3B42ADD3577D350209CD538F2224302AD46ED89272",
+ "hmac_key": "C00EA1BFEAD49726A4B4C56CFBF219BD0E37295F4C1C838EC473DECC732F753C",
+ "identity_token_hmac": "F1A9C559BD880189641845E9A651884C590AC1CC4165DECA33AB64C51F2689E3",
+ "key_seed": "5D4FB15064519023C6218E35AE9B2D52D342E1E4310BC876A282E4078DE3B3D1",
+ "ldt_key": "BEDCA450ABCB8B5103A7DB0F0528A6730562B0934F62DFDFEB8949354D0CAFD4E101AF5F1ABFC20E64B979C3CB4D73E69190A41E6FB135DA8FD05D0631003882",
+ "plaintext": "249630967EA149B9B2F2498B9824A52D317F1CFDBD16B2EE0C830C"
+ },
+ {
+ "adv_salt": "9020",
+ "ciphertext": "DB1FA74871692FB6FC716584821A0CAC608E",
+ "hmac_key": "F5282F1B47045F1503FA6F0BB6826C9CB4A5C3C2D96F4CAD328D91A0FA60DF5E",
+ "identity_token_hmac": "E011BCAECDBBCD331816032F019F76078C1E47806A38DD6A2928231C9C22960E",
+ "key_seed": "16042559E2AB7392A3C297B88FD0A3694D4FAC223086B03B60473DE84B3A4B98",
+ "ldt_key": "134CEFEE472C4CD6066D064A6DD705D21C1FAB43174B096063C8698D4878F9F356B15BB6B695AED38CCF7A54B132B47ECB9B429F6CC12376B16CD285F25883E4",
+ "plaintext": "3801AFDDFD22B16A9FC330A4D14C0C216D9A"
+ },
+ {
+ "adv_salt": "B416",
+ "ciphertext": "3FD2CA364E9ABBA987AAE45D5C022B4AF774F2",
+ "hmac_key": "0C4037B37F9C4D607D91304CFD787CCB548720965CD5FCCC9CF7D8F1B4EB9EDD",
+ "identity_token_hmac": "1CDEC3C91FE18DE6E6B6022DF8C095F0AC05DC94168D22E86B83DDDB59EEB5AA",
+ "key_seed": "DA40AC0B2424FA5F53FC032ECDFA9ABD8435B908DFE451A3943718A68FB1B900",
+ "ldt_key": "7706D3DB253174C1CD4AF31690B3F5BBB4723CE48DB1685812481FF083FB7522C8049855F9278E73BA19A670C1E6834341250D45B10AE3C0995AFF261EB7011D",
+ "plaintext": "7709999026D4CFCB96C8B51A18285F00AB0609"
+ },
+ {
+ "adv_salt": "513F",
+ "ciphertext": "4C356FB91804FDFE40D608D2FA95204F",
+ "hmac_key": "14E2A8EE9F3439A5AD0D91AD6659F861763A5EAEEA9BC9FF950DD550EA5E2144",
+ "identity_token_hmac": "9ACC36A7C4AFA0D810E51768DB0D1280D3E7CE394C7B3CACA544D86D7ADBE685",
+ "key_seed": "AD90C78112CC93EF1D588CEC6114ECA8F949106D7498B6FF2738F60D4C39E3B0",
+ "ldt_key": "4082257057BF11A9A8EF7EF91862E420957C86ABC1DBAEE5FBABC3833001CE0B90D2096AD4E44B16C3F76DDEBC0FCF2C9E320039BB528ADA89AB806C5EA47FF5",
+ "plaintext": "486BBB7782B4C679B59D8791D1982985"
+ },
+ {
+ "adv_salt": "BF51",
+ "ciphertext": "FA4F4B54B39030D78185D71ADF35B70CDA4A67FC61FA30118DE4",
+ "hmac_key": "5FE98DB4539BA363111EC9E63F36ECF1E712B5EEC6C1555E75F47F34A66D385F",
+ "identity_token_hmac": "93202A0D36100FF814B3B120FC185C84EAC4AA81CE5EA1A17D2D73650B6B502E",
+ "key_seed": "2E0266AA823838A0C03D3FB4AD0A51F425379379067D7A0CD1650A1BFB2296DE",
+ "ldt_key": "58618E080BCAA76BB5A446A81F26C902F9BA6246C1C9D01F5FF563386BB143CE1896D9CB3C37A369896C12D8088488A3EC82369EF659294E62F69046CC82C8E6",
+ "plaintext": "74F37042ADA22F88D0D338DC74409A3E80E676BF0043C850C404"
+ },
+ {
+ "adv_salt": "D0FA",
+ "ciphertext": "89E8307036BE9F3443FD98A08B163015577770",
+ "hmac_key": "58432E0BDDB8747F3EDC68085087DA99E4F14798FC9F10B9ECDA092C8B00C7F2",
+ "identity_token_hmac": "726FFA6370BCC23E1DD2B80749CF9B5AC77668D189C46BC09086DDBE16F6B5BE",
+ "key_seed": "FA95613BC2BDC64E9C2D82C588162E1820BDB21BAF633D6FDC910FD281A53433",
+ "ldt_key": "FDCD5116C85434334874C24E5583304A5DD0ED401E9ACD37C2F67E61CA108D85389D37A59164AD103698855FBE92FE2C1BA44D9C7927B6463A4119C4113C24FB",
+ "plaintext": "F5B63533E7C12F59B7C7328B91771F20603B17"
+ },
+ {
+ "adv_salt": "CF97",
+ "ciphertext": "8E61F3D054491EEDC16B5D1D41E6AA288DDE01EA85949CAF",
+ "hmac_key": "F4F2F4D0CD50C49DA9C53544C4A55E28076F32042F47EE683E819D88D485B2A8",
+ "identity_token_hmac": "C45FDE6D91388B9C50CC240AF29105B8FCEE1AE8DA78279A44CCA55D942267E1",
+ "key_seed": "8C055A0D0A65E9E916540B1A644402C49BB52A8640AA754289DE2DE277D0A8F8",
+ "ldt_key": "6A9BDFCDA9110ABC983DF3439B4D1D01FC85065BBBF29B0D7B8AFDC533D38A2CFE97C2A9E68ECCD5CF4A69ED2CDF4B8B6D832E382AB9BF6DCEA17CF16717162F",
+ "plaintext": "96AFDA3D88FE3DB2E3DE4DF332146F867BE90D9C43D2C47B"
+ },
+ {
+ "adv_salt": "AC35",
+ "ciphertext": "3E928D6767AA90A759784D4D13FA6EE2EEAE2A35C4DCF0072E3A09D4F8",
+ "hmac_key": "DCD67593752AB14E87BB808300C6C66C91CB2FA25D62A6514F556564B331BED5",
+ "identity_token_hmac": "171F0532504142E41460159A7D1837DF2F850858DDCBC951EEDA65AC75C32A7F",
+ "key_seed": "882F96B6ADDB9D6FAB79F4E60C643AF05AD71F3B24E4ADB3CCB7161479BB0EE1",
+ "ldt_key": "31EA954EC47F5FDEE4D3938671AF77521788E73E090A6F2A66B67141055CD75DD33F4B8E42163B2F21C413ACAA498F03B74B936195D13042B76557C232960F22",
+ "plaintext": "CF7080DE671FF22EBF40D640BB936F353E82690498EA296F41F94D5C43"
+ },
+ {
+ "adv_salt": "B613",
+ "ciphertext": "CB3041FD5DA18A96FC80C8B1CEF3550B978C70DE98828C2B8386DB",
+ "hmac_key": "C80FB73025F878C94D9B1D0FBFBB0BCC2EC58E6B70CEDB0B6F5C8CAFC8B602A3",
+ "identity_token_hmac": "5401E6D4577B19A6EE3BE303522F6BCC479C3EF6ACC56D38A92BEDDB52939B6F",
+ "key_seed": "7DC4F44DE1798BE251D7E7A04C1DF966F9AB95F9FC5A49082748BA447DD15FBC",
+ "ldt_key": "440AB453063146EEC285BA78D07FDAFB4A16BB8B7B53BC280BC4E68CD941393049BD2A3CEE1E5BE355F45C0C6409EB1521D28C8E349D30F5C1B3288109BE10FE",
+ "plaintext": "AE6591893D5C744DA7994DF7739188EBEEFD817D1952236FE69AFE"
+ },
+ {
+ "adv_salt": "0379",
+ "ciphertext": "DB996FAC1234138C23FB41992A7EF0780E206F2F92ABC2525A",
+ "hmac_key": "C1A05129B34CA6A1AF456D8131EAADA8C726F094900B80BF6803459BBB124695",
+ "identity_token_hmac": "9E03313DF9976F77780B8FA9EDA1CFE507E7D2C0CF319B4B9742A2B1AE0924A1",
+ "key_seed": "EB0E8902818056408E2596C714D968A023C67BD616739F144DF890D14EA219D7",
+ "ldt_key": "546A7DD47F7AB24A55A980576921D52FE5E70CA73C562CB8748570D572F26DD288055E938AEC8D20D1CFD9BB0BF62315996F8F8B9E85DC15A9F28DCCA26FCA1A",
+ "plaintext": "71AD500B84B6FF0779906ED33191567FBCCE0D96EA06861654"
+ },
+ {
+ "adv_salt": "C35E",
+ "ciphertext": "EE37C54F29697110BA36D71664924192A6A325538B02404D456A8D887DA2",
+ "hmac_key": "6133AFD1126BE85311C0727EAA7F4D9BF1876A2A10E1AFA68788887471AF1A84",
+ "identity_token_hmac": "32DEEDCCB7BC8E996B9EAAEAE13E0E39E6780E45AE6FCAFF86EC06A7B7C69D5A",
+ "key_seed": "B5669B2D04A1DF129C5F9DB6615F7C441379A0390811D18BB37BD30BB68B4EFD",
+ "ldt_key": "5BA46FDC79A07DAE2FC23FDE2AFE925B452BAB69D2E590D47A59C653626AFCFEF901AD0930F8C3387948323C95CB81B978F16C2F3F60A728D9900CF70039934F",
+ "plaintext": "559CBD79CD4C31B6A5CC4D3D717D7DB5CCBE81A64ED6EBE45B51F56DA625"
+ },
+ {
+ "adv_salt": "7748",
+ "ciphertext": "0C5878CFC2569F410D9778D63267A2E7BAA9D500CFDB22A88C5CA0",
+ "hmac_key": "3EF5244431BAB0D7C71A946E911D744A73F03A99C738F026D332D0F0F5AFC078",
+ "identity_token_hmac": "388B67797237FE594F5C2EFCBF455495EB12079DBFBCC5BE6433B5F7CFA352CC",
+ "key_seed": "DCD1C168499570924F48A270C2A124C0D6CC98C25BE10BFF9B1501AE975AABD5",
+ "ldt_key": "9BAFF61B1CD7F9CAD69CD0BF62F990D994B73322D6850A71976377AF8FB4AB909369FAC038B9F4EA187B71F68F5E213C0A79E43D98F0F3F896F5BF98BD1CC147",
+ "plaintext": "C4C5FF757AF9F00815632AAABFB61B7E040D44651CAECA132DD898"
+ },
+ {
+ "adv_salt": "0072",
+ "ciphertext": "DCC53FF627D8610BB11C91E0B4B55EA42F3DD3A15CDC7A39D1",
+ "hmac_key": "76ACCBBA980D236DCC82B2722EFCCEAC1D100623F43ED538294EDC50A251DE20",
+ "identity_token_hmac": "C7521A6CD92D5245556D6FB7940D6EA4C55AFA6BF485E39C13CBE285B13A68F0",
+ "key_seed": "4BCA4BE4CD51155A91A05378B1F4A260DF52F4C97695BB9583F0A3DCDF79C5D0",
+ "ldt_key": "55292E8A6D7DB367CCD8F1C70CB5E45DAD137B88B885D3E16DA8C1267ED79AE5AFABDF8A95C6B919BCFF06A1D53D7E8BABD2C5190DF0379775D503FBFE65504D",
+ "plaintext": "0F3CC471872DD0DB7ECCB49FC121F6B82F580CF8A056B38B91"
+ },
+ {
+ "adv_salt": "92E8",
+ "ciphertext": "9D7A16FF9BA61DF8E9C334DFA7DC4CACDB8E",
+ "hmac_key": "5DBB733D2B294A0588CA8269C78B0DF193248F1C57162DBC2964E4555C7D7A43",
+ "identity_token_hmac": "07CDE87E1ABEF617ABC4656486ACACF06F374CB1398321616535931073C0A679",
+ "key_seed": "9838CB399FE0A326FADCBD72741BFC44D7E3931B8DD1548106FD6B9EB2E957AD",
+ "ldt_key": "6E24140E0ED82DD3E8F438E00F9FABF0980A8B19119F077A294AC077F4662FDEDB96ABB3E60C700E926595A96172C657DB31D98899F4DECADC200360BF658F0F",
+ "plaintext": "E82C53A487B1F338B2BC803C600BD9A02096"
+ },
+ {
+ "adv_salt": "9383",
+ "ciphertext": "4885E9C9E997A4B971DD11E3E77290A98D6D478124",
+ "hmac_key": "425B973660A913AD6CB0207E02AB0F345A89B508778E5416A01FC632D73ACB5D",
+ "identity_token_hmac": "1B0B1D1F74FAC903899A010DA97DCDA03EC4374730445056BD13AEB3A7CDC0CE",
+ "key_seed": "CDC7DA21484EA21B0BF595BBD199EC129A80575FB00AAA54AFD79B0EE7823439",
+ "ldt_key": "1D9FC4B353E8F42FFF9216EB74A63288266299972A2CF73AFC649A07967FA1096093CD34FE0A14B257AE04F616BE0729C3A782CFB1381A74EABAE8AE26A86644",
+ "plaintext": "3A4D5D67AC8DE93A7D44473D846090A8EE4EA0E875"
+ },
+ {
+ "adv_salt": "C210",
+ "ciphertext": "34DBDFB607BE2B7D28585DA18509B3E335D7979AD84C5F",
+ "hmac_key": "8B2575D2DBEE5987CADC9362900CE93ACDC0EC0BB7BC500BBE64EBAF50691E4A",
+ "identity_token_hmac": "761325227F7FE98C167C9E02CA7820151C70D304E6399356050D4355CCE99D62",
+ "key_seed": "758AB716E1EE6062613F2AF07F136225BA1965BA8899AC8F5CBF947C048B3624",
+ "ldt_key": "F72B9009F078D118108CF081507821DA62C4522FF2595679B4E73E003E0BDAAB8263EE64BC4C62FD0AEAE0F635C1B3757280618C337E1267726183C18AA2F86F",
+ "plaintext": "8034DA557861DEB71ACBFAF06B2363E2217A842A0282DC"
+ },
+ {
+ "adv_salt": "4932",
+ "ciphertext": "18DFA83D270515BA234A700C014DA5D6EB53A3F74F5AEEDDF9792B0904A3F5",
+ "hmac_key": "F9DA93ED8A58CEE5875A0A57BA00457441F1DD66114DA3835CE947F6683327C6",
+ "identity_token_hmac": "B61DB6EE722BDD44FFB11AC3187BA9F59D25B726D3C91963A1B92ED2E68CDE63",
+ "key_seed": "170AE50C4C3D672E225AA92AC5414FD3B7B5073073A61D50DF3E36044EF582AE",
+ "ldt_key": "766F6E50B231EC7692A9D5B1CC14A009B7AC6431A642E2CE219EEA3045E7EC45EA0943C823E372057962167DF8F57C916B3D0BB9F7D7B0C82EC80D4B947B54DF",
+ "plaintext": "116E13593BE0E8FEE54932013E43E984AA7FF6C8C0A825AED747D175BCF2B6"
+ },
+ {
+ "adv_salt": "ABB2",
+ "ciphertext": "C4075AE6956FCF87B34F8E4508C94BEB414AACC0A386D7",
+ "hmac_key": "8DAECC5753E47A2440DD3050160DC457F3AA0B6724AC5AD8277CC2AA4E9F422F",
+ "identity_token_hmac": "9556EC591F5D4B96CF0D27E081274D32EB6B842AEBC0F1440180B80E44415435",
+ "key_seed": "930D256D59C815A9511F10774CE147419026A620F262F5237FE1251B93505FD5",
+ "ldt_key": "20FB37DF50084F9267A8DC7A9B7BABC66611469FF26480807458619D63275A34C37836D07BE5D47CC03348A8A8BA96B41DD39A518B6E1AE4F44CADD7763DFEAE",
+ "plaintext": "4171C59B3CD3F41D44E18B6AB8876873DDCD25B9EBFFF1"
+ },
+ {
+ "adv_salt": "BC3C",
+ "ciphertext": "E7BA016C044E5F65A32B7858C27BE1DB4B97640D5AC8F81CA166AA2A4AA955",
+ "hmac_key": "75A59414DD7AEAAE0518BCBD74A24850094E980E79EC63BC9B52349AB8210D66",
+ "identity_token_hmac": "FFC4D1BFDC4FBC90E39B089B90246AA5D32AB0D6407E0D1A2B327FC01AD2DFDE",
+ "key_seed": "03CCD2A359286FB1D0EDE3D61A340A2EDF0A7A9CC46F0F65CC2249021D650C50",
+ "ldt_key": "E1D3E029AE94ACB98A5B0FA63AD3FE4D52118E7D0615540C34B3427F3BDE06390BC26CC5303DB52260CD46696E9A245AC48B4299D72AC6DF95056A53A4004A01",
+ "plaintext": "63CD8D1E2EB4A2919FA24DB11E57C3F649D39FA14952A3FB0874A73B0B0CCD"
}
]
diff --git a/nearby/presence/ldt_np_adv/src/lib.rs b/nearby/presence/ldt_np_adv/src/lib.rs
index 542d6a5..1d202f7 100644
--- a/nearby/presence/ldt_np_adv/src/lib.rs
+++ b/nearby/presence/ldt_np_adv/src/lib.rs
@@ -25,58 +25,104 @@ mod tests;
use array_view::ArrayView;
use core::fmt;
-use crypto_provider::{aes::BLOCK_SIZE, CryptoProvider};
-use ldt::{LdtDecryptCipher, LdtEncryptCipher, LdtError, Mix, Padder, Swap, XorPadder};
-use ldt_tbc::TweakableBlockCipher;
-use np_hkdf::{legacy_ldt_expanded_salt, NpHmacSha256Key, NpKeySeedHkdf};
+use core::ops;
+use crypto_provider::{aes::BLOCK_SIZE, CryptoProvider, CryptoRng, FromCryptoRng};
+use ldt::{LdtCipher, LdtDecryptCipher, LdtEncryptCipher, LdtError, Swap, XorPadder};
+use np_hkdf::{v0_ldt_expanded_salt, NpHmacSha256Key, NpKeySeedHkdf};
use xts_aes::XtsAes128;
/// Max LDT-XTS-AES data size: `(2 * AES block size) - 1`
pub const LDT_XTS_AES_MAX_LEN: usize = 31;
-/// Legacy (v0) format uses a 14-byte metadata key
-pub const NP_LEGACY_METADATA_KEY_LEN: usize = 14;
+/// V0 format uses a 14-byte identity token
+pub const V0_IDENTITY_TOKEN_LEN: usize = 14;
-/// The salt included in an NP advertisement.
+/// Max payload size once identity token prefix has been removed
+pub const NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN: usize = LDT_XTS_AES_MAX_LEN - V0_IDENTITY_TOKEN_LEN;
+
+/// Length of a V0 advertisement salt
+pub const V0_SALT_LEN: usize = 2;
+
+/// The salt included in a V0 NP advertisement.
/// LDT does not use an IV but can instead incorporate the 2 byte, regularly rotated,
/// salt from the advertisement payload and XOR it with the padded tweak data.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct LegacySalt {
+pub struct V0Salt {
/// Salt bytes extracted from the incoming NP advertisement
- bytes: [u8; 2],
+ bytes: [u8; V0_SALT_LEN],
}
-impl LegacySalt {
+impl V0Salt {
/// Returns the salt as a byte array.
- pub fn bytes(&self) -> &[u8; 2] {
- &self.bytes
+ pub fn bytes(&self) -> [u8; V0_SALT_LEN] {
+ self.bytes
}
}
-impl From<[u8; 2]> for LegacySalt {
- fn from(arr: [u8; 2]) -> Self {
+impl From<[u8; V0_SALT_LEN]> for V0Salt {
+ fn from(arr: [u8; V0_SALT_LEN]) -> Self {
Self { bytes: arr }
}
}
+/// "Short" 14-byte identity token type employed for V0
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub struct V0IdentityToken([u8; V0_IDENTITY_TOKEN_LEN]);
+
+impl V0IdentityToken {
+ /// Constructs a V0 identity token from raw bytes.
+ pub const fn new(value: [u8; V0_IDENTITY_TOKEN_LEN]) -> Self {
+ Self(value)
+ }
+ /// Returns the underlying bytes
+ pub fn bytes(&self) -> [u8; V0_IDENTITY_TOKEN_LEN] {
+ self.0
+ }
+
+ /// Returns the token bytes as a slice
+ pub fn as_slice(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl From<[u8; V0_IDENTITY_TOKEN_LEN]> for V0IdentityToken {
+ fn from(value: [u8; V0_IDENTITY_TOKEN_LEN]) -> Self {
+ Self(value)
+ }
+}
+
+impl AsRef<[u8]> for V0IdentityToken {
+ fn as_ref(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl FromCryptoRng for V0IdentityToken {
+ fn new_random<R: CryptoRng>(rng: &mut R) -> Self {
+ Self(rng.gen())
+ }
+}
+
/// [LdtEncryptCipher] parameterized for XTS-AES-128 with the [Swap] mix function.
-pub type LdtEncrypterXtsAes128<C> = LdtEncryptCipher<{ BLOCK_SIZE }, XtsAes128<C>, Swap>;
+pub type NpLdtEncryptCipher<C> = LdtEncryptCipher<{ BLOCK_SIZE }, XtsAes128<C>, Swap>;
+
+/// [LdtDecryptCipher] parameterized for XTS-AES-128 with the [Swap] mix function.
+type NpLdtDecryptCipher<C> = LdtDecryptCipher<{ BLOCK_SIZE }, XtsAes128<C>, Swap>;
-/// A Nearby Presence specific LDT decrypter which verifies the hmac tag of the given payload
-/// parameterized for XTS-AES-128 with the [Swap] mix function.
-pub type LdtNpAdvDecrypterXtsAes128<C> =
- LdtNpAdvDecrypter<{ BLOCK_SIZE }, LDT_XTS_AES_MAX_LEN, XtsAes128<C>, Swap, C>;
+/// Range of valid NP LDT message lengths for encryption/decryption, in a convenient form that
+/// doesn't need a CryptoProvider parameter.
+pub const VALID_INPUT_LEN: ops::Range<usize> = BLOCK_SIZE..BLOCK_SIZE * 2;
/// Build a Nearby Presence specific LDT XTS-AES-128 decrypter from a provided [NpKeySeedHkdf] and
/// metadata_key_hmac, with the [Swap] mix function
pub fn build_np_adv_decrypter_from_key_seed<C: CryptoProvider>(
key_seed: &NpKeySeedHkdf<C>,
- metadata_key_tag: [u8; 32],
-) -> LdtNpAdvDecrypterXtsAes128<C> {
+ identity_token_hmac: [u8; 32],
+) -> AuthenticatedNpLdtDecryptCipher<C> {
build_np_adv_decrypter(
- &key_seed.legacy_ldt_key(),
- metadata_key_tag,
- key_seed.legacy_metadata_key_hmac_key(),
+ &key_seed.v0_ldt_key(),
+ identity_token_hmac,
+ key_seed.v0_identity_token_hmac_key(),
)
}
@@ -84,28 +130,25 @@ pub fn build_np_adv_decrypter_from_key_seed<C: CryptoProvider>(
/// with the [Swap] mix function
pub fn build_np_adv_decrypter<C: CryptoProvider>(
ldt_key: &ldt::LdtKey<xts_aes::XtsAes128Key>,
- metadata_key_tag: [u8; 32],
- metadata_key_hmac_key: NpHmacSha256Key<C>,
-) -> LdtNpAdvDecrypterXtsAes128<C> {
- LdtNpAdvDecrypter {
- ldt_decrypter: LdtXtsAes128Decrypter::<C>::new(ldt_key),
- metadata_key_tag,
- metadata_key_hmac_key,
+ identity_token_hmac: [u8; 32],
+ identity_token_hmac_key: NpHmacSha256Key,
+) -> AuthenticatedNpLdtDecryptCipher<C> {
+ AuthenticatedNpLdtDecryptCipher {
+ ldt_decrypter: NpLdtDecryptCipher::<C>::new(ldt_key),
+ metadata_key_tag: identity_token_hmac,
+ metadata_key_hmac_key: identity_token_hmac_key,
}
}
-// [LdtDecryptCipher] parameterized for XTS-AES-128 with the [Swap] mix function.
-type LdtXtsAes128Decrypter<C> = LdtDecryptCipher<{ BLOCK_SIZE }, XtsAes128<C>, Swap>;
-
/// Decrypts and validates a NP legacy format advertisement encrypted with LDT.
///
/// A NP legacy advertisement will always be in the format of:
///
-/// Header (1 byte) | Identity DE header (1 byte) | Salt (2 bytes) | Identity (14 bytes) | repeated
+/// Header (1 byte) | Salt (2 bytes) | Identity token (14 bytes) | repeated
/// { DE header | DE payload }
///
/// Example:
-/// Header (1 byte) | Identity DE header (1 byte) | Salt (2 bytes) | Identity (14 bytes) |
+/// Header (1 byte) | Salt (2 bytes) | Identity token (14 bytes) |
/// Tx power DE header (1 byte) | Tx power (1 byte) | Action DE header(1 byte) | action (1-3 bytes)
///
/// The ciphertext bytes will always start with the Identity through the end of the
@@ -117,70 +160,61 @@ type LdtXtsAes128Decrypter<C> = LdtDecryptCipher<{ BLOCK_SIZE }, XtsAes128<C>, S
/// `O` is the max output size (must be 2 * B - 1).
/// `T` is the tweakable block cipher used by LDT.
/// `M` is the mix function used by LDT.
-pub struct LdtNpAdvDecrypter<
- const B: usize,
- const O: usize,
- T: TweakableBlockCipher<B>,
- M: Mix,
- C: CryptoProvider,
-> {
- ldt_decrypter: LdtDecryptCipher<B, T, M>,
+pub struct AuthenticatedNpLdtDecryptCipher<C: CryptoProvider> {
+ ldt_decrypter: LdtDecryptCipher<BLOCK_SIZE, XtsAes128<C>, Swap>,
metadata_key_tag: [u8; 32],
- metadata_key_hmac_key: NpHmacSha256Key<C>,
+ metadata_key_hmac_key: NpHmacSha256Key,
}
-impl<const B: usize, const O: usize, T, M, C> LdtNpAdvDecrypter<B, O, T, M, C>
-where
- T: TweakableBlockCipher<B>,
- M: Mix,
- C: CryptoProvider,
-{
+impl<C: CryptoProvider> AuthenticatedNpLdtDecryptCipher<C> {
/// Decrypt an advertisement payload using the provided padder.
///
- /// If the plaintext's metadata key matches this item's MAC, return the plaintext, otherwise `None`.
+ /// If the plaintext's identity token matches this decrypter's MAC, returns the verified identity
+ /// token and the remaining plaintext (the bytes after the identity token).
///
/// NOTE: because LDT acts as a PRP over the entire message, tampering with any bit scrambles
/// the whole message, so we can leverage the MAC on just the metadata key to ensure integrity
/// for the whole message.
///
/// # Errors
- /// - If `payload` has a length outside of `[B, B * 2)`.
+ /// - If `payload` has a length outside `[BLOCK_SIZE, BLOCK_SIZE * 2)`.
/// - If the decrypted plaintext fails its HMAC validation
- pub fn decrypt_and_verify<P: Padder<B, T>>(
+ #[allow(clippy::expect_used, clippy::indexing_slicing)]
+ pub fn decrypt_and_verify(
&self,
payload: &[u8],
- padder: &P,
- ) -> Result<ArrayView<u8, O>, LdtAdvDecryptError> {
- assert_eq!(B * 2 - 1, O); // should be compiled away
-
- // have to check length before passing to LDT to ensure copying into the buffer is safe
- if payload.len() < B || payload.len() > O {
- return Err(LdtAdvDecryptError::InvalidLength(payload.len()));
- }
-
+ padder: &XorPadder<BLOCK_SIZE>,
+ ) -> Result<
+ (V0IdentityToken, ArrayView<u8, NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN>),
+ LdtAdvDecryptError,
+ > {
// we copy to avoid exposing plaintext that hasn't been validated w/ hmac
- let mut buffer = [0_u8; O];
- buffer[..payload.len()].copy_from_slice(payload);
-
- #[allow(clippy::expect_used)]
- self.ldt_decrypter
- .decrypt(&mut buffer[..payload.len()], padder)
- .map_err(|e| match e {
- LdtError::InvalidLength(l) => LdtAdvDecryptError::InvalidLength(l),
- })
- .and_then(|_| {
- self.metadata_key_hmac_key
- .verify_hmac(&buffer[..NP_LEGACY_METADATA_KEY_LEN], self.metadata_key_tag)
- .map_err(|_| LdtAdvDecryptError::MacMismatch)
- .map(|_| {
- ArrayView::try_from_array(buffer, payload.len())
- .expect("this will never be hit because the length is validated above")
- })
- })
+ let mut buffer = [0_u8; LDT_XTS_AES_MAX_LEN];
+ let populated_buffer = buffer
+ .get_mut(..payload.len())
+ .ok_or(LdtAdvDecryptError::InvalidLength(payload.len()))?;
+ populated_buffer.copy_from_slice(payload);
+
+ self.ldt_decrypter.decrypt(populated_buffer, padder).map_err(|e| match e {
+ LdtError::InvalidLength(l) => LdtAdvDecryptError::InvalidLength(l),
+ })?;
+ // slice is safe since input is a valid LDT-XTS-AES len
+ let identity_token = &populated_buffer[..V0_IDENTITY_TOKEN_LEN];
+ self.metadata_key_hmac_key
+ .verify_hmac::<C>(identity_token, self.metadata_key_tag)
+ .map_err(|_| LdtAdvDecryptError::MacMismatch)?;
+
+ let token_arr: [u8; V0_IDENTITY_TOKEN_LEN] =
+ identity_token.try_into().expect("Length verified above");
+ Ok((
+ token_arr.into(),
+ ArrayView::try_from_slice(&buffer[V0_IDENTITY_TOKEN_LEN..payload.len()])
+ .expect("Buffer len less token len is the max output len"),
+ ))
}
}
-/// Errors that can occur during [LdtNpAdvDecrypter::decrypt_and_verify].
+/// Errors that can occur during [AuthenticatedNpLdtDecryptCipher::decrypt_and_verify].
#[derive(Debug, PartialEq, Eq)]
pub enum LdtAdvDecryptError {
/// The ciphertext data was an invalid length.
@@ -199,9 +233,8 @@ impl fmt::Display for LdtAdvDecryptError {
}
}
}
+
/// Build a XorPadder by HKDFing the NP advertisement salt
-pub fn salt_padder<const B: usize, C: CryptoProvider>(salt: LegacySalt) -> XorPadder<{ B }> {
- // Assuming that the tweak size == the block size here, which it is for XTS.
- // If that's ever not true, yet another generic parameter will address that.
- XorPadder::from(legacy_ldt_expanded_salt::<B, C>(&salt.bytes))
+pub fn salt_padder<C: CryptoProvider>(salt: V0Salt) -> XorPadder<BLOCK_SIZE> {
+ XorPadder::from(v0_ldt_expanded_salt::<C>(&salt.bytes))
}
diff --git a/nearby/presence/ldt_np_adv/src/np_adv_test_vectors.rs b/nearby/presence/ldt_np_adv/src/np_adv_test_vectors.rs
index cf176dd..488858d 100644
--- a/nearby/presence/ldt_np_adv/src/np_adv_test_vectors.rs
+++ b/nearby/presence/ldt_np_adv/src/np_adv_test_vectors.rs
@@ -11,21 +11,23 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+
#![allow(clippy::indexing_slicing, clippy::unwrap_used, clippy::panic, clippy::expect_used)]
extern crate std;
+
use crate::{
- build_np_adv_decrypter_from_key_seed, salt_padder, LdtEncrypterXtsAes128, LegacySalt,
- NP_LEGACY_METADATA_KEY_LEN,
+ build_np_adv_decrypter_from_key_seed, salt_padder, NpLdtEncryptCipher, V0Salt,
+ V0_IDENTITY_TOKEN_LEN,
};
use anyhow::anyhow;
use crypto_provider_default::CryptoProviderImpl;
-use rand::Rng;
-use rand_ext::{random_vec_rc, seeded_rng};
+use ldt::LdtCipher;
use serde_json::json;
use std::vec::Vec;
use std::{fs, io::Read as _, println, string::String};
use test_helper::{extract_key_array, extract_key_vec};
+use test_vector_hkdf::TestVectorHkdf;
#[test]
fn np_adv_test_vectors() -> Result<(), anyhow::Error> {
@@ -39,26 +41,26 @@ fn np_adv_test_vectors() -> Result<(), anyhow::Error> {
_ => return Err(anyhow!("bad json")),
};
- assert_eq!(1000, test_cases.len());
+ assert_eq!(100, test_cases.len());
for tc in test_cases {
let key_seed = extract_key_array::<32>(&tc, "key_seed");
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let ldt_key = hkdf.legacy_ldt_key();
- let hmac_key = hkdf.legacy_metadata_key_hmac_key();
+ let ldt_key = hkdf.v0_ldt_key();
+ let hmac_key = hkdf.v0_identity_token_hmac_key();
assert_eq!(&extract_key_vec(&tc, "ldt_key"), &ldt_key.as_concatenated());
assert_eq!(&extract_key_vec(&tc, "hmac_key"), &hmac_key.as_bytes());
- let salt = LegacySalt::from(extract_key_array(&tc, "adv_salt"));
- let padder = salt_padder::<16, CryptoProviderImpl>(salt);
+ let salt = V0Salt::from(extract_key_array(&tc, "adv_salt"));
+ let padder = salt_padder::<CryptoProviderImpl>(salt);
- let ldt_enc = LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&ldt_key);
+ let ldt_enc = NpLdtEncryptCipher::<CryptoProviderImpl>::new(&ldt_key);
let decrypter = build_np_adv_decrypter_from_key_seed(
&hkdf,
- extract_key_array(&tc, "metadata_key_hmac"),
+ extract_key_array(&tc, "identity_token_hmac"),
);
let plaintext = extract_key_vec(&tc, "plaintext");
@@ -69,9 +71,11 @@ fn np_adv_test_vectors() -> Result<(), anyhow::Error> {
assert_eq!(ciphertext, ciphertext_actual);
- let plaintext_actual = decrypter.decrypt_and_verify(&ciphertext, &padder).unwrap();
+ let (identity_token, plaintext_actual) =
+ decrypter.decrypt_and_verify(&ciphertext, &padder).unwrap();
- assert_eq!(&plaintext, plaintext_actual.as_slice());
+ assert_eq!(&plaintext[..V0_IDENTITY_TOKEN_LEN], identity_token.as_slice());
+ assert_eq!(&plaintext[V0_IDENTITY_TOKEN_LEN..], plaintext_actual.as_slice());
}
Ok(())
@@ -81,23 +85,34 @@ fn np_adv_test_vectors() -> Result<(), anyhow::Error> {
#[ignore]
#[test]
fn gen_test_vectors() {
- let mut rng = seeded_rng();
-
let mut array = Vec::<serde_json::Value>::new();
- for _ in 0..1_000 {
- let len =
- rng.gen_range(crypto_provider::aes::BLOCK_SIZE..crypto_provider::aes::BLOCK_SIZE * 2);
- let plaintext = random_vec_rc(&mut rng, len);
- let key_seed: [u8; 32] = rng.gen();
+ for i in 0_u32..100 {
+ let test_vector_seed_hkdf = TestVectorHkdf::<CryptoProviderImpl>::new(
+ "NP LDT test vectors Y7yJTRXy+8saKiYSu76/TbabkAFhK55zF8QutxcQlGc",
+ &i.to_be_bytes(),
+ );
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let ldt_key = hkdf.legacy_ldt_key();
- let hmac_key = hkdf.legacy_metadata_key_hmac_key();
- let hmac: [u8; 32] = hmac_key.calculate_hmac(&plaintext[..NP_LEGACY_METADATA_KEY_LEN]);
- let ldt_enc = LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&ldt_key);
+ let len = test_vector_seed_hkdf
+ .derive_range_element(
+ "plaintext len",
+ crypto_provider::aes::BLOCK_SIZE as u64
+ ..=crypto_provider::aes::BLOCK_SIZE as u64 * 2 - 1,
+ )
+ .try_into()
+ .unwrap();
+ let plaintext = test_vector_seed_hkdf.derive_vec("plaintext", len);
+ let key_seed: [u8; 32] = test_vector_seed_hkdf.derive_array("key seed");
- let padder = salt_padder::<16, CryptoProviderImpl>(LegacySalt::from(rng.gen::<[u8; 2]>()));
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let ldt_key = hkdf.v0_ldt_key();
+ let hmac_key = hkdf.v0_identity_token_hmac_key();
+ let hmac: [u8; 32] =
+ hmac_key.calculate_hmac::<CryptoProviderImpl>(&plaintext[..V0_IDENTITY_TOKEN_LEN]);
+ let ldt_enc = NpLdtEncryptCipher::<CryptoProviderImpl>::new(&ldt_key);
+
+ let salt = V0Salt::from(test_vector_seed_hkdf.derive_array("salt"));
+ let padder = salt_padder::<CryptoProviderImpl>(salt);
let mut ciphertext = plaintext.clone();
ldt_enc.encrypt(&mut ciphertext[..], &padder).unwrap();
@@ -105,12 +120,13 @@ fn gen_test_vectors() {
"key_seed": hex::encode_upper(key_seed),
"ldt_key": hex::encode_upper(ldt_key.as_concatenated()),
"hmac_key": hex::encode_upper(hmac_key.as_bytes()),
- "adv_salt": hex::encode_upper(rng.gen::<[u8; 2]>()),
+ "adv_salt": hex::encode_upper(salt.bytes()),
"plaintext": hex::encode_upper(plaintext),
"ciphertext": hex::encode_upper(ciphertext),
- "metadata_key_hmac": hex::encode_upper(hmac),
+ "identity_token_hmac": hex::encode_upper(hmac),
}));
}
println!("{}", serde_json::ser::to_string_pretty(&array).unwrap());
+ panic!("Don't leave this test enabled. Meanwhile, enjoy the text output above.");
}
diff --git a/nearby/presence/ldt_np_adv/src/tests.rs b/nearby/presence/ldt_np_adv/src/tests.rs
index 30bc7b6..a731762 100644
--- a/nearby/presence/ldt_np_adv/src/tests.rs
+++ b/nearby/presence/ldt_np_adv/src/tests.rs
@@ -16,18 +16,23 @@
extern crate alloc;
use crate::{
- build_np_adv_decrypter_from_key_seed, salt_padder, LdtAdvDecryptError, LdtEncrypterXtsAes128,
- LdtNpAdvDecrypterXtsAes128, LdtXtsAes128Decrypter, LegacySalt, LDT_XTS_AES_MAX_LEN,
- NP_LEGACY_METADATA_KEY_LEN,
+ build_np_adv_decrypter_from_key_seed, salt_padder, AuthenticatedNpLdtDecryptCipher,
+ LdtAdvDecryptError, NpLdtDecryptCipher, NpLdtEncryptCipher, V0IdentityToken, V0Salt,
+ LDT_XTS_AES_MAX_LEN, V0_IDENTITY_TOKEN_LEN,
};
use alloc::vec::Vec;
use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
-use ldt::{DefaultPadder, LdtError, LdtKey, XorPadder};
+use ldt::{DefaultPadder, LdtCipher, LdtError, LdtKey, XorPadder};
use np_hkdf::NpKeySeedHkdf;
use rand::Rng;
use rand_ext::{random_bytes, random_vec, seeded_rng};
+extern crate std;
+
+use crypto_provider::aes::BLOCK_SIZE;
+use std::vec;
+
#[test]
fn decrypt_matches_correct_ciphertext() {
let mut rng = CryptoRng::new();
@@ -35,10 +40,11 @@ fn decrypt_matches_correct_ciphertext() {
let test_state = make_test_components::<CryptoProviderImpl>(&mut rng);
let cipher = build_np_adv_decrypter_from_key_seed(&test_state.hkdf, test_state.hmac);
- let decrypted =
+ let (token, plaintext) =
cipher.decrypt_and_verify(&test_state.ciphertext, &test_state.padder).unwrap();
- assert_eq!(&test_state.plaintext, decrypted.as_ref());
+ assert_eq!(test_state.identity_token, token);
+ assert_eq!(&test_state.remaining_plaintext, plaintext.as_ref());
}
}
@@ -85,7 +91,7 @@ fn encrypt_works() {
let cipher = test_state.ldt_enc;
- let mut plaintext_copy = test_state.plaintext.clone();
+ let mut plaintext_copy = test_state.all_plaintext.clone();
cipher.encrypt(&mut plaintext_copy[..], &test_state.padder).unwrap();
assert_eq!(test_state.ciphertext, plaintext_copy);
@@ -96,83 +102,146 @@ fn encrypt_works() {
#[allow(deprecated)]
fn encrypt_too_short_err() {
let ldt_enc =
- LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&LdtKey::from_concatenated(&[0; 64]));
+ NpLdtEncryptCipher::<CryptoProviderImpl>::new(&LdtKey::from_concatenated(&[0; 64]));
- let mut payload = [0; 7];
- assert_eq!(Err(LdtError::InvalidLength(7)), ldt_enc.encrypt(&mut payload, &DefaultPadder));
+ let mut payload = vec![0; BLOCK_SIZE - 1];
+ assert_eq!(
+ Err(LdtError::InvalidLength(BLOCK_SIZE - 1)),
+ ldt_enc.encrypt(&mut payload, &DefaultPadder)
+ );
}
#[test]
#[allow(deprecated)]
fn encrypt_too_long_err() {
let ldt_enc =
- LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&LdtKey::from_concatenated(&[0; 64]));
+ NpLdtEncryptCipher::<CryptoProviderImpl>::new(&LdtKey::from_concatenated(&[0; 64]));
- let mut payload = [0; 40];
- assert_eq!(Err(LdtError::InvalidLength(40)), ldt_enc.encrypt(&mut payload, &DefaultPadder));
+ let mut payload = vec![0; BLOCK_SIZE * 2];
+ assert_eq!(
+ Err(LdtError::InvalidLength(BLOCK_SIZE * 2)),
+ ldt_enc.encrypt(&mut payload, &DefaultPadder)
+ );
}
#[test]
fn decrypt_too_short_err() {
- let adv_cipher = LdtNpAdvDecrypterXtsAes128 {
- ldt_decrypter: LdtXtsAes128Decrypter::<CryptoProviderImpl>::new(
- &LdtKey::from_concatenated(&[0; 64]),
- ),
- metadata_key_tag: [0; 32],
- metadata_key_hmac_key: np_hkdf::NpHmacSha256Key::<CryptoProviderImpl>::from([0; 32]),
- };
-
- let payload = [0; 7];
+ let adv_cipher: AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl> =
+ AuthenticatedNpLdtDecryptCipher {
+ ldt_decrypter: NpLdtDecryptCipher::<CryptoProviderImpl>::new(
+ &LdtKey::from_concatenated(&[0; 64]),
+ ),
+ metadata_key_tag: [0; 32],
+ metadata_key_hmac_key: np_hkdf::NpHmacSha256Key::from([0; 32]),
+ };
+
+ // 1 byte less than a full block
+ let payload = vec![0; BLOCK_SIZE - 1];
assert_eq!(
- Err(LdtAdvDecryptError::InvalidLength(7)),
- adv_cipher.decrypt_and_verify(&payload, &DefaultPadder)
+ Err(LdtAdvDecryptError::InvalidLength(BLOCK_SIZE - 1)),
+ adv_cipher.decrypt_and_verify(&payload, &XorPadder::from([0_u8; BLOCK_SIZE]))
);
}
#[test]
fn decrypt_too_long_err() {
- let adv_cipher = LdtNpAdvDecrypterXtsAes128 {
- ldt_decrypter: LdtXtsAes128Decrypter::<CryptoProviderImpl>::new(
- &LdtKey::from_concatenated(&[0; 64]),
- ),
- metadata_key_tag: [0; 32],
- metadata_key_hmac_key: np_hkdf::NpHmacSha256Key::<CryptoProviderImpl>::from([0; 32]),
- };
-
- let payload = [0; 40];
+ let adv_cipher: AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl> =
+ AuthenticatedNpLdtDecryptCipher {
+ ldt_decrypter: NpLdtDecryptCipher::<CryptoProviderImpl>::new(
+ &LdtKey::from_concatenated(&[0; 64]),
+ ),
+ metadata_key_tag: [0; 32],
+ metadata_key_hmac_key: np_hkdf::NpHmacSha256Key::from([0; 32]),
+ };
+
+ // 2 full blocks
+ let payload = [0; BLOCK_SIZE * 2];
assert_eq!(
- Err(LdtAdvDecryptError::InvalidLength(40)),
- adv_cipher.decrypt_and_verify(&payload, &DefaultPadder)
+ Err(LdtAdvDecryptError::InvalidLength(BLOCK_SIZE * 2)),
+ adv_cipher.decrypt_and_verify(&payload, &XorPadder::from([0; BLOCK_SIZE]))
);
}
+#[test]
+fn verify_input_len_const() {
+ // make sure it matches the authoritative upstream
+ assert_eq!(crate::VALID_INPUT_LEN, NpLdtEncryptCipher::<CryptoProviderImpl>::VALID_INPUT_LEN);
+}
+
+#[test]
+fn ldt_ffi_test_scenario() {
+ // used in ldt_ffi_tests.cc and LdtNpJniTests
+ let key_seed: [u8; 32] = [
+ 204, 219, 36, 137, 233, 252, 172, 66, 179, 147, 72, 184, 148, 30, 209, 154, 29, 54, 14,
+ 117, 224, 152, 200, 193, 94, 107, 28, 194, 182, 32, 205, 57,
+ ];
+
+ let salt: V0Salt = [12, 15].into();
+ let plaintext = [
+ 205_u8, 104, 63, 225, 161, 209, 248, 70, 84, 61, 10, 19, 212, 174, 164, 0, 64, 200, 214,
+ 123,
+ ];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let ldt_key = hkdf.v0_ldt_key();
+ let identity_token_hmac = hkdf
+ .v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&plaintext[..V0_IDENTITY_TOKEN_LEN]);
+ let decrypter = build_np_adv_decrypter_from_key_seed(&hkdf, identity_token_hmac);
+
+ let padder = salt_padder::<CryptoProviderImpl>(salt);
+ let mut ciphertext = plaintext;
+ NpLdtEncryptCipher::<CryptoProviderImpl>::new(&ldt_key)
+ .encrypt(&mut ciphertext, &padder)
+ .unwrap();
+
+ let (token, contents) = decrypter.decrypt_and_verify(&ciphertext, &padder).unwrap();
+ assert_eq!(&plaintext[..V0_IDENTITY_TOKEN_LEN], token.as_slice());
+ assert_eq!(&plaintext[V0_IDENTITY_TOKEN_LEN..], contents.as_slice());
+
+ // Uncomment if updating the FFI test
+ // {
+ // use std::println;
+ // use test_helper::hex_bytes;
+ // println!("Key seed:\n{}\n{}", hex_bytes(&key_seed), hex::encode_upper(&key_seed));
+ // println!("Identity token HMAC:\n{}\n{}", hex_bytes(&identity_token_hmac), hex::encode_upper(&identity_token_hmac));
+ // println!("Plaintext:\n{}\n{}", hex_bytes(&plaintext), hex::encode_upper(&plaintext));
+ // println!("Salt:\n{}\n{}", hex_bytes(salt.bytes()), hex::encode_upper(salt.bytes()));
+ // println!("Ciphertext:\n{}\n{}", hex_bytes(&ciphertext), hex::encode_upper(&ciphertext));
+ // panic!();
+ // }
+}
+
/// Returns (plaintext, ciphertext, padder, hmac key, MAC, ldt)
fn make_test_components<C: crypto_provider::CryptoProvider>(
rng: &mut C::CryptoRng,
) -> LdtAdvTestComponents<C> {
// [1, 2) blocks of XTS-AES
let mut rc_rng = seeded_rng();
- let payload_len = rc_rng
- .gen_range(crypto_provider::aes::BLOCK_SIZE..=(crypto_provider::aes::BLOCK_SIZE * 2 - 1));
- let plaintext = random_vec::<C>(rng, payload_len);
+ let payload_len = rc_rng.gen_range(BLOCK_SIZE..=(BLOCK_SIZE * 2 - 1));
+ let all_plaintext = random_vec::<C>(rng, payload_len);
- let salt = LegacySalt { bytes: random_bytes::<2, C>(rng) };
- let padder = salt_padder::<16, C>(salt);
+ let salt = V0Salt { bytes: random_bytes::<2, C>(rng) };
+ let padder = salt_padder::<C>(salt);
let key_seed: [u8; 32] = random_bytes::<32, C>(rng);
let hkdf = np_hkdf::NpKeySeedHkdf::new(&key_seed);
- let ldt_key = hkdf.legacy_ldt_key();
- let hmac_key = hkdf.legacy_metadata_key_hmac_key();
- let hmac: [u8; 32] = hmac_key.calculate_hmac(&plaintext[..NP_LEGACY_METADATA_KEY_LEN]);
+ let ldt_key = hkdf.v0_ldt_key();
+ let hmac_key = hkdf.v0_identity_token_hmac_key();
+ let identity_token: [u8; V0_IDENTITY_TOKEN_LEN] =
+ all_plaintext[..V0_IDENTITY_TOKEN_LEN].try_into().unwrap();
+ let hmac: [u8; 32] = hmac_key.calculate_hmac::<C>(&identity_token);
- let ldt_enc = LdtEncrypterXtsAes128::<C>::new(&ldt_key);
+ let ldt_enc = NpLdtEncryptCipher::<C>::new(&ldt_key);
let mut ciphertext = [0_u8; LDT_XTS_AES_MAX_LEN];
- ciphertext[..plaintext.len()].copy_from_slice(&plaintext);
- ldt_enc.encrypt(&mut ciphertext[..plaintext.len()], &padder).unwrap();
-
+ ciphertext[..all_plaintext.len()].copy_from_slice(&all_plaintext);
+ ldt_enc.encrypt(&mut ciphertext[..all_plaintext.len()], &padder).unwrap();
+ let remaining_plaintext = all_plaintext[V0_IDENTITY_TOKEN_LEN..].to_vec();
LdtAdvTestComponents {
- plaintext,
+ all_plaintext,
+ identity_token: identity_token.into(),
+ remaining_plaintext,
ciphertext: ciphertext[..payload_len].to_vec(),
padder,
hmac,
@@ -182,10 +251,38 @@ fn make_test_components<C: crypto_provider::CryptoProvider>(
}
struct LdtAdvTestComponents<C: CryptoProvider> {
- plaintext: Vec<u8>,
+ all_plaintext: Vec<u8>,
+ identity_token: V0IdentityToken,
+ /// Plaintext after the identity token
+ remaining_plaintext: Vec<u8>,
ciphertext: Vec<u8>,
- padder: XorPadder<{ crypto_provider::aes::BLOCK_SIZE }>,
+ padder: XorPadder<{ BLOCK_SIZE }>,
hmac: [u8; 32],
- ldt_enc: LdtEncrypterXtsAes128<C>,
+ ldt_enc: NpLdtEncryptCipher<C>,
hkdf: NpKeySeedHkdf<C>,
}
+
+mod coverage_gaming {
+ extern crate std;
+
+ use crate::{V0IdentityToken, V0_IDENTITY_TOKEN_LEN};
+ use crypto_provider::{CryptoProvider, CryptoRng};
+ use crypto_provider_default::CryptoProviderImpl;
+ use std::{collections, format};
+
+ #[test]
+ fn legacy_identity_token() {
+ let token = V0IdentityToken::from([0; V0_IDENTITY_TOKEN_LEN]);
+ // debug
+ let _ = format!("{:?}", token);
+ // hash
+ let _ = collections::HashSet::new().insert(&token);
+ // bytes
+ assert_eq!(token.0, token.bytes());
+ // AsRef
+ assert_eq!(token.0.as_slice(), token.as_ref());
+ // FromCryptoRng
+ let mut rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
+ let _: V0IdentityToken = rng.gen();
+ }
+}
diff --git a/nearby/presence/ldt_np_adv_ffi/.cargo/config.toml b/nearby/presence/ldt_np_adv_ffi/.cargo/config.toml
deleted file mode 100644
index 430406b..0000000
--- a/nearby/presence/ldt_np_adv_ffi/.cargo/config.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[target.aarch64-apple-darwin]
-rustflags = [
- "-lSystem",
-]
-
-[target.x86_64-apple-darwin]
-rustflags = [
- "-lSystem",
-] \ No newline at end of file
diff --git a/nearby/presence/ldt_np_adv_ffi/Cargo.lock b/nearby/presence/ldt_np_adv_ffi/Cargo.lock
deleted file mode 100644
index d8664ea..0000000
--- a/nearby/presence/ldt_np_adv_ffi/Cargo.lock
+++ /dev/null
@@ -1,947 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aead"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
-dependencies = [
- "bytes",
- "crypto-common",
- "generic-array",
-]
-
-[[package]]
-name = "aes"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
-dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures",
-]
-
-[[package]]
-name = "aes-gcm"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
-dependencies = [
- "aead",
- "aes",
- "cipher",
- "ctr",
- "ghash",
- "subtle",
-]
-
-[[package]]
-name = "aes-gcm-siv"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
-dependencies = [
- "aead",
- "aes",
- "cipher",
- "ctr",
- "polyval",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "aliasable"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
-
-[[package]]
-name = "array_ref"
-version = "0.1.0"
-
-[[package]]
-name = "array_view"
-version = "0.1.0"
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "base16ct"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
-
-[[package]]
-name = "base64ct"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
-
-[[package]]
-name = "bitflags"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "bssl-crypto"
-version = "0.1.0"
-dependencies = [
- "bssl-sys",
-]
-
-[[package]]
-name = "bssl-sys"
-version = "0.1.0"
-
-[[package]]
-name = "bytes"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
-
-[[package]]
-name = "cbc"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
-dependencies = [
- "cipher",
-]
-
-[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "cipher"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
-dependencies = [
- "crypto-common",
- "inout",
-]
-
-[[package]]
-name = "const-oid"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6340df57935414636969091153f35f68d9f00bbc8fb4a9c6054706c213e6c6bc"
-
-[[package]]
-name = "cpufeatures"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crypto-bigint"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
-dependencies = [
- "generic-array",
- "rand_core",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "rand_core",
- "typenum",
-]
-
-[[package]]
-name = "crypto_provider"
-version = "0.1.0"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "crypto_provider_boringssl"
-version = "0.1.0"
-dependencies = [
- "bssl-crypto",
- "crypto_provider",
-]
-
-[[package]]
-name = "crypto_provider_openssl"
-version = "0.1.0"
-dependencies = [
- "cfg-if",
- "crypto_provider",
- "crypto_provider_stubs",
- "openssl",
- "ouroboros",
-]
-
-[[package]]
-name = "crypto_provider_rustcrypto"
-version = "0.1.0"
-dependencies = [
- "aead",
- "aes",
- "aes-gcm",
- "aes-gcm-siv",
- "cbc",
- "cfg-if",
- "crypto_provider",
- "ctr",
- "ed25519-dalek",
- "hkdf",
- "hmac",
- "p256",
- "rand",
- "rand_chacha",
- "rand_core",
- "sec1",
- "sha2",
- "subtle",
- "x25519-dalek",
-]
-
-[[package]]
-name = "crypto_provider_stubs"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
-]
-
-[[package]]
-name = "ctr"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
-dependencies = [
- "cipher",
-]
-
-[[package]]
-name = "curve25519-dalek"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "curve25519-dalek-derive",
- "digest",
- "fiat-crypto",
- "platforms",
- "rustc_version",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "curve25519-dalek-derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.22",
-]
-
-[[package]]
-name = "der"
-version = "0.7.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
-dependencies = [
- "const-oid",
- "zeroize",
-]
-
-[[package]]
-name = "digest"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
-dependencies = [
- "block-buffer",
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "ed25519"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
-dependencies = [
- "pkcs8",
- "signature",
-]
-
-[[package]]
-name = "ed25519-dalek"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
-dependencies = [
- "curve25519-dalek",
- "ed25519",
- "rand_core",
- "serde",
- "sha2",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "elliptic-curve"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
-dependencies = [
- "base16ct",
- "crypto-bigint",
- "digest",
- "ff",
- "generic-array",
- "group",
- "hkdf",
- "rand_core",
- "sec1",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "ff"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
-dependencies = [
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "fiat-crypto"
-version = "0.1.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
-
-[[package]]
-name = "foreign-types"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-dependencies = [
- "foreign-types-shared",
-]
-
-[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
- "zeroize",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "ghash"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
-dependencies = [
- "opaque-debug",
- "polyval",
-]
-
-[[package]]
-name = "group"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
-dependencies = [
- "ff",
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "hkdf"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
-dependencies = [
- "hmac",
-]
-
-[[package]]
-name = "hmac"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "inout"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
-dependencies = [
- "block-padding",
- "generic-array",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-dependencies = [
- "spin 0.5.2",
-]
-
-[[package]]
-name = "ldt"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
- "ldt_tbc",
-]
-
-[[package]]
-name = "ldt_np_adv"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "ldt",
- "ldt_tbc",
- "np_hkdf",
- "xts_aes",
-]
-
-[[package]]
-name = "ldt_np_adv_ffi"
-version = "0.1.0"
-dependencies = [
- "cfg-if",
- "crypto_provider",
- "crypto_provider_boringssl",
- "crypto_provider_openssl",
- "crypto_provider_rustcrypto",
- "lazy_static",
- "ldt",
- "ldt_np_adv",
- "libc_alloc",
- "np_hkdf",
- "panic-abort",
- "rand",
- "spin 0.9.8",
-]
-
-[[package]]
-name = "ldt_tbc"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.147"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
-
-[[package]]
-name = "libc_alloc"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a090348b66d90d8507e30f0d2bd88e5a5c454bd1733fc6d617cbc3471bf69ea"
-
-[[package]]
-name = "lock_api"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "np_hkdf"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
- "ldt",
- "xts_aes",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
-
-[[package]]
-name = "opaque-debug"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
-
-[[package]]
-name = "openssl"
-version = "0.10.62"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
-dependencies = [
- "bitflags",
- "cfg-if",
- "foreign-types",
- "libc",
- "once_cell",
- "openssl-macros",
- "openssl-sys",
-]
-
-[[package]]
-name = "openssl-macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.22",
-]
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.98"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
- "vcpkg",
-]
-
-[[package]]
-name = "ouroboros"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d813b7b31a82efae94bd30ffaac09aec85efc18db2d5ec3aead1a220ee954351"
-dependencies = [
- "aliasable",
- "ouroboros_macro",
- "static_assertions",
-]
-
-[[package]]
-name = "ouroboros_macro"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a56f651b4dd45ae3ac3d260ced32eaf0620cddaae5f26c69b554a9016594726"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 2.0.22",
-]
-
-[[package]]
-name = "p256"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
-dependencies = [
- "elliptic-curve",
- "primeorder",
-]
-
-[[package]]
-name = "panic-abort"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e20e6499bbbc412f280b04a42346b356c6fa0753d5fd22b7bd752ff34c778ee"
-
-[[package]]
-name = "pkcs8"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
-dependencies = [
- "der",
- "spki",
-]
-
-[[package]]
-name = "pkg-config"
-version = "0.3.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
-
-[[package]]
-name = "platforms"
-version = "3.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
-
-[[package]]
-name = "polyval"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "opaque-debug",
- "universal-hash",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
-
-[[package]]
-name = "primeorder"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
-dependencies = [
- "elliptic-curve",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rustc_version"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "sec1"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
-dependencies = [
- "base16ct",
- "der",
- "generic-array",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
-
-[[package]]
-name = "serde"
-version = "1.0.164"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
-
-[[package]]
-name = "sha2"
-version = "0.10.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "signature"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "spin"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
-dependencies = [
- "lock_api",
-]
-
-[[package]]
-name = "spki"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
-dependencies = [
- "base64ct",
- "der",
-]
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "subtle"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
-
-[[package]]
-name = "typenum"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
-
-[[package]]
-name = "universal-hash"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
-dependencies = [
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "vcpkg"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
-
-[[package]]
-name = "version_check"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "x25519-dalek"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
-dependencies = [
- "curve25519-dalek",
- "rand_core",
-]
-
-[[package]]
-name = "xts_aes"
-version = "0.1.0"
-dependencies = [
- "array_ref",
- "crypto_provider",
- "ldt_tbc",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
diff --git a/nearby/presence/ldt_np_adv_ffi/Cargo.toml b/nearby/presence/ldt_np_adv_ffi/Cargo.toml
index 829f932..fdc5501 100644
--- a/nearby/presence/ldt_np_adv_ffi/Cargo.toml
+++ b/nearby/presence/ldt_np_adv_ffi/Cargo.toml
@@ -5,41 +5,24 @@ edition = "2021"
publish = false
[dependencies]
-crypto_provider = { path = "../../crypto/crypto_provider" }
-crypto_provider_openssl = { path = "../../crypto/crypto_provider_openssl", optional = true }
-crypto_provider_rustcrypto = { path = "../../crypto/crypto_provider_rustcrypto", optional = true }
-crypto_provider_boringssl = { path = "../../crypto/crypto_provider_boringssl", optional = true }
-ldt = { path = "../ldt" }
-ldt_np_adv = { path = "../ldt_np_adv" }
-np_hkdf = { path = "../np_hkdf" }
+crypto_provider_default.workspace = true
+crypto_provider.workspace = true
+ldt.workspace = true
+ldt_np_adv.workspace = true
+np_hkdf.workspace = true
-cfg-if = "1.0.0"
-lazy_static = { version = "1.4.0" }
-
-# no_std only deps
-libc_alloc = { version = "1.0.4", optional = true }
-panic-abort = { version = "0.3.2", optional = true }
-spin = { version = "0.9.8", optional = true }
+cfg-if.workspace = true
+lazy_static.workspace = true
+spin = { workspace = true, optional = true }
[dev-dependencies]
-rand = "0.8.5"
+rand.workspace = true
[lib]
# boringssl and bssl-sys are built as a static lib, so we need to as well
crate-type = ["staticlib"]
[features]
-# by default we support no_std and use rustcrypto primitives
-default = ["lazy_static/spin_no_std", "spin", "libc_alloc", "panic-abort", "crypto_provider_rustcrypto"]
-std = ["crypto_provider_rustcrypto", "crypto_provider_rustcrypto/std"]
-openssl = ["crypto_provider_openssl"]
-boringssl = ["crypto_provider_boringssl"]
-
-[profile.release-min-size]
-inherits = "release"
-panic = "abort"
-codegen-units = 1
-lto = true
-# z optimizes for size
-opt-level = "z"
-strip = true
+default = ["lazy_static/spin_no_std", "spin", "crypto_provider_default/rustcrypto"]
+std = ["crypto_provider_default/std", "crypto_provider_default/rustcrypto"]
+boringssl = ["crypto_provider_default/boringssl"] \ No newline at end of file
diff --git a/nearby/presence/ldt_np_adv_ffi/c/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi/c/CMakeLists.txt
new file mode 100644
index 0000000..476b228
--- /dev/null
+++ b/nearby/presence/ldt_np_adv_ffi/c/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 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.
+
+# Use ExternalProject to ensure that the rust artifacts are built
+include(ExternalProject)
+set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/target/tmp)
+if (CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(CARGO_ARTIFACT_DIR debug)
+ set(CARGO_PROFILE dev)
+else ()
+ set(CARGO_ARTIFACT_DIR release)
+ set(CARGO_PROFILE release)
+endif ()
+
+ExternalProject_Add(
+ ldt_np_adv_ffi
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND cargo build -p ldt_np_adv_ffi --no-default-features --features std --profile=${CARGO_PROFILE}
+ BUILD_BYPRODUCTS ${NEARBY_ROOT}/target/${CARGO_ARTIFACT_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}
+ BINARY_DIR "${NEARBY_ROOT}/target/"
+ INSTALL_COMMAND "")
+
+include_directories(${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/c/include/)
+
+add_subdirectory(sample)
+
+if (ENABLE_TESTS)
+ message(STATUS "Enabling ldt tests")
+ add_subdirectory(tests)
+ add_subdirectory(benchmarks)
+endif ()
+
+# Fuzzers won't build on windows so we need a separate flag to pull them in
+if (ENABLE_FUZZ)
+ message(STATUS "Enabling ldt fuzzers")
+ add_subdirectory(fuzz)
+endif ()
diff --git a/nearby/presence/ldt_np_adv_ffi/c/benchmarks/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi/c/benchmarks/CMakeLists.txt
new file mode 100644
index 0000000..330c5ab
--- /dev/null
+++ b/nearby/presence/ldt_np_adv_ffi/c/benchmarks/CMakeLists.txt
@@ -0,0 +1,24 @@
+# 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.
+
+add_executable(
+ ldt_benchmarks
+ ldt_benchmarks.cc
+)
+
+target_link_libraries(
+ ldt_benchmarks
+ "${NEARBY_ROOT}/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ benchmark::benchmark
+)
diff --git a/nearby/presence/ldt_np_c_sample/tests/ldt_benchmarks.cc b/nearby/presence/ldt_np_adv_ffi/c/benchmarks/ldt_benchmarks.cc
index 2559954..2559954 100644
--- a/nearby/presence/ldt_np_c_sample/tests/ldt_benchmarks.cc
+++ b/nearby/presence/ldt_np_adv_ffi/c/benchmarks/ldt_benchmarks.cc
diff --git a/nearby/presence/ldt_np_adv_ffi/c/fuzz/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi/c/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..3c64c8e
--- /dev/null
+++ b/nearby/presence/ldt_np_adv_ffi/c/fuzz/CMakeLists.txt
@@ -0,0 +1,30 @@
+# 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.
+
+fuzztest_setup_fuzzing_flags()
+
+add_executable(
+ ldt_fuzzer
+ ldt_fuzzer.cc
+)
+
+target_link_libraries(
+ ldt_fuzzer
+ PRIVATE
+ optimized "${NEARBY_ROOT}/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ debug "${NEARBY_ROOT}/target/debug/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ ssl)
+
+link_fuzztest(ldt_fuzzer)
+gtest_discover_tests(ldt_fuzzer) \ No newline at end of file
diff --git a/nearby/presence/ldt_np_adv_ffi/c/fuzz/ldt_fuzzer.cc b/nearby/presence/ldt_np_adv_ffi/c/fuzz/ldt_fuzzer.cc
new file mode 100644
index 0000000..8e4f28f
--- /dev/null
+++ b/nearby/presence/ldt_np_adv_ffi/c/fuzz/ldt_fuzzer.cc
@@ -0,0 +1,125 @@
+/*
+ * 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 <array>
+#include <vector>
+
+#include "fuzztest/fuzztest.h"
+#include "gtest/gtest.h"
+#include "np_ldt.h"
+#include "openssl/digest.h"
+#include "openssl/hkdf.h"
+#include "openssl/hmac.h"
+#include "openssl/obj_mac.h"
+
+void LdtDecryptBadMac(std::array<uint8_t, 32> key_seed_bytes,
+ std::array<uint8_t, 2> salt_bytes,
+ std::vector<uint8_t> plaintext_bytes,
+ std::array<uint8_t, 32> metadata_key_hmac_tag_bytes) {
+ NpLdtKeySeed key_seed;
+ memcpy(key_seed.bytes, key_seed_bytes.data(), key_seed_bytes.size());
+
+ NpLdtSalt salt;
+ memcpy(salt.bytes, salt_bytes.data(), salt_bytes.size());
+
+ NpMetadataKeyHmac metadata_key_hmac;
+ memcpy(metadata_key_hmac.bytes, metadata_key_hmac_tag_bytes.data(),
+ metadata_key_hmac_tag_bytes.size());
+
+ auto enc_handle = NpLdtEncryptCreate(key_seed);
+ EXPECT_NE(0, enc_handle.handle);
+
+ auto result = NpLdtEncrypt(enc_handle, plaintext_bytes.data(),
+ plaintext_bytes.size(), salt);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+
+ auto dec_handle = NpLdtDecryptCreate(key_seed, metadata_key_hmac);
+ EXPECT_NE(0, dec_handle.handle);
+ result = NpLdtDecryptAndVerify(dec_handle, plaintext_bytes.data(),
+ plaintext_bytes.size(), salt);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_ERROR_MAC_MISMATCH, result)
+ << "we expect mac mismatch since we're using a random mac";
+
+ result = NpLdtEncryptClose(enc_handle);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+
+ result = NpLdtDecryptClose(dec_handle);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+}
+
+FUZZ_TEST(LdtFuzzers, LdtDecryptBadMac)
+ .WithDomains(fuzztest::Arbitrary<std::array<uint8_t, 32>>(),
+ fuzztest::Arbitrary<std::array<uint8_t, 2>>(),
+ fuzztest::Arbitrary<std::vector<uint8_t>>()
+ .WithMinSize(16)
+ .WithMaxSize(31),
+ fuzztest::Arbitrary<std::array<uint8_t, 32>>());
+
+void LdtDecryptCorrectMac(std::array<uint8_t, 32> key_seed_bytes,
+ std::array<uint8_t, 2> salt_bytes,
+ std::vector<uint8_t> plaintext_bytes) {
+ NpLdtKeySeed key_seed;
+ memcpy(key_seed.bytes, key_seed_bytes.data(), key_seed_bytes.size());
+
+ NpLdtSalt salt;
+ memcpy(salt.bytes, salt_bytes.data(), salt_bytes.size());
+
+ // calculate metadata key hmac key by HKDFing key seed
+ // Reference:
+ // https://commondatastorage.googleapis.com/chromium-boringssl-docs/hkdf.h.html
+ // 32 byte HMAC-SHA256 key
+ uint8_t metadata_key_hmac_key[32] = {0};
+ auto result = HKDF(metadata_key_hmac_key, sizeof(metadata_key_hmac_key),
+ EVP_sha256(), (const uint8_t *)&key_seed.bytes, (size_t)32,
+ (const uint8_t *)"Google Nearby", (size_t)13,
+ (const uint8_t *)"V0 Identity token verification HMAC key",
+ (size_t)39);
+ EXPECT_EQ(1, result);
+ // calculate metadata key hmac using hkdf'd hmac key
+ NpMetadataKeyHmac metadata_key_hmac = {.bytes = {0}};
+ // will be written to by HMAC call, but it will always be
+ // 32 because that's what SHA256 outputs
+ unsigned int md_len = 32;
+ // first 14 bytes of payload are metadata key
+ HMAC(EVP_sha256(), metadata_key_hmac_key, 32, plaintext_bytes.data(), 14,
+ metadata_key_hmac.bytes, &md_len);
+
+ auto enc_handle = NpLdtEncryptCreate(key_seed);
+ EXPECT_NE(0, enc_handle.handle);
+
+ result = NpLdtEncrypt(enc_handle, plaintext_bytes.data(),
+ plaintext_bytes.size(), salt);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+
+ auto dec_handle = NpLdtDecryptCreate(key_seed, metadata_key_hmac);
+ EXPECT_NE(0, dec_handle.handle);
+ result = NpLdtDecryptAndVerify(dec_handle, plaintext_bytes.data(),
+ plaintext_bytes.size(), salt);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+
+ result = NpLdtEncryptClose(enc_handle);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+
+ result = NpLdtDecryptClose(dec_handle);
+ EXPECT_EQ(NP_LDT_RESULT::NP_LDT_SUCCESS, result);
+}
+
+FUZZ_TEST(LdtFuzzers, LdtDecryptCorrectMac)
+ .WithDomains(fuzztest::Arbitrary<std::array<uint8_t, 32>>(),
+ fuzztest::Arbitrary<std::array<uint8_t, 2>>(),
+ fuzztest::Arbitrary<std::vector<uint8_t>>()
+ .WithMinSize(16)
+ .WithMaxSize(31));
diff --git a/nearby/presence/ldt_np_adv_ffi/include/np_ldt.h b/nearby/presence/ldt_np_adv_ffi/c/include/np_ldt.h
index 13af781..13af781 100644
--- a/nearby/presence/ldt_np_adv_ffi/include/np_ldt.h
+++ b/nearby/presence/ldt_np_adv_ffi/c/include/np_ldt.h
diff --git a/nearby/presence/ldt_np_adv_ffi/c/sample/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi/c/sample/CMakeLists.txt
new file mode 100644
index 0000000..a18f15e
--- /dev/null
+++ b/nearby/presence/ldt_np_adv_ffi/c/sample/CMakeLists.txt
@@ -0,0 +1,19 @@
+# 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.
+add_executable(ldt_c_sample main.c)
+
+target_link_libraries(
+ ldt_c_sample
+ "${NEARBY_ROOT}/target/${CARGO_ARTIFACT_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+) \ No newline at end of file
diff --git a/nearby/presence/ldt_np_c_sample/main.c b/nearby/presence/ldt_np_adv_ffi/c/sample/main.c
index 9348a70..9348a70 100644
--- a/nearby/presence/ldt_np_c_sample/main.c
+++ b/nearby/presence/ldt_np_adv_ffi/c/sample/main.c
diff --git a/nearby/presence/ldt_np_c_sample/tests/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi/c/tests/CMakeLists.txt
index 141563d..a4cbc24 100644
--- a/nearby/presence/ldt_np_c_sample/tests/CMakeLists.txt
+++ b/nearby/presence/ldt_np_adv_ffi/c/tests/CMakeLists.txt
@@ -22,44 +22,9 @@ add_executable(
target_link_libraries(
ldt_ffi_tests
- "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ "${NEARBY_ROOT}/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
jsoncpp
GTest::gtest_main
)
-if(UNIX)
- target_link_libraries(
- ldt_ffi_tests
- dl pthread -fsanitize=address
- )
-elseif(MSVC)
- target_link_libraries(
- ldt_ffi_tests
- bcrypt ntdll userenv ws2_32
- )
-endif()
-gtest_discover_tests(ldt_ffi_tests)
-
-# Benchmarks
-add_executable(
- ldt_benchmarks
- ldt_benchmarks.cc
-)
-
-target_link_libraries(
- ldt_benchmarks
- "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- benchmark::benchmark
-)
-
-if(UNIX)
- target_link_libraries(
- ldt_benchmarks
- dl pthread -fsanitize=address
- )
-elseif(MSVC)
- target_link_libraries(
- ldt_benchmarks
- bcrypt ntdll userenv ws2_32
- )
-endif()
+gtest_discover_tests(ldt_ffi_tests) \ No newline at end of file
diff --git a/nearby/presence/ldt_np_c_sample/tests/ldt_ffi_tests.cc b/nearby/presence/ldt_np_adv_ffi/c/tests/ldt_ffi_tests.cc
index 7cd1fb3..65e0f68 100644
--- a/nearby/presence/ldt_np_c_sample/tests/ldt_ffi_tests.cc
+++ b/nearby/presence/ldt_np_adv_ffi/c/tests/ldt_ffi_tests.cc
@@ -18,6 +18,7 @@ extern "C" {
#include <algorithm>
#include <fstream>
+#include <iomanip>
// TODO: get multi threaded tests working on windows
#ifndef _WIN32
@@ -36,9 +37,9 @@ static const uint8_t KEY_SEED_BYTES[] = {
204, 219, 36, 137, 233, 252, 172, 66, 179, 147, 72, 184, 148, 30, 209, 154,
29, 54, 14, 117, 224, 152, 200, 193, 94, 107, 28, 194, 182, 32, 205, 57};
static const uint8_t KNOWN_HMAC_BYTES[] = {
- 223, 185, 10, 31, 155, 31, 226, 141, 24, 187, 204,
- 165, 34, 64, 181, 204, 44, 203, 95, 141, 82, 137,
- 163, 203, 100, 235, 53, 65, 202, 97, 75, 180};
+ 0xB4, 0xC5, 0x9F, 0xA5, 0x99, 0x24, 0x1B, 0x81, 0x75, 0x8D, 0x97,
+ 0x6B, 0x5A, 0x62, 0x1C, 0x05, 0x23, 0x2F, 0xE1, 0xBF, 0x89, 0xAE,
+ 0x59, 0x87, 0xCA, 0x25, 0x4C, 0x35, 0x54, 0xDC, 0xE5, 0x0E};
static const uint8_t TEST_DATA_BYTES[] = {205, 104, 63, 225, 161, 209, 248,
70, 84, 61, 10, 19, 212, 174,
164, 0, 64, 200, 214, 123};
@@ -65,7 +66,7 @@ static NpLdtDecryptHandle create_dec_handle_from_test_key() {
static void hex_string_to_bytes(const char *hexString, uint8_t *out,
size_t len) {
for (size_t count = 0; count < len; count++) {
- sscanf(hexString, "%2hhx", &out[count]); // NOLINT(cert-err34-c)
+ sscanf(hexString, "%2hhx", &out[count]); // NOLINT(cert-err34-c)
hexString += 2;
}
}
@@ -93,11 +94,11 @@ TEST(LdtFfiTests, TestJsonData) {
if (!parsingSuccessful) {
std::cout << reader.getFormattedErrorMessages() << "\n";
}
- ASSERT_TRUE(root.size() == 1000);
+ ASSERT_TRUE(root.size() == 100);
for (const auto &v : root) {
auto key_seed = v["key_seed"].asCString();
- auto metadata_key_hmac = v["metadata_key_hmac"].asCString();
+ auto identity_token_hmac = v["identity_token_hmac"].asCString();
auto adv_salt = v["adv_salt"].asCString();
auto plaintext = v["plaintext"].asCString();
auto ciphertext = v["ciphertext"].asCString();
@@ -105,12 +106,12 @@ TEST(LdtFfiTests, TestJsonData) {
NpLdtKeySeed np_key_seed;
auto len = strlen(key_seed) / 2;
hex_string_to_bytes(key_seed, np_key_seed.bytes, len);
- ASSERT_EQ(len, 32);
+ ASSERT_EQ(len, 32u);
NpMetadataKeyHmac known_hmac;
- len = strlen(metadata_key_hmac) / 2;
- hex_string_to_bytes(metadata_key_hmac, known_hmac.bytes, len);
- ASSERT_EQ(len, 32);
+ len = strlen(identity_token_hmac) / 2;
+ hex_string_to_bytes(identity_token_hmac, known_hmac.bytes, len);
+ ASSERT_EQ(len, 32u);
NpLdtEncryptHandle enc_handle = NpLdtEncryptCreate(np_key_seed);
ASSERT_TRUE(enc_handle.handle != 0);
@@ -118,7 +119,7 @@ TEST(LdtFfiTests, TestJsonData) {
NpLdtSalt salt_data;
len = strlen(adv_salt) / 2;
hex_string_to_bytes(adv_salt, salt_data.bytes, len);
- ASSERT_TRUE(len == 2);
+ ASSERT_TRUE(len == 2u);
len = strlen(plaintext) / 2;
auto buffer = (uint8_t *)malloc(len);
@@ -294,7 +295,6 @@ TEST(LdtFfiTests, MultiThreadedTests) {
pthread_cond_broadcast(&cond);
// Wait for them all to finish and check the status
- for (i = 0; i < num_threads; i++)
- ASSERT_EQ(pthread_join(tid[i], nullptr), 0);
+ for (i = 0; i < num_threads; i++) ASSERT_EQ(pthread_join(tid[i], nullptr), 0);
}
#endif
diff --git a/nearby/presence/ldt_np_adv_ffi/rust-toolchain.toml b/nearby/presence/ldt_np_adv_ffi/rust-toolchain.toml
deleted file mode 100644
index 271800c..0000000
--- a/nearby/presence/ldt_np_adv_ffi/rust-toolchain.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[toolchain]
-channel = "nightly" \ No newline at end of file
diff --git a/nearby/presence/ldt_np_adv_ffi/src/handle_map.rs b/nearby/presence/ldt_np_adv_ffi/src/handle_map.rs
index 9d83c19..669f2bb 100644
--- a/nearby/presence/ldt_np_adv_ffi/src/handle_map.rs
+++ b/nearby/presence/ldt_np_adv_ffi/src/handle_map.rs
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::Box;
use crate::LdtAdvDecrypter;
use crate::LdtAdvEncrypter;
use core::marker::PhantomData;
@@ -22,7 +21,7 @@ use lazy_static::lazy_static;
// Pull in the needed deps for std vs no_std
cfg_if::cfg_if! {
// Test pulls in std which causes duplicate errors
- if #[cfg(any(feature = "std", test, feature = "boringssl", feature = "openssl"))] {
+ if #[cfg(any(feature = "std", test, feature = "boringssl"))] {
use std::sync::{Mutex, MutexGuard};
use std::collections::HashMap;
diff --git a/nearby/presence/ldt_np_adv_ffi/src/lib.rs b/nearby/presence/ldt_np_adv_ffi/src/lib.rs
index 1534857..3ad6af4 100644
--- a/nearby/presence/ldt_np_adv_ffi/src/lib.rs
+++ b/nearby/presence/ldt_np_adv_ffi/src/lib.rs
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#![no_std]
#![deny(
missing_docs,
clippy::indexing_slicing,
@@ -20,60 +19,24 @@
clippy::panic,
clippy::expect_used
)]
-#![allow(internal_features)]
-// TODO: Remove usage of `lang_items` when ffi is no longer alloc
-// These features are needed to support no_std + alloc
-#![feature(lang_items)]
//! Rust ffi wrapper of ldt_np_adv, can be called from C/C++ Clients
extern crate alloc;
-use alloc::boxed::Box;
use core::slice;
-use handle_map::get_enc_handle_map;
+use crypto_provider_default::CryptoProviderImpl;
+use ldt::LdtCipher;
use ldt_np_adv::{
- build_np_adv_decrypter_from_key_seed, salt_padder, LdtAdvDecryptError, LdtEncrypterXtsAes128,
- LdtNpAdvDecrypterXtsAes128, LegacySalt,
+ build_np_adv_decrypter_from_key_seed, salt_padder, AuthenticatedNpLdtDecryptCipher,
+ LdtAdvDecryptError, NpLdtEncryptCipher, V0Salt, V0_IDENTITY_TOKEN_LEN,
};
use np_hkdf::NpKeySeedHkdf;
-use crate::handle_map::get_dec_handle_map;
-
mod handle_map;
-// Pull in the needed deps for std vs no_std
-cfg_if::cfg_if! {
- // Test pulls in std which causes duplicate errors
- if #[cfg(any(feature = "std", test, feature = "boringssl", feature = "openssl"))] {
- extern crate std;
- } else {
- // Allow using Box in no_std
- mod no_std;
- }
-}
-
-// Fail early for invalid combination of feature flags, we need at least one crypto library specified
-#[cfg(all(
- not(feature = "openssl"),
- not(feature = "crypto_provider_rustcrypto"),
- not(feature = "boringssl")
-))]
-compile_error!("Either the \"openssl\", \"boringssl\"or \"default\" features flag needs to be set in order to specify cryptographic library");
-
-// Need to have one of the crypto provider impls
-cfg_if::cfg_if! {
- if #[cfg(feature = "openssl")] {
- use crypto_provider_openssl::Openssl as CryptoProviderImpl;
- } else if #[cfg(feature = "boringssl")]{
- use crypto_provider_boringssl::Boringssl as CryptoProviderImpl;
- } else {
- use crypto_provider_rustcrypto::RustCrypto as CryptoProviderImpl;
- }
-}
-
-pub(crate) type LdtAdvDecrypter = LdtNpAdvDecrypterXtsAes128<CryptoProviderImpl>;
-pub(crate) type LdtAdvEncrypter = LdtEncrypterXtsAes128<CryptoProviderImpl>;
+pub(crate) type LdtAdvDecrypter = AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl>;
+pub(crate) type LdtAdvEncrypter = NpLdtEncryptCipher<CryptoProviderImpl>;
const SUCCESS: i32 = 0;
@@ -111,23 +74,23 @@ extern "C" fn NpLdtDecryptCreate(
&NpKeySeedHkdf::new(&key_seed.bytes),
metadata_key_hmac.bytes,
);
- let handle = get_dec_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
+ let handle = handle_map::get_dec_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
NpLdtDecryptHandle { handle }
}
#[no_mangle]
extern "C" fn NpLdtEncryptCreate(key_seed: NpLdtKeySeed) -> NpLdtEncryptHandle {
let cipher = LdtAdvEncrypter::new(
- &NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed.bytes).legacy_ldt_key(),
+ &NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed.bytes).v0_ldt_key(),
);
- let handle = get_enc_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
+ let handle = handle_map::get_enc_handle_map().insert::<CryptoProviderImpl>(Box::new(cipher));
NpLdtEncryptHandle { handle }
}
#[no_mangle]
extern "C" fn NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i32 {
map_to_error_code(|| {
- get_enc_handle_map()
+ handle_map::get_enc_handle_map()
.remove(&handle.handle)
.ok_or(CloseCipherError::InvalidHandle)
.map(|_| SUCCESS)
@@ -137,7 +100,7 @@ extern "C" fn NpLdtEncryptClose(handle: NpLdtEncryptHandle) -> i32 {
#[no_mangle]
extern "C" fn NpLdtDecryptClose(handle: NpLdtDecryptHandle) -> i32 {
map_to_error_code(|| {
- get_dec_handle_map()
+ handle_map::get_dec_handle_map()
.remove(&handle.handle)
.ok_or(CloseCipherError::InvalidHandle)
.map(|_| SUCCESS)
@@ -153,8 +116,8 @@ extern "C" fn NpLdtEncrypt(
) -> i32 {
map_to_error_code(|| {
let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
- let padder = salt_padder::<16, CryptoProviderImpl>(LegacySalt::from(salt.bytes));
- get_enc_handle_map()
+ let padder = salt_padder::<CryptoProviderImpl>(V0Salt::from(salt.bytes));
+ handle_map::get_enc_handle_map()
.get(&handle.handle)
.map(|cipher| {
cipher.encrypt(data, &padder).map(|_| 0).map_err(|e| match e {
@@ -174,9 +137,10 @@ extern "C" fn NpLdtDecryptAndVerify(
) -> i32 {
map_to_error_code(|| {
let data = unsafe { slice::from_raw_parts_mut(buffer, buffer_len) };
- let padder = salt_padder::<16, CryptoProviderImpl>(LegacySalt::from(salt.bytes));
+ let padder = salt_padder::<CryptoProviderImpl>(V0Salt::from(salt.bytes));
- get_dec_handle_map()
+ #[allow(clippy::indexing_slicing)]
+ handle_map::get_dec_handle_map()
.get(&handle.handle)
.map(|cipher| {
cipher
@@ -185,8 +149,10 @@ extern "C" fn NpLdtDecryptAndVerify(
LdtAdvDecryptError::InvalidLength(_) => DecryptError::InvalidLength,
LdtAdvDecryptError::MacMismatch => DecryptError::HmacDoesntMatch,
})
- .map(|plaintext| {
- data.copy_from_slice(plaintext.as_slice());
+ .map(|(token, plaintext)| {
+ // slicing is safe: token and plaintext sum to data's len
+ data[..V0_IDENTITY_TOKEN_LEN].copy_from_slice(token.as_slice());
+ data[V0_IDENTITY_TOKEN_LEN..].copy_from_slice(plaintext.as_slice());
SUCCESS
})
})
diff --git a/nearby/presence/ldt_np_adv_ffi_fuzz/CMakeLists.txt b/nearby/presence/ldt_np_adv_ffi_fuzz/CMakeLists.txt
deleted file mode 100644
index 2144811..0000000
--- a/nearby/presence/ldt_np_adv_ffi_fuzz/CMakeLists.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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.
-
-cmake_minimum_required(VERSION 3.0)
-
-# libfuzzer needs clang
-SET(CMAKE_C_COMPILER "clang")
-
-include_directories(
- ${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/include/)
-
-# enable fuzzer with ASAN
-# Can't use MSAN since EVP_KDF_fetch seems to read uninitialized memory, maybe on purpose?
-add_compile_options(-fsanitize=fuzzer,address)
-
-# we need at least version 3.0.5 for the core.h header used in the fuzzers
-find_package(OpenSSL 3.0.5 REQUIRED)
-if (OPENSSL_FOUND)
- message(STATUS "OpenSSL Found: ${OPENSSL_VERSION}")
- message(STATUS "OpenSSL Include: ${OPENSSL_INCLUDE_DIR}")
- message(STATUS "OpenSSL Libraries: ${OPENSSL_LIBRARIES}")
-endif ()
-
-add_executable(fuzzer_decrypt_bad_mac src/fuzzer_decrypt_bad_mac.c)
-target_link_libraries(fuzzer_decrypt_bad_mac
- optimized "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- debug "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/debug/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- dl pthread -fsanitize=fuzzer,address)
-target_link_libraries(fuzzer_decrypt_bad_mac OpenSSL::SSL)
-
-add_executable(fuzzer_decrypt_correct_mac src/fuzzer_decrypt_correct_mac.c)
-target_link_libraries(fuzzer_decrypt_correct_mac
- optimized "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- debug "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/debug/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- dl pthread -fsanitize=fuzzer,address)
-target_link_libraries(fuzzer_decrypt_correct_mac OpenSSL::SSL)
diff --git a/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_bad_mac.c b/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_bad_mac.c
deleted file mode 100644
index 18abb0f..0000000
--- a/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_bad_mac.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 <openssl/aes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "np_ldt.h"
-
-// Fuzz decrypting data that doesn't match the hmac
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- // data:
- // 32 byte key seed
- // 2 byte salt
- // 31 byte plaintext
- // 1 byte length of plaintext to use
- // 32 byte metadata key hmac
- if (size < 98) {
- return -1;
- }
-
- NpLdtKeySeed key_seed;
- memcpy(&key_seed.bytes, data, 32);
-
- NpLdtSalt salt;
- memcpy(&salt.bytes, data + 32, 2);
-
- uint8_t payload[31];
- memcpy(&payload, data + 32 + 2, 31);
-
- uint8_t payload_len;
- memcpy(&payload_len, data + 32 + 2 + 31, 1);
- // length in [16, 31]
- payload_len = 16 + (payload_len % 16);
-
- NpMetadataKeyHmac metadata_key_hmac;
- memcpy(&metadata_key_hmac.bytes, data + 32 + 2 + 31 + 1, 32);
-
- // create a cipher
- NpLdtEncryptHandle enc_handle = NpLdtEncryptCreate(key_seed);
- if (enc_handle.handle == 0) {
- printf("Error: create LDT failed\n");
- __builtin_trap();
- return 0;
- }
-
- // encrypt with it
- NP_LDT_RESULT result = NpLdtEncrypt(enc_handle, payload, payload_len, salt);
- if (result != 0) {
- printf("Error: encrypt\n");
- __builtin_trap();
- return 0;
- }
-
- NpLdtDecryptHandle dec_handle = NpLdtDecryptCreate(key_seed, metadata_key_hmac);
- if (dec_handle.handle == 0) {
- printf("Error: create LDT failed\n");
- __builtin_trap();
- return 0;
- }
-
- // decrypt & verify -- we expect mac mismatch since we're using a random mac
- result = NpLdtDecryptAndVerify(dec_handle, payload, payload_len, salt);
- if (result != -2) {
- printf("Error: decryption didn't fail with the expected MAC mismatch\n");
- __builtin_trap();
- return 0;
- }
-
- // deallocate the cipher
- result = NpLdtEncryptClose(enc_handle);
- if (result) {
- printf("Error: close cipher\n");
- __builtin_trap();
- return result;
- }
-
- result = NpLdtDecryptClose(dec_handle);
- if (result) {
- printf("Error: close cipher failed\n");
- __builtin_trap();
- return result;
- }
-
- return 0; // Values other than 0 and -1 are reserved for future use.
-}
diff --git a/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_correct_mac.c b/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_correct_mac.c
deleted file mode 100644
index e99a7e8..0000000
--- a/nearby/presence/ldt_np_adv_ffi_fuzz/src/fuzzer_decrypt_correct_mac.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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 <openssl/core.h>
-#include <openssl/core_names.h>
-#include <openssl/hmac.h>
-#include <openssl/kdf.h>
-#include <openssl/obj_mac.h>
-#include <openssl/params.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "np_ldt.h"
-
-// Fuzz decrypting data that doesn't match the hmac
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- // data:
- // 32 byte key seed
- // 2 byte salt
- // 31 byte plaintext
- // 1 byte length of plaintext to use
- if (size < 66) {
- return -1;
- }
-
- NpLdtKeySeed key_seed;
- memcpy(&key_seed.bytes, data, 32);
-
- NpLdtSalt salt;
- memcpy(&salt.bytes, data + 32, 2);
-
- uint8_t payload[31];
- memcpy(&payload, data + 32 + 2, 31);
-
- uint8_t payload_len;
- memcpy(&payload_len, data + 32 + 2 + 31, 1);
- // length in [16, 31]
- payload_len = 16 + (payload_len % 16);
-
- // calculate metadata key hmac key by HKDFing key seed
- // HKDF code from https://www.openssl.org/docs/man3.0/man7/EVP_KDF-HKDF.html
- EVP_KDF *kdf;
- EVP_KDF_CTX *kctx;
- // 32 byte HMAC-SHA256 key
- uint8_t metadata_key_hmac_key[32] = {0};
- OSSL_PARAM params[5], *p = params;
-
- kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
- if (kdf == NULL) {
- printf("Couldn't allocate KDF\n");
- __builtin_trap();
- return 0;
- }
- kctx = EVP_KDF_CTX_new(kdf);
- EVP_KDF_free(kdf);
-
- *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, SN_sha256,
- strlen(SN_sha256));
- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, &key_seed.bytes,
- (size_t)32);
- *p++ = OSSL_PARAM_construct_octet_string(
- OSSL_KDF_PARAM_INFO, "Legacy metadata key verification HMAC key",
- (size_t)41);
- *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, "Google Nearby",
- (size_t)13);
- *p = OSSL_PARAM_construct_end();
- if (EVP_KDF_derive(kctx, metadata_key_hmac_key, sizeof(metadata_key_hmac_key),
- params) <= 0) {
- printf("HKDF error\n");
- __builtin_trap();
- return 0;
- }
-
- EVP_KDF_CTX_free(kctx);
-
- // calculate metadata key hmac using hkdf'd hmac key
- NpMetadataKeyHmac metadata_key_hmac = {.bytes = {0}};
- // will be written to by HMAC call, but it will always be
- // 32 because that's what SHA256 outputs
- unsigned int md_len = 32;
- // first 14 bytes of payload are metadata key
- HMAC(EVP_sha256(), metadata_key_hmac_key, 32, payload, 14,
- metadata_key_hmac.bytes, &md_len);
-
- // create a cipher
- NpLdtEncryptHandle enc_handle = NpLdtEncryptCreate(key_seed);
- if (enc_handle.handle == 0) {
- printf("Error: create LDT failed\n");
- __builtin_trap();
- return 0;
- }
-
- // encrypt with it
- NP_LDT_RESULT result = NpLdtEncrypt(enc_handle, payload, payload_len, salt);
- if (result != 0) {
- printf("Error: encrypt\n");
- __builtin_trap();
- return 0;
- }
-
- NpLdtDecryptHandle dec_handle = NpLdtDecryptCreate(key_seed, metadata_key_hmac);
- if (dec_handle.handle == 0) {
- printf("Error: create LDT failed\n");
- __builtin_trap();
- return 0;
- }
-
- // decrypt & verify -- we expect mac mismatch since we're using a random mac
- result = NpLdtDecryptAndVerify(dec_handle, payload, payload_len, salt);
- if (result != 0) {
- printf("Error: decryption failed\n");
- __builtin_trap();
- return 0;
- }
-
- // deallocate the ciphers
- result = NpLdtEncryptClose(enc_handle);
- if (result) {
- printf("Error: close cipher failed\n");
- __builtin_trap();
- return result;
- }
-
- result = NpLdtDecryptClose(dec_handle);
- if (result) {
- printf("Error: close cipher failed\n");
- __builtin_trap();
- return result;
- }
-
- return 0; // Values other than 0 and -1 are reserved for future use.
-}
diff --git a/nearby/presence/ldt_np_c_sample/CMakeLists.txt b/nearby/presence/ldt_np_c_sample/CMakeLists.txt
deleted file mode 100644
index aefc0ba..0000000
--- a/nearby/presence/ldt_np_c_sample/CMakeLists.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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_directories(
- ${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/include/
- ${CMAKE_SOURCE_DIR}/ldt_np_c_sample/)
-
-include(ExternalProject)
-set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/target/tmp)
-ExternalProject_Add(
- ldt_np_adv_ffi
- DOWNLOAD_COMMAND ""
- CONFIGURE_COMMAND ""
- BUILD_COMMAND cargo build COMMAND cargo build --release --no-default-features --features std
- BINARY_DIR "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi"
- INSTALL_COMMAND "")
-
-add_executable(ldt_c_sample main.c)
-target_link_libraries(
- ldt_c_sample
- optimized "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
- debug "${CMAKE_SOURCE_DIR}/ldt_np_adv_ffi/target/debug/${CMAKE_STATIC_LIBRARY_PREFIX}ldt_np_adv_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
-)
-
-if(UNIX)
- target_link_libraries(
- ldt_c_sample
- dl pthread
- )
-elseif(MSVC)
- target_link_libraries(
- ldt_c_sample
- bcrypt ntdll userenv ws2_32
- )
-endif()
-
-
-if(ENABLE_TESTS)
- message(STATUS "Enabling ldt tests")
- add_subdirectory(tests)
-endif()
diff --git a/nearby/presence/ldt_np_jni/Cargo.toml b/nearby/presence/ldt_np_jni/Cargo.toml
index 2551c14..cf7c2db 100644
--- a/nearby/presence/ldt_np_jni/Cargo.toml
+++ b/nearby/presence/ldt_np_jni/Cargo.toml
@@ -20,7 +20,6 @@ jni.workspace = true
[features]
default = ["rustcrypto"]
rustcrypto = ["crypto_provider_default/rustcrypto", "crypto_provider_default/std"]
-opensslbssl = ["crypto_provider_default/opensslbssl"]
boringssl = ["crypto_provider_default/boringssl"]
[lib]
diff --git a/nearby/presence/ldt_np_jni/java/LdtNpJni/src/main/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJni.java b/nearby/presence/ldt_np_jni/java/LdtNpJni/src/main/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJni.java
index 6af362a..1c0db30 100644
--- a/nearby/presence/ldt_np_jni/java/LdtNpJni/src/main/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJni.java
+++ b/nearby/presence/ldt_np_jni/java/LdtNpJni/src/main/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJni.java
@@ -17,22 +17,25 @@ package com.google.android.gms.nearby.presence.hazmat;
import androidx.annotation.IntDef;
-
/** JNI for a Nearby Presence LDT-XTS-AES128 cipher with the "swap" mix function. */
class LdtNpJni {
/** Error codes which map to return values on the native side. */
- @IntDef({DecryptErrorCode.DATA_LEN_ERROR, DecryptErrorCode.JNI_OP_ERROR, DecryptErrorCode.MAC_MISMATCH} )
+ @IntDef({
+ DecryptErrorCode.DATA_LEN_ERROR,
+ DecryptErrorCode.JNI_OP_ERROR,
+ DecryptErrorCode.MAC_MISMATCH
+ })
public @interface DecryptErrorCode {
- int DATA_LEN_ERROR = -1;
+ int DATA_LEN_ERROR = -1;
int JNI_OP_ERROR = -2;
int MAC_MISMATCH = -3;
}
/** Error codes which map to return values on the native side. */
- @IntDef({EncryptErrorCode.DATA_LEN_ERROR, EncryptErrorCode.JNI_OP_ERROR} )
+ @IntDef({EncryptErrorCode.DATA_LEN_ERROR, EncryptErrorCode.JNI_OP_ERROR})
public @interface EncryptErrorCode {
- int DATA_LEN_ERROR = -1;
+ int DATA_LEN_ERROR = -1;
int JNI_OP_ERROR = -2;
}
@@ -43,8 +46,8 @@ class LdtNpJni {
/**
* Create a new LDT-XTS-AES128 Encryption cipher using the "swap" mix function.
*
- * @param keySeed is the 32-byte key material from the Nearby Presence credential from which
- * the LDT key will be derived.
+ * @param keySeed is the 32-byte key material from the Nearby Presence credential from which the
+ * LDT key will be derived.
* @return 0 on error, or a non-zero handle on success.
*/
static native long createEncryptionCipher(byte[] keySeed);
@@ -52,16 +55,17 @@ class LdtNpJni {
/**
* Create a new LDT-XTS-AES128 Decryption cipher using the "swap" mix function.
*
- * @param keySeed is the 32-byte key material from the Nearby Presence credential from which
- * the LDT key will be derived.
- * @param hmacTag is the hmac auth tag calculated on the metadata key used to verify
- * decryption was successful.
+ * @param keySeed is the 32-byte key material from the Nearby Presence credential from which the
+ * LDT key will be derived.
+ * @param hmacTag is the hmac auth tag calculated on the metadata key used to verify decryption
+ * was successful.
* @return 0 on error, or a non-zero handle on success.
*/
static native long createDecryptionCipher(byte[] keySeed, byte[] hmacTag);
/**
* Close the native resources for an LdtEncryptCipher instance.
+ *
* @param ldtEncryptHandle a ldt handle returned from {@link LdtNpJni#createEncryptionCipher}.
*/
static native void closeEncryptCipher(long ldtEncryptHandle);
@@ -76,28 +80,28 @@ class LdtNpJni {
/**
* Encrypt a 16-31 byte buffer in-place.
*
- * @param ldtEncryptHandle a ldt encryption handle returned from {@link LdtNpJni#createEncryptionCipher}.
- * @param salt is the big-endian 2 byte salt that will be used in the Nearby
- * Presence advertisement, which will be incorporated into the tweaks LDT uses
- * while encrypting.
+ * @param ldtEncryptHandle a ldt encryption handle returned from {@link
+ * LdtNpJni#createEncryptionCipher}.
+ * @param salt is the big-endian 2 byte salt that will be used in the Nearby Presence
+ * advertisement, which will be incorporated into the tweaks LDT uses while encrypting.
* @param data 16-31 bytes of plaintext data to be encrypted
- * @return 0 on success, in which case `buffer` will now contain ciphertext or a non-zero
- * an error code on failure
+ * @return 0 on success, in which case `buffer` will now contain ciphertext or a non-zero an error
+ * code on failure
*/
@EncryptErrorCode
static native int encrypt(long ldtEncryptHandle, char salt, byte[] data);
/**
- * Decrypt a 16-31 byte buffer in-place and verify the plaintext metadata key matches
- * this item's MAC, if not the buffer will not be decrypted.
+ * Decrypt a 16-31 byte buffer in-place and verify the plaintext metadata key matches this item's
+ * MAC, if not the buffer will not be decrypted.
*
- * @param ldtDecryptHandle a ldt encryption handle returned from {@link LdtNpJni#createDecryptionCipher}.
- * @param salt is the big-endian 2 byte salt that will be used in the Nearby
- * Presence advertisement, which will be incorporated into the tweaks LDT uses
- * while encrypting.
+ * @param ldtDecryptHandle a ldt encryption handle returned from {@link
+ * LdtNpJni#createDecryptionCipher}.
+ * @param salt is the big-endian 2 byte salt that will be used in the Nearby Presence
+ * advertisement, which will be incorporated into the tweaks LDT uses while encrypting.
* @param data 16-31 bytes of ciphertext data to be decrypted
- * @return 0 on success, in which case `buffer` will now contain ciphertext or a non-zero
- * an error code on failure, in which case data will remain unchanged.
+ * @return 0 on success, in which case `buffer` will now contain ciphertext or a non-zero an error
+ * code on failure, in which case data will remain unchanged.
*/
@DecryptErrorCode
static native int decryptAndVerify(long ldtDecryptHandle, char salt, byte[] data);
diff --git a/nearby/presence/ldt_np_jni/java/LdtNpJni/src/test/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJniTests.kt b/nearby/presence/ldt_np_jni/java/LdtNpJni/src/test/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJniTests.kt
index 07d29a3..e360599 100644
--- a/nearby/presence/ldt_np_jni/java/LdtNpJni/src/test/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJniTests.kt
+++ b/nearby/presence/ldt_np_jni/java/LdtNpJni/src/test/java/com/google/android/gms/nearby/presence/hazmat/LdtNpJniTests.kt
@@ -22,15 +22,15 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
const val KEY_SEED = "CCDB2489E9FCAC42B39348B8941ED19A1D360E75E098C8C15E6B1CC2B620CD39"
-const val HMAC_TAG = "DFB90A1F9B1FE28D18BBCCA52240B5CC2CCB5F8D5289A3CB64EB3541CA614BB4"
+const val HMAC_TAG = "B4C59FA599241B81758D976B5A621C05232FE1BF89AE5987CA254C3554DCE50E"
const val PLAINTEXT = "CD683FE1A1D1F846543D0A13D4AEA40040C8D67B"
-const val SALT_BYTES = "32EE"
-const val EXPECTED_CIPHER_TEXT = "04344411F1E57C841FE0F7150636BC782455059A"
+const val SALT_BYTES = "0C0F"
+const val EXPECTED_CIPHER_TEXT = "61E481C12F4DE24F2D4AB22D8908F80D3A3F9B40"
class LdtNpJniTests {
@Test
fun roundTripTest() {
- // Data taken from first test case in ldt_np_adv/resources/test/np_adv_test_vectors.json
+ // Data taken from ldt_ffi_test_scenario()
val keySeed = KEY_SEED.decodeHex()
val hmacTag = HMAC_TAG.decodeHex()
val plaintext = PLAINTEXT.decodeHex()
@@ -164,4 +164,4 @@ private fun String.decodeHex(): ByteArray {
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
-} \ No newline at end of file
+}
diff --git a/nearby/presence/ldt_np_jni/src/lib.rs b/nearby/presence/ldt_np_jni/src/lib.rs
index e232c1e..334bcd9 100644
--- a/nearby/presence/ldt_np_jni/src/lib.rs
+++ b/nearby/presence/ldt_np_jni/src/lib.rs
@@ -36,8 +36,8 @@ use jni::{
JNIEnv,
};
-use ldt::XorPadder;
-use ldt_np_adv::{LdtAdvDecryptError, LdtEncrypterXtsAes128, LdtNpAdvDecrypterXtsAes128};
+use ldt::{LdtCipher, XorPadder};
+use ldt_np_adv::{AuthenticatedNpLdtDecryptCipher, LdtAdvDecryptError, NpLdtEncryptCipher};
use np_hkdf::NpKeySeedHkdf;
use crypto_provider_default::CryptoProviderImpl;
@@ -56,10 +56,11 @@ const CREATE_ERROR: jlong = 0;
/// Status code returned on successful cipher operations
const SUCCESS: jint = 0;
-type LdtAdvDecrypter = LdtNpAdvDecrypterXtsAes128<CryptoProviderImpl>;
-type LdtAdvEncrypter = LdtEncrypterXtsAes128<CryptoProviderImpl>;
+type LdtAdvDecrypter = AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl>;
+type LdtAdvEncrypter = NpLdtEncryptCipher<CryptoProviderImpl>;
/// Marker trait to ensure above types are thread safe
+#[allow(dead_code)]
trait JniThreadSafe: Send + Sync {}
impl JniThreadSafe for LdtAdvDecrypter {}
@@ -90,7 +91,7 @@ extern "system" fn Java_com_google_android_gms_nearby_presence_hazmat_LdtNpJni_c
key_seed.as_slice().try_into().expect("Length is checked above"),
);
- let cipher = LdtAdvEncrypter::new(&hkdf_key_seed.legacy_ldt_key());
+ let cipher = LdtAdvEncrypter::new(&hkdf_key_seed.v0_ldt_key());
box_to_handle(cipher).map_err(|_| CREATE_ERROR)
})
}
@@ -221,14 +222,15 @@ extern "system" fn Java_com_google_android_gms_nearby_presence_hazmat_LdtNpJni_d
})?;
with_handle::<LdtAdvDecrypter, _, _>(handle, |cipher| {
- let result = cipher
+ let (identity_token, plaintext) = cipher
.decrypt_and_verify(buffer.as_mut_slice(), &expand_np_salt_to_padder(salt))
.map_err(|err| match err {
LdtAdvDecryptError::InvalidLength(_) => DecryptError::DataLen,
LdtAdvDecryptError::MacMismatch => DecryptError::MacMisMatch,
})?;
- let jbyte_buffer = bytes_to_jbytes(result.as_slice());
+ let concatenated = &[identity_token.as_slice(), plaintext.as_slice()].concat();
+ let jbyte_buffer = bytes_to_jbytes(concatenated);
env.set_byte_array_region(&data, 0, jbyte_buffer)
.map_err(|_| DecryptError::JniOp)
@@ -301,7 +303,7 @@ fn box_to_handle<T>(thing: T) -> Result<jlong, ()> {
/// Returns a XorPadder containing the HKDF of the salt.
fn expand_np_salt_to_padder(np_salt: jchar) -> XorPadder<{ crypto_provider::aes::BLOCK_SIZE }> {
let salt_bytes = np_salt.to_be_bytes();
- ldt_np_adv::salt_padder::<16, CryptoProviderImpl>(salt_bytes.into())
+ ldt_np_adv::salt_padder::<CryptoProviderImpl>(salt_bytes.into())
}
fn map_to_error_code<E: JniError, F: Fn() -> Result<jint, E>>(f: F) -> jint {
diff --git a/nearby/presence/np_adv/Cargo.toml b/nearby/presence/np_adv/Cargo.toml
index 9b576a6..5a72ecd 100644
--- a/nearby/presence/np_adv/Cargo.toml
+++ b/nearby/presence/np_adv/Cargo.toml
@@ -17,7 +17,7 @@ xts_aes.workspace = true
crypto_provider.workspace = true
strum.workspace = true
strum_macros.workspace = true
-nom = { version = "7.1.3", default-features = false }
+nom.workspace = true
lazy_static.workspace = true
sink.workspace = true
tinyvec.workspace = true
@@ -36,6 +36,7 @@ serde_json = { workspace = true, features = ["std"] }
serde.workspace = true
anyhow.workspace = true
test_helper = { path = "../test_helper" }
+test_vector_hkdf.workspace = true
criterion.workspace = true
crypto_provider_default = { workspace = true, features = ["std", "rustcrypto"] }
np_ed25519 = { workspace = true, features = ["std"] }
diff --git a/nearby/presence/np_adv/benches/deser_adv.rs b/nearby/presence/np_adv/benches/deser_adv.rs
index b52f53a..0cc553b 100644
--- a/nearby/presence/np_adv/benches/deser_adv.rs
+++ b/nearby/presence/np_adv/benches/deser_adv.rs
@@ -21,34 +21,34 @@
clippy::panic
)]
-use core::marker::PhantomData;
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
-use crypto_provider::{CryptoProvider, CryptoRng};
+use crypto_provider::{ed25519, CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
-use ldt_np_adv::LegacySalt;
+use ldt_np_adv::{V0IdentityToken, V0Salt, V0_IDENTITY_TOKEN_LEN};
+use np_adv::credential::matched::EmptyMatchedCredential;
use np_adv::deserialization_arena;
use np_adv::extended::serialize::AdvertisementType;
+use np_adv::extended::V1IdentityToken;
+use np_adv::legacy::serialize::UnencryptedEncoder;
use np_adv::{
credential::{book::*, v0::*, v1::*, *},
- de_type::EncryptedIdentityDataElementType,
deserialize_advertisement,
extended::{
data_elements::{GenericDataElement, TxPowerDataElement},
deserialize::VerificationMode,
serialize::{
- AdvBuilder as ExtendedAdvBuilder, MicEncryptedSectionEncoder, PublicSectionEncoder,
- SectionBuilder, SectionEncoder, SignedEncryptedSectionEncoder,
+ AdvBuilder as ExtendedAdvBuilder, MicEncryptedSectionEncoder, SectionBuilder,
+ SectionEncoder, SignedEncryptedSectionEncoder, UnencryptedSectionEncoder,
},
},
legacy::{
- actions::{ActionBits, ActionsDataElement},
- serialize::{AdvBuilder as LegacyAdvBuilder, LdtIdentity},
- ShortMetadataKey,
+ data_elements::actions::{ActionBits, ActionsDataElement},
+ serialize::{AdvBuilder as LegacyAdvBuilder, LdtEncoder},
},
- shared_data::{ContextSyncSeqNum, TxPower},
- MetadataKey, PublicIdentity,
+ shared_data::TxPower,
};
+use np_hkdf::{DerivedSectionKeys, NpKeySeedHkdf};
use rand::{Rng as _, SeedableRng as _};
use strum::IntoEnumIterator;
@@ -67,42 +67,40 @@ pub fn deser_adv_v1_encrypted(c: &mut Criterion) {
),
|b| {
let identities = (0..num_identities)
- .map(|_| V1Identity::random(&mut crypto_rng))
+ .map(|_| V1Identity::random::<CryptoProviderImpl>(&mut crypto_rng))
.collect::<Vec<_>>();
let mut adv_builder = ExtendedAdvBuilder::new(AdvertisementType::Encrypted);
// take the first n identities, one section per identity
for identity in identities.iter().take(num_sections) {
- let broadcast_cm = SimpleSignedBroadcastCryptoMaterial::new(
+ let broadcast_cm = V1BroadcastCredential::new(
identity.key_seed,
- identity.extended_metadata_key,
- identity.key_pair.private_key(),
+ identity.identity_token,
+ identity.private_key.clone(),
);
match identity_type {
VerificationMode::Mic => {
let mut sb = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Private,
&broadcast_cm,
))
.unwrap();
add_des(&mut sb);
- sb.add_to_advertisement();
+ sb.add_to_advertisement::<CryptoProviderImpl>();
}
VerificationMode::Signature => {
let mut sb = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Private,
&broadcast_cm,
))
.unwrap();
add_des(&mut sb);
- sb.add_to_advertisement();
+ sb.add_to_advertisement::<CryptoProviderImpl>();
}
}
}
@@ -112,7 +110,7 @@ pub fn deser_adv_v1_encrypted(c: &mut Criterion) {
run_with_v1_creds::<
CryptoProviderImpl
>(
- b, crypto_type, identities, adv.as_slice()
+ b, crypto_type, identities, adv.as_slice(),
)
},
);
@@ -126,10 +124,10 @@ pub fn deser_adv_v1_plaintext(c: &mut Criterion) {
c.bench_function("Deser V1 plaintext: sections=1", |b| {
let mut adv_builder = ExtendedAdvBuilder::new(AdvertisementType::Plaintext);
- let mut sb = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut sb = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
add_des(&mut sb);
- sb.add_to_advertisement();
+ sb.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
@@ -157,20 +155,16 @@ pub fn deser_adv_v0_encrypted(c: &mut Criterion) {
let identity = &identities[0];
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(
- identity.key_seed,
- identity.legacy_metadata_key,
- );
+ let broadcast_cm =
+ V0BroadcastCredential::new(identity.key_seed, identity.identity_token);
let mut adv_builder =
- LegacyAdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- EncryptedIdentityDataElementType::Private,
- LegacySalt::from(rng.gen::<[u8; 2]>()),
+ LegacyAdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(
+ V0Salt::from(rng.gen::<[u8; 2]>()),
&broadcast_cm,
));
- let mut action_bits = ActionBits::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(3).unwrap());
+ let action_bits = ActionBits::default();
adv_builder.add_data_element(ActionsDataElement::from(action_bits)).unwrap();
let adv = adv_builder.into_advertisement().unwrap();
@@ -188,10 +182,9 @@ pub fn deser_adv_v0_encrypted(c: &mut Criterion) {
}
pub fn deser_adv_v0_plaintext(c: &mut Criterion) {
- let mut adv_builder = LegacyAdvBuilder::new(PublicIdentity);
+ let mut adv_builder = LegacyAdvBuilder::new(UnencryptedEncoder);
- let mut action_bits = ActionBits::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(3).unwrap());
+ let action_bits = ActionBits::default();
adv_builder.add_data_element(ActionsDataElement::from(action_bits)).unwrap();
let adv = adv_builder.into_advertisement().unwrap();
@@ -227,16 +220,16 @@ pub fn deser_adv_v0_plaintext(c: &mut Criterion) {
fn run_with_v0_creds<C>(
b: &mut Bencher,
crypto_material_type: CryptoMaterialType,
- identities: Vec<V0Identity<C>>,
+ identities: Vec<V0Identity>,
adv: &[u8],
) where
C: CryptoProvider,
{
let mut creds = identities
.into_iter()
- .map(|identity| identity.into_discovery_credential())
- .map(|discovery_credential| MatchableCredential {
- discovery_credential,
+ .map(|identity| identity.into_discovery_credential::<C>())
+ .map(|crypto_material| MatchableCredential {
+ discovery_credential: crypto_material,
match_data: EmptyMatchedCredential,
})
.collect::<Vec<_>>();
@@ -283,16 +276,16 @@ fn run_with_v0_creds<C>(
fn run_with_v1_creds<C>(
b: &mut Bencher,
crypto_material_type: CryptoMaterialType,
- identities: Vec<V1Identity<C>>,
+ identities: Vec<V1Identity>,
adv: &[u8],
) where
C: CryptoProvider,
{
let mut creds = identities
.into_iter()
- .map(|identity| identity.into_discovery_credential())
- .map(|discovery_credential| MatchableCredential {
- discovery_credential,
+ .map(|identity| identity.into_discovery_credential::<C>())
+ .map(|crypto_material| MatchableCredential {
+ discovery_credential: crypto_material,
match_data: EmptyMatchedCredential,
})
.collect::<Vec<_>>();
@@ -333,6 +326,7 @@ fn run_with_v1_creds<C>(
}
}
}
+
fn add_des<I: SectionEncoder>(
sb: &mut SectionBuilder<&mut np_adv::extended::serialize::AdvBuilder, I>,
) {
@@ -348,51 +342,61 @@ criterion_group!(
);
criterion_main!(benches);
-struct V0Identity<C: CryptoProvider> {
+struct V0Identity {
key_seed: [u8; 32],
- legacy_metadata_key: ShortMetadataKey,
- _marker: PhantomData<C>,
+ identity_token: V0IdentityToken,
}
-impl<C: CryptoProvider> V0Identity<C> {
+impl V0Identity {
/// Generate a new identity with random crypto material
fn random<R: rand::Rng + rand::CryptoRng>(rng: &mut R) -> Self {
Self {
key_seed: rng.gen(),
- legacy_metadata_key: ShortMetadataKey(rng.gen()),
- _marker: PhantomData,
+ identity_token: V0IdentityToken::from(rng.gen::<[u8; V0_IDENTITY_TOKEN_LEN]>()),
}
}
/// Convert this `V0Identity` into a V0 discovery credential.
- fn into_discovery_credential(self) -> V0DiscoveryCredential {
- SimpleBroadcastCryptoMaterial::<V0>::new(self.key_seed, self.legacy_metadata_key)
- .derive_v0_discovery_credential::<C>()
+ fn into_discovery_credential<C: CryptoProvider>(self) -> V0DiscoveryCredential {
+ let hkdf = NpKeySeedHkdf::<C>::new(&self.key_seed);
+ V0DiscoveryCredential::new(
+ self.key_seed,
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<C>(self.identity_token.as_slice()),
+ )
}
}
-struct V1Identity<C: CryptoProvider> {
+struct V1Identity {
key_seed: [u8; 32],
- extended_metadata_key: MetadataKey,
- key_pair: np_ed25519::KeyPair<C>,
+ identity_token: V1IdentityToken,
+ private_key: ed25519::PrivateKey,
}
-impl<C: CryptoProvider> V1Identity<C> {
+impl V1Identity {
/// Generate a new identity with random crypto material
- fn random(rng: &mut C::CryptoRng) -> Self {
+ fn random<C: CryptoProvider>(rng: &mut C::CryptoRng) -> Self {
Self {
key_seed: rng.gen(),
- extended_metadata_key: MetadataKey(rng.gen()),
- key_pair: np_ed25519::KeyPair::<C>::generate(),
+ identity_token: rng.gen(),
+ private_key: ed25519::PrivateKey::generate::<C::Ed25519>(),
}
}
/// Convert this `V1Identity` into a `V1DiscoveryCredential`.
- fn into_discovery_credential(self) -> V1DiscoveryCredential {
- SimpleSignedBroadcastCryptoMaterial::new(
+ fn into_discovery_credential<C: CryptoProvider>(self) -> V1DiscoveryCredential {
+ let hkdf = NpKeySeedHkdf::<C>::new(&self.key_seed);
+
+ V1DiscoveryCredential::new(
self.key_seed,
- self.extended_metadata_key,
- self.key_pair.private_key(),
+ hkdf.v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ hkdf.v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ hkdf.v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ self.private_key.derive_public_key::<C::Ed25519>(),
)
- .derive_v1_discovery_credential::<C>()
}
}
diff --git a/nearby/presence/np_adv/resources/test/mic-encrypted-test-vectors.json b/nearby/presence/np_adv/resources/test/mic-encrypted-test-vectors.json
deleted file mode 100644
index a7834ec..0000000
--- a/nearby/presence/np_adv/resources/test/mic-encrypted-test-vectors.json
+++ /dev/null
@@ -1,2295 +0,0 @@
-[
- {
- "adv_header_byte": "20",
- "aes_key": "F3DB017C70E08EC5178C92F3AEA0C362",
- "data_elements": [
- {
- "contents": "CF75D23EDA8F6E4A23",
- "de_type": 383
- },
- {
- "contents": "731B76151735869205CC41",
- "de_type": 73
- },
- {
- "contents": "7C2A8DE86B2CBB997703",
- "de_type": 228
- },
- {
- "contents": "99F5163DCA0BB9BE89755A6C5AB321",
- "de_type": 446
- }
- ],
- "encoded_section": "6D91100056F596D16E1F87B107EE86102FFC6D5E9002F00C41CDDF533667362CD14AC54A9388FA3D30AA7CA6603071B8B0FA19BF582479F773F1C7D0EADF98E98B9447139F244D571B780475ACD9CB248F33B2C085925213360732D44081C27CA6EB40BD8A626BC776D88C5FDB09",
- "identity_type": "trusted",
- "key_seed": "F0ED9126768CE7DC685FF74932AC5A876442C4E42359A43F720A575142A45043",
- "metadata_key": "45795EE4C6533A830886E2C5885EB9E5",
- "nonce": "40E95D525FAEA1C1FEE39A8E",
- "section_mic_hmac_key": "A22386E85112EF883218A5B75669B7102E017E9AA149F408A079F60B1D14B4F4",
- "section_salt": "56F596D16E1F87B107EE86102FFC6D5E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "F076F2B4FA1F3704DDC4EC5CD60C4657",
- "data_elements": [
- {
- "contents": "B62889",
- "de_type": 72
- },
- {
- "contents": "68FDB8895CB7ABCF18390616113107B73321A905D22FDB99",
- "de_type": 175
- },
- {
- "contents": "D5A173DC337EFA759D443C50F14F25AC18A06D44C4",
- "de_type": 354
- }
- ],
- "encoded_section": "6D911000CB9C39FAF5D89CEF1FD7E313DC2F95D79004919332D945C714DE3B58B0762E7F9378D80F35D0DE1E8BD321656B270EA3379F029FB09E44AAFB091B0678A0AB69B055CCE5C2F576EAE52DAC0D6C11FD6A878ABF337B9647FF259ED24F5687641E8ED13A612810F22EC240",
- "identity_type": "provisioned",
- "key_seed": "907E34F78FBC8CA40FCA224C12B95BA2C4A0148BA0D19BDADEE1798579EF7D35",
- "metadata_key": "B524D8ABD8E7DCFD13CE922F2FD9EFAC",
- "nonce": "AD0AC7BE3A89262786A55139",
- "section_mic_hmac_key": "690542812A39DB48DD638AED6021A250767F79604C638E361A8F7F5FE92C5E40",
- "section_salt": "CB9C39FAF5D89CEF1FD7E313DC2F95D7"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "B9549633BA2531AEF16D592815C12269",
- "data_elements": [
- {
- "contents": "BA",
- "de_type": 79
- },
- {
- "contents": "796F131D0D034508",
- "de_type": 141
- },
- {
- "contents": "0245",
- "de_type": 522
- }
- ],
- "encoded_section": "48911000897E4DB6C940976334871B64811D8379900416AC9B5760E31F037634EED3B9C81AEF75B5134E7065DCEFF8CF3197BD2242BE4E29384125B35FB9A4BB7D4D1A650F1E30DBA3",
- "identity_type": "provisioned",
- "key_seed": "E66AECA540D070C5E430CE461A3E209F0650AAF3E69CC79C20935DEA3D468A46",
- "metadata_key": "B2AC31CB7B88B7FA165B5E41AE706E04",
- "nonce": "E3CB89790FEA866E19F4926A",
- "section_mic_hmac_key": "EE72E920E379F06879BD8AED8EF9BF8D5903E5CF94A83815929260521F84C17C",
- "section_salt": "897E4DB6C940976334871B64811D8379"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "088B6339D6D727E797DD1EA3EAC999B3",
- "data_elements": [
- {
- "contents": "DDCCC496B0BE050B7607",
- "de_type": 850
- }
- ],
- "encoded_section": "429110008F292492B012ACE2C0EF4F25E0901F9490022CF669461319C1165AA131A7BF2835C97FC3ECD77522FB93CE0675D0313D7AB03E230DBE46E286192CD451E9FF",
- "identity_type": "trusted",
- "key_seed": "CB61506281210764CE5E3504BF3A41AF69196369375BFE16245B0CA19421650D",
- "metadata_key": "B9696864507A1DC2EF99DF5441AD25EF",
- "nonce": "9CC88703DA8A3C82DA5DF32D",
- "section_mic_hmac_key": "8DE5B98089EEEAB5ABB079EE0C6C8F37289CFCDA74B81BE4F3599EA7F10B3A3C",
- "section_salt": "8F292492B012ACE2C0EF4F25E0901F94"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "142EF4EFAA03C54D43958647B4A9053A",
- "data_elements": [
- {
- "contents": "B8E42416CD4B3281EE2EDB1B36B89DFD17D35C46B354D6",
- "de_type": 441
- },
- {
- "contents": "72787349FDC162A25D13BA",
- "de_type": 664
- },
- {
- "contents": "E0A29FC658F199AFF9",
- "de_type": 308
- },
- {
- "contents": "8859EB742D3B433BD0F992285B9EEAA1",
- "de_type": 319
- }
- ],
- "encoded_section": "7C911000DFCC6FC56956B0D99F2F29682117B0759004E48F8DE2D74AC7FEAFBEA42F808B4DCE7D17F2841097DA561701AF9F365BA4F702A4CA79D40F6F88C383487B6524BFACDDF294D2DE20CCD7B2BF3A765598144323933CEAD4C1A5C6522A867A5BFDF562A43C537A50A3987AB4F9AE446043117F7A20E1C41B398F",
- "identity_type": "provisioned",
- "key_seed": "311F871B4605A04B3310C13D7297AEE745EE105A5D116D05B114A39C2DE27B85",
- "metadata_key": "18C51BF65C261CFB2F8106AA4C8476B6",
- "nonce": "1F562F760A35CE9445D40B28",
- "section_mic_hmac_key": "6F25A84CB39DACD4B9DC7BB4354EE7BB268FBB559121D0F530BE2FDC212C7478",
- "section_salt": "DFCC6FC56956B0D99F2F29682117B075"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "0C3C901C96C81D5822A42886F20E4D24",
- "data_elements": [
- {
- "contents": "",
- "de_type": 437
- }
- ],
- "encoded_section": "38911000B3AF643914DD58250EF9795F77B0FA3B90018EACECB07EEC9E2E72550CB8C373FB6EDA5F1CAF378E19C6207AE3C6F7CDA7E1321B56",
- "identity_type": "private",
- "key_seed": "39739EA99CFB0EF8200B08C12213FB3370A4DFB58CEADA17764FBCA9FC05B914",
- "metadata_key": "A1F9BE98BF2BE21F318FF60776ECF594",
- "nonce": "E067B8B38B20F64D35EE4B1C",
- "section_mic_hmac_key": "DB710921FA3969941C33329A0FC10AED0EB49A7BEA627ABBAB6E4BBBF6886478",
- "section_salt": "B3AF643914DD58250EF9795F77B0FA3B"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "0DFF79575A76A69E5545F23F2D568BF5",
- "data_elements": [
- {
- "contents": "8D530D2FF57D6A089257EEA03F2643CCF76DF103",
- "de_type": 739
- },
- {
- "contents": "88E7ABACA5E9",
- "de_type": 563
- },
- {
- "contents": "9CA636C900FFAEB51060B40D1E60D751840CA3",
- "de_type": 831
- },
- {
- "contents": "8AC0EC13CB0B",
- "de_type": 944
- },
- {
- "contents": "4FD1B972DDA8376DF7181799B3AEC3D4FA3875CDA0B9F2A244085CDD72",
- "de_type": 263
- }
- ],
- "encoded_section": "94911000A089A545FC2F1E048CCFEFF6FC7530BA9002D0BA12200150BF15A06427841CC00E9CC99FC3032DDB93D46A96DEC5F92DD89849328418BB27225CA77542A2BBDE1896CF76D0143EA351786BC3DB40228363971552E8CB5BF440F6B6569B610D0F09B6E6B46922D86E1DB35A2AE0507A10268AD4077867FF55C7286971DB6BF27D01B68BEF04B9FE12FF660A0ECE154D2B27",
- "identity_type": "trusted",
- "key_seed": "5CE70AB764EE544F6A9B48791033EDB78D6541368BE2A02C41C93BEE27645D15",
- "metadata_key": "29F72458A212E09F3E13A14D927CBB97",
- "nonce": "C6002C4E093E3ACD57A0DA8A",
- "section_mic_hmac_key": "BF94C21240800483EE76C69F94D1E7E867EFC9AB11CE74E672C936634C0F7883",
- "section_salt": "A089A545FC2F1E048CCFEFF6FC7530BA"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "048C8515B3970ACA7E06DD671E758AB7",
- "data_elements": [
- {
- "contents": "672D400589BB794E2A33DE53A62FF97458DAC28DF015F304CE9EBCE8CF",
- "de_type": 502
- },
- {
- "contents": "C2D9DC3F76FC72BE4BF7D3AFF43B1041B0BC93512BF73ADA95EDC4",
- "de_type": 692
- },
- {
- "contents": "B010CC19D7FB",
- "de_type": 129
- }
- ],
- "encoded_section": "7C91100095FFF79474626138B7A9200A474C449F900259C6F85AD235549231775D62E7E710EA91D16662378B15BD5C34B7D14543BB5F289B37E17599C0AF6572A0630356ECA030870CAE9697E92FA9BB0632BE009F643C018B1571592CB0750C158BE299806D0673779B000E047CF4E4D8BD732544EDE5C6CBB4F71E05",
- "identity_type": "trusted",
- "key_seed": "9F52A2F6A5F571B558151E84D8965C427733005A6CD580E66B5C398443BB7479",
- "metadata_key": "4C95AE9955DE9A3684F52B00461035BF",
- "nonce": "33CA4805B89AE4F80DB67BE3",
- "section_mic_hmac_key": "4BC7E7FC685A2E3D9EC90B20014586C986E3054B456EC2851E6606AEDC3955EA",
- "section_salt": "95FFF79474626138B7A9200A474C449F"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "4C9F52374665C592601F5B2BD404B94A",
- "data_elements": [
- {
- "contents": "91EAFB7D",
- "de_type": 663
- },
- {
- "contents": "22027014F8D43A605E0C179A1E144A3058D7C024359E7A42B83DBA9B0F",
- "de_type": 163
- },
- {
- "contents": "0830ACBE1994FB",
- "de_type": 291
- }
- ],
- "encoded_section": "669110005723CCC591C04732B131D258FB5C9A219002E345F42E0D2D02EF57D890EE70F4A95BFE4C9651BF6E2067BD6707820636D5E484F9D519029D86290ECC42C846AF1D0C8D03BD155D791F47637F9F698A8B9D71E261712DE1F1219ED87F7F2045BC240A41",
- "identity_type": "trusted",
- "key_seed": "1D02A26B11FB561BD54036A1FA2B325E74D226CA72428C391650E5249B40E0E9",
- "metadata_key": "702C35764676569F45279BE0BA2F941D",
- "nonce": "08838921E1C57E275B554B1E",
- "section_mic_hmac_key": "163F7952B1866F16C0E5CD3CA950D786E53F04C7CEEBA1946AD76C16185F52FD",
- "section_salt": "5723CCC591C04732B131D258FB5C9A21"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "A3034AE0322F5E77ED6B21B5E5368108",
- "data_elements": [
- {
- "contents": "537F96FD94E13BE589F0141145CFC0EEC4F86FBDB2",
- "de_type": 571
- },
- {
- "contents": "D301FFB24B5B",
- "de_type": 541
- },
- {
- "contents": "EA95F07C25B75C04E1B2B8731F6A55BA379FB141",
- "de_type": 51
- },
- {
- "contents": "2EFD3101E2311BBB108F0A7503907EAF0C2EAAA60CDA8D33A294C4CEACE0",
- "de_type": 729
- },
- {
- "contents": "B0",
- "de_type": 411
- }
- ],
- "encoded_section": "91911000DE2A89ED98474AF3E41E48487E8AEBDE90014C18BCB9F9AAC5C11A1BE00A10A5DCD2C49A74BEBAF0FE72FD5053B9DF8B9976C80BE0DCE8FEE83F1BFA9A89EB176CA48EE4ED5D15C6CDAD6B9E41187AA6316D7BFD8E454A53971AC00836F7AB0771FF0534050037D49C6AEB18CF9F8590E5CDEE2FBC330FCDC640C63F0735B7E3F02FE61A0496EF976A158AD3455D",
- "identity_type": "private",
- "key_seed": "959D2F3CAB8EE4A2DEB0255C03762CF5D39EB919300420E75A089050FB025E20",
- "metadata_key": "EF5E9A0867560E52AE1F05FCA7E48D29",
- "nonce": "23B64C2B1724E5AE9528FCD4",
- "section_mic_hmac_key": "2F1B12002184860A496B2DF7FB743401BA8E8BC5F22F661BAD69335E99DB8A19",
- "section_salt": "DE2A89ED98474AF3E41E48487E8AEBDE"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "15AB0E1BF3C908D5A92C9A52158DAC00",
- "data_elements": [],
- "encoded_section": "35911000172C7E49FB61097603390278AA4B48F8900477935610288681FDC9B7250022F01CFA66E59183F392C5C2485D8240ABC96D15",
- "identity_type": "provisioned",
- "key_seed": "C1FE7DD8760BDC37EEED65E07FF3F9DB9B2DA247260038675679921566A4466C",
- "metadata_key": "D84140E3576B04F8D9290744C62D20A1",
- "nonce": "A8FD0BF085BA1C3E8A23FC0C",
- "section_mic_hmac_key": "3BBF201D9180707DDF5DA4321B477A2D0CFEFC00D72EE560F0E41B5178315366",
- "section_salt": "172C7E49FB61097603390278AA4B48F8"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "2C8D685B3ED53CA46D6A6AC126596C84",
- "data_elements": [
- {
- "contents": "E95043396FF5CE7FEA272F1E9D8A",
- "de_type": 359
- }
- ],
- "encoded_section": "46911000B9EB78D15B9493668E3506DD9E7A2DEC9001884E76187E89CB0107A5090D664508854DCF8722E98904E6BB57422710F3CBB3271A743BAE59467EED31F62B714060F040",
- "identity_type": "private",
- "key_seed": "0C43A03CC43B6536086910E73F4499C368BE47235FEA439124005FD91047C8DD",
- "metadata_key": "6B8DFEAC098F9DD035F14843C3196CC8",
- "nonce": "920205C1FC28E58575E08D47",
- "section_mic_hmac_key": "5FE0D08732D5615AE4447E726DEAB0083D9458E66DAE596377DDC103C34A4442",
- "section_salt": "B9EB78D15B9493668E3506DD9E7A2DEC"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "C56F4750DBCFE87ADD8E2159B3EB5646",
- "data_elements": [
- {
- "contents": "148ADAFBA927A9A3D361CB34792A1FD1311A",
- "de_type": 16
- },
- {
- "contents": "37215F",
- "de_type": 776
- },
- {
- "contents": "5B75B7A4044E3100635709818ECB099706",
- "de_type": 563
- },
- {
- "contents": "4A70F7FE36FC",
- "de_type": 49
- }
- ],
- "encoded_section": "6B91100010510FF96F9DE71AFB125A00637D9A159002692F0CA5C9AD242760DFCCB7F9E445AB0545ABDD91DBB4E6A7DCAE21ABF58D01CC3C1B95AF9442EDF2FA1ED5C551FABF071981137AFB04F4B67F13D43CAA959F53819A4B90913C7CD4B945665E74898BDEEA50939FA6",
- "identity_type": "trusted",
- "key_seed": "18D77C2D69389B38F6430DECF46D34893C188EDF6F57E306BD159A441D602D68",
- "metadata_key": "0DFE12776B497E72E415E41625C4A2A4",
- "nonce": "A25A744723723AB492153CE9",
- "section_mic_hmac_key": "B1BC6C3AC220AF74BAC5EA8A85692095575FA6C2172ED9E66669114164BF55E1",
- "section_salt": "10510FF96F9DE71AFB125A00637D9A15"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3BDA27AEC19E0135552AD5ABB02C45D2",
- "data_elements": [
- {
- "contents": "92F73CEBBE55EFF2391445A2B96299155B78",
- "de_type": 984
- },
- {
- "contents": "8C4615561E9CF7589FA8E6F7B57893025DF55C",
- "de_type": 919
- },
- {
- "contents": "DDF6FEBA14ABB1B094A277D361A8C70B988E1010534FAFDF25",
- "de_type": 676
- },
- {
- "contents": "8650458E65DE07BFFCD2EC46E0D4D05609A66D9AB777FA341EFE3280A5AC",
- "de_type": 784
- }
- ],
- "encoded_section": "9D911000D86DFF361F5567606CCBAD126A86C01390028E06467447060E4E27C066C5B7F8B785D2476A0FFACC9C85C1E2211B7609D8A4A2C7036F982F923D1DFCF0161B60A3AA5DE2287B909FABE3E902EF1CCD45AB7D9CACE4FAB3C05CB9A00FCC5AD93E9E3B2B31A2ECC226D2209BF24FC7D13D0AE53C912D03DF47F1A4C132BF949C555E8D35436011B852DDB228F4964483F820DA360FFC9506087F99",
- "identity_type": "trusted",
- "key_seed": "A6915F7F275F268563F06B70294DE268F4C8FE2ED64831049F5071DD2D7AFF7F",
- "metadata_key": "29B703C99077654D9EC2BD86066D3CC5",
- "nonce": "ED125BA0057DCFEB89ED7190",
- "section_mic_hmac_key": "1B8F822A197030498D51E0F2E4B9C7C306074D7C83C73CAE508D2FFA46EB743A",
- "section_salt": "D86DFF361F5567606CCBAD126A86C013"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "9E629E04812454CB600A54C8837CC057",
- "data_elements": [
- {
- "contents": "C1B396A29B6967ECF8673E009B2E7F94C4DECD7FA20C176EA0AD98B9",
- "de_type": 253
- },
- {
- "contents": "3FFEC56E8DB922CD8C5AB5E47452E571",
- "de_type": 605
- }
- ],
- "encoded_section": "67911000229151F0CBA214F520EFDBF30FB4DA43900287511210A4AF78894FA1DEE707C412015D271BEE2789F49BB5DC67D44E5B9E58B6421F4C834D13F29940800D31315840591BD869F1C2D2887914627DE54D90AA254C6CE1699AA9CA7198ADD71BDC46D91117",
- "identity_type": "trusted",
- "key_seed": "1C9A55E064B78E94CB6B070F433CA94D21CB3318E048A7A2CAA83FF958419794",
- "metadata_key": "1A240C90D7E260458660C8B07F991AE6",
- "nonce": "2BEB4BC7C05434ABBA19E538",
- "section_mic_hmac_key": "050D12FF03D51C57EC4AE018EDC1896C38226E1A0481362E415CCB28F5A01B5D",
- "section_salt": "229151F0CBA214F520EFDBF30FB4DA43"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "8C996EFAD07DDDED26DFDF98812CA923",
- "data_elements": [
- {
- "contents": "B7C019E21BDE02221C04A4",
- "de_type": 43
- }
- ],
- "encoded_section": "42911000D1662A41EA8D74EEDE6BE6686D41414E90029CE0D1823D6C861F9B05C79235D6C1CB99634640B9BA98F7B3C72B67F242E2E40E36C937F671A88D63FF97C4C4",
- "identity_type": "trusted",
- "key_seed": "2027245C1810377C3846FFC4F33A46FD5F55BEFBB13C9EB07D7D5AD3CFAB48B4",
- "metadata_key": "9F4AD9EDF0A6CAAD2E9E99871E4CE52C",
- "nonce": "A71E97EBB5FEF5C10118B443",
- "section_mic_hmac_key": "3BEFA04D9C10EC14E050D8106803C71F788E338E191EDFA21FC2029FE1A90922",
- "section_salt": "D1662A41EA8D74EEDE6BE6686D41414E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "AE8C6F011FE35C9C96FE8EBDE339A41F",
- "data_elements": [
- {
- "contents": "607A867B3B29B89041F9",
- "de_type": 979
- },
- {
- "contents": "5E799499",
- "de_type": 25
- },
- {
- "contents": "92CB515B79EDD5E37C12C6B5864DF420AF7DDE1B5919331DA7",
- "de_type": 577
- }
- ],
- "encoded_section": "649110008A4AF96D2B686F8C79E0133C7A1300D39001533E4A9492889398E4BEA2572B455C201BE24382C5D0FCEF256113AA7541173BBC6A2B9AFC3CB2A133424BA12055069603174E36F3407444B5FBFA5BFAE8C8B6BD893AB31B9D869105014A931AEA10",
- "identity_type": "private",
- "key_seed": "F728E206C88A47D4C5063BBF54C218435A04B921E3D0E2774572D88024076D7E",
- "metadata_key": "CD8451667D7BBD7EB4CD5E456ECF8167",
- "nonce": "3F7D4273CDA786C66C557ADC",
- "section_mic_hmac_key": "82B0C8B8007802CE1CCF367F07830FDAD2401C8EB5849613602E568E634DAFB4",
- "section_salt": "8A4AF96D2B686F8C79E0133C7A1300D3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "9078B570449046A4C6FD9246ABE3E17E",
- "data_elements": [
- {
- "contents": "381690D8CB5DE6CB",
- "de_type": 724
- },
- {
- "contents": "905EB45FAD",
- "de_type": 144
- },
- {
- "contents": "969FEFE0",
- "de_type": 302
- },
- {
- "contents": "75202C93DD512023EFD3EBF3",
- "de_type": 742
- }
- ],
- "encoded_section": "5E911000F765D4EE37755137F6B7AF43D4ECF2CB9002361BF7AEC5BEA9E0F9790E737E559951EB09254D0B4304A81E21FF7C9B463A8AF4D29B35B6B909C255286B707B85F028D277148C6A82877695FF915BD0602946C37F4AAF6C1C315B98",
- "identity_type": "trusted",
- "key_seed": "DD3AB1ADE4D985E6D6E67F2FE19DD6A75A9F5B4560CD3C05FAFF8A88C283AB3F",
- "metadata_key": "D53DBD8613161F1527385E5F27FEE124",
- "nonce": "D30A2D8CEFAB8C91E0B1799D",
- "section_mic_hmac_key": "EDFA40290EB30E6669C551947A061A587843CCE47F4620E51ABA239AB79AA739",
- "section_salt": "F765D4EE37755137F6B7AF43D4ECF2CB"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "C2FF97FBAB946B17D2BD0CA0712FA7DB",
- "data_elements": [
- {
- "contents": "B0F9DF275D2D5A37C95B9CC9AB",
- "de_type": 114
- }
- ],
- "encoded_section": "44911000EB645DE61C9BB4C40BC585AABA223BAA9004B40CE842866C9F317B5C429C501392E13495FA18E48C34BDABF4152C8E98E90ED1AFD11BCABD4EF60CBA9347FB0120",
- "identity_type": "provisioned",
- "key_seed": "CAB68F8D497B54A0B25EE602EDC659B8C12F9E9E49EC8FC2C2487E8FA955E606",
- "metadata_key": "CDCE54153DA53A283DBF35F0D456FBDF",
- "nonce": "D7FA723581DFA37F8CD7F284",
- "section_mic_hmac_key": "EECDEE6DCC125C40BD1002DFBAA77C8D5F16D6A9D152E6524A13E213F5CDA36A",
- "section_salt": "EB645DE61C9BB4C40BC585AABA223BAA"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "BD5FFED9F8FF99EFD9276BAE103C8520",
- "data_elements": [
- {
- "contents": "A9F592F1DCA1C71CCF03CC0310DF337C9A",
- "de_type": 683
- },
- {
- "contents": "E18AD6552B4C",
- "de_type": 277
- }
- ],
- "encoded_section": "52911000A798801A6B6BB3B3CE199A04C6D39C749002F4A793DDD478205BE47B9D5A3D02821CFECD82A205E596D82F1CA5F52DFD12D2F160C20332DD75B56CFF48AFC079B80AB8151D3FC020D71FF03A220692",
- "identity_type": "trusted",
- "key_seed": "9DA9C8ADB2F20D379E5C103E92D60D4ACC946AD0DC57B08E71A6CAF174DE27FD",
- "metadata_key": "32044EF9F7B354E253E7206AC19172BC",
- "nonce": "FD61DCBF349648F6BCAD5FF7",
- "section_mic_hmac_key": "CEF13D97D862C57A7CC2ED89FA453B5F331A39B46EF3DAED677C6354FCF41A99",
- "section_salt": "A798801A6B6BB3B3CE199A04C6D39C74"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "AB8FC3047B5D459C0FE3A8D32DA1D396",
- "data_elements": [
- {
- "contents": "70E9867134E018A407BFFA11681FE66225551030",
- "de_type": 694
- }
- ],
- "encoded_section": "4C911000F340B13BAF10C096314AD12554265BA69004D98C2427C11201067AAA42C262F78315F0FBD68F03CA256E74CD74CC39E3B0399E41E8DC766AB30241498364F94C204BA6F1D12C66C752",
- "identity_type": "provisioned",
- "key_seed": "9E50221DB4D19E3E2E6E0D61F2FE4FD765B0AB77D795B8BF9DEE945C9258D90F",
- "metadata_key": "E59AB0FB0471EDE9516038F2B830FC8D",
- "nonce": "D547910B27183848271E093E",
- "section_mic_hmac_key": "0C67958E203428FCD8B023C2C97BEFD62A64E72DC0F3F9078AE494DA235E4E80",
- "section_salt": "F340B13BAF10C096314AD12554265BA6"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "5E155066D56083328A063FBD5AFBF1CE",
- "data_elements": [
- {
- "contents": "B2E8AD80552E7D",
- "de_type": 638
- },
- {
- "contents": "EBA00821E05107D40E6B3CAB8E86027D497F34670527D1D6",
- "de_type": 337
- },
- {
- "contents": "549E6C2D1425",
- "de_type": 826
- }
- ],
- "encoded_section": "63911000A847D51D7D049D481D63F14F4A8D01099002FC5925A9E42B41321E56021A3D01157DC10E00CFF86A66638C7313814DF85E2E050AC4235DE9634416B34AAEC4419D9F50D49952742723228FA5CC8A8981C6E5E71904FE5FDAD5111C3C81C88E65",
- "identity_type": "trusted",
- "key_seed": "BE5027936C60695FF4EA18AC1F81078221C50A8C22C98F36C9A5877D369E4000",
- "metadata_key": "1B43759002C9095970DB092A0086FECF",
- "nonce": "CCA806551E3DE4A2C7015C4F",
- "section_mic_hmac_key": "B8C388D47A6B125B3E637DBE4281824A170687F5D596510B94A95DFBD0420A5F",
- "section_salt": "A847D51D7D049D481D63F14F4A8D0109"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "BA3816EAD76DAC246880A27F137D4CC2",
- "data_elements": [
- {
- "contents": "3909A77A6295",
- "de_type": 706
- },
- {
- "contents": "A360F1",
- "de_type": 563
- },
- {
- "contents": "9B77E78C7CB64198BC2E5E676080B8652C88A3F1A71B5B62CC5B87",
- "de_type": 496
- },
- {
- "contents": "DD4080284EEF0BFBA61283376C7A",
- "de_type": 129
- },
- {
- "contents": "D3",
- "de_type": 362
- }
- ],
- "encoded_section": "7791100034A1CA42CE8D750265DD13710E6AA8F390024301C25BBA38E693BCF7834E08B62F4B4569EC8704250959F6EEE5971C2E25BB63EF65C1CA1B20917A433DAA9379ADB3773F463BC8A81A938CB83EA4E1BBF4CB1A4409D38E9511B4660A5C5458337CCBD98AA3E3A41D88C98ED0A9D8AE27F28206D0",
- "identity_type": "trusted",
- "key_seed": "7052FBAFC59D8ED636F51F254C3E8D2429604C2A58A3A0A27C54C2D83B4D4353",
- "metadata_key": "0230CE096D5CBE15B55F65F270D0D411",
- "nonce": "51FD2C7EBA743483252DA523",
- "section_mic_hmac_key": "C1941723E73EE200B78932065A479E2380FBEE95082846C9FEEDA9D35C13E84E",
- "section_salt": "34A1CA42CE8D750265DD13710E6AA8F3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3F7BAA4E9ADF649F68504D2BADC49E59",
- "data_elements": [
- {
- "contents": "C7CD03AABE413B68D38D5528B8",
- "de_type": 784
- },
- {
- "contents": "BA87E5F9338B888B0ADCE8C80BFFE11D2467303431",
- "de_type": 902
- }
- ],
- "encoded_section": "5D911000D22DBB4DD6D440F26183BD13D0C3DF6A9004AA523D21ABBF464C0DD1166437AF2EE5159310A4E2C500A84A7824DA48C2DB85C9BC79B60DA83EE61EDFBA617008A7340431E5B7ECB19E7F140D6F0D7E22589A51AAE13A00780820",
- "identity_type": "provisioned",
- "key_seed": "1E2D99F50E548FC49590D5E6C066B4DC955EF40DDEE79167EC359E551048E1D1",
- "metadata_key": "83D500F6D6106BC3C2B17AE408023E91",
- "nonce": "4A9AED02A25AF38FB2E2E2F7",
- "section_mic_hmac_key": "B29B84CFF65C3EE4616A502AC61C029C706D6B1EDD39EDF4D76EA5A84453BF5E",
- "section_salt": "D22DBB4DD6D440F26183BD13D0C3DF6A"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "5BA9C6F943DAF529109F4B100F49D597",
- "data_elements": [],
- "encoded_section": "35911000C739C6227A353DD9B0EB277131E35DCF900469ED27AFB7C387B5475E150CD81AEC4884892FD73C27B796E7685D75C10A7F71",
- "identity_type": "provisioned",
- "key_seed": "1344FE8EFB2E14874FEB0571343BBA222C0FD904204BBA55ED94F0CD28C26FB7",
- "metadata_key": "DB1BAE09B154172E09141BFFE4CF561D",
- "nonce": "108AA9D4432E50BCDECCBD6C",
- "section_mic_hmac_key": "2E20757E70673D996C6D58E403A0F87CDE24F7EE3038C17FE07D435B44093CD5",
- "section_salt": "C739C6227A353DD9B0EB277131E35DCF"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "39CD401AE8F611D1651E0FDD59BA8F45",
- "data_elements": [
- {
- "contents": "F4658B8BCCCF49B7AB79",
- "de_type": 564
- },
- {
- "contents": "C9F2A6B90E08CC",
- "de_type": 988
- },
- {
- "contents": "820BE5C34A2CC3E9",
- "de_type": 870
- },
- {
- "contents": "0F02CD73",
- "de_type": 573
- }
- ],
- "encoded_section": "5E911000E6CBCB218624EE2DC2DBABAB38F837769002F43D65267B214BF792B14655201C57B346BF233AEA5FD07FC5163FE7D1659F6A8DB901B503D26320F94D3B25EC2647F294BAD0748EEE05FE24F42CFA240062F74715FAF8CB6873C017",
- "identity_type": "trusted",
- "key_seed": "D72CDA23016D822CFE1E5294916DC83CF98EC2ADAE9121F80803386DC5CF6E78",
- "metadata_key": "47001AE1B7E542147BF57D1C62F22F9E",
- "nonce": "B677F8EEF05E5C4FD69BC645",
- "section_mic_hmac_key": "CD8F4F64EB964FF7E0EFE036347DD0007A1A763B3001F02361CCC3A680C368FF",
- "section_salt": "E6CBCB218624EE2DC2DBABAB38F83776"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "194ED59DCF4144A697CD1AD63E33A3B4",
- "data_elements": [
- {
- "contents": "D5156EF7CAD1096B1EBE82E0",
- "de_type": 777
- }
- ],
- "encoded_section": "44911000032224758D14BA41AF92F6D88A501E2C9002C7D754757898C9E34AA838CDFBAF155B30084E02BE29B58C33ACC954F941842FC053B0ADD4CA9F3D3618EDBA2CDA81",
- "identity_type": "trusted",
- "key_seed": "F77600BA15BA4C8B396C8A0C3B8ABECF2B064A045E583BECD39116C572E7AD12",
- "metadata_key": "DB7F42852277D6552C91815416FCBF72",
- "nonce": "5A2D8E75D0B7634F06D7325A",
- "section_mic_hmac_key": "862D13102D1431D175E2E8B6ED0D30D99C6E43EFED3FCA6D14CFD8AEA3BBE15B",
- "section_salt": "032224758D14BA41AF92F6D88A501E2C"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3337A6A8FC085CDCD20C3F46E78E7AB5",
- "data_elements": [
- {
- "contents": "70D83068132E37C88B72A4EE79D173537E8F",
- "de_type": 277
- }
- ],
- "encoded_section": "4A91100013D9056CD070347F927B0F615DDFEC549004C7894D8A1B5608C1EC182CC0AB86375EEBFE92E0A4EF6878AAFBCB637738E21F4EA1C9F76D65EB4AE29BC86CE43C9F49859C66F2FB",
- "identity_type": "provisioned",
- "key_seed": "1507CD75F60429CB9E63C4D4A09FEAC92E772223D9E95838E8784AE1969F3E7A",
- "metadata_key": "481E466127EF90D5C53596E8552EC52E",
- "nonce": "F7A694ED8C95C9D7A755D82B",
- "section_mic_hmac_key": "F7355B49456F6C57FE860ACCE4A711214D71D5F08B574E5BA37E165B52000A36",
- "section_salt": "13D9056CD070347F927B0F615DDFEC54"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "FBB1328618CCD896CC70AF937CAE8281",
- "data_elements": [
- {
- "contents": "467333809F3B",
- "de_type": 952
- },
- {
- "contents": "50CE12F4FF7B16B5643EF1C66368DF27DEDF3CEC9B24A3",
- "de_type": 300
- },
- {
- "contents": "08443858DD0A",
- "de_type": 124
- },
- {
- "contents": "E873C2B86B0C5A28624DBBFDE0AE3D22D03EABBF5BA71EAD",
- "de_type": 448
- },
- {
- "contents": "F1447D2F9281DBEE34476C48B22351E8F27CB782A10A29FA69E5ADCB3EBE",
- "de_type": 399
- }
- ],
- "encoded_section": "9C911000E33DCEF3193A00CA24590E41CB1607C79004439EFC4200D70EB58A7579DEBD80F04B5E8002A076C37A1D6510BA493BBD60569363F1FC3FC5A379DFEF1BDE620330DA1C8D06AB062EB96C92762FE17DD96776B35D13CA41488C1C83F2FFE0D0EF5262B632D856D10CB666762BA5CA742A0E9E95C9931779E319C7854ABE32BE0480D1FA754E1EEBEB1521C148FBF4A70F3185091CB04D57884A",
- "identity_type": "provisioned",
- "key_seed": "D30C0A924112C23C73BAC89EC03E7F9EB81E26916553AB6556C1240C20EC37B5",
- "metadata_key": "308A7C574957C93A9B3E6CEA175AB263",
- "nonce": "5D0946C2808A4C895626EF0B",
- "section_mic_hmac_key": "8421457116D650DB88EB790AFB90AD99C53EFE2F875528CA25ADAA615F35D9CE",
- "section_salt": "E33DCEF3193A00CA24590E41CB1607C7"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "E03DF6ABB87D6F554B5BEC78A7E8B0FF",
- "data_elements": [
- {
- "contents": "B94A3080F25FE185C6C36E9A21405519666684E0847BF36DD115A926",
- "de_type": 503
- },
- {
- "contents": "",
- "de_type": 415
- }
- ],
- "encoded_section": "5791100094339CFAA454A5D2E977F38C35E2844D9002E15B4F8862B4A3E4D5FCDDEC6FC36567A1E9A6EC6E2CAAC28CC1C72CC81CB4E190AD8C8C1997EDA2A8391662DC44D4D5B818959ACC574FA1CF7E99645C4DF138B587",
- "identity_type": "trusted",
- "key_seed": "6B1BDAC7E669C8EF0847707AC2365C0D3864B31D6F13C088D4630CAE016B520F",
- "metadata_key": "A50CC2AEFD3369D7D1DA0F0D0E537F19",
- "nonce": "0C4819136C0E397ABDD9E354",
- "section_mic_hmac_key": "A1FC278429196727FCF080260972AC6BAE2670C7383C2E297D1721428168F8C8",
- "section_salt": "94339CFAA454A5D2E977F38C35E2844D"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "D79C9AC03BE4012DC980193BFD6B9844",
- "data_elements": [],
- "encoded_section": "35911000711C9EC86B8A068AF07B7FE5C85CC9D39004D54FC742603A383E4F153DBB7462EA99ACDCA8E5B667784D8DDB99FE360DABB7",
- "identity_type": "provisioned",
- "key_seed": "6FC2E3B1B4E9D1A97ADE86D36D78F377C5AF881DE70D981C8553DB86D830F617",
- "metadata_key": "FFC3763940BF40D4C90C1C9F1A108195",
- "nonce": "5FB63D89B5C5D0A2908B0A62",
- "section_mic_hmac_key": "3F353E77278CAC09E16D0F86B6723510700210D5C8A73E6EEF04921FDDE689F1",
- "section_salt": "711C9EC86B8A068AF07B7FE5C85CC9D3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "CDD28EF3B99341DA9DE1C30C254E4430",
- "data_elements": [
- {
- "contents": "99CE21E4964A6A7C14E6BF387369",
- "de_type": 361
- }
- ],
- "encoded_section": "46911000E9FF177F159C1A081403717389F200EA9004505BB69C948A0A4849FEA66E702DB7500BC961E0151EAD701AA1BA69C29A1E2B363678656DB7E72D4A98AA28A8894CE84B",
- "identity_type": "provisioned",
- "key_seed": "A2A3EBFA3847569FDC2713784A56CD71A1DEAABE14190EC0B86AF832EEBBDD59",
- "metadata_key": "4432862698BC0A055C41E6219F86C655",
- "nonce": "64C1217301A32C5B82B94358",
- "section_mic_hmac_key": "C78D782F47CBEC0D0F0470DEC491B8808A6C08E71F5C325E0B359551AE38ACA4",
- "section_salt": "E9FF177F159C1A081403717389F200EA"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "F2912200A19661C7B3256F2ED8D635E1",
- "data_elements": [
- {
- "contents": "7321",
- "de_type": 467
- },
- {
- "contents": "",
- "de_type": 743
- },
- {
- "contents": "B58EA8527B77EB7DBF5CF9D10748D743DF6E8F37D8",
- "de_type": 592
- }
- ],
- "encoded_section": "5591100029FDA91C6673EE9F5E81041BE492146890026FF0F473F33B7DE9BFA2EA578382EBCBE4227D5570F2365433A6A4751FD10BA87D17552C9315E4ECA5A45D4EA4F20AC118D0CF61A0E0E49E90C9658FF4D1CC6E",
- "identity_type": "trusted",
- "key_seed": "FD7967CD290B0ACCA1FB012C6B17FADB54CC062A92E4E3F095B6221265606BC3",
- "metadata_key": "7485DC8BD4A36F721112C2947751F068",
- "nonce": "CF3A08D31D6DB3F85ABFAEFC",
- "section_mic_hmac_key": "DE0AB90DC2E5437C201A96A529552965E9113AE01E76E225E906DB2C854C4F74",
- "section_salt": "29FDA91C6673EE9F5E81041BE4921468"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "425A003859115F90D385DED38FC3138A",
- "data_elements": [
- {
- "contents": "FF1E4283ACD7",
- "de_type": 592
- },
- {
- "contents": "FBE130FC8F63BD7012",
- "de_type": 224
- },
- {
- "contents": "7DEDF0BFF3CAAB7C6EEB72A4F7B906AC50A92F6E27F0C0BE5DA402D6E1",
- "de_type": 740
- },
- {
- "contents": "B3929F152C596C0BEF4233703F00B6621C1FF3A358F3C86DCFB16B72",
- "de_type": 312
- },
- {
- "contents": "0F5043C11D1C467CCDCB83DCE0BE43AC1D94DD5611",
- "de_type": 891
- }
- ],
- "encoded_section": "A1911000D3F3AF795C519468EFC23F73081ADE8E9001D17E0B80D5304A3B3078ABD224B53EEFF7BC4D82C69097FE3731085ADE750593E3267702827CB9CD176EE205CCE43458E2AED220AABE1587FF7FEEFA571B629E2A205D207044EA651809B9F5C9102C35E0368A0C22CEA27DAF899A987DD40352EDA04C8DDC7ABB3B6F279C7779162B472543393F37A9EE4A9A6F1E6ED3EC8E46551715F1F254A13E0604C71E",
- "identity_type": "private",
- "key_seed": "CBD5BDDC7DF1CF4DE8C67B8C5D8B3936E4370BD2FB8674BDD032DAB651935098",
- "metadata_key": "85F9B7DC74148374E28EE18DEB067DDC",
- "nonce": "64822DF95082DD9FAC3ABF49",
- "section_mic_hmac_key": "DCE1733FCC2792C2FC5E717B60BF387A153B202A6FF51896D67849A33D700BCD",
- "section_salt": "D3F3AF795C519468EFC23F73081ADE8E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "7B1388703BC7E6A02BC3FD5ADA646469",
- "data_elements": [
- {
- "contents": "7D62FA053E4F6358FFE38CC63265B5C631",
- "de_type": 618
- }
- ],
- "encoded_section": "499110000FB390BC9AC7F8533F693FC4F1C9BD6A9004BF6D2926E7409C8B991DDF484AF4F056C15513C85442EF6D8CA694BDCCDA70B5ED790BFBF4F026113C0E71CFDE64EAB674438D7A",
- "identity_type": "provisioned",
- "key_seed": "2B56B30BAF8A4D98B8D2D6DBBA920C7E58CC2A308BCBEBC2444E695CDB84DB9D",
- "metadata_key": "F9B398674610A9887928F01BFF47348C",
- "nonce": "CA88F80E008C85191F0368E2",
- "section_mic_hmac_key": "61032327C90BA52D7AE489911943770F4ADC0CBFF70B3C1FCC6C8CCF684D11DE",
- "section_salt": "0FB390BC9AC7F8533F693FC4F1C9BD6A"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "C131B7DDCCBF6B9D6697A73183BB9C2D",
- "data_elements": [],
- "encoded_section": "35911000D6A73EDFDB9C58847962A374CD39EF8E9004564B9DA3B33DE90A04DB8E09C9F74E39B3974D254418BD31BEDAF2079776203B",
- "identity_type": "provisioned",
- "key_seed": "619CDE7F5C7F48C2A728740F73ED8BED80DBC75A8F80A210B7787A3CA7D99894",
- "metadata_key": "894C9EB0A0CD63439D7D38D98271886C",
- "nonce": "988D2E9390677C9D60D253C7",
- "section_mic_hmac_key": "B9ECF2780619E5BB483F7E67D47D5F6C453260B05B1C6C8B9DE3A1AA200E859E",
- "section_salt": "D6A73EDFDB9C58847962A374CD39EF8E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "471C247B67E71991EEA742A60395E761",
- "data_elements": [],
- "encoded_section": "35911000AF15F574B747192E9BD4F216FA1B4B7790046EBE5844F9C2B310D203E1F7B096319C81C5F10A0173AA6130BBFFDE2C335BA2",
- "identity_type": "provisioned",
- "key_seed": "AC53B58E3C5655CFC99E96EDA60B6356B91878707EBBB72C58B40372067F2654",
- "metadata_key": "B3C7283A417F10365A58239881EA3357",
- "nonce": "36F08B54F7A71C96317A1379",
- "section_mic_hmac_key": "C873EDA6670390B6576A70192A1CC51663DC71878502344B4E89570B4DEB8CCB",
- "section_salt": "AF15F574B747192E9BD4F216FA1B4B77"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "FE9F6FB58671E09A1A982B395153F5AA",
- "data_elements": [
- {
- "contents": "3EF87149ABACBBE77A658C12AF57C5CC23549860",
- "de_type": 886
- },
- {
- "contents": "2FA53563",
- "de_type": 266
- },
- {
- "contents": "07",
- "de_type": 504
- },
- {
- "contents": "D174D239EA526214B9F3DFA561C2E67AEB39CB5E8E45006EF7",
- "de_type": 727
- }
- ],
- "encoded_section": "73911000996E2F8D9CA965F32EB4884BFF25EB659002555A82FC0FCC2977E3F47AE4C3ED20652D644EF87BA79F9C7A4D0CEFFF756F6F3EA21275055C45685B915A6CF3500FEB68C62D6DB778D6037719D08E1CE1A47A60BFA574B92458EA9853CA12C6085EDC5B3357767D033BB8BD858C6C45F4",
- "identity_type": "trusted",
- "key_seed": "797A0E23E450BD746F50A900291EDF12A427207E9345F1ECA7F247754D4E3778",
- "metadata_key": "EE52E516F455BF41B9FE45B525300D80",
- "nonce": "8032538D846F75783A371130",
- "section_mic_hmac_key": "7B1519118268CFD05BE2529648964A31267DE90B31858A541E3B6FA5B5A5BA48",
- "section_salt": "996E2F8D9CA965F32EB4884BFF25EB65"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "259CA266C07D24489E2320751FFACA50",
- "data_elements": [
- {
- "contents": "1293957F338220C0DFCF99BB988D4B10A2",
- "de_type": 588
- },
- {
- "contents": "A66E4E117DE27225",
- "de_type": 527
- },
- {
- "contents": "A371A89597B5908CF70EB5CD70",
- "de_type": 348
- },
- {
- "contents": "EF8C4B",
- "de_type": 893
- }
- ],
- "encoded_section": "6A911000CE373177E0843767D3CBDE3EE36AF17190041C77A0D1B5A6D84E23CEA79D55760F47327519B09C00EF56BA591D952D09BF7649316ABEAA1DB8CBBA6C60CB9800B14CAA592DC6BE015529375E516D04DB3364041E1CD3C4545F053AE220D2AC5D9A1D8F15A18A5C",
- "identity_type": "provisioned",
- "key_seed": "0C8BB4BAD43C47257EFE360BD5D5DBE4896E84694141ED2BFEC0489578B217EC",
- "metadata_key": "0F57379CD24569CF8D875802667F8018",
- "nonce": "2537E78DBA5A7038AD729338",
- "section_mic_hmac_key": "FC12ECFFC1AA17039E7B4D5671BD50D23427170DE99771C2560D50630AAB4FDC",
- "section_salt": "CE373177E0843767D3CBDE3EE36AF171"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "75678439AC49152DF67381CC8EE0C97D",
- "data_elements": [
- {
- "contents": "AAF565A6056E72F5701175",
- "de_type": 900
- },
- {
- "contents": "",
- "de_type": 882
- },
- {
- "contents": "1BE514ACA5DB37",
- "de_type": 958
- },
- {
- "contents": "4E37988B6C6BEA4DB361B0ABA2BB437B4AD2A36629E927A798C952DD",
- "de_type": 994
- },
- {
- "contents": "7A7051FB81E50D6E053F5485690060BB125BF0B564C25E8141F18A96",
- "de_type": 502
- }
- ],
- "encoded_section": "8E9110008CF745CF3EF5643BF08137D12572917690017A062343BD2CA81B100320E63F160D60C0E4FA222E7E8D2DDEEF54E8DB3E6F1FB8ED544B20CCC68B7325C41E13169FF9243D361927D8B8D70CB9BAD2BF8D144A7E7181AD04B286370859944B00B285A07237C9B7C06ECA02F133C1ADB18676DB418CB0F625548CEE8D1EC557723967A2DBE6B6FDE4266E810D",
- "identity_type": "private",
- "key_seed": "B2289A540886CA52A77D25F5130E9772E28FCE89F62ECC13606D63DCEE99DA3F",
- "metadata_key": "982AE1A57B20C2386179D149B6EF266F",
- "nonce": "80CD1289986D617F60412E98",
- "section_mic_hmac_key": "7568EA434871461F5D6FC2DD811AFD04A037DDA922D703E0C62B59BE3FD8463B",
- "section_salt": "8CF745CF3EF5643BF08137D125729176"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "7BB7CE9DD41A841A3D5A7EFD4C320177",
- "data_elements": [
- {
- "contents": "AFD0D457BF0EA8EB58FB",
- "de_type": 663
- },
- {
- "contents": "2E252A7580FA1B62063666B69F3C6332E4B8F9707C7A21E9E02950D9C5",
- "de_type": 817
- },
- {
- "contents": "B60A909ED57A8DE3A7860923B92A7D5F6A8D",
- "de_type": 800
- },
- {
- "contents": "B6C8C14C3304DA",
- "de_type": 874
- },
- {
- "contents": "44359C8173B6FB9A92391A0EAE5C6CED3795595BF808E685FEA3800C",
- "de_type": 41
- }
- ],
- "encoded_section": "9F9110007C40D5971CAF5E56EA8BF03ACE6BD22D90029D30A51708C5EF060F6B2302BBAFF4C86DD795B8E6C90593DF259C7456F78C3C538BB0F15EDF17939A6C167B07648A62BBEDC503DBAE8861E36C6D465288149E9E99BC0514AE21D81EE7A68420BED4EC65D36A625CAB083EF8AA67EBBEAE047778D2B1A6DBF17FF25BC013B70582694E68E21E45C2537CE508A82751F5079DA2D24255E6800D7B48241B",
- "identity_type": "trusted",
- "key_seed": "ED15F635173F72E83E0FECAE6051EE847DC187452B21CD45FAB6695D6B46FB6A",
- "metadata_key": "FA3B46AB691AAA00B09C9CD962E3811C",
- "nonce": "40AB25BE3D15124FDD3852C2",
- "section_mic_hmac_key": "EA130B96787E966323391209C412448E67E2554BFC79E1D0A4C1D8F28D29840C",
- "section_salt": "7C40D5971CAF5E56EA8BF03ACE6BD22D"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "09E7B0FA69B5C2148852706F8C5F82BD",
- "data_elements": [
- {
- "contents": "8C43E3E02909D0E210F56F35F3A53ABDB0",
- "de_type": 153
- },
- {
- "contents": "45",
- "de_type": 747
- },
- {
- "contents": "EABB820A273B4051E4",
- "de_type": 653
- },
- {
- "contents": "",
- "de_type": 828
- },
- {
- "contents": "640DA947E4BA04CC0C40BE9FA8DA6819E90ADFAB03675A24BC2D66E541",
- "de_type": 780
- }
- ],
- "encoded_section": "7C91100049432641BB8252194672F33CAECB191190047289517226E7FBBDE5818FD68CEAE9209FF8BAA41136E4807358253C75094411B689D301DC04E3516A85D40B21DF0700D7B92EC91D1EEA36287C7705A61105847DD7D8A428E634D74A99BE9AD6EAA73D38FE8F69CE611C48AB50D989C8E64F6E8E01A44AD1A5B2",
- "identity_type": "provisioned",
- "key_seed": "B169199CF07A1D54ED407BF64823FF86996412B093B8484B37834D8924EF93D4",
- "metadata_key": "9E2A47BDDF6F1B9BEA356760D0F3E69C",
- "nonce": "1BFD42F51287EB2A9F5E1F4A",
- "section_mic_hmac_key": "3BC6B7E8D9F2574AFDB2475C7446292E50BD425D7C29210ACBB02926A8BF3446",
- "section_salt": "49432641BB8252194672F33CAECB1911"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3895442EB8CDC0F81A3C413255B87845",
- "data_elements": [
- {
- "contents": "8A78F02365C12DF7959D96CD0DC8D50C000230D7500F2773BF92",
- "de_type": 791
- },
- {
- "contents": "6494FA1960D6F8",
- "de_type": 709
- },
- {
- "contents": "DF5B46AF34309403DE697850F22EB80BEB",
- "de_type": 10
- },
- {
- "contents": "5BB5A41FF36679",
- "de_type": 284
- }
- ],
- "encoded_section": "79911000543133A572BF9818330781F72566EBA39001945FCDA195E5DD57E890340E1145DDB3E7F29F61570FFC84C816A65BECF670144691E6DEED393F745D1C2FCA8F81A02EB783E970DFF3182D3A0DA22DC6046EFA6AA8311E1B7A9B9B3397B1C7F2DA32F5AF4A59698565FEB006903A3A2BB2AA774E65DDA3",
- "identity_type": "private",
- "key_seed": "41A397419E6A7A9BAC80625800C7C5CFC5A9E38D334423670A10C95B46385944",
- "metadata_key": "6DF6268ABB94ED2B7572647828350E37",
- "nonce": "3FFCA5B7F335F4080095078A",
- "section_mic_hmac_key": "8E01172131A0E1AF5B2E800FBB4F6B941561F6A25326CCE3FF8549C87F059B75",
- "section_salt": "543133A572BF9818330781F72566EBA3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "FE335C4919EB054F5D03A0F3659BB5ED",
- "data_elements": [],
- "encoded_section": "35911000CF8C1FF97CECF7F829F6C8A71E77CD779004792DD541DC78082D871E1191261E74A3B8E20A809244EC191525C631BB404865",
- "identity_type": "provisioned",
- "key_seed": "354C47FE5F08043C0739F02C7C491A5CDC2ADEEABE5C95CA26EF56D3301F32F0",
- "metadata_key": "0CBB7E1212820A68D7DA2C386E9CA368",
- "nonce": "D0CF770C2DF7104179F8FEA3",
- "section_mic_hmac_key": "D94E767398418969D4D7F94690A8BCBE3E5D7F85990B958A83FF465E723CA19B",
- "section_salt": "CF8C1FF97CECF7F829F6C8A71E77CD77"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "ACD71592FCB1FD6C6D8ED46C23769315",
- "data_elements": [
- {
- "contents": "C8A12CCC17EE72A7AB87A19A",
- "de_type": 38
- },
- {
- "contents": "2A0E63613F23C6B46B0C7FA2F22112381E62F5B1E9",
- "de_type": 129
- },
- {
- "contents": "80F038E4063FBDCD0612FE767119359E",
- "de_type": 564
- },
- {
- "contents": "4DA8FAC9B8994DB6",
- "de_type": 3
- }
- ],
- "encoded_section": "789110000F3ABCDAB5986222DDFCBBB8FF38566C900428609F59EC9E471AA93544E7103F645AC96E4FAFC86CDD5CDA58B682D3FFFA015B6578E6C2E1C21AA406B7175401D3FCE1ABBE909A2A50C0804D4E1A8CAE5E27B1BED0823246EA34539ADC01915175F58B47E44680672B72EF54451DD632977507326C",
- "identity_type": "provisioned",
- "key_seed": "23DFBD6B52C3B59B254DB98D406E8479C25020C1DFA630A8BD2C89F88080C615",
- "metadata_key": "379389FFDDE6252B5130D231D63472DD",
- "nonce": "15F7BCC7074470D3F1CFB56D",
- "section_mic_hmac_key": "BBD2B93E7B2477438E34C1205D0BCE0B365A7BC302EDB5CF0F82B6894603E24D",
- "section_salt": "0F3ABCDAB5986222DDFCBBB8FF38566C"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "BF15896C0DB200DAE1115AC614084DA2",
- "data_elements": [
- {
- "contents": "B874CE053E51E004F52641A7CFB2D3B0FD74B7DBE178776A671A0DAE2F",
- "de_type": 302
- },
- {
- "contents": "913E81800F04456267ABA9E4782859A4E1C7F9BA7E9F",
- "de_type": 115
- },
- {
- "contents": "803EF3051156701AB4EDAEF5FCB355594348E96537E5EC0571BE99",
- "de_type": 353
- },
- {
- "contents": "CE22",
- "de_type": 749
- },
- {
- "contents": "8BF83F936CA560AF25B8E0FD2C",
- "de_type": 140
- }
- ],
- "encoded_section": "A09110000909CE4451ADA9FEAE94AFC32F74DA8C9002500BEFA6439AF0E094408096D11836FF233FD696C45B67FC5FE377CA37A7156D30C7747C04731ED487D679E79747AEAB7B9264C1F02FF4B3B56A6282FF1BA99927C50B6CB9A5AD8300C58F0DA8D189F7B891E3165A3951B9587FCEAD411774E3C191ED51D02878659572425B45D0098395AC66421C05B5B7984A66B82115AB609678A5B2E8B109BB1DE8AE",
- "identity_type": "trusted",
- "key_seed": "D32BF06FA8E93B413768C8F0CD5422EC87FD4F07A83471240BA220E36153FA02",
- "metadata_key": "1FE225A34E0798FF526E8B55F10AD9AC",
- "nonce": "B54225F9D30F237B635A51E4",
- "section_mic_hmac_key": "CE683F20EFFEBF4F062DA3EEDB52DDE50B32C8D63BF2B8A5551EDDD354940500",
- "section_salt": "0909CE4451ADA9FEAE94AFC32F74DA8C"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "5C0FF3E5206B0B714A43B06D56DA4CD8",
- "data_elements": [
- {
- "contents": "B83154F8BF3A58B9F7F622486850E19C9798FF7B0D2B57DF1ADB",
- "de_type": 604
- },
- {
- "contents": "2855D0AD4AA6C16ABB392AA9EFD8A0973235E86129F8CD652F1F",
- "de_type": 362
- },
- {
- "contents": "8744051612F79A9F05D48FEEF1F276B6039B4EA57B",
- "de_type": 639
- }
- ],
- "encoded_section": "87911000DB30A3E8AB8EB0FFE1A3C1C32107E97F900229702D3456ED474EB3634E1123F78A5EE68795E469986D32E140F7768372A49544565B77EDC858130D8F31885D21142238E6160BFBC4AA1E2C16617029B098225727DBE761B39D8C4F3A9B81DD79320B786B8A73AB12495BDCA873416489EFA679DBCF4D890CB24953E193DC729A7FB13CD7",
- "identity_type": "trusted",
- "key_seed": "CBD84DE224729EC23993EC958BA5EC191C55984C7565A37C202C66BC2F496DC5",
- "metadata_key": "E2C1CC17E5DA3035D3A4A9D67B696A8F",
- "nonce": "1769E6807F6DD41EED99365E",
- "section_mic_hmac_key": "3B760F5F10A764D965E928C2EC75BF3C185BC1E60F1BC25E3A4F2A23B08275C9",
- "section_salt": "DB30A3E8AB8EB0FFE1A3C1C32107E97F"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "EF4525C9E148E35CE5B6B1ED3EC7F397",
- "data_elements": [],
- "encoded_section": "35911000F37AF80B78106073DEE5B3E89CBE817690015242E1B8F8D5B0AD1A98BB81C0B7AA6E2F08129AA0AC99057C4EF93D009FACBD",
- "identity_type": "private",
- "key_seed": "45E271D048743BAF708F32EAC2E0C37B0AD50DC468268F45FA5A00F273710BC8",
- "metadata_key": "D5BB4FEA17C7E817338B14C4D01F95AA",
- "nonce": "9EB99045CCBB3943C3C85689",
- "section_mic_hmac_key": "94142F9B2D08B819B2681AA5A8532AA239FA5D248DE1400308218E1171A19B2E",
- "section_salt": "F37AF80B78106073DEE5B3E89CBE8176"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "D7B12DF79375EAD42C400EC4B32C845F",
- "data_elements": [
- {
- "contents": "5EC3",
- "de_type": 27
- },
- {
- "contents": "9E9931D907110614B32CD6406AD1F2EB87A10F09B7E8E787112EED",
- "de_type": 473
- },
- {
- "contents": "D832A59D",
- "de_type": 739
- },
- {
- "contents": "F9A4AB6E8C79AA9949",
- "de_type": 326
- },
- {
- "contents": "DA3460FC544F1F95",
- "de_type": 983
- }
- ],
- "encoded_section": "759110009631F8139C4DBED9E68452694DDFC8839004ECDED2D0BE3DF39682EB8C2218A08B11479557857995B61401E0F13ACAAD078B464F1BC371BF9374A4AC12E24E92258EB2020E02A85BBB90568AB3BF976B36BECEC7BA4D0925816AD13747288FA4FF6F5533C22E342606A7B9929FA0A5672FAB",
- "identity_type": "provisioned",
- "key_seed": "869972ED54E5B68EF1C466213667435B7C08EBDDFB74F685ED7E16CADB6BD315",
- "metadata_key": "4B943DF47FA8A1A5ED1983F6BA680BF1",
- "nonce": "0A885C98D19D59923D1D4CE8",
- "section_mic_hmac_key": "0FF1627C891D82AD29699A9382972D0D134EC708C71ABBB25F117C50E7564E7A",
- "section_salt": "9631F8139C4DBED9E68452694DDFC883"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "D99D1918B0ECB9895C5079AC3708F8DB",
- "data_elements": [
- {
- "contents": "9504B53F3858406A21CDB1A8E6E4726EE54D26EF868A1CD0FB3FB6",
- "de_type": 354
- },
- {
- "contents": "",
- "de_type": 219
- },
- {
- "contents": "E68CCEB0AEEAD509B8D936D690940E628CB3446E7A5AD4",
- "de_type": 570
- },
- {
- "contents": "27C89F3446D81FA865168C6942",
- "de_type": 663
- },
- {
- "contents": "A7B1EAF81C107EE58AC4433F9B2F9194A1C5B3B31F7DBD775E8C",
- "de_type": 854
- }
- ],
- "encoded_section": "9D9110007E27BC504F56BB2720C62A72226B8C369004EF6CDC81805C1A1B8C3689B047217487EF72A690D9EE8B7DB36DE15EBAF6746CD77D0E9C979344B10045AA56EFEC9ACE8DCB27C444163CEFE58CD7DB8F33F3BFB3F34483F7EDA5D0BDF0DFDCD63AD61AC00E548B445F480EE3F2B5F7CBC8646CB6C916CEBB660725C6735F7105F9FBFA765E51EE242D53E97F79F4FD2151590529DE523296437B2B",
- "identity_type": "provisioned",
- "key_seed": "C50E2225963721E5B6EFCE5B1A228B14BDD2BA34AA67E7225550B081BAD88726",
- "metadata_key": "062D3B665FE311167539CBC5BEAB9BFE",
- "nonce": "E35AE35D209210B3880DAAA4",
- "section_mic_hmac_key": "80C63B2ACF7CF9FAC9852D0208BD4797B5DCDEF5A3F4BA561D07FD2ABEED9F03",
- "section_salt": "7E27BC504F56BB2720C62A72226B8C36"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "905119285260089FF9BE8FF6CC825E02",
- "data_elements": [
- {
- "contents": "C7773F175A4EE4",
- "de_type": 167
- }
- ],
- "encoded_section": "3F9110002F823378B9F59BBDE54978A162E849E09001CA8F84780BF04A3EA8FBE518141707B75121CDAFB8F0E4A24D354D5775AD46CD6E698AD77AC066B5250F",
- "identity_type": "private",
- "key_seed": "4D8C6CD25657A64D6A4FC29AA77B921362224AA73F33A03B48A547BAE062F80F",
- "metadata_key": "0E77A2EF879199FCDB210192BA8F61BD",
- "nonce": "71FCB2AE5A7E75EA035E4C2F",
- "section_mic_hmac_key": "4C314CD5B4BA1DA13BA002B6F8B5B23B83E52A3151E8D3188B18A9116D393FB5",
- "section_salt": "2F823378B9F59BBDE54978A162E849E0"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "58242E8A9A5B025E720AA40BA1CB864D",
- "data_elements": [
- {
- "contents": "786DF190FA",
- "de_type": 989
- },
- {
- "contents": "C35CCE593DFC7F1B67D9FDB6DEB00A",
- "de_type": 8
- },
- {
- "contents": "CD5807FFDB0B16362997F91B45C3F1",
- "de_type": 736
- },
- {
- "contents": "AE7B1B9F94",
- "de_type": 485
- }
- ],
- "encoded_section": "6891100064EDA38990FF5640000A6F909B9B4C339004B2D2CAA61055C3A3B5B633A6864D112D20D55DD235B254BD1B4DDE1ED246B422D549F6ED9EBA4E61B144AE199F41786257AFABFF2D09F5ED1D551AA90897424C7DE78D9F4211352DFC23D15FA49BAF2AA3160C",
- "identity_type": "provisioned",
- "key_seed": "930ABBE8D4AA0392A66E624A958254C607E161BDB8F63C4DB39E049C200AA63B",
- "metadata_key": "06190C656B704517A79EBE4A713C90D1",
- "nonce": "08746932375AFD8D733B8CCF",
- "section_mic_hmac_key": "E9018DBA2F5D458EBF7F765F5E0A291DC789BF054BDD7F21ABB08F3C9CE0C068",
- "section_salt": "64EDA38990FF5640000A6F909B9B4C33"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "2E74FA5A2A52433667B756AB26FCD187",
- "data_elements": [
- {
- "contents": "A60BC355C90F28BC4939E07D1CE8FDA9F3BFBC190219B42A0396EBA4F4C0",
- "de_type": 59
- },
- {
- "contents": "5D789F74C3EDE4BC72D2E79DE9AAF8",
- "de_type": 990
- }
- ],
- "encoded_section": "6791100074C764F6E930524EF16015CE7D9861A090016D3B7274B511B5F2C9F5A18052F777C5F86FA997CE3BC22C9C6C9A5CA085DBE6488B2A78C6A73EC270656AEACCB923F608AE77568EA51827AE96FF9E6CE819A78E0A4EB2C5CA3B4970BD181F397E3E98EE7B",
- "identity_type": "private",
- "key_seed": "2AF41D8404581C2831B893C7DB59D544B64CFB736BFABC81A01C1875066EC279",
- "metadata_key": "CAAFC39835637CF21D4B75303E2CC3AA",
- "nonce": "22231C84688BAF0FB9538C9F",
- "section_mic_hmac_key": "795A1998284D2DFE1A0E29D8118E10D830AFE527DC341E2654B88F2C1EB1B06A",
- "section_salt": "74C764F6E930524EF16015CE7D9861A0"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "7B2C7A448A3450294EDC49709E51BA60",
- "data_elements": [
- {
- "contents": "E1CF16D6B5287453B1",
- "de_type": 956
- }
- ],
- "encoded_section": "4191100052105E2C85C91460D02A73EEF05F82709002CFD75D43FD7EEBFBB78A62325C09B1C96593C0ED6CA278F49AF34804167F948B99611B4C536AE40E3B74243E",
- "identity_type": "trusted",
- "key_seed": "E685FFAC5E3BAAF679C7991522FB5A6CEC3F100597766673D2746868D929D360",
- "metadata_key": "6E6DBC6DD5DC80171A5B0DCD03F1BD90",
- "nonce": "5677F857950960AC98F055B4",
- "section_mic_hmac_key": "F47EFE70DD21595388F4747DC599502C15BDE2199335DF51DE8F50A3E6858EE0",
- "section_salt": "52105E2C85C91460D02A73EEF05F8270"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "640ED142DA551CC82073E01140C9F6FF",
- "data_elements": [
- {
- "contents": "CC848267E64EE36BD16459",
- "de_type": 1
- },
- {
- "contents": "13C03AE9514CEEA49B840E14C3D8FABB",
- "de_type": 287
- }
- ],
- "encoded_section": "55911000B89F5B7D2D1679457B14537AA5D43AB79001E4AE76D2D7376A024CFAE9AF27D5D51D4409BBE5B1F0ADCE4EA97CA14545F965091703432E7238CD345852880A893E18B154A85EC8F2B0C80B28C20376224BC8",
- "identity_type": "private",
- "key_seed": "757A5313F590A0A3CB7880514176C98223D8D89B6C366F0A9C3E614A95667FD3",
- "metadata_key": "8E48AB97578B936E9DEF574317F5643A",
- "nonce": "2F4D288A2F3C29654024DF64",
- "section_mic_hmac_key": "87973F076C0DA1706FBFA208CF3680032F72EFD30A1F35DBDD720FEDB5A73FAA",
- "section_salt": "B89F5B7D2D1679457B14537AA5D43AB7"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "25B113A142425E28DBF10262674CCB91",
- "data_elements": [
- {
- "contents": "2DC3DFB78F9FEDA6140EFFF49EA5CDB1587B3B",
- "de_type": 38
- }
- ],
- "encoded_section": "4A911000BD6BA0CD360D3ECEAC02350FFA2287AE90048C31FDA2D808BABB89DEDDC545DEDF43A15DC84FBAF251F8553C3ADA164CD855C3392347333E6ED803F1B35A04CB2DE8491B0AD57C",
- "identity_type": "provisioned",
- "key_seed": "B94AF2DE34B622260AB6EB5A28897241EF07FD726FF6B46B09AB855B74BCCE21",
- "metadata_key": "12188B3AAA6203B3D7B7FFF944B28C03",
- "nonce": "27D5AA6EB9343720C99B48A4",
- "section_mic_hmac_key": "F36CE020CBD605AB0D5A58EEFC5B13041B3E8EE37FCD23DA8768D05B7E969217",
- "section_salt": "BD6BA0CD360D3ECEAC02350FFA2287AE"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "86BEC41ABB2C0615E293D625F5A5CC21",
- "data_elements": [
- {
- "contents": "796D434C2A64E6542A6E8A182C29A6C0A0D10CFBE5",
- "de_type": 697
- },
- {
- "contents": "B166F37A451DE048DFFE08768C22CC9E16161DE1FC111BE153E74567A3AF",
- "de_type": 786
- },
- {
- "contents": "15F72C03BCD436FB515626CC4D45B007465E01F99F141A06C2452D08C031",
- "de_type": 75
- }
- ],
- "encoded_section": "8E911000D67B70722D003E7D47A47A965DDC27EA9002BC3C5974EFF692C78D91B4BC70B183AC34AB08D6774A186DB2EAE6518C429EF6EE80C853B3F36AFF69463401AB265A7841C55974F8307B351ACD0AFC676A7F8E3B6785354E8C8341AC1D159B3449674AB3FC1664DC6A98CBE7B365D5F29CCD0945B37F3DA5B15711A1554A8D20DE4E9C36F89AE8CDC0529F18",
- "identity_type": "trusted",
- "key_seed": "8D0769C53264F0E56940C303DC296FD0FAC215BB638670FDE74C2D254EC351B6",
- "metadata_key": "6E402856AB9B61F6C85EE44427DC3B78",
- "nonce": "76315884D2C7B9F90A9E40BF",
- "section_mic_hmac_key": "E87538BF29EE50BAE15333A281438C3A5776A0544CC3AB1EF84612ED7D59D40D",
- "section_salt": "D67B70722D003E7D47A47A965DDC27EA"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "F22B4181441945D8B70988072189C682",
- "data_elements": [],
- "encoded_section": "35911000324C90A945FF9A8AECA1AC7F71C9B7FB900106FABFF1B5D76193C4196B7CE59C3AAA8D2FD16CCFA6CF09E8C226BD7604AC56",
- "identity_type": "private",
- "key_seed": "BD5DE9F03A2FAA422C470AFC4F151615F326CBE3E60828C0ECF68CF1215BB760",
- "metadata_key": "60FEAF935A8ADA1C80FECDDB8F4290A8",
- "nonce": "74FF9C6FC9B74DBC58D80EEC",
- "section_mic_hmac_key": "83F5E26CDD98C91D084CD544BAC0EB6C79F3B79B388575973C75F76C66671427",
- "section_salt": "324C90A945FF9A8AECA1AC7F71C9B7FB"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "48543F7CDFE13F94F1FF50E76088C2AE",
- "data_elements": [
- {
- "contents": "9AB990FC7EF63FC213AE08BC81C35EEF8AAE8DF403E17839D9F25C30C7CA",
- "de_type": 731
- },
- {
- "contents": "2D33ADC55687CC6D516326D3083A01DF79F7C20347BE2BA49726",
- "de_type": 652
- }
- ],
- "encoded_section": "7391100008FF6026C41A8392B3401F690B0FA3E3900456BD090474095981D8D630D9AC342F4DBB5653D8CC96BB884B960AAF63A142323A4C41B7B287DE61D6724BAE3BD0C9692357BAB8A84265443B452CC632A26228824ED3B278FEA3E89BAB1F849DC2D59B92F7923D886E39B641A0824C5754",
- "identity_type": "provisioned",
- "key_seed": "80D21E28838910DF3318A81884493AD8B3156E22B9EC94DF8E440963D1E6BB0E",
- "metadata_key": "F588CA28D3A30ADB81E4CF0F154FC445",
- "nonce": "E3C19711F434B76AB66ED99E",
- "section_mic_hmac_key": "5C093723FBC9061053CBE302658A97A8641724524D38B88FA576563153E43944",
- "section_salt": "08FF6026C41A8392B3401F690B0FA3E3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "EC4C02761EBCE92561D9876B86277ABD",
- "data_elements": [],
- "encoded_section": "35911000812086DBDE127B30D0A49750706EFA7090023EAC44AC52CC19411C1EB8A3B054D3A4DA29BA7AB1F48B2B66D53A0E89BEEA81",
- "identity_type": "trusted",
- "key_seed": "F905BB1C2C53DE72F94DF4E6D2B06BFB56BE0B64FB9388FA64D0532ECBB2EA91",
- "metadata_key": "3FA740734AB4B08F591E7A1678684145",
- "nonce": "7DFB4025DEE53AAB242382E4",
- "section_mic_hmac_key": "C606528062B1FC77C27EEF4A4C3C2DE18672B5334A4505036F0F7D8E3FED343A",
- "section_salt": "812086DBDE127B30D0A49750706EFA70"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "08BF72906B4385228E63E345F18A05C0",
- "data_elements": [
- {
- "contents": "9EC2961EB5315850F02F",
- "de_type": 332
- },
- {
- "contents": "75A55F90EBBF",
- "de_type": 89
- },
- {
- "contents": "5B1B5253D80289F8F01BE72974EEBDC3ED",
- "de_type": 204
- }
- ],
- "encoded_section": "5E9110007EAF5B0AF95F689E81F61A051D316FD49002DB318ECF2B751DB740797728EA96E14ADCE0B2BB27EBFC6D45312379906D6494808D7E9C8BA6242B4A02C4C23223112D77B94131BB9BE739661753C158001AF9CD0EDF73B899AA266F",
- "identity_type": "trusted",
- "key_seed": "EB8F85BE87A0A9347B3CBECE969B008A57FFEF6E4E8A95F734893EE710B27FE7",
- "metadata_key": "825022A58B49C829B9B524E12AF0E160",
- "nonce": "B5143876982CFC9AC88966E4",
- "section_mic_hmac_key": "F649D8AF765E2E31FB870480932F4952FFCA19301F2FAFCBDB992928268BC8D5",
- "section_salt": "7EAF5B0AF95F689E81F61A051D316FD4"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "6FA3188C366D18061138ECE126A97BFA",
- "data_elements": [],
- "encoded_section": "359110006B869584D8B9A2617A3911586E08679290028283D6FFC57D5D5FC3690502E95413F8BF29DF7EA841527BBBE6DE1C918E5B35",
- "identity_type": "trusted",
- "key_seed": "4ABD1D1549B74AEECA657499EDEFA7701D724FF427142DFA2ACA1A087455E339",
- "metadata_key": "32152EC7E3BD86FB1D19DB1136E934EC",
- "nonce": "5F7C76D24DCFE9E61B909C2D",
- "section_mic_hmac_key": "89CC3C25CDCE4A6D36EDABF94C225087C455DA885AA113254AB3A71DAB0F27E4",
- "section_salt": "6B869584D8B9A2617A3911586E086792"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "46C102A2CFEB44FD44236234AC618374",
- "data_elements": [
- {
- "contents": "2DAED2D919",
- "de_type": 752
- },
- {
- "contents": "69642A6B9FA86810",
- "de_type": 907
- },
- {
- "contents": "C9133E66C06507782EFCA12CFD2255DD2AC3CCFE568E5B",
- "de_type": 75
- },
- {
- "contents": "11917BC9DB942E",
- "de_type": 253
- },
- {
- "contents": "B772136AF949D06B3C74EECB6A2877B73140CF7BD459",
- "de_type": 741
- }
- ],
- "encoded_section": "84911000D5B533CD04983822338C7E4679ABF0069004CB79ABFEA568754DF58A73D97993AE327F22F6EA434A49AA5D12110FB08F88A77C3EA795B49DFE542046BE6FF89B46146088D770CA8D4E221D73BEECB978974A7E3A2B29C0FE7002230356778F0AB6BBFC45279E08D93657B5D857EE9915A3343FDFAD5ED96C886E225EE77AABAB71",
- "identity_type": "provisioned",
- "key_seed": "B45EA904C8AD8040870C0C5996E7D6474109D43A1ED77CFD4EC5A0909ED8537D",
- "metadata_key": "F27F824E7A676B87F008B914C697F731",
- "nonce": "A9D31F3FC180A643BFD2393B",
- "section_mic_hmac_key": "C57B68D19F0C0467792E61C6129CAEFC41C9BC017CFDBF3ECECFE053247C86B4",
- "section_salt": "D5B533CD04983822338C7E4679ABF006"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "E76311EA2FA2BD5E23ADDD81EEB7035C",
- "data_elements": [
- {
- "contents": "F0A613ACBCA74BE6A2B1EBFD40C52E0D66E5AB04",
- "de_type": 294
- }
- ],
- "encoded_section": "4C911000CC0BB7E46499CF0636B26F05408554E39004020E9465725DE7A884C5B175C90015562B2F9B106F9F1AEC608425109ECAC0513AD32D14354CE552859514849D19D6BB59CE2D0EF9A0F9",
- "identity_type": "provisioned",
- "key_seed": "CC9A75CC75BB1D230A75AE87B6AA6D14E08ECD864C90DFA2C144DA62AA2FDA4F",
- "metadata_key": "D1FA24F308946E26486C02AB69CACDFF",
- "nonce": "DDA1727B363F44B3A00AC548",
- "section_mic_hmac_key": "1FFE447BB7A8331E0AB04BD9E920759CE433094711AAE085EED90F11AAB04DB9",
- "section_salt": "CC0BB7E46499CF0636B26F05408554E3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "E670DF92DE550C7D16A47FF544AEB0A6",
- "data_elements": [
- {
- "contents": "5297CB087EF89FF30B412ED7FBFE9B",
- "de_type": 536
- },
- {
- "contents": "C6C348BA415CB959EE2B51B43DAF200076890AD49B044F5F847728",
- "de_type": 555
- }
- ],
- "encoded_section": "65911000FAF0B973AAED0ADA284F65A67CC775A6900191A4765553BDA369F32677FF10F57E0793B4FC72165819EB2E38975021A78E8367C4BC9A94E846F6A04ACCE516355A0A93938147C6908509D1599D7EA96A377B7ECB31F81BA98D8AA01CED9617C410D6",
- "identity_type": "private",
- "key_seed": "238046E9C80693E551BF4F3E7E563FDB8FC7EF319A4E3405D603DAA10BFA0AF2",
- "metadata_key": "BB080335533CFA2002C3FB861236215D",
- "nonce": "30A968C64C6D236C78A202D7",
- "section_mic_hmac_key": "20309013BDC66CF400D5E221109AB10CF0E742555D8713BBB332648E3897E847",
- "section_salt": "FAF0B973AAED0ADA284F65A67CC775A6"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "236A98706211AAF9BE9FF085882ACD8E",
- "data_elements": [
- {
- "contents": "6D6AC5C8256B7859373EB86A68E7F9",
- "de_type": 748
- },
- {
- "contents": "ED06337DA3ACC11B7BD86A0D315DA7A4EF",
- "de_type": 703
- },
- {
- "contents": "1639315FF6AAAA4B",
- "de_type": 855
- },
- {
- "contents": "785FD18ABF9AEDED7D3D407144A7BCE2F34444",
- "de_type": 738
- }
- ],
- "encoded_section": "7C911000F1B2D3FF697FEA61F1D24313BA24DFB09004BA73F0D4A7915365382ABF284BBB970F4F4FD77A6B3F48CE433EDF5679495A60CC803BACE3039072420D0FE9C1CBB529280C72864F31A3523FE98BBD39AC48E3A47524E57BC2259AD362901721E8EB8FE1F563C6C3EFF3374A277553D9D41732D44A4CB97BFE1F",
- "identity_type": "provisioned",
- "key_seed": "2D8D09BB3E1DFAB0611039A1BAF74D5258343FA303332251F86EA7D1FCCBA814",
- "metadata_key": "158E2E60C7F45BB9D6487B4BB3984DEE",
- "nonce": "9592919D3E310674BFDC2E9E",
- "section_mic_hmac_key": "69D008503467933362AFA9AAEB534D22839A8946A0A2AC717553CD50ECBD5D44",
- "section_salt": "F1B2D3FF697FEA61F1D24313BA24DFB0"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "52A4E397E30CD9CC7494F1FB77E608AA",
- "data_elements": [
- {
- "contents": "8C3E52853DF5586EBD",
- "de_type": 413
- }
- ],
- "encoded_section": "41911000BC844E7B944BEB5585FAAB4B71443FE990044489F0D699085E6ECDBC45D5A180550578468BF5FCAF01E7AAFC8612A47B5B8BB81A82E844D8EF05E4B223B5",
- "identity_type": "provisioned",
- "key_seed": "4975391685B7E23B969FD2EAF9ADAFFDA9E54345F6C978691019DFE171CF1AEE",
- "metadata_key": "ABBCF6913AF3396D4698A3D3ED9C844C",
- "nonce": "6DBC8A54F98C20F59D424BBD",
- "section_mic_hmac_key": "7DA38D6F5976FA186530C3259FC16951302C45E1A182A5B856778AC15D261A63",
- "section_salt": "BC844E7B944BEB5585FAAB4B71443FE9"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "81775F391E97501F10A06ACF2C1E1E8A",
- "data_elements": [
- {
- "contents": "E0E9135120FB76345D7F8649D99DCF21082B",
- "de_type": 209
- },
- {
- "contents": "A8930F2B30AD1020C7719732557A115B73",
- "de_type": 702
- },
- {
- "contents": "8F573C102D81EAD9DC",
- "de_type": 608
- }
- ],
- "encoded_section": "6A9110005135798EFB48BFB42A2542E5EC84F8BE90024EDE7FBED7BE6DB4BF57CCAF6B79B42AD2AE82EF17209B1118B1B9BC30E3DC7EE47CC74BE402A40786226E6662CF3C582AECFEDB6BD9FDD87CD780D34B7CC7708714ABD30875A945E6592FC178421FE73B85293353",
- "identity_type": "trusted",
- "key_seed": "CEB5046E0E41EA2D087D6BB2584FC8F5AC4AE70C3F262AFA2FE83BEFC6A7F96C",
- "metadata_key": "09F8FB1D817845D11CE0DD441FB6E6B5",
- "nonce": "70D102E7E612845E49DC9A32",
- "section_mic_hmac_key": "600AF01CC5117CB4AC58D49609CA3235EA0ADAC22B68D6FEA6973397744E7100",
- "section_salt": "5135798EFB48BFB42A2542E5EC84F8BE"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "F3293976BEB4E1EA2904909A54A90D0B",
- "data_elements": [
- {
- "contents": "AEA9748A963B21DDDC0B",
- "de_type": 82
- }
- ],
- "encoded_section": "41911000CCFD0A49D64FB8913DB3533CD842618F90020B1F2BE6DFF4647003A4CD20BEC2045A9BC3557018B6D8D1DDF5BAF68CBB0043BFE6F7F3A16914E72473574C",
- "identity_type": "trusted",
- "key_seed": "F7AB19164021C53FD3F406A4F4617A396FBB0B2083680D6A70F0FA93ACE0F337",
- "metadata_key": "43CAC734B4E59E6410B789DCA22E05B6",
- "nonce": "14B2E4D0A4BE88CD3AEEB9FF",
- "section_mic_hmac_key": "6D816BF43B74326FE8A2A88B37CE383F8B46D0C126454936586F027EC60C489D",
- "section_salt": "CCFD0A49D64FB8913DB3533CD842618F"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "375B33A2656E245BB1ECD330174673A4",
- "data_elements": [
- {
- "contents": "54A8E89BD5EEA62D46C39CEE1D60ED4733976A",
- "de_type": 596
- },
- {
- "contents": "",
- "de_type": 599
- },
- {
- "contents": "05286DB66919D9F031C704E925CBF68E6B8E",
- "de_type": 766
- },
- {
- "contents": "95B7B05F119963240B933C337C6FA9B6",
- "de_type": 336
- }
- ],
- "encoded_section": "76911000AB7FA706A14892CDC9CED6E9C13C028D9002D26550BE730945C1CA0C220A658856FA14430A49D45BCEEDE10DD1CAFD274BE5FD828116B8E3E3D71A3F679486A30D832958AD1B2E1415BF7F111BF4F6CCF94634C904B46F5FB2482F8520F7EA10061C018B6C24891AFE186B8144EFB4981D1E79",
- "identity_type": "trusted",
- "key_seed": "D93D2A387F132BE81714405D487F9323099CD7089ED80FE06DBD5F19B9479AC4",
- "metadata_key": "C249909E8C874421F56B5D5FD883F6D0",
- "nonce": "3608D422560EBDF764ECC44F",
- "section_mic_hmac_key": "ED742AAFE3D39273AC51EC4E94A7E5AD3EFE52D36E61F96ACD446F2A9C77618C",
- "section_salt": "AB7FA706A14892CDC9CED6E9C13C028D"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "9911435E27099CC033ADA0B809A9BA61",
- "data_elements": [],
- "encoded_section": "35911000DB8B02B57082EB58CC198556EBED435E9004A72315469AD264409CF53387374629C4683B4C7D198CCFFA95ABA332D9EAD095",
- "identity_type": "provisioned",
- "key_seed": "DE3FF3C256080ACA31DCE848A0EF6DE573A584AC3FDF00011207692CBFC71AED",
- "metadata_key": "A59DB751175865B4DB9CE9F5791D48E2",
- "nonce": "22CEE3D3F35609F5B04F2681",
- "section_mic_hmac_key": "88118CAA46862E8B57E83C23387C88F232BF22E5772D80E9EC15B75DA160F25F",
- "section_salt": "DB8B02B57082EB58CC198556EBED435E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "78237E429DEB7FF64A0CF0390C6B5AB5",
- "data_elements": [],
- "encoded_section": "3591100092F6C10DFBB105F88D53E46103584A369001CEBC52E442697CE7C0439351600F775089647E153AA0A20B8E0446CF188523A9",
- "identity_type": "private",
- "key_seed": "3343E7EAA3F48E39F01E5E8BDD5082E6DC4FA5A75E4FA570E717EDECAA9D26C2",
- "metadata_key": "65D3B6A2568AE0425F06C2E1A5F75F61",
- "nonce": "B44EB10C11D792A4474CD363",
- "section_mic_hmac_key": "FA58129EF913C31E017D2583EF3C53A6921C4C05F1F46DFAA29644E1AC8D13F1",
- "section_salt": "92F6C10DFBB105F88D53E46103584A36"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "718BB6207F09ABF1767C88964995A316",
- "data_elements": [
- {
- "contents": "41B733343BE9A40195965F3BE53A9E8DA772F91D",
- "de_type": 38
- },
- {
- "contents": "CB88998C5B3ADC6834216F607769",
- "de_type": 644
- },
- {
- "contents": "E2974A19DE611A27FF0AF9D27042B8073563FD2119C828CE",
- "de_type": 587
- },
- {
- "contents": "4FE69B",
- "de_type": 58
- },
- {
- "contents": "16A152105C8A1CF879C2838EA6CF4CC9",
- "de_type": 494
- }
- ],
- "encoded_section": "8F91100054D79FCDA215B6D37188275A6D71B49C9002E7ED4C98D0689465F88315C5E1E4CB1C994AF90E6DB73F55D62E14F5F6102EAEC722DD4B819BA652CDA67523910FBF4AD135A678F170DF68642B9A3E651817C280D56CB333C492B7B7C6EEC2718D16DEE888255E9470E50548CFDD8EF3FA1BE96BE3FC9206AF1E806AB72D7CEB2556A84DED90BFB26C7473D6A3",
- "identity_type": "trusted",
- "key_seed": "87AF0A342940CCE0D8A7C250CEC581D677776EFE684FE7A461538D306F79595F",
- "metadata_key": "ADC6D21008E6C6F9C6140DD2CA7A2D74",
- "nonce": "DEA185B8030CB125ACCD1991",
- "section_mic_hmac_key": "0B96048E575A8DDE941E0BFCC9AF72673B9E59D0EEE1D410EA3B5D7059D8CE43",
- "section_salt": "54D79FCDA215B6D37188275A6D71B49C"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "AD321D407A23FC1F3DEA4AFBFCE666D8",
- "data_elements": [
- {
- "contents": "DE6102C7908322A68E36094307406EFE",
- "de_type": 130
- },
- {
- "contents": "D811C6749B",
- "de_type": 979
- }
- ],
- "encoded_section": "50911000EEF15DD154F1CBB12B876AB7E4C28C519001BADA4DD563CC46E682BE16A078D5AE079DB587A78C9BD6BB37621F9F8EA5B7FB490D6857D3C3D3BCCABDF00E85438DB6227C002BFA7291D54E5FF9",
- "identity_type": "private",
- "key_seed": "9B702205F66C701BAE43D0EDDF8C3EAD92C80A3A8583C3397E7A3371758011EF",
- "metadata_key": "FF0BEBFC2C42168A47B3474D3439772F",
- "nonce": "D225BF85D21A4C34FE6B6AA8",
- "section_mic_hmac_key": "9CE75F27AC9E99BEA41587BFFB701F9D59793C68127183BA3BA38D219DBFDD1F",
- "section_salt": "EEF15DD154F1CBB12B876AB7E4C28C51"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "D62FF5F858D26914C62F3C93ABD608D0",
- "data_elements": [
- {
- "contents": "72FFD6C3F4B1B90771A08D281085",
- "de_type": 817
- },
- {
- "contents": "A4F94F7BEFD75D29A53C2ACDC0A908C2F5AA0768",
- "de_type": 618
- },
- {
- "contents": "0FBBAC5329C023",
- "de_type": 729
- }
- ],
- "encoded_section": "6791100097FF92E30C6B6E08B416A150E2099C2C9004A34006E38EDAD68F7BBA8294E12E9F92DF7A91259AFC5B813BE7A4FD8601959912E5B2CFBACA99A2460EC2CC0F6DE999F47A7580B9F0CEA2E0F882836864E82CEC3DF6F890269AABF65852CB9CF026D85452",
- "identity_type": "provisioned",
- "key_seed": "393F3DAA73636DE22AF63B869FFC970C1DAE302372E51F35BAC421F3C354B666",
- "metadata_key": "CA8F91CB3DA7A5A37E33F851D93EBEAF",
- "nonce": "A521F5DAA92BF1C1654569ED",
- "section_mic_hmac_key": "67AADDFA3C1E18B279906DB7987D29EDFEA643D678FA1AB4987A0A1D610005B0",
- "section_salt": "97FF92E30C6B6E08B416A150E2099C2C"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "EF85681E26EF87C8D2A1A3EE56FEAD2A",
- "data_elements": [
- {
- "contents": "C24BDBD7E3697F223F1621217A9C36DC9394EC33",
- "de_type": 335
- },
- {
- "contents": "C1",
- "de_type": 14
- },
- {
- "contents": "E4231F2308EB41",
- "de_type": 902
- }
- ],
- "encoded_section": "5891100037E9D4686030FBAC57D3FE42D92B096490014DBC20227A7388E74D0961E8674691D101607D944F8AAD12C950188603894DA02D5FA3698A54DC40598F44313F297CDCCBC1DC14CD32D267267747B0B125D91A89A557",
- "identity_type": "private",
- "key_seed": "4A289EAEC36BE20656071FE87F8A55155D8A893815038B9ABCBAD3E72DB0C8AC",
- "metadata_key": "C0450DFCC6AB17837C56EEDBE57D62A8",
- "nonce": "A9FA4AB4C0929CF2CDEDDF34",
- "section_mic_hmac_key": "8D45B9467DF17FE0943F155851C70CCEA0555BD59453503FF6A861F9011EF853",
- "section_salt": "37E9D4686030FBAC57D3FE42D92B0964"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "BAC1BE39B5BE69F29396EF5CC41402B9",
- "data_elements": [
- {
- "contents": "AF9A279790C0EB79F07F700C1CED8CAF60B72F",
- "de_type": 101
- },
- {
- "contents": "14F153F824",
- "de_type": 463
- }
- ],
- "encoded_section": "529110008ED27B5A64F8584EE798DA971BB3890290023D54202AA267D540AD159401DD2CC11E1F387FC4F90C9BA19D810C095D415CDF08EEC637B9CB2DF1259229CB2F02F894D63404B428C9AA33BDA7507601",
- "identity_type": "trusted",
- "key_seed": "9AAF4E2D596A7B4CA21DF9312AFD43A63FA8FA727DD60273072C4C4C0D472E3C",
- "metadata_key": "5F68164865C2DFB852C81375C3D3D5E6",
- "nonce": "4F23D7E91CB8E22BD3712FC1",
- "section_mic_hmac_key": "0BF5C29B16B353256F793BBB4F1C8C52597D3F1C2EFA9D61EA46CDFDE84797C7",
- "section_salt": "8ED27B5A64F8584EE798DA971BB38902"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "68A9C01E867B79A4CF5C2B9B0A5AF91C",
- "data_elements": [
- {
- "contents": "AE6F1048CD",
- "de_type": 505
- },
- {
- "contents": "092DCE72E9C606136151791CACA850F34040EB06480609",
- "de_type": 524
- }
- ],
- "encoded_section": "57911000E8C86E9B41DF4F3B937952F49BC6738B900232D03070C79D80DDE8C1E0999B4434DD06A23FCF22CCD7DCA29E5074665F99831137706D16C0200B8B4598365543AD4BD647A682DD8D226897C1EB8F43C443DBD6F8",
- "identity_type": "trusted",
- "key_seed": "580ACE8B6CDE7180BD4AD61F486AB6AF65F04174A9E10C982CA1BE480E27085B",
- "metadata_key": "E850D26EF14BBB1E7B3D1A5F64A50353",
- "nonce": "2DD94E374A847EE945DCDEDE",
- "section_mic_hmac_key": "597E20CCB0FF2807C1B8217F21115FB753F67303B79DC679094D7105C5EE8A16",
- "section_salt": "E8C86E9B41DF4F3B937952F49BC6738B"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "CC5210E1AA93721F6A77C03B0F1460F9",
- "data_elements": [
- {
- "contents": "31B8D3BD3DAD8D7EA787EBBAAD32",
- "de_type": 105
- },
- {
- "contents": "52CD1D16C9C10292F325BD",
- "de_type": 679
- },
- {
- "contents": "9AA553097F55186B693EF9F811255D4F9E33012D",
- "de_type": 70
- }
- ],
- "encoded_section": "69911000B0B06E5BCBFB897F867D1A98860C88819001968D65E73BFDB4A9C8D0CBCFD94F0AFF86A172DBA041C9B4819B60AE15C84ABF10167323F72BCE73348C948BADCACA60B31C01DF54A03A41FFA1CB83B1724E34BA74D43D17956AEBD6F5E9411F6D801A30C545F5",
- "identity_type": "private",
- "key_seed": "BB1C67EC1220D0A1CD718868B6DFF75A45F535D79358AD7417E98F584A520850",
- "metadata_key": "5E11BC73AFA36ABB0FA9D177F470772C",
- "nonce": "10C1E9BEAA44D044A6A52DA8",
- "section_mic_hmac_key": "8F47EFD6981006EC099088AA42864E13399300C42A22D67FE00540745BC434D7",
- "section_salt": "B0B06E5BCBFB897F867D1A98860C8881"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "636CF984B555E396E1ABE06B45A0DC9A",
- "data_elements": [
- {
- "contents": "26124A707B14872CE3CCA803962D1E8E",
- "de_type": 356
- },
- {
- "contents": "5BE121EE1535F68B384B2048",
- "de_type": 191
- }
- ],
- "encoded_section": "5791100091150893740502FC52626D5C1FE1D97B9004D692F649B521B08446966B43B3A0E2853FC66A18FD044B2D9FA619580671AF9A093BC9C29AC2285193C8377E231E4E378A0EB12B69F309BBED412881C06054211F79",
- "identity_type": "provisioned",
- "key_seed": "9F10722920D514FCD00582382A3D744B7513089C4ED4F0F762E62F079817EADA",
- "metadata_key": "CED359A792C26F42583568633F362936",
- "nonce": "AC3820DF4711726BD92A95E3",
- "section_mic_hmac_key": "73CFEDBC2C7DCC199778704504D8406E69DEF3850E9E556E65264FA5C0F72049",
- "section_salt": "91150893740502FC52626D5C1FE1D97B"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "BB72B0AF2C215797791F4813246EEAAA",
- "data_elements": [
- {
- "contents": "B560FB4055782B29002780C1C79A92C3AB5C94BBFE1D30",
- "de_type": 704
- },
- {
- "contents": "D9D67201EFBBC989BC73CB82CE5A54BA30270BCBCD16C3D918C46C8FBA",
- "de_type": 759
- }
- ],
- "encoded_section": "6F911000C4FC89ADEB54417C2145D31AFE590E67900479850A6176A11C5005C1B816084BBBC8E1B96A5E84FA83927CFE3F85B13CA15C78C4E487AF94942D9527A4EE40FCE291F8A4076FF3285DBC70EB2AE12076384B309C9DB593EF97E5952F1A878E9357C5215EC4CA7382A07821CE",
- "identity_type": "provisioned",
- "key_seed": "4F5BCFCBCE781EBD9353546FEFDAB4123548E63980050C1FB2FEBE745EFDEFFC",
- "metadata_key": "18CE930F2687B1C72063C2B147ACBD0C",
- "nonce": "09C9C088DEE34D597B83255B",
- "section_mic_hmac_key": "3BD3CBD58CE94F98266BE570B2897F0C0CDBC8900AFB76E0699315F0132C8D5E",
- "section_salt": "C4FC89ADEB54417C2145D31AFE590E67"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "9BBC179545C4C8661833BFEFE25E4478",
- "data_elements": [],
- "encoded_section": "3591100018CA84AD571B443615D490F5A1AB791E900287C25FBD0A1AA47A74D7960394D449914CF5F364A1DBBFEC57B7447A38AD0152",
- "identity_type": "trusted",
- "key_seed": "0B5BD58A7DB4DAB27EAB2B71CE802751442437C426E163735196EBDD9EEC98A4",
- "metadata_key": "21E42F417AA748179A50406477891087",
- "nonce": "22A25ECB407B6DC73A8BCE1F",
- "section_mic_hmac_key": "35857C6B5BFBA20A9012E81B452C95D5F62B7D429C9F250F6FC8C96EEFDAD338",
- "section_salt": "18CA84AD571B443615D490F5A1AB791E"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "29912DF85FEE4E2802F3CC758240C118",
- "data_elements": [
- {
- "contents": "20EC521C467D60C62519AFEFFAB2989DA34F609D7348CB0648",
- "de_type": 881
- },
- {
- "contents": "7CDFF605A49D2327C04C9523E972",
- "de_type": 339
- }
- ],
- "encoded_section": "6291100096874E513BB028EA8D3147662E898C929004510A31F7EEE22BBAA1A676F50D87B736D02CF8AD40A2FC01F73D61050AF86BDD26889F66B6C7811E98013B10549BA699C5B0FF6B97BC95CA461512A91C6CD748A847E8A06250284F89D8768282",
- "identity_type": "provisioned",
- "key_seed": "BDBB0B95B3F933B91F05CC9ECED4DD468E3174109DEB7A4F0783C40F39E20761",
- "metadata_key": "A97FB828B07A9D327D5567152634D0D4",
- "nonce": "F8BD43493933BD842C97F146",
- "section_mic_hmac_key": "32031801363FBE1A50288A6A9B0756EAA7CC2D653CA0B2AAF345CC13884DD2CE",
- "section_salt": "96874E513BB028EA8D3147662E898C92"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "5D161A5D965DE072EC72B7EAAC295469",
- "data_elements": [
- {
- "contents": "2499FFB9C498F2",
- "de_type": 884
- },
- {
- "contents": "941AFF758DD7D3B66EF8321874A7834A7E7F51BB284122405EE0",
- "de_type": 463
- },
- {
- "contents": "74C7CF3DF00CA35B",
- "de_type": 435
- },
- {
- "contents": "E07BAF5D40CA3AE208E6BDAFF05B4F9E0112559EC495",
- "de_type": 2
- },
- {
- "contents": "58E1ADF13A6F2383CCDE989D6CEB02EE47F1F3",
- "de_type": 396
- }
- ],
- "encoded_section": "9591100066B9B5E27075D2EAFB9B4E2E4159CA659002025D80ECE442E6A3D7F5DF17BEE9E8AA64D2904E04D09898D04EEB323B64C9AC0DC4F9FA55ECD3B7D58DEB3D9FD72FE1D8A213CCD6DFE89D053B106AE0F7A41844294DDAFB6E22A35F6F5A1251CAE0829609A463D966DC5C2BAEBD166B166CEBF5E3471EE3EAE4DFB5A594C0C64ECDBB00D301299F9782000628F11738B95006",
- "identity_type": "trusted",
- "key_seed": "5AEE4779ADDC954FAABA8C967AF32BAF74DA2E3790FF77750F20A10C300C66E9",
- "metadata_key": "5819227E20E94984AF636A055E65EDF1",
- "nonce": "627AF9F6E80A568473F0D41B",
- "section_mic_hmac_key": "97182D1562F3DAC1911CBE791388036D5826EFC5BD2C9B7729555BC39D6300B9",
- "section_salt": "66B9B5E27075D2EAFB9B4E2E4159CA65"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "8EF15FC5E15B86747BD2390DFD8D8FF4",
- "data_elements": [
- {
- "contents": "5F99290FC42275AC698492E2263094B80F692233DB0DF8644B",
- "de_type": 845
- }
- ],
- "encoded_section": "51911000474A64D6CC5E1B015636E3CAF848E92D90029797772EBCF190224F6B5193FC0573554FD8D1B7C2B8DFB0C2344080EC5DE79A14650738DB3E375AB1F2416A0E091F2DADD7710C6731F9D2F4BC1ACF",
- "identity_type": "trusted",
- "key_seed": "3807E53D0E4A6A3C131FE2D9A12F3A17C9A81E206DD2403424D079986548F36D",
- "metadata_key": "649BF41A962338BDCAFB3D6EFB39F30C",
- "nonce": "11EFABF3B773890FD705DC45",
- "section_mic_hmac_key": "BC9DE8BEFBFBFCEED8132F0E74A7FAE68CCF1F3259B42670C074355E57771EC6",
- "section_salt": "474A64D6CC5E1B015636E3CAF848E92D"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "D87966196010EEDAE937B516E77C110B",
- "data_elements": [
- {
- "contents": "D72414FDE144",
- "de_type": 693
- },
- {
- "contents": "89B82594CDEB3253E8BE54402F4EB47427FA",
- "de_type": 139
- },
- {
- "contents": "59F5D560DCB71A1A9AB340270EFCCC791F60ED3E5C16C9",
- "de_type": 361
- },
- {
- "contents": "5E8317B7EF6B2304CE733AF9AA4303",
- "de_type": 347
- },
- {
- "contents": "6B46914ACC05AC520CD86D64D95EF8B0E3B52684AC19C7",
- "de_type": 217
- }
- ],
- "encoded_section": "99911000550E90767EA297708A890EB778F86F42900194407433CAFDBC096242CBB630D9EFF2428967372331DA563029EE56D7736DB1C6B0F4171C6AACC70B165A1D7079B7213A484AC56B751F106EA890EE1F44B1DD84B03340FF64DE0D86EDF6E3C266B6E29F973D7DA9EA80DA5504E23FA9DEFB13DF26D97D8AC03B102233E7A400716212664A1A66A04360810288591BBC53D82755D0B7F4",
- "identity_type": "private",
- "key_seed": "5E128361F047F517713A5E7A9FBDFCBB8A65431B0FD54CEA276C15AA38738D00",
- "metadata_key": "6219FC039F504E84C27E0C30A7922D50",
- "nonce": "219ED909CC34B1C57EB81FED",
- "section_mic_hmac_key": "80144AD3F7356F4D118216C943ADE3CE6A4C1CA1AC36CCEFD81AF75222A0C277",
- "section_salt": "550E90767EA297708A890EB778F86F42"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "ED1872743ABF1CE1C54B5924D8B523C9",
- "data_elements": [
- {
- "contents": "1EFD8A5E7097C3EA66A30F3F6EC8",
- "de_type": 8
- },
- {
- "contents": "70AA1FBCAEAF957AF9C114",
- "de_type": 741
- },
- {
- "contents": "727C6DA4BC51406D03",
- "de_type": 628
- },
- {
- "contents": "C80BCC953AFBD14D003F9C18",
- "de_type": 905
- },
- {
- "contents": "B3EC6F94CA366939C934FA84052FD4",
- "de_type": 357
- }
- ],
- "encoded_section": "8091100002C4DA8D1B21BAE28B3F9A0EB5693E8F900493FCDCCF43EBF7EF19D4476026AE4F5241FE0162977FB70B8E376CEE57BC2A866306A3787F61E88D954EAF7060BCE7A3023C7683CD7EB4F9D15A14147EAF9FE39A0BF9863BCFFEF8F4F2E8AE52F06651E06E94F809CE32E06DC15434A3A3D7AF4E42BBF88EB53E9197D489",
- "identity_type": "provisioned",
- "key_seed": "3DBF4DD4A42D6FE76568BF430BC73BC5772762941753D48A76134021D17123C7",
- "metadata_key": "B6B17BEBEA55CFA5B610047C599FDCB4",
- "nonce": "9E2B3708BC702B007B2B49E8",
- "section_mic_hmac_key": "F0E7F12DF72F3EF40DE46181DD19D3E673AEE02757529C53F3F6DF9F8AAEF663",
- "section_salt": "02C4DA8D1B21BAE28B3F9A0EB5693E8F"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "74300AD75CB40E2D6CC26BF7C3EE29E6",
- "data_elements": [
- {
- "contents": "506CEBFF222CD35C949137A3A47D6FAD9620",
- "de_type": 439
- }
- ],
- "encoded_section": "4A9110007816B4ED58791237D1053F88CD8B7B859001D1EBFF70B960E79E6DFA6A89359F991816C253BB5B09AA2E98748E101D8BB2D18D4043847E353F85C82A586B92D5E7F0DC03E6CD14",
- "identity_type": "private",
- "key_seed": "8CE98EB290087656B04E4996CBF4007E92E653CAE71AF06D479B96D45B83447B",
- "metadata_key": "81A2696BD7D21903EE2D63D2C4C44E4C",
- "nonce": "CDCBF3E9E0E3EA002A004AFE",
- "section_mic_hmac_key": "48966839EED698298B8544D0FABBB3E8009D9D67CE88CEB6F29B1FBFAEFB7C47",
- "section_salt": "7816B4ED58791237D1053F88CD8B7B85"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "256EC73F1FAF17723C9B5C6062749FF7",
- "data_elements": [],
- "encoded_section": "359110007897264056B8ED625680B2F5124C30A890045D4D46423E9067DF2DFD36F3718282724748E10C6E16DA2C039F9C30D9FF6054",
- "identity_type": "provisioned",
- "key_seed": "D458DDE6E939B3C03B8CA27BE7D624D70F3777FB31C8278152C3C0161269A228",
- "metadata_key": "76BCF4EB8C12033E8BF0534B8A6AAF4A",
- "nonce": "1451BFC0DA68DCB2E0FCB937",
- "section_mic_hmac_key": "DDAF42B3C3AC34F3E8F2C882568213E333A91F0A049E79AF52E98669048CA81A",
- "section_salt": "7897264056B8ED625680B2F5124C30A8"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "1599363CAC85444B80B2BD6F32B44889",
- "data_elements": [],
- "encoded_section": "35911000D8624D1EC90B225B457D22AF6D8B4F799004990761D38053D068BBE94F66F9968E14BB793A96B05BA0F4716C0A7814D331B0",
- "identity_type": "provisioned",
- "key_seed": "7CF0C36D0E587661503F8F70B8F3A06AEA7B6352E843387F353CA8355EB92ADB",
- "metadata_key": "A54230D1BAD378D531DB91F517D11568",
- "nonce": "D25B10F1899F9A9C56648C1E",
- "section_mic_hmac_key": "C1A07E6C0ECA629D1ABB6CF5D6175F97E97637756561930B256BB6891012A830",
- "section_salt": "D8624D1EC90B225B457D22AF6D8B4F79"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3EB28DFBFF8CB955CC44F68B0085F70E",
- "data_elements": [
- {
- "contents": "8511547C881A7F7036FA2009F904BF",
- "de_type": 42
- },
- {
- "contents": "7C4430D434907C017DACFD336A161E70C10815B6",
- "de_type": 284
- },
- {
- "contents": "15C1124EF76C2D9BB61C",
- "de_type": 132
- },
- {
- "contents": "3E3B0BFE93189B50",
- "de_type": 694
- }
- ],
- "encoded_section": "759110007F2CB662B15FBA6D7C18AB52889B266D9004CB724FEF84FE55FCB1A2B571C77EE17C930A5F6606F40EC38F4241A6B287A8B1EB443F7C013B34B3113D193F884B120F0AA415452FFAAA0B40B78DD80A09858F2068537D2AC8F8DF750509B9D52A4B9B39F10C2CFC42A9B90FC762945BC31CAD",
- "identity_type": "provisioned",
- "key_seed": "547C965E115345BADE7FA439398A1618870F0392671DEDE9944FCC693DBE32B4",
- "metadata_key": "C55B065D5B03C633C7546FFE3043FB8B",
- "nonce": "888A5C195BCC1327C7DA9E7A",
- "section_mic_hmac_key": "F672CB3E86B8E87B727CB0814C7AE096C3E7C7EE2398D1581847C26951486BBA",
- "section_salt": "7F2CB662B15FBA6D7C18AB52889B266D"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "A952EA928E55FAE45B612EFBB2E92897",
- "data_elements": [
- {
- "contents": "A39AD60114B4E470CD6E5B1981F6D94FDF21E386A957B3",
- "de_type": 11
- },
- {
- "contents": "30309360211C7E94BC8B3692BCE38EE888ECF197C594C3D07D",
- "de_type": 10
- },
- {
- "contents": "66DF42C0A9CC3385053676451C23276C1CB169D74DDB1C46A6EDE2C89707",
- "de_type": 610
- },
- {
- "contents": "550E675F587E",
- "de_type": 554
- }
- ],
- "encoded_section": "939110008F8202EF37CD727B74948F6A5205650390045048FB340FCBE272C4D667BD6691E08084C56D24D168EE7C6B3AD228DF31ADD89B1627C7511ADF1E12882ACECB1C05B49539F332C01F0C2778F039A5727864A5FA46F9030820D06D961123CBDED94746017E6B2224D43BB304D590F12343258BDCF84F691600B58C18025956190BD91D359B1654D5862590962E89FC3541",
- "identity_type": "provisioned",
- "key_seed": "D75311C9FD54732B0D1D58E8C13D69582675936BC2D4B948E4DA8B8FD4E4EC19",
- "metadata_key": "44A8ED043D7B7A04048C04871D04BF28",
- "nonce": "39A11C1233C3887D0FE2FF95",
- "section_mic_hmac_key": "0370E5CD2CA4944C5633BDB505F471ED4ABD6F9E0803BD57669BF1A096FBFAF4",
- "section_salt": "8F8202EF37CD727B74948F6A52056503"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "375CC4495D0E6037B4A269A5A4EA302C",
- "data_elements": [
- {
- "contents": "E51613F10B7423784CB6E3FF2E58",
- "de_type": 683
- },
- {
- "contents": "ECBD79DDFA8130DCDEF28AD2AF40C6A8DBB16B2972",
- "de_type": 264
- },
- {
- "contents": "9FD18CDBD2FC1FBAF9B317FF280956",
- "de_type": 617
- },
- {
- "contents": "8871908BB20E8F",
- "de_type": 918
- },
- {
- "contents": "DD8DA6F96A3751",
- "de_type": 721
- }
- ],
- "encoded_section": "84911000C7A3432633031353A946F0684CFCFEBD90012BD99B1A635B8CB01DDBBDB46AFE8742B053F93A65C75293797C523784EAE07488134AE32476E0F698D440C3A0A389DB48B6846E2D42A89584741285C09301225752A1A5C8152E010337BBA3ECB3C15D6893C2B2CEAB1FB452D50E5990EA1C9B007C08642769AF82551F3FFA44040B",
- "identity_type": "private",
- "key_seed": "D948351CA86C11F94DFA31FC2B86C7EBD32251E770E243B287D5C03630A7A4B4",
- "metadata_key": "0F37FFFBB8B3BF85BE6B4A5D7AE60C37",
- "nonce": "5A8953196DB0C6B086052AC9",
- "section_mic_hmac_key": "6A6CE54F7E0FCB42716786C56294DB3FF4839464EB6D6DDE3037015BF42591CD",
- "section_salt": "C7A3432633031353A946F0684CFCFEBD"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "2276BD761EED06699E8A4C1B005226C8",
- "data_elements": [
- {
- "contents": "09D7C7411219259A530E4207",
- "de_type": 202
- },
- {
- "contents": "E6206D70CB69117E5B0CFC6484E5A9F6E6",
- "de_type": 335
- },
- {
- "contents": "124F723ABCB0F46AC2D9904E49F29C72F6A37A6F1C",
- "de_type": 173
- },
- {
- "contents": "F03BE2BA870E9DDDE0A20C37F7C3C513418FC8595CC2D9",
- "de_type": 162
- }
- ],
- "encoded_section": "8A9110006FD81C4F4977A61EA77802E4AE331B1B90044590EF69F794BECCA20B04E1A5794A8FE0BE6B353BAE140B8A37594A011AA936FCD209E03D522D1C147E321147E9B33735F2CA413B5C945091EC1AB92537B781F26714EAB879BF33E801BE58488C11306DD259B63B1F05FC146871978B17CACF8AEF88D021782A6DB7112D4C930FCA66626E69140B",
- "identity_type": "provisioned",
- "key_seed": "B3E1C7E5933E243B2457C3493F6C62D88640DF85591E1A370EBB5ED1A7E87DDE",
- "metadata_key": "584C3B455D31A6EB73CA6286A6D1D677",
- "nonce": "7C59A6FBC27521B60FDE3D85",
- "section_mic_hmac_key": "4FC402F911776BD4BA7E1B934A76823AAEB91AEAE70F229149737AD2446C8721",
- "section_salt": "6FD81C4F4977A61EA77802E4AE331B1B"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "ABD1E3B92ECCC94887008F9712C8B92E",
- "data_elements": [
- {
- "contents": "53AA992BF504934429F0D55BCA57E7E4DD02BF1C51",
- "de_type": 77
- },
- {
- "contents": "37",
- "de_type": 41
- }
- ],
- "encoded_section": "4F911000117F8B155FCF545D9DDE2E2404BF08579001181FAA51DA6430295D27D32A8894FC80977F9FBB2260C5F335DF5E2985B1E9DF677F8DF40E3DD10180E31FD4A1E640AA81AD2D59ED29C73E0DD9",
- "identity_type": "private",
- "key_seed": "BAE413A1CB297D1B55956EF2E3D47463B15721D83113EB265CDE9742DE57D1E2",
- "metadata_key": "E118EB2F2448E831DCB2F01211D4E299",
- "nonce": "641B644EC4576653B4ECE6BE",
- "section_mic_hmac_key": "7001ACCF2A6FE829E333351CF9500F0EC9F144AC2432E2D4E65BA205B5A2A083",
- "section_salt": "117F8B155FCF545D9DDE2E2404BF0857"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "0B886C679F8368F71B69095633FD827A",
- "data_elements": [
- {
- "contents": "C57A03111A582D033BA2F0BBF50F0698BC008461C715",
- "de_type": 648
- },
- {
- "contents": "0C95F385C694E2BC55C219B0086BA9F8B64C0633",
- "de_type": 415
- },
- {
- "contents": "C9826C977F5D51",
- "de_type": 246
- },
- {
- "contents": "B88067D984",
- "de_type": 989
- },
- {
- "contents": "98C5E507657F0B36CAF5D0EB02A5B30F1087",
- "de_type": 663
- }
- ],
- "encoded_section": "8C911000AD6BDCEEB60CC9801003D4F71FB8AF0F90049916A86D88CC6C404111A7D9075FFC0C699303B2BB1CDC7492495C139069B609E02C45F3F2F5D1F11C5CC45EAA610AE5F9A3085D638A8D774E060572A9E8E276FDC2B9EAFFAF23469097068D9F2AA77BCB5F548EF636B8BEF3C02495DB690858EA8A13C78501E64C54D05155EA488719C539D7B9060048",
- "identity_type": "provisioned",
- "key_seed": "B323DB96EBC1CBB190E305EBE290EF7E600D3D3E7D23688DC2C8C23B4EFC7A4B",
- "metadata_key": "6436A7FA7D38F566B85179BFF2E4DA68",
- "nonce": "43B0153AB9B6FFB0DA670B28",
- "section_mic_hmac_key": "88BBCFCEB5CFAB8C69C5C978C8C21758ADE72E557C108CDF780367F6456C85B4",
- "section_salt": "AD6BDCEEB60CC9801003D4F71FB8AF0F"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "E4E6282E18B2700912371FD299648904",
- "data_elements": [
- {
- "contents": "6E",
- "de_type": 875
- },
- {
- "contents": "3E7F165B8725499C73A790",
- "de_type": 547
- }
- ],
- "encoded_section": "4791100001BF56D7253FE9F2388222BE2B414EB49004A2C3ACCC4EEFD9949E6470223F1085EEF12CA22DBF4E5A9DA978E44AF3E93F6142BE9270F59E188FEF58BBAC3BDCE8413351",
- "identity_type": "provisioned",
- "key_seed": "CFF5A7B58AD3CF1BF200E0874E1E404E0B8EC0BCE8812F1FFD4537E2330BF4F2",
- "metadata_key": "C048921E6EE411AD4698E29A54BC6B4D",
- "nonce": "8D23F89851021F5141478E33",
- "section_mic_hmac_key": "1988C5772B660124148F05733A326F0F0C29DC301F2989294312F41C56292A59",
- "section_salt": "01BF56D7253FE9F2388222BE2B414EB4"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "78DECA4E98143AB700746AACAE4CC14E",
- "data_elements": [
- {
- "contents": "F42C1F5B9E2060A6D4CDA7A2963F44A524BFFD5F0F2D69F3322DCF4B93E3",
- "de_type": 359
- }
- ],
- "encoded_section": "56911000FE30CCFEF9FADE459409BCA8286268B79002DC0290C23BD3C7F0DCD8443EABD050919255A3755D0F5EBCBA7B540DA11DF0E844207B803710FBE088BE18847F5406B7711DBC583711B7930508B0B06F801CA9AA",
- "identity_type": "trusted",
- "key_seed": "F44873C8E1AC0DC8D63BC7CE805E543BA8A73CB83DF807B608246E14CFCCE5D7",
- "metadata_key": "D0CB13BBC77450B18573A000E0E4B324",
- "nonce": "D97378F4DF5B4D5249845D4E",
- "section_mic_hmac_key": "11A63498ACF2C0D60AFEE3AD00117129582FFD6D50D3CA4A21CD3330BAF0B2C0",
- "section_salt": "FE30CCFEF9FADE459409BCA8286268B7"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "99CA428E9B70F3A4F34CCE2EA3FFD1C6",
- "data_elements": [
- {
- "contents": "95651D83B5B463A0B4D7C3BF97C1CDFD9A2853DD216D",
- "de_type": 842
- },
- {
- "contents": "B1E32F",
- "de_type": 633
- },
- {
- "contents": "B44550D17D11C579DDE453A78F8E68",
- "de_type": 764
- }
- ],
- "encoded_section": "6691100074678AA45A5827136A450437EE29F5E39004B94F1326A3CE7BDCA34AC253366FE37E6849758193586827933D9E096053DC06102448287A436069815904A0F3895C825ED3538CB827DF1B153E833F11DD926D4E5A45CD20EA0FE3FDB21A587C6C77638B",
- "identity_type": "provisioned",
- "key_seed": "71A3A2B3B223F84BE6E8595208384B34D0379E898137A3B5DC4F18C71502CACF",
- "metadata_key": "8998FDB14463108B5A5F66FE289D13BF",
- "nonce": "AFE96D0E4FF65C1734F9F99B",
- "section_mic_hmac_key": "2222BA7F416FFEB9B14B07D5D2522EDDF0D2E82CB116D23699566520035BC6E7",
- "section_salt": "74678AA45A5827136A450437EE29F5E3"
- },
- {
- "adv_header_byte": "20",
- "aes_key": "3C5965394479133B2B0CDA3474935C12",
- "data_elements": [
- {
- "contents": "4C5DE6A43F855833418B23DE6E4C0AB9B8A6D1C581F15A683D",
- "de_type": 831
- },
- {
- "contents": "1AE2D41BF9064E056C22712044707CEA3EFAF26964D83E684D33CE",
- "de_type": 355
- }
- ],
- "encoded_section": "6F911000BE86E394E730BAE02E2A22E8B54CF1A4900408EB6891543847E08002B13233D680C89B22F57320B4890E87533A2B4DFC30021206330351F378D93A7CE5051655B1EC84F8F4F68DBB327EDD4E0DA4948323F1B931733AA4D28F06238FF3622178015BB5C709094AC23A3E448D",
- "identity_type": "provisioned",
- "key_seed": "CFBB3B4D111CDF95E4AA9642D5D6C1611B8522D6F76C7B1F23C09DCE58133FE2",
- "metadata_key": "3BFA93FB827970E4CD401DD9903ABF19",
- "nonce": "2CFBAEDFFF07C80511FE4B1B",
- "section_mic_hmac_key": "16B7AD3BB2B10A5B5D64ACEB9733BEDC6D0FD351E5D12AB36FF5FB283DEDF3F4",
- "section_salt": "BE86E394E730BAE02E2A22E8B54CF1A4"
- }
-] \ No newline at end of file
diff --git a/nearby/presence/np_adv/resources/test/mic-extended-salt-encrypted-test-vectors.json b/nearby/presence/np_adv/resources/test/mic-extended-salt-encrypted-test-vectors.json
new file mode 100644
index 0000000..52ff336
--- /dev/null
+++ b/nearby/presence/np_adv/resources/test/mic-extended-salt-encrypted-test-vectors.json
@@ -0,0 +1,2213 @@
+[
+ {
+ "adv_header_byte": "20",
+ "aes_key": "93FD082896AFAD5C02272FCAC7A4B19B",
+ "data_elements": [
+ {
+ "contents": "F111383178463B",
+ "de_type": 965
+ },
+ {
+ "contents": "77A7CA333048119F23A460ABA89494CF7075CB3CC00E",
+ "de_type": 148
+ },
+ {
+ "contents": "E7B0F2",
+ "de_type": 596
+ },
+ {
+ "contents": "7B25D72AF20B8B53495E79E004108C7651C5F9CF07BDCD784874",
+ "de_type": 969
+ },
+ {
+ "contents": "938EF51180242B59D35CAD0DA09ED9FAA4D809BC",
+ "de_type": 47
+ }
+ ],
+ "encoded_section": "02E628D03BE58B76606FD929A1D1F814D1163B0AE8EFD98D12D07B1F0D8D0203296CC45F4BB29B1B55859205A94440A19A7D13551244694A00388C0DF6B25405C6D2F6E15D8D1E4383D8D6A28BE510CB8941A7E44040B656C77670B9DE3612BD51E7FC7200C5CA9D4014BD784335CC4C377156D3E8B8750CDEAF086D82715EFCDB87F02C7F96D8EAF7E011169F2A",
+ "identity_token": "92220A2275B7CB8D5B8F7FDEE137C385",
+ "key_seed": "74BD3E08D69FBF2DC5431C5D2CC66BF83D602B54FA10334916F9457DD7F309DA",
+ "nonce": "C2B4EB521EA983D74D009C90",
+ "section_mic_hmac_key": "D1A28568BDFFFFB2D23AD8FAA174F72993AC0B5B23ED27CB27E7D99760AE368B",
+ "section_salt": "E628D03BE58B76606FD929A1D1F814D1"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "D371D308EB2FE0705ACBECFA55123A55",
+ "data_elements": [],
+ "encoded_section": "02074BA9EC8D17A3258489F865AA8B5AF679E71F22BA9938EDB211EA8163236EA810390E1A6CAE374F5446C039F9A031CE38",
+ "identity_token": "1F01AB90BD3A83FE37E74A301D415475",
+ "key_seed": "1104D617C7F480B1B5875CE6711FF91BC76FB208F8CD7D9F9A08AA9DB0FBC5A3",
+ "nonce": "4FEC96E42BE9C8CD180003A3",
+ "section_mic_hmac_key": "A5E871DC448A3B0EFD26DFEBA9EED9FC74EE02481C6704FE906D7A82E2BBCD29",
+ "section_salt": "074BA9EC8D17A3258489F865AA8B5AF6"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "97F371754AFE9C6F5438F467D077CEA8",
+ "data_elements": [],
+ "encoded_section": "02973AC46A20846531A220E935400EDDFEC74BA44660727C7B33874948C21A903010ED5DE380C975B9216B743277D73628A8",
+ "identity_token": "3ECB6505ECA3F0644780E4F848B8C914",
+ "key_seed": "777BA0008B38A5AF3F3CE15B1DB83B2612E312739447D525885DC0123FD347B5",
+ "nonce": "A848DAB9F824A480E1ACC319",
+ "section_mic_hmac_key": "FBAF9AF0C9E256671A99C74F3FDB9C17803ED334F5BB24C72FA056E05E3FFF12",
+ "section_salt": "973AC46A20846531A220E935400EDDFE"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "C401C5B15A57D0A26CEE901764560E0E",
+ "data_elements": [
+ {
+ "contents": "F83D3AAF1566156FAF5128917CAD10CE348BCF",
+ "de_type": 563
+ },
+ {
+ "contents": "FB04C7C54945BE1F575F",
+ "de_type": 945
+ }
+ ],
+ "encoded_section": "02ED1132C6CB2146F95306E0095791FB969C04AD11D18479F8A868273B5A3C3E1833592069C4077690D4A48D8F5F55C27FF3565B3D859F44E6D4DC439A38BC6063D55F20EA3494469131156AC1568BA18A8AE6322B",
+ "identity_token": "932D597EA1265715083C01111B233551",
+ "key_seed": "5B1F90B019BC982CA431E8CE303F506E192913E9E0D9E7AF75936F1A8336E29E",
+ "nonce": "CE5FAF170ABFEE4B7D446D23",
+ "section_mic_hmac_key": "A876F7A6153B0A4E0C00E367D2A62C2E69B8B172AACD2F88F5AEA1CE1992BB32",
+ "section_salt": "ED1132C6CB2146F95306E0095791FB96"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "9CBAD2E4548CBCCD00B6E0FB7FBF9473",
+ "data_elements": [
+ {
+ "contents": "7A306B5925D15D6B43B7",
+ "de_type": 149
+ },
+ {
+ "contents": "5912AE51A1D62035C323468AF0198079E1A7110FDBA42D",
+ "de_type": 664
+ },
+ {
+ "contents": "091D6CE6C774BDF76F52CF04688503B8496460F3E90D0880",
+ "de_type": 305
+ },
+ {
+ "contents": "248EC62B07E7904634AD309D8238B1514FCEF2D86601BB2ACA027F14",
+ "de_type": 507
+ }
+ ],
+ "encoded_section": "026A74D621344D87428CEE5060FFDB570C73D57CE4A2CFF3EB2C14839E619A1D967170CAFCA1BAF48A2E45501A6453450187A1D4854E4B238A56DB9E26F231288701D10E43D8468A1E661AB447C32E366315B6BC1073EE143D7C02458C56030516A3DB91E367C941689CAFD6FA9252FF37B88EE0ED4D99EB9313B7BE72F5931ED45525D49C1E068C96D133078E33B466EECEC2",
+ "identity_token": "19263E5F61578937D8D7EFC85325267B",
+ "key_seed": "8578CDF5097D9F1C253B4DDA8471A03AF7F26A01FAE138D2F3D350FBB752FF24",
+ "nonce": "0C6C9E6B32B490B080285EDB",
+ "section_mic_hmac_key": "953DBE0C875F66FFFA680AEA984DFF74C906D326B58B19A804F20BD104B236A3",
+ "section_salt": "6A74D621344D87428CEE5060FFDB570C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "DCE5AF2A5A7AB0A6F2308EF445084D6A",
+ "data_elements": [
+ {
+ "contents": "44986ED23F155AC13CB849AD9C4FD3",
+ "de_type": 520
+ },
+ {
+ "contents": "9AE30C51E00E42BB",
+ "de_type": 294
+ },
+ {
+ "contents": "",
+ "de_type": 192
+ }
+ ],
+ "encoded_section": "02384716FD70BCC1D2B3572C678ACDCB1CCB3ED7DAD80CEB08CD5C6E324C5BF51830123D1A83775462CC0BD667255BD88D21D8A972AF982CFCCB54DE20E1F38F8A7F6E2E525B13AC0AA5282ECB34FD2AA8C2",
+ "identity_token": "1831C66E762DD247D3D0A3F7CD278B6D",
+ "key_seed": "2168D48C66B609FA91D4A98D35F0941AB227F1D05CB42C81E6C3773DBCCE8556",
+ "nonce": "6BE8AB33FEA8DFCAF84ECC84",
+ "section_mic_hmac_key": "A62AAB51DDFA839AF5FA651C807D7148269148D0926E1A86D108796B98706601",
+ "section_salt": "384716FD70BCC1D2B3572C678ACDCB1C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "A220AB81C5F6D95C89F75244513A865C",
+ "data_elements": [
+ {
+ "contents": "6045FC019235",
+ "de_type": 587
+ },
+ {
+ "contents": "F46063F443E58DD9A62CF5935E009EB1F4DB4021072AA8662EA3667D",
+ "de_type": 720
+ },
+ {
+ "contents": "335D2813B9BB0B3D302B",
+ "de_type": 978
+ },
+ {
+ "contents": "CBAD44D6954386F14343090074EF8B4BF900F75B810B",
+ "de_type": 209
+ },
+ {
+ "contents": "A5",
+ "de_type": 818
+ }
+ ],
+ "encoded_section": "025676256DEEE42A0A9FB667E01DE178058CA5C182B845F41E66D5A78E96C550B1620460461E74C4B4FAA6277A598899798E8E07B73E6B99BBBD4F22767E7B9C751B4AE7FD09529BFC16BFF03E02662E3D2F6AAFB8429B233260311E995B59CB3757479A4F5B1F167E0E461BA882F9F1A95D8B7B5A65014DA76C3796BFAB028974E9F487",
+ "identity_token": "E98107D0B6209C2F99E458FF9DDA5EDD",
+ "key_seed": "67397E84E19D943457D649FC1C85177CA2283A285DEC02F77DAE3223822F10C6",
+ "nonce": "84C350AAA3DBEFE6C4AEE93D",
+ "section_mic_hmac_key": "CAC3BB4657D8FE9840CE0B2339AE0F7416D583748B89D950BDE6DECA04EC5C5C",
+ "section_salt": "5676256DEEE42A0A9FB667E01DE17805"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "8183EC3E35044B898637AC452F1344F8",
+ "data_elements": [],
+ "encoded_section": "026167137CA22AF2130EA98F1046B4063D4D2353C7595F0631AC75DC9B450BEFEA106A6C243686C795EE3D7B68717556E523",
+ "identity_token": "E0855E9D123AD57CD4BAA1619A33CB8F",
+ "key_seed": "1572B2064990B9BA7EA8FD487BE6580BED3AD5332CA54605D801D82C25813372",
+ "nonce": "1AFDA6FFD7B3CF5FC5C2844E",
+ "section_mic_hmac_key": "E6F8DF148FC91C004791D9CB5E6881CA536E14CB366F6B2D73C1C3995161A74D",
+ "section_salt": "6167137CA22AF2130EA98F1046B4063D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "083CFF217DC4F7DFFA8B3989A602A800",
+ "data_elements": [
+ {
+ "contents": "F01E2E1B19F7F410819FD81F2B22F7065E3164E1A54ACFF05B73D011",
+ "de_type": 886
+ },
+ {
+ "contents": "87A24D8B5990862B291D9CDF44A7CF15",
+ "de_type": 363
+ },
+ {
+ "contents": "",
+ "de_type": 230
+ }
+ ],
+ "encoded_section": "026DC137DC284DA96BE876644C985CFB021DFDAB61844B115F94E05FA2D4EAD52345AA96C988FB3376D05D29BDA4D027AAFE41CF5E10625A61B12A000FCA96AD5D5BAE78AA3A8C186DCF5729744F572FF4370291D35642D5088995AD034E28CC61D05876729AB1",
+ "identity_token": "7310CA7BB155529509A89AC74042075E",
+ "key_seed": "5DC834BD1930C71E749AEEE8E3518EBC09C9B860B6F6372D58A1BD141E89B08F",
+ "nonce": "4410414C0013373CBE93D03E",
+ "section_mic_hmac_key": "B9B9B858E9859BA09D8A1F17B0E6AC0C5F6286C708C95552A464924B629C7C10",
+ "section_salt": "6DC137DC284DA96BE876644C985CFB02"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B44C62C6931281637F75DE6F1D3F39B1",
+ "data_elements": [],
+ "encoded_section": "02048517CD42EC7AF6C9FB66E2F3078ACFA38819E6A4E0B9BD8859750BADB4232910C0BE5A04C215798BC885D7781C579B72",
+ "identity_token": "D9EB6B7007B30C0EF6CF01A7910D8B11",
+ "key_seed": "15F39B4B7DA56E28820DE711A002EFE525A5E32605234508F57E31A12C520938",
+ "nonce": "EEABEA7D9A551E134F3BB00E",
+ "section_mic_hmac_key": "0C9AFE67BD257E145EDC49C851378382C4899F18B61ED1A9D1488D63D9A7AE1B",
+ "section_salt": "048517CD42EC7AF6C9FB66E2F3078ACF"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "187638BAC5FEA85287840A933BF6BC8F",
+ "data_elements": [
+ {
+ "contents": "15CAF364A09A674E23B3724F87",
+ "de_type": 655
+ },
+ {
+ "contents": "B44AAA22887D6901DAB2B15D2821DA6CAF",
+ "de_type": 663
+ },
+ {
+ "contents": "3D75D65255A28AFA0FFAC86128AC",
+ "de_type": 568
+ },
+ {
+ "contents": "8F87B0032134C16C3A5C55E944216C6CBA1FCA9699",
+ "de_type": 919
+ }
+ ],
+ "encoded_section": "021131C64A1BDAC5CD00E80724986AB4FFD8B57A83029720FCBDD1CB945FA6A0E95D43C3FEC6573FC13757D4EDF3D85AD806A456778D52E013B1B418BE71E73CC08857EEF334BC2DBC1AE87C04D8D5FC35874B09964455EF5B444D0569F53D2EA3F442011BB799A6646E266EEDB93BB2295E58C17BCE62C63DF2A988773A94",
+ "identity_token": "33C178C3119530767A131BA20E39C282",
+ "key_seed": "B1D18E5E497268A55170AE018FE33B3085490E7FA03A04AF02A6853BAA9C700F",
+ "nonce": "19A21AE5D8370686F9D64523",
+ "section_mic_hmac_key": "F751860DCF60C03436AA4782865E8C89C33C1851352793CE41E3E08B5585866F",
+ "section_salt": "1131C64A1BDAC5CD00E80724986AB4FF"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "BA6A05D814D7478B1D442A0C6E5ACBD3",
+ "data_elements": [
+ {
+ "contents": "7E5AF9A1D0129006",
+ "de_type": 272
+ }
+ ],
+ "encoded_section": "0284E383F03BCFBA802956AC1D331D49148DBDAE82CC80EF8E854495252475C3491BC6A881642FDDA6C4B8403F32D4E3EBC65F5702BA53D740EA6A01C2",
+ "identity_token": "2AD4A3ED2DB4D967EAC7F080F4CF40C8",
+ "key_seed": "19F9E4A47586993C7A276A929D00A0FFC15FE2F4020CF6B05B04C4F4D0C6DD1A",
+ "nonce": "F807F49730187CB3ADE6199D",
+ "section_mic_hmac_key": "1576D69950F0F1E079F379F3ADB914775C4AD5AD22CD61561F8B9372225E8019",
+ "section_salt": "84E383F03BCFBA802956AC1D331D4914"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "EB5575D5CF3527ECA045F3979A56A309",
+ "data_elements": [
+ {
+ "contents": "35D7835CAC",
+ "de_type": 205
+ },
+ {
+ "contents": "7FE4C599A437353892D3C213AC6A1AC604F4F9AF",
+ "de_type": 582
+ }
+ ],
+ "encoded_section": "02ED47A961048AF2432C532A68C85D8774E661489D120680C88F13AAEEBB7FB3492F43D8628F8F4F0908A22FFA780DDD956F89A5050DBB98E4F52C25FF30349A76D9B9E39D7FEABA2E63CBAA742B683B65",
+ "identity_token": "82A145333F4DEE9F069AADF41C54F072",
+ "key_seed": "DE758EEEE4750E04730AA94B4F238B6CD535F551C2BA67446A254314D600ED28",
+ "nonce": "4241309102A36EEB9CECAD67",
+ "section_mic_hmac_key": "4C1043B09127BBD4807B84CB8095EB362229FD36D9392553B988807B8EA386D0",
+ "section_salt": "ED47A961048AF2432C532A68C85D8774"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "9BD48ADA5F488E055CC936AE39807325",
+ "data_elements": [
+ {
+ "contents": "342C2F6E6DC0F507E670A49386",
+ "de_type": 389
+ }
+ ],
+ "encoded_section": "0288E7C4BD0D3B41077F9D17F9CDFAD09AC4BB564892C8E1CAFC76393E1BCBFF0720893D1D78C7F60C4A4379DA5631EB6410BBF5B9D2E695C95895F1386B3533A72F",
+ "identity_token": "98AC76B171BBA2D6F74D2EB070CCB2A5",
+ "key_seed": "289A2476986D21D1D4461D43370BFB00BAA75DB8129366D1B287E1DF2346D686",
+ "nonce": "5AA5D7324173A3A8B25CFD2E",
+ "section_mic_hmac_key": "613B7BEC61CA3F4917327E9F57265497A2DA3FB4A8D1A2E64F450E70BF4C2A55",
+ "section_salt": "88E7C4BD0D3B41077F9D17F9CDFAD09A"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "D6964D2F633FDF7ED603E51BDDC2257E",
+ "data_elements": [
+ {
+ "contents": "AC844B564093FA92B8CA12B19613D2F77F4A656F8319",
+ "de_type": 600
+ }
+ ],
+ "encoded_section": "025588191AB27D12C53FBB0AC6514C35B6A213087FD19806FD6344B4BB336E49962992FB90F69A43E3D3281CC6E20822037F382FB9D98F25653F9FA6984E51DEBAEA3061605A4614434689",
+ "identity_token": "A0A4A57454A31A1B4CE36D757ECD18AA",
+ "key_seed": "AB60BD9D7B2DBE281E8A6EB916B2042923046CF68F36CDA67F27E117AD4A7CC2",
+ "nonce": "82E43E99AD73B19CFD430B95",
+ "section_mic_hmac_key": "8F4D7D6A549F07659A3FC656056C17916AD3A4ADAC5DA504388BFEF875990157",
+ "section_salt": "5588191AB27D12C53FBB0AC6514C35B6"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "4B9221D8B63D26A9711B130E1C0535EE",
+ "data_elements": [
+ {
+ "contents": "ED6EBC",
+ "de_type": 591
+ },
+ {
+ "contents": "1D8DDBD8DF0C950711662DA284BC23FA6C6FDF479636",
+ "de_type": 29
+ },
+ {
+ "contents": "7AD06A9E86A0A2DF",
+ "de_type": 596
+ }
+ ],
+ "encoded_section": "027EF3DDC32AD8B67DEB708CB96FACF7E87C2ED0A5F105F30E74CC01BA5995023B39908CD7C3A28D416AD43B60A822D3A6781CEA5EAD3A26EEE188FEDBCC4B86207D626E3A7C5177E7EBB46D720404463C45A0832B3B146BF9E842",
+ "identity_token": "46470C0BA32542A5ED33D66AE1481EE6",
+ "key_seed": "7397B457C7BACC338D5C6134346FAF2D3164EE0E53FB48C18EAB31257483E83C",
+ "nonce": "BF76260300391F69E456FE0F",
+ "section_mic_hmac_key": "7056AD67950509C88DFEECEBE92D739F5C702C566F1854EE785EAC1509C26815",
+ "section_salt": "7EF3DDC32AD8B67DEB708CB96FACF7E8"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "1E806EFC9EDD141577721BB5E61CA53F",
+ "data_elements": [
+ {
+ "contents": "57A7035EA380C98F071876E21F4CEAEA67E964A732568F5D10AF",
+ "de_type": 518
+ },
+ {
+ "contents": "913B76C6EA7BE3C1FAF1C2E1CD4F929F4F56565BCC1113674C17",
+ "de_type": 898
+ },
+ {
+ "contents": "",
+ "de_type": 415
+ },
+ {
+ "contents": "5D48E33377BFA3527720447FDC7F8DA97DFC44DC4A",
+ "de_type": 588
+ },
+ {
+ "contents": "A3",
+ "de_type": 908
+ }
+ ],
+ "encoded_section": "026567A1F3D63165D9D7A854C9642CE61B9DE8B6E101BE92EC9ED692E04BF86E866946345059A1F4F9C54A625AC3EC77B55C37C774CD11AF71385AFB813F8DFECDB95CA83929CB8309AE5206F125E22E25368DA9580EAAA50F61EAAF37FA6A61D44CA946D3BE28D9E298858E09DF3D50CEF793CA14D94A733C1FE663A8ED047D4718336108C1154EBCE52E",
+ "identity_token": "DE24F284089324DCB3AF76801C2F94B6",
+ "key_seed": "6555B34DD6A332E6F727381BCE1A2B9FBDEC1B5367367BBCFCB5071BCF8178DF",
+ "nonce": "F423CF36EF58853645712DF1",
+ "section_mic_hmac_key": "54C323CCC04E240721D7F77C1205F216D251C79E41FCB3695EAB28C6C5423C40",
+ "section_salt": "6567A1F3D63165D9D7A854C9642CE61B"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "77F61511E7F92A37D2A114DD4CC4889F",
+ "data_elements": [
+ {
+ "contents": "51F97F",
+ "de_type": 22
+ },
+ {
+ "contents": "EB58DF0C96A41AA69329CC97D11242F4A3850D89FA82376C83",
+ "de_type": 110
+ },
+ {
+ "contents": "BDFDCF83C918D94DDE25E6A13E0586CD83EFC76F5C43AE46CFFE",
+ "de_type": 674
+ },
+ {
+ "contents": "F2C0052877838299",
+ "de_type": 273
+ }
+ ],
+ "encoded_section": "0282028A9CDE5CFB8B7B85C55034433DD7A9C6DC3CEEC3F54854F91708D8DAD5B458C396ADD9D43DF02B09513E3E428A0B91BC838C3D10B5D755ACFF0BA217A77117A96C3E2D5849F2861E7DC257A3450D740424901564F7F25EA0E7E239E628C8E22381D9B0FA86896E0A562DDCB26E1E6C4EB2DB7D4559CEA1",
+ "identity_token": "15A7903360B4430A13965FC72FA2B9D2",
+ "key_seed": "E06BFE99B917D1C1B38AB13D3F6A2163AF91507531E86E5F6F32D7116D94AA03",
+ "nonce": "F1728A657AD70C28875CBC1E",
+ "section_mic_hmac_key": "3AEAC66D3852FEB86D7D1FCBEA0A9D6EA47EFE74BF6F2CB6E861BB1ABE8E3657",
+ "section_salt": "82028A9CDE5CFB8B7B85C55034433DD7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "C606686684F622AEC70CAA4F201F2EF3",
+ "data_elements": [
+ {
+ "contents": "4FA0D0",
+ "de_type": 599
+ },
+ {
+ "contents": "B3E804B287672E412D53B1183CEC5D",
+ "de_type": 174
+ },
+ {
+ "contents": "526BD3460157EBE8D364D73C30419689F8E5EA4A47",
+ "de_type": 461
+ },
+ {
+ "contents": "C378C50F",
+ "de_type": 800
+ }
+ ],
+ "encoded_section": "0222C5A6BC119ACEB0EC9EDCA6D57639B767DE04C14B5F0B4DEE8B49E4DE3AC7CD47CDEFFB4ECFDF012DED1CB340D2E3D98D7DE9970BB9F48ADC6998B8A52B1CC674048CB3C58752BAFD16B73DC21D36973DF5F18BA6027AD6060AB0EB78862BA8D7BED26968C3629F",
+ "identity_token": "59BA27AA8A76A50F12A5D2BC8EDA7635",
+ "key_seed": "CC49C0BC358FFB2BF90A62F446709CA6A6FD1CE686EB7D4EB37FF620AB5866E1",
+ "nonce": "D222455382EF2556A27EF3B3",
+ "section_mic_hmac_key": "507CDE4A24AAAD3B43BE6AAAAE73CA5C5F59D011AD220F1272E7FF4D43747F22",
+ "section_salt": "22C5A6BC119ACEB0EC9EDCA6D57639B7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "A33086631E13B0A0226E32EF4D4CCDBD",
+ "data_elements": [],
+ "encoded_section": "0228770D81B47DD0E4F188546B893534900F41411BF870D5E9458D457698D1F74710D4A0F4340600E0E9285E5E6F3351E3CA",
+ "identity_token": "92A3CA4B2F9F59AB64EFBBFE25121C7E",
+ "key_seed": "D6AB21137556AF94989CF92E53261B867163C16147313EC5275B8E1DD5073BE1",
+ "nonce": "59480DC604E5C6AA30BFEF23",
+ "section_mic_hmac_key": "9B12B9904F7ACF8E22828B994212CABE3FC8B85F6121D1E5D47951473A0379DD",
+ "section_salt": "28770D81B47DD0E4F188546B89353490"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "05099C0809FFCE0781D65DB0E2F6B265",
+ "data_elements": [
+ {
+ "contents": "3B",
+ "de_type": 789
+ },
+ {
+ "contents": "2626C80C748B72F0A32FC66788960604A3FAED3070AB9114B8E358106CBC",
+ "de_type": 671
+ },
+ {
+ "contents": "09F36841",
+ "de_type": 406
+ },
+ {
+ "contents": "",
+ "de_type": 145
+ },
+ {
+ "contents": "BCBA4F2899DE",
+ "de_type": 446
+ }
+ ],
+ "encoded_section": "0227A3A0FE2CD4B612A4DD0355C51E1C2D53FA09EAB78824316A73D15FC3238396482A461EEBF605D7B33293B3D196BF25B1667EA66BB514A7F7EF27648FB8048B94FA70B2D4EA36BCD86D913ACA072E6D89CF3F5490550820D362E1A8B395B539B466D74A9592AA8ECE",
+ "identity_token": "C76668A2A2FA840BC9C89353B8540B43",
+ "key_seed": "162E48714870CDB8C0BE54F698A9010FFBC9532C15C8C2DD130D579AB4AE4512",
+ "nonce": "08860371E5C35E5F8B076FB5",
+ "section_mic_hmac_key": "DF7611BF559EA9C2D8A0A5E7032D4813971952E0A8701C4F55652939CA1A47BF",
+ "section_salt": "27A3A0FE2CD4B612A4DD0355C51E1C2D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B5B046CFE2E170E4E29529FC53380945",
+ "data_elements": [],
+ "encoded_section": "0209539A273A8888A0158CB6D08FE4CC1C0839E0605B3EAC31AC2855629A66D6F2106532ECC714BF797E4A08D85E49AE31DC",
+ "identity_token": "A9BF53E9D87F9E63328C211778CEB74B",
+ "key_seed": "AEF3279A8EEC857AB241D4B6678BAC2CC4EAA9CABF2A4C229E9FE17C44D725E8",
+ "nonce": "025E4CF04B1E5B5A77BFCA51",
+ "section_mic_hmac_key": "967C2FBC5F186228F868E5BEA0482273B1686A3411687FE6123FA533BB4D7FC4",
+ "section_salt": "09539A273A8888A0158CB6D08FE4CC1C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "5126EA9102AD6B5ED537A4D06C62A735",
+ "data_elements": [],
+ "encoded_section": "02FA35178CEF220907A4C1C1EF1AB507C7D294D3B20708B7D18524BF185DA511A510052AA4B0C8474901B9B7E8D7B64AC9E7",
+ "identity_token": "027C381EF363ED32EA4CECA28DAD7FA8",
+ "key_seed": "6C43637A9F73217C7EC4D4754A0B292230B96368E7D4A70FD3C42B3F42E11685",
+ "nonce": "3A6CD0CDD1DF482C7A7B44D7",
+ "section_mic_hmac_key": "E2F8A00B2F7AC93D7BA123A5855124052A4077FE7CC331DB260AB2D284A87E1A",
+ "section_salt": "FA35178CEF220907A4C1C1EF1AB507C7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "6451E8C836D286C2C658118FF5E0F808",
+ "data_elements": [
+ {
+ "contents": "7E07F945516A13D0910FBBB4C05258A4B21405268DF1DD3DA8EF",
+ "de_type": 175
+ },
+ {
+ "contents": "86D01ACD89762B2F",
+ "de_type": 691
+ },
+ {
+ "contents": "A0151F3798A7E3E871",
+ "de_type": 81
+ }
+ ],
+ "encoded_section": "0278DBC03386503100B99EEDFDAA3A54AA59606C74808EA12DF14116C0AAF2551143D8F46AFA3CDFE853CDB017AAA6AFDACBD1B5FD0088A709C4B9F007DD53269BBF736DFF095E0C7AD6087B9B8947B5F6D22C5ABC75278BAF2ABDD8D326B3D07C96C370F1",
+ "identity_token": "5A1729E7B2B2193C67112CD8DEC59637",
+ "key_seed": "82158E1C98CAE04C9FF662087015A804F181B25565FC29BB0CCEB32AD29AF8A6",
+ "nonce": "1C4B30EFE7A7EE25837487DD",
+ "section_mic_hmac_key": "3A3FEBA1F8EC810C8ADA1EB14859C5CC3B1A391B0ABEF72BAB65DC1EF1AD7E43",
+ "section_salt": "78DBC03386503100B99EEDFDAA3A54AA"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "37CED522A58075CD5910D4AD5C755AFF",
+ "data_elements": [],
+ "encoded_section": "029134AAA791A8F2F363752DE40D98CAD079A38F6AA2E33B1F368213CA503B1EBF108276BDB43AEFB7AF93C1B94EBC08EAF1",
+ "identity_token": "542BC2A7B465A7069300EA500112834B",
+ "key_seed": "B6DE0DBCA9A2C1290749B479AEBFF54549CC733CA19439E66A8EC38A81AEEFA1",
+ "nonce": "D8FB3E5CBEECB405135DE22B",
+ "section_mic_hmac_key": "311EE9A96B22421A80A8813DBD29ED80FE7AC3212A64988033105047A72A90E6",
+ "section_salt": "9134AAA791A8F2F363752DE40D98CAD0"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "D03161023435EBFCAF2F2D0ADAE25EFC",
+ "data_elements": [
+ {
+ "contents": "28",
+ "de_type": 471
+ },
+ {
+ "contents": "6536FA2872CDAF623C96BCEFF2471CB4E036039A4BE890ACB57FB1EA68",
+ "de_type": 72
+ },
+ {
+ "contents": "3F9D7E766C0879AE49D791",
+ "de_type": 118
+ },
+ {
+ "contents": "1D4CDFC938C8BE1CEE8BC23DA0D65E51121C1CE238E37259EE389D12",
+ "de_type": 778
+ }
+ ],
+ "encoded_section": "02A17062B53D66D4533A53A453F2485BE62F35088593326E7742857102AD4D29E45FD71D6D2423810C4B94EE6C28BCB8D171D49564294B141921978D180CA20F1798397775BF0E1F4182C915E186E768837E8E7779611BF91FD12C2E9E8608BE33C4AA6E7664C477D7186E03151F5692C1D61E246BE67263333765EF7573769AAF",
+ "identity_token": "DBB90C1A48327EF7A00F4B43D68A1F81",
+ "key_seed": "92750637170C948A4C8F8DBEC0C99DFA3B3F62D666E78860A0E66090E9EEAF46",
+ "nonce": "90059268A0BAAB4B5C27102D",
+ "section_mic_hmac_key": "D894D0DBC6434DC2E305B9DBAE11164339617951C9503578183E2243A89A0A62",
+ "section_salt": "A17062B53D66D4533A53A453F2485BE6"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "4709FE87DD6401199C69B10B42568335",
+ "data_elements": [
+ {
+ "contents": "1C2BBEA2EB6A22D4",
+ "de_type": 213
+ },
+ {
+ "contents": "5734FB78B9DB664F434594B0DE",
+ "de_type": 745
+ }
+ ],
+ "encoded_section": "02C9525C2999AA4C2313D3A88E0DD65385C468B7D341E9C2DA03D43E31514EAE512BB2AD526CF2AE44A758B4DEF16471C615F34A79E7CB8E4294BD91EA791BDA401DD3F4A6BA80EF87187D037E",
+ "identity_token": "67B6209E52C3003631906D5B6F8F99E2",
+ "key_seed": "E8BBEFAA58A804851A6A5FEEF442A5B42E1790D624E171D82666F37D98F479AD",
+ "nonce": "13ACC6C2DEB7C80286605695",
+ "section_mic_hmac_key": "2C5777BA0FC851E2168A7F6A065542A454A00FDBC37796DD2C0F61B8F0F479DB",
+ "section_salt": "C9525C2999AA4C2313D3A88E0DD65385"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "50D0D6451249827DFEC86AD5CABA7541",
+ "data_elements": [
+ {
+ "contents": "A2365C5B",
+ "de_type": 232
+ }
+ ],
+ "encoded_section": "02CCC6C1F682DC2B26C2F0EBD88DF8CD10B46827F6998B5BCD033810162169C9E6177E21F144FBF887F2D62C9384E5C67E9C293E808D79710B",
+ "identity_token": "84A064CB500C36450216D83A3893987A",
+ "key_seed": "BD2E624D9CFE4D8BFFD5F64E71D91E7E6C355207AAC713DCD27E762E43F93778",
+ "nonce": "2CD2585EC8A6FFB46BDD67B7",
+ "section_mic_hmac_key": "CBA836A7141228C2F80DD3CBA933639E4901D26EA5D596DF73749070389E72FE",
+ "section_salt": "CCC6C1F682DC2B26C2F0EBD88DF8CD10"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "353C59AD9C7303309F3F25D3DA7D5623",
+ "data_elements": [
+ {
+ "contents": "8E8E775CF15104DA9C2F070D9778",
+ "de_type": 22
+ },
+ {
+ "contents": "C05C83A5",
+ "de_type": 492
+ }
+ ],
+ "encoded_section": "02E13EE1C144ACAAC46546A7FC73BC517AEC2793AF4C8289C1179DB702134B875F279099ADA5B9F9D20CF79506163A1BB5B7CB158AB8FEB2D5BED7A9DC2737819FB7B5DC2475404D58",
+ "identity_token": "8206FA4E58FBB7DB6CCDC6A8E17D215A",
+ "key_seed": "9BBCA7052AAB7FFE1E37DCE21853BDC901CA146141C567A77E042D1DB8E7677C",
+ "nonce": "60FE311C1DE98B1F0CB8F645",
+ "section_mic_hmac_key": "9AF2DB9C6C964A6B120625992CBFE9810428FB44F41EA85EE8C98FAF048B45C3",
+ "section_salt": "E13EE1C144ACAAC46546A7FC73BC517A"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "63DBF59EA2D3FAD77153DB5412A0468B",
+ "data_elements": [
+ {
+ "contents": "4657BDF649917C3279B8D5E6D8107DF5FE",
+ "de_type": 698
+ }
+ ],
+ "encoded_section": "025368A3DEB0ABAFA3684502DBF3F2D2F1A4919DA6DFA241CA937D946397B2FAD624E77A62AC2FC3FFEACDED692D3C146025FD5E9A540D93A6BB85443C5958087A248897A165",
+ "identity_token": "2F46468244F32581D94A0E134A269C27",
+ "key_seed": "8C34898BE3791991680388FDAE3F11539734BD838C00F4D721D886031B1CD8D1",
+ "nonce": "158DA837D312152F80C64662",
+ "section_mic_hmac_key": "62BCFEF7FABECF3EF0B822A4970BF3444DB880A02805943EB055FE7E3E5BBFF7",
+ "section_salt": "5368A3DEB0ABAFA3684502DBF3F2D2F1"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "6FF3996ADE933F9445D5D9B3BA72ECED",
+ "data_elements": [],
+ "encoded_section": "02DFD2A8ACFCB1979E11868B2EB2A148861E7D3C74802325EA20998C2CF3013BA51070A82DE70003EBD48675EFDA6C8A1040",
+ "identity_token": "573B7D3AF2FD3EDDDA487D8254537EAC",
+ "key_seed": "45B309037CCE98B8DADF3DF7818D3A3B842E292E9F8C54E82F10C4B91EE601DA",
+ "nonce": "9FFEC13ECBB99430B280A426",
+ "section_mic_hmac_key": "4C699D0E312750AA09EFCA9A4C8C4E7E032BC4D5398A6F72F4FB6AFD22D64110",
+ "section_salt": "DFD2A8ACFCB1979E11868B2EB2A14886"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "95D640F8FEEF0F476D173FB35C70E3A8",
+ "data_elements": [
+ {
+ "contents": "0E32AADB46",
+ "de_type": 405
+ },
+ {
+ "contents": "DD700C351B",
+ "de_type": 316
+ },
+ {
+ "contents": "C58F70E4A3F3EDBD5E8E2F0A",
+ "de_type": 651
+ }
+ ],
+ "encoded_section": "029855CCB82C1B5CB8DBD66839B011C07894F5F607E6B8C7FE9C8841A25BB06AD92F451F1DAD781A11061A62ADB2B7F8E951759290C76BCF3497C6323C597BFDB3DB01BDE012660251994A30CEB69F3E76",
+ "identity_token": "4D475A274742151475B341C48194D9F5",
+ "key_seed": "4DCF489FA193E73A86A4EB4C3268CEE5B950A1957C0CA006F3422A15A11DD205",
+ "nonce": "1BC76946373179415F596851",
+ "section_mic_hmac_key": "3381BD66395B21BCFD1C73E775C967784C3F3DE77F2FC1EBE5D2CF5EEACB91C3",
+ "section_salt": "9855CCB82C1B5CB8DBD66839B011C078"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "31B7CC1805DAD1ED55DFCBA3ABD6C01A",
+ "data_elements": [
+ {
+ "contents": "D5D8A14C3B06",
+ "de_type": 534
+ },
+ {
+ "contents": "4D974CBC01B6728564EB30C3C780500EC117E0B2667EC576E10D7DF5",
+ "de_type": 364
+ },
+ {
+ "contents": "79CC9D9954D0C77577859D94D862FA",
+ "de_type": 131
+ },
+ {
+ "contents": "F1A1CA7D01BCF394",
+ "de_type": 115
+ }
+ ],
+ "encoded_section": "0220E344A3BD5D875DA30DF57C04B32022F56AE8CF9A5F02F774BD2483829674CA544027FC5D3CDE71FD19D2AE4861CB74ADE4484C3F758870EB49C211D07B2A0B1DBCAB684203713EC5ADC830B6FB75C927813EFC51BAFED6ECDF8322B679FB9190DAD7AA7915BDE58E399FE58066EBAB338B8F1AE1",
+ "identity_token": "4AC470B5857B8F029D2F8E4B634765F2",
+ "key_seed": "41F01CFE759E12F979BB0A6B23DBF53D408761D4F667CAB71042C9789588CC44",
+ "nonce": "8BACC88ED412BB6E927D153B",
+ "section_mic_hmac_key": "E7B1D619DF9082D0A9328111D0D72FD515B276BA4954B697B942363DBD12120D",
+ "section_salt": "20E344A3BD5D875DA30DF57C04B32022"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "D75007BB49FEF17E0CF767B19412BA83",
+ "data_elements": [
+ {
+ "contents": "483FF7B534C3DC8427",
+ "de_type": 702
+ },
+ {
+ "contents": "",
+ "de_type": 310
+ },
+ {
+ "contents": "02826430E4AD154BAD4FC491CFFEC8",
+ "de_type": 638
+ }
+ ],
+ "encoded_section": "026B334E9E52C272A60F1CD9AB613752273F973DF5218C53E2B5FC7487309A978F31870C486D424DF9B79D0D68C6594ACC1E30F8F4D7F3FC7E559FDBEFF1B88A849FB996E466D2F725D8C76BFC705F34227E67",
+ "identity_token": "60040508990303A048FACF72038CE464",
+ "key_seed": "98DF428BC184564FB1DCA947106B8F89CBB668C74A9CB48C0721430BD2047A1A",
+ "nonce": "C4CC65DCE3FA0CC241D9AA35",
+ "section_mic_hmac_key": "49AB3D69719CCE05B5A246DCF61AAB29376178213347CA7F318F9661A21CC63E",
+ "section_salt": "6B334E9E52C272A60F1CD9AB61375227"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "FAA4F8C869F0F4469CFA8B98E0B84786",
+ "data_elements": [
+ {
+ "contents": "9C3CFD4796001FFA0F0B1A17C2DDD4971945CF1581",
+ "de_type": 900
+ }
+ ],
+ "encoded_section": "027EA134E36AA6249D20357948A07A39430106C70B56C2DDD6649EA769968F03AE283A99A8441AC04033B08878A90E7684242045AC3A191170C5ACBB55B2218679CF770A384C7FB67E06",
+ "identity_token": "7FCFA0BC8F7C8C85EF59ADB9D250F8F5",
+ "key_seed": "7032B5E67A8BEF82845ADF25B6152283D544435CDCABFCA0750BCB81A84934A8",
+ "nonce": "018137DF8171014B5AA4F794",
+ "section_mic_hmac_key": "F2571523E2DC1E97A4A1D95D74967F22268C47733385C3241FAB1653A1F61BCA",
+ "section_salt": "7EA134E36AA6249D20357948A07A3943"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "135CFF48972D3892BD5236733CBDE72F",
+ "data_elements": [
+ {
+ "contents": "13E83591B1805E6EF828EBAB8189A0F7F47E65F6EA9B8EDD",
+ "de_type": 325
+ },
+ {
+ "contents": "8582F902174439B061C45305",
+ "de_type": 514
+ },
+ {
+ "contents": "ADF4960FABA6559565B659F87C13DD9C0838CCF7881CDC",
+ "de_type": 133
+ },
+ {
+ "contents": "F4884DC85E0B24372426BC917E7824B9CCC6C682619428170A2EF989CF",
+ "de_type": 863
+ }
+ ],
+ "encoded_section": "029EE7BC1BBBE9DABEF0A56E7E11D1A11D432AFF55DAB52B42407E950ECD6FB8D174564E551C9E68F5C5F229808F63E587225B49D682D481A708DBDCF8DC53D55AEB7250AF51464C4C8EDF689933DD8414BAD3BFA8C633B7914A67A55D90598A8070EC256500F60B92F22B2E0A08749AD01AD7AAFEEC9C547993E7D8F5495E1D9B0CA185F41DAE0F48E4E953530CF8A8EF77A80CDC11",
+ "identity_token": "24DB26605841C2C1F2FF4EAFA8C9A3B6",
+ "key_seed": "B80CEE8A5289B0E88AEE0FD08789C7D762F4DFF8D0FC5D79CC9332F24F7AB889",
+ "nonce": "20979F413869AE8D0069CEA6",
+ "section_mic_hmac_key": "F57425B28C88DD3C938D7C7F9E2E2DEDE7883C21116B6C2AECD9659F508172EB",
+ "section_salt": "9EE7BC1BBBE9DABEF0A56E7E11D1A11D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "DDC14ABAE3E57A2E436D2B154CA341E2",
+ "data_elements": [
+ {
+ "contents": "0100CA9F13A748A7769E5DD2239A",
+ "de_type": 465
+ }
+ ],
+ "encoded_section": "02AD0144308355660F11BC1522BB4040343B6EE18AFFEF9B71D3239005448AD9FA2193AA48A6A9D558FCC66E02BD74A9A83891166A550882FDB1654D80C853A5F40E40",
+ "identity_token": "70AE495464B5C777F3B7533287CABFA0",
+ "key_seed": "703D9283FAFFA27816DFE81AB6FC0C86F70F9EE2A59F9AE9FA675BB94F4AFAF2",
+ "nonce": "F29395253E56ED38E3AEE6C7",
+ "section_mic_hmac_key": "62107DA82458F0FF6C1F510024186527BEC70BEB8E9E2BC63618656F1F10E27E",
+ "section_salt": "AD0144308355660F11BC1522BB404034"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "744AC27B83E2766619EC0FA0A3B7145F",
+ "data_elements": [
+ {
+ "contents": "8809E7D36FF481A81F7CFD46325C0E4999977FF41E8D9E6D",
+ "de_type": 326
+ },
+ {
+ "contents": "662C4AAB4A9065207E",
+ "de_type": 794
+ },
+ {
+ "contents": "7B302C10AB20F7E646A1DF783ABFDD4A568C9C1C17E26F8A",
+ "de_type": 111
+ }
+ ],
+ "encoded_section": "02CB4B333C50936FA751BFD0BF7F69C50DFC0358422A96FC26DC3450BAF84BB28751B73C86769524A89061A0178DAF1B8BA70B97DA597B7B4536312CD3FE3302EEC5659948F0310B6A04EA623628523BA417256D89531912AB7E5F5DF54EF46DD764CF9B7E10303A4CD3CE36A96E5F46139A98",
+ "identity_token": "A8ED77B3381D625297D75804FE02F5F1",
+ "key_seed": "94DA586A9221F4376146845409E3CD6C6464BD5313D34E2E6AAC864BE7088C20",
+ "nonce": "54278CC24894F36FD3FA5AF6",
+ "section_mic_hmac_key": "FACFF42071ECFC827096DCC9464F0FD7EE42772DE4D3CB9E33AE208A206D8145",
+ "section_salt": "CB4B333C50936FA751BFD0BF7F69C50D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "8382239DC9F8AD351C6691B8765751A8",
+ "data_elements": [
+ {
+ "contents": "731A9182CFCDCB4B5AFDC795BB7D773039",
+ "de_type": 672
+ },
+ {
+ "contents": "AB559ED81984D1E11D3D77C65B1B068E",
+ "de_type": 34
+ },
+ {
+ "contents": "EC20C11534",
+ "de_type": 182
+ }
+ ],
+ "encoded_section": "02574DD074E3030F3C440118AF057A6E81DE77D7C6A81CB708D46329C685DBF63A3E49CB49CE48208A0BC9BE897C615383859784266BEABD8739CFCEB412B7D160A078FC7DC9717CD450C0EC5CFE6FF9078EE887CF798B061A8DC8A0A4B81FA7",
+ "identity_token": "A23C1EC6DA331C8BFCC59AD45299A8AD",
+ "key_seed": "3FFFE6BC8E09AEC10917636F693B7B623B83B0F60CD0A53B6E671AFA06BA71D7",
+ "nonce": "603365E941059E1DBA63216A",
+ "section_mic_hmac_key": "0600965BADD5FE7A27707EC8DD96E50F8565A262FA2F006E9C34C32FAA442F21",
+ "section_salt": "574DD074E3030F3C440118AF057A6E81"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "0B146273164E3535D882394B7D8E8A10",
+ "data_elements": [
+ {
+ "contents": "A6",
+ "de_type": 435
+ },
+ {
+ "contents": "FCD83E31FC",
+ "de_type": 117
+ }
+ ],
+ "encoded_section": "02DFD3246C71A4A97E4B1BA9D4F7AC34AACDAA84C85C205A6730B0C34D1925BB3D1BED7A91D44420270CFAD5FF0D68D5A081A74B5E6A9F825DAA528DD0",
+ "identity_token": "F188D1E3D8D9C0272F29936D3AA2C4C0",
+ "key_seed": "0454EA82B20D1CB3895AA549F07794CE16A417EBEA2D45CC3D7CEE88840D1DEE",
+ "nonce": "4A37E74B7919321224347C0F",
+ "section_mic_hmac_key": "89FB1E3BB8673A6A39207460CC3EFB7BFEA89A274547F2C1DCD105AF454A48F7",
+ "section_salt": "DFD3246C71A4A97E4B1BA9D4F7AC34AA"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "A6C5055276D8481CEF2ECCCD19DC6D86",
+ "data_elements": [
+ {
+ "contents": "E8C34AE045BECA84AFDF145AB2C11534C16FB5",
+ "de_type": 260
+ },
+ {
+ "contents": "87E8D027D88BDD326D08D4B0",
+ "de_type": 547
+ },
+ {
+ "contents": "A74A12CFF895DE4FD969A2BFEE920D3A131220",
+ "de_type": 954
+ },
+ {
+ "contents": "C02CB796EE5010050633D340C8",
+ "de_type": 784
+ },
+ {
+ "contents": "32EF1931690553C3B4AEDD035D12FB776F93BF91",
+ "de_type": 742
+ }
+ ],
+ "encoded_section": "02A0318DC4C04450120D114911CB0F21DA6895C9D7D2B7AF43E57F6DF8A5B85F297250D4B38EE384132B5026A691A5A848C1284550348231A6A97CF8D47CA5F1F71AC81B984264A05F794327D9C50A9F72A5A102CD566D023DFF1C4E116C82B83BBC8A0884611E37C6CD8581360318DE18DC880E2B00048F9C4308A81975B0B73F0A255F229D267F19CEDE7329D8180F71978672",
+ "identity_token": "E0D703959CE67BF41B6976FD455FCE5B",
+ "key_seed": "CB83F57DBD5CE9CA5F898CB4F5556A090479FD88C20F7EE18D632FAF178323A4",
+ "nonce": "380124B5FF2BF739EE781770",
+ "section_mic_hmac_key": "B044296E5AD11AE978E19E56856D6829769C3F38E488A3D741E9AA632BB32FF7",
+ "section_salt": "A0318DC4C04450120D114911CB0F21DA"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "690CA5CE0AC60ADF00AE579BDB164319",
+ "data_elements": [
+ {
+ "contents": "284488",
+ "de_type": 778
+ },
+ {
+ "contents": "2F9112B4015F302DD3068CB5C06236ACB4ED1ED9908BFD8859485E",
+ "de_type": 824
+ }
+ ],
+ "encoded_section": "0230ECD327F2101FD57C67F868BFE5591A9EA0510A3A1918D42719B7D937FC25EB347643A382CB1EEF1BE0D45278B0EF49241FD4AA53333E9B20D7DF545644C794C0C313FC9C2D22968DADB4406A9E092999EBFB7F92",
+ "identity_token": "35AB8A4472A635C5EC6458F32686DBEB",
+ "key_seed": "99637210F99F390A997F576C706F9BC7C8581692E1285E29D1BCDE117CC0B428",
+ "nonce": "10CCB0A8DE6C3AFC5E747D1C",
+ "section_mic_hmac_key": "57447E9E35E7BF08280D4F92360E0141A766AA4CE818AAA45752563253DBD173",
+ "section_salt": "30ECD327F2101FD57C67F868BFE5591A"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "73D9602DDB93D7699C8C046E0B9E602C",
+ "data_elements": [],
+ "encoded_section": "02D74F68B471771AD2A4F8559305EC53902AEAF1CBF3D8C11992C5DE18AC41601310DD15D84C0CB36514110875BA8151D0EF",
+ "identity_token": "00EE8F5898673EFCC8D7D593ACA886C2",
+ "key_seed": "6BCC9CE0FCED7111026D0ABAC01E65F4149D37F617683A58960B8F4AB3DA64B9",
+ "nonce": "14B891CE7E628E756A830231",
+ "section_mic_hmac_key": "8A469C665BB030DFA05EBAEDEFCBA98BB35C9B9EBE41B1692B2D74ACB0973D58",
+ "section_salt": "D74F68B471771AD2A4F8559305EC5390"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "116268F2138D48B7377D1F9B993F112F",
+ "data_elements": [
+ {
+ "contents": "142941",
+ "de_type": 384
+ },
+ {
+ "contents": "4E6B16DA0CD13D6EC21E797862C3AFDD25BE",
+ "de_type": 254
+ },
+ {
+ "contents": "B77B7519377B061318D90278B71FBA82C604D2DB5C69",
+ "de_type": 570
+ }
+ ],
+ "encoded_section": "02BE0BB3EBC88AD859D7B875008C0931365F394AB17B39FB727A93193C4FEAC4E844DF2573378CFFA4B15B0D082B3D59EAB8373E20E17079FE768CA1A2479D57E002BC914D4BC807673ACD10F31FF5F6A39183669EC4B8F593E6E086C4456A3A872F3F401844",
+ "identity_token": "BEC77D2328CC57D22E0258715D0841E9",
+ "key_seed": "70FF80E5D4D65D6C8E4C68082D75ACD7B1EA9FD3C0F4AA154D4086D2D20D0A8D",
+ "nonce": "DC2D9C34D25C7E6D95B384F6",
+ "section_mic_hmac_key": "2FEE78E42D658EAE17656D3815534D07B399660A2030795ADEF7FFF532321509",
+ "section_salt": "BE0BB3EBC88AD859D7B875008C093136"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "52E5153F816929E66AB35A982F597400",
+ "data_elements": [
+ {
+ "contents": "DF09806C22CEE77C4C664EFEE3288301768D",
+ "de_type": 589
+ }
+ ],
+ "encoded_section": "0263497BB609ACDC19D570B16320321281AF7072F3BB15F889145ED8A9AE6E9F6A25CC28D879CFDE5740FA13C8E044D88BB6CA7A7DD16174A3ED805757529717CB260449D92B67",
+ "identity_token": "855F0220CB5E718D26321D4D7C7577C7",
+ "key_seed": "A1F0ABA90F81ED6943F95065A29589446498EC2F79520A56108539E3C30A19D4",
+ "nonce": "39A3380C10BB5CF8E9435BAA",
+ "section_mic_hmac_key": "6B654DBCC294323566E00D2A8C486A6F1ECB91FF949FA640B93D3B152F047230",
+ "section_salt": "63497BB609ACDC19D570B16320321281"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B6E9D40607D8C39ECF7625E686CEF325",
+ "data_elements": [
+ {
+ "contents": "2B2948F09099",
+ "de_type": 544
+ },
+ {
+ "contents": "E551587B",
+ "de_type": 375
+ },
+ {
+ "contents": "4E6F0748C486",
+ "de_type": 37
+ }
+ ],
+ "encoded_section": "0205FA3C47404A35D4FD5BF0F547164C81B299006BA6CBEFBD4E0E4A450CFFA1382856C3C42CDA3A189D6FA37FFE8CA32EA8548FE61DEFAC42D1532D3865A41D6F71DB37B9C1DB88B1A3",
+ "identity_token": "72A30E0B2EF76A0265690E2564D197F3",
+ "key_seed": "13F03C6648844D00F21EA2CF23AC0B8284D36465438DE45C81A59775BA116FCE",
+ "nonce": "499227762DE0BC7B33BC7153",
+ "section_mic_hmac_key": "8714D596BE3472DF951E6861CA718DF4C391976F932EEEF3F8B48F78C2AF7C40",
+ "section_salt": "05FA3C47404A35D4FD5BF0F547164C81"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "2293B6380F70640ABA8871ED56932E20",
+ "data_elements": [
+ {
+ "contents": "0479AB07E83192319E104D967353472F1DC0F863CCCCE0BB99",
+ "de_type": 258
+ },
+ {
+ "contents": "A0AC8E8D1A916AA5AB9E021CF32A85288F238809CBAE59AE8A71",
+ "de_type": 672
+ },
+ {
+ "contents": "",
+ "de_type": 27
+ }
+ ],
+ "encoded_section": "0294E4D54F244E47A822FF413F6BC376B2B6162B1A181C00187B1ABDB43612153D4B8EA58CD0CFC7314AE91A06A4E35027FEB5EB8C9D93AB2872B2A3B561EDFD98F3A937890D95B5994729C4D04DB85258644B6E92E15E87C21CC5D567A005CF496490988A3AE18BAD1F233DE0",
+ "identity_token": "3AA3E8B81C9B7D2D22CFD1E3FD7EA5D5",
+ "key_seed": "DBC016C10B947661DE37B57C0C33FFBA01B89FD64B9417DC635D9D19C44511A3",
+ "nonce": "3F5472259721D69E0511C6F1",
+ "section_mic_hmac_key": "1097F2D8149337A3927ECD7E4E0534AE66E7CECBA50D8C8699E2747AAEEB82DB",
+ "section_salt": "94E4D54F244E47A822FF413F6BC376B2"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "BCAD6FBC54D804FB305B651664B5EEED",
+ "data_elements": [
+ {
+ "contents": "98758452",
+ "de_type": 78
+ },
+ {
+ "contents": "816C9AADF492",
+ "de_type": 123
+ },
+ {
+ "contents": "C5AC",
+ "de_type": 539
+ },
+ {
+ "contents": "98C2695950C4B5C2F3C69D91B019D5045198846A088508158C4835",
+ "de_type": 929
+ },
+ {
+ "contents": "22C4B157B2334471749AB6",
+ "de_type": 320
+ }
+ ],
+ "encoded_section": "028C8FFACE6BCDFE650833331F10BFDFB7B4E3B071CA7AC5CC1A3BAE79685825EA4FFA30EA2417529BFF840848F99C6A8243648D1F8244457FCA1F808E370B94D2F04BF78B7E51C23752D922268EB1443C0B08D3D2CEE883673ECE7AE5DD5EC5E99360901AFD815B2413BB071A62FF2960",
+ "identity_token": "A1D0AB03665B36F07643E7DEACE86D57",
+ "key_seed": "40A14BB11063D05593EB466ACA4C4DF438FFE2FDA5D874A4E5B3B4E79A6DC65B",
+ "nonce": "484B3BAE18B85C1027094E93",
+ "section_mic_hmac_key": "CE4B87F04EBF02FF12744FCAD9753239514C6E0856D6C2C6CA768315385A98FC",
+ "section_salt": "8C8FFACE6BCDFE650833331F10BFDFB7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B5CBEC978876F51A7BB1396D7A1A5796",
+ "data_elements": [
+ {
+ "contents": "E55EF6F4749B6ED7F1E3254ED7",
+ "de_type": 427
+ },
+ {
+ "contents": "6B1F8A",
+ "de_type": 586
+ }
+ ],
+ "encoded_section": "022FCDCA777563F84DDE7D907A02D77407964B19DF4F96C67E2F5E3078AD2D094326EC3BA4DD06CBF9CD27A0996D83942964893D079B8CA07E07B72D80482F25156C66BC22D60047",
+ "identity_token": "A1D64E8B5EF18E775F30C87C7F41937F",
+ "key_seed": "CF5EA21DD3F05F95A8A1658B4904E63F7ECBBDF860F1D27B88E4B418E914D87F",
+ "nonce": "C8C9C5FCF402ADFC23600F63",
+ "section_mic_hmac_key": "9768775B2D00E70743DB112CFA2E4DB37DB7D9D469E594D364EE254533F2714E",
+ "section_salt": "2FCDCA777563F84DDE7D907A02D77407"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "841D9C330BD88576BB9159CFD67F912E",
+ "data_elements": [
+ {
+ "contents": "815DBB833846588103164057A0156ADDC531E401D585BD5368B419",
+ "de_type": 864
+ },
+ {
+ "contents": "2FA2A37BC6594C3B4A29A2BA077AB8F324F1C743354C2A1B97",
+ "de_type": 71
+ },
+ {
+ "contents": "E91DCCA08179D3",
+ "de_type": 873
+ }
+ ],
+ "encoded_section": "02F49C8B85636DBD028678AA984B5A0F2643DBF77E8FC339E837757F1FE34403F353E16488648B5914A8EB8045BEC91AE34344DE4B90445DB2730AC1FADA1635D2DB87068BBA5ED44F6EEA57EAE2CA5B15BD5FDDBDC1C71C1AF39E58E2E2DDFD721C6E7B4CBBA4918FCC33688EC2119A6402854F69",
+ "identity_token": "27A1DED5C2E9533BF3F99698E1E525BC",
+ "key_seed": "6B7032582260EC0DA57AA5AD575BEFEC7D28696DC6035472F5745873DCB3B840",
+ "nonce": "6B048702497ECD3CADA72B3B",
+ "section_mic_hmac_key": "80747614953138AF6109362B19BD2C97FB7F8A224C908CA870258F1CFD5D6196",
+ "section_salt": "F49C8B85636DBD028678AA984B5A0F26"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "56CD7B921FCE0DC253137ACBEF4C9E7F",
+ "data_elements": [
+ {
+ "contents": "8E2BA03625D8EB749839CA099D48DE15C7887A93",
+ "de_type": 194
+ }
+ ],
+ "encoded_section": "02999AD00461B54D36BA7FC221F7F10D1239480EA7C91F1C200AC73639F608F5022706B4E495786CEDD18D582218A20C83534889C7026B633769D626E2BF60E33069B91D50A8CB1CEF",
+ "identity_token": "158D50035DE9F0289B63225B57629D58",
+ "key_seed": "CF8C5DDD57F9E7399E46F52E06906C39D6155AAB1BA940EDC3068F3642B0F3CA",
+ "nonce": "7E6FEF58E278A361FA3F77BA",
+ "section_mic_hmac_key": "561D62F4B1EC440C5A8C9511A0981C6A14F1A30EE5D156AC2460A25D9F2A095D",
+ "section_salt": "999AD00461B54D36BA7FC221F7F10D12"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "99305ED53E510A6A5620AF58B298A200",
+ "data_elements": [
+ {
+ "contents": "BAE0D38B",
+ "de_type": 354
+ },
+ {
+ "contents": "CEC61AB08C2D8EF32C869D2FE2",
+ "de_type": 67
+ },
+ {
+ "contents": "0EF4293C",
+ "de_type": 947
+ }
+ ],
+ "encoded_section": "02E368EE79CEE4FF33EA1BCF4950B8A8799DFA666B5562CA808D1919E6F24C5A3C2DB36770DB9C7514738035B233AB2025C66D50FA57008D76346564BD8D3BEDA68A676153B3638C47AE4ED7043A6F",
+ "identity_token": "9105B80384B6610035BC153B06A07D90",
+ "key_seed": "D72E99D75674D6C2F4E8EED8D64568DABC14FA7C55BF6F7E0B04302142474AF1",
+ "nonce": "61E591B344D506E266FEB0E2",
+ "section_mic_hmac_key": "501159272ABDB1D1BA4BE9311D77AC0559D63152DA5BD34A2820DA15A82AD037",
+ "section_salt": "E368EE79CEE4FF33EA1BCF4950B8A879"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "F9C9733A407F95BC056EA093672AAC62",
+ "data_elements": [
+ {
+ "contents": "39A6851F0D7562A8D67C87847D",
+ "de_type": 33
+ },
+ {
+ "contents": "C7",
+ "de_type": 159
+ },
+ {
+ "contents": "C94372A46C75",
+ "de_type": 471
+ },
+ {
+ "contents": "E212FDD45F7031CCF2F0",
+ "de_type": 609
+ },
+ {
+ "contents": "60A513C6D691D578B1B8E0D8678C4C93417CCC8772A98A744EC6C3",
+ "de_type": 305
+ }
+ ],
+ "encoded_section": "0239448EC52D1360B39AAF3D8D2ECBE21C8903D1847E324F6AA5575C8EE28D8E4157ADCE19A5988809B2C3396F2F55B8B1A6D7C14B509EAD06129426C91C94D7387DD790EF5EACA005EABAEAFF8D0E4E1A2286A3EBD393A0B0E2A0C73F900B32D82F28F3CF8441414116BC415BF3D652DC1F6ADCBCE89D5A5E",
+ "identity_token": "EB2E94C1013BBCE935289A687EE855F4",
+ "key_seed": "CF638C9E9ADEED53473692F67FB230EFCA033A90FB31FE01640296AD33198E24",
+ "nonce": "8A1421B5D302EABCB4E9AFDE",
+ "section_mic_hmac_key": "C0F1CC05E31EDC758059D4FA1C6A539059A63E86ED3A81EFE5B49ED6504BC816",
+ "section_salt": "39448EC52D1360B39AAF3D8D2ECBE21C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "AA35088237F8B48B7B9783E54DCC7310",
+ "data_elements": [
+ {
+ "contents": "C54293E528BF5A6D1C5299",
+ "de_type": 119
+ },
+ {
+ "contents": "B8F16ECD",
+ "de_type": 266
+ },
+ {
+ "contents": "C025E0",
+ "de_type": 749
+ },
+ {
+ "contents": "B668775936872A95200E2A1A544742E4B5DA218E66",
+ "de_type": 581
+ }
+ ],
+ "encoded_section": "02605100404180967E0C35A27B303198AA0777DBC954ECAEC74857B598034CF02642E7BE5C315CFD1DCD1AB6164D1AC72EE44713D4332D0ACD1C0A588BB4DED8FBD841CC2D6EC37D6FF4DC1D9E3E1DBFFE520C351C868F4DACD799112FBE876903BD4DB4",
+ "identity_token": "681670B22B7549584CC281C7E9C7BDC1",
+ "key_seed": "5B8298AAA972242D14166249DAB29D642898C1EDBF4AEE35E5A28A523D79EF4A",
+ "nonce": "EAE83D7AF44006D4DB2FBEF7",
+ "section_mic_hmac_key": "D4810C45A1A468EFFC95E987192D01D0B2ECFD313E9852B1A3C914AEE1BAAB5D",
+ "section_salt": "605100404180967E0C35A27B303198AA"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "E6E881B42FC339A5ECA605018A8EFCE5",
+ "data_elements": [
+ {
+ "contents": "",
+ "de_type": 486
+ },
+ {
+ "contents": "05BE835BECBFF491794F",
+ "de_type": 824
+ }
+ ],
+ "encoded_section": "02BBDBD06DC3AB72F0082A6D0BC513951E56012BBCAAAC40D3F10B436E42DCDBD020E61B167FB0A77E527F3837E41D9AB666EDEF30B943B65984B33E7CCEBE0B4F79",
+ "identity_token": "21346A45B8489F23A9E63CB46B0AD4EE",
+ "key_seed": "D940EE0C157926DAB1DBF8020B86F06D152092B162CAF11C607B125A18FE58EC",
+ "nonce": "5A5DBDBC22E9F0485B0F0C4B",
+ "section_mic_hmac_key": "0BC02C5EB12F36E458141B6C48D553B9164D52F712BEDD2E0A7CB3FDB3C54862",
+ "section_salt": "BBDBD06DC3AB72F0082A6D0BC513951E"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "0E6F2D1663BA6A254DE665F436412DAB",
+ "data_elements": [
+ {
+ "contents": "4E4693617BA9052ECC",
+ "de_type": 692
+ },
+ {
+ "contents": "",
+ "de_type": 510
+ },
+ {
+ "contents": "6DC4A08E16F5789C7F4CC0625715EC35E03DEC75153C98F9F3",
+ "de_type": 501
+ },
+ {
+ "contents": "72EC503A57",
+ "de_type": 283
+ }
+ ],
+ "encoded_section": "02184D45A5DFF4F98BBA2B9BCCD0E66F1E6E4F2095ABB97491594F1E2615C6EEEA434ACD59264403E3B7C932D33D7AF49E223255148D5B9176DA76830D451DC226F6290B659EFB946BE7CB2F323D1AC1ED48187ACA1C7A7A1AF00E47D0A09AEA3D5B1FEED1",
+ "identity_token": "EF610B037D7AA8DB3C45146D1CF5510C",
+ "key_seed": "33D5F107E69D63BB05BD8CDDE5BCA9749BC619217585D756B67D84889942B812",
+ "nonce": "3600FCE45834326431FD54EA",
+ "section_mic_hmac_key": "36DC6B1B43D34B4A36A28DD14996986E4F3B14D346A24B1C7D5055202E1232C4",
+ "section_salt": "184D45A5DFF4F98BBA2B9BCCD0E66F1E"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "67C7EA4F6E8B95960DF747286E6C253D",
+ "data_elements": [
+ {
+ "contents": "DFC4A6D167092E0EC4386C1F377C8D7A982D",
+ "de_type": 444
+ }
+ ],
+ "encoded_section": "02AC62D0F2D343B4B67F2541B51FAB36F7DE79C99A6FBB63335DD4A5DB2D418C2B253164CEFA3BCB42A517E89BCD1FB1E5C6F04FA0C99CCB247F03D8A9575F2154D07D25D551BF",
+ "identity_token": "63E358995194244AD3281A35F844DEBF",
+ "key_seed": "AABF59ABBB17F47267FC66D84EADD558ED1AAFDEA87072FBAE1597E4F894CC2C",
+ "nonce": "438DCBDC58F3DC62CF4DD8C0",
+ "section_mic_hmac_key": "9C1F6AEEDBF0ED82872AEE17C94E67388D8DE56BF4E6D064B091F26314BC1C37",
+ "section_salt": "AC62D0F2D343B4B67F2541B51FAB36F7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "CE4777B8675B646E84D6CBA4000FE4CD",
+ "data_elements": [
+ {
+ "contents": "F1C005DE37",
+ "de_type": 856
+ },
+ {
+ "contents": "5CD278AE4F49F14B64AE6FFA980EDA5A30A96D674AE21E35EF1ACF",
+ "de_type": 669
+ },
+ {
+ "contents": "2CF1F076D4D763145F",
+ "de_type": 339
+ },
+ {
+ "contents": "E8EF398A871164F4AAC2512A73C2BBECD0ED64",
+ "de_type": 116
+ }
+ ],
+ "encoded_section": "02777790C1F455A388A8A8908F2530F5823703F5594AF0E8BC06C2C683DB980BF2575C3006313D8F42FC9A6E4F133C88CAF4EE90C76199F59C6778C13865B9FA83AFD4C4E27F22E1857B682EE6401C973E67F6A04CB1FC1030861B77DABD0FD7018DBDD221F4CCC89BBA1423311439598E945890317E4DB25C",
+ "identity_token": "98BE3C3FDFF640C7902485986A54CB7B",
+ "key_seed": "8AC62E22A13FD1D0BC83021FBE72E253187FD032D48150CE2E363F0DCA427A01",
+ "nonce": "838BA90741E30DB71D749F04",
+ "section_mic_hmac_key": "CA069B89338B5A7AB5B6385DF46AD1EDBEE95EE58763002DC70201E132F0B98D",
+ "section_salt": "777790C1F455A388A8A8908F2530F582"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "73204F77542E61479FFBB70F15BE9D82",
+ "data_elements": [
+ {
+ "contents": "E731",
+ "de_type": 228
+ },
+ {
+ "contents": "795B467FE034E95A4441C2E6E67FBE2117483A61793D21748522A4882BF8",
+ "de_type": 994
+ },
+ {
+ "contents": "0532BB79831FFD7B67D9FC26C7C25759EBE3AB6B",
+ "de_type": 343
+ },
+ {
+ "contents": "A488A172EFF5843E44EA9C",
+ "de_type": 28
+ }
+ ],
+ "encoded_section": "024E89F9D070337876390A8DC90F532057A9F37C117727BDBBD0521775EAC63B345A3E53A0483357B963123F26B640EADA4F0EF043D4B25D831100557C0DF475FFC0A6E721D016053596B52CB0404090F67FAF7565661416996E3EB43882485EFA6EB866520D4CBB482F26EAEE25053B69059BF757603E9514DF131B",
+ "identity_token": "49A94C68702A530BA761CF9A02D0D447",
+ "key_seed": "03BA9921A9EC9DE1B4C3975F758B63E9D5110DA1ED0C3926D9B047804C36C525",
+ "nonce": "CA9A5E6F0D1FB66704D8835E",
+ "section_mic_hmac_key": "790DB507668CD2006E6C56455ACCFD851022A5FD00E5AD27DC3A7F011241EE47",
+ "section_salt": "4E89F9D070337876390A8DC90F532057"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "13A1E3A6D3075C5319C41E8467634AE0",
+ "data_elements": [
+ {
+ "contents": "F98092C5EEE605C57E4F559DE1A39F6E097E90A6DF5ADD0516B1D0AE7C5E",
+ "de_type": 586
+ },
+ {
+ "contents": "9894D7",
+ "de_type": 148
+ },
+ {
+ "contents": "2F910D12E20F96F45D7E8D75D378C34ADC",
+ "de_type": 473
+ },
+ {
+ "contents": "",
+ "de_type": 382
+ }
+ ],
+ "encoded_section": "0201E3D1E7546915A844FBAE96D804883DC7EE8DA279EF8B4A38498DBB4B05C1444E7A3076881D63895422DDC17BE94B3AB229D60FC56E3F7B356246DB710D92629B73ADD1F33F12518070CB4B6409C406DCCDE26A4AD9972FC8235F4912ED2538D0B9D6B8D736C9FA05BF569A9033C4",
+ "identity_token": "39D0F77560A9F411D420421C51345467",
+ "key_seed": "D752C5EC1FD70E7443A37506DB53F6D9E1D521779526D7458CAA5E0239027498",
+ "nonce": "14BBE83961C2E06DF151C3D5",
+ "section_mic_hmac_key": "290C81A58DFBE27E6FCB3DFE0BC632B9D929AC6A60527853230793FFFEE83969",
+ "section_salt": "01E3D1E7546915A844FBAE96D804883D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "065DEA7DD770D48BE65DAF2A01922D92",
+ "data_elements": [
+ {
+ "contents": "1B690D",
+ "de_type": 183
+ }
+ ],
+ "encoded_section": "02006BF54BA34C5EEABE6733C40C6A4B9FEDB9B4127A2B99B33B12AA97FF6CB70D16AC7E7B3147A10EDB1F652024427E285A71D69A95BD2A",
+ "identity_token": "5CE752DDBBDE278BB19C9C3B3ED426AA",
+ "key_seed": "649A30B204D8F4A1B64EB975ADB6A2B83A7B6BC69728489535090564F3ABA77A",
+ "nonce": "454F3FBAA1278732E147A055",
+ "section_mic_hmac_key": "99262C1952E0E08CAC8768A100996C6CF6F1519EC57F18A0B1D73F5B2F6426FB",
+ "section_salt": "006BF54BA34C5EEABE6733C40C6A4B9F"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "C6F955057E1A4F1FFC1F2ABEA0B8FD33",
+ "data_elements": [],
+ "encoded_section": "027518E350DA3DC2A90BEBE9C1446ADC7DC841ADD922FC0E770BFF64583C4D9E7610A97E13326A236796EC40EC1C636A3B65",
+ "identity_token": "A161A4CC8259EB0F707BF4DF7B3DC27A",
+ "key_seed": "E73209D0C0D85198651F3B798FC53A0927DED2EEC6CE5B8EFB83E50BEF351209",
+ "nonce": "A5984AB79981B29B451A8BC8",
+ "section_mic_hmac_key": "A8AD4166470668BE0394BA7A2B9DD470F34C3BA85186BD1ECB8B00C4DD8C513C",
+ "section_salt": "7518E350DA3DC2A90BEBE9C1446ADC7D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "5A3D5F583031D4031F313ECCF3E7CDD1",
+ "data_elements": [
+ {
+ "contents": "7CA2CD5E09B6164ED80BDFD96614AB0EAF",
+ "de_type": 643
+ }
+ ],
+ "encoded_section": "02C99D27CDFF106A9BF60401B30A12B78CC29E229B704A39A08B30A358EC76C0B124735CC7DA14B34B5D303B34BCF804C0FF5E6FB3A56426766182C9DB7FB908D4AA1DCB08C0",
+ "identity_token": "40CE8EF0C7FB9C8B822F760DACF25447",
+ "key_seed": "1928670C4B6F0DEBED5BAF7A97E950BBE94EC7D567A70CE967E4B2B212B5A7A9",
+ "nonce": "E8D11B32953AD61E43FF147A",
+ "section_mic_hmac_key": "4CFDEBF521FF7DF20B146DB5947E0939F80346BA991E4D06BCE88587B675052A",
+ "section_salt": "C99D27CDFF106A9BF60401B30A12B78C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "1D8DA89F7A7D6CE5CB5AA18F77039AF1",
+ "data_elements": [
+ {
+ "contents": "632D457E2AFD3A",
+ "de_type": 945
+ },
+ {
+ "contents": "E4B2038436599A2A4888A76F09A99786DA51BC3F",
+ "de_type": 628
+ }
+ ],
+ "encoded_section": "02660B19D834927254C3CA4C44B4E58F9592C282EAEEFC114E0CAB05CF072BF7E5310DC0238DF9009FA972F31FDB78172E2D8751ABFB1B8D2C5A1472CB8AB52F915318FBEB98357115D69CB19FA2B381E5EE03",
+ "identity_token": "58CFED2666F58A35DB28BEFADE58C82A",
+ "key_seed": "4B54C23D5EE9BA26FAB0C9D819532B27104C3158DCF1204D2C90E493371465FF",
+ "nonce": "BC35F77BE3787AE9D562921E",
+ "section_mic_hmac_key": "832DD5525C889D87C58DFC886FC275FD53EF23602257DBAAADD8260445190895",
+ "section_salt": "660B19D834927254C3CA4C44B4E58F95"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "DEFCEB7C3979CDA6A93ABB83FC1B2D1A",
+ "data_elements": [
+ {
+ "contents": "2D7A34E6CA20A0E05E4639488D400B35EA638CE6E538678F10BA",
+ "de_type": 143
+ },
+ {
+ "contents": "E84E413DC7B2226F720540790093",
+ "de_type": 781
+ },
+ {
+ "contents": "FD05E7976720868B46D00A20A71E",
+ "de_type": 358
+ }
+ ],
+ "encoded_section": "022B54CE0520655913AD3C401F94530EE71BDFC769D515CB765DCA10AB115D32FD4F371FA81787527B9EE63C1D0B68DBFEC7C9651EEB12D6442CEC14CA7877CEE0261668C118A1A255A0994F5B8B7D86D5A6242B709350887160A90EF1DD0A3F0DBC402C8C114CD57EED600F0044C6E971",
+ "identity_token": "8C50C0ACF8A65AEDEB6963051EBB25EC",
+ "key_seed": "E78E6D29382220CEE2E4C81341D26B5FA63132186B82A0F0EC2A723B2BB184C1",
+ "nonce": "A3E85AD7D06053583B8A3734",
+ "section_mic_hmac_key": "E1CAD553106692395DDEB1B29597259001161AE17E76B7D1329891F98547002A",
+ "section_salt": "2B54CE0520655913AD3C401F94530EE7"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "4357834BD8534421FC328E433DC7B1B5",
+ "data_elements": [
+ {
+ "contents": "A0B4D6535ADDE0",
+ "de_type": 842
+ },
+ {
+ "contents": "82B652635D1D50ED2BA2B02EB2C724B314C1F528079AE302",
+ "de_type": 350
+ }
+ ],
+ "encoded_section": "02258C3D33CE4C862F9B69FAAD6C1BFE1F1F8D746B94BD1AB65354B648AC0D054A35385EF82E5626CEB99335CF2637088410D4B278EC77451E3C9AE2DB438AF702EA1327B74E5B341CEE8D2D1DF16A482EE18DE4F8511B",
+ "identity_token": "D53777A4358E0F2A2EC95AFA3D408870",
+ "key_seed": "A01B914623D5624DBBF6DBC8757BF955A979E32B187BC7F70E3EDBDB95C4716F",
+ "nonce": "B55F4A96033F23DBB8BD3F5C",
+ "section_mic_hmac_key": "13A8C92D1F018B4F892D459BBFFFBA84307867F39B300918B0D6518766347554",
+ "section_salt": "258C3D33CE4C862F9B69FAAD6C1BFE1F"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "326371E295F358C8F1237CC22F501666",
+ "data_elements": [
+ {
+ "contents": "6C378A24DE51EE42",
+ "de_type": 264
+ },
+ {
+ "contents": "248624F8FF242C90854382BB24",
+ "de_type": 248
+ },
+ {
+ "contents": "99135A2BC5D7D748EE152CE572FFC032207AA2AA605D",
+ "de_type": 514
+ },
+ {
+ "contents": "1EA3BE72AE386B6F42",
+ "de_type": 820
+ },
+ {
+ "contents": "94AC3E25F14015AC7C7AAC7E611A931FAF59A447F1D3AE",
+ "de_type": 708
+ }
+ ],
+ "encoded_section": "023B3CCC62107DBA3672E653B736AC923AA99D7B440C792BCA1D85378A240F0D766A47C965608B564999D496CDA5185BA9180928BCA9C43D9CDE40A6F8B5E52141EE95718009505ADE7B0D5285867B634ADEF94FC38951BD92B98C4005CE71ADFEA83040140F00688181B3763809B99366E69077DF00ECF3CE124D629BB0AA5F49A2378DCB05EAE7F9D64B38",
+ "identity_token": "53E15A1B5692E1BE92BD953C353F7B91",
+ "key_seed": "8DA28C3966FAA33B3C7302CD269126F56D184CFC10498ED7969A288AFB0DA616",
+ "nonce": "F4839E1496794C1F01572669",
+ "section_mic_hmac_key": "B65A6625E49603D87BB9CDF3D5B0D4C2DCDB4536F45A953A67FE6F101C1AE798",
+ "section_salt": "3B3CCC62107DBA3672E653B736AC923A"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "EDA860E0707ED96A1172A45CC0811384",
+ "data_elements": [
+ {
+ "contents": "29",
+ "de_type": 305
+ },
+ {
+ "contents": "B72753",
+ "de_type": 903
+ },
+ {
+ "contents": "6983195D8AA985C58DB6DA9ADABBB38DB3917430F36372",
+ "de_type": 540
+ },
+ {
+ "contents": "BF901CD8",
+ "de_type": 951
+ },
+ {
+ "contents": "A4",
+ "de_type": 859
+ }
+ ],
+ "encoded_section": "021026C610CCE881C1A6126022EFE069A66FDB75AAE177D28EAD4AEC586AE134F23F54F49C0E7D888DB5DD850D204030D83C303EC74ABEA7876345F687BBAC70AC0F1C47D6FF493166B00D002A6E7B89CDB7E10E921F081D8C674D10E2D2633E92",
+ "identity_token": "A3D9812AA67DE7AFAFB41B411582B2F0",
+ "key_seed": "4A23659FB7CFA0A0E73DE712ADD01F8FA0E7215FF8CFBD35771236B60A387011",
+ "nonce": "53E571E0DF89BF6C7216C7C2",
+ "section_mic_hmac_key": "5ACB14F2E5F318A1C9D769FFEF152293CF1A0A37B735153951DD236CA6DAD527",
+ "section_salt": "1026C610CCE881C1A6126022EFE069A6"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "6AED67F14438D7D911EDB8D722F488BD",
+ "data_elements": [],
+ "encoded_section": "02F4CA6005D5468E98560AC1A7EF01DEE90F3B25A4E8592F10463ED297782C65DF10AA8303AD3B3F647B0B35AB90E3751E3A",
+ "identity_token": "DB6F1DD46763D8721214EA515B47CFFA",
+ "key_seed": "F86B31559658B13CC4384D00DDA8CA7924F7F545DCB973E94AFA03D006B8E305",
+ "nonce": "A7702BAF126B2CBAE121878E",
+ "section_mic_hmac_key": "1AE36FC285306CC764C77EA289920D5428518672A3B9A5941C02DC4D2C836231",
+ "section_salt": "F4CA6005D5468E98560AC1A7EF01DEE9"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "6B926CEBE38D4132E4BE5532867BD395",
+ "data_elements": [
+ {
+ "contents": "67B6BC35D8B35057BFC81EE006076C575766A1",
+ "de_type": 148
+ },
+ {
+ "contents": "3D2F96ADD78DEE2E928A2A6D1452AC9B5C",
+ "de_type": 830
+ }
+ ],
+ "encoded_section": "02C4D4D2A92767AA88EC70C16EF70254C5028B41E18F6CFE231D87F6DF5CCACB1E3A2A223140474CA5A48FC80DEF2A64251E63A8645D1B338045BE4F1755E31916DC8169AF62BD094E015DF416DCB929C6FE9419C0E553CCB48BC8B8",
+ "identity_token": "9BD9767523D8349176EB79FAA07CC03F",
+ "key_seed": "9D09EA97DF4EEC2BB30BF025A9E6B81BD3EEB19870BBA43A4EEE452066BA7F03",
+ "nonce": "5B6638F881B5983B1A5E97C2",
+ "section_mic_hmac_key": "8F6F64C6F8626EA4F63A0B62B87E5A9F25A5ADE408E1E829E06B952BFC1FC419",
+ "section_salt": "C4D4D2A92767AA88EC70C16EF70254C5"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "BBCA7CCF407D135B2E4E30F2F2D5BECF",
+ "data_elements": [],
+ "encoded_section": "021AA76A19C77A439E19ADB69D70B0DB1C25F4EF40194EA5874083980925FE7A7710C4C42DA77C168CD699E7ACE28920571B",
+ "identity_token": "5350E2CA3B7927CADA9D6F2B02C28310",
+ "key_seed": "1B679F25EB8C387B01FFB315A1DB04D8981936963BFCAE20BF4F5524C1F762AE",
+ "nonce": "182CB56F4E9A946E490A066B",
+ "section_mic_hmac_key": "F7683F77117946A69929DBD6580EA3311C1DAF13C3755FDF052DCA96D0685970",
+ "section_salt": "1AA76A19C77A439E19ADB69D70B0DB1C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "52C67744CF1B5AE97F091C915CFAA6A4",
+ "data_elements": [
+ {
+ "contents": "0A882289B49B",
+ "de_type": 860
+ },
+ {
+ "contents": "38DB2A68327F6FFCDDCB2DEAE4B4D7C1C68FBD52F18711A8952AE1CE",
+ "de_type": 586
+ },
+ {
+ "contents": "E89FE85C63F175B22F6D373707D9C51F7D062B7278DFEB7F2699041DC4",
+ "de_type": 403
+ },
+ {
+ "contents": "FF6658532AD2EECB814EB0A5BF41",
+ "de_type": 63
+ },
+ {
+ "contents": "FBAA7E6F8C867A50DA6EB4F406B7FEEFC2378AC3CF45F1DEE9742FC9",
+ "de_type": 910
+ }
+ ],
+ "encoded_section": "0240A2448B3046FFE23A82D40AE027B410210C3D699F8057821BCB3C7465565CA087A7250E582F9AA365F5FC4E35F1F1340926427605DF90EED725463E57D16453CA4D3AC95BF35434676E3AA1616176E89F53AC9224003690DFEB64DB256D9DEFEDDB93D9393DEFA3A5BC664C8A234118E5548A6495334FC717CBC4571D2152B6D28FE4EECDE4F3C4179C62CB02BDE28EC7A55C029E3030A30407028FE1A4CE0925F431A2B14437E6",
+ "identity_token": "44CFC684E6C7050263E2CAB4D744A814",
+ "key_seed": "9A30AAA2B9A12B59236DB28F6761EFC40CCDDE59A07518BDB19D45BA2B72BF26",
+ "nonce": "AD0E77BB4D951804E67A70B8",
+ "section_mic_hmac_key": "CEB035A541C1D12C0F02B861402E73D21C8F4C2EC5C4C8DEFFD1623EC7FCBFDD",
+ "section_salt": "40A2448B3046FFE23A82D40AE027B410"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "23F75DC56095B764A3367B0BAC2CAB3A",
+ "data_elements": [
+ {
+ "contents": "3ECF",
+ "de_type": 825
+ },
+ {
+ "contents": "A0A7F010524BB3B0CF95D62762830DD0192486B2C21E",
+ "de_type": 307
+ },
+ {
+ "contents": "E58DB864D613F4CF4B613B0F9103BC14841C7B00ACE1CDDE594E448F",
+ "de_type": 769
+ },
+ {
+ "contents": "84E31D1747DA456817",
+ "de_type": 98
+ }
+ ],
+ "encoded_section": "02E1422169AFD9B4F1C931B65EF8BFCB907E66B43EB676DCF362B31F339BB43B1A58B6D6E192491D7C136397078953ABB335D77668F6EC744FD67142A16C9FCAE8761E4F8388E8B0A2DA4037AB767EDFF9A9A30E209A8D6E2E23A371C4085780A50EDDCD91B895442DB896B38455B9221B3096C69684C14599AC",
+ "identity_token": "10D4BDF9C47D2AB3EC885FBD625C0246",
+ "key_seed": "1FE48B81802881434FD77BF3C21EC0E8858AF9164C27C74D0F4B362F0EB5C528",
+ "nonce": "833F029D2BD54533FC3E70BC",
+ "section_mic_hmac_key": "78F4C0AAA20F8DA2EFC963344E5926EE8A07494B48E778BC158B3997AB2B6285",
+ "section_salt": "E1422169AFD9B4F1C931B65EF8BFCB90"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "7617C16EFAEF5EDFB06625756362C2A0",
+ "data_elements": [
+ {
+ "contents": "E5D673BAFF29A4D3C1",
+ "de_type": 270
+ },
+ {
+ "contents": "6A57381D",
+ "de_type": 887
+ },
+ {
+ "contents": "0E556091078C6748C36BAF40BBB4E4BB",
+ "de_type": 205
+ },
+ {
+ "contents": "2055F5870F08F9CD3EFA17955C99F226404A",
+ "de_type": 383
+ },
+ {
+ "contents": "C8A4A9A3FA548102A1F96327A4287A70D500DE35862AEC8E1AC6F1DB84",
+ "de_type": 628
+ }
+ ],
+ "encoded_section": "0279C36005CB2893825C08AC9D00C707FABE695CE889681CF240A6D97597ED0E7E6B4B7EE58F722D9DEA51FF86226C332E4917FA9E0724B39DBC3C1C9425F4CAAF49019E646B21816BA6B92701E19118AA31321C1ACC9725D4B7AECE13F56161A978E8F646FBEF9A61498F657340BB21E8D96E8F1980F62FF69F92695C6164D59D271991E38B4367DED244F3C4",
+ "identity_token": "F65402F8A50A61A802B8D5C12F7B6139",
+ "key_seed": "91E49925060895395298594A49F168FC765017D07C6E7A111FCED5C43A0C3A51",
+ "nonce": "5E14CA25F6C86D3DAAAE3A82",
+ "section_mic_hmac_key": "F81460B1DA857EF01821651349218A0B6DA51DBD2338913621264D75C0EA0BCE",
+ "section_salt": "79C36005CB2893825C08AC9D00C707FA"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "7D5C69BCCFE498E5464BEDDEFA884421",
+ "data_elements": [
+ {
+ "contents": "445E8055",
+ "de_type": 714
+ },
+ {
+ "contents": "2098DE470E2583D9FC2E040859F58B2C45D3",
+ "de_type": 769
+ },
+ {
+ "contents": "72BC2F855131395E0C6C0E5814B02D406724A11179EC",
+ "de_type": 799
+ },
+ {
+ "contents": "7456300CB3DD5E",
+ "de_type": 241
+ }
+ ],
+ "encoded_section": "02FD4D5055F7192BE8BA25A2FA5385B5D524CDE482D669C0E529D5308E322AE8A14F3A9DDC777769014856F0A8E6A042F1C05FB685E2E14E6B63F18556036E4D68A37E9941D7BD4F583C469D5F37105A22BE25B994D2227206DFE0922276D6375D480C08DE38B82D8DE92B0ED8C7AA1A37",
+ "identity_token": "AE507BDB86B14FE8EB76147249EC5865",
+ "key_seed": "797EE27B2E559335E524718A4346DC8823367D14A7D7242B0645A103D1E73391",
+ "nonce": "13623B08CBFD928C92254CFF",
+ "section_mic_hmac_key": "409F3A5462F5B64E15C9264A981ECEDC489C5779AAF29CB5523714DBBB82A06E",
+ "section_salt": "FD4D5055F7192BE8BA25A2FA5385B5D5"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "F5F75410EF7DC53152BD2130C6327171",
+ "data_elements": [],
+ "encoded_section": "022252124D2BC9B6498FDFCCD0196CF4C56B993255169168AA337B00796E3C0DDA106B5F1F519ADC5898F7F5661895462E16",
+ "identity_token": "E18F1D6F8CEB5CF84C941AA47C728D66",
+ "key_seed": "4A01C7DC09BD3999C74B95A6B50FC0CFAFEE1E36C260026D0DD46F21C56D82EF",
+ "nonce": "497A0BDB69B6E6258A1941A3",
+ "section_mic_hmac_key": "B4D73916A49E25F62EC59C9E9B24A347EB1A5B95694681467B8FF6EC79A3EC27",
+ "section_salt": "2252124D2BC9B6498FDFCCD0196CF4C5"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "3A64FA90D74450D083302E2C059C9665",
+ "data_elements": [
+ {
+ "contents": "CFC759543DAD41C009FC402A",
+ "de_type": 988
+ },
+ {
+ "contents": "786F5232031993953C6A9A08C1976E8C30BFF38FA84531086FF19DFF",
+ "de_type": 846
+ }
+ ],
+ "encoded_section": "025F023F5D79C52E9DBAB9F0DA69237D642DA017E11913BBB351FAA7067EB3B06A3E8BFB15DE59E4CD1C3444935A180C26E58FCD08650970B216E1CEE4E8E96A4EFB59E03AB6409A5FBC07282CAF51181B8196D0D6DD95D424076EBA7F4C92AC",
+ "identity_token": "71E0154EC5B0D069EF2CBDBE4D4F64EC",
+ "key_seed": "076E48318DBCAE9AC52822CCB8C328E8E526278A881C3E777285843D900DC7C3",
+ "nonce": "B81706D97EDB8A2F21130E10",
+ "section_mic_hmac_key": "5F5F097D7C90D9DD993E554E3620ACB5E32EEED68D0A70C8D0A96B9E8FCFCE0C",
+ "section_salt": "5F023F5D79C52E9DBAB9F0DA69237D64"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B443584BA0695A5DE100FC7E4471F096",
+ "data_elements": [
+ {
+ "contents": "8D07D7C161B1E3B9AD44036C9152",
+ "de_type": 568
+ },
+ {
+ "contents": "241997237B",
+ "de_type": 304
+ },
+ {
+ "contents": "EAE8BF35970B3FA758ECD25FAFB52DAAE97E90AE207A5AE1F65EAD0D49",
+ "de_type": 240
+ },
+ {
+ "contents": "C3BEE2960CA3C9BA732858B26600209CC17E277BB91578F7F992A7",
+ "de_type": 923
+ },
+ {
+ "contents": "FAC026BE6D3446FD6C7EA221B4",
+ "de_type": 282
+ }
+ ],
+ "encoded_section": "02AADF94195BB7269EEA6B86F55F8F625EBAB866B50BDE8C3963CEFD8AF4C6415F77869D51C5DF0D1BE02D052056B0A8EC667DF3E294C898501276BB22C0657468C4BA18A25F35C4C3EE4A233A77C5C3C77F23588264BDE91EE9D0B00735C5A5DFF02F97849972CE1FF1CC5DC22200D33DF6FD1957F9CFE6C42242B63563BEAA654E63F10611B4C43262949BA084C9ADD9DD34430D71A64D68",
+ "identity_token": "F73F1700F798A87559130AB945C74741",
+ "key_seed": "DAC1B91B10F16C4398EF7C8058ACCAEC2A9B30A0FB9AD66E121DD19CDAEB37A0",
+ "nonce": "2EC6381E4B347BFED3E91754",
+ "section_mic_hmac_key": "642792EDF30489843D0FE58973082D231FDC14BE72A4C007BBBBF85CBE8757A2",
+ "section_salt": "AADF94195BB7269EEA6B86F55F8F625E"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "83EC80F024DF21B65CFEFD1EF94740E2",
+ "data_elements": [
+ {
+ "contents": "27A69E731F",
+ "de_type": 287
+ },
+ {
+ "contents": "DB716058E34CF7B472543BA8",
+ "de_type": 576
+ },
+ {
+ "contents": "5672B7B1AA5E483968D00E77AB12",
+ "de_type": 124
+ },
+ {
+ "contents": "F46774",
+ "de_type": 705
+ }
+ ],
+ "encoded_section": "02D525060ACC8BA94C63CDDEC60BEDB5AD791F43370ED6BDE4CC9BAE70A03E4C9B3D33536D52A575D5C02DD67E91BED7C3DE179AFC1C035397388F48297764EA4E8C329557E6A71FE5A63379A8618777524C2AD19E0A9BF1F65F6BC54C076C",
+ "identity_token": "DCF0C0BC6CF0AED2BB98005F9BD314CC",
+ "key_seed": "40402744DE9F4976A2DC489058A6E3392FB0B9835DB8C7018E678B3406C4441D",
+ "nonce": "02DA50D948182D528619E7AB",
+ "section_mic_hmac_key": "035640B10657D96179E987095B1D01D9A98C6158A98726FDDFADFCA582268F9E",
+ "section_salt": "D525060ACC8BA94C63CDDEC60BEDB5AD"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "0418BBAF50BB908526F913583233E243",
+ "data_elements": [
+ {
+ "contents": "F45CB09C4F9BCC64CEA8729CB757EBB30B9F35DDA00494D9DB2CFF53ACAE",
+ "de_type": 909
+ },
+ {
+ "contents": "50F3A9F85CE86BB46570EC179649CACF30E68184C26F0EF029D88AF32869",
+ "de_type": 47
+ },
+ {
+ "contents": "036508751C50D9C40FF288AC9CC81B46D0CA17",
+ "de_type": 498
+ }
+ ],
+ "encoded_section": "02CCE7901E20E283CD0A9CC73E4EECE408A6D1C01EDC8574E8FF9F2D4E1F07CB7267AC537E5BC0F41CA06B85E63818B10F5B012DB59C0D127A1AF043750A04910CF3E8CFCD245190702461AF431A690891BA9B37146990A0A330674F9708D25B3730D5B23A4DBEDF46694CBF3D7AA4CE6C35C8CC833A22B82B74A3858DCBFC262C065EB5A5DBEB36B7",
+ "identity_token": "F8D68732B8CB236625F2F9FE6EC1DC4B",
+ "key_seed": "A2BA315C4719A6F2F908D6662DBBCB072B283D419F9A56B79B2B6233E96C21C7",
+ "nonce": "1B41FBADE98FA042E9FEC7C3",
+ "section_mic_hmac_key": "72F23D0F266F564D8D5A2545426A7CDDA3F7D20D43E372CB6EE46D85871537FA",
+ "section_salt": "CCE7901E20E283CD0A9CC73E4EECE408"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "E2EE6FE0CCA11951F4854DA7BDA99ED3",
+ "data_elements": [
+ {
+ "contents": "C40552987F158C0CFC56EBF3",
+ "de_type": 321
+ },
+ {
+ "contents": "",
+ "de_type": 503
+ }
+ ],
+ "encoded_section": "020E4D5C6ED93B014055B8951F8FD220A57D827187D544B46DCD6ED9432B424F4122E01AC41591CB4DF89F5D00410412A7647452BF4AE9865BC9F337CBC12706F1881985",
+ "identity_token": "F46324863C329E19C0522E7AFB0D9B82",
+ "key_seed": "43766BADDE1B80B6598CA446112A8FC98DD42EAB244B3DEBF08302D7BD4FD376",
+ "nonce": "FC43822BD63D014A2ABA6479",
+ "section_mic_hmac_key": "DF4154082EFCF4F670B87A36A31E095ED7B7AFBF8C324D9F8E0D29E1EEE8F7FE",
+ "section_salt": "0E4D5C6ED93B014055B8951F8FD220A5"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "77F690701DDFD7AAEE15B393CA8E4113",
+ "data_elements": [],
+ "encoded_section": "029E470E6DD0076A256D60553EC207DA37F38577FBF8CB639C6E8F84A4502D5CAD10B4F17F4720071345C051290A66EE1347",
+ "identity_token": "AEA2B76D803628E0426E64AB7477B395",
+ "key_seed": "13154557990A80FB24A70BCE09BBF62DAC2C95146B1163508D9CACEE89C75D96",
+ "nonce": "6B54C468B6CD60C9BCF05C06",
+ "section_mic_hmac_key": "7C56EF628CB49E0E3439DBE47034A4EE4D74CC431D919E7ED97F31B7C4680D00",
+ "section_salt": "9E470E6DD0076A256D60553EC207DA37"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "CF0F755BC0929BA3338B04E0126BC444",
+ "data_elements": [
+ {
+ "contents": "0AA5A94208D57B66ABE5B8341167C1544ED91B35C6",
+ "de_type": 695
+ },
+ {
+ "contents": "3E39B499E2B74671EC3A54CB",
+ "de_type": 920
+ }
+ ],
+ "encoded_section": "02ED8065C1778DDB635023F96FC9DB4B43C2FCFC10BD074146EED51E7F9A46C9C437F01690BF9BAB7C0A9964BFDAFF313CF0B46D6387B78922EC76F009B1C9D11C103F54DB4B6C2CC32CFCE97E2F3349B91AF70279128DDE2D",
+ "identity_token": "0A257DF8A7692B3249407E160C037F32",
+ "key_seed": "3F64813E8A4B3DC815206ADADF36DB6D66B9BAD623636491CE3A47A85A80ACE1",
+ "nonce": "E1AA1F6A438632C46B33AB73",
+ "section_mic_hmac_key": "A8A1D0BB14D04085F5340F1ED0AEE5C2201BD4EC668991370E804DA18EC94CB5",
+ "section_salt": "ED8065C1778DDB635023F96FC9DB4B43"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "08851035A5C0B4211E613496BAF5EB58",
+ "data_elements": [
+ {
+ "contents": "C0D408E8EF9DDB0E755EB45523D250D58B7F5B647721C03ED8",
+ "de_type": 21
+ },
+ {
+ "contents": "0BD5FAC43AEB6F8CCEB0583EE744B80A897ED7558D57DFD06BB81C",
+ "de_type": 323
+ }
+ ],
+ "encoded_section": "022C1DC1FC780C25AA2E4852BA8CDB2BCB44DBC4820A019D95184F42A70E419861498AF4A6CD8AC3D9E110C0021461F9020233FBF843404099F378366DB902EB106947263B984BF7D40116604F55C42DB12F25C686B250E139DC1C994CDF5E7C1CF308144E294155D20AD3",
+ "identity_token": "776B3A62CB93BA94651552C97A2E4267",
+ "key_seed": "9509B69A6A2BB6CCBB1A1E7436E77AFC2D00A2FABD2A1665A7BA6FD6E33354B3",
+ "nonce": "42DA14BD4FA470084787B4EB",
+ "section_mic_hmac_key": "603743F9A5815E17229E364C363DEAB2ED6341B86E6D6A4F2F723629272CD0DD",
+ "section_salt": "2C1DC1FC780C25AA2E4852BA8CDB2BCB"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B60EBD62633BB487ED9F7D9E426A0D96",
+ "data_elements": [
+ {
+ "contents": "7A0AC4F78A416F5B0114535909A5307F",
+ "de_type": 902
+ },
+ {
+ "contents": "EF581947C68D9E50AA05",
+ "de_type": 46
+ },
+ {
+ "contents": "FD",
+ "de_type": 888
+ },
+ {
+ "contents": "FD",
+ "de_type": 315
+ },
+ {
+ "contents": "CEDFEE9059F500C97D25C94F",
+ "de_type": 7
+ }
+ ],
+ "encoded_section": "02DF453EF92630EB12DC02E3EDCA4A36A08BA4F34CBFA1B595CB3A6D01C58724D0455434E8D72455F125B81A186A41FA589EE9710ABD7F9F67E011912FD0DFB2337306AC59112298BA20EE5FE66227AB94034D13388BB4484B8A6587A31F0234024115F6D30CF9",
+ "identity_token": "A1C908312B87892BB9828075C672635F",
+ "key_seed": "6D32B114EF3DF0128A529FDF8B2E7EFBAFF451FAB30302DDD8BCDC811D0FF0AD",
+ "nonce": "720138995818A3EE421768BF",
+ "section_mic_hmac_key": "9243F2687949CC4D05AEB4D8FB77890569AD61591E37FF206959B6CF98342BEB",
+ "section_salt": "DF453EF92630EB12DC02E3EDCA4A36A0"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "DB1A823A46931F80A323BA830F003123",
+ "data_elements": [
+ {
+ "contents": "8100834C61C6C93430E5C7BD4B86866C074468",
+ "de_type": 0
+ },
+ {
+ "contents": "CE623A4184335F6C9D55A7A2FE02478336DDF05D8F4BFFAE",
+ "de_type": 238
+ }
+ ],
+ "encoded_section": "023AF28C09CAEC840269BF5DEEEB2AA95C60E64AF819E6A97B8ABE980FD7320593400018850FCA6227B727F1ECFEFC2B74B62F21E44B40B14500E9736646713FE6B65DBCEA9A39CA410D4F4E7C25FC753BF4E89064485C09E8B30D936CF3FC31E704",
+ "identity_token": "0758CA3E92715E8088FEDB4D069661F7",
+ "key_seed": "46F7E0CC1B0AFF6971DE8E4AF1BEDA76D5FBBBC1673D67D5E3592207241B03CC",
+ "nonce": "CD05581E1D32C9D6F251E1DA",
+ "section_mic_hmac_key": "7EAE309E12347554A36BE7F5416BC98458A6BBE1CE11812AF7E1E0170942DE7D",
+ "section_salt": "3AF28C09CAEC840269BF5DEEEB2AA95C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "094545346D6DA2AB87E9F21C22EBEB5A",
+ "data_elements": [
+ {
+ "contents": "FBD5BF3B86FC4DF98299A04516E245CF69BD201E44111D9F58835F",
+ "de_type": 962
+ },
+ {
+ "contents": "7A00781BDED3EB83ACB0F347A49F14D039",
+ "de_type": 611
+ },
+ {
+ "contents": "42A41A496D6BE276833FFFFD2778E555A4ACC09190B60594CFAA1F",
+ "de_type": 992
+ },
+ {
+ "contents": "F86971896012BD",
+ "de_type": 517
+ }
+ ],
+ "encoded_section": "02F8F5300B7A01F96A0B73610D4A82F877EC68C96FE249E235C18FC5856E98E4646AADE7D3002AA4F39AF7F2113392EE3C6521AAB6EDABC8A5C5CD33275355C434BA00554158FE2207C510267BB6A50B721D2BF1DB8A832CEE8C1D09CBE920E9B9AE68686B7393211E5CD0943C97A76CA8A0FD82B18CE06A7ED92FB378BE450B6930A6F241B1D2696E80B598",
+ "identity_token": "6F95D140C0F87F34DD4CE7CB17CE8609",
+ "key_seed": "0CCB26C7DB958F8435D66E11D6A68875DA25E7D12A11EAA58386A2290A42027E",
+ "nonce": "6DD2B018A20FAA4E46703F7B",
+ "section_mic_hmac_key": "D5A0F725FE6E6D8BDC79C2C668196D3303D6465C92D478BC676F91C1A462E024",
+ "section_salt": "F8F5300B7A01F96A0B73610D4A82F877"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "621702EDC90A5A8954B64A8CF883DAC1",
+ "data_elements": [
+ {
+ "contents": "09",
+ "de_type": 482
+ },
+ {
+ "contents": "D5",
+ "de_type": 698
+ }
+ ],
+ "encoded_section": "02B14D7C2C925F3E24ACB1E4A5D4DA6F193FA87DDA8E2FEF20F01FFB5ABF3B8CFC18B5ABC3BB0FA0C46785729CFCB9192442D7DCF702EFC0304F",
+ "identity_token": "9E6F8A6063A6BDD60D5954F592A3B8F2",
+ "key_seed": "C62E96131C7C8B805CC9FE6FD634CB9BF84BD4984529B30576B3F3856CF04E63",
+ "nonce": "0FDA5313782FED9FF7E65C4C",
+ "section_mic_hmac_key": "89023EED69C4E5DA5ACD11E15AA540323F2EA47A19E4937C19A10DB89BF9A735",
+ "section_salt": "B14D7C2C925F3E24ACB1E4A5D4DA6F19"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "B5CE72C63EFA9DD095716472FAEE0784",
+ "data_elements": [
+ {
+ "contents": "DC06F9FBA5ED966657D9CFA8667DC006850CF89899DD",
+ "de_type": 989
+ },
+ {
+ "contents": "F68AA9DFC06B7EB7D9CBBF5EAFA968984A100C2B03C504A5E1D9C7",
+ "de_type": 706
+ },
+ {
+ "contents": "055D1DEDA05C238D7A31E5CCAE",
+ "de_type": 379
+ },
+ {
+ "contents": "5D1B64B0D53EDAE32FA989CCC38E1B2ACEAEE0930EDC",
+ "de_type": 221
+ }
+ ],
+ "encoded_section": "02E1630DAC1DF049E06A3020858C0857589FF7482D737059F5C999422EC552C91670AA375473BE99ADE7BEBCE8F54E3EA98B2C36D02BAF87EAACB81D0C461C824138DFBBE8BDF53FA7E19F53BEEE1EC2E228956F551335C7BE1FA38CA5933DE6AF767650F6B00C4CE3F7FEC0ECEAAB12811D79317CE035BE9E5E19522A1E329CB0D9B6FD0275F619D95F0BFDF8F071C4FB0A",
+ "identity_token": "57EABE3C09AF926FCAC347ABFAD9E33B",
+ "key_seed": "D3E7B4BD3F00BB656B34B68A9B57D3499B1690439F52E39BF55145069B69E012",
+ "nonce": "70AA23057C2F616829EB283B",
+ "section_mic_hmac_key": "6DF923F1C439D6DCB1D17267F1DCF9F77974CA0CDF3815525FC480F56FBD46C7",
+ "section_salt": "E1630DAC1DF049E06A3020858C085758"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "E257258A3F83CEC8750E338556A3806F",
+ "data_elements": [
+ {
+ "contents": "FC2AA7F38F27003ACE8033FABCE80A1A0A2855",
+ "de_type": 534
+ },
+ {
+ "contents": "93CFA0A1BF2C1517B833EE189ADBE984348FE43D91B738D1D51B1A52",
+ "de_type": 317
+ },
+ {
+ "contents": "4883BFDB2678",
+ "de_type": 899
+ },
+ {
+ "contents": "EF90D2A4545867C3",
+ "de_type": 654
+ },
+ {
+ "contents": "37C02A83E008FA26",
+ "de_type": 532
+ }
+ ],
+ "encoded_section": "0289F842808FD5738C338616A2560581A8A52F4A6E16A6AD73CAA41028724B501D64C5800CE30D76F8D3BAD6CD098CDCE3FEB9F4425CDC836605063FFC21BCDD041E0158EB7478416478361D4E2073A9E1C61EE770E179998E0211D0B225F1F59C2B9392F5843E3E4F99716B356E52081797EDA99115FC8A0012D55A0C3D119117D0D98F57AF",
+ "identity_token": "80FAE8E4817345A5115FE9556AA13FE2",
+ "key_seed": "C6044A22FEF3D9547667D2B2E2BDB95FE9E436B43F7137CB775B790BBF1C5914",
+ "nonce": "DCB6A5793686750BFF4725CA",
+ "section_mic_hmac_key": "B2A815D44780CBD0317F016087313B40970A52496DAA6B665EDEEBE1287BC499",
+ "section_salt": "89F842808FD5738C338616A2560581A8"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "C92370BF646709CC74E15195B1ABABD1",
+ "data_elements": [
+ {
+ "contents": "BCBFD4CA484D111FC650E199022CEDB4472F4D9F59C27551835889B9",
+ "de_type": 89
+ },
+ {
+ "contents": "479B03",
+ "de_type": 87
+ },
+ {
+ "contents": "7491B3382FB4A3",
+ "de_type": 857
+ },
+ {
+ "contents": "28006920EB7BE921EE08CA9336FF3707D9EF2A7D46FD3CB35978CFCD0C72",
+ "de_type": 714
+ }
+ ],
+ "encoded_section": "02E87E2FF9D4E8BED3A34DE8708A523395A9FDFF7E97F5E5222F1C4B3AA8AAF6845EA536945D4DFA8BFEDDC75C93B34610D1621CCE80013B78B90E0E007523EA372201FA31AFC18C88A789792AE6E37CC5F054D82642578AC1DAC9EC7A79931FAE1F296A85C216E879CB49D5438B4D9F7342F63576831F37CBA052BEF9674439",
+ "identity_token": "08ACA51C40D663F21A4CF2BFDAD1E502",
+ "key_seed": "D4B0FE67999329E23C3217DB7A469FC35280B5978CE80E532C08B59BCEE4EF00",
+ "nonce": "8FCF4745A019605307496CCF",
+ "section_mic_hmac_key": "E2CD200FD23CE0BCDB1CB503048CE71B4E7E3F150D5658F8234B6C6D28893749",
+ "section_salt": "E87E2FF9D4E8BED3A34DE8708A523395"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "5787FFD3CFFF8F69FE45E50872B49181",
+ "data_elements": [
+ {
+ "contents": "8401AAFF665AD9920B6B33B839A72F",
+ "de_type": 237
+ },
+ {
+ "contents": "8B88158B1F60546E56508E86",
+ "de_type": 969
+ }
+ ],
+ "encoded_section": "02E44ED613C98F0DC2AE5C4323042CD36D21B0A7C29E85FB08B05F62E9EA5FE3C231E9F3572CBD15F02D0A232F930664DE8A8D93CD63BF008526F7F60015C1BCB75F2BC2D12AC600CE2E0F87AA96C8E54BF99F",
+ "identity_token": "19D4435134937780CED35A279D095109",
+ "key_seed": "6C41D17E9C408D509BEC4EA6716F010BC72B801F9545BDF8F9DB9539AC6273C6",
+ "nonce": "189F567A1F62F04507652C14",
+ "section_mic_hmac_key": "D1B6432B61BB4272E325A6979882FE9BED562061A383C648C3294B19B707169C",
+ "section_salt": "E44ED613C98F0DC2AE5C4323042CD36D"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "5533BA11358651AC5301BCC7DFE8AC6E",
+ "data_elements": [
+ {
+ "contents": "B775D5A14D08158FF431E168F10515145B07",
+ "de_type": 798
+ },
+ {
+ "contents": "2FE686DF80A9EBFE2405D84EAB72016B882AB50A11CE9EE5ECC5",
+ "de_type": 430
+ },
+ {
+ "contents": "1276D64D40BBAE244D398A82396342",
+ "de_type": 482
+ },
+ {
+ "contents": "C8EAFF62E466C78817A3747427C22E68750507B744A6",
+ "de_type": 823
+ },
+ {
+ "contents": "C964A89C33D058E2D533",
+ "de_type": 773
+ }
+ ],
+ "encoded_section": "02A25AF6F97A49FD5AD7A58AC7C618CADCE311355595A5534B1F7F0BAADF291C8A7AB1895AF21700990CD60C3B451431E563A6D614CA7E04A84935698C0401CF79D74AA6DD6B65E23E6B0FDAA670D41B995EE23576190458B823A743CC915471252B601682AD93237C3B986070F377F4E1254953760337B10F55882E805E44447AE30E32DD4111B1BE46735F9409A8F57BFD89C9CBC8389EB5DC220B",
+ "identity_token": "F8378536329D2B2E962DE8AC894BA112",
+ "key_seed": "195197E02A7D9C2F04073A07987A7FBA10B4EAF66D69FAB54015A68960933535",
+ "nonce": "E3647946D8FC39BCBF6CB625",
+ "section_mic_hmac_key": "1E35AFE30548CE05848D3E362CD077E2DB826E10B217D21C3026CD2D91F1CAFC",
+ "section_salt": "A25AF6F97A49FD5AD7A58AC7C618CADC"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "E8EA3502A9010273177F4A0273E3B568",
+ "data_elements": [
+ {
+ "contents": "",
+ "de_type": 93
+ },
+ {
+ "contents": "AD7FA1E4C83E494CADC0E105",
+ "de_type": 591
+ },
+ {
+ "contents": "8085D6",
+ "de_type": 425
+ },
+ {
+ "contents": "267DB04BA141F8A0B9D16F98F815AA051AC5A2DD18AE2CBB5C",
+ "de_type": 719
+ },
+ {
+ "contents": "0C4AD34F70D189FB9B6B93A52E0804BE81CAA18CDD",
+ "de_type": 272
+ }
+ ],
+ "encoded_section": "025723B7208ADF96D9B8BC420F33486A6C8B36F43A0470FE4B458949F34055F1E75BAB75AA88F163CC5E6DCE56928779AB957A749284BD8B7B84527BF9AD52C4A08EF70D4CD2B76BAE77533DF9239474DCF758373A9D0EB08BD383A582626E70F39871439F29B764B9348F6B9984421D2E7F6A13C62B7164CC9219958E",
+ "identity_token": "655638465094190FE9A77463BFC9E126",
+ "key_seed": "AE9604009D3FD6E950A44CC767AE10C22A6744CCF2CD8E0C76E76385E6081DD5",
+ "nonce": "228A038D1F89336A39CD594D",
+ "section_mic_hmac_key": "ECB8CB36E3E179D9FD78006D46C85058F1A2BAB87014F58D792382331B7FC062",
+ "section_salt": "5723B7208ADF96D9B8BC420F33486A6C"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "489C9B6D1094A881909199D2F70129E9",
+ "data_elements": [
+ {
+ "contents": "A50C355E004E703AB3E11199F9F7042FB8B297A8EF63EA692AE83EFCFD10",
+ "de_type": 636
+ },
+ {
+ "contents": "58069F92B86136E4DAFADE70D940D3C997D95F94",
+ "de_type": 434
+ },
+ {
+ "contents": "FE0781315E780B0C45D4B4B1",
+ "de_type": 577
+ }
+ ],
+ "encoded_section": "0271B85F63AC3C61F03F39EF0E169D1D82FCF69C3E0CE5EE7830BAF677CAB9A146578963EA76613CC2A8B79EAD6AC940394D4BB937993A3C29BB3566FA8B23B9F6C035CDF9CA49FBAAF3B9D32E7D177EEE6D5E30D64DA436E0A6F3822B94C8F9DC84F77D0546A0728F6D4A0C0886DAE3C50D217601E697BB48",
+ "identity_token": "F795F354C5FEEBF98A35AA27BF4FB65D",
+ "key_seed": "9E41319F2ABE29937E2BC9AADB59DF37DDD64CC95470A1FA92FCD92284C49C07",
+ "nonce": "8D134D36CACDFA48AD2E1624",
+ "section_mic_hmac_key": "8F01AC5CEA8B33DC8E3A6917CACE845E3113D054A6F190CCA4F8B19B00789CCE",
+ "section_salt": "71B85F63AC3C61F03F39EF0E169D1D82"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "1AEFDBD92CF0BFDD813CED1AD930424B",
+ "data_elements": [
+ {
+ "contents": "89",
+ "de_type": 537
+ },
+ {
+ "contents": "B5838F8BFF3E1FF8CBE34A",
+ "de_type": 148
+ }
+ ],
+ "encoded_section": "02AD263B2C711BFC36EDFA522E9607CE18DA76E578E9130C9FEE33FEDA62BD179322CF68031C2EF90E092EDB3707CD7F86FA9CD806C56ABC93321E301D4986832966C748",
+ "identity_token": "03785872BE7F3F5A06BA8DE5A547A0B6",
+ "key_seed": "E3D6F78BC1A45CB75B06E63B81733A1B31DAF8AF1E4790B884599718BB790412",
+ "nonce": "67A8B67A65C9C4D46FCCDD11",
+ "section_mic_hmac_key": "6C89903E5DFF8B5D2CF1B2DE9EDDC78FAAC03B5EBCC77B9CF810A9F29E6AB15A",
+ "section_salt": "AD263B2C711BFC36EDFA522E9607CE18"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "11FEBEE577A641BE1BD6D7A95DA0DC61",
+ "data_elements": [],
+ "encoded_section": "029C0F1303B8D7E8FB226FC19EB2D987E443667F2221C7DAEF257221200FC24B6210F1D684DDAEE3DFA978FE9A0C807887B4",
+ "identity_token": "9BF79D0640C3F033616E88C085BA0E84",
+ "key_seed": "E71E5C9532BFF3AE23003A89003A6D78BCD3D11705FC47C56D55ACDF0C1E8625",
+ "nonce": "727CC259D161A356AEA07884",
+ "section_mic_hmac_key": "4D2C247CB47A94E69FB4D4BE132D0F7C3FFBC4756234ED5B1E6D3A8DB4A88F7A",
+ "section_salt": "9C0F1303B8D7E8FB226FC19EB2D987E4"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "72909F4BB264D9EE250C302AB93F9691",
+ "data_elements": [],
+ "encoded_section": "027BE514C8BD6C7BE897EA35578108DD35C1D8154719977EA32D96CA42E86AE207107F459409E5AAAA74A2DB0542D6062DEA",
+ "identity_token": "5846C49FD8AC98C1892ECFA87C40496D",
+ "key_seed": "8D6D511E1B70E96DCF325405832C77CC3565D1503AA3965894616C1F0C57E113",
+ "nonce": "1524A30566D6169A501F43C0",
+ "section_mic_hmac_key": "C743F000CE8B2ED5C3735E9CCEA37E634A0965E71CB8CE9DA599917FA6337C50",
+ "section_salt": "7BE514C8BD6C7BE897EA35578108DD35"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "9FCAF424921B3EAC6108BBAD5A73CB99",
+ "data_elements": [
+ {
+ "contents": "9E1B5533A9E53934781C72",
+ "de_type": 208
+ },
+ {
+ "contents": "952B14BF77506C",
+ "de_type": 549
+ },
+ {
+ "contents": "6E5D3C18ACD4B106A55B4A2637FA57DCD34D",
+ "de_type": 782
+ },
+ {
+ "contents": "9931CB53B91C9EF8F62E358284A44B00D8AC1A95AA73",
+ "de_type": 222
+ }
+ ],
+ "encoded_section": "02D14BDD76436FA2B760E9AF470F4321DDDA37CA2E790A42149020904EB4F7C88A560D3F833B34C52AFE8DF576F04DD03F9E961F946B06501E88B0D7EFCB951EB7D876BE437FE69385B7CF0F331CA1B3A2E3E95279F83E363542E7D5F757AE3091B5A288B485C50EF7BB755A39296357C1864AC797E35505",
+ "identity_token": "36D94D61F32E7B6B24F59C8295F1AF96",
+ "key_seed": "4BB6613384D29BA3C848795DD8C4A2C43DC9510A8EC03F6043E815AF783B7F38",
+ "nonce": "C59C14410DA46F23624443C5",
+ "section_mic_hmac_key": "DF3E0EA835945BC60C5F661AFE7A4E33A056508943126AC0D057BB51C453F71A",
+ "section_salt": "D14BDD76436FA2B760E9AF470F4321DD"
+ },
+ {
+ "adv_header_byte": "20",
+ "aes_key": "CE880F0EE78F5EEF297475B681DFC310",
+ "data_elements": [
+ {
+ "contents": "99F0EA",
+ "de_type": 289
+ },
+ {
+ "contents": "98F41B89B20F1FE7",
+ "de_type": 498
+ },
+ {
+ "contents": "467C",
+ "de_type": 91
+ }
+ ],
+ "encoded_section": "02F18F6DCDBD4B8E8DE00A1A433A282C7EF840CA1A3788B4E9D8C8A6B9D413047925F0E300086648E857BB9ADFF9F6F6391661A854C2FA5F1AA7CA204D3DD126F6294C1E788D05",
+ "identity_token": "04ED862F43B938ABBCF539EBC70A59C7",
+ "key_seed": "710AE30C71188D8EB7E644A28219FF52966F449DC5B6BF342CC62A387E9FD166",
+ "nonce": "742EB407037A9A1001C248D7",
+ "section_mic_hmac_key": "49363E312316016C76C23E7AA07FB33C1CE4DBD0DDF9390FCA2601294E8740F0",
+ "section_salt": "F18F6DCDBD4B8E8DE00A1A433A282C7E"
+ }
+] \ No newline at end of file
diff --git a/nearby/presence/np_adv/src/credential/book.rs b/nearby/presence/np_adv/src/credential/book.rs
index 902d55a..ef6b269 100644
--- a/nearby/presence/np_adv/src/credential/book.rs
+++ b/nearby/presence/np_adv/src/credential/book.rs
@@ -16,27 +16,25 @@
//! the credentials to try for either advertisement version.
//! See [`CredentialBookBuilder`] for batteries-included implementations.
-use crate::credential::source::{
- CredentialSource, DiscoveryCredentialSource, SliceCredentialSource,
-};
-use crate::credential::v0::{V0DiscoveryCryptoMaterial, V0};
-use crate::credential::v1::{
- SignedSectionIdentityResolutionMaterial, SignedSectionVerificationMaterial,
- UnsignedSectionIdentityResolutionMaterial, UnsignedSectionVerificationMaterial,
- V1DiscoveryCryptoMaterial, V1,
-};
-#[cfg(feature = "alloc")]
-use crate::credential::ReferencedMatchedCredential;
use crate::credential::{
- DiscoveryCryptoMaterial, MatchableCredential, MatchedCredential, ProtocolVersion,
+ source::{CredentialSource, SliceCredentialSource},
+ v0::{V0DiscoveryCryptoMaterial, V0},
+ v1::{
+ MicExtendedSaltSectionIdentityResolutionMaterial,
+ MicExtendedSaltSectionVerificationMaterial, MicShortSaltSectionIdentityResolutionMaterial,
+ MicShortSaltSectionVerificationMaterial, SignedSectionIdentityResolutionMaterial,
+ SignedSectionVerificationMaterial, V1DiscoveryCryptoMaterial, V1,
+ },
+ DiscoveryMetadataCryptoMaterial, MatchableCredential, MatchedCredential, ProtocolVersion,
};
-use core::borrow::Borrow;
-use core::marker::PhantomData;
+use core::{borrow::Borrow, marker::PhantomData};
use crypto_provider::CryptoProvider;
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
extern crate alloc;
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
+use crate::credential::ReferencedMatchedCredential;
+#[cfg(any(feature = "alloc", test))]
use alloc::vec::Vec;
/// A collection of credentials to try when attempting to deserialize
@@ -171,17 +169,15 @@ where
/// refer to the "precalculated" crypto-material variants
/// for each protocol version.
pub(crate) mod precalculated_for_version {
- use crate::credential::v0::{
- PrecalculatedV0DiscoveryCryptoMaterial, V0DiscoveryCredential, V0,
+ use crate::credential::{
+ v0::{PrecalculatedV0DiscoveryCryptoMaterial, V0DiscoveryCredential, V0},
+ v1::{PrecalculatedV1DiscoveryCryptoMaterial, V1DiscoveryCredential, V1},
+ DiscoveryMetadataCryptoMaterial, ProtocolVersion,
};
- use crate::credential::v1::{
- PrecalculatedV1DiscoveryCryptoMaterial, V1DiscoveryCredential, V1,
- };
- use crate::credential::{DiscoveryCryptoMaterial, ProtocolVersion};
use crypto_provider::CryptoProvider;
pub trait MappingTrait<V: ProtocolVersion> {
- type Output: DiscoveryCryptoMaterial<V>;
+ type Output: DiscoveryMetadataCryptoMaterial<V>;
/// Provides pre-calculated crypto-material for the given
/// discovery credential.
fn precalculate<C: CryptoProvider>(
@@ -222,13 +218,12 @@ where
}
/// Iterator type for [`CachedCredentialSource`].
-pub struct CachedCredentialSourceIterator<
- 'a,
- V: ProtocolVersion + 'a,
- S: DiscoveryCredentialSource<'a, V> + 'a,
- const N: usize,
-> where
+pub struct CachedCredentialSourceIterator<'a, V, S, const N: usize>
+where
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
+ V: ProtocolVersion + 'a,
+ S: CredentialSource<'a, V> + 'a,
+ S::Crypto: Borrow<V::DiscoveryCredential>,
{
/// The current index of the (enumerated) elements that we're iterating over.
/// Always counts up at every iteration, and may lie outside of the range
@@ -244,10 +239,12 @@ pub struct CachedCredentialSourceIterator<
source_iterator: S::Iterator,
}
-impl<'a, V: ProtocolVersion + 'a, S: DiscoveryCredentialSource<'a, V> + 'a, const N: usize> Iterator
- for CachedCredentialSourceIterator<'a, V, S, N>
+impl<'a, V, S, const N: usize> Iterator for CachedCredentialSourceIterator<'a, V, S, N>
where
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
+ V: ProtocolVersion + 'a,
+ S: CredentialSource<'a, V> + 'a,
+ S::Crypto: Borrow<V::DiscoveryCredential>,
{
type Item = (PossiblyCachedDiscoveryCryptoMaterial<'a, V>, S::Matched);
fn next(&mut self) -> Option<Self::Item> {
@@ -272,7 +269,7 @@ where
}
}
-/// A [`CredentialSource`] which augments the externally-provided [`DiscoveryCredentialSource`] with
+/// A [`CredentialSource`] which augments the externally-provided [`CredentialSource`] with
/// a cache containing up to the specified number of pre-calculated credentials.
pub struct CachedCredentialSource<V: ProtocolVersion, S, const N: usize>
where
@@ -292,7 +289,8 @@ pub(crate) fn init_cache_from_source<'a, V: ProtocolVersion, S, const N: usize,
original: &'a S,
) -> [Option<PrecalculatedCryptoForProtocolVersion<V>>; N]
where
- S: DiscoveryCredentialSource<'a, V> + 'a,
+ S: CredentialSource<'a, V> + 'a,
+ S::Crypto: Borrow<V::DiscoveryCredential>,
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
{
let mut cache = [0u8; N].map(|_| None);
@@ -307,10 +305,10 @@ where
impl<'a, V: ProtocolVersion, S, const N: usize> CachedCredentialSource<V, S, N>
where
- S: DiscoveryCredentialSource<'a, V> + 'a,
+ S: CredentialSource<'a, V> + 'a,
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
{
- /// Constructs a [`CachedCredentialSource`] from the given [`DiscoveryCredentialSource`]
+ /// Constructs a [`CachedCredentialSource`] from the given [`CredentialSource`]
/// and the given (initial) cache contents, as constructed via the
/// [`init_cache_from_source`] helper function.
pub(crate) fn new(
@@ -354,7 +352,7 @@ where
}
}
-impl<'a, V: ProtocolVersion> DiscoveryCryptoMaterial<V>
+impl<'a, V: ProtocolVersion> DiscoveryMetadataCryptoMaterial<V>
for PossiblyCachedDiscoveryCryptoMaterial<'a, V>
where
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
@@ -368,7 +366,7 @@ where
}
impl<'a> V0DiscoveryCryptoMaterial for PossiblyCachedDiscoveryCryptoMaterial<'a, V0> {
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C> {
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C> {
match &self.wrapped {
PossiblyCachedDiscoveryCryptoMaterialKind::Discovery(x) => x.ldt_adv_cipher::<C>(),
PossiblyCachedDiscoveryCryptoMaterialKind::Precalculated(x) => x.ldt_adv_cipher::<C>(),
@@ -390,15 +388,28 @@ impl<'a> V1DiscoveryCryptoMaterial for PossiblyCachedDiscoveryCryptoMaterial<'a,
}
}
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial {
+ ) -> MicShortSaltSectionIdentityResolutionMaterial {
match &self.wrapped {
PossiblyCachedDiscoveryCryptoMaterialKind::Discovery(x) => {
- x.unsigned_identity_resolution_material::<C>()
+ x.mic_short_salt_identity_resolution_material::<C>()
}
PossiblyCachedDiscoveryCryptoMaterialKind::Precalculated(x) => {
- x.unsigned_identity_resolution_material::<C>()
+ x.mic_short_salt_identity_resolution_material::<C>()
+ }
+ }
+ }
+
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
+ match &self.wrapped {
+ PossiblyCachedDiscoveryCryptoMaterialKind::Discovery(x) => {
+ x.mic_extended_salt_identity_resolution_material::<C>()
+ }
+ PossiblyCachedDiscoveryCryptoMaterialKind::Precalculated(x) => {
+ x.mic_extended_salt_identity_resolution_material::<C>()
}
}
}
@@ -414,15 +425,28 @@ impl<'a> V1DiscoveryCryptoMaterial for PossiblyCachedDiscoveryCryptoMaterial<'a,
}
}
- fn unsigned_verification_material<C: CryptoProvider>(
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicShortSaltSectionVerificationMaterial {
+ match &self.wrapped {
+ PossiblyCachedDiscoveryCryptoMaterialKind::Discovery(x) => {
+ x.mic_short_salt_verification_material::<C>()
+ }
+ PossiblyCachedDiscoveryCryptoMaterialKind::Precalculated(x) => {
+ x.mic_short_salt_verification_material::<C>()
+ }
+ }
+ }
+
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial {
+ ) -> MicExtendedSaltSectionVerificationMaterial {
match &self.wrapped {
PossiblyCachedDiscoveryCryptoMaterialKind::Discovery(x) => {
- x.unsigned_verification_material::<C>()
+ x.mic_extended_salt_verification_material::<C>()
}
PossiblyCachedDiscoveryCryptoMaterialKind::Precalculated(x) => {
- x.unsigned_verification_material::<C>()
+ x.mic_extended_salt_verification_material::<C>()
}
}
}
@@ -432,11 +456,12 @@ impl<'a, V: ProtocolVersion, S, const N: usize> CredentialSource<'a, V>
for CachedCredentialSource<V, S, N>
where
Self: 'a,
- S: DiscoveryCredentialSource<'a, V> + 'a,
+ S: CredentialSource<'a, V> + 'a,
+ S::Crypto: Borrow<V::DiscoveryCredential>,
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
- PossiblyCachedDiscoveryCryptoMaterial<'a, V>: DiscoveryCryptoMaterial<V>,
+ PossiblyCachedDiscoveryCryptoMaterial<'a, V>: DiscoveryMetadataCryptoMaterial<V>,
{
- type Matched = <S as DiscoveryCredentialSource<'a, V>>::Matched;
+ type Matched = <S as CredentialSource<'a, V>>::Matched;
type Crypto = PossiblyCachedDiscoveryCryptoMaterial<'a, V>;
type Iterator = CachedCredentialSourceIterator<'a, V, S, N>;
@@ -454,7 +479,7 @@ where
/// can store an arbitrary amount of pre-calculated crypto-materials.
///
/// Requires `alloc` as a result of internally leveraging a `Vec`.
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
pub struct PrecalculatedOwnedCredentialSource<V: ProtocolVersion, M: MatchedCredential>
where
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
@@ -462,7 +487,7 @@ where
credentials: Vec<(PrecalculatedCryptoForProtocolVersion<V>, M)>,
}
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
impl<'a, V: ProtocolVersion + 'a, M: MatchedCredential + 'a>
PrecalculatedOwnedCredentialSource<V, M>
where
@@ -486,7 +511,7 @@ where
}
}
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
fn reference_crypto_and_match_data<C, M: MatchedCredential>(
pair_ref: &(C, M),
) -> (&C, ReferencedMatchedCredential<M>) {
@@ -494,13 +519,13 @@ fn reference_crypto_and_match_data<C, M: MatchedCredential>(
(c, m.into())
}
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
impl<'a, V: ProtocolVersion, M: MatchedCredential> CredentialSource<'a, V>
for PrecalculatedOwnedCredentialSource<V, M>
where
Self: 'a,
precalculated_for_version::Marker: precalculated_for_version::MappingTrait<V>,
- &'a PrecalculatedCryptoForProtocolVersion<V>: DiscoveryCryptoMaterial<V>,
+ &'a PrecalculatedCryptoForProtocolVersion<V>: DiscoveryMetadataCryptoMaterial<V>,
{
type Matched = ReferencedMatchedCredential<'a, M>;
type Crypto = &'a PrecalculatedCryptoForProtocolVersion<V>;
@@ -531,7 +556,7 @@ pub type CachedSliceCredentialBook<'a, M, const N0: usize, const N1: usize> =
CachedSliceCredentialSource<'a, V1, M, N1>,
>;
-#[cfg(feature = "alloc")]
+#[cfg(any(feature = "alloc", test))]
/// A credential-book which owns all of its (non-matched) credential data,
/// and maintains pre-calculated cryptographic information about all
/// stored credentials for speedy advertisement deserialization.
diff --git a/nearby/presence/np_adv/src/credential/matched.rs b/nearby/presence/np_adv/src/credential/matched.rs
new file mode 100644
index 0000000..90265d4
--- /dev/null
+++ b/nearby/presence/np_adv/src/credential/matched.rs
@@ -0,0 +1,318 @@
+// 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.
+
+//! Contains matched credential structs and traits which contain information about the credential
+//! which is passed back to the caller upon a successful decrypt and credential match.
+
+#[cfg(any(test, feature = "alloc"))]
+use alloc::vec::Vec;
+#[cfg(any(test, feature = "alloc"))]
+use crypto_provider::CryptoProvider;
+
+#[cfg(any(test, feature = "alloc"))]
+use crate::credential::metadata::{decrypt_metadata_with_nonce, encrypt_metadata};
+use crate::credential::{v0::V0, v1::V1, ProtocolVersion};
+use core::{convert::Infallible, fmt::Debug};
+use ldt_np_adv::V0IdentityToken;
+
+/// The portion of a credential's data to be bundled with the advertisement content it was used to
+/// decrypt. At a minimum, this includes any encrypted identity-specific metadata.
+///
+/// As it is `Debug` and `Eq`, implementors should not hold any cryptographic secrets to avoid
+/// accidental logging, timing side channels on comparison, etc, or should use custom impls of
+/// those traits rather than deriving them.
+///
+/// Instances of `MatchedCredential` may be cloned whenever advertisement content is
+/// successfully associated with a credential (see [`WithMatchedCredential`]). As a
+/// result, it's recommended to use matched-credentials which reference
+/// some underlying match-data, but don't necessarily own it.
+/// See [`ReferencedMatchedCredential`] for the most common case of shared references.
+pub trait MatchedCredential: Debug + PartialEq + Eq + Clone {
+ /// The type returned for successful calls to [`Self::fetch_encrypted_metadata`].
+ type EncryptedMetadata: AsRef<[u8]>;
+
+ /// The type of errors for [`Self::fetch_encrypted_metadata`].
+ type EncryptedMetadataFetchError: Debug;
+
+ /// Attempts to obtain the (AES-GCM)-encrypted metadata bytes for the credential,
+ /// with possible failure based on the availability of the underlying data (i.e:
+ /// failing disk reads.)
+ ///
+ /// If your implementation does not maintain any encrypted metadata for each credential,
+ /// you may simply return an empty byte-array from this method.
+ ///
+ /// If your method for obtaining metadata cannot fail, use
+ /// the `core::convert::Infallible` type for the error type
+ /// [`Self::EncryptedMetadataFetchError`].
+ fn fetch_encrypted_metadata(
+ &self,
+ ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError>;
+}
+
+/// [`MatchedCredential`] wrapper around a shared reference to a [`MatchedCredential`].
+/// This is done instead of providing a blanket impl of [`MatchedCredential`] for
+/// reference types to allow for downstream crates to impl [`MatchedCredential`] on
+/// specific reference types.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ReferencedMatchedCredential<'a, M: MatchedCredential> {
+ wrapped: &'a M,
+}
+
+impl<'a, M: MatchedCredential> From<&'a M> for ReferencedMatchedCredential<'a, M> {
+ fn from(wrapped: &'a M) -> Self {
+ Self { wrapped }
+ }
+}
+
+impl<'a, M: MatchedCredential> AsRef<M> for ReferencedMatchedCredential<'a, M> {
+ fn as_ref(&self) -> &M {
+ self.wrapped
+ }
+}
+
+impl<'a, M: MatchedCredential> MatchedCredential for ReferencedMatchedCredential<'a, M> {
+ type EncryptedMetadata = <M as MatchedCredential>::EncryptedMetadata;
+ type EncryptedMetadataFetchError = <M as MatchedCredential>::EncryptedMetadataFetchError;
+ fn fetch_encrypted_metadata(
+ &self,
+ ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
+ self.wrapped.fetch_encrypted_metadata()
+ }
+}
+
+/// A simple implementation of [`MatchedCredential`] where all match-data
+/// is contained in the encrypted metadata byte-field.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct MetadataMatchedCredential<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> {
+ encrypted_metadata: A,
+}
+
+#[cfg(any(test, feature = "alloc"))]
+impl MetadataMatchedCredential<Vec<u8>> {
+ /// Builds a [`MetadataMatchedCredential`] whose contents are given
+ /// as plaintext to be encrypted using AES-GCM against the given
+ /// broadcast crypto-material.
+ pub fn encrypt_from_plaintext<V, C>(
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ identity_token: V::IdentityToken,
+ plaintext_metadata: &[u8],
+ ) -> Self
+ where
+ V: ProtocolVersion,
+ C: CryptoProvider,
+ {
+ // TODO move this to identity provider
+ let encrypted_metadata = encrypt_metadata::<C, V>(hkdf, identity_token, plaintext_metadata);
+ Self { encrypted_metadata }
+ }
+}
+
+impl<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> MetadataMatchedCredential<A> {
+ /// Builds a new [`MetadataMatchedCredential`] with the given
+ /// encrypted metadata.
+ pub fn new(encrypted_metadata: A) -> Self {
+ Self { encrypted_metadata }
+ }
+}
+
+impl<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> MatchedCredential
+ for MetadataMatchedCredential<A>
+{
+ type EncryptedMetadata = A;
+ type EncryptedMetadataFetchError = Infallible;
+ fn fetch_encrypted_metadata(&self) -> Result<Self::EncryptedMetadata, Infallible> {
+ Ok(self.encrypted_metadata.clone())
+ }
+}
+
+/// Trivial implementation of [`MatchedCredential`] which consists of no match-data.
+/// Suitable for usage scenarios where the decoded advertisement contents matter,
+/// but not necessarily which devices generated the contents.
+///
+/// Attempting to obtain the encrypted metadata from this type of credential
+/// will always yield an empty byte-array.
+#[derive(Default, Debug, PartialEq, Eq, Clone)]
+pub struct EmptyMatchedCredential;
+
+impl MatchedCredential for EmptyMatchedCredential {
+ type EncryptedMetadata = [u8; 0];
+ type EncryptedMetadataFetchError = Infallible;
+ fn fetch_encrypted_metadata(
+ &self,
+ ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
+ Ok([0u8; 0])
+ }
+}
+
+#[cfg(any(test, feature = "devtools"))]
+/// A [`MatchedCredential`] which consists only of the `key_seed` in the crypto-material
+/// for the credential. Note that this is unique per-credential by construction,
+/// and so this provides natural match-data for credentials in settings where
+/// there may not be any other information available.
+///
+/// Since this matched-credential type contains cryptographic information mirroring
+/// a credential's crypto-material, this structure is not suitable for production
+/// usage outside of unit tests and dev-tools.
+///
+/// Additionally, note that the metadata on this particular kind of matched credential
+/// is deliberately made inaccessible. This is done because a key-seed representation
+/// is only suitable in very limited circumstances where no other meaningful
+/// identifying information is available, such as that which is contained in metadata.
+/// Attempting to obtain the encrypted metadata from this type of matched credential
+/// will always yield an empty byte-array.
+#[derive(Default, Debug, PartialEq, Eq, Clone)]
+pub struct KeySeedMatchedCredential {
+ key_seed: [u8; 32],
+}
+
+#[cfg(any(test, feature = "devtools"))]
+impl From<[u8; 32]> for KeySeedMatchedCredential {
+ fn from(key_seed: [u8; 32]) -> Self {
+ Self { key_seed }
+ }
+}
+#[cfg(any(test, feature = "devtools"))]
+impl From<KeySeedMatchedCredential> for [u8; 32] {
+ fn from(matched: KeySeedMatchedCredential) -> Self {
+ matched.key_seed
+ }
+}
+
+#[cfg(any(test, feature = "devtools"))]
+impl MatchedCredential for KeySeedMatchedCredential {
+ type EncryptedMetadata = [u8; 0];
+ type EncryptedMetadataFetchError = Infallible;
+ fn fetch_encrypted_metadata(
+ &self,
+ ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
+ Ok([0u8; 0])
+ }
+}
+
+/// Common trait to deserialized, decrypted V0 advs and V1 sections which
+/// exposes relevant data about matched identities.
+pub trait HasIdentityMatch {
+ /// The protocol version for which this advertisement
+ /// content has an identity-match.
+ type Version: ProtocolVersion;
+
+ /// Gets the decrypted plaintext version-specific
+ /// metadata key for the associated identity.
+ fn identity_token(&self) -> <Self::Version as ProtocolVersion>::IdentityToken;
+}
+
+impl HasIdentityMatch for V0IdentityToken {
+ type Version = V0;
+ fn identity_token(&self) -> Self {
+ *self
+ }
+}
+
+impl HasIdentityMatch for crate::extended::V1IdentityToken {
+ type Version = V1;
+ fn identity_token(&self) -> Self {
+ *self
+ }
+}
+
+#[cfg(any(test, feature = "alloc"))]
+/// Type for errors from [`WithMatchedCredential#decrypt_metadata`]
+#[derive(Debug)]
+pub enum MatchedMetadataDecryptionError<M: MatchedCredential> {
+ /// Retrieving the encrypted metadata failed for one reason
+ /// or another, so we didn't get a chance to try decryption.
+ RetrievalFailed(<M as MatchedCredential>::EncryptedMetadataFetchError),
+ /// The encrypted metadata could be retrieved, but it did
+ /// not successfully decrypt against the matched identity.
+ /// This could be an indication of data corruption or
+ /// of malformed crypto on the sender-side.
+ DecryptionFailed,
+}
+
+/// Decrypted advertisement content with the [MatchedCredential] from the credential that decrypted
+/// it, along with any other information which is relevant to the identity-match.
+#[derive(Debug, PartialEq, Eq)]
+pub struct WithMatchedCredential<M: MatchedCredential, T: HasIdentityMatch> {
+ matched: M,
+ /// The 12-byte metadata nonce as derived from the key-seed HKDF
+ /// to be used for decrypting the encrypted metadata in the attached
+ /// matched-credential.
+ metadata_nonce: [u8; 12],
+ contents: T,
+}
+
+impl<'a, M: MatchedCredential + Clone, T: HasIdentityMatch>
+ WithMatchedCredential<ReferencedMatchedCredential<'a, M>, T>
+{
+ /// Clones the referenced match-data to update this container
+ /// so that the match-data is owned, rather than borrowed.
+ pub fn clone_match_data(self) -> WithMatchedCredential<M, T> {
+ let matched = self.matched.as_ref().clone();
+ let metadata_nonce = self.metadata_nonce;
+ let contents = self.contents;
+
+ WithMatchedCredential { matched, metadata_nonce, contents }
+ }
+}
+
+impl<M: MatchedCredential, T: HasIdentityMatch> WithMatchedCredential<M, T> {
+ pub(crate) fn new(matched: M, metadata_nonce: [u8; 12], contents: T) -> Self {
+ Self { matched, metadata_nonce, contents }
+ }
+ /// Applies the given function to the wrapped contents, yielding
+ /// a new instance with the same matched-credential.
+ pub fn map<R: HasIdentityMatch>(
+ self,
+ mapping: impl FnOnce(T) -> R,
+ ) -> WithMatchedCredential<M, R> {
+ let contents = mapping(self.contents);
+ let matched = self.matched;
+ let metadata_nonce = self.metadata_nonce;
+ WithMatchedCredential { matched, metadata_nonce, contents }
+ }
+ /// Credential data for the credential that decrypted the content.
+ pub fn matched_credential(&self) -> &M {
+ &self.matched
+ }
+ /// The decrypted advertisement content.
+ pub fn contents(&self) -> &T {
+ &self.contents
+ }
+
+ #[cfg(any(test, feature = "alloc"))]
+ fn decrypt_metadata_from_fetch<C: CryptoProvider>(
+ &self,
+ encrypted_metadata: &[u8],
+ ) -> Result<Vec<u8>, MatchedMetadataDecryptionError<M>> {
+ decrypt_metadata_with_nonce::<C, T::Version>(
+ self.metadata_nonce,
+ self.contents.identity_token(),
+ encrypted_metadata,
+ )
+ .map_err(|_| MatchedMetadataDecryptionError::DecryptionFailed)
+ }
+
+ #[cfg(any(test, feature = "alloc"))]
+ /// Attempts to decrypt the encrypted metadata
+ /// associated with the matched credential
+ /// based on the details of the identity-match.
+ pub fn decrypt_metadata<C: CryptoProvider>(
+ &self,
+ ) -> Result<Vec<u8>, MatchedMetadataDecryptionError<M>> {
+ self.matched
+ .fetch_encrypted_metadata()
+ .map_err(|e| MatchedMetadataDecryptionError::RetrievalFailed(e))
+ .and_then(|x| Self::decrypt_metadata_from_fetch::<C>(self, x.as_ref()))
+ }
+}
diff --git a/nearby/presence/np_adv/src/credential/metadata/mod.rs b/nearby/presence/np_adv/src/credential/metadata/mod.rs
new file mode 100644
index 0000000..4e3a930
--- /dev/null
+++ b/nearby/presence/np_adv/src/credential/metadata/mod.rs
@@ -0,0 +1,79 @@
+// 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.
+
+//! A parking ground for the semi-dormant metadata code.
+//!
+//! Eventually, when we have a clearer idea of how metadat encryption and identity providers
+//! interact, this is likely to change aggressively.
+
+use alloc::vec::Vec;
+use crypto_provider::{
+ aead::{Aead, AeadInit},
+ aes::{self},
+ CryptoProvider,
+};
+
+use crate::credential::{MetadataDecryptionError, ProtocolVersion};
+
+#[cfg(test)]
+mod tests;
+
+/// Encrypts the given plaintext metadata bytes to allow that metadata
+/// to be shared with receiving devices.
+pub fn encrypt_metadata<C: CryptoProvider, V: ProtocolVersion>(
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ identity_token: V::IdentityToken,
+ plaintext_metadata: &[u8],
+) -> Vec<u8> {
+ let aead = <<C as CryptoProvider>::Aes128Gcm as AeadInit<aes::Aes128Key>>::new(
+ &V::extract_metadata_key::<C>(identity_token),
+ );
+ // No additional authenticated data for encrypted metadata.
+ aead.encrypt(plaintext_metadata, &[], &V::metadata_nonce_from_key_seed(hkdf))
+ .expect("Metadata encryption should be infallible")
+}
+
+/// Decrypt the given metadata using the given hkdf and version-specific
+/// identity token. Returns [`MetadataDecryptionError`] in the case that
+/// the decryption operation failed.
+///
+/// See also [decrypt_metadata_with_nonce].
+pub fn decrypt_metadata<C: CryptoProvider, V: ProtocolVersion>(
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ identity_token: V::IdentityToken,
+ encrypted_metadata: &[u8],
+) -> Result<Vec<u8>, MetadataDecryptionError> {
+ decrypt_metadata_with_nonce::<C, V>(
+ V::metadata_nonce_from_key_seed(hkdf),
+ identity_token,
+ encrypted_metadata,
+ )
+}
+
+/// Decrypt the given metadata using the given hkdf and version-specific
+/// identity token. Returns [`MetadataDecryptionError`] in the case that
+/// the decryption operation failed.
+///
+/// See also [decrypt_metadata].
+pub fn decrypt_metadata_with_nonce<C: CryptoProvider, V: ProtocolVersion>(
+ nonce: <C::Aes128Gcm as Aead>::Nonce,
+ identity_token: V::IdentityToken,
+ encrypted_metadata: &[u8],
+) -> Result<Vec<u8>, MetadataDecryptionError> {
+ // No additional authenticated data for encrypted metadata.
+ let metadata_key = V::extract_metadata_key::<C>(identity_token);
+ <<C as CryptoProvider>::Aes128Gcm as AeadInit<aes::Aes128Key>>::new(&metadata_key)
+ .decrypt(encrypted_metadata, &[], &nonce)
+ .map_err(|_| MetadataDecryptionError)
+}
diff --git a/nearby/presence/np_adv/src/credential/metadata/tests.rs b/nearby/presence/np_adv/src/credential/metadata/tests.rs
new file mode 100644
index 0000000..0409ebf
--- /dev/null
+++ b/nearby/presence/np_adv/src/credential/metadata/tests.rs
@@ -0,0 +1,95 @@
+// 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.
+
+use super::*;
+use crate::credential::v0::V0;
+use crate::credential::v1::V1;
+use crate::extended::V1IdentityToken;
+use alloc::vec;
+use crypto_provider_default::CryptoProviderImpl;
+use ldt_np_adv::V0IdentityToken;
+
+#[test]
+fn v0_metadata_decryption_works_same_metadata_key() {
+ let key_seed = [3u8; 32];
+ let identity_token = V0IdentityToken::from([5u8; 14]);
+
+ let metadata = vec![7u8; 42];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let encrypted_metadata =
+ encrypt_metadata::<CryptoProviderImpl, V0>(&hkdf, identity_token, &metadata);
+
+ let decryption_result =
+ decrypt_metadata::<CryptoProviderImpl, V0>(&hkdf, identity_token, &encrypted_metadata);
+ assert_eq!(decryption_result, Ok(metadata))
+}
+
+#[test]
+fn v1_metadata_decryption_works_same_metadata_key() {
+ let key_seed = [9u8; 32];
+ let identity_token = V1IdentityToken::from([2u8; 16]);
+
+ let metadata = vec![6u8; 51];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let encrypted_metadata =
+ encrypt_metadata::<CryptoProviderImpl, V1>(&hkdf, identity_token, &metadata);
+
+ let decryption_result =
+ decrypt_metadata::<CryptoProviderImpl, V1>(&hkdf, identity_token, &encrypted_metadata);
+ assert_eq!(decryption_result, Ok(metadata))
+}
+
+#[test]
+fn v0_metadata_decryption_fails_different_metadata_key() {
+ let key_seed = [3u8; 32];
+ let identity_token = V0IdentityToken::from([5u8; 14]);
+
+ let metadata = vec![7u8; 42];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let encrypted_metadata =
+ encrypt_metadata::<CryptoProviderImpl, V0>(&hkdf, identity_token, &metadata);
+
+ let decrypting_identity_token = V0IdentityToken::from([6u8; 14]);
+
+ let decryption_result = decrypt_metadata::<CryptoProviderImpl, V0>(
+ &hkdf,
+ decrypting_identity_token,
+ &encrypted_metadata,
+ );
+ assert_eq!(decryption_result, Err(MetadataDecryptionError))
+}
+
+#[test]
+fn v1_metadata_decryption_fails_different_metadata_key() {
+ let key_seed = [251u8; 32];
+ let identity_token = V1IdentityToken::from([127u8; 16]);
+
+ let metadata = vec![255u8; 42];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let encrypted_metadata =
+ encrypt_metadata::<CryptoProviderImpl, V1>(&hkdf, identity_token, &metadata);
+
+ let decrypting_identity_token = V1IdentityToken::from([249u8; 16]);
+
+ let decryption_result = decrypt_metadata::<CryptoProviderImpl, V1>(
+ &hkdf,
+ decrypting_identity_token,
+ &encrypted_metadata,
+ );
+ assert_eq!(decryption_result, Err(MetadataDecryptionError))
+}
diff --git a/nearby/presence/np_adv/src/credential/mod.rs b/nearby/presence/np_adv/src/credential/mod.rs
index 3cab51e..b61106d 100644
--- a/nearby/presence/np_adv/src/credential/mod.rs
+++ b/nearby/presence/np_adv/src/credential/mod.rs
@@ -18,25 +18,25 @@
//! efficiency gains with implementations tailored to suit (e.g. caching a few hot credentials
//! rather than reading from disk every time, etc).
-use crate::MetadataKey;
-
-use crate::credential::v0::{V0DiscoveryCredential, V0ProtocolVersion};
-
-use core::convert::Infallible;
+use crate::credential::matched::{MatchedCredential, ReferencedMatchedCredential};
use core::fmt::Debug;
-use crypto_provider::{CryptoProvider, CryptoRng};
+use crypto_provider::{aead::Aead, aes, CryptoProvider, FromCryptoRng};
pub mod book;
+pub mod matched;
pub mod source;
-#[cfg(test)]
-pub mod tests;
pub mod v0;
pub mod v1;
+#[cfg(any(test, feature = "alloc"))]
+pub mod metadata;
+
+#[cfg(test)]
+mod tests;
+
/// Information about a credential as supplied by the caller.
-#[derive(Clone)]
pub struct MatchableCredential<V: ProtocolVersion, M: MatchedCredential> {
- /// The discovery credential/cryptographic information associated
+ /// The cryptographic information associated
/// with this particular credential which is used for discovering
/// advertisements/advertisement sections generated via the
/// paired sender credential.
@@ -47,11 +47,6 @@ pub struct MatchableCredential<V: ProtocolVersion, M: MatchedCredential> {
}
impl<V: ProtocolVersion, M: MatchedCredential> MatchableCredential<V, M> {
- /// De-structures this credential into the pairing of a discovery
- /// credential and some matched credential data.
- pub fn into_pair(self) -> (V::DiscoveryCredential, M) {
- (self.discovery_credential, self.match_data)
- }
/// Views this credential as a (borrowed) discovery-credential
/// combined with some matched credential data
/// (which is copied - see documentation on [`MatchedCredential`])
@@ -60,176 +55,6 @@ impl<V: ProtocolVersion, M: MatchedCredential> MatchableCredential<V, M> {
}
}
-/// The portion of a credential's data to be bundled with the advertisement content it was used to
-/// decrypt. At a minimum, this includes any encrypted identity-specific metadata.
-///
-/// As it is `Debug` and `Eq`, implementors should not hold any cryptographic secrets to avoid
-/// accidental logging, timing side channels on comparison, etc, or should use custom impls of
-/// those traits rather than deriving them.
-///
-/// Instances of `MatchedCredential` may be cloned whenever advertisement content is
-/// successfully associated with a credential (see [`crate::WithMatchedCredential`]). As a
-/// result, it's recommended to use matched-credentials which reference
-/// some underlying match-data, but don't necessarily own it.
-/// See [`ReferencedMatchedCredential`] for the most common case of shared references.
-pub trait MatchedCredential: Debug + PartialEq + Eq + Clone {
- /// The type returned for successful calls to [`Self::fetch_encrypted_metadata`].
- type EncryptedMetadata: AsRef<[u8]>;
-
- /// The type of errors for [`Self::fetch_encrypted_metadata`].
- type EncryptedMetadataFetchError: Debug;
-
- /// Attempts to obtain the (AES-GCM)-encrypted metadata bytes for the credential,
- /// with possible failure based on the availability of the underlying data (i.e:
- /// failing disk reads.)
- ///
- /// If your implementation does not maintain any encrypted metadata for each credential,
- /// you may simply return an empty byte-array from this method.
- ///
- /// If your method for obtaining metadata cannot fail, use
- /// the `core::convert::Infallible` type for the error type
- /// [`Self::EncryptedMetadataFetchError`].
- fn fetch_encrypted_metadata(
- &self,
- ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError>;
-}
-
-/// [`MatchedCredential`] wrapper around a shared reference to a [`MatchedCredential`].
-/// This is done instead of providing a blanket impl of [`MatchedCredential`] for
-/// reference types to allow for downstream crates to impl [`MatchedCredential`] on
-/// specific reference types.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ReferencedMatchedCredential<'a, M: MatchedCredential> {
- wrapped: &'a M,
-}
-
-impl<'a, M: MatchedCredential> From<&'a M> for ReferencedMatchedCredential<'a, M> {
- fn from(wrapped: &'a M) -> Self {
- Self { wrapped }
- }
-}
-
-impl<'a, M: MatchedCredential> AsRef<M> for ReferencedMatchedCredential<'a, M> {
- fn as_ref(&self) -> &M {
- self.wrapped
- }
-}
-
-impl<'a, M: MatchedCredential> MatchedCredential for ReferencedMatchedCredential<'a, M> {
- type EncryptedMetadata = <M as MatchedCredential>::EncryptedMetadata;
- type EncryptedMetadataFetchError = <M as MatchedCredential>::EncryptedMetadataFetchError;
- fn fetch_encrypted_metadata(
- &self,
- ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
- self.wrapped.fetch_encrypted_metadata()
- }
-}
-
-/// A simple implementation of [`MatchedCredential`] where all match-data
-/// is contained in the encrypted metadata byte-field.
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct MetadataMatchedCredential<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> {
- encrypted_metadata: A,
-}
-
-#[cfg(any(test, feature = "alloc"))]
-impl MetadataMatchedCredential<alloc::vec::Vec<u8>> {
- /// Builds a [`MetadataMatchedCredential`] whose contents are given
- /// as plaintext to be encrypted using AES-GCM against the given
- /// broadcast crypto-material.
- pub fn encrypt_from_plaintext<V, B, C>(broadcast_cm: &B, plaintext_metadata: &[u8]) -> Self
- where
- V: ProtocolVersion,
- B: BroadcastCryptoMaterial<V>,
- C: CryptoProvider,
- {
- let encrypted_metadata = broadcast_cm.encrypt_metadata::<C>(plaintext_metadata);
- Self { encrypted_metadata }
- }
-}
-
-impl<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> MetadataMatchedCredential<A> {
- /// Builds a new [`MetadataMatchedCredential`] with the given
- /// encrypted metadata.
- pub fn new(encrypted_metadata: A) -> Self {
- Self { encrypted_metadata }
- }
-}
-
-impl<A: AsRef<[u8]> + Clone + Debug + PartialEq + Eq> MatchedCredential
- for MetadataMatchedCredential<A>
-{
- type EncryptedMetadata = A;
- type EncryptedMetadataFetchError = Infallible;
- fn fetch_encrypted_metadata(&self) -> Result<Self::EncryptedMetadata, Infallible> {
- Ok(self.encrypted_metadata.clone())
- }
-}
-
-/// Trivial implementation of [`MatchedCredential`] which consists of no match-data.
-/// Suitable for usage scenarios where the decoded advertisement contents matter,
-/// but not necessarily which devices generated the contents.
-///
-/// Attempting to obtain the encrypted metadata from this type of credential
-/// will always yield an empty byte-array.
-#[derive(Default, Debug, PartialEq, Eq, Clone)]
-pub struct EmptyMatchedCredential;
-
-impl MatchedCredential for EmptyMatchedCredential {
- type EncryptedMetadata = [u8; 0];
- type EncryptedMetadataFetchError = Infallible;
- fn fetch_encrypted_metadata(
- &self,
- ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
- Ok([0u8; 0])
- }
-}
-
-#[cfg(any(test, feature = "devtools"))]
-/// A [`MatchedCredential`] which consists only of the `key_seed` in the crypto-material
-/// for the credential. Note that this is unique per-credential by construction,
-/// and so this provides natural match-data for credentials in settings where
-/// there may not be any other information available.
-///
-/// Since this matched-credential type contains cryptographic information mirroring
-/// a credential's crypto-material, this structure is not suitable for production
-/// usage outside of unit tests and dev-tools.
-///
-/// Additionally, note that the metadata on this particular kind of matched credential
-/// is deliberately made inaccessible. This is done because a key-seed representation
-/// is only suitable in very limited circumstances where no other meaningful
-/// identifying information is available, such as that which is contained in metadata.
-/// Attempting to obtain the encrypted metadata from this type of matched credential
-/// will always yield an empty byte-array.
-#[derive(Default, Debug, PartialEq, Eq, Clone)]
-pub struct KeySeedMatchedCredential {
- key_seed: [u8; 32],
-}
-
-#[cfg(any(test, feature = "devtools"))]
-impl From<[u8; 32]> for KeySeedMatchedCredential {
- fn from(key_seed: [u8; 32]) -> Self {
- Self { key_seed }
- }
-}
-#[cfg(any(test, feature = "devtools"))]
-impl From<KeySeedMatchedCredential> for [u8; 32] {
- fn from(matched: KeySeedMatchedCredential) -> Self {
- matched.key_seed
- }
-}
-
-#[cfg(any(test, feature = "devtools"))]
-impl MatchedCredential for KeySeedMatchedCredential {
- type EncryptedMetadata = [u8; 0];
- type EncryptedMetadataFetchError = Infallible;
- fn fetch_encrypted_metadata(
- &self,
- ) -> Result<Self::EncryptedMetadata, Self::EncryptedMetadataFetchError> {
- Ok([0u8; 0])
- }
-}
-
/// Error returned when metadata decryption fails.
#[derive(Debug, Eq, PartialEq)]
pub struct MetadataDecryptionError;
@@ -248,43 +73,24 @@ pub trait ProtocolVersion: protocol_version_seal::ProtocolVersionSeal {
/// is the minimal amount of cryptographic materials that we need
/// in order to discover advertisements/sections which make
/// use of the sender-paired version of the credential.
- type DiscoveryCredential: DiscoveryCryptoMaterial<Self> + Clone;
+ type DiscoveryCredential: DiscoveryMetadataCryptoMaterial<Self> + Clone;
- /// The native-length metadata key for this protocol version
- /// [i.e: if V0, a 14-byte metadata key, or if V1, a 16-byte
- /// metadata key.]
- type MetadataKey: Clone + AsRef<[u8]>;
+ /// The native-length identity token for this protocol version
+ /// [i.e: if V0, a 14-byte identity token, or if V1, a 16-byte
+ /// identity token.]
+ type IdentityToken: Clone + AsRef<[u8]> + FromCryptoRng;
/// Computes the metadata nonce for this version from the given key-seed.
- fn metadata_nonce_from_key_seed<C: CryptoProvider>(key_seed: &[u8; 32]) -> [u8; 12];
+ fn metadata_nonce_from_key_seed<C: CryptoProvider>(
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> <C::Aes128Gcm as Aead>::Nonce;
- /// Expands the passed metadata key (if needed) to a 16-byte metadata key
+ // TODO this should be done by the identity provider that owns the corresponding credential
+ /// Transforms the passed metadata key (if needed) to a 16-byte metadata key
/// which may be used for metadata encryption/decryption
- fn expand_metadata_key<C: CryptoProvider>(metadata_key: Self::MetadataKey) -> MetadataKey;
-
- /// Generates a random metadata key using the given cryptographically-secure Rng
- fn gen_random_metadata_key<R: CryptoRng>(rng: &mut R) -> Self::MetadataKey;
-
- #[cfg(any(test, feature = "alloc"))]
- /// Decrypt the given metadata using the given metadata nonce and version-specific
- /// metadata key. Returns [`MetadataDecryptionError`] in the case that
- /// the decryption operation failed.
- fn decrypt_metadata<C: CryptoProvider>(
- metadata_nonce: [u8; 12],
- metadata_key: Self::MetadataKey,
- encrypted_metadata: &[u8],
- ) -> Result<alloc::vec::Vec<u8>, MetadataDecryptionError> {
- use crypto_provider::{
- aead::{Aead, AeadInit},
- aes::Aes128Key,
- };
-
- let metadata_key = Self::expand_metadata_key::<C>(metadata_key);
- let metadata_key = Aes128Key::from(metadata_key.0);
- let aead = <<C as CryptoProvider>::Aes128Gcm as AeadInit<Aes128Key>>::new(&metadata_key);
- // No additional authenticated data for encrypted metadata.
- aead.decrypt(encrypted_metadata, &[], &metadata_nonce).map_err(|_| MetadataDecryptionError)
- }
+ fn extract_metadata_key<C: CryptoProvider>(
+ identity_token: Self::IdentityToken,
+ ) -> aes::Aes128Key;
}
/// Trait for structures which provide cryptographic
@@ -292,101 +98,8 @@ pub trait ProtocolVersion: protocol_version_seal::ProtocolVersionSeal {
/// See [`crate::credential::v0::V0DiscoveryCryptoMaterial`]
/// and [`crate::credential::v1::V1DiscoveryCryptoMaterial`]
/// for V0 and V1 specializations.
-pub trait DiscoveryCryptoMaterial<V: ProtocolVersion> {
+pub trait DiscoveryMetadataCryptoMaterial<V: ProtocolVersion> {
/// Constructs or copies the metadata nonce used for decryption of associated credential
/// metadata for the identity represented via this crypto material.
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12];
}
-
-/// Cryptographic materials necessary for broadcasting encrypted
-/// advertisement contents with the given protocol version.
-pub trait BroadcastCryptoMaterial<V: ProtocolVersion> {
- /// Yields a copy of the key seed to be used to derive other key materials used
- /// in the encryption of broadcasted advertisement contents.
- fn key_seed(&self) -> [u8; 32];
-
- /// Yields a copy of the metadata-key (size dependent on protocol version)
- /// to tag advertisement contents sent with this broadcast crypto-material.
- fn metadata_key(&self) -> V::MetadataKey;
-
- /// Yields the 16-byte expanded metadata key, suitable for metadata encryption.
- fn expanded_metadata_key<C: CryptoProvider>(&self) -> MetadataKey {
- V::expand_metadata_key::<C>(self.metadata_key())
- }
-
- /// Constructs the metadata nonce used for encryption of associated credential
- /// metadata for the identity represented via this crypto material.
- fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
- V::metadata_nonce_from_key_seed::<C>(&self.key_seed())
- }
-
- /// Derives a V0 discovery credential from this V0 broadcast crypto-material
- /// which may be used to discover v0 advertisements broadcasted with this credential.`
- fn derive_v0_discovery_credential<C: CryptoProvider>(&self) -> V0DiscoveryCredential
- where
- V: V0ProtocolVersion,
- {
- let key_seed = self.key_seed();
- let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
- let metadata_key_hmac =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(self.metadata_key().as_ref());
- V0DiscoveryCredential::new(key_seed, metadata_key_hmac)
- }
-
- #[cfg(any(test, feature = "alloc"))]
- /// Encrypts the given plaintext metadata bytes to allow that metadata
- /// to be shared with receiving devices.
- fn encrypt_metadata<C: CryptoProvider>(
- &self,
- plaintext_metadata: &[u8],
- ) -> alloc::vec::Vec<u8> {
- use crypto_provider::{
- aead::{Aead, AeadInit},
- aes::Aes128Key,
- };
- let plaintext_metadata_key = self.expanded_metadata_key::<C>();
- let plaintext_metadata_key = Aes128Key::from(plaintext_metadata_key.0);
-
- let aead =
- <<C as CryptoProvider>::Aes128Gcm as AeadInit<Aes128Key>>::new(&plaintext_metadata_key);
- // No additional authenticated data for encrypted metadata.
- aead.encrypt(plaintext_metadata, &[], &self.metadata_nonce::<C>())
- .expect("Metadata encryption should be infallible")
- }
-}
-
-/// Concrete implementation of [`BroadcastCryptoMaterial<V>`] for
-/// a particular protocol version which keeps the key seed
-/// and the metadata key contiguous in memory.
-///
-/// Broadcast crypto-material specified in this way will only
-/// be usable for (unsigned) advertisement content broadcasts
-/// in the given protocol version.
-///
-/// For more flexible expression of broadcast credentials,
-/// feel free to directly implement one or more of the
-/// [`BroadcastCryptoMaterial`] and/or
-/// [`crate::credential::v1::SignedBroadcastCryptoMaterial`]
-/// traits on your own struct, dependent on the details
-/// of your own broadcast credentials.
-pub struct SimpleBroadcastCryptoMaterial<V: ProtocolVersion> {
- key_seed: [u8; 32],
- metadata_key: V::MetadataKey,
-}
-
-impl<V: ProtocolVersion> SimpleBroadcastCryptoMaterial<V> {
- /// Builds some simple broadcast crypto-materials out of
- /// the provided key-seed and version-specific metadata-key.
- pub fn new(key_seed: [u8; 32], metadata_key: V::MetadataKey) -> Self {
- Self { key_seed, metadata_key }
- }
-}
-
-impl<V: ProtocolVersion> BroadcastCryptoMaterial<V> for SimpleBroadcastCryptoMaterial<V> {
- fn key_seed(&self) -> [u8; 32] {
- self.key_seed
- }
- fn metadata_key(&self) -> V::MetadataKey {
- self.metadata_key.clone()
- }
-}
diff --git a/nearby/presence/np_adv/src/credential/source.rs b/nearby/presence/np_adv/src/credential/source.rs
index 709bbd6..f22ed97 100644
--- a/nearby/presence/np_adv/src/credential/source.rs
+++ b/nearby/presence/np_adv/src/credential/source.rs
@@ -16,59 +16,17 @@
//! credentials for discovering advertisements/advertisement
//! sections for a _particular_ protocol version.
-use crate::credential::{
- DiscoveryCryptoMaterial, MatchableCredential, MatchedCredential, ProtocolVersion,
- ReferencedMatchedCredential,
-};
-use core::borrow::Borrow;
-
-/// Specialized version of the [`CredentialSource`] trait for
-/// credential-sources which provide discovery credentials
-/// for a specific protocol version.
-///
-/// If you want ready-made structures which can provide
-/// credentials for both V0 and V1 protocol versions,
-/// see [`crate::credential::book::CredentialBook`]
-/// and [`crate::credential::book::CredentialBookBuilder`] instead.
-///
-/// It's preferred to use this kind of credential-source
-/// in client code, if possible, and then lift to a
-/// [`CredentialSource`] using [`AsCredentialSource`]
-/// instead of implementing [`CredentialSource`] directly,
-/// since it's better to trust this crate to handle
-/// the details of what's in [`DiscoveryCryptoMaterial`]s
-/// for specific protocol versions.
-pub trait DiscoveryCredentialSource<'a, V: ProtocolVersion>
-where
- Self: 'a,
-{
- /// The kind of data yielded to the caller upon a successful
- /// identity-match.
- type Matched: MatchedCredential;
-
- /// The kind of crypto-material yielded from the wrapped
- /// iterator, which allows borrowing a discovery credential.
- type Crypto: DiscoveryCryptoMaterial<V> + Borrow<V::DiscoveryCredential>;
-
- /// The iterator type produced which emits credentials.
- /// This is a lending iterator which may borrow things from `self`.
- type Iterator: Iterator<Item = (Self::Crypto, Self::Matched)>;
-
- /// Iterate over the available credentials
- fn iter(&'a self) -> Self::Iterator;
-}
+use crate::credential::matched::{MatchedCredential, ReferencedMatchedCredential};
+use crate::credential::{DiscoveryMetadataCryptoMaterial, MatchableCredential, ProtocolVersion};
/// A source of credentials for a particular protocol version,
-/// utilizing any [`DiscoveryCryptoMaterial`] which is usable
+/// utilizing any [`DiscoveryMetadataCryptoMaterial`] which is usable
/// for discovering advertisements in that protocol version.
///
/// This trait is largely leveraged as a tool for building
/// new kinds of [`crate::credential::book::CredentialBook`]s
/// via the [`crate::credential::book::CredentialBookFromSources`]
-/// wrapper. It differs from the [`DiscoveryCredentialSource`]
-/// trait in that the crypto-materials do not have to be
-/// discovery credentials, and can instead be some pre-calculated
-/// crypto-materials.
+/// wrapper.
///
/// See [`crate::credential::book::CachedCredentialSource`]
/// for an example of this pattern.
@@ -82,7 +40,7 @@ where
/// The kind of crypto-material yielded from the wrapped
/// iterator.
- type Crypto: DiscoveryCryptoMaterial<V>;
+ type Crypto: DiscoveryMetadataCryptoMaterial<V>;
/// The iterator type produced which emits credentials.
/// This is a lending iterator which may borrow things from `self`.
@@ -92,27 +50,7 @@ where
fn iter(&'a self) -> Self::Iterator;
}
-// Note: This is needed to get around coherence problems
-// with the [`CredentialSource`] trait's relationship
-// with [`DiscoveryCredentialSource`] if it were declared
-// as a sub-trait (i.e: conflicting impls)
-/// Wrapper which turns any [`DiscoveryCredentialSource`]
-/// into a [`CredentialSource`].
-pub struct AsCredentialSource<S>(pub S);
-
-impl<'a, V: ProtocolVersion, S: DiscoveryCredentialSource<'a, V>> CredentialSource<'a, V>
- for AsCredentialSource<S>
-{
- type Matched = <S as DiscoveryCredentialSource<'a, V>>::Matched;
- type Crypto = <S as DiscoveryCredentialSource<'a, V>>::Crypto;
- type Iterator = <S as DiscoveryCredentialSource<'a, V>>::Iterator;
-
- fn iter(&'a self) -> Self::Iterator {
- self.0.iter()
- }
-}
-
-/// A simple [`DiscoveryCredentialSource`] which iterates over a provided slice of credentials
+/// A simple [`CredentialSource`] which iterates over a provided slice of credentials
pub struct SliceCredentialSource<'c, V: ProtocolVersion, M: MatchedCredential> {
credentials: &'c [MatchableCredential<V, M>],
}
@@ -124,12 +62,12 @@ impl<'c, V: ProtocolVersion, M: MatchedCredential> SliceCredentialSource<'c, V,
}
}
-impl<'a, 'b, V: ProtocolVersion, M: MatchedCredential> DiscoveryCredentialSource<'a, V>
+impl<'a, 'b, V: ProtocolVersion, M: MatchedCredential> CredentialSource<'a, V>
for SliceCredentialSource<'b, V, M>
where
'b: 'a,
Self: 'b,
- &'a <V as ProtocolVersion>::DiscoveryCredential: DiscoveryCryptoMaterial<V>,
+ &'a <V as ProtocolVersion>::DiscoveryCredential: DiscoveryMetadataCryptoMaterial<V>,
{
type Matched = ReferencedMatchedCredential<'a, M>;
type Crypto = &'a V::DiscoveryCredential;
diff --git a/nearby/presence/np_adv/src/credential/tests.rs b/nearby/presence/np_adv/src/credential/tests.rs
index 8b12bfc..7e92934 100644
--- a/nearby/presence/np_adv/src/credential/tests.rs
+++ b/nearby/presence/np_adv/src/credential/tests.rs
@@ -15,38 +15,38 @@
extern crate alloc;
+use crate::credential::matched::{
+ EmptyMatchedCredential, KeySeedMatchedCredential, ReferencedMatchedCredential,
+};
+use crate::credential::v1::MicSectionVerificationMaterial;
use crate::credential::{
book::{
init_cache_from_source, CachedCredentialSource, PossiblyCachedDiscoveryCryptoMaterialKind,
},
source::{CredentialSource, SliceCredentialSource},
v0::{V0DiscoveryCredential, V0},
- v1::{
- SignedBroadcastCryptoMaterial, SimpleSignedBroadcastCryptoMaterial, V1DiscoveryCredential,
- V1DiscoveryCryptoMaterial, V1,
- },
- BroadcastCryptoMaterial, EmptyMatchedCredential, KeySeedMatchedCredential, MatchableCredential,
- MetadataDecryptionError, ProtocolVersion, ReferencedMatchedCredential,
- SimpleBroadcastCryptoMaterial,
+ v1::{V1BroadcastCredential, V1DiscoveryCredential, V1DiscoveryCryptoMaterial, V1},
+ MatchableCredential,
};
-use crate::legacy::ShortMetadataKey;
-use crate::MetadataKey;
-use alloc::{vec, vec::Vec};
+use crate::extended::{V1IdentityToken, V1_IDENTITY_TOKEN_LEN};
+use alloc::vec::Vec;
+use crypto_provider::{ed25519, CryptoProvider};
use crypto_provider_default::CryptoProviderImpl;
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
+
fn get_zeroed_v0_discovery_credential() -> V0DiscoveryCredential {
V0DiscoveryCredential::new([0u8; 32], [0u8; 32])
}
fn get_constant_packed_v1_discovery_credential(value: u8) -> V1DiscoveryCredential {
- let key_pair = np_ed25519::KeyPair::<CryptoProviderImpl>::generate();
- SimpleSignedBroadcastCryptoMaterial::new(
+ V1BroadcastCredential::new(
[value; 32],
- MetadataKey([value; 16]),
+ V1IdentityToken::from([value; V1_IDENTITY_TOKEN_LEN]),
// NOTE: This winds up being unused in these test cases
- key_pair.private_key(),
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
)
- .derive_v1_discovery_credential::<CryptoProviderImpl>()
+ .derive_discovery_credential::<CryptoProviderImpl>()
}
#[test]
@@ -71,9 +71,11 @@ fn cached_credential_source_keeps_same_entries_as_original() {
.iter()
.map(|cred| {
(
- cred.discovery_credential
- .unsigned_verification_material::<CryptoProviderImpl>()
- .mic_hmac_key,
+ *cred
+ .discovery_credential
+ .mic_extended_salt_verification_material::<CryptoProviderImpl>()
+ .mic_hmac_key()
+ .as_bytes(),
ReferencedMatchedCredential::from(&cred.match_data),
)
})
@@ -82,7 +84,10 @@ fn cached_credential_source_keeps_same_entries_as_original() {
.iter()
.map(|(crypto_material, match_data)| {
(
- crypto_material.unsigned_verification_material::<CryptoProviderImpl>().mic_hmac_key,
+ *crypto_material
+ .mic_extended_salt_verification_material::<CryptoProviderImpl>()
+ .mic_hmac_key()
+ .as_bytes(),
match_data,
)
})
@@ -119,90 +124,13 @@ fn cached_credential_source_has_requested_cache_size() {
}
}
-#[test]
-fn v0_metadata_decryption_works_same_metadata_key() {
- let key_seed = [3u8; 32];
- let metadata_key = ShortMetadataKey([5u8; 14]);
-
- let metadata = vec![7u8; 42];
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
-
- let encrypted_metadata = broadcast_cm.encrypt_metadata::<CryptoProviderImpl>(&metadata);
-
- let metadata_nonce = broadcast_cm.metadata_nonce::<CryptoProviderImpl>();
-
- let decryption_result = V0::decrypt_metadata::<CryptoProviderImpl>(
- metadata_nonce,
- metadata_key,
- &encrypted_metadata,
- );
- assert_eq!(decryption_result, Ok(metadata))
-}
-
-#[test]
-fn v1_metadata_decryption_works_same_metadata_key() {
- let key_seed = [9u8; 32];
- let metadata_key = MetadataKey([2u8; 16]);
-
- let metadata = vec![6u8; 51];
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
-
- let encrypted_metadata = broadcast_cm.encrypt_metadata::<CryptoProviderImpl>(&metadata);
-
- let metadata_nonce = broadcast_cm.metadata_nonce::<CryptoProviderImpl>();
-
- let decryption_result = V1::decrypt_metadata::<CryptoProviderImpl>(
- metadata_nonce,
- metadata_key,
- &encrypted_metadata,
- );
- assert_eq!(decryption_result, Ok(metadata))
-}
+mod coverage_gaming {
+ use crate::credential::MetadataDecryptionError;
+ use alloc::format;
-#[test]
-fn v0_metadata_decryption_fails_different_metadata_key() {
- let key_seed = [3u8; 32];
- let encrypting_metadata_key = ShortMetadataKey([5u8; 14]);
-
- let metadata = vec![7u8; 42];
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, encrypting_metadata_key);
-
- let encrypted_metadata = broadcast_cm.encrypt_metadata::<CryptoProviderImpl>(&metadata);
-
- let metadata_nonce = broadcast_cm.metadata_nonce::<CryptoProviderImpl>();
-
- let decrypting_metadata_key = ShortMetadataKey([6u8; 14]);
-
- let decryption_result = V0::decrypt_metadata::<CryptoProviderImpl>(
- metadata_nonce,
- decrypting_metadata_key,
- &encrypted_metadata,
- );
- assert_eq!(decryption_result, Err(MetadataDecryptionError))
-}
-
-#[test]
-fn v1_metadata_decryption_fails_different_metadata_key() {
- let key_seed = [251u8; 32];
- let encrypting_metadata_key = MetadataKey([127u8; 16]);
-
- let metadata = vec![255u8; 42];
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, encrypting_metadata_key);
-
- let encrypted_metadata = broadcast_cm.encrypt_metadata::<CryptoProviderImpl>(&metadata);
-
- let metadata_nonce = broadcast_cm.metadata_nonce::<CryptoProviderImpl>();
-
- let decrypting_metadata_key = MetadataKey([249u8; 16]);
-
- let decryption_result = V1::decrypt_metadata::<CryptoProviderImpl>(
- metadata_nonce,
- decrypting_metadata_key,
- &encrypted_metadata,
- );
- assert_eq!(decryption_result, Err(MetadataDecryptionError))
+ #[test]
+ fn metadata_decryption_error_debug() {
+ let err = MetadataDecryptionError;
+ let _ = format!("{:?}", err);
+ }
}
diff --git a/nearby/presence/np_adv/src/credential/v0.rs b/nearby/presence/np_adv/src/credential/v0.rs
index c89909d..84ff768 100644
--- a/nearby/presence/np_adv/src/credential/v0.rs
+++ b/nearby/presence/np_adv/src/credential/v0.rs
@@ -13,39 +13,42 @@
// limitations under the License.
//! Cryptographic materials for v0 advertisement-format credentials.
-use crate::credential::{protocol_version_seal, DiscoveryCryptoMaterial, ProtocolVersion};
-use crate::legacy::ShortMetadataKey;
-use crate::MetadataKey;
-use crypto_provider::{CryptoProvider, CryptoRng};
+use crate::credential::{protocol_version_seal, DiscoveryMetadataCryptoMaterial, ProtocolVersion};
+use crypto_provider::{aead::Aead, aes, aes::ctr, CryptoProvider};
+use ldt_np_adv::V0IdentityToken;
+use np_hkdf::NpKeySeedHkdf;
/// Cryptographic information about a particular V0 discovery credential
/// necessary to match and decrypt encrypted V0 advertisements.
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct V0DiscoveryCredential {
- key_seed: [u8; 32],
- legacy_metadata_key_hmac: [u8; 32],
+ /// The 32-byte key-seed used for generating other key material.
+ pub key_seed: [u8; 32],
+
+ /// The (LDT-variant) HMAC of the identity token.
+ pub expected_identity_token_hmac: [u8; 32],
}
impl V0DiscoveryCredential {
/// Construct an [V0DiscoveryCredential] from the provided identity data.
- pub fn new(key_seed: [u8; 32], legacy_metadata_key_hmac: [u8; 32]) -> Self {
- Self { key_seed, legacy_metadata_key_hmac }
+ pub fn new(key_seed: [u8; 32], expected_identity_token_hmac: [u8; 32]) -> Self {
+ Self { key_seed, expected_identity_token_hmac }
}
}
-impl DiscoveryCryptoMaterial<V0> for V0DiscoveryCredential {
+impl DiscoveryMetadataCryptoMaterial<V0> for V0DiscoveryCredential {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
- V0::metadata_nonce_from_key_seed::<C>(&self.key_seed)
+ np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed).v0_metadata_nonce()
}
}
impl V0DiscoveryCryptoMaterial for V0DiscoveryCredential {
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C> {
- let hkdf = np_hkdf::NpKeySeedHkdf::new(&self.key_seed);
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C> {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
ldt_np_adv::build_np_adv_decrypter(
- &hkdf.legacy_ldt_key(),
- self.legacy_metadata_key_hmac,
- hkdf.legacy_metadata_key_hmac_key(),
+ &hkdf.v0_ldt_key(),
+ self.expected_identity_token_hmac,
+ hkdf.v0_identity_token_hmac_key(),
)
}
}
@@ -58,17 +61,17 @@ impl protocol_version_seal::ProtocolVersionSeal for V0 {}
impl ProtocolVersion for V0 {
type DiscoveryCredential = V0DiscoveryCredential;
- type MetadataKey = ShortMetadataKey;
+ type IdentityToken = V0IdentityToken;
- fn metadata_nonce_from_key_seed<C: CryptoProvider>(key_seed: &[u8; 32]) -> [u8; 12] {
- let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(key_seed);
- hkdf.legacy_metadata_nonce()
- }
- fn expand_metadata_key<C: CryptoProvider>(metadata_key: ShortMetadataKey) -> MetadataKey {
- metadata_key.expand::<C>()
+ fn metadata_nonce_from_key_seed<C: CryptoProvider>(
+ hkdf: &NpKeySeedHkdf<C>,
+ ) -> <C::Aes128Gcm as Aead>::Nonce {
+ hkdf.v0_metadata_nonce()
}
- fn gen_random_metadata_key<R: CryptoRng>(rng: &mut R) -> ShortMetadataKey {
- ShortMetadataKey(rng.gen())
+
+ // TODO should be IdP specific
+ fn extract_metadata_key<C: CryptoProvider>(metadata_key: V0IdentityToken) -> aes::Aes128Key {
+ np_hkdf::v0_metadata_expanded_key::<C>(&metadata_key.bytes()).into()
}
}
@@ -83,18 +86,18 @@ impl V0ProtocolVersion for V0 {}
/// be stored in implementors of this trait.
// Space-time tradeoffs:
// - LDT keys (64b) take about 1.4us.
-pub trait V0DiscoveryCryptoMaterial: DiscoveryCryptoMaterial<V0> {
+pub trait V0DiscoveryCryptoMaterial: DiscoveryMetadataCryptoMaterial<V0> {
/// Returns an LDT NP advertisement cipher built with the provided `Aes`
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C>;
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C>;
}
/// [`V0DiscoveryCryptoMaterial`] that minimizes CPU time when providing key material at
/// the expense of occupied memory.
pub struct PrecalculatedV0DiscoveryCryptoMaterial {
pub(crate) legacy_ldt_key: ldt::LdtKey<xts_aes::XtsAes128Key>,
- pub(crate) legacy_metadata_key_hmac: [u8; 32],
- pub(crate) legacy_metadata_key_hmac_key: [u8; 32],
- pub(crate) metadata_nonce: [u8; 12],
+ pub(crate) legacy_identity_token_hmac: [u8; 32],
+ pub(crate) legacy_identity_token_hmac_key: [u8; 32],
+ pub(crate) metadata_nonce: ctr::AesCtrNonce,
}
impl PrecalculatedV0DiscoveryCryptoMaterial {
@@ -102,26 +105,26 @@ impl PrecalculatedV0DiscoveryCryptoMaterial {
pub(crate) fn new<C: CryptoProvider>(discovery_credential: &V0DiscoveryCredential) -> Self {
let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&discovery_credential.key_seed);
Self {
- legacy_ldt_key: hkdf.legacy_ldt_key(),
- legacy_metadata_key_hmac: discovery_credential.legacy_metadata_key_hmac,
- legacy_metadata_key_hmac_key: *hkdf.legacy_metadata_key_hmac_key().as_bytes(),
- metadata_nonce: hkdf.legacy_metadata_nonce(),
+ legacy_ldt_key: hkdf.v0_ldt_key(),
+ legacy_identity_token_hmac: discovery_credential.expected_identity_token_hmac,
+ legacy_identity_token_hmac_key: *hkdf.v0_identity_token_hmac_key().as_bytes(),
+ metadata_nonce: hkdf.v0_metadata_nonce(),
}
}
}
-impl DiscoveryCryptoMaterial<V0> for PrecalculatedV0DiscoveryCryptoMaterial {
+impl DiscoveryMetadataCryptoMaterial<V0> for PrecalculatedV0DiscoveryCryptoMaterial {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
self.metadata_nonce
}
}
impl V0DiscoveryCryptoMaterial for PrecalculatedV0DiscoveryCryptoMaterial {
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C> {
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C> {
ldt_np_adv::build_np_adv_decrypter(
&self.legacy_ldt_key,
- self.legacy_metadata_key_hmac,
- self.legacy_metadata_key_hmac_key.into(),
+ self.legacy_identity_token_hmac,
+ self.legacy_identity_token_hmac_key.into(),
)
}
}
@@ -129,26 +132,65 @@ impl V0DiscoveryCryptoMaterial for PrecalculatedV0DiscoveryCryptoMaterial {
// Implementations for reference types -- we don't provide a blanket impl for references
// due to the potential to conflict with downstream crates' implementations.
-impl<'a> DiscoveryCryptoMaterial<V0> for &'a V0DiscoveryCredential {
+impl<'a> DiscoveryMetadataCryptoMaterial<V0> for &'a V0DiscoveryCredential {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
(*self).metadata_nonce::<C>()
}
}
impl<'a> V0DiscoveryCryptoMaterial for &'a V0DiscoveryCredential {
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C> {
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C> {
(*self).ldt_adv_cipher::<C>()
}
}
-impl<'a> DiscoveryCryptoMaterial<V0> for &'a PrecalculatedV0DiscoveryCryptoMaterial {
+impl<'a> DiscoveryMetadataCryptoMaterial<V0> for &'a PrecalculatedV0DiscoveryCryptoMaterial {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
(*self).metadata_nonce::<C>()
}
}
impl<'a> V0DiscoveryCryptoMaterial for &'a PrecalculatedV0DiscoveryCryptoMaterial {
- fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C> {
+ fn ldt_adv_cipher<C: CryptoProvider>(&self) -> ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C> {
(*self).ldt_adv_cipher::<C>()
}
}
+
+/// Crypto material for creating V1 advertisements.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct V0BroadcastCredential {
+ /// The 32-byte key-seed used for generating other key material.
+ pub key_seed: [u8; 32],
+
+ /// The 14-byte identity-token which identifies the sender.
+ pub identity_token: V0IdentityToken,
+}
+
+impl V0BroadcastCredential {
+ /// Builds some simple broadcast crypto-materials out of
+ /// the provided key-seed and version-specific metadata-key.
+ pub fn new(key_seed: [u8; 32], identity_token: V0IdentityToken) -> Self {
+ Self { key_seed, identity_token }
+ }
+
+ /// Key seed from which other keys are derived.
+ pub(crate) fn key_seed(&self) -> [u8; 32] {
+ self.key_seed
+ }
+
+ /// Identity token that will be incorporated into encrypted advertisements.
+ pub(crate) fn identity_token(&self) -> V0IdentityToken {
+ self.identity_token
+ }
+
+ /// Derive a discovery credential with the data necessary to discover advertisements produced
+ /// by this broadcast credential.
+ pub fn derive_discovery_credential<C: CryptoProvider>(&self) -> V0DiscoveryCredential {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
+
+ V0DiscoveryCredential::new(
+ self.key_seed,
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<C>(&self.identity_token.bytes()),
+ )
+ }
+}
diff --git a/nearby/presence/np_adv/src/credential/v1.rs b/nearby/presence/np_adv/src/credential/v1.rs
index 386799f..b6b9c71 100644
--- a/nearby/presence/np_adv/src/credential/v1.rs
+++ b/nearby/presence/np_adv/src/credential/v1.rs
@@ -14,35 +14,46 @@
//! Cryptographic materials for v1 advertisement-format credentials.
-use crate::credential::{
- protocol_version_seal, BroadcastCryptoMaterial, DiscoveryCryptoMaterial, ProtocolVersion,
-};
-use crate::MetadataKey;
-use crypto_provider::{aes::Aes128Key, ed25519, ed25519::PublicKey, CryptoProvider, CryptoRng};
-use np_hkdf::UnsignedSectionKeys;
+use crate::credential::{protocol_version_seal, DiscoveryMetadataCryptoMaterial, ProtocolVersion};
+use crate::extended::V1IdentityToken;
+use crypto_provider::{aead::Aead, aes, ed25519, CryptoProvider};
+use np_hkdf::{DerivedSectionKeys, NpKeySeedHkdf};
/// Cryptographic information about a particular V1 discovery credential
/// necessary to match and decrypt encrypted V1 sections.
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct V1DiscoveryCredential {
- key_seed: [u8; 32],
- expected_unsigned_metadata_key_hmac: [u8; 32],
- expected_signed_metadata_key_hmac: [u8; 32],
- pub_key: ed25519::RawPublicKey,
+ /// The 32-byte key-seed used for generating other key material.
+ pub key_seed: [u8; 32],
+
+ /// The MIC-short-salt variant of the HMAC of the identity token.
+ pub expected_mic_short_salt_identity_token_hmac: [u8; 32],
+
+ /// The MIC-extended-salt variant of the HMAC of the identity token.
+ pub expected_mic_extended_salt_identity_token_hmac: [u8; 32],
+
+ /// The signed-extended-salt variant of the HMAC of the identity token.
+ pub expected_signed_extended_salt_identity_token_hmac: [u8; 32],
+
+ /// The ed25519 public key used for verification of signed sections.
+ pub public_key: ed25519::PublicKey,
}
+
impl V1DiscoveryCredential {
/// Construct a V1 discovery credential from the provided identity data.
pub fn new(
key_seed: [u8; 32],
- expected_unsigned_metadata_key_hmac: [u8; 32],
- expected_signed_metadata_key_hmac: [u8; 32],
- pub_key: ed25519::RawPublicKey,
+ expected_mic_short_salt_identity_token_hmac: [u8; 32],
+ expected_mic_extended_salt_identity_token_hmac: [u8; 32],
+ expected_signed_extended_salt_identity_token_hmac: [u8; 32],
+ public_key: ed25519::PublicKey,
) -> Self {
Self {
key_seed,
- expected_unsigned_metadata_key_hmac,
- expected_signed_metadata_key_hmac,
- pub_key,
+ expected_mic_short_salt_identity_token_hmac,
+ expected_mic_extended_salt_identity_token_hmac,
+ expected_signed_extended_salt_identity_token_hmac,
+ public_key,
}
}
@@ -50,25 +61,24 @@ impl V1DiscoveryCredential {
pub(crate) fn to_precalculated<C: CryptoProvider>(
&self,
) -> PrecalculatedV1DiscoveryCryptoMaterial {
- let signed_identity_resolution_material = self.signed_identity_resolution_material::<C>();
- let unsigned_identity_resolution_material =
- self.unsigned_identity_resolution_material::<C>();
- let signed_verification_material = self.signed_verification_material::<C>();
- let unsigned_verification_material = self.unsigned_verification_material::<C>();
- let metadata_nonce = self.metadata_nonce::<C>();
PrecalculatedV1DiscoveryCryptoMaterial {
- signed_identity_resolution_material,
- unsigned_identity_resolution_material,
- signed_verification_material,
- unsigned_verification_material,
- metadata_nonce,
+ signed_identity_resolution_material: self.signed_identity_resolution_material::<C>(),
+ mic_short_salt_identity_resolution_material: self
+ .mic_short_salt_identity_resolution_material::<C>(),
+ mic_extended_salt_identity_resolution_material: self
+ .mic_extended_salt_identity_resolution_material::<C>(),
+ signed_verification_material: self.signed_verification_material::<C>(),
+ mic_short_salt_verification_material: self.mic_short_salt_verification_material::<C>(),
+ mic_extended_salt_verification_material: self
+ .mic_extended_salt_verification_material::<C>(),
+ metadata_nonce: self.metadata_nonce::<C>(),
}
}
}
-impl DiscoveryCryptoMaterial<V1> for V1DiscoveryCredential {
+impl DiscoveryMetadataCryptoMaterial<V1> for V1DiscoveryCredential {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
- V1::metadata_nonce_from_key_seed::<C>(&self.key_seed)
+ np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed).v1_metadata_nonce()
}
}
@@ -77,32 +87,50 @@ impl V1DiscoveryCryptoMaterial for V1DiscoveryCredential {
&self,
) -> SignedSectionIdentityResolutionMaterial {
let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
- SignedSectionIdentityResolutionMaterial::from_hkdf_and_expected_metadata_key_hmac(
+ SignedSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
&hkdf,
- self.expected_signed_metadata_key_hmac,
+ self.expected_signed_extended_salt_identity_token_hmac,
)
}
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial {
+ ) -> MicShortSaltSectionIdentityResolutionMaterial {
let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
- UnsignedSectionIdentityResolutionMaterial::from_hkdf_and_expected_metadata_key_hmac(
+ MicShortSaltSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
&hkdf,
- self.expected_unsigned_metadata_key_hmac,
+ self.expected_mic_short_salt_identity_token_hmac,
+ )
+ }
+
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
+ MicExtendedSaltSectionIdentityResolutionMaterial::from_hkdf_and_expected_identity_token_hmac(
+ &hkdf,
+ self.expected_mic_extended_salt_identity_token_hmac,
)
}
fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
- SignedSectionVerificationMaterial { pub_key: self.pub_key }
+ SignedSectionVerificationMaterial { public_key: self.public_key.clone() }
}
- fn unsigned_verification_material<C: CryptoProvider>(
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial {
+ ) -> MicShortSaltSectionVerificationMaterial {
let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
- let mic_hmac_key = *UnsignedSectionKeys::hmac_key(&hkdf).as_bytes();
- UnsignedSectionVerificationMaterial { mic_hmac_key }
+ let mic_hmac_key = *hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes();
+ MicShortSaltSectionVerificationMaterial { mic_hmac_key }
+ }
+
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionVerificationMaterial {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&self.key_seed);
+ let mic_hmac_key = *hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes();
+ MicExtendedSaltSectionVerificationMaterial { mic_hmac_key }
}
}
@@ -114,17 +142,18 @@ impl protocol_version_seal::ProtocolVersionSeal for V1 {}
impl ProtocolVersion for V1 {
type DiscoveryCredential = V1DiscoveryCredential;
- type MetadataKey = MetadataKey;
+ type IdentityToken = V1IdentityToken;
- fn metadata_nonce_from_key_seed<C: CryptoProvider>(key_seed: &[u8; 32]) -> [u8; 12] {
- let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(key_seed);
- hkdf.extended_metadata_nonce()
+ fn metadata_nonce_from_key_seed<C: CryptoProvider>(
+ hkdf: &NpKeySeedHkdf<C>,
+ ) -> <C::Aes128Gcm as Aead>::Nonce {
+ hkdf.v1_metadata_nonce()
}
- fn expand_metadata_key<C: CryptoProvider>(metadata_key: MetadataKey) -> MetadataKey {
- metadata_key
- }
- fn gen_random_metadata_key<R: CryptoRng>(rng: &mut R) -> MetadataKey {
- MetadataKey(rng.gen())
+
+ fn extract_metadata_key<C: CryptoProvider>(
+ identity_token: Self::IdentityToken,
+ ) -> aes::Aes128Key {
+ identity_token.into_bytes().into()
}
}
@@ -142,12 +171,12 @@ impl V1ProtocolVersion for V1 {}
#[derive(Clone)]
pub(crate) struct SectionIdentityResolutionMaterial {
/// The AES key for decrypting section ciphertext
- pub(crate) aes_key: Aes128Key,
- /// The metadata key HMAC key for deriving and verifying the identity metadata
+ pub(crate) aes_key: aes::Aes128Key,
+ /// The identity token HMAC key for deriving and verifying the identity metadata
/// key HMAC against the expected value.
- pub(crate) metadata_key_hmac_key: [u8; 32],
- /// The expected metadata key HMAC to check against for an identity match.
- pub(crate) expected_metadata_key_hmac: [u8; 32],
+ pub(crate) identity_token_hmac_key: [u8; 32],
+ /// The expected identity token HMAC to check against for an identity match.
+ pub(crate) expected_identity_token_hmac: [u8; 32],
}
/// Cryptographic materials necessary for determining whether or not
@@ -175,50 +204,97 @@ impl SignedSectionIdentityResolutionMaterial {
/// Constructs identity-resolution material for a signed section whose
/// discovery credential leverages the provided HKDF and has the given
/// expected metadata-key HMAC.
- pub(crate) fn from_hkdf_and_expected_metadata_key_hmac<C: CryptoProvider>(
+ pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
hkdf: &np_hkdf::NpKeySeedHkdf<C>,
- expected_metadata_key_hmac: [u8; 32],
+ expected_identity_token_hmac: [u8; 32],
) -> Self {
Self(SectionIdentityResolutionMaterial {
- aes_key: hkdf.extended_signed_section_aes_key(),
- metadata_key_hmac_key: *hkdf.extended_signed_metadata_key_hmac_key().as_bytes(),
- expected_metadata_key_hmac,
+ aes_key: hkdf.v1_signature_keys().aes_key(),
+ identity_token_hmac_key: *hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes(),
+ expected_identity_token_hmac,
})
}
}
/// Cryptographic materials necessary for determining whether or not
-/// a given V1 MIC advertisement section matches an identity.
+/// a given V1 MIC extended salt advertisement section matches an identity.
#[derive(Clone)]
-pub struct UnsignedSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
+pub struct MicExtendedSaltSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
-impl UnsignedSectionIdentityResolutionMaterial {
+impl MicExtendedSaltSectionIdentityResolutionMaterial {
+ /// Extracts the underlying section-identity resolution material carried around
+ /// within this wrapper for resolution of MIC extended salt sections.
+ pub(crate) fn into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial {
+ self.0
+ }
+ /// Gets the underlying section-identity resolution material carried around
+ /// within this wrapper for resolution of MIC extended salt sections.
+ #[cfg(any(test, feature = "devtools"))]
+ pub(crate) fn as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial {
+ &self.0
+ }
#[cfg(test)]
- pub(crate) fn from_raw(raw: SectionIdentityResolutionMaterial) -> Self {
- Self(raw)
+ pub(crate) fn as_mut_raw_resolution_material(
+ &mut self,
+ ) -> &mut SectionIdentityResolutionMaterial {
+ &mut self.0
+ }
+ /// Constructs identity-resolution material for an MIC extended salt section whose
+ /// discovery credential leverages the provided HKDF and has the given
+ /// expected metadata-key HMAC.
+ pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ expected_identity_token_hmac: [u8; 32],
+ ) -> Self {
+ Self(SectionIdentityResolutionMaterial {
+ aes_key: hkdf.v1_mic_extended_salt_keys().aes_key(),
+ identity_token_hmac_key: *hkdf
+ .v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .as_bytes(),
+ expected_identity_token_hmac,
+ })
}
+}
+
+/// Cryptographic materials necessary for determining whether
+/// a given V1 MIC short salt advertisement section matches an identity.
+#[derive(Clone)]
+pub struct MicShortSaltSectionIdentityResolutionMaterial(SectionIdentityResolutionMaterial);
+
+impl MicShortSaltSectionIdentityResolutionMaterial {
/// Extracts the underlying section-identity resolution material carried around
- /// within this wrapper for resolution of unsigned sections.
+ /// within this wrapper for resolution of MIC short salt sections.
pub(crate) fn into_raw_resolution_material(self) -> SectionIdentityResolutionMaterial {
self.0
}
/// Gets the underlying section-identity resolution material carried around
- /// within this wrapper for resolution of unsigned sections.
+ /// within this wrapper for resolution of MIC short salt sections.
#[cfg(any(test, feature = "devtools"))]
pub(crate) fn as_raw_resolution_material(&self) -> &SectionIdentityResolutionMaterial {
&self.0
}
- /// Constructs identity-resolution material for an unsigned (MIC) section whose
+ #[cfg(test)]
+ pub(crate) fn as_mut_raw_resolution_material(
+ &mut self,
+ ) -> &mut SectionIdentityResolutionMaterial {
+ &mut self.0
+ }
+
+ /// Constructs identity-resolution material for a MIC short salt section whose
/// discovery credential leverages the provided HKDF and has the given
/// expected metadata-key HMAC.
- pub(crate) fn from_hkdf_and_expected_metadata_key_hmac<C: CryptoProvider>(
+ pub(crate) fn from_hkdf_and_expected_identity_token_hmac<C: CryptoProvider>(
hkdf: &np_hkdf::NpKeySeedHkdf<C>,
- expected_metadata_key_hmac: [u8; 32],
+ expected_identity_token_hmac: [u8; 32],
) -> Self {
Self(SectionIdentityResolutionMaterial {
- aes_key: UnsignedSectionKeys::aes_key(hkdf),
- metadata_key_hmac_key: *hkdf.extended_unsigned_metadata_key_hmac_key().as_bytes(),
- expected_metadata_key_hmac,
+ aes_key: hkdf.v1_mic_short_salt_keys().aes_key(),
+ identity_token_hmac_key: *hkdf
+ .v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .as_bytes(),
+ expected_identity_token_hmac,
})
}
}
@@ -229,34 +305,50 @@ impl UnsignedSectionIdentityResolutionMaterial {
pub struct SignedSectionVerificationMaterial {
/// The np_ed25519 public key to be
/// used for signature verification of signed sections.
- pub(crate) pub_key: ed25519::RawPublicKey,
+ pub(crate) public_key: ed25519::PublicKey,
}
impl SignedSectionVerificationMaterial {
/// Gets the np_ed25519 public key for the given identity,
/// used for signature verification of signed sections.
- pub(crate) fn signature_verification_public_key<C: CryptoProvider>(
- &self,
- ) -> np_ed25519::PublicKey<C> {
- np_ed25519::PublicKey::from_bytes(&self.pub_key).expect("Should only contain valid keys")
+ pub(crate) fn signature_verification_public_key(&self) -> ed25519::PublicKey {
+ self.public_key.clone()
+ }
+}
+
+/// Crypto materials for V1 MIC short salt sections which are not employed in identity resolution,
+/// but may be necessary to fully decrypt a MIC short salt section.
+#[derive(Clone)]
+pub struct MicShortSaltSectionVerificationMaterial {
+ /// The MIC HMAC key for verifying the integrity of MIC short salt sections.
+ pub(crate) mic_hmac_key: [u8; 32],
+}
+
+impl MicSectionVerificationMaterial for MicShortSaltSectionVerificationMaterial {
+ fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key {
+ self.mic_hmac_key.into()
}
}
-/// Crypto materials for V1 unsigned sections which are not employed in identity resolution,
-/// but may be necessary to fully decrypt an unsigned section.
+/// Crypto materials for V1 MIC extended salt sections which are not employed in identity
+/// resolution, but may be necessary to fully decrypt a MIC extended salt section.
#[derive(Clone)]
-pub struct UnsignedSectionVerificationMaterial {
- /// The MIC HMAC key for verifying the integrity of unsigned sections.
+pub struct MicExtendedSaltSectionVerificationMaterial {
+ /// The MIC HMAC key for verifying the integrity of MIC extended salt sections.
pub(crate) mic_hmac_key: [u8; 32],
}
-impl UnsignedSectionVerificationMaterial {
- /// Returns the MIC HMAC key for unsigned sections
- pub(crate) fn mic_hmac_key<C: CryptoProvider>(&self) -> np_hkdf::NpHmacSha256Key<C> {
+impl MicSectionVerificationMaterial for MicExtendedSaltSectionVerificationMaterial {
+ fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key {
self.mic_hmac_key.into()
}
}
+pub(crate) trait MicSectionVerificationMaterial {
+ /// Returns the HMAC key for calculating the MIC of the sections
+ fn mic_hmac_key(&self) -> np_hkdf::NpHmacSha256Key;
+}
+
// Space-time tradeoffs:
// - Calculating an HKDF from the key seed costs about 2us on a gLinux laptop, and occupies 80b.
// - Calculating an AES (16b) or HMAC (32b) key from the HKDF costs about 700ns.
@@ -268,39 +360,54 @@ impl UnsignedSectionVerificationMaterial {
// is only used on the matching identity, not all identities.
/// Cryptographic material for an individual NP credential used to decrypt and verify v1 sections.
-pub trait V1DiscoveryCryptoMaterial: DiscoveryCryptoMaterial<V1> {
+pub trait V1DiscoveryCryptoMaterial: DiscoveryMetadataCryptoMaterial<V1> {
/// Constructs or copies the identity resolution material for signed sections
fn signed_identity_resolution_material<C: CryptoProvider>(
&self,
) -> SignedSectionIdentityResolutionMaterial;
- /// Constructs or copies the identity resolution material for unsigned sections
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+ /// Constructs or copies the identity resolution material for MIC short salt sections
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicShortSaltSectionIdentityResolutionMaterial;
+
+ /// Constructs or copies the identity resolution material for MIC extended salt sections
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial;
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial;
/// Constructs or copies non-identity-resolution deserialization material for signed
/// sections.
fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial;
- /// Constructs or copies non-identity-resolution deserialization material for unsigned
+ /// Constructs or copies non-identity-resolution deserialization material for MIC short salt
/// sections.
- fn unsigned_verification_material<C: CryptoProvider>(
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial;
+ ) -> MicShortSaltSectionVerificationMaterial;
+
+ /// Constructs or copies non-identity-resolution deserialization material for MIC extended salt
+ /// sections.
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionVerificationMaterial;
}
-/// V1 [`DiscoveryCryptoMaterial`] that minimizes CPU time when providing key material at
+/// [`V1DiscoveryCryptoMaterial`] that minimizes CPU time when providing key material at
/// the expense of occupied memory
pub struct PrecalculatedV1DiscoveryCryptoMaterial {
pub(crate) signed_identity_resolution_material: SignedSectionIdentityResolutionMaterial,
- pub(crate) unsigned_identity_resolution_material: UnsignedSectionIdentityResolutionMaterial,
+ pub(crate) mic_short_salt_identity_resolution_material:
+ MicShortSaltSectionIdentityResolutionMaterial,
+ pub(crate) mic_extended_salt_identity_resolution_material:
+ MicExtendedSaltSectionIdentityResolutionMaterial,
pub(crate) signed_verification_material: SignedSectionVerificationMaterial,
- pub(crate) unsigned_verification_material: UnsignedSectionVerificationMaterial,
+ pub(crate) mic_short_salt_verification_material: MicShortSaltSectionVerificationMaterial,
+ pub(crate) mic_extended_salt_verification_material: MicExtendedSaltSectionVerificationMaterial,
pub(crate) metadata_nonce: [u8; 12],
}
-impl DiscoveryCryptoMaterial<V1> for PrecalculatedV1DiscoveryCryptoMaterial {
+impl DiscoveryMetadataCryptoMaterial<V1> for PrecalculatedV1DiscoveryCryptoMaterial {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
self.metadata_nonce
}
@@ -312,25 +419,39 @@ impl V1DiscoveryCryptoMaterial for PrecalculatedV1DiscoveryCryptoMaterial {
) -> SignedSectionIdentityResolutionMaterial {
self.signed_identity_resolution_material.clone()
}
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial {
- self.unsigned_identity_resolution_material.clone()
+ ) -> MicShortSaltSectionIdentityResolutionMaterial {
+ self.mic_short_salt_identity_resolution_material.clone()
+ }
+
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
+ self.mic_extended_salt_identity_resolution_material.clone()
}
fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
self.signed_verification_material.clone()
}
- fn unsigned_verification_material<C: CryptoProvider>(
+
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicShortSaltSectionVerificationMaterial {
+ self.mic_short_salt_verification_material.clone()
+ }
+
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial {
- self.unsigned_verification_material.clone()
+ ) -> MicExtendedSaltSectionVerificationMaterial {
+ self.mic_extended_salt_verification_material.clone()
}
}
// Implementations for reference types -- we don't provide a blanket impl for references
// due to the potential to conflict with downstream crates' implementations.
-impl<'a> DiscoveryCryptoMaterial<V1> for &'a V1DiscoveryCredential {
+impl<'a> DiscoveryMetadataCryptoMaterial<V1> for &'a V1DiscoveryCredential {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
(*self).metadata_nonce::<C>()
}
@@ -342,22 +463,36 @@ impl<'a> V1DiscoveryCryptoMaterial for &'a V1DiscoveryCredential {
) -> SignedSectionIdentityResolutionMaterial {
(*self).signed_identity_resolution_material::<C>()
}
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicShortSaltSectionIdentityResolutionMaterial {
+ (*self).mic_short_salt_identity_resolution_material::<C>()
+ }
+
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial {
- (*self).unsigned_identity_resolution_material::<C>()
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
+ (*self).mic_extended_salt_identity_resolution_material::<C>()
}
fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
(*self).signed_verification_material::<C>()
}
- fn unsigned_verification_material<C: CryptoProvider>(
+
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial {
- (*self).unsigned_verification_material::<C>()
+ ) -> MicShortSaltSectionVerificationMaterial {
+ (*self).mic_short_salt_verification_material::<C>()
+ }
+
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionVerificationMaterial {
+ (*self).mic_extended_salt_verification_material::<C>()
}
}
-impl<'a> DiscoveryCryptoMaterial<V1> for &'a PrecalculatedV1DiscoveryCryptoMaterial {
+impl<'a> DiscoveryMetadataCryptoMaterial<V1> for &'a PrecalculatedV1DiscoveryCryptoMaterial {
fn metadata_nonce<C: CryptoProvider>(&self) -> [u8; 12] {
(*self).metadata_nonce::<C>()
}
@@ -369,84 +504,92 @@ impl<'a> V1DiscoveryCryptoMaterial for &'a PrecalculatedV1DiscoveryCryptoMateria
) -> SignedSectionIdentityResolutionMaterial {
(*self).signed_identity_resolution_material::<C>()
}
- fn unsigned_identity_resolution_material<C: CryptoProvider>(
+
+ fn mic_short_salt_identity_resolution_material<C: CryptoProvider>(
+ &self,
+ ) -> MicShortSaltSectionIdentityResolutionMaterial {
+ (*self).mic_short_salt_identity_resolution_material::<C>()
+ }
+
+ fn mic_extended_salt_identity_resolution_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionIdentityResolutionMaterial {
- (*self).unsigned_identity_resolution_material::<C>()
+ ) -> MicExtendedSaltSectionIdentityResolutionMaterial {
+ (*self).mic_extended_salt_identity_resolution_material::<C>()
}
fn signed_verification_material<C: CryptoProvider>(&self) -> SignedSectionVerificationMaterial {
(*self).signed_verification_material::<C>()
}
- fn unsigned_verification_material<C: CryptoProvider>(
+
+ fn mic_short_salt_verification_material<C: CryptoProvider>(
&self,
- ) -> UnsignedSectionVerificationMaterial {
- (*self).unsigned_verification_material::<C>()
+ ) -> MicShortSaltSectionVerificationMaterial {
+ (*self).mic_short_salt_verification_material::<C>()
}
-}
-
-/// Extension of [`BroadcastCryptoMaterial`] for `V1` to add
-/// crypto-materials which are necessary to sign V1 sections.
-pub trait SignedBroadcastCryptoMaterial: BroadcastCryptoMaterial<V1> {
- /// Gets the advertisement-signing private key for constructing
- /// signature-verified V1 sections.
- ///
- /// The private key is returned in an opaque, crypto-provider-independent
- /// form to provide a safeguard against leaking the bytes of the key.
- fn signing_key(&self) -> ed25519::PrivateKey;
-
- /// Constructs the V1 discovery credential which may be used to discover
- /// V1 advertisement sections broadcasted using this broadcast crypto-material
- fn derive_v1_discovery_credential<C: CryptoProvider>(&self) -> V1DiscoveryCredential {
- let key_seed = self.key_seed();
- let metadata_key = self.metadata_key();
- let pub_key = self.signing_key().derive_public_key::<C::Ed25519>();
- let pub_key = pub_key.to_bytes();
- let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
- let unsigned = hkdf
- .extended_unsigned_metadata_key_hmac_key()
- .calculate_hmac(metadata_key.0.as_slice());
- let signed =
- hkdf.extended_signed_metadata_key_hmac_key().calculate_hmac(metadata_key.0.as_slice());
- V1DiscoveryCredential::new(key_seed, unsigned, signed, pub_key)
+ fn mic_extended_salt_verification_material<C: CryptoProvider>(
+ &self,
+ ) -> MicExtendedSaltSectionVerificationMaterial {
+ (*self).mic_extended_salt_verification_material::<C>()
}
}
-/// Concrete implementation of a [`SignedBroadcastCryptoMaterial`] which keeps the key
-/// seed, the V1 metadata key, and the signing key contiguous in memory.
-///
-/// For more flexible expression of broadcast
-/// credentials, feel free to directly implement [`SignedBroadcastCryptoMaterial`]
-/// for your own broadcast-credential-storing data-type.
-pub struct SimpleSignedBroadcastCryptoMaterial {
- key_seed: [u8; 32],
- metadata_key: MetadataKey,
- signing_key: ed25519::PrivateKey,
+/// Crypto material for creating V1 sections.
+#[derive(Clone)]
+pub struct V1BroadcastCredential {
+ /// The 32-byte key-seed used for generating other key material.
+ pub key_seed: [u8; 32],
+
+ /// The 16-byte identity-token which identifies the sender.
+ pub identity_token: V1IdentityToken,
+
+ /// The ed25519 private key to be used for signing section contents.
+ pub private_key: ed25519::PrivateKey,
}
-impl SimpleSignedBroadcastCryptoMaterial {
+impl V1BroadcastCredential {
/// Builds some simple V1 signed broadcast crypto-materials out of
- /// the provided key-seed, metadata-key, and signing key.
+ /// the provided key-seed, metadata-key, and ed25519 private key.
pub fn new(
key_seed: [u8; 32],
- metadata_key: MetadataKey,
- signing_key: ed25519::PrivateKey,
+ identity_token: V1IdentityToken,
+ private_key: ed25519::PrivateKey,
) -> Self {
- Self { key_seed, metadata_key, signing_key }
+ Self { key_seed, identity_token, private_key }
}
-}
-impl BroadcastCryptoMaterial<V1> for SimpleSignedBroadcastCryptoMaterial {
- fn key_seed(&self) -> [u8; 32] {
+ /// Key seed from which other keys are derived.
+ pub(crate) fn key_seed(&self) -> [u8; 32] {
self.key_seed
}
- fn metadata_key(&self) -> MetadataKey {
- self.metadata_key
+
+ /// Identity token that will be incorporated into encrypted advertisements.
+ pub(crate) fn identity_token(&self) -> V1IdentityToken {
+ self.identity_token
+ }
+
+ /// Derive a discovery credential with the data necessary to discover advertisements produced
+ /// by this broadcast credential.
+ pub fn derive_discovery_credential<C: CryptoProvider>(&self) -> V1DiscoveryCredential {
+ let key_seed = self.key_seed();
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
+
+ V1DiscoveryCredential::new(
+ key_seed,
+ hkdf.v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ hkdf.v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ hkdf.v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(self.identity_token.as_slice()),
+ self.signing_key().derive_public_key::<C::Ed25519>(),
+ )
}
-}
-impl SignedBroadcastCryptoMaterial for SimpleSignedBroadcastCryptoMaterial {
- fn signing_key(&self) -> ed25519::PrivateKey {
- self.signing_key.clone()
+ /// Key used for signature-protected sections
+ pub(crate) fn signing_key(&self) -> ed25519::PrivateKey {
+ self.private_key.clone()
}
}
diff --git a/nearby/presence/np_adv/src/de_type.rs b/nearby/presence/np_adv/src/de_type.rs
deleted file mode 100644
index 4966ed0..0000000
--- a/nearby/presence/np_adv/src/de_type.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.
-
-//! DE types that are shared across v0 and v1.
-
-// The same ids are used for v0/legacy and v1/extended
-const IDENTITY_DE_TYPES_BY_CODE: [Option<IdentityDataElementType>; 5] = [
- // no need for more elements since identity types are at indices 1-4
- None, // 0b0000
- Some(IdentityDataElementType::Private), // 0b0001
- Some(IdentityDataElementType::Trusted), // 0b0010
- Some(IdentityDataElementType::Public), // 0b0011
- Some(IdentityDataElementType::Provisioned), // 0b0100
-];
-
-/// DE types for special DEs that contain other DEs and consume the entire payload of the
-/// advertisement.
-///
-/// Shared between V0 and V1.
-///
-/// Must not overlap with [`PlainDataElementType`](crate::legacy::de_type::PlainDataElementType).
-#[derive(strum_macros::EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
-#[allow(clippy::enum_variant_names)]
-pub(crate) enum IdentityDataElementType {
- Private,
- Trusted,
- Public,
- Provisioned,
-}
-
-impl IdentityDataElementType {
- pub(crate) fn as_encrypted_identity_de_type(&self) -> Option<EncryptedIdentityDataElementType> {
- match self {
- IdentityDataElementType::Private => Some(EncryptedIdentityDataElementType::Private),
- IdentityDataElementType::Trusted => Some(EncryptedIdentityDataElementType::Trusted),
- IdentityDataElementType::Public => None,
- IdentityDataElementType::Provisioned => {
- Some(EncryptedIdentityDataElementType::Provisioned)
- }
- }
- }
-
- /// Type codes for identity DEs are shared between versions 0 and 1.
- pub(crate) fn shared_type_code(&self) -> u8 {
- match self {
- IdentityDataElementType::Private => 0b0001,
- IdentityDataElementType::Trusted => 0b0010,
- IdentityDataElementType::Public => 0b0011,
- IdentityDataElementType::Provisioned => 0b0100,
- }
- }
-
- pub(crate) fn from_shared_type_code(code: u8) -> Option<Self> {
- IDENTITY_DE_TYPES_BY_CODE.get(code as usize).and_then(|o| *o)
- }
-}
-
-/// The identity DE types that support encryption.
-#[derive(strum_macros::EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
-pub enum EncryptedIdentityDataElementType {
- /// An identity that's shared with other devices where a user has signed in to their identity provider
- Private,
- /// An identity shared via some trust designation (e.g. starred contacts)
- Trusted,
- /// An identity established via a p2p link between two specific devices
- Provisioned,
-}
-
-impl EncryptedIdentityDataElementType {
- pub(crate) fn as_identity_data_element_type(&self) -> IdentityDataElementType {
- match self {
- EncryptedIdentityDataElementType::Private => IdentityDataElementType::Private,
- EncryptedIdentityDataElementType::Trusted => IdentityDataElementType::Trusted,
- EncryptedIdentityDataElementType::Provisioned => IdentityDataElementType::Provisioned,
- }
- }
-}
diff --git a/nearby/presence/np_adv/src/deser_v1_tests.rs b/nearby/presence/np_adv/src/deser_v1_tests.rs
deleted file mode 100644
index e0cabc9..0000000
--- a/nearby/presence/np_adv/src/deser_v1_tests.rs
+++ /dev/null
@@ -1,562 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-use core::marker::PhantomData;
-use rand::{rngs::StdRng, seq::SliceRandom as _, Rng as _, SeedableRng as _};
-
-extern crate std;
-
-use crate::{
- credential::{
- book::{CredentialBook, CredentialBookBuilder},
- v1::{
- SignedBroadcastCryptoMaterial, SimpleSignedBroadcastCryptoMaterial,
- V1DiscoveryCredential,
- },
- EmptyMatchedCredential, MatchableCredential, MatchedCredential,
- },
- de_type::EncryptedIdentityDataElementType,
- deserialization_arena,
- deserialization_arena::DeserializationArena,
- deserialize_advertisement,
- extended::{
- data_elements::GenericDataElement,
- deserialize::VerificationMode,
- serialize::{
- AdvBuilder, AdvertisementType, EncodedAdvertisement, MicEncryptedSectionEncoder,
- PublicSectionEncoder, SectionBuilder, SectionEncoder, SignedEncryptedSectionEncoder,
- },
- },
- AdvDeserializationError, AdvDeserializationErrorDetailsHazmat, HasIdentityMatch, MetadataKey,
- PlaintextIdentityMode, Section, V1AdvertisementContents, V1DeserializedSection,
-};
-use crypto_provider::{CryptoProvider, CryptoRng};
-use std::{collections, prelude::rust_2021::*, vec};
-use strum::IntoEnumIterator as _;
-
-use crate::extended::NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT;
-use crypto_provider_default::CryptoProviderImpl;
-
-#[test]
-fn v1_plaintext() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let identities = (0..100)
- .map(|_| TestIdentity::<CryptoProviderImpl>::random(&mut rng))
- .collect::<Vec<_>>();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let section_configs: Vec<SectionConfig<CryptoProviderImpl>> =
- fill_plaintext_adv(&mut rng, &mut adv_builder);
- let adv = adv_builder.into_advertisement();
- let creds = identities
- .iter()
- .map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
- match_data: EmptyMatchedCredential,
- })
- .collect::<Vec<_>>();
-
- let arena = deserialization_arena!();
- // check if the section is empty or there is more than one public section
- let cred_book =
- CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(&[], &creds);
- if section_configs.is_empty() {
- let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(
- v1_error,
- AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
- }
- ); //assert a adv deserialization error
- } else {
- let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(0, v1_contents.invalid_sections_count());
- assert_eq!(section_configs.len(), v1_contents.sections.len());
- for (section_config, section) in section_configs.iter().zip(v1_contents.sections.iter())
- {
- assert_section_equals(section_config, section);
- }
- }
- }
-}
-
-#[test]
-fn v1_all_identities_resolvable_ciphertext() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let identities = (0..100)
- .map(|_| TestIdentity::<CryptoProviderImpl>::random(&mut rng))
- .collect::<Vec<_>>();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let section_configs = fill_encrypted_adv(&mut rng, &identities, &mut adv_builder);
- let adv = adv_builder.into_advertisement();
- let creds = identities
- .iter()
- .map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
- match_data: EmptyMatchedCredential,
- })
- .collect::<Vec<_>>();
- let arena = deserialization_arena!();
- // check if the section header would be 0 or if the section is empty
- let cred_book =
- CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(&[], &creds);
- if section_configs.is_empty() {
- let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(
- v1_error,
- AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
- }
- ); //assert a adv deserialization error
- } else {
- let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(0, v1_contents.invalid_sections_count());
- assert_eq!(section_configs.len(), v1_contents.sections.len());
- for (section_config, section) in section_configs.iter().zip(v1_contents.sections.iter())
- {
- assert_section_equals(section_config, section);
- }
- }
- }
-}
-
-#[test]
-fn v1_only_non_matching_identities_available_ciphertext() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let identities = (0..100)
- .map(|_| TestIdentity::<CryptoProviderImpl>::random(&mut rng))
- .collect::<Vec<_>>();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let section_configs = fill_encrypted_adv(&mut rng, &identities, &mut adv_builder);
- let adv = adv_builder.into_advertisement();
- let creds = identities
- .iter()
- .filter(|i| {
- // remove all identities used in sections
- !section_configs
- .iter()
- .any(|sc| sc.identity.map(|sci| sci.key_seed == i.key_seed).unwrap_or(false))
- })
- .map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
- match_data: EmptyMatchedCredential,
- })
- .collect::<Vec<_>>();
-
- let arena = deserialization_arena!();
- // check if the section header would be 0
- let cred_book =
- CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(&[], &creds);
- if section_configs.is_empty() {
- let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(
- v1_error,
- AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
- }
- ); //assert a adv deserialization error
- } else {
- let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- // all encrypted identity sections are invalid
- let encrypted_section_count =
- section_configs.iter().filter(|sc| sc.identity.is_some()).count();
- assert_eq!(encrypted_section_count, v1_contents.invalid_sections_count());
- assert_eq!(section_configs.len() - encrypted_section_count, v1_contents.sections.len());
- for (section_config, section) in section_configs
- .iter()
- // skip encrypted sections
- .filter(|sc| sc.identity.is_none())
- .zip(v1_contents.sections.iter())
- {
- assert_section_equals(section_config, section);
- }
- }
- }
-}
-
-#[test]
-fn v1_no_creds_available_ciphertext() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let identities = (0..100).map(|_| TestIdentity::random(&mut rng)).collect::<Vec<_>>();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let section_configs = fill_encrypted_adv::<StdRng, CryptoProviderImpl>(
- &mut rng,
- &identities,
- &mut adv_builder,
- );
- let adv = adv_builder.into_advertisement();
- let arena = deserialization_arena!();
- // check if the section header would be 0
- let cred_book = CredentialBookBuilder::<EmptyMatchedCredential>::build_cached_slice_book::<
- 0,
- 0,
- CryptoProviderImpl,
- >(&[], &[]);
- if section_configs.is_empty() {
- let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(
- v1_error,
- AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
- }
- ); //assert a adv deserialization error
- } else {
- let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- // all encrypted identity sections are invalid
- let encrypted_section_count =
- section_configs.iter().filter(|sc| sc.identity.is_some()).count();
- assert_eq!(encrypted_section_count, v1_contents.invalid_sections_count());
- assert_eq!(section_configs.len() - encrypted_section_count, v1_contents.sections.len());
-
- for (section_config, section) in section_configs
- .iter()
- // skip encrypted sections
- .filter(|sc| sc.identity.is_none())
- .zip(v1_contents.sections.iter())
- {
- assert_section_equals(section_config, section);
- }
- }
- }
-}
-
-#[test]
-fn v1_only_some_matching_identities_available_ciphertext() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let identities = (0..100)
- .map(|_| TestIdentity::<CryptoProviderImpl>::random(&mut rng))
- .collect::<Vec<_>>();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let section_configs = fill_encrypted_adv(&mut rng, &identities, &mut adv_builder);
- let adv = adv_builder.into_advertisement();
- // identities used in sections, which may be used in multiple sections too
- let identities_to_remove: collections::HashSet<_> = identities
- .iter()
- .filter(|i| {
- let identity_used = section_configs
- .iter()
- .any(|sc| sc.identity.map(|sci| sci.key_seed == i.key_seed).unwrap_or(false));
-
- // only remove half the identities that were used
- identity_used && rng.gen()
- })
- .map(|i| i.key_seed)
- .collect();
-
- let creds = identities
- .iter()
- .filter(|i| !identities_to_remove.contains(&i.key_seed))
- .map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
- match_data: EmptyMatchedCredential,
- })
- .collect::<Vec<_>>();
-
- let arena = deserialization_arena!();
-
- let cred_book =
- CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(&[], &creds);
-
- // check if the section header would be 0
- if section_configs.is_empty() {
- let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
- assert_eq!(
- v1_error,
- AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
- }
- ); //assert a adv deserialization error
- } else {
- let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
-
- let affected_sections: Vec<_> = section_configs
- .iter()
- .filter(|sc| {
- sc.identity
- .map(|sci| identities_to_remove.iter().any(|ks| &sci.key_seed == ks))
- .unwrap_or(false)
- })
- .collect();
-
- assert_eq!(affected_sections.len(), v1_contents.invalid_sections_count());
- assert_eq!(section_configs.len() - affected_sections.len(), v1_contents.sections.len());
-
- for (section_config, section) in section_configs
- .iter()
- // skip sections w/ removed identities
- .filter(|sc| {
- sc.identity.map(|i| !identities_to_remove.contains(&i.key_seed)).unwrap_or(true)
- })
- .zip(v1_contents.sections.iter())
- {
- assert_section_equals(section_config, section);
- }
- }
- }
-}
-
-fn assert_section_equals<M: MatchedCredential, C: CryptoProvider>(
- section_config: &SectionConfig<C>,
- section: &V1DeserializedSection<M>,
-) {
- match section_config.identity {
- None => match section {
- V1DeserializedSection::Plaintext(p) => {
- assert!(section_config.verification_mode.is_none());
-
- assert_eq!(section_config.plaintext_mode.unwrap(), p.identity());
- assert_eq!(
- section_config.data_elements,
- p.iter_data_elements().map(|de| (&de.unwrap()).into()).collect::<Vec<_>>()
- )
- }
- V1DeserializedSection::Decrypted(_) => panic!("no id, but decrypted section"),
- },
- Some(_) => match section {
- V1DeserializedSection::Plaintext(_) => panic!("id, but plaintext section"),
- V1DeserializedSection::Decrypted(wmc) => {
- assert!(section_config.plaintext_mode.is_none());
-
- assert_eq!(
- section_config.data_elements,
- wmc.contents()
- .iter_data_elements()
- .map(|de| (&de.unwrap()).into())
- .collect::<Vec<GenericDataElement>>()
- );
- assert_eq!(
- section_config.identity.unwrap().identity_type,
- wmc.contents().identity_type()
- );
- assert_eq!(
- section_config.identity.unwrap().extended_metadata_key,
- wmc.contents().metadata_key()
- );
- assert_eq!(
- section_config.verification_mode.unwrap(),
- wmc.contents().verification_mode()
- );
- }
- },
- }
-}
-
-fn deser_v1_error<'a, B, P>(
- arena: DeserializationArena<'a>,
- adv: &'a EncodedAdvertisement,
- cred_book: &'a B,
-) -> AdvDeserializationError
-where
- B: CredentialBook<'a>,
- P: CryptoProvider,
-{
- let v1_contents = match deserialize_advertisement::<_, P>(arena, adv.as_slice(), cred_book) {
- Err(e) => e,
- _ => panic!("Expecting an error!"),
- };
- v1_contents
-}
-
-fn deser_v1<'adv, B, P>(
- arena: DeserializationArena<'adv>,
- adv: &'adv EncodedAdvertisement,
- cred_book: &'adv B,
-) -> V1AdvertisementContents<'adv, B::Matched>
-where
- B: CredentialBook<'adv>,
- P: CryptoProvider,
-{
- deserialize_advertisement::<_, P>(arena, adv.as_slice(), cred_book)
- .expect("Should be a valid advertisement")
- .into_v1()
- .expect("Should be V1")
-}
-
-/// Populate a random number of sections with randomly chosen identities and random DEs
-fn fill_plaintext_adv<'a, R: rand::Rng, C: CryptoProvider>(
- mut rng: &mut R,
- adv_builder: &mut AdvBuilder,
-) -> Vec<SectionConfig<'a, C>> {
- let mut expected = Vec::new();
- // build sections
- for _ in 0..rng.gen_range(0..=NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT) {
- let res = adv_builder.section_builder(PublicSectionEncoder::default()).map(|s| {
- SectionConfig::new(
- None,
- Some(PlaintextIdentityMode::Public),
- None,
- add_des(s, &mut rng),
- )
- });
- match res {
- Ok(tuple) => expected.push(tuple),
- Err(_) => {
- // couldn't fit that section; maybe another smaller section will fit
- continue;
- }
- }
- }
- expected
-}
-
-/// Populate a random number of sections with randomly chosen identities and random DEs
-fn fill_encrypted_adv<'a, R: rand::Rng, C: CryptoProvider>(
- mut rng: &mut R,
- identities: &'a Vec<TestIdentity<C>>,
- adv_builder: &mut AdvBuilder,
-) -> Vec<SectionConfig<'a, C>> {
- let mut expected = Vec::new();
- let mut salt_rng = C::CryptoRng::new();
- // build sections
- for _ in 0..rng.gen_range(0..=6) {
- let chosen_index = rng.gen_range(0..identities.len());
- let identity = &identities[chosen_index];
-
- let broadcast_cm = identity.broadcast_credential();
-
- let res = if rng.gen_bool(0.5) {
- adv_builder
- .section_builder(MicEncryptedSectionEncoder::<C>::new_random_salt(
- &mut salt_rng,
- identity.identity_type,
- &broadcast_cm,
- ))
- .map(|s| {
- SectionConfig::new(
- Some(identity),
- None,
- Some(VerificationMode::Mic),
- add_des(s, &mut rng),
- )
- })
- } else {
- adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<C>::new_random_salt(
- &mut salt_rng,
- identity.identity_type,
- &broadcast_cm,
- ))
- .map(|s| {
- SectionConfig::new(
- Some(identity),
- None,
- Some(VerificationMode::Signature),
- add_des(s, &mut rng),
- )
- })
- };
- match res {
- Ok(tuple) => expected.push(tuple),
- Err(_) => {
- // couldn't fit that section; maybe another smaller section will fit
- continue;
- }
- }
- }
- expected
-}
-
-struct TestIdentity<C: CryptoProvider> {
- identity_type: EncryptedIdentityDataElementType,
- key_seed: [u8; 32],
- extended_metadata_key: MetadataKey,
- key_pair: np_ed25519::KeyPair<C>,
- marker: PhantomData<C>,
-}
-impl<C: CryptoProvider> TestIdentity<C> {
- /// Generate a new identity with random crypto material
- fn random<R: rand::Rng + rand::CryptoRng>(rng: &mut R) -> Self {
- Self {
- identity_type: *EncryptedIdentityDataElementType::iter()
- .collect::<Vec<_>>()
- .choose(rng)
- .unwrap(),
- key_seed: rng.gen(),
- extended_metadata_key: MetadataKey(rng.gen()),
- key_pair: np_ed25519::KeyPair::<C>::generate(),
- marker: PhantomData,
- }
- }
- /// Returns a (simple, signed) broadcast credential using crypto material from this identity
- fn broadcast_credential(&self) -> SimpleSignedBroadcastCryptoMaterial {
- SimpleSignedBroadcastCryptoMaterial::new(
- self.key_seed,
- self.extended_metadata_key,
- self.key_pair.private_key(),
- )
- }
- /// Returns a discovery credential using crypto material from this identity
- fn discovery_credential(&self) -> V1DiscoveryCredential {
- self.broadcast_credential().derive_v1_discovery_credential::<C>()
- }
-}
-/// Add several DEs with random types and contents
-fn add_des<I: SectionEncoder, R: rand::Rng>(
- mut sb: SectionBuilder<&mut AdvBuilder, I>,
- rng: &mut R,
-) -> Vec<GenericDataElement> {
- let mut des = Vec::new();
- for _ in 0..rng.gen_range(0..=2) {
- // not worried about multi byte type encoding here, so just sticking with what can sometimes
- // fit in the 1-byte header, and isn't an identity element
- let de_type = rng.gen_range(10_u32..=20);
- // covers lengths that fit or don't fit in 3 bits (1 byte header)
- let de_len = rng.gen_range(0..=10);
- let mut de_data = vec![0; de_len];
- rng.fill(&mut de_data[..]);
- let de = GenericDataElement::try_from(de_type.into(), &de_data).unwrap();
- if sb.add_de(|_| de.clone()).is_err() {
- // no more room in the section
- break;
- }
- des.push(de);
- }
- sb.add_to_advertisement();
- des
-}
-struct SectionConfig<'a, C: CryptoProvider> {
- /// `Some` iff an encrypted identity should be used
- identity: Option<&'a TestIdentity<C>>,
- /// `Some` iff `identity` is `None`
- plaintext_mode: Option<PlaintextIdentityMode>,
- /// `Some` iff `identity` is `Some`
- verification_mode: Option<VerificationMode>,
- data_elements: Vec<GenericDataElement>,
-}
-impl<'a, C: CryptoProvider> SectionConfig<'a, C> {
- pub fn new(
- identity: Option<&'a TestIdentity<C>>,
- plaintext_mode: Option<PlaintextIdentityMode>,
- verification_mode: Option<VerificationMode>,
- data_elements: Vec<GenericDataElement>,
- ) -> Self {
- Self { identity, plaintext_mode, verification_mode, data_elements }
- }
-}
diff --git a/nearby/presence/np_adv/src/deserialization_arena.rs b/nearby/presence/np_adv/src/deserialization_arena.rs
index 9b58cbf..d0ab12e 100644
--- a/nearby/presence/np_adv/src/deserialization_arena.rs
+++ b/nearby/presence/np_adv/src/deserialization_arena.rs
@@ -15,7 +15,7 @@
//! Types for creating arenas used in deserialization of np_adv. This implementation is purpose-made
//! for deserializing in `np_adv` and is not intended for general use as an arena.
-use crate::extended::BLE_ADV_SVC_CONTENT_LEN;
+use crate::extended::BLE_5_ADV_SVC_MAX_CONTENT_LEN;
/// Create a [`DeserializationArena`] suitable for use with deserializing an advertisement.
#[macro_export]
@@ -64,13 +64,13 @@ impl<'a> DeserializationArenaAllocator<'a> {
/// [`deserialization_arena!`][crate::deserialization_arena!] macro to create an instance.
pub struct DeserializationArena<'a> {
#[doc(hidden)] // Exposed for use by `deserialization_arena!` only.
- pub buffer: &'a mut [u8; BLE_ADV_SVC_CONTENT_LEN],
+ pub buffer: &'a mut [u8; BLE_5_ADV_SVC_MAX_CONTENT_LEN],
}
impl<'a> DeserializationArena<'a> {
#[doc(hidden)] // Exposed for use by `deserialization_arena!` only.
- pub fn new_buffer() -> [u8; BLE_ADV_SVC_CONTENT_LEN] {
- [0; BLE_ADV_SVC_CONTENT_LEN]
+ pub fn new_buffer() -> [u8; BLE_5_ADV_SVC_MAX_CONTENT_LEN] {
+ [0; BLE_5_ADV_SVC_MAX_CONTENT_LEN]
}
/// Convert this arena into an allocator that can start allocating.
@@ -87,11 +87,11 @@ pub(crate) struct ArenaOutOfSpace;
#[cfg(test)]
mod test {
- use crate::{deserialization_arena::ArenaOutOfSpace, extended::BLE_ADV_SVC_CONTENT_LEN};
+ use crate::{deserialization_arena::ArenaOutOfSpace, extended::BLE_5_ADV_SVC_MAX_CONTENT_LEN};
#[test]
fn test_creation() {
- assert_eq!(BLE_ADV_SVC_CONTENT_LEN, deserialization_arena!().buffer.len());
+ assert_eq!(BLE_5_ADV_SVC_MAX_CONTENT_LEN, deserialization_arena!().buffer.len());
}
#[test]
@@ -99,7 +99,7 @@ mod test {
let arena = deserialization_arena!();
let mut allocator = arena.into_allocator();
assert_eq!(Ok(&mut [0_u8; 100][..]), allocator.allocate(100));
- assert_eq!(BLE_ADV_SVC_CONTENT_LEN - 100, allocator.slice.len());
+ assert_eq!(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 100, allocator.slice.len());
}
#[test]
diff --git a/nearby/presence/np_adv/src/extended/data_elements/mod.rs b/nearby/presence/np_adv/src/extended/data_elements/mod.rs
index 4e6e481..2989966 100644
--- a/nearby/presence/np_adv/src/extended/data_elements/mod.rs
+++ b/nearby/presence/np_adv/src/extended/data_elements/mod.rs
@@ -17,13 +17,15 @@
//! Commonly used DEs have dedicated types (e.g. [TxPowerDataElement], etc), but if another DE is
//! needed, [GenericDataElement] will allow constructing any type of DE.
-use crate::extended::{
- de_type::DeType,
- deserialize::DataElement,
- serialize::{DeHeader, SingleTypeDataElement, WriteDataElement},
- DeLength, ENCRYPTION_INFO_DE_TYPE, MAX_DE_LEN,
+use crate::{
+ extended::{
+ de_type::DeType,
+ deserialize::data_element::DataElement,
+ serialize::{DeHeader, SingleTypeDataElement, WriteDataElement},
+ MAX_DE_LEN,
+ },
+ shared_data::*,
};
-use crate::shared_data::*;
use array_view::ArrayView;
use sink::Sink;
@@ -138,54 +140,6 @@ pub enum ActionsDataElementError {
ActionsTooLong,
}
-pub(crate) const SIGNATURE_ENCRYPTION_SCHEME: u8 = 0b00001000;
-pub(crate) const MIC_ENCRYPTION_SCHEME: u8 = 0b00000000;
-
-/// Determines whether a signature or mic encryption scheme is used
-pub(crate) struct EncryptionInfoDataElement {
- /// First byte is bESSSSRRR where SSSS is the encryption scheme, rest are the salt
- pub info: [u8; 17],
-}
-
-impl SingleTypeDataElement for EncryptionInfoDataElement {
- const DE_TYPE: DeType = ENCRYPTION_INFO_DE_TYPE;
-}
-
-impl EncryptionInfoDataElement {
- pub(crate) fn serialize(&self) -> [u8; 19] {
- let mut buffer = [0_u8; 19];
- buffer[0..2].copy_from_slice(self.de_header().serialize().as_slice());
- buffer[2..19].copy_from_slice(&self.info);
- buffer
- }
-
- fn de_header(&self) -> DeHeader {
- DeHeader::new(
- Self::DE_TYPE,
- DeLength {
- len: self.info.len().try_into().expect("encryption info is a valid length"),
- },
- )
- }
-
- /// Constructs the signature encryption scheme variant
- pub fn signature(salt_bytes: &[u8; 16]) -> Self {
- Self::new(SIGNATURE_ENCRYPTION_SCHEME, salt_bytes)
- }
-
- /// Constructs the mic encryption scheme variant
- pub fn mic(salt_bytes: &[u8; 16]) -> Self {
- Self::new(MIC_ENCRYPTION_SCHEME, salt_bytes)
- }
-
- fn new(scheme: u8, salt_bytes: &[u8; 16]) -> Self {
- let mut sig_info = [0_u8; 17];
- sig_info[0] = scheme;
- sig_info[1..].copy_from_slice(salt_bytes);
- Self { info: sig_info }
- }
-}
-
/// Context sync sequence number
pub struct ContextSyncSeqNumDataElement {
num: ContextSyncSeqNum,
diff --git a/nearby/presence/np_adv/src/extended/data_elements/tests.rs b/nearby/presence/np_adv/src/extended/data_elements/tests.rs
index 6f085cd..018f92c 100644
--- a/nearby/presence/np_adv/src/extended/data_elements/tests.rs
+++ b/nearby/presence/np_adv/src/extended/data_elements/tests.rs
@@ -17,51 +17,52 @@
extern crate std;
use super::*;
-use crate::extended::serialize::AdvertisementType;
-use crate::{
- extended::serialize::{section_tests::SectionBuilderExt, AdvBuilder, PublicSectionEncoder},
- shared_data::TxPower,
-};
+use crate::extended::serialize::{section_tests::SectionBuilderExt, AdvBuilder};
+use crate::extended::serialize::{AdvertisementType, UnencryptedSectionEncoder};
+use crate::extended::V1_ENCODING_UNENCRYPTED;
+use crypto_provider_default::CryptoProviderImpl;
#[test]
fn serialize_tx_power_de() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder.add_de_res(|_| TxPower::try_from(3_i8).map(TxPowerDataElement::from)).unwrap();
assert_eq!(
&[
- 3, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 2, // section len
0x15, // len 1 type 0x05
3
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
#[test]
fn serialize_actions_de_empty() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder.add_de_res(|_| ActionsDataElement::try_from_actions(&[])).unwrap();
assert_eq!(
&[
- 2, // section header
- 0x03, // public identity
- 0x06, // len 0 type 0x06
+ V1_ENCODING_UNENCRYPTED, //header
+ 1, // section len
+ 0x06, // len 0 type 0x06
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_actions_de_non_empty() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de_res(|_| ActionsDataElement::try_from_actions(&[1, 1, 2, 3, 5, 8]))
@@ -69,19 +70,21 @@ fn serialize_actions_de_non_empty() {
assert_eq!(
&[
- 8, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 7, // section len
0x66, // len 6 type 0x06
1, 1, 2, 3, 5, 8 // fibonacci, of course
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_context_sync_seq_num_de() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de_res(|_| ContextSyncSeqNum::try_from(3).map(ContextSyncSeqNumDataElement::from))
@@ -89,59 +92,65 @@ fn serialize_context_sync_seq_num_de() {
assert_eq!(
&[
- 4, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 3, // section len
0x81, 0x13, // len 1 type 0x13
3, // seq num
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_connectivity_info_de_bluetooth() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder.add_de(|_| ConnectivityInfoDataElement::bluetooth([1; 4], [2; 6])).unwrap();
assert_eq!(
&[
- 14, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 13, // section len
0x8B, 0x11, // len 11 type 0x11
1, // connectivity type
1, 1, 1, 1, // svc id
2, 2, 2, 2, 2, 2 // mac
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_connectivity_info_de_mdns() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder.add_de(|_| ConnectivityInfoDataElement::mdns([1; 4], 2)).unwrap();
assert_eq!(
&[
- 9, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 8, // section len
0x86, 0x11, // len 11 type 0x11
2, // connectivity type
1, 1, 1, 1, // svc id
2 // port
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_connectivity_info_de_wifi_direct() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de(|_| ConnectivityInfoDataElement::wifi_direct([1; 10], [2; 10], [3; 2], 4))
@@ -149,8 +158,8 @@ fn serialize_connectivity_info_de_wifi_direct() {
assert_eq!(
&[
- 27, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 26, // section len
0x98, 0x11, // len 24 type 0x11
3, // connectivity type
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // ssid
@@ -158,14 +167,16 @@ fn serialize_connectivity_info_de_wifi_direct() {
3, 3, // freq
4 // port
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+#[rustfmt::skip]
#[test]
fn serialize_connectivity_capabilities_de_wifi_direct() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de(|_| ConnectivityCapabilityDataElement::wifi_direct([1; 3], [2; 3]))
@@ -173,13 +184,46 @@ fn serialize_connectivity_capabilities_de_wifi_direct() {
assert_eq!(
&[
- 10, // section header
- 0x03, // public identity
+ V1_ENCODING_UNENCRYPTED,
+ 9, // section len
0x87, 0x12, // len 7 type 0x12
2, // connectivity type
1, 1, 1, // supported
2, 2, 2, // connected
],
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
+
+mod coverage_gaming {
+ use super::*;
+ use alloc::format;
+ #[test]
+ fn de_type_const_from() {
+ let _ = DeType::const_from(3);
+ }
+
+ #[test]
+ fn template() {}
+
+ #[test]
+ fn generic_de_error_derives() {
+ let err = GenericDataElementError::DataTooLong;
+ let _ = format!("{:?}", err);
+ assert_eq!(err, err);
+ }
+
+ #[test]
+ fn actions_de_error_derives() {
+ let err = ActionsDataElementError::ActionsTooLong;
+ let _ = format!("{:?}", err);
+ assert_eq!(err, err);
+ }
+
+ #[test]
+ fn generic_data_element_debug() {
+ let generic =
+ GenericDataElement::try_from(DeType::from(1000_u32), &[10, 11, 12, 13]).unwrap();
+ let _ = format!("{:?}", generic);
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/de_type.rs b/nearby/presence/np_adv/src/extended/de_type.rs
index 975df90..baefe6a 100644
--- a/nearby/presence/np_adv/src/extended/de_type.rs
+++ b/nearby/presence/np_adv/src/extended/de_type.rs
@@ -13,10 +13,9 @@
// limitations under the License.
//! V1 DE type types
-use crate::de_type::{EncryptedIdentityDataElementType, IdentityDataElementType};
/// Data element types for extended advertisements
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct DeType {
// 4 billion type codes should be enough for anybody
code: u32,
@@ -52,98 +51,13 @@ impl From<DeType> for u32 {
}
}
-pub(crate) trait ExtendedDataElementType: Sized {
- /// A type code for use in the DE header.
- fn type_code(&self) -> DeType;
- /// Returns the matching type for the code, else `None`
- fn from_type_code(de_type: DeType) -> Option<Self>;
-}
-
-impl ExtendedDataElementType for IdentityDataElementType {
- fn type_code(&self) -> DeType {
- DeType::from(self.shared_type_code())
- }
-
- fn from_type_code(de_type: DeType) -> Option<Self> {
- de_type.code.try_into().ok().and_then(Self::from_shared_type_code)
- }
-}
-
-impl ExtendedDataElementType for EncryptedIdentityDataElementType {
- fn type_code(&self) -> DeType {
- DeType::from(self.as_identity_data_element_type().shared_type_code())
- }
-
- fn from_type_code(code: DeType) -> Option<Self> {
- IdentityDataElementType::from_type_code(code)
- .and_then(|idet| idet.as_encrypted_identity_de_type())
- }
-}
-
#[cfg(test)]
-mod tests {
- extern crate std;
-
- use super::*;
- use std::{collections, fmt};
+mod test {
+ use crate::extended::de_type::DeType;
#[test]
- fn identity_type_codes_are_consistent() {
- de_type_codes_are_consistent::<IdentityDataElementType>()
- }
-
- #[test]
- fn encrypted_identity_type_codes_are_consistent() {
- de_type_codes_are_consistent::<EncryptedIdentityDataElementType>()
- }
-
- #[test]
- fn identity_type_codes_are_distinct() {
- de_distinct_type_codes::<IdentityDataElementType>()
- }
-
- #[test]
- fn encrypted_identity_type_codes_are_distinct() {
- de_distinct_type_codes::<EncryptedIdentityDataElementType>()
- }
-
- #[test]
- fn identity_no_accidentally_mapped_type_codes() {
- de_no_accidentally_mapped_type_codes::<IdentityDataElementType>()
- }
-
- #[test]
- fn encrypted_identity_no_accidentally_mapped_type_codes() {
- de_no_accidentally_mapped_type_codes::<EncryptedIdentityDataElementType>()
- }
-
- fn de_type_codes_are_consistent<
- D: PartialEq + fmt::Debug + ExtendedDataElementType + strum::IntoEnumIterator,
- >() {
- for det in D::iter() {
- let actual = D::from_type_code(det.type_code());
- assert_eq!(Some(det), actual)
- }
- }
-
- fn de_distinct_type_codes<
- D: PartialEq + fmt::Debug + ExtendedDataElementType + strum::IntoEnumIterator,
- >() {
- let codes = D::iter().map(|det| det.type_code()).collect::<collections::HashSet<_>>();
- assert_eq!(codes.len(), D::iter().count());
- }
-
- fn de_no_accidentally_mapped_type_codes<
- D: PartialEq + fmt::Debug + ExtendedDataElementType + strum::IntoEnumIterator,
- >() {
- let codes = D::iter().map(|det| det.type_code()).collect::<collections::HashSet<_>>();
- // not going to try all 4 billion possibilities, but we can make an effort
- for possible_code in 0_u32..100_000 {
- if codes.contains(&possible_code.into()) {
- continue;
- }
-
- assert_eq!(None, D::from_type_code(possible_code.into()));
- }
+ fn u32_from_de_type() {
+ let de = DeType::from(8u32);
+ let _val: u32 = de.into();
}
}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/data_element/mod.rs b/nearby/presence/np_adv/src/extended/deserialize/data_element/mod.rs
new file mode 100644
index 0000000..e717fa1
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/data_element/mod.rs
@@ -0,0 +1,260 @@
+// 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.
+
+//! Parsing logic for V1 data elements, header + contents
+
+use crate::extended::{de_requires_extended_bit, de_type::DeType, deserialize, DeLength};
+use array_view::ArrayView;
+use nom::{branch, bytes, combinator, error, number, sequence};
+use np_hkdf::v1_salt;
+
+#[cfg(test)]
+mod tests;
+
+/// A deserialized data element in a section.
+///
+/// The DE has been processed to the point of exposing a DE type and its contents as a `&[u8]`, but
+/// no DE-type-specific processing has been performed.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct DataElement<'adv> {
+ offset: v1_salt::DataElementOffset,
+ de_type: DeType,
+ contents: &'adv [u8],
+}
+
+impl<'adv> DataElement<'adv> {
+ pub(crate) fn new(
+ offset: v1_salt::DataElementOffset,
+ de_type: DeType,
+ contents: &'adv [u8],
+ ) -> Self {
+ Self { offset, de_type, contents }
+ }
+}
+
+impl DeHeader {
+ pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], DeHeader> {
+ // 1-byte header: 0b0LLLTTTT
+ let parse_single_byte_de_header =
+ combinator::map_opt::<&[u8], _, DeHeader, error::Error<&[u8]>, _, _>(
+ combinator::consumed(combinator::map_res(
+ combinator::verify(number::complete::u8, |&b| !deserialize::hi_bit_set(b)),
+ |b| {
+ // L bits
+ let len = (b >> 4) & 0x07;
+ // T bits
+ let de_type = ((b & 0x0F) as u32).into();
+
+ len.try_into().map(|l| (l, de_type))
+ },
+ )),
+ |(header_bytes, (len, de_type))| {
+ ArrayView::try_from_slice(header_bytes).map(|header_bytes| DeHeader {
+ header_bytes,
+ contents_len: len,
+ de_type,
+ })
+ },
+ );
+
+ // multi-byte headers: 0b1LLLLLLL (0b1TTTTTTT)* 0b0TTTTTTT
+ // leading 1 in first byte = multibyte format
+ // leading 1 in subsequent bytes = there is at least 1 more type bytes
+ // leading 0 = this is the last header byte
+ // 127-bit length, effectively infinite type bit length
+
+ // It's conceivable to have non-canonical extended type sequences where 1 or more leading
+ // bytes don't have any bits set (other than the marker hi bit), thereby contributing nothing
+ // to the final value.
+ // To prevent that, we require that either there be only 1 type byte, or that the first of the
+ // multiple type bytes must have a value bit set. It's OK to have no value bits in subsequent
+ // type bytes.
+
+ let parse_ext_de_header = combinator::verify(
+ combinator::map_opt(
+ combinator::consumed(sequence::pair(
+ // length byte w/ leading 1
+ combinator::map_res(
+ combinator::verify(number::complete::u8::<&[u8], _>, |&b| {
+ deserialize::hi_bit_set(b)
+ }),
+ // snag the lower 7 bits
+ |b| (b & 0x7F).try_into(),
+ ),
+ branch::alt((
+ // 1 type byte case
+ combinator::recognize(
+ // 0-hi-bit type code byte
+ combinator::verify(number::complete::u8, |&b| {
+ !deserialize::hi_bit_set(b)
+ }),
+ ),
+ // multiple type byte case: leading type byte must have at least 1 value bit
+ combinator::recognize(sequence::tuple((
+ // hi bit and at least 1 value bit, otherwise it would be non-canonical
+ combinator::verify(number::complete::u8, |&b| {
+ deserialize::hi_bit_set(b) && (b & 0x7F != 0)
+ }),
+ // 0-3 1-hi-bit type code bytes with any bit pattern. Max is 3 since two 7
+ // bit type chunks are processed before and after this, for a total of 5,
+ // and that's as many 7-bit chunks as are needed to support a 32-bit type.
+ bytes::complete::take_while_m_n(0, 3, deserialize::hi_bit_set),
+ // final 0-hi-bit type code byte
+ combinator::verify(number::complete::u8, |&b| {
+ !deserialize::hi_bit_set(b)
+ }),
+ ))),
+ )),
+ )),
+ |(header_bytes, (len, type_bytes))| {
+ // snag the low 7 bits of each type byte and accumulate
+ type_bytes
+ .iter()
+ .try_fold(0_u64, |accum, b| {
+ accum.checked_shl(7).map(|n| n + ((b & 0x7F) as u64))
+ })
+ .and_then(|type_code| u32::try_from(type_code).ok())
+ .and_then(|type_code| {
+ ArrayView::try_from_slice(header_bytes).map(|header_bytes| DeHeader {
+ header_bytes,
+ contents_len: len,
+ de_type: type_code.into(),
+ })
+ })
+ },
+ ),
+ |header| {
+ // verify that the length and type code actually require use of the extended bit
+ de_requires_extended_bit(header.de_type.as_u32(), header.contents_len.len)
+ },
+ );
+
+ branch::alt((parse_single_byte_de_header, parse_ext_de_header))(input)
+ }
+}
+
+impl<'adv> DataElement<'adv> {
+ /// The offset of the DE in its containing Section.
+ ///
+ /// Used with the section salt to derive per-DE salt.
+ pub fn offset(&self) -> v1_salt::DataElementOffset {
+ self.offset
+ }
+ /// The type of the DE
+ pub fn de_type(&self) -> DeType {
+ self.de_type
+ }
+ /// The contents of the DE
+ pub fn contents(&self) -> &'adv [u8] {
+ self.contents
+ }
+}
+
+/// An iterator that parses the given data elements iteratively. In environments where memory is
+/// not severely constrained, it is usually safer to collect this into `Result<Vec<DataElement>>`
+/// so the validity of the whole advertisement can be checked before proceeding with further
+/// processing.
+#[derive(Debug)]
+pub struct DataElementParsingIterator<'adv> {
+ input: &'adv [u8],
+ // The index of the data element this is currently at
+ offset: u8,
+}
+
+impl<'adv> DataElementParsingIterator<'adv> {
+ pub(crate) fn new(input: &'adv [u8]) -> Self {
+ Self { input, offset: 0 }
+ }
+}
+
+impl<'adv> Iterator for DataElementParsingIterator<'adv> {
+ type Item = Result<DataElement<'adv>, DataElementParseError>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match ProtoDataElement::parse(self.input) {
+ Ok((rem, pde)) => {
+ self.input = rem;
+ let current_offset = self.offset;
+ self.offset = if let Some(offset) = self.offset.checked_add(1) {
+ offset
+ } else {
+ return Some(Err(DataElementParseError::TooManyDataElements));
+ };
+ Some(Ok(pde.into_data_element(v1_salt::DataElementOffset::from(current_offset))))
+ }
+ Err(nom::Err::Failure(e)) => Some(Err(DataElementParseError::NomError(e.code))),
+ Err(nom::Err::Incomplete(_)) => {
+ panic!("Should always complete since we are parsing using the `nom::complete` APIs")
+ }
+ Err(nom::Err::Error(_)) => {
+ // nom `Error` is recoverable, it usually means we should move on the parsing the
+ // next section. There is nothing after data elements within a section, so we just
+ // check that there is no remaining data.
+ if !self.input.is_empty() {
+ return Some(Err(DataElementParseError::UnexpectedDataAfterEnd));
+ }
+ None
+ }
+ }
+ }
+}
+
+/// The error that may arise while parsing data elements.
+#[derive(Debug, PartialEq, Eq)]
+pub enum DataElementParseError {
+ /// Unexpected data found after the end of the data elements portion. This means either the
+ /// parser was fed with additional data (it should only be given the bytes within a section,
+ /// not the whole advertisement), or the length field in the header of the data element is
+ /// malformed.
+ UnexpectedDataAfterEnd,
+ /// There are too many data elements in the advertisement. The maximum number supported by the
+ /// current parsing logic is 255.
+ TooManyDataElements,
+ /// A parse error is returned during nom.
+ NomError(error::ErrorKind),
+}
+
+/// Deserialize-specific version of a DE header that incorporates the header length.
+/// This is needed for encrypted identities that need to construct a slice of everything in the
+/// section following the identity DE header.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub(crate) struct DeHeader {
+ /// The original bytes of the header, at most 6 bytes long (1 byte len, 5 bytes type)
+ pub(crate) header_bytes: ArrayView<u8, 6>,
+ pub(crate) de_type: DeType,
+ pub(crate) contents_len: DeLength,
+}
+
+/// An intermediate stage in parsing a [DataElement] that lacks `offset`.
+#[derive(Debug, PartialEq, Eq)]
+pub struct ProtoDataElement<'d> {
+ header: DeHeader,
+ /// `len()` must equal `header.contents_len`
+ contents: &'d [u8],
+}
+
+impl<'d> ProtoDataElement<'d> {
+ pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], ProtoDataElement> {
+ let (remaining, header) = DeHeader::parse(input)?;
+ let len = header.contents_len;
+ combinator::map(bytes::complete::take(len.as_u8()), move |slice| {
+ let header_clone = header.clone();
+ ProtoDataElement { header: header_clone, contents: slice }
+ })(remaining)
+ }
+
+ fn into_data_element(self, offset: v1_salt::DataElementOffset) -> DataElement<'d> {
+ DataElement::new(offset, self.header.de_type, self.contents)
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/data_element/tests.rs b/nearby/presence/np_adv/src/extended/deserialize/data_element/tests.rs
new file mode 100644
index 0000000..473cf37
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/data_element/tests.rs
@@ -0,0 +1,348 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+use super::*;
+use alloc::{vec, vec::Vec};
+
+#[test]
+fn parse_de_single_byte_header_length_overrun() {
+ // length 7, type 0x03
+ let input = [0b0111_0011, 0x01, 0x02];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // attempted to read DE contents
+ input: &input.as_slice()[1..],
+ code: error::ErrorKind::Eof,
+ }),
+ ProtoDataElement::parse(&input).unwrap_err()
+ );
+}
+
+#[test]
+fn parse_de_multi_byte_header_length_overrun() {
+ let input = [0b1000_0111, 0x1F, 0x01, 0x02];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // attempted to read DE contents
+ input: &input.as_slice()[2..],
+ code: error::ErrorKind::Eof,
+ }),
+ ProtoDataElement::parse(&input).unwrap_err()
+ );
+}
+
+#[test]
+fn parse_de_with_1_byte_header() {
+ let data = [0x51, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[6..],
+ ProtoDataElement {
+ header: DeHeader {
+ de_type: 1_u8.into(),
+ header_bytes: ArrayView::try_from_slice(&[0x51]).unwrap(),
+ contents_len: 5_u8.try_into().unwrap(),
+ },
+ contents: &data[1..6],
+ }
+ )),
+ ProtoDataElement::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_with_2_byte_header() {
+ let data = [0x85, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[7..],
+ ProtoDataElement {
+ header: DeHeader {
+ de_type: 16_u8.into(),
+ header_bytes: ArrayView::try_from_slice(&[0x85, 0x10]).unwrap(),
+ contents_len: 5_u8.try_into().unwrap(),
+ },
+ contents: &data[2..7],
+ }
+ )),
+ ProtoDataElement::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_with_3_byte_header() {
+ let data = [0x85, 0xC1, 0x41, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[8..],
+ ProtoDataElement {
+ header: DeHeader {
+ header_bytes: ArrayView::try_from_slice(&[0x85, 0xC1, 0x41]).unwrap(),
+ contents_len: 5_u8.try_into().unwrap(),
+ de_type: 0b0000_0000_0000_0000_0010_0000_1100_0001_u32.into(),
+ },
+ contents: &data[3..8],
+ }
+ )),
+ ProtoDataElement::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_header_1_byte() {
+ let data = [0x51, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[1..],
+ DeHeader {
+ de_type: 1_u8.into(),
+ contents_len: 5_u8.try_into().unwrap(),
+ header_bytes: ArrayView::try_from_slice(&[0x51]).unwrap(),
+ }
+ )),
+ DeHeader::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_header_2_bytes() {
+ let data = [0x88, 0x01];
+ assert_eq!(
+ Ok((
+ &data[2..],
+ DeHeader {
+ de_type: 1_u8.into(),
+ contents_len: 8_u8.try_into().unwrap(),
+ header_bytes: ArrayView::try_from_slice(&[0x88, 0x01]).unwrap(),
+ }
+ )),
+ DeHeader::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_header_3_bytes() {
+ let data = [0x83, 0xC1, 0x41, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[3..],
+ DeHeader {
+ de_type: 0b0000_0000_0000_0000_0010_0000_1100_0001_u32.into(),
+ contents_len: 3_u8.try_into().unwrap(),
+ header_bytes: ArrayView::try_from_slice(&[0x83, 0xC1, 0x41]).unwrap(),
+ }
+ )),
+ DeHeader::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_header_4_bytes() {
+ let data = [0x83, 0xC1, 0xC1, 0x41, 0xFF, 0xFF];
+ assert_eq!(
+ Ok((
+ &data[4..],
+ DeHeader {
+ de_type: 0b0000_0000_0001_0000_0110_0000_1100_0001_u32.into(),
+ contents_len: 3_u8.try_into().unwrap(),
+ header_bytes: ArrayView::try_from_slice(&[0x83, 0xC1, 0xC1, 0x41]).unwrap(),
+ }
+ )),
+ DeHeader::parse(&data)
+ );
+}
+
+#[test]
+fn parse_de_header_max_length_extension() {
+ // 1 byte length + 5 bytes of type is the max possible length of an extended DE header.
+ // The first 3 bits of type will be discarded by the left shift, so if an extended DE header
+ // does make it to 5 bytes, we will only read the least significant 32 bits out of a possible 35.
+ // The contents of the most significant 3 bits of type code must be 0's, otherwise the adv will
+ // be discarded
+ let data = [0x80, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F];
+ assert_eq!(
+ Ok((
+ &data[6..],
+ DeHeader {
+ de_type: u32::MAX.into(),
+ contents_len: 0_u8.try_into().unwrap(),
+ header_bytes: ArrayView::try_from_slice(&[0x80, 0x8F, 0xFF, 0xFF, 0xFF, 0x7F])
+ .unwrap(),
+ }
+ )),
+ DeHeader::parse(&data)
+ );
+}
+
+// In a 6 byte extended de header, if any bits are non-zero in the most 3 significant bits of type,
+// the parsing will fail as this would be out of range of a valid u32 value.
+#[test]
+fn parse_de_6_byte_header_invalid_significant_bits() {
+ assert!(DeHeader::parse(&[0x80, 0x9F, 0xFF, 0xFF, 0xFF, 0x7F]).is_err());
+ assert!(DeHeader::parse(&[0x80, 0xCF, 0xFF, 0xFF, 0xFF, 0x7F]).is_err());
+ assert!(DeHeader::parse(&[0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]).is_err());
+}
+
+#[test]
+fn parse_de_header_over_max_length_extension() {
+ // last header byte cannot contain a leading 1
+ let data = [0x80, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // failed parsing the last byte
+ input: &data.as_slice()[5..],
+ code: error::ErrorKind::Verify,
+ }),
+ DeHeader::parse(&data).unwrap_err()
+ );
+}
+
+// Test edge cases which can be represented in fewer bytes
+#[test]
+fn parse_de_header_invalid_multi_byte_type_code() {
+ // extended length and type codes which can be represented in a single byte
+ assert!(DeHeader::parse(&[0b1000_0000, 0b000_0000]).is_err());
+ assert!(DeHeader::parse(&[0b1000_0000, 0b000_0001]).is_err());
+ assert!(DeHeader::parse(&[0b1000_0111, 0b000_1111]).is_err());
+
+ // first byte of type doesn't have any bits in it so it contributes nothing
+ assert!(DeHeader::parse(&[0b1000_0111, 0b1000_0000, 0b0100_0000]).is_err());
+ // first 2 bytes of type are unnecessary
+ assert!(DeHeader::parse(&[0b1000_0001, 0b1000_0000, 0b1000_0000, 0b1100_0000]).is_err());
+
+ // extended bit set with no following byte
+ assert!(DeHeader::parse(&[0b1000_0001, 0b1000_0000]).is_err());
+
+ // needs one extra bit of length so must use extended
+ assert!(DeHeader::parse(&[0b100_1111, 0b000_1111]).is_ok());
+
+ // needs one extra bit of type so must use extended
+ assert!(DeHeader::parse(&[0b100_0111, 0b001_1111]).is_ok());
+
+ // valid to trail with all 0's for a larger type code
+ assert!(DeHeader::parse(&[0b100_1111, 0b1000_0001, 0b0000_0000]).is_ok());
+
+ // valid to trail with all 0's in middle of type code
+ assert!(DeHeader::parse(&[0b100_1111, 0b1000_0001, 0b1000_0000, 0b0000_0001]).is_ok());
+}
+
+#[test]
+fn de_iteration_exposes_correct_data() {
+ let mut de_data = vec![];
+ // de 1 byte header, type 5, len 5
+ de_data.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 16, len 1
+ de_data.extend_from_slice(&[0x81, 0x10, 0x01]);
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ let des = iterator.collect::<Result<Vec<_>, _>>().unwrap();
+
+ assert_eq!(
+ vec![
+ DataElement::new(0.into(), 5_u32.into(), &[0x01, 0x02, 0x03, 0x04, 0x05]),
+ DataElement::new(1.into(), 16_u32.into(), &[0x01]),
+ ],
+ des
+ );
+}
+
+#[test]
+fn de_iteration_single_de() {
+ let mut de_data = vec![];
+ // de 2 byte header, type 16, len 1
+ de_data.extend_from_slice(&[0x81, 0x10, 0x01]);
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ let des = iterator.collect::<Result<Vec<_>, _>>().unwrap();
+
+ assert_eq!(vec![DataElement::new(0.into(), 16_u32.into(), &[0x01]),], des);
+}
+
+#[test]
+fn de_iteration_single_de_empty_contents() {
+ let mut de_data = vec![];
+ // de 1 byte header, type 1, len 0
+ de_data.extend_from_slice(&[0x01]);
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ let des = iterator.collect::<Result<Vec<_>, _>>().unwrap();
+
+ assert_eq!(vec![DataElement::new(0.into(), 1_u32.into(), &[])], des);
+}
+
+#[test]
+fn de_iteration_max_number_des() {
+ let mut de_data = vec![];
+ // de 1 byte header, type 1, len 0
+ // add this 255 times which is the max amount of
+ // supported DEs in a single section
+ for _ in 0..255 {
+ de_data.extend_from_slice(&[0x01]);
+ }
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ assert!(iterator.collect::<Result<Vec<_>, _>>().is_ok());
+}
+
+#[test]
+fn de_iteration_over_max_number_des() {
+ let mut de_data = vec![];
+ // de 1 byte header, type 1, len 0
+ // add this 256 times to exceed max number of des in a section
+ for _ in 0..256 {
+ de_data.extend_from_slice(&[0x01]);
+ }
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ assert_eq!(
+ iterator.collect::<Result<Vec<_>, _>>(),
+ Err(DataElementParseError::TooManyDataElements)
+ );
+}
+
+#[test]
+fn de_parse_error_invalid_length_header() {
+ let mut de_data = vec![];
+ // de 1 byte header, type 1, len 2, but only one byte left to process
+ de_data.extend_from_slice(&[0x21, 0x00]);
+
+ let iterator = DataElementParsingIterator::new(&de_data);
+ assert_eq!(
+ iterator.collect::<Result<Vec<_>, _>>(),
+ Err(DataElementParseError::UnexpectedDataAfterEnd)
+ );
+}
+
+mod coverage_gaming {
+ use super::*;
+ use alloc::format;
+
+ #[allow(clippy::clone_on_copy)]
+ #[test]
+ fn data_element_debug_and_clone() {
+ let de = DataElement::new(0.into(), 0_u32.into(), &[]);
+ let _ = format!("{:?}", de);
+ let _ = de.clone();
+ let iterator = DataElementParsingIterator::new(&[]);
+ let _ = format!("{:?}", iterator);
+ let _ = format!("{:?}", DataElementParseError::TooManyDataElements);
+ let (_, header) = DeHeader::parse(&[0x11, 0xFF]).unwrap();
+ let _ = format!("{:?}", header);
+ let _ = header.clone();
+ let (_, pde) = ProtoDataElement::parse(&[0x11, 0xFF]).unwrap();
+ let _ = format!("{:?}", pde);
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/dev_tools.rs b/nearby/presence/np_adv/src/extended/deserialize/dev_tools.rs
new file mode 100644
index 0000000..e77e083
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/dev_tools.rs
@@ -0,0 +1,87 @@
+// 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.
+
+use core::fmt::Debug;
+
+use crate::deserialization_arena::DeserializationArena;
+use array_view::ArrayView;
+use crypto_provider::CryptoProvider;
+
+use crate::extended::deserialize::section::intermediate::{
+ parse_sections, CiphertextSection, IntermediateSection,
+};
+use crate::extended::NP_ADV_MAX_SECTION_LEN;
+use crate::{credential::book::CredentialBook, header::V1AdvHeader};
+
+/// Error in decryption operations for `deser_decrypt_v1_section_bytes_for_dev_tools`.
+#[derive(Debug, Clone)]
+pub enum AdvDecryptionError {
+ /// Cannot decrypt because the input section is not encrypted.
+ InputNotEncrypted,
+ /// Error parsing the given section.
+ ParseError,
+ /// No suitable credential found to decrypt the given section.
+ NoMatchingCredentials,
+}
+
+/// The encryption scheme used for a V1 advertisement.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum V1EncryptionScheme {
+ /// Indicates MIC-based encryption and verification.
+ Mic,
+ /// Indicates signature-based encryption and verification.
+ Signature,
+}
+
+/// Decrypt, but do not further deserialize the v1 bytes, intended for developer tooling uses only.
+/// Production uses should use [crate::deserialize_advertisement] instead, which deserializes to a
+/// structured format and provides extra type safety.
+pub fn deser_decrypt_v1_section_bytes_for_dev_tools<'adv, 'cred, B, P>(
+ arena: DeserializationArena<'adv>,
+ cred_book: &'cred B,
+ header_byte: u8,
+ section_bytes: &'adv [u8],
+) -> Result<(ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, V1EncryptionScheme), AdvDecryptionError>
+where
+ B: CredentialBook<'cred>,
+ P: CryptoProvider,
+{
+ let header = V1AdvHeader::new(header_byte);
+ let int_sections =
+ parse_sections(header, section_bytes).map_err(|_| AdvDecryptionError::ParseError)?;
+ let cipher_section = match &int_sections[0] {
+ IntermediateSection::Plaintext(_) => Err(AdvDecryptionError::InputNotEncrypted)?,
+ IntermediateSection::Ciphertext(section) => section,
+ };
+
+ let mut allocator = arena.into_allocator();
+ for (crypto_material, _) in cred_book.v1_iter() {
+ if let Some(plaintext) = cipher_section
+ .try_resolve_identity_and_decrypt::<_, P>(&mut allocator, &crypto_material)
+ {
+ let pt = plaintext.expect(concat!(
+ "Should not run out of space because DeserializationArenaAllocator is big ",
+ "enough to hold a single advertisement, and we exit immediately upon ",
+ "successful decryption",
+ ));
+
+ let encryption_scheme = match cipher_section {
+ CiphertextSection::SignatureEncrypted(_) => V1EncryptionScheme::Signature,
+ CiphertextSection::MicEncrypted(_) => V1EncryptionScheme::Mic,
+ };
+ return Ok((pt, encryption_scheme));
+ }
+ }
+ Err(AdvDecryptionError::NoMatchingCredentials)
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mic_decrypt_tests.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mic_decrypt_tests.rs
deleted file mode 100644
index bf78b7d..0000000
--- a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mic_decrypt_tests.rs
+++ /dev/null
@@ -1,471 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-
-use super::*;
-use crate::deserialization_arena;
-use crate::extended::data_elements::TxPowerDataElement;
-use crate::extended::deserialize::DataElementParseError;
-use crate::extended::serialize::{AdvertisementType, SingleTypeDataElement, WriteDataElement};
-use crate::shared_data::TxPower;
-use crate::{
- credential::{v1::V1, SimpleBroadcastCryptoMaterial},
- de_type::EncryptedIdentityDataElementType,
- extended::{
- deserialize::{
- encrypted_section::{
- EncryptedSectionContents, IdentityResolutionOrDeserializationError,
- MicVerificationError,
- },
- parse_sections,
- test_stubs::IntermediateSectionExt,
- CiphertextSection, DataElement, RawV1Salt,
- },
- serialize::{AdvBuilder, CapacityLimitedVec, MicEncryptedSectionEncoder},
- },
- parse_adv_header, AdvHeader, Section,
-};
-use crypto_provider_default::CryptoProviderImpl;
-use np_hkdf::v1_salt::DataElementOffset;
-use sink::Sink;
-use std::{prelude::rust_2021::*, vec};
-
-#[test]
-fn deserialize_mic_encrypted_correct_keys() {
- let metadata_key = MetadataKey([1; 16]);
- let key_seed = [2; 32];
- let raw_salt = RawV1Salt([3; 16]);
- let section_salt = V1Salt::<CryptoProviderImpl>::from(raw_salt);
- let identity_type = EncryptedIdentityDataElementType::Private;
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
-
- let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- V1Salt::from(*section_salt.as_array_ref()),
- &broadcast_cm,
- ))
- .unwrap();
-
- let txpower_de = TxPowerDataElement::from(TxPower::try_from(5).unwrap());
- section_builder.add_de(|_| txpower_de.clone()).unwrap();
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
-
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let adv_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(adv_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- let section = sections.into_iter().next().unwrap();
- let enc_section = section.as_ciphertext().unwrap();
-
- let contents = if let CiphertextSection::MicEncryptedIdentity(contents) = &enc_section {
- contents
- } else {
- panic!("incorrect flavor");
- };
-
- let keypair = np_ed25519::KeyPair::<CryptoProviderImpl>::generate();
-
- // deserializing to Section works
- let discovery_credential =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, keypair.private_key())
- .derive_v1_discovery_credential::<CryptoProviderImpl>();
-
- let identity_resolution_material =
- discovery_credential.unsigned_identity_resolution_material::<CryptoProviderImpl>();
- let verification_material =
- discovery_credential.unsigned_verification_material::<CryptoProviderImpl>();
-
- let arena = deserialization_arena!();
- let mut allocator = arena.into_allocator();
- let section = contents
- .try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
- &mut allocator,
- &identity_resolution_material,
- &verification_material,
- )
- .unwrap();
-
- assert_eq!(
- DecryptedSection::new(
- EncryptedIdentityDataElementType::Private,
- VerificationMode::Mic,
- metadata_key,
- raw_salt,
- SectionContents {
- section_header: 19 // encryption info de
- + 2 // de header
- + 16 // metadata key
- + 2 // de contents
- + 16, // mic hmac tag
- // battery DE
- data_element_start_offset: 2,
- de_region_excl_identity: &[txpower_de.de_header().serialize().as_slice(), &[5],]
- .concat(),
- }
- ),
- section
- );
- let data_elements = section.collect_data_elements().unwrap();
- assert_eq!(
- data_elements,
- &[DataElement { offset: 2.into(), de_type: 0x05_u8.into(), contents: &[5] }]
- );
-
- assert_eq!(
- vec![(DataElementOffset::from(2_u8), TxPowerDataElement::DE_TYPE, vec![5_u8])],
- data_elements
- .into_iter()
- .map(|de| (de.offset(), de.de_type(), de.contents().to_vec()))
- .collect::<Vec<_>>()
- );
-
- let mut encryption_info_bytes = [0_u8; 19];
- encryption_info_bytes[0..2].copy_from_slice(&[0x91, 0x10]);
- encryption_info_bytes[2] = 0x00;
- encryption_info_bytes[3..].copy_from_slice(section_salt.as_slice());
-
- let ciphertext_end = adv.as_slice().len() - 16;
- assert_eq!(
- &MicEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 19 // encryption info de
- + 2 // de header
- + 16 // metadata key
- + 2 // de contents
- + 16, // mic hmac tag
- adv_header,
- encryption_info: EncryptionInfo { bytes: encryption_info_bytes },
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x1],
- offset: 1.into(),
- identity_type: EncryptedIdentityDataElementType::Private,
- },
- all_ciphertext: &adv.as_slice()[1 + 1 + 19 + 2..ciphertext_end],
- },
- mic: SectionMic { mic: adv.as_slice()[ciphertext_end..].try_into().unwrap() }
- },
- contents
- );
-
- // plaintext is correct
- {
- let identity_resolution_contents =
- contents.contents.compute_identity_resolution_contents::<CryptoProviderImpl>();
- let identity_match = identity_resolution_contents
- .try_match::<CryptoProviderImpl>(
- &identity_resolution_material.into_raw_resolution_material(),
- )
- .unwrap();
- let arena = deserialization_arena!();
- let mut allocator = arena.into_allocator();
- let decrypted = contents
- .contents
- .decrypt_ciphertext::<CryptoProviderImpl>(&mut allocator, identity_match)
- .unwrap();
-
- let mut expected = Vec::new();
- // battery de
- expected.extend_from_slice(txpower_de.clone().de_header().serialize().as_slice());
- let _ = txpower_de.write_de_contents(&mut expected);
-
- assert_eq!(metadata_key, decrypted.metadata_key_plaintext);
- assert_eq!(&expected, decrypted.plaintext_contents);
- }
-}
-
-#[test]
-fn deserialize_mic_encrypted_incorrect_aes_key_error() {
- // bad aes key -> bad metadata key plaintext
- do_bad_deserialize_params::<CryptoProviderImpl>(
- IdentityResolutionOrDeserializationError::IdentityMatchingError,
- Some([0xFF; 16].into()),
- None,
- None,
- None,
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_incorrect_metadata_key_hmac_key_error() {
- // bad metadata key hmac key -> bad calculated metadata key mac
- do_bad_deserialize_params::<CryptoProviderImpl>(
- IdentityResolutionOrDeserializationError::IdentityMatchingError,
- None,
- Some([0xFF; 32].into()),
- None,
- None,
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_incorrect_mic_hmac_key_error() {
- // bad mic hmac key -> bad calculated mic
- do_bad_deserialize_params::<CryptoProviderImpl>(
- MicVerificationError::MicMismatch.into(),
- None,
- None,
- Some([0xFF; 32].into()),
- None,
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_incorrect_expected_metadata_key_hmac_error() {
- // bad expected metadata key mac
- do_bad_deserialize_params::<CryptoProviderImpl>(
- IdentityResolutionOrDeserializationError::IdentityMatchingError,
- None,
- None,
- None,
- Some([0xFF; 32]),
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_incorrect_salt_error() {
- // bad salt -> bad iv -> bad metadata key plaintext
- do_bad_deserialize_tampered(
- DeserializeError::IdentityResolutionOrDeserializationError(
- IdentityResolutionOrDeserializationError::IdentityMatchingError,
- ),
- |_| {},
- |adv| adv[23..39].copy_from_slice(&[0xFF; 16]),
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_de_that_wont_parse() {
- // add an extra byte to the section, leading it to try to parse a DE that doesn't exist
- do_bad_deserialize_tampered(
- DeserializeError::DataElementParseError(DataElementParseError::UnexpectedDataAfterEnd),
- |sec| sec.try_push(0xFF).unwrap(),
- |_| {},
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_tampered_mic_error() {
- // flip the a bit in the first MIC byte
- do_bad_deserialize_tampered(
- DeserializeError::IdentityResolutionOrDeserializationError(
- MicVerificationError::MicMismatch.into(),
- ),
- |_| {},
- |adv| {
- let mic_start = adv.len() - 16;
- adv[mic_start] ^= 0x01
- },
- );
-}
-
-#[test]
-fn deserialize_mic_encrypted_tampered_payload_error() {
- // flip the last payload bit
- do_bad_deserialize_tampered(
- DeserializeError::IdentityResolutionOrDeserializationError(
- MicVerificationError::MicMismatch.into(),
- ),
- |_| {},
- |adv| *adv.last_mut().unwrap() ^= 0x01,
- );
-}
-
-/// Attempt a decryption that will fail when using the provided parameters for decryption only.
-/// `None` means use the correct value for that parameter.
-fn do_bad_deserialize_params<C: CryptoProvider>(
- error: IdentityResolutionOrDeserializationError<MicVerificationError>,
- aes_key: Option<crypto_provider::aes::Aes128Key>,
- metadata_key_hmac_key: Option<np_hkdf::NpHmacSha256Key<C>>,
- mic_hmac_key: Option<np_hkdf::NpHmacSha256Key<C>>,
- expected_metadata_key_hmac: Option<[u8; 32]>,
-) {
- let metadata_key = MetadataKey([1; 16]);
- let key_seed = [2; 32];
- let section_salt: V1Salt<C> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
- let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::new(&key_seed);
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
-
- let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<C>::new(
- identity_type,
- section_salt,
- &broadcast_cm,
- ))
- .unwrap();
-
- section_builder.add_de(|_| TxPowerDataElement::from(TxPower::try_from(7).unwrap())).unwrap();
-
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
-
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- let section = sections.into_iter().next().unwrap();
- let enc_section = section.as_ciphertext().unwrap();
- let contents = if let CiphertextSection::MicEncryptedIdentity(contents) = &enc_section {
- contents
- } else {
- panic!("incorrect flavor");
- };
-
- let unsigned_identity_resolution_material = SectionIdentityResolutionMaterial {
- aes_key: aes_key.unwrap_or_else(|| np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf)),
- metadata_key_hmac_key: *metadata_key_hmac_key
- .unwrap_or_else(|| key_seed_hkdf.extended_unsigned_metadata_key_hmac_key())
- .as_bytes(),
- expected_metadata_key_hmac: expected_metadata_key_hmac.unwrap_or_else(|| {
- key_seed_hkdf.extended_unsigned_metadata_key_hmac_key().calculate_hmac(&metadata_key.0)
- }),
- };
- let identity_resolution_material =
- UnsignedSectionIdentityResolutionMaterial::from_raw(unsigned_identity_resolution_material);
-
- let verification_material = UnsignedSectionVerificationMaterial {
- mic_hmac_key: *mic_hmac_key
- .unwrap_or_else(|| np_hkdf::UnsignedSectionKeys::hmac_key(&key_seed_hkdf))
- .as_bytes(),
- };
-
- assert_eq!(
- error,
- contents
- .try_resolve_identity_and_deserialize::<C>(
- &mut deserialization_arena!().into_allocator(),
- &identity_resolution_material,
- &verification_material,
- )
- .unwrap_err()
- );
-}
-
-#[derive(Debug, PartialEq)]
-enum DeserializeError {
- IdentityResolutionOrDeserializationError(
- IdentityResolutionOrDeserializationError<MicVerificationError>,
- ),
- DataElementParseError(DataElementParseError),
-}
-
-fn do_bad_deserialize_tampered(
- expected_error: DeserializeError,
- mangle_section: impl Fn(&mut CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>),
- mangle_adv: impl Fn(&mut Vec<u8>),
-) {
- let metadata_key = MetadataKey([1; 16]);
- let key_seed = [2; 32];
- let section_salt: V1Salt<CryptoProviderImpl> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
-
- let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- section_salt,
- &broadcast_cm,
- ))
- .unwrap();
-
- section_builder.add_de(|_| TxPowerDataElement::from(TxPower::try_from(7).unwrap())).unwrap();
-
- mangle_section(&mut section_builder.section);
-
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
- let mut adv_mut = adv.as_slice().to_vec();
- mangle_adv(&mut adv_mut);
-
- let (remaining, header) = parse_adv_header(&adv_mut).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- let section = sections.into_iter().next().unwrap();
- let enc_section = section.as_ciphertext().unwrap();
- let contents = if let CiphertextSection::MicEncryptedIdentity(contents) = &enc_section {
- contents
- } else {
- panic!("incorrect flavor");
- };
-
- // generate a random key pair since we need _some_ public key in our discovery
- // credential, even if it winds up going unused
- let key_pair = np_ed25519::KeyPair::<CryptoProviderImpl>::generate();
-
- let discovery_credential =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key())
- .derive_v1_discovery_credential::<CryptoProviderImpl>();
-
- let identity_resolution_material =
- discovery_credential.unsigned_identity_resolution_material::<CryptoProviderImpl>();
- let verification_material =
- discovery_credential.unsigned_verification_material::<CryptoProviderImpl>();
-
- match contents.try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
- &mut deserialization_arena!().into_allocator(),
- &identity_resolution_material,
- &verification_material,
- ) {
- Ok(section) => {
- assert_eq!(
- expected_error,
- DeserializeError::DataElementParseError(
- section.collect_data_elements().unwrap_err()
- )
- );
- }
- Err(e) => assert_eq!(
- expected_error,
- DeserializeError::IdentityResolutionOrDeserializationError(e),
- ),
- };
-}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mod.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mod.rs
index eb2fe01..fc38b1c 100644
--- a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mod.rs
+++ b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/mod.rs
@@ -14,20 +14,26 @@
use crate::{
credential::v1::*,
- deserialization_arena::DeserializationArenaAllocator,
extended::{
- deserialize::{
- DecryptedSection, EncryptedIdentityMetadata, EncryptionInfo, SectionContents,
- SectionMic, VerificationMode,
- },
+ deserialize::{DecryptedSection, SectionMic, VerificationMode},
section_signature_payload::*,
- METADATA_KEY_LEN, NP_ADV_MAX_SECTION_LEN,
+ V1IdentityToken, NP_ADV_MAX_SECTION_LEN, V1_IDENTITY_TOKEN_LEN,
},
- MetadataKey, V1Header, NP_SVC_UUID,
+ NP_SVC_UUID,
};
+use crate::deserialization_arena::DeserializationArenaAllocator;
+
#[cfg(any(feature = "devtools", test))]
extern crate alloc;
+
+use crate::{
+ extended::{
+ deserialize::section::header::CiphertextExtendedIdentityToken,
+ salt::{MultiSalt, V1Salt},
+ },
+ header::V1AdvHeader,
+};
#[cfg(any(feature = "devtools", test))]
use alloc::vec::Vec;
#[cfg(feature = "devtools")]
@@ -38,24 +44,28 @@ use crypto_provider::{
hmac::Hmac,
CryptoProvider,
};
-use np_hkdf::v1_salt::V1Salt;
+use np_hkdf::v1_salt::ExtendedV1Salt;
+
+#[cfg(test)]
+use crate::extended::deserialize::encrypted_section::tests::IdentityResolutionOrDeserializationError;
use super::ArenaOutOfSpace;
#[cfg(test)]
-mod mic_decrypt_tests;
-#[cfg(test)]
-mod signature_decrypt_tests;
+mod tests;
/// Represents the contents of an encrypted section
/// which are directly employed in identity resolution.
/// This does not incorporate any information about credentials.
+///
+/// Should be re-used for multiple identity resolution attempts, if applicable, to amortize the
+/// cost of calculating this data.
#[derive(PartialEq, Eq, Debug)]
pub(crate) struct SectionIdentityResolutionContents {
- /// The ciphertext for the metadata key
- pub(crate) metadata_key_ciphertext: [u8; METADATA_KEY_LEN],
- /// The 12-byte cryptographic nonce which is derived from the encryption info
- /// and the identity metadata for a particular section.
+ /// The ciphertext for the identity token
+ pub(crate) identity_token: CiphertextExtendedIdentityToken,
+ /// The 12-byte cryptographic nonce which is derived from the salt for a
+ /// particular section.
pub(crate) nonce: AesCtrNonce,
}
@@ -73,29 +83,34 @@ impl SectionIdentityResolutionContents {
&self,
identity_resolution_material: &SectionIdentityResolutionMaterial,
) -> Option<IdentityMatch<C>> {
- let mut decrypt_buf = self.metadata_key_ciphertext;
- let aes_key = &identity_resolution_material.aes_key;
- let mut cipher = C::AesCtr128::new(aes_key, NonceAndCounter::from_nonce(self.nonce));
+ let mut decrypt_buf = self.identity_token.0;
+ let mut cipher = C::AesCtr128::new(
+ &identity_resolution_material.aes_key,
+ NonceAndCounter::from_nonce(self.nonce),
+ );
cipher.apply_keystream(&mut decrypt_buf[..]);
- let metadata_key_hmac_key: np_hkdf::NpHmacSha256Key<C> =
- identity_resolution_material.metadata_key_hmac_key.into();
- let expected_metadata_key_hmac = identity_resolution_material.expected_metadata_key_hmac;
- metadata_key_hmac_key.verify_hmac(&decrypt_buf[..], expected_metadata_key_hmac).ok().map(
- move |_| IdentityMatch {
+ let identity_token_hmac_key: np_hkdf::NpHmacSha256Key =
+ identity_resolution_material.identity_token_hmac_key.into();
+ identity_token_hmac_key
+ .verify_hmac::<C>(
+ &decrypt_buf[..],
+ identity_resolution_material.expected_identity_token_hmac,
+ )
+ .ok()
+ .map(move |_| IdentityMatch {
cipher,
- metadata_key_plaintext: MetadataKey(decrypt_buf),
+ identity_token: V1IdentityToken(decrypt_buf),
nonce: self.nonce,
- },
- )
+ })
}
}
/// Carries data about an identity "match" for a particular section
/// against some particular V1 identity-resolution crypto-materials.
pub(crate) struct IdentityMatch<C: CryptoProvider> {
- /// Decrypted metadata key ciphertext
- metadata_key_plaintext: MetadataKey,
+ /// Decrypted identity token
+ identity_token: V1IdentityToken,
/// The AES-Ctr nonce to be used in section decryption and verification
nonce: AesCtrNonce,
/// The state of the AES-Ctr cipher after successfully decrypting
@@ -106,22 +121,24 @@ pub(crate) struct IdentityMatch<C: CryptoProvider> {
/// Maximum length of a section's contents, after the metadata-key.
#[allow(unused)]
-const MAX_SECTION_CONTENTS_LEN: usize = NP_ADV_MAX_SECTION_LEN - METADATA_KEY_LEN;
+const MAX_SECTION_CONTENTS_LEN: usize = NP_ADV_MAX_SECTION_LEN - V1_IDENTITY_TOKEN_LEN;
/// Bare, decrypted contents from an encrypted section,
/// including the decrypted metadata key and the decrypted section ciphertext.
/// At this point, verification of the plaintext contents has not yet been performed.
-pub(crate) struct RawDecryptedSection<'adv> {
- pub(crate) metadata_key_plaintext: MetadataKey,
+pub(crate) struct RawDecryptedSection<'a> {
+ // Only used with feature = "devtools"
+ #[allow(unused)]
+ pub(crate) identity_token: V1IdentityToken,
pub(crate) nonce: AesCtrNonce,
- pub(crate) plaintext_contents: &'adv [u8],
+ pub(crate) plaintext_contents: &'a [u8],
}
#[cfg(feature = "devtools")]
-impl<'adv> RawDecryptedSection<'adv> {
+impl<'a> RawDecryptedSection<'a> {
pub(crate) fn to_raw_bytes(&self) -> ArrayView<u8, NP_ADV_MAX_SECTION_LEN> {
let mut result = Vec::new();
- result.extend_from_slice(&self.metadata_key_plaintext.0);
+ result.extend_from_slice(self.identity_token.as_slice());
result.extend_from_slice(self.plaintext_contents);
ArrayView::try_from_slice(&result).expect("Won't panic because of the involved lengths")
}
@@ -130,17 +147,21 @@ impl<'adv> RawDecryptedSection<'adv> {
/// Represents the contents of an encrypted section,
/// independent of the encryption type.
#[derive(PartialEq, Eq, Debug)]
-pub(crate) struct EncryptedSectionContents<'a> {
- pub(crate) section_header: u8,
- pub(crate) adv_header: V1Header,
- pub(crate) encryption_info: EncryptionInfo,
- pub(crate) identity: EncryptedIdentityMetadata,
- /// All ciphertext (Contents of identity DE + all DEs)
- /// Length must be in `[METADATA_KEY_LEN, NP_ADV_MAX_SECTION_LEN]`.
- pub(crate) all_ciphertext: &'a [u8],
+pub(crate) struct EncryptedSectionContents<'adv, S> {
+ adv_header: V1AdvHeader,
+ format_bytes: &'adv [u8],
+ pub(crate) salt: S,
+ /// Ciphertext of identity token (part of section header)
+ identity_token: CiphertextExtendedIdentityToken,
+ /// The portion of the ciphertext that has been encrypted.
+ /// Length must be in `[0, NP_ADV_MAX_SECTION_LEN]`.
+ section_contents: &'adv [u8],
+ // The length byte exactly as it appears in the adv. This is the length of the encrypted
+ // contents plus any additional bytes of suffix
+ total_section_contents_len: u8,
}
-impl<'a> EncryptedSectionContents<'a> {
+impl<'adv, S: V1Salt> EncryptedSectionContents<'adv, S> {
/// Constructs a representation of the contents of an encrypted V1 section
/// from the advertisement header, the section header, information about
/// the encryption used for identity verification, identity metadata,
@@ -148,30 +169,29 @@ impl<'a> EncryptedSectionContents<'a> {
///
/// # Panics
/// If `all_ciphertext` is greater than `NP_ADV_MAX_SECTION_LEN` bytes,
- /// or less than `METADATA_KEY_LEN` bytes.
+ /// or less than `IDENTITY_TOKEN_LEN` bytes.
pub(crate) fn new(
- adv_header: V1Header,
- section_header: u8,
- encryption_info: EncryptionInfo,
- identity: EncryptedIdentityMetadata,
- all_ciphertext: &'a [u8],
+ adv_header: V1AdvHeader,
+ format_bytes: &'adv [u8],
+ salt: S,
+ identity_token: CiphertextExtendedIdentityToken,
+ section_contents_len: u8,
+ section_contents: &'adv [u8],
) -> Self {
- assert!(all_ciphertext.len() >= METADATA_KEY_LEN);
- assert!(all_ciphertext.len() <= NP_ADV_MAX_SECTION_LEN);
- Self { adv_header, section_header, encryption_info, identity, all_ciphertext }
+ assert!(section_contents.len() <= NP_ADV_MAX_SECTION_LEN - V1_IDENTITY_TOKEN_LEN);
+ Self {
+ adv_header,
+ format_bytes,
+ salt,
+ identity_token,
+ total_section_contents_len: section_contents_len,
+ section_contents,
+ }
}
/// Gets the salt for this encrypted section
- pub(crate) fn salt<C: CryptoProvider>(&self) -> V1Salt<C> {
- self.encryption_info.salt().into()
- }
-
- /// Constructs a cryptographic nonce for this encrypted section
- /// based on the contained salt.
- pub(crate) fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
- self.salt::<C>()
- .derive(Some(self.identity.offset))
- .expect("AES-CTR nonce is a valid HKDF size")
+ pub(crate) fn salt(&self) -> MultiSalt {
+ self.salt.into()
}
/// Constructs some cryptographic contents for section identity-resolution
@@ -179,34 +199,30 @@ impl<'a> EncryptedSectionContents<'a> {
pub(crate) fn compute_identity_resolution_contents<C: CryptoProvider>(
&self,
) -> SectionIdentityResolutionContents {
- let nonce = self.compute_nonce::<C>();
- let metadata_key_ciphertext: [u8; METADATA_KEY_LEN] = self.all_ciphertext
- [..METADATA_KEY_LEN]
- .try_into()
- .expect("slice will always fit into same size array");
-
- SectionIdentityResolutionContents { nonce, metadata_key_ciphertext }
+ let nonce = self.salt.compute_nonce::<C>();
+ SectionIdentityResolutionContents { nonce, identity_token: self.identity_token }
}
/// Given an identity-match, decrypts the ciphertext in this encrypted section
/// and returns the raw bytes of the decrypted plaintext.
pub(crate) fn decrypt_ciphertext<C: CryptoProvider>(
&self,
- arena: &mut DeserializationArenaAllocator<'a>,
+ arena: &mut DeserializationArenaAllocator<'adv>,
mut identity_match: IdentityMatch<C>,
- ) -> Result<RawDecryptedSection<'a>, ArenaOutOfSpace> {
- // Fill decrypt_buf with the ciphertext after the metadata key
+ ) -> Result<RawDecryptedSection<'adv>, ArenaOutOfSpace> {
+ // Fill decrypt_buf with the ciphertext after the section length
let decrypt_buf =
- arena.allocate(u8::try_from(self.all_ciphertext.len() - METADATA_KEY_LEN).expect(
- "all_ciphertext.len() must be in [METADATA_KEY_LEN, NP_ADV_MAX_SECTION_LEN]",
- ))?;
- decrypt_buf.copy_from_slice(&self.all_ciphertext[METADATA_KEY_LEN..]);
+ arena
+ .allocate(u8::try_from(self.section_contents.len()).expect(
+ "section_contents.len() must be in [0, NP_ADV_MAX_SECTION_CONTENTS_LEN - EXTENDED_IDENTITY_TOKEN_LEN]",
+ ))?;
+ decrypt_buf.copy_from_slice(self.section_contents);
// Decrypt everything after the metadata key
identity_match.cipher.apply_keystream(decrypt_buf);
Ok(RawDecryptedSection {
- metadata_key_plaintext: identity_match.metadata_key_plaintext,
+ identity_token: identity_match.identity_token,
nonce: identity_match.nonce,
plaintext_contents: decrypt_buf,
})
@@ -216,21 +232,21 @@ impl<'a> EncryptedSectionContents<'a> {
#[cfg(feature = "devtools")]
pub(crate) fn try_resolve_identity_and_decrypt<P: CryptoProvider>(
&self,
- allocator: &mut DeserializationArenaAllocator<'a>,
+ allocator: &mut DeserializationArenaAllocator<'adv>,
identity_resolution_material: &SectionIdentityResolutionMaterial,
) -> Option<Result<ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, ArenaOutOfSpace>> {
- let identity_resolution_contents = self.compute_identity_resolution_contents::<P>();
- identity_resolution_contents.try_match(identity_resolution_material).map(|identity_match| {
- let decrypted_section = self.decrypt_ciphertext::<P>(allocator, identity_match)?;
- Ok(decrypted_section.to_raw_bytes())
- })
+ self.compute_identity_resolution_contents::<P>()
+ .try_match(identity_resolution_material)
+ .map(|identity_match| {
+ Ok(self.decrypt_ciphertext::<P>(allocator, identity_match)?.to_raw_bytes())
+ })
}
}
/// An encrypted section which is verified using a ed25519 signature
#[derive(PartialEq, Eq, Debug)]
pub(crate) struct SignatureEncryptedSection<'a> {
- pub(crate) contents: EncryptedSectionContents<'a>,
+ pub(crate) contents: EncryptedSectionContents<'a, ExtendedV1Salt>,
}
impl<'a> SignatureEncryptedSection<'a> {
@@ -245,51 +261,41 @@ impl<'a> SignatureEncryptedSection<'a> {
where
P: CryptoProvider,
{
+ let identity_token = identity_match.identity_token;
let raw_decrypted = self.contents.decrypt_ciphertext(arena, identity_match)?;
- let metadata_key = raw_decrypted.metadata_key_plaintext;
let nonce = raw_decrypted.nonce;
let remaining = raw_decrypted.plaintext_contents;
- if remaining.len() < crypto_provider::ed25519::SIGNATURE_LENGTH {
- return Err(SignatureVerificationError::SignatureMissing.into());
- }
+ let (plaintext_des, sig) = remaining
+ .split_last_chunk::<{ crypto_provider::ed25519::SIGNATURE_LENGTH }>()
+ .ok_or(SignatureVerificationError::SignatureMissing)?;
- // should not panic due to above check
- let (non_identity_des, sig) =
- remaining.split_at(remaining.len() - crypto_provider::ed25519::SIGNATURE_LENGTH);
+ let expected_signature = crypto_provider::ed25519::Signature::from(*sig);
- // All implementations only check for 64 bytes, and this will always result in a 64 byte signature.
- let expected_signature =
- np_ed25519::Signature::<P>::try_from(sig).expect("Signature is always 64 bytes.");
-
- let section_signature_payload = SectionSignaturePayload::from_deserialized_parts(
- self.contents.adv_header.header_byte,
- self.contents.section_header,
- &self.contents.encryption_info.bytes,
+ let section_signature_payload = SectionSignaturePayload::new(
+ self.contents.format_bytes,
+ self.contents.salt.bytes(),
&nonce,
- self.contents.identity.header_bytes,
- metadata_key,
- non_identity_des,
+ identity_token.as_slice(),
+ self.contents.total_section_contents_len,
+ plaintext_des,
);
let public_key = verification_material.signature_verification_public_key();
- section_signature_payload.verify(&expected_signature, &public_key).map_err(|e| {
- // Length of the payload should fit in the signature verification buffer.
- debug_assert!(e != np_ed25519::SignatureVerificationError::PayloadTooBig);
-
- SignatureVerificationError::SignatureMismatch
- })?;
-
- let salt = self.contents.salt::<P>();
+ section_signature_payload.verify::<P::Ed25519>(expected_signature, &public_key).map_err(
+ |e| {
+ // Length of the payload should fit in the signature verification buffer.
+ debug_assert!(e != np_ed25519::SignatureVerificationError::PayloadTooBig);
+ SignatureVerificationError::SignatureMismatch
+ },
+ )?;
Ok(DecryptedSection::new(
- self.contents.identity.identity_type,
VerificationMode::Signature,
- metadata_key,
- salt.into(),
- // de offset 2 because of leading encryption info and identity DEs
- SectionContents::new(self.contents.section_header, non_identity_des, 2),
+ self.contents.salt(),
+ identity_token,
+ plaintext_des,
))
}
@@ -307,6 +313,13 @@ impl<'a> SignatureEncryptedSection<'a> {
}
/// Try deserializing into a [Section] given some raw signed crypto-material.
+ ///
+ /// A less-efficient, one-shot way of getting
+ /// [EncryptedSectionContents::compute_identity_resolution_contents] and then attempting
+ /// deserialization.
+ ///
+ /// Normally, id resolution contents would be calculated for a bunch of sections, and then have
+ /// many identities tried on them. This just works for one identity.
#[cfg(test)]
pub(crate) fn try_resolve_identity_and_deserialize<P: CryptoProvider>(
&self,
@@ -317,9 +330,9 @@ impl<'a> SignatureEncryptedSection<'a> {
DecryptedSection,
IdentityResolutionOrDeserializationError<SignatureVerificationError>,
> {
- let section_identity_resolution_contents =
- self.contents.compute_identity_resolution_contents::<P>();
- match section_identity_resolution_contents
+ match self
+ .contents
+ .compute_identity_resolution_contents::<P>()
.try_match::<P>(identity_resolution_material.as_raw_resolution_material())
{
Some(identity_match) => self
@@ -330,36 +343,6 @@ impl<'a> SignatureEncryptedSection<'a> {
}
}
-/// An error when attempting to resolve an identity and then
-/// attempt to deserialize an encrypted advertisement.
-///
-/// This should not be exposed publicly, since it's too
-/// detailed.
-#[cfg(test)]
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) enum IdentityResolutionOrDeserializationError<V: VerificationError> {
- /// Failed to match the encrypted adv to an identity
- IdentityMatchingError,
- /// Failed to deserialize the encrypted adv after matching the identity
- DeserializationError(DeserializationError<V>),
-}
-
-#[cfg(test)]
-impl<V: VerificationError> From<DeserializationError<V>>
- for IdentityResolutionOrDeserializationError<V>
-{
- fn from(deserialization_error: DeserializationError<V>) -> Self {
- Self::DeserializationError(deserialization_error)
- }
-}
-
-#[cfg(test)]
-impl<V: VerificationError> From<V> for IdentityResolutionOrDeserializationError<V> {
- fn from(verification_error: V) -> Self {
- Self::DeserializationError(DeserializationError::VerificationError(verification_error))
- }
-}
-
/// An error when attempting to deserialize an encrypted advertisement,
/// assuming that we already have an identity-match.
///
@@ -406,7 +389,7 @@ impl VerificationError for SignatureVerificationError {}
/// An encrypted section whose contents are verified to match a message integrity code (MIC)
#[derive(PartialEq, Eq, Debug)]
pub(crate) struct MicEncryptedSection<'a> {
- pub(crate) contents: EncryptedSectionContents<'a>,
+ pub(crate) contents: EncryptedSectionContents<'a, MultiSalt>,
pub(crate) mic: SectionMic,
}
@@ -418,48 +401,71 @@ impl<'a> MicEncryptedSection<'a> {
&self,
allocator: &mut DeserializationArenaAllocator<'a>,
identity_match: IdentityMatch<P>,
- verification_material: &UnsignedSectionVerificationMaterial,
+ crypto_material: &impl V1DiscoveryCryptoMaterial,
) -> Result<DecryptedSection<'a>, DeserializationError<MicVerificationError>>
where
P: CryptoProvider,
{
- let raw_decrypted = self.contents.decrypt_ciphertext(allocator, identity_match)?;
- let metadata_key = raw_decrypted.metadata_key_plaintext;
- let nonce = raw_decrypted.nonce;
- let remaining_des = raw_decrypted.plaintext_contents;
-
+ let hmac_key = match self.contents.salt {
+ MultiSalt::Short(_) => {
+ crypto_material.mic_short_salt_verification_material::<P>().mic_hmac_key()
+ }
+ MultiSalt::Extended(_) => {
+ crypto_material.mic_extended_salt_verification_material::<P>().mic_hmac_key()
+ }
+ };
+
+ let mut mic_hmac = hmac_key.build_hmac::<P>();
// if mic is ok, the section was generated by someone holding at least the shared credential
- let mut mic_hmac = verification_material.mic_hmac_key::<P>().build_hmac();
mic_hmac.update(&NP_SVC_UUID);
- mic_hmac.update(&[self.contents.adv_header.header_byte]);
- mic_hmac.update(&[self.contents.section_header]);
- mic_hmac.update(&self.contents.encryption_info.bytes);
- mic_hmac.update(&nonce);
- mic_hmac.update(&self.contents.identity.header_bytes);
- mic_hmac.update(self.contents.all_ciphertext);
+ mic_hmac.update(&[self.contents.adv_header.contents()]);
+ // section format
+ mic_hmac.update(self.contents.format_bytes);
+ // salt bytes
+ mic_hmac.update(self.contents.salt.as_slice());
+ // nonce
+ mic_hmac.update(identity_match.nonce.as_slice());
+ // ciphertext identity token
+ mic_hmac.update(self.contents.identity_token.0.as_slice());
+ // section payload len
+ mic_hmac.update(&[self.contents.total_section_contents_len]);
+ // rest of encrypted contents
+ mic_hmac.update(self.contents.section_contents);
mic_hmac
// adv only contains first 16 bytes of HMAC
.verify_truncated_left(&self.mic.mic)
.map_err(|_e| MicVerificationError::MicMismatch)?;
- let salt = self.contents.salt::<P>();
-
+ // plaintext identity token, already decrypted during identity match
+ let identity_token = identity_match.identity_token;
+ let raw_decrypted = self.contents.decrypt_ciphertext(allocator, identity_match)?;
Ok(DecryptedSection::new(
- self.contents.identity.identity_type,
VerificationMode::Mic,
- metadata_key,
- salt.into(),
- // offset 2 for encryption info and identity DEs
- SectionContents::new(self.contents.section_header, remaining_des, 2),
+ self.contents.salt(),
+ identity_token,
+ raw_decrypted.plaintext_contents,
))
}
/// Try decrypting into some raw bytes given some raw unsigned crypto-material.
#[cfg(feature = "devtools")]
- pub(crate) fn try_resolve_identity_and_decrypt<P: CryptoProvider>(
+ pub(crate) fn try_resolve_short_salt_identity_and_decrypt<P: CryptoProvider>(
&self,
allocator: &mut DeserializationArenaAllocator<'a>,
- identity_resolution_material: &UnsignedSectionIdentityResolutionMaterial,
+ identity_resolution_material: &MicShortSaltSectionIdentityResolutionMaterial,
+ ) -> Option<Result<ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, ArenaOutOfSpace>> {
+ self.contents.try_resolve_identity_and_decrypt::<P>(
+ allocator,
+ identity_resolution_material.as_raw_resolution_material(),
+ )
+ }
+
+ /// Try decrypting into some raw bytes given some raw unsigned crypto-material.
+ #[cfg(feature = "devtools")]
+ pub(crate) fn try_resolve_extended_salt_identity_and_decrypt<P: CryptoProvider>(
+ &self,
+ allocator: &mut DeserializationArenaAllocator<'a>,
+ identity_resolution_material: &MicExtendedSaltSectionIdentityResolutionMaterial,
) -> Option<Result<ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, ArenaOutOfSpace>> {
self.contents.try_resolve_identity_and_decrypt::<P>(
allocator,
@@ -472,20 +478,27 @@ impl<'a> MicEncryptedSection<'a> {
pub(crate) fn try_resolve_identity_and_deserialize<P: CryptoProvider>(
&self,
allocator: &mut DeserializationArenaAllocator<'a>,
- identity_resolution_material: &UnsignedSectionIdentityResolutionMaterial,
- verification_material: &UnsignedSectionVerificationMaterial,
+ crypto_material: &impl V1DiscoveryCryptoMaterial,
) -> Result<DecryptedSection, IdentityResolutionOrDeserializationError<MicVerificationError>>
{
let section_identity_resolution_contents =
self.contents.compute_identity_resolution_contents::<P>();
- match section_identity_resolution_contents
- .try_match::<P>(identity_resolution_material.as_raw_resolution_material())
- {
- Some(identity_match) => self
- .try_deserialize(allocator, identity_match, verification_material)
- .map_err(|e| e.into()),
- None => Err(IdentityResolutionOrDeserializationError::IdentityMatchingError),
+
+ let identity_match = match self.contents.salt {
+ MultiSalt::Short(_) => section_identity_resolution_contents.try_match::<P>(
+ crypto_material
+ .mic_short_salt_identity_resolution_material::<P>()
+ .as_raw_resolution_material(),
+ ),
+ MultiSalt::Extended(_) => section_identity_resolution_contents.try_match::<P>(
+ crypto_material
+ .mic_extended_salt_identity_resolution_material::<P>()
+ .as_raw_resolution_material(),
+ ),
}
+ .ok_or(IdentityResolutionOrDeserializationError::IdentityMatchingError)?;
+
+ self.try_deserialize(allocator, identity_match, crypto_material).map_err(|e| e.into())
}
}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests.rs
new file mode 100644
index 0000000..2afa41c
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests.rs
@@ -0,0 +1,88 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+use super::*;
+use crate::extended::V1_IDENTITY_TOKEN_LEN;
+use np_hkdf::v1_salt::{ExtendedV1Salt, EXTENDED_SALT_LEN};
+
+#[cfg(test)]
+mod mic_decrypt_tests;
+
+#[cfg(test)]
+mod signature_decrypt_tests;
+
+#[cfg(test)]
+mod coverage_gaming;
+
+/// An error when attempting to resolve an identity and then
+/// attempt to deserialize an encrypted advertisement.
+///
+/// This should not be exposed publicly, since it's too
+/// detailed.
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) enum IdentityResolutionOrDeserializationError<V: VerificationError> {
+ /// Failed to match the encrypted adv to an identity
+ IdentityMatchingError,
+ /// Failed to deserialize the encrypted adv after matching the identity
+ DeserializationError(DeserializationError<V>),
+}
+
+impl<V: VerificationError> From<DeserializationError<V>>
+ for IdentityResolutionOrDeserializationError<V>
+{
+ fn from(deserialization_error: DeserializationError<V>) -> Self {
+ Self::DeserializationError(deserialization_error)
+ }
+}
+
+impl<V: VerificationError> From<V> for IdentityResolutionOrDeserializationError<V> {
+ fn from(verification_error: V) -> Self {
+ Self::DeserializationError(DeserializationError::VerificationError(verification_error))
+ }
+}
+
+pub(crate) fn first_section_contents(after_version_header: &[u8]) -> &[u8] {
+ &after_version_header[1 + EXTENDED_SALT_LEN + V1_IDENTITY_TOKEN_LEN + 1..]
+}
+
+pub(crate) fn first_section_identity_token(
+ salt: MultiSalt,
+ after_version_header: &[u8],
+) -> CiphertextExtendedIdentityToken {
+ // Next 16 bytes after 1 byte format and 16 byte salt
+ after_version_header[1 + salt.as_slice().len()..][..V1_IDENTITY_TOKEN_LEN]
+ .try_into()
+ .map(|arr: [u8; V1_IDENTITY_TOKEN_LEN]| arr.into())
+ .unwrap()
+}
+
+pub(crate) fn first_section_format(after_version_header: &[u8]) -> &[u8] {
+ // 1 byte of format comes at the beginning
+ &after_version_header[..1]
+}
+
+pub(crate) fn first_section_salt(after_version_header: &[u8]) -> ExtendedV1Salt {
+ // Next 16 bytes after 1 byte format
+ after_version_header[1..][..EXTENDED_SALT_LEN]
+ .try_into()
+ .map(|arr: [u8; EXTENDED_SALT_LEN]| arr.into())
+ .unwrap()
+}
+
+pub(crate) fn first_section_contents_len(after_version_header: &[u8]) -> u8 {
+ // section len is the first byte after format + salt + identity token
+ after_version_header[1 + EXTENDED_SALT_LEN + V1_IDENTITY_TOKEN_LEN..][0]
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/coverage_gaming.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/coverage_gaming.rs
new file mode 100644
index 0000000..0d8ba8f
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/coverage_gaming.rs
@@ -0,0 +1,60 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+use super::super::*;
+use alloc::format;
+use crypto_provider_default::CryptoProviderImpl;
+
+#[test]
+fn section_identity_resolution_content_derives() {
+ let salt: ExtendedV1Salt = [0; 16].into();
+ let nonce = salt.compute_nonce::<CryptoProviderImpl>();
+ let token = CiphertextExtendedIdentityToken([0; 16]);
+ let section = SectionIdentityResolutionContents { identity_token: token, nonce };
+ assert_eq!(section, section);
+ let _ = format!("{:?}", section);
+}
+
+#[test]
+fn sig_encrypted_section_debug() {
+ let ss = SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ V1AdvHeader::new(0),
+ &[0],
+ [0x00; 16].into(),
+ [0x00; V1_IDENTITY_TOKEN_LEN].into(),
+ 1,
+ &[0x00; 1],
+ ),
+ };
+ let _ = format!("{:?}", ss);
+}
+
+#[test]
+fn error_enum_debug_derives() {
+ let mic_err = MicVerificationError::MicMismatch;
+ let _ = format!("{:?}", mic_err);
+
+ let sig_err = SignatureVerificationError::SignatureMissing;
+ let _ = format!("{:?}", sig_err);
+
+ let deser_err = DeserializationError::ArenaOutOfSpace::<MicVerificationError>;
+ let _ = format!("{:?}", deser_err);
+
+ let err =
+ IdentityResolutionOrDeserializationError::IdentityMatchingError::<MicVerificationError>;
+ let _ = format!("{:?}", err);
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/mic_decrypt_tests.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/mic_decrypt_tests.rs
new file mode 100644
index 0000000..5d2f759
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/mic_decrypt_tests.rs
@@ -0,0 +1,642 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+extern crate std;
+
+use super::super::*;
+use crate::{
+ deserialization_arena,
+ extended::{
+ data_elements::TxPowerDataElement,
+ deserialize::{
+ encrypted_section::tests::first_section_identity_token,
+ section::intermediate::{
+ parse_sections, tests::IntermediateSectionExt, CiphertextSection,
+ },
+ DataElement, DataElementParseError, Section,
+ },
+ salt::{ShortV1Salt, SHORT_SALT_LEN},
+ serialize::{
+ AdvBuilder, AdvertisementType, CapacityLimitedVec, MicEncryptedSectionEncoder,
+ WriteDataElement,
+ },
+ V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN,
+ },
+ shared_data::TxPower,
+ NpVersionHeader,
+};
+use crypto_provider::ed25519;
+use crypto_provider_default::CryptoProviderImpl;
+use np_hkdf::{v1_salt::EXTENDED_SALT_LEN, DerivedSectionKeys};
+use sink::Sink;
+
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
+
+#[test]
+fn deserialize_mic_encrypted_correct_keys_extended_salt() {
+ deserialize_mic_encrypted_correct_keys(ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into())
+}
+
+#[test]
+fn deserialize_mic_encrypted_correct_keys_short_salt() {
+ deserialize_mic_encrypted_correct_keys(ShortV1Salt::from([3; SHORT_SALT_LEN]).into())
+}
+
+fn deserialize_mic_encrypted_correct_keys(salt: MultiSalt) {
+ let identity_token = V1IdentityToken::from([1; 16]);
+ let key_seed = [2; 32];
+ let broadcast_cm = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
+
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let mut section_builder = adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ salt,
+ &broadcast_cm,
+ ))
+ .unwrap();
+
+ let txpower_de = TxPowerDataElement::from(TxPower::try_from(5).unwrap());
+ section_builder.add_de(|_| txpower_de.clone()).unwrap();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+ let adv = adv_builder.into_advertisement();
+
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+
+ let adv_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+
+ let sections = parse_sections(adv_header, remaining).unwrap();
+ assert_eq!(1, sections.len());
+
+ let section = sections.into_iter().next().unwrap();
+ let enc_section = section.as_ciphertext().unwrap();
+
+ let contents = if let CiphertextSection::MicEncrypted(contents) = &enc_section {
+ contents
+ } else {
+ panic!("incorrect flavor");
+ };
+
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
+ // deserializing to Section works
+ let discovery_credential = V1BroadcastCredential::new(key_seed, identity_token, private_key)
+ .derive_discovery_credential::<CryptoProviderImpl>();
+
+ let arena = deserialization_arena!();
+ let mut allocator = arena.into_allocator();
+ let section = contents
+ .try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
+ &mut allocator,
+ &discovery_credential,
+ )
+ .unwrap();
+
+ assert_eq!(
+ DecryptedSection::new(
+ VerificationMode::Mic,
+ salt,
+ identity_token,
+ &[txpower_de.de_header().serialize().as_slice(), &[5],].concat(),
+ ),
+ section
+ );
+ let data_elements = section.collect_data_elements().unwrap();
+ assert_eq!(data_elements, &[DataElement::new(0.into(), 0x05_u8.into(), &[5])]);
+
+ let (_header, contents_bytes) =
+ remaining.split_at(1 + 1 + salt.as_slice().len() + V1_IDENTITY_TOKEN_LEN);
+ assert_eq!(
+ &MicEncryptedSection {
+ contents: EncryptedSectionContents {
+ adv_header,
+ format_bytes: &[match salt {
+ MultiSalt::Short(_) => {
+ V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN
+ }
+ MultiSalt::Extended(_) => {
+ V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN
+ }
+ }],
+ salt,
+ identity_token: first_section_identity_token(salt, remaining),
+ section_contents: &contents_bytes
+ [..contents_bytes.len() - SectionMic::CONTENTS_LEN],
+ total_section_contents_len: contents_bytes.len().try_into().unwrap(),
+ },
+ mic: SectionMic {
+ mic: contents_bytes[contents_bytes.len() - SectionMic::CONTENTS_LEN..]
+ .try_into()
+ .unwrap()
+ },
+ },
+ contents
+ );
+
+ // plaintext is correct
+ {
+ let identity_resolution_contents =
+ contents.contents.compute_identity_resolution_contents::<CryptoProviderImpl>();
+ let identity_match = identity_resolution_contents
+ .try_match::<CryptoProviderImpl>(&match salt {
+ MultiSalt::Short(_) => discovery_credential
+ .mic_short_salt_identity_resolution_material::<CryptoProviderImpl>()
+ .into_raw_resolution_material(),
+ MultiSalt::Extended(_) => discovery_credential
+ .mic_extended_salt_identity_resolution_material::<CryptoProviderImpl>()
+ .into_raw_resolution_material(),
+ })
+ .unwrap();
+ let arena = deserialization_arena!();
+ let mut allocator = arena.into_allocator();
+ let decrypted = contents
+ .contents
+ .decrypt_ciphertext::<CryptoProviderImpl>(&mut allocator, identity_match)
+ .unwrap();
+
+ let mut expected = Vec::new();
+ // battery de
+ expected.extend_from_slice(txpower_de.clone().de_header().serialize().as_slice());
+ let _ = txpower_de.write_de_contents(&mut expected);
+
+ assert_eq!(identity_token, decrypted.identity_token);
+ assert_eq!(&expected, decrypted.plaintext_contents);
+ }
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_incorrect_aes_key_error() {
+ // bad aes key -> bad metadata key plaintext
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_short_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .aes_key = [0xFF; 16].into();
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_incorrect_identity_token_hmac_key_error() {
+ // bad metadata key hmac key -> bad calculated metadata key mac
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_short_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .identity_token_hmac_key = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_incorrect_mic_hmac_key_error() {
+ // bad mic hmac key -> bad calculated mic
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ MicVerificationError::MicMismatch.into(),
+ |cm| {
+ cm.mic_short_salt_verification_material.mic_hmac_key = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_incorrect_expected_identity_token_hmac_error() {
+ // bad expected metadata key mac
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_short_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .expected_identity_token_hmac = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_incorrect_aes_key_error() {
+ // bad aes key -> bad metadata key plaintext
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_extended_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .aes_key = [0xFF; 16].into();
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_incorrect_identity_token_hmac_key_error() {
+ // bad metadata key hmac key -> bad calculated metadata key mac
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_extended_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .identity_token_hmac_key = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_incorrect_mic_hmac_key_error() {
+ // bad mic hmac key -> bad calculated mic
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ MicVerificationError::MicMismatch.into(),
+ |cm| {
+ cm.mic_extended_salt_verification_material.mic_hmac_key = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_incorrect_expected_identity_token_hmac_error() {
+ // bad expected metadata key mac
+ do_bad_deserialize_params::<CryptoProviderImpl>(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ |cm| {
+ cm.mic_extended_salt_identity_resolution_material
+ .as_mut_raw_resolution_material()
+ .expected_identity_token_hmac = [0xFF; 32];
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_incorrect_salt_error() {
+ // bad salt -> bad iv -> bad metadata key plaintext
+ do_bad_deserialize_tampered(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ ),
+ |_| {},
+ // replace the extended salt bytes
+ |adv| adv[2..18].fill(0xFF),
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_de_that_wont_parse() {
+ // add an extra byte to the section, leading it to try to parse a DE that doesn't exist
+ do_bad_deserialize_tampered(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ DeserializeError::DataElementParseError(DataElementParseError::UnexpectedDataAfterEnd),
+ |sec| sec.try_push(0xFF).unwrap(),
+ |_| {},
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_tampered_mic_error() {
+ // flip a bit in the first MIC byte
+ do_bad_deserialize_tampered(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ MicVerificationError::MicMismatch.into(),
+ ),
+ |_| {},
+ |adv| {
+ let mic_start = adv.len() - 16;
+ adv[mic_start] ^= 0x01
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_extended_salt_tampered_payload_error() {
+ // flip the last payload bit
+ do_bad_deserialize_tampered(
+ ExtendedV1Salt::from([3; EXTENDED_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ MicVerificationError::MicMismatch.into(),
+ ),
+ |_| {},
+ |adv| {
+ let before_mic = adv.len() - 17;
+ adv[before_mic] ^= 0x01
+ },
+ );
+}
+#[test]
+fn deserialize_mic_encrypted_short_salt_incorrect_salt_error() {
+ // bad salt -> bad iv -> bad metadata key plaintext
+ do_bad_deserialize_tampered(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ IdentityResolutionOrDeserializationError::IdentityMatchingError,
+ ),
+ |_| {},
+ // replace the extended salt bytes
+ |adv| adv[2..4].fill(0xFF),
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_de_that_wont_parse() {
+ // add an extra byte to the section, leading it to try to parse a DE that doesn't exist
+ do_bad_deserialize_tampered(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ DeserializeError::DataElementParseError(DataElementParseError::UnexpectedDataAfterEnd),
+ |sec| sec.try_push(0xFF).unwrap(),
+ |_| {},
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_tampered_mic_error() {
+ // flip a bit in the first MIC byte
+ do_bad_deserialize_tampered(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ MicVerificationError::MicMismatch.into(),
+ ),
+ |_| {},
+ |adv| {
+ let mic_start = adv.len() - 16;
+ adv[mic_start] ^= 0x01
+ },
+ );
+}
+
+#[test]
+fn deserialize_mic_encrypted_short_salt_tampered_payload_error() {
+ // flip the last payload bit
+ do_bad_deserialize_tampered(
+ ShortV1Salt::from([3; SHORT_SALT_LEN]).into(),
+ DeserializeError::IdentityResolutionOrDeserializationError(
+ MicVerificationError::MicMismatch.into(),
+ ),
+ |_| {},
+ |adv| {
+ let before_mic = adv.len() - 17;
+ adv[before_mic] ^= 0x01
+ },
+ );
+}
+
+#[test]
+fn arena_out_of_space_on_mic_verify() {
+ let identity_token = V1IdentityToken::from([1; 16]);
+ let key_seed = [2; 32];
+ let section_salt = ExtendedV1Salt::from([3; 16]);
+ let broadcast_cm = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
+
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let mut section_builder = adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ section_salt,
+ &broadcast_cm,
+ ))
+ .unwrap();
+
+ let txpower_de = TxPowerDataElement::from(TxPower::try_from(5).unwrap());
+ section_builder.add_de(|_| txpower_de.clone()).unwrap();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+ let adv = adv_builder.into_advertisement();
+
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+
+ let adv_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+
+ let sections = parse_sections(adv_header, remaining).unwrap();
+ assert_eq!(1, sections.len());
+
+ let section = sections.into_iter().next().unwrap();
+ let enc_section = section.as_ciphertext().unwrap();
+
+ let contents = if let CiphertextSection::MicEncrypted(contents) = &enc_section {
+ contents
+ } else {
+ panic!("incorrect flavor");
+ };
+
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
+ // deserializing to Section works
+ let discovery_credential = V1BroadcastCredential::new(key_seed, identity_token, private_key)
+ .derive_discovery_credential::<CryptoProviderImpl>();
+
+ let arena = deserialization_arena!();
+ let mut allocator = arena.into_allocator();
+ let _ = allocator.allocate(250).unwrap();
+ let res = contents.try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
+ &mut allocator,
+ &discovery_credential,
+ );
+ assert_eq!(
+ Err(IdentityResolutionOrDeserializationError::DeserializationError(
+ DeserializationError::ArenaOutOfSpace
+ )),
+ res
+ );
+}
+
+/// Attempt a decryption that will fail when using the provided parameters for decryption only.
+/// `None` means use the correct value for that parameter.
+fn do_bad_deserialize_params<C: CryptoProvider>(
+ salt: MultiSalt,
+ error: IdentityResolutionOrDeserializationError<MicVerificationError>,
+ mut mangle_crypto_material: impl FnMut(&mut PrecalculatedV1DiscoveryCryptoMaterial),
+) {
+ let identity_token = V1IdentityToken([1; 16]);
+ let key_seed = [2; 32];
+ let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
+
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+
+ let broadcast_cm = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
+
+ let mut section_builder = adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ salt,
+ &broadcast_cm,
+ ))
+ .unwrap();
+
+ section_builder.add_de(|_| TxPowerDataElement::from(TxPower::try_from(7).unwrap())).unwrap();
+
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+
+ let adv = adv_builder.into_advertisement();
+
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+
+ let v1_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+
+ let sections = parse_sections(v1_header, remaining).unwrap();
+ assert_eq!(1, sections.len());
+
+ let section = sections.into_iter().next().unwrap();
+ let enc_section = section.as_ciphertext().unwrap();
+ let contents = if let CiphertextSection::MicEncrypted(contents) = &enc_section {
+ contents
+ } else {
+ panic!("incorrect flavor");
+ };
+
+ // start with correct crypto material
+ let mut crypto_material = V1DiscoveryCredential::new(
+ key_seed,
+ key_seed_hkdf
+ .v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(&identity_token.0),
+ key_seed_hkdf
+ .v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(&identity_token.0),
+ key_seed_hkdf
+ .v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<C>(&identity_token.0),
+ crypto_provider::ed25519::PrivateKey::generate::<C::Ed25519>()
+ .derive_public_key::<C::Ed25519>(),
+ )
+ .to_precalculated::<C>();
+
+ // then break it per the test case
+ mangle_crypto_material(&mut crypto_material);
+
+ assert_eq!(
+ error,
+ contents
+ .try_resolve_identity_and_deserialize::<C>(
+ &mut deserialization_arena!().into_allocator(),
+ &crypto_material
+ )
+ .unwrap_err()
+ );
+}
+
+#[derive(Debug, PartialEq)]
+enum DeserializeError {
+ IdentityResolutionOrDeserializationError(
+ IdentityResolutionOrDeserializationError<MicVerificationError>,
+ ),
+ DataElementParseError(DataElementParseError),
+}
+
+fn do_bad_deserialize_tampered(
+ salt: MultiSalt,
+ expected_error: DeserializeError,
+ mangle_section: impl Fn(&mut CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>),
+ mangle_adv: impl Fn(&mut Vec<u8>),
+) {
+ let metadata_key = V1IdentityToken([1; 16]);
+ let key_seed = [2; 32];
+
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+
+ let broadcast_cm = V1BroadcastCredential::new(
+ key_seed,
+ metadata_key,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
+
+ let mut section_builder = adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ salt,
+ &broadcast_cm,
+ ))
+ .unwrap();
+
+ section_builder.add_de(|_| TxPowerDataElement::from(TxPower::try_from(7).unwrap())).unwrap();
+
+ mangle_section(&mut section_builder.section);
+
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+
+ let adv = adv_builder.into_advertisement();
+ let mut adv_mut = adv.as_slice().to_vec();
+ mangle_adv(&mut adv_mut);
+
+ let (remaining, header) = NpVersionHeader::parse(&adv_mut).unwrap();
+
+ let v1_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+
+ let sections = parse_sections(v1_header, remaining).unwrap();
+ assert_eq!(1, sections.len());
+
+ let section = sections.into_iter().next().unwrap();
+ let enc_section = section.as_ciphertext().unwrap();
+ let contents = if let CiphertextSection::MicEncrypted(contents) = &enc_section {
+ contents
+ } else {
+ panic!("incorrect flavor");
+ };
+
+ // generate a random key pair since we need _some_ public key in our discovery
+ // credential, even if it winds up going unused
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
+
+ let discovery_credential = V1BroadcastCredential::new(key_seed, metadata_key, private_key)
+ .derive_discovery_credential::<CryptoProviderImpl>();
+
+ match contents.try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
+ &mut deserialization_arena!().into_allocator(),
+ &discovery_credential,
+ ) {
+ Ok(section) => {
+ assert_eq!(
+ expected_error,
+ DeserializeError::DataElementParseError(
+ section.collect_data_elements().unwrap_err()
+ )
+ );
+ }
+ Err(e) => assert_eq!(
+ expected_error,
+ DeserializeError::IdentityResolutionOrDeserializationError(e),
+ ),
+ };
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/signature_decrypt_tests.rs b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/signature_decrypt_tests.rs
index af70228..d843cb0 100644
--- a/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/signature_decrypt_tests.rs
+++ b/nearby/presence/np_adv/src/extended/deserialize/encrypted_section/tests/signature_decrypt_tests.rs
@@ -16,63 +16,50 @@
extern crate std;
-use crate::deserialization_arena;
-use crate::extended::data_elements::TxPowerDataElement;
-use crate::extended::deserialize::{
- DataElementParseError, DecryptedSection, EncryptionInfo, RawV1Salt, SectionContents,
-};
-use crate::extended::serialize::AdvertisementType;
-use crate::shared_data::TxPower;
+use super::*;
use crate::{
- credential::v1::*,
- de_type::EncryptedIdentityDataElementType,
+ deserialization_arena,
extended::{
+ data_elements::TxPowerDataElement,
deserialize::{
- encrypted_section::{
- EncryptedSectionContents, IdentityResolutionOrDeserializationError,
- SignatureEncryptedSection, SignatureVerificationError,
+ encrypted_section,
+ section::intermediate::{
+ parse_sections, tests::IntermediateSectionExt, CiphertextSection,
},
- parse_sections,
- test_stubs::IntermediateSectionExt,
- CiphertextSection, DataElement, EncryptedIdentityMetadata, VerificationMode,
+ DataElement, DataElementParseError, Section,
},
- section_signature_payload::*,
serialize::{
- AdvBuilder, CapacityLimitedVec, SignedEncryptedSectionEncoder, SingleTypeDataElement,
- WriteDataElement,
+ AdvBuilder, AdvertisementType, CapacityLimitedVec, SignedEncryptedSectionEncoder,
+ SingleTypeDataElement, WriteDataElement,
},
- NP_ADV_MAX_SECTION_LEN,
+ V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN,
},
- parse_adv_header, AdvHeader, MetadataKey, Section,
+ shared_data::TxPower,
+ NpVersionHeader,
};
-use crypto_provider::{aes::ctr::AesCtrNonce, CryptoProvider};
+use crypto_provider::ed25519;
use crypto_provider_default::CryptoProviderImpl;
-use np_hkdf::v1_salt;
-use np_hkdf::v1_salt::V1Salt;
+use np_hkdf::{v1_salt, DerivedSectionKeys};
use sink::Sink;
use std::{prelude::rust_2021::*, vec};
-type KeyPair = np_ed25519::KeyPair<CryptoProviderImpl>;
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
#[test]
-fn deserialize_signature_encrypted_correct_keys() {
- let metadata_key = MetadataKey([1; 16]);
+fn deserialize_signature_encrypted_correct_keys_extended_salt() {
+ let identity_token = V1IdentityToken::from([1; 16]);
let key_seed = [2; 32];
- let raw_salt = RawV1Salt([3; 16]);
- let section_salt = V1Salt::<CryptoProviderImpl>::from(raw_salt);
- let identity_type = EncryptedIdentityDataElementType::Private;
+ let section_salt = ExtendedV1Salt::from([3; 16]);
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let key_pair = KeyPair::generate();
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cm = V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- V1Salt::from(*section_salt.as_array_ref()),
+ .section_builder(SignedEncryptedSectionEncoder::new::<CryptoProviderImpl>(
+ section_salt,
&broadcast_cm,
))
.unwrap();
@@ -80,63 +67,72 @@ fn deserialize_signature_encrypted_correct_keys() {
let txpower_de = TxPowerDataElement::from(TxPower::try_from(7).unwrap());
section_builder.add_de(|_| txpower_de.clone()).unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
+ let (after_version_header, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
- let adv_header = if let AdvHeader::V1(h) = header {
+ let adv_header = if let NpVersionHeader::V1(h) = header {
h
} else {
panic!("incorrect header");
};
- let sections = parse_sections(adv_header, remaining).unwrap();
+ let sections = parse_sections(adv_header, after_version_header).unwrap();
assert_eq!(1, sections.len());
let section = sections.into_iter().next().unwrap();
let enc_section = section.as_ciphertext().unwrap();
- let contents = if let CiphertextSection::SignatureEncryptedIdentity(contents) = &enc_section {
+ let contents = if let CiphertextSection::SignatureEncrypted(contents) = &enc_section {
contents
} else {
panic!("incorrect flavor");
};
- let mut encryption_info_bytes = [0_u8; 19];
- encryption_info_bytes[0..2].copy_from_slice(&[0x91, 0x10]);
- encryption_info_bytes[2] = 0x08;
- encryption_info_bytes[3..].copy_from_slice(section_salt.as_slice());
-
- let section_len = 19 + 2 + 16 + 2 + 64;
assert_eq!(
&SignatureEncryptedSection {
contents: EncryptedSectionContents {
- section_header: section_len,
adv_header,
- encryption_info: EncryptionInfo { bytes: encryption_info_bytes },
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x1],
- offset: 1.into(),
- identity_type: EncryptedIdentityDataElementType::Private,
- },
- // adv header + salt + section header + encryption info + identity header
- all_ciphertext: &adv.as_slice()[1 + 1 + 19 + 2..],
+ format_bytes: &[V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN],
+ salt: section_salt,
+ identity_token: first_section_identity_token(
+ section_salt.into(),
+ after_version_header
+ ),
+ // adv header + section len + format + salt + identity token
+ section_contents: first_section_contents(after_version_header),
+ total_section_contents_len: contents.contents.total_section_contents_len
},
},
contents
);
+ let mut de_bytes = Vec::new();
+ de_bytes.extend_from_slice(txpower_de.de_header().serialize().as_slice());
+ let _ = txpower_de.write_de_contents(&mut de_bytes);
+ let de_bytes = de_bytes;
+
// plaintext is correct
{
- let crypto_material = V1DiscoveryCredential::new(
+ let credential = V1DiscoveryCredential::new(
key_seed,
- key_seed_hkdf.extended_unsigned_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_seed_hkdf.extended_signed_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_pair.public().to_bytes(),
+ key_seed_hkdf
+ .v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ private_key.derive_public_key::<Ed25519ProviderImpl>(),
);
let signed_identity_resolution_material =
- crypto_material.signed_identity_resolution_material::<CryptoProviderImpl>();
+ credential.signed_identity_resolution_material::<CryptoProviderImpl>();
let identity_resolution_contents =
contents.contents.compute_identity_resolution_contents::<CryptoProviderImpl>();
let identity_match = identity_resolution_contents
@@ -150,45 +146,47 @@ fn deserialize_signature_encrypted_correct_keys() {
let decrypted =
contents.contents.decrypt_ciphertext(&mut allocator, identity_match).unwrap();
- let mut expected = Vec::new();
- expected.extend_from_slice(txpower_de.de_header().serialize().as_slice());
- let _ = txpower_de.write_de_contents(&mut expected);
-
- let nonce: AesCtrNonce = section_salt.derive(Some(1.into())).unwrap();
+ let nonce: AesCtrNonce = section_salt.compute_nonce::<CryptoProviderImpl>();
- let mut encryption_info = vec![0x91, 0x10, 0x08];
- encryption_info.extend_from_slice(section_salt.as_slice());
- let encryption_info: [u8; EncryptionInfo::TOTAL_DE_LEN] =
- encryption_info.try_into().unwrap();
-
- let sig_payload = SectionSignaturePayload::from_deserialized_parts(
- 0x20,
- section_len,
- &encryption_info,
+ let sig_payload = SectionSignaturePayload::new(
+ &[V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN],
+ section_salt.as_slice(),
&nonce,
- [0x90, 0x1],
- metadata_key,
- &expected,
+ identity_token.as_slice(),
+ (de_bytes.len() + crypto_provider::ed25519::SIGNATURE_LENGTH).try_into().unwrap(),
+ &de_bytes,
);
- expected.extend_from_slice(&sig_payload.sign(&key_pair).to_bytes());
- assert_eq!(metadata_key, decrypted.metadata_key_plaintext);
+ let mut de_and_sig = de_bytes.clone();
+ de_and_sig
+ .extend_from_slice(&sig_payload.sign::<Ed25519ProviderImpl>(&private_key).to_bytes());
+ assert_eq!(identity_token, decrypted.identity_token);
assert_eq!(nonce, decrypted.nonce);
- assert_eq!(&expected, decrypted.plaintext_contents);
+ assert_eq!(&de_and_sig, decrypted.plaintext_contents);
}
// deserialization to Section works
{
- let crypto_material = V1DiscoveryCredential::new(
+ let credential = V1DiscoveryCredential::new(
key_seed,
- key_seed_hkdf.extended_unsigned_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_seed_hkdf.extended_signed_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_pair.public().to_bytes(),
+ key_seed_hkdf
+ .v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ private_key.derive_public_key::<Ed25519ProviderImpl>(),
);
let signed_identity_resolution_material =
- crypto_material.signed_identity_resolution_material::<CryptoProviderImpl>();
+ credential.signed_identity_resolution_material::<CryptoProviderImpl>();
let signed_verification_material =
- crypto_material.signed_verification_material::<CryptoProviderImpl>();
+ credential.signed_verification_material::<CryptoProviderImpl>();
let arena = deserialization_arena!();
let mut allocator = arena.into_allocator();
@@ -202,27 +200,18 @@ fn deserialize_signature_encrypted_correct_keys() {
assert_eq!(
DecryptedSection::new(
- EncryptedIdentityDataElementType::Private,
VerificationMode::Signature,
- metadata_key,
- raw_salt,
- SectionContents {
- section_header: 19 + 2 + 16 + 1 + 1 + 64,
- data_element_start_offset: 2,
- de_region_excl_identity:
- &[txpower_de.de_header().serialize().as_slice(), &[7],].concat(),
- },
+ section_salt.into(),
+ identity_token,
+ &de_bytes,
),
section
);
let data_elements = section.collect_data_elements().unwrap();
- assert_eq!(
- data_elements,
- &[DataElement { offset: 2.into(), de_type: 0x05_u8.into(), contents: &[7] }]
- );
+ assert_eq!(data_elements, &[DataElement::new(0.into(), 0x05_u8.into(), &[7])]);
assert_eq!(
- vec![(v1_salt::DataElementOffset::from(2_u8), TxPowerDataElement::DE_TYPE, vec![7u8])],
+ vec![(v1_salt::DataElementOffset::from(0_u8), TxPowerDataElement::DE_TYPE, vec![7u8])],
data_elements
.into_iter()
.map(|de| (de.offset(), de.de_type(), de.contents().to_vec()))
@@ -275,7 +264,10 @@ fn deserialize_signature_encrypted_incorrect_pub_key_error() {
None,
None,
None,
- Some(KeyPair::generate().public()),
+ Some(
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>()
+ .derive_public_key::<Ed25519ProviderImpl>(),
+ ),
);
}
@@ -288,7 +280,9 @@ fn deserialize_signature_encrypted_incorrect_salt_error() {
),
None,
|_| {},
- |adv_mut| adv_mut[5..21].copy_from_slice(&[0xFF; 16]),
+ |adv_mut| {
+ adv_mut[1 + 1 + 1..][..EXTENDED_SALT_LEN].copy_from_slice(&[0xFF; EXTENDED_SALT_LEN])
+ },
)
}
@@ -325,19 +319,19 @@ fn deserialize_signature_encrypted_tampered_ciphertext_error() {
}
#[test]
-fn deserialize_signature_encrypted_missing_signature_de_error() {
- let section_len = 19 + 2 + 16 + 1 + 1;
+fn deserialize_signature_encrypted_missing_signature_error() {
+ let de_len = 2;
do_bad_deserialize_tampered(
DeserializeError::IdentityResolutionOrDeserializationError(
SignatureVerificationError::SignatureMissing.into(),
),
- Some(section_len),
+ Some(de_len as u8),
|_| {},
|adv_mut| {
- // chop off signature DE
+ // chop off signature
adv_mut.truncate(adv_mut.len() - 64);
// fix section length
- adv_mut[1] = section_len;
+ adv_mut[1 + 1 + EXTENDED_SALT_LEN + V1_IDENTITY_TOKEN_LEN..][0] = de_len as u8;
},
)
}
@@ -346,51 +340,81 @@ fn deserialize_signature_encrypted_missing_signature_de_error() {
fn deserialize_signature_encrypted_des_wont_parse() {
do_bad_deserialize_tampered(
DeserializeError::DataElementParseError(DataElementParseError::UnexpectedDataAfterEnd),
- Some(19 + 2 + 16 + 1 + 1 + 64 + 1),
+ Some(2 + 1 + crypto_provider::ed25519::SIGNATURE_LENGTH as u8),
// add an impossible DE
- |section| section.try_push(0xFF).unwrap(),
+ |section| {
+ section.try_push(0xFF).unwrap();
+ },
|_| {},
)
}
+#[test]
+fn arena_out_of_space_on_signature_verify() {
+ let salt: ExtendedV1Salt = [0; 16].into();
+ let nonce = salt.compute_nonce::<CryptoProviderImpl>();
+ let sig_enc_section = SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ V1AdvHeader::new(0),
+ &[0],
+ [0; 16].into(),
+ [0x00; V1_IDENTITY_TOKEN_LEN].into(),
+ 1,
+ &[0x00; 1],
+ ),
+ };
+
+ let arena = deserialization_arena!();
+ let mut allocator = arena.into_allocator();
+ let _ = allocator.allocate(250).unwrap();
+
+ let cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
+ &[0u8; 16].into(),
+ NonceAndCounter::from_nonce(nonce),
+ );
+ let im: encrypted_section::IdentityMatch<CryptoProviderImpl> =
+ IdentityMatch { cipher, identity_token: V1IdentityToken([0; 16]), nonce };
+
+ let signed_verification_material = SignedSectionVerificationMaterial {
+ public_key: ed25519::PublicKey::from_bytes::<Ed25519ProviderImpl>([0u8; 32])
+ .expect("public key should be valid bytes"),
+ };
+
+ let _ = sig_enc_section.try_deserialize(&mut allocator, im, &signed_verification_material);
+}
+
/// Attempt a deserialization that will fail when using the provided parameters for decryption only.
/// `None` means use the correct value for that parameter.
fn do_bad_deserialize_params<C: CryptoProvider>(
error: IdentityResolutionOrDeserializationError<SignatureVerificationError>,
aes_key: Option<crypto_provider::aes::Aes128Key>,
- metadata_key_hmac_key: Option<np_hkdf::NpHmacSha256Key<C>>,
+ metadata_key_hmac_key: Option<np_hkdf::NpHmacSha256Key>,
expected_metadata_key_hmac: Option<[u8; 32]>,
- pub_key: Option<np_ed25519::PublicKey<C>>,
+ pub_key: Option<ed25519::PublicKey>,
) {
- let metadata_key = MetadataKey([1; 16]);
+ let metadata_key = V1IdentityToken([1; 16]);
let key_seed = [2; 32];
- let section_salt: v1_salt::V1Salt<C> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
- let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::new(&key_seed);
- let key_pair = np_ed25519::KeyPair::<C>::generate();
+ let section_salt: v1_salt::ExtendedV1Salt = [3; 16].into();
+ let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
+ let private_key = ed25519::PrivateKey::generate::<C::Ed25519>();
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cm = V1BroadcastCredential::new(key_seed, metadata_key, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::new(
- identity_type,
- section_salt,
- &broadcast_cm,
- ))
+ .section_builder(SignedEncryptedSectionEncoder::new::<C>(section_salt, &broadcast_cm))
.unwrap();
section_builder.add_de_res(|_| TxPower::try_from(2).map(TxPowerDataElement::from)).unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
- let v1_header = if let AdvHeader::V1(h) = header {
+ let v1_header = if let NpVersionHeader::V1(h) = header {
h
} else {
panic!("incorrect header");
@@ -401,7 +425,7 @@ fn do_bad_deserialize_params<C: CryptoProvider>(
let section = sections.into_iter().next().unwrap();
let enc_section = section.as_ciphertext().unwrap();
- let contents = if let CiphertextSection::SignatureEncryptedIdentity(contents) = &enc_section {
+ let contents = if let CiphertextSection::SignatureEncrypted(contents) = &enc_section {
contents
} else {
panic!("incorrect flavor");
@@ -409,20 +433,22 @@ fn do_bad_deserialize_params<C: CryptoProvider>(
let signed_identity_resolution_material =
SignedSectionIdentityResolutionMaterial::from_raw(SectionIdentityResolutionMaterial {
- aes_key: aes_key.unwrap_or_else(|| key_seed_hkdf.extended_signed_section_aes_key()),
+ aes_key: aes_key.unwrap_or_else(|| key_seed_hkdf.v1_signature_keys().aes_key()),
- metadata_key_hmac_key: *metadata_key_hmac_key
- .unwrap_or_else(|| key_seed_hkdf.extended_signed_metadata_key_hmac_key())
+ identity_token_hmac_key: *metadata_key_hmac_key
+ .unwrap_or_else(|| key_seed_hkdf.v1_signature_keys().identity_token_hmac_key())
.as_bytes(),
- expected_metadata_key_hmac: expected_metadata_key_hmac.unwrap_or_else(|| {
+ expected_identity_token_hmac: expected_metadata_key_hmac.unwrap_or_else(|| {
key_seed_hkdf
- .extended_signed_metadata_key_hmac_key()
- .calculate_hmac(&metadata_key.0)
+ .v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&metadata_key.0)
}),
});
let signed_verification_material = SignedSectionVerificationMaterial {
- pub_key: pub_key.unwrap_or_else(|| key_pair.public()).to_bytes(),
+ public_key: pub_key
+ .unwrap_or_else(|| private_key.derive_public_key::<Ed25519ProviderImpl>()),
};
assert_eq!(
@@ -447,28 +473,25 @@ enum DeserializeError {
/// Run a test that mangles the advertisement contents before attempting to deserialize.
///
-/// Since the advertisement is ciphertext, only changes outside
+/// The section will have a TxPower DE added.
fn do_bad_deserialize_tampered(
expected_error: DeserializeError,
- expected_section_len: Option<u8>,
+ expected_section_de_len: Option<u8>,
mangle_section: impl Fn(&mut CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>),
mangle_adv_contents: impl Fn(&mut Vec<u8>),
) {
- let metadata_key = MetadataKey([1; 16]);
+ let identity_token = V1IdentityToken::from([1; V1_IDENTITY_TOKEN_LEN]);
let key_seed = [2; 32];
- let section_salt: v1_salt::V1Salt<CryptoProviderImpl> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
+ let section_salt: v1_salt::ExtendedV1Salt = [3; EXTENDED_SALT_LEN].into();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let key_pair = KeyPair::generate();
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cm = V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::new(
- identity_type,
+ .section_builder(SignedEncryptedSectionEncoder::new::<CryptoProviderImpl>(
section_salt,
&broadcast_cm,
))
@@ -478,64 +501,72 @@ fn do_bad_deserialize_tampered(
mangle_section(&mut section_builder.section);
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
let mut adv_mut = adv.as_slice().to_vec();
mangle_adv_contents(&mut adv_mut);
- let (remaining, header) = parse_adv_header(&adv_mut).unwrap();
+ let (after_version_header, header) = NpVersionHeader::parse(&adv_mut).unwrap();
- let adv_header = if let AdvHeader::V1(h) = header {
+ let adv_header = if let NpVersionHeader::V1(h) = header {
h
} else {
panic!("incorrect header");
};
- let sections = parse_sections(adv_header, remaining).unwrap();
+ let sections = parse_sections(adv_header, after_version_header).unwrap();
assert_eq!(1, sections.len());
let section = sections.into_iter().next().unwrap();
let enc_section = section.as_ciphertext().unwrap();
- let contents = if let CiphertextSection::SignatureEncryptedIdentity(contents) = &enc_section {
+ let contents = if let CiphertextSection::SignatureEncrypted(contents) = &enc_section {
contents
} else {
panic!("incorrect flavor");
};
+ if let Some(len) = expected_section_de_len {
+ assert_eq!(usize::from(len), contents.contents.section_contents.len());
+ }
- let mut encryption_info_bytes = [0_u8; 19];
- encryption_info_bytes[0..2].copy_from_slice(&[0x91, 0x10]);
- encryption_info_bytes[2] = 0x08;
- encryption_info_bytes[3..].copy_from_slice(&adv_mut[5..21]);
-
- let section_len = 19 + 2 + 16 + 2 + 64;
+ let extracted_salt = first_section_salt(after_version_header);
assert_eq!(
&SignatureEncryptedSection {
contents: EncryptedSectionContents {
- section_header: expected_section_len.unwrap_or(section_len),
adv_header,
- encryption_info: EncryptionInfo { bytes: encryption_info_bytes },
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x1],
- offset: 1.into(),
- identity_type: EncryptedIdentityDataElementType::Private,
- },
- all_ciphertext: &adv_mut[1 + 1 + 19 + 2..],
+ // extract data from adv buffer in case the caller tampered with things
+ salt: extracted_salt,
+ identity_token: first_section_identity_token(
+ extracted_salt.into(),
+ after_version_header
+ ),
+ section_contents: first_section_contents(after_version_header),
+ format_bytes: first_section_format(after_version_header),
+ total_section_contents_len: first_section_contents_len(after_version_header),
},
},
contents
);
- let crypto_material = V1DiscoveryCredential::new(
+ let credential = V1DiscoveryCredential::new(
key_seed,
- key_seed_hkdf.extended_unsigned_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_seed_hkdf.extended_signed_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_pair.public().to_bytes(),
+ key_seed_hkdf
+ .v1_mic_short_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_mic_extended_salt_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ key_seed_hkdf
+ .v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(&identity_token.0),
+ private_key.derive_public_key::<Ed25519ProviderImpl>(),
);
let identity_resolution_material =
- crypto_material.signed_identity_resolution_material::<CryptoProviderImpl>();
- let verification_material =
- crypto_material.signed_verification_material::<CryptoProviderImpl>();
+ credential.signed_identity_resolution_material::<CryptoProviderImpl>();
+ let verification_material = credential.signed_verification_material::<CryptoProviderImpl>();
match contents.try_resolve_identity_and_deserialize::<CryptoProviderImpl>(
&mut deserialization_arena!().into_allocator(),
diff --git a/nearby/presence/np_adv/src/extended/deserialize/mod.rs b/nearby/presence/np_adv/src/extended/deserialize/mod.rs
index 6ec7881..c6c7ba4 100644
--- a/nearby/presence/np_adv/src/extended/deserialize/mod.rs
+++ b/nearby/presence/np_adv/src/extended/deserialize/mod.rs
@@ -13,264 +13,84 @@
// limitations under the License.
//! Deserialization for V1 advertisement contents
-
#[cfg(any(test, feature = "alloc"))]
-extern crate alloc;
-
-#[cfg(any(test, feature = "alloc", feature = "devtools"))]
use alloc::vec::Vec;
-use core::array::TryFromSliceError;
-use core::fmt::Debug;
-use nom::{branch, bytes, combinator, error, multi, number, sequence};
-use strum::IntoEnumIterator as _;
+use core::{array::TryFromSliceError, fmt::Debug};
-use array_view::ArrayView;
-use crypto_provider::CryptoProvider;
-use np_hkdf::v1_salt::{self, V1Salt};
-
-use crate::array_vec::ArrayVecOption;
-#[cfg(any(feature = "devtools", test))]
-use crate::credential::v1::V1DiscoveryCryptoMaterial;
-use crate::credential::v1::V1;
-use crate::deserialization_arena::ArenaOutOfSpace;
-#[cfg(any(feature = "devtools", test))]
-use crate::deserialization_arena::DeserializationArenaAllocator;
-#[cfg(test)]
-use crate::extended::deserialize::encrypted_section::IdentityResolutionOrDeserializationError;
-use crate::extended::{NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT, NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT};
use crate::{
- de_type::{EncryptedIdentityDataElementType, IdentityDataElementType},
+ array_vec::ArrayVecOption,
+ credential::{
+ book::CredentialBook,
+ matched::{HasIdentityMatch, MatchedCredential, WithMatchedCredential},
+ v1::{V1DiscoveryCryptoMaterial, V1},
+ },
+ deserialization_arena::{ArenaOutOfSpace, DeserializationArena, DeserializationArenaAllocator},
extended::{
- data_elements::{MIC_ENCRYPTION_SCHEME, SIGNATURE_ENCRYPTION_SCHEME},
- de_type::{DeType, ExtendedDataElementType as _},
- deserialize::encrypted_section::{
- DeserializationError, EncryptedSectionContents, MicEncryptedSection,
- MicVerificationError, SignatureEncryptedSection, SignatureVerificationError,
+ deserialize::{
+ data_element::{DataElement, DataElementParseError, DataElementParsingIterator},
+ encrypted_section::{
+ DeserializationError, MicVerificationError, SectionIdentityResolutionContents,
+ SignatureVerificationError,
+ },
+ section::intermediate::{
+ parse_sections, CiphertextSection, IntermediateSection, PlaintextSection,
+ },
},
- DeLength, ENCRYPTION_INFO_DE_TYPE, METADATA_KEY_LEN, NP_ADV_MAX_SECTION_LEN,
+ salt::MultiSalt,
+ V1IdentityToken, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT,
},
- HasIdentityMatch, MetadataKey, PlaintextIdentityMode, V1Header,
+ header::V1AdvHeader,
+ AdvDeserializationError, AdvDeserializationErrorDetailsHazmat,
};
-
-pub(crate) mod encrypted_section;
-
-#[cfg(test)]
-mod parse_tests;
-
-#[cfg(test)]
-mod section_tests;
+use crypto_provider::CryptoProvider;
#[cfg(test)]
-mod test_stubs;
-
-/// Parse into [IntermediateSection]s, exposing the underlying parsing errors.
-/// Consumes all of `adv_body`.
-pub(crate) fn parse_sections(
- adv_header: V1Header,
- adv_body: &[u8],
-) -> Result<
- ArrayVecOption<IntermediateSection, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT>,
- nom::Err<error::Error<&[u8]>>,
-> {
- combinator::all_consuming(branch::alt((
- // Public advertisement
- multi::fold_many_m_n(
- 1,
- NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT,
- IntermediateSection::parser_public_section(),
- ArrayVecOption::default,
- |mut acc, item| {
- acc.push(item);
- acc
- },
- ),
- // Encrypted advertisement
- multi::fold_many_m_n(
- 1,
- NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT,
- IntermediateSection::parser_encrypted_with_header(adv_header),
- ArrayVecOption::default,
- |mut acc, item| {
- acc.push(item);
- acc
- },
- ),
- )))(adv_body)
- .map(|(_rem, sections)| sections)
-}
+mod tests;
-/// A partially processed section that hasn't been decrypted (if applicable) yet.
-#[derive(PartialEq, Eq, Debug)]
-pub(crate) enum IntermediateSection<'a> {
- /// A section that was not encrypted, e.g. a public identity or no-identity section.
- Plaintext(PlaintextSection<'a>),
- /// A section whose contents were encrypted, e.g. a private identity section.
- Ciphertext(CiphertextSection<'a>),
-}
-
-impl<'a> IntermediateSection<'a> {
- fn parser_public_section(
- ) -> impl Fn(&'a [u8]) -> nom::IResult<&'a [u8], IntermediateSection<'a>> {
- move |adv_body| {
- let (remaining, section_contents_len) =
- combinator::verify(number::complete::u8, |sec_len| {
- *sec_len as usize <= NP_ADV_MAX_SECTION_LEN && *sec_len as usize > 0
- })(adv_body)?;
-
- // Section structure possibilities:
- // - Public Identity DE, all other DEs
- let parse_public_identity = combinator::map(
- // 1 starting offset because of public identity before it
- sequence::tuple((PublicIdentity::parse, nom::combinator::rest)),
- // move closure to copy section_len into scope
- move |(_identity, rest)| {
- IntermediateSection::Plaintext(PlaintextSection::new(
- PlaintextIdentityMode::Public,
- SectionContents::new(
- /* section_header */ section_contents_len,
- rest,
- 1,
- ),
- ))
- },
- );
- combinator::map_parser(
- bytes::complete::take(section_contents_len),
- // Guarantee we consume all of the section (not all of the adv body)
- // Note: `all_consuming` should never fail, since we used the `rest` parser above.
- combinator::all_consuming(parse_public_identity),
- )(remaining)
- }
- }
-
- fn parser_encrypted_with_header(
- adv_header: V1Header,
- ) -> impl Fn(&'a [u8]) -> nom::IResult<&[u8], IntermediateSection> {
- move |adv_body| {
- let (remaining, section_contents_len) =
- combinator::verify(number::complete::u8, |sec_len| {
- *sec_len as usize <= NP_ADV_MAX_SECTION_LEN && *sec_len as usize > 0
- })(adv_body)?;
-
- // Section structure possibilities:
- // - Encryption information, non-public Identity header, ciphertext
- // - Encryption information, non-public Identity header, ciphertext, MIC
-
- let parse_encrypted_identity = combinator::map(
- sequence::tuple((
- EncryptionInfo::parse_signature,
- combinator::verify(
- combinator::consumed(sequence::tuple((
- EncryptedIdentityMetadata::parser_at_offset(
- v1_salt::DataElementOffset::from(1),
- ),
- combinator::rest,
- ))),
- // should be trivially true since section length was checked above,
- // but this is an invariant for EncryptedSection, so we double check
- |(identity_and_ciphertext, _tuple)| {
- (METADATA_KEY_LEN..=NP_ADV_MAX_SECTION_LEN)
- .contains(&identity_and_ciphertext.len())
- },
- ),
- )),
- move |(encryption_info, (identity_and_ciphertext, (identity, _des_ciphertext)))| {
- // skip identity de header -- rest of that de is ciphertext
- let to_skip = identity.header_bytes.len();
- IntermediateSection::Ciphertext(CiphertextSection::SignatureEncryptedIdentity(
- SignatureEncryptedSection {
- contents: EncryptedSectionContents::new(
- adv_header,
- section_contents_len,
- encryption_info,
- identity,
- &identity_and_ciphertext[to_skip..],
- ),
- },
- ))
- },
- );
-
- let parse_mic_encrypted_identity = combinator::map(
- sequence::tuple((
- EncryptionInfo::parse_mic,
- combinator::verify(
- combinator::consumed(sequence::tuple((
- EncryptedIdentityMetadata::parser_at_offset(
- v1_salt::DataElementOffset::from(1),
- ),
- combinator::rest,
- ))),
- // Should be trivially true since section length was checked above,
- // but this is an invariant for MicEncryptedSection, so we double check.
- // Also verify that there is enough space at the end to contain a valid-length MIC.
- |(identity_ciphertext_and_mic, _tuple)| {
- (METADATA_KEY_LEN + SectionMic::CONTENTS_LEN..=NP_ADV_MAX_SECTION_LEN)
- .contains(&identity_ciphertext_and_mic.len())
- },
- ),
- )),
- move |(
- encryption_info,
- (identity_ciphertext_and_mic, (identity, _ciphertext_and_mic)),
- )| {
- // should not panic since we have already ensured a valid length
- let (identity_and_ciphertext, mic) = identity_ciphertext_and_mic
- .split_at(identity_ciphertext_and_mic.len() - SectionMic::CONTENTS_LEN);
- // skip identity de header -- rest of that de is ciphertext
- let to_skip = identity.header_bytes.len();
- IntermediateSection::Ciphertext(CiphertextSection::MicEncryptedIdentity(
- MicEncryptedSection {
- contents: EncryptedSectionContents::new(
- adv_header,
- section_contents_len,
- encryption_info,
- identity,
- &identity_and_ciphertext[to_skip..],
- ),
- mic: mic.try_into().unwrap_or_else(|_| {
- panic!("{} is a valid length", SectionMic::CONTENTS_LEN)
- }),
- },
- ))
- },
- );
-
- combinator::map_parser(
- bytes::complete::take(section_contents_len),
- // guarantee we consume all of the section (not all of the adv body)
- combinator::all_consuming(branch::alt((
- parse_mic_encrypted_identity,
- parse_encrypted_identity,
- ))),
- )(remaining)
- }
- }
-}
-
-#[derive(PartialEq, Eq, Debug)]
-struct SectionContents<'adv> {
- section_header: u8,
- de_region_excl_identity: &'adv [u8],
- data_element_start_offset: u8,
-}
-
-impl<'adv> SectionContents<'adv> {
- fn new(
- section_header: u8,
- de_region_excl_identity: &'adv [u8],
- data_element_start_offset: u8,
- ) -> Self {
- Self { section_header, de_region_excl_identity, data_element_start_offset }
- }
-
- fn iter_data_elements(&self) -> DataElementParsingIterator<'adv> {
- DataElementParsingIterator {
- input: self.de_region_excl_identity,
- offset: self.data_element_start_offset,
+pub mod data_element;
+pub(crate) mod encrypted_section;
+pub(crate) mod section;
+
+/// Provides deserialization APIs which expose more of the internals, suitable for use only in
+/// dev tools.
+#[cfg(feature = "devtools")]
+pub mod dev_tools;
+
+/// Deserialize and decrypt the contents of a v1 adv after the version header
+pub(crate) fn deser_decrypt_v1<'adv, 'cred, B, P>(
+ arena: DeserializationArena<'adv>,
+ cred_book: &'cred B,
+ remaining: &'adv [u8],
+ header: V1AdvHeader,
+) -> Result<V1AdvertisementContents<'adv, B::Matched>, AdvDeserializationError>
+where
+ B: CredentialBook<'cred>,
+ P: CryptoProvider,
+{
+ let mut sections_in_processing =
+ SectionsInProcessing::<'_, B::Matched>::from_advertisement_contents::<P>(
+ header, remaining,
+ )?;
+
+ let mut allocator = arena.into_allocator();
+
+ // Hot loop
+ // We assume that iterating credentials is more expensive than iterating sections
+ for (crypto_material, match_data) in cred_book.v1_iter() {
+ sections_in_processing
+ .try_decrypt_with_credential::<_, P>(&mut allocator, crypto_material, match_data)
+ .expect(concat!(
+ "Should not run out of space because DeserializationArenaAllocator is big ",
+ "enough to hold a single advertisement, and we exit immediately upon ",
+ "successful decryption",
+ ));
+ if sections_in_processing.resolved_all_identities() {
+ // No need to consider the other credentials
+ break;
}
}
+ Ok(sections_in_processing.finished_with_decryption_attempts())
}
/// A section deserialized from a V1 advertisement.
@@ -294,83 +114,24 @@ pub trait Section<'adv, E: Debug> {
}
}
-/// A plaintext section deserialized from a V1 advertisement.
-#[derive(PartialEq, Eq, Debug)]
-pub struct PlaintextSection<'adv> {
- identity: PlaintextIdentityMode,
- contents: SectionContents<'adv>,
-}
-
-impl<'adv> PlaintextSection<'adv> {
- fn new(identity: PlaintextIdentityMode, contents: SectionContents<'adv>) -> Self {
- Self { identity, contents }
- }
-
- /// The identity mode for the section.
- ///
- /// Since plaintext sections do not use encryption, they cannot be matched to a single identity,
- /// and only have a mode (no identity or public).
- pub fn identity(&self) -> PlaintextIdentityMode {
- self.identity
- }
-}
-
-impl<'adv> Section<'adv, DataElementParseError> for PlaintextSection<'adv> {
- type Iterator = DataElementParsingIterator<'adv>;
-
- fn iter_data_elements(&self) -> Self::Iterator {
- self.contents.iter_data_elements()
- }
-}
-
-/// A byte buffer the size of a V1 salt.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct RawV1Salt([u8; 16]);
-
-impl RawV1Salt {
- /// Returns the raw salt bytes as a vec.
- #[cfg(feature = "devtools")]
- pub fn to_vec(&self) -> Vec<u8> {
- self.0.to_vec()
- }
-}
-
-impl<C: CryptoProvider> From<RawV1Salt> for V1Salt<C> {
- fn from(raw_salt: RawV1Salt) -> Self {
- raw_salt.0.into()
- }
-}
-
-impl<C: CryptoProvider> From<V1Salt<C>> for RawV1Salt {
- fn from(salt: V1Salt<C>) -> Self {
- RawV1Salt(salt.into_array())
- }
-}
-
/// Fully-parsed and verified decrypted contents from an encrypted section.
#[derive(Debug, PartialEq, Eq)]
pub struct DecryptedSection<'adv> {
- identity_type: EncryptedIdentityDataElementType,
verification_mode: VerificationMode,
- metadata_key: MetadataKey,
- salt: RawV1Salt,
- contents: SectionContents<'adv>,
+ identity_token: V1IdentityToken,
+ salt: MultiSalt,
+ /// Decrypted DE data, excluding any encoder suffix
+ plaintext: &'adv [u8],
}
impl<'adv> DecryptedSection<'adv> {
fn new(
- identity_type: EncryptedIdentityDataElementType,
verification_mode: VerificationMode,
- metadata_key: MetadataKey,
- salt: RawV1Salt,
- contents: SectionContents<'adv>,
+ salt: MultiSalt,
+ identity_token: V1IdentityToken,
+ plaintext: &'adv [u8],
) -> Self {
- Self { identity_type, verification_mode, metadata_key, salt, contents }
- }
-
- /// The type of identity DE used in the section.
- pub fn identity_type(&self) -> EncryptedIdentityDataElementType {
- self.identity_type
+ Self { verification_mode, identity_token, salt, plaintext }
}
/// The verification mode used in the section.
@@ -378,16 +139,26 @@ impl<'adv> DecryptedSection<'adv> {
self.verification_mode
}
- /// The salt used for decryption of this advertisement.
- pub fn salt(&self) -> RawV1Salt {
- self.salt
+ /// The identity token extracted from the section
+ pub fn identity_token(&self) -> &V1IdentityToken {
+ &self.identity_token
+ }
+
+ /// The salt used for decryption of this section.
+ pub fn salt(&self) -> &MultiSalt {
+ &self.salt
+ }
+
+ #[cfg(test)]
+ pub(crate) fn plaintext(&self) -> &'adv [u8] {
+ self.plaintext
}
}
impl<'adv> HasIdentityMatch for DecryptedSection<'adv> {
type Version = V1;
- fn metadata_key(&self) -> MetadataKey {
- self.metadata_key
+ fn identity_token(&self) -> V1IdentityToken {
+ self.identity_token
}
}
@@ -395,88 +166,7 @@ impl<'adv> Section<'adv, DataElementParseError> for DecryptedSection<'adv> {
type Iterator = DataElementParsingIterator<'adv>;
fn iter_data_elements(&self) -> Self::Iterator {
- self.contents.iter_data_elements()
- }
-}
-
-#[derive(PartialEq, Eq, Debug)]
-pub(crate) enum CiphertextSection<'a> {
- SignatureEncryptedIdentity(SignatureEncryptedSection<'a>),
- MicEncryptedIdentity(MicEncryptedSection<'a>),
-}
-
-impl<'a> CiphertextSection<'a> {
- /// Tries to match this section's identity using the given crypto-material,
- /// and if successful, tries to decrypt this section.
- #[cfg(test)]
- pub(crate) fn try_resolve_identity_and_deserialize<C, P>(
- &'a self,
- allocator: &mut DeserializationArenaAllocator<'a>,
- crypto_material: &C,
- ) -> Result<DecryptedSection<'a>, SectionDeserializeError>
- where
- C: V1DiscoveryCryptoMaterial,
- P: CryptoProvider,
- {
- match self {
- CiphertextSection::SignatureEncryptedIdentity(contents) => {
- let identity_resolution_material =
- crypto_material.signed_identity_resolution_material::<P>();
- let verification_material = crypto_material.signed_verification_material::<P>();
-
- contents
- .try_resolve_identity_and_deserialize::<P>(
- allocator,
- &identity_resolution_material,
- &verification_material,
- )
- .map_err(|e| e.into())
- }
- CiphertextSection::MicEncryptedIdentity(contents) => {
- let identity_resolution_material =
- crypto_material.unsigned_identity_resolution_material::<P>();
- let verification_material = crypto_material.unsigned_verification_material::<P>();
-
- contents
- .try_resolve_identity_and_deserialize::<P>(
- allocator,
- &identity_resolution_material,
- &verification_material,
- )
- .map_err(|e| e.into())
- }
- }
- }
-
- /// Try decrypting into some raw bytes given some raw unsigned crypto-material.
- #[cfg(feature = "devtools")]
- pub(crate) fn try_resolve_identity_and_decrypt<
- C: V1DiscoveryCryptoMaterial,
- P: CryptoProvider,
- >(
- &self,
- allocator: &mut DeserializationArenaAllocator<'a>,
- crypto_material: &C,
- ) -> Option<Result<ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, ArenaOutOfSpace>> {
- match self {
- CiphertextSection::SignatureEncryptedIdentity(x) => {
- let identity_resolution_material =
- crypto_material.signed_identity_resolution_material::<P>();
- x.try_resolve_identity_and_decrypt::<P>(allocator, &identity_resolution_material)
- }
- CiphertextSection::MicEncryptedIdentity(x) => {
- let identity_resolution_material =
- crypto_material.unsigned_identity_resolution_material::<P>();
- x.try_resolve_identity_and_decrypt::<P>(allocator, &identity_resolution_material)
- }
- }
- }
-
- pub(crate) fn contents(&self) -> &EncryptedSectionContents<'a> {
- match self {
- CiphertextSection::SignatureEncryptedIdentity(x) => &x.contents,
- CiphertextSection::MicEncryptedIdentity(x) => &x.contents,
- }
+ DataElementParsingIterator::new(self.plaintext)
}
}
@@ -492,34 +182,6 @@ pub enum SectionDeserializeError {
ArenaOutOfSpace,
}
-#[cfg(test)]
-impl From<IdentityResolutionOrDeserializationError<MicVerificationError>>
- for SectionDeserializeError
-{
- fn from(error: IdentityResolutionOrDeserializationError<MicVerificationError>) -> Self {
- match error {
- IdentityResolutionOrDeserializationError::IdentityMatchingError => {
- Self::IncorrectCredential
- }
- IdentityResolutionOrDeserializationError::DeserializationError(e) => e.into(),
- }
- }
-}
-
-#[cfg(test)]
-impl From<IdentityResolutionOrDeserializationError<SignatureVerificationError>>
- for SectionDeserializeError
-{
- fn from(error: IdentityResolutionOrDeserializationError<SignatureVerificationError>) -> Self {
- match error {
- IdentityResolutionOrDeserializationError::IdentityMatchingError => {
- Self::IncorrectCredential
- }
- IdentityResolutionOrDeserializationError::DeserializationError(e) => e.into(),
- }
- }
-}
-
impl From<DeserializationError<MicVerificationError>> for SectionDeserializeError {
fn from(mic_deserialization_error: DeserializationError<MicVerificationError>) -> Self {
match mic_deserialization_error {
@@ -547,191 +209,226 @@ impl From<DeserializationError<SignatureVerificationError>> for SectionDeseriali
}
}
-/// An iterator that parses the given data elements iteratively. In environments where memory is
-/// not severely constrained, it is usually safer to collect this into `Result<Vec<DataElement>>`
-/// so the validity of the whole advertisement can be checked before proceeding with further
-/// processing.
-#[derive(Debug)]
-pub struct DataElementParsingIterator<'adv> {
- input: &'adv [u8],
- // The index of the data element this is currently at
- offset: u8,
-}
-
-/// The error that may arise while parsing data elements.
-#[derive(Debug, PartialEq, Eq)]
-pub enum DataElementParseError {
- /// Only one identity data element is allowed in an advertisement, but a duplicate is found
- /// while parsing.
- DuplicateIdentityDataElement,
- /// Unexpected data found after the end of the data elements portion. This means either the
- /// parser was fed with additional data (it should only be given the bytes within a section,
- /// not the whole advertisement), or the length field in the header of the data element is
- /// malformed.
- UnexpectedDataAfterEnd,
- /// There are too many data elements in the advertisement. The maximum number supported by the
- /// current parsing logic is 255.
- TooManyDataElements,
- /// A parse error is returned during nom.
- NomError(nom::error::ErrorKind),
-}
-
-impl<'adv> Iterator for DataElementParsingIterator<'adv> {
- type Item = Result<DataElement<'adv>, DataElementParseError>;
-
- fn next(&mut self) -> Option<Self::Item> {
- match ProtoDataElement::parse(self.input) {
- Ok((rem, pde)) => {
- if !IdentityDataElementType::iter().all(|t| t.type_code() != pde.header.de_type) {
- return Some(Err(DataElementParseError::DuplicateIdentityDataElement));
+/// A ciphertext section which has not yet been
+/// resolved to an identity, but for which some
+/// `SectionIdentityResolutionContents` have been
+/// pre-computed for speedy identity-resolution.
+struct ResolvableCiphertextSection<'a> {
+ identity_resolution_contents: SectionIdentityResolutionContents,
+ ciphertext_section: CiphertextSection<'a>,
+}
+
+/// A collection of possibly-deserialized sections which are separated according
+/// to whether/not they're intermediate encrypted sections (of either type)
+/// or fully-deserialized, with a running count of the number of malformed sections.
+/// Each potentially-valid section is tagged with a 0-based index derived from the original
+/// section ordering as they appeared within the original advertisement to ensure
+/// that the fully-deserialized advertisement may be correctly reconstructed.
+struct SectionsInProcessing<'adv, M: MatchedCredential> {
+ deserialized_sections: ArrayVecOption<
+ (usize, V1DeserializedSection<'adv, M>),
+ { NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT },
+ >,
+ encrypted_sections: ArrayVecOption<
+ (usize, ResolvableCiphertextSection<'adv>),
+ { NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT },
+ >,
+ malformed_sections_count: usize,
+}
+
+impl<'adv, M: MatchedCredential> SectionsInProcessing<'adv, M> {
+ /// Attempts to parse a V1 advertisement's contents after the version header
+ /// into a collection of not-yet-fully-deserialized sections which may
+ /// require credentials to be decrypted.
+ fn from_advertisement_contents<C: CryptoProvider>(
+ header: V1AdvHeader,
+ remaining: &'adv [u8],
+ ) -> Result<Self, AdvDeserializationError> {
+ let int_sections =
+ parse_sections(header, remaining).map_err(|_| AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError,
+ })?;
+ let mut deserialized_sections = ArrayVecOption::default();
+ let mut encrypted_sections = ArrayVecOption::default();
+ // keep track of ordering for later sorting during `self.finished_with_decryption_attempts()`.
+ for (idx, s) in int_sections.into_iter().enumerate() {
+ match s {
+ IntermediateSection::Plaintext(p) => {
+ deserialized_sections.push((idx, V1DeserializedSection::Plaintext(p)))
+ }
+ IntermediateSection::Ciphertext(ciphertext_section) => {
+ let identity_resolution_contents =
+ ciphertext_section.identity_resolution_contents::<C>();
+ let resolvable_ciphertext_section = ResolvableCiphertextSection {
+ identity_resolution_contents,
+ ciphertext_section,
+ };
+ encrypted_sections.push((idx, resolvable_ciphertext_section));
}
- self.input = rem;
- let current_offset = self.offset;
- self.offset = if let Some(offset) = self.offset.checked_add(1) {
- offset
- } else {
- return Some(Err(DataElementParseError::TooManyDataElements));
- };
- Some(Ok(pde.into_data_element(v1_salt::DataElementOffset::from(current_offset))))
- }
- Err(nom::Err::Failure(e)) => Some(Err(DataElementParseError::NomError(e.code))),
- Err(nom::Err::Incomplete(_)) => {
- panic!("Should always complete since we are parsing using the `nom::complete` APIs")
}
- Err(nom::Err::Error(_)) => {
- // nom `Error` is recoverable, it usually means we should move on the parsing the
- // next section. There is nothing after data elements within a section, so we just
- // check that there is no remaining data.
- if !self.input.is_empty() {
- return Some(Err(DataElementParseError::UnexpectedDataAfterEnd));
+ }
+ Ok(Self { deserialized_sections, encrypted_sections, malformed_sections_count: 0 })
+ }
+
+ /// Returns true iff we have resolved all sections to identities.
+ fn resolved_all_identities(&self) -> bool {
+ self.encrypted_sections.is_empty()
+ }
+
+ /// Runs through all of the encrypted sections in processing, and attempts
+ /// to use the given credential to decrypt them. Suitable for situations
+ /// where iterating over credentials is relatively slow compared to
+ /// the cost of iterating over sections-in-memory.
+ fn try_decrypt_with_credential<C: V1DiscoveryCryptoMaterial, P: CryptoProvider>(
+ &mut self,
+ arena: &mut DeserializationArenaAllocator<'adv>,
+ crypto_material: C,
+ match_data: M,
+ ) -> Result<(), ArenaOutOfSpace> {
+ let mut i = 0;
+ while i < self.encrypted_sections.len() {
+ let (section_idx, section): &(usize, ResolvableCiphertextSection) =
+ &self.encrypted_sections[i];
+ // Fast-path: Check for an identity match, ignore if there's no identity match.
+ let identity_resolution_contents = &section.identity_resolution_contents;
+ let identity_resolution_material = match &section.ciphertext_section {
+ CiphertextSection::MicEncrypted(m) => match m.contents.salt {
+ MultiSalt::Short(_) => crypto_material
+ .mic_short_salt_identity_resolution_material::<P>()
+ .into_raw_resolution_material(),
+ MultiSalt::Extended(_) => crypto_material
+ .mic_extended_salt_identity_resolution_material::<P>()
+ .into_raw_resolution_material(),
+ },
+
+ CiphertextSection::SignatureEncrypted(_) => crypto_material
+ .signed_identity_resolution_material::<P>()
+ .into_raw_resolution_material(),
+ };
+ match identity_resolution_contents.try_match::<P>(&identity_resolution_material) {
+ None => {
+ // Try again with another section
+ i += 1;
+ continue;
+ }
+ Some(identity_match) => {
+ // The identity matched, so now we need to more closely scrutinize
+ // the provided ciphertext. Try to decrypt and parse the section.
+ let deserialization_result = match &section.ciphertext_section {
+ CiphertextSection::SignatureEncrypted(c) => c
+ .try_deserialize(
+ arena,
+ identity_match,
+ &crypto_material.signed_verification_material::<P>(),
+ )
+ .map_err(SectionDeserializeError::from),
+ CiphertextSection::MicEncrypted(c) => c
+ .try_deserialize(arena, identity_match, &crypto_material)
+ .map_err(SectionDeserializeError::from),
+ };
+ match deserialization_result {
+ Ok(s) => {
+ self.deserialized_sections.push((
+ *section_idx,
+ V1DeserializedSection::Decrypted(WithMatchedCredential::new(
+ match_data.clone(),
+ crypto_material.metadata_nonce::<P>(),
+ s,
+ )),
+ ));
+ }
+ Err(e) => match e {
+ SectionDeserializeError::IncorrectCredential => {
+ // keep it around to try with another credential
+ i += 1;
+ continue;
+ }
+ SectionDeserializeError::ParseError => {
+ // the credential worked, but the section itself was bogus
+ self.malformed_sections_count += 1;
+ }
+ SectionDeserializeError::ArenaOutOfSpace => {
+ return Err(ArenaOutOfSpace);
+ }
+ },
+ }
+ // By default, if we have an identity match, assume that decrypting the section worked,
+ // or that the section was somehow invalid.
+ // We don't care about maintaining order, so use O(1) remove
+ let _ = self.encrypted_sections.swap_remove(i);
+ // don't advance i -- it now points to a new element
}
- None
}
}
+ Ok(())
}
-}
-
-/// Deserialize-specific version of a DE header that incorporates the header length.
-/// This is needed for encrypted identities that need to construct a slice of everything in the
-/// section following the identity DE header.
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub(crate) struct DeHeader {
- /// The original bytes of the header, at most 6 bytes long (1 byte len, 5 bytes type)
- pub(crate) header_bytes: ArrayView<u8, 6>,
- pub(crate) de_type: DeType,
- pub(crate) contents_len: DeLength,
-}
-impl DeHeader {
- pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], DeHeader> {
- // 1-byte header: 0b0LLLTTTT
- let parse_single_byte_de_header =
- combinator::map_opt::<&[u8], _, DeHeader, error::Error<&[u8]>, _, _>(
- combinator::consumed(combinator::map_res(
- combinator::verify(number::complete::u8, |&b| !hi_bit_set(b)),
- |b| {
- // L bits
- let len = (b >> 4) & 0x07;
- // T bits
- let de_type = ((b & 0x0F) as u32).into();
-
- len.try_into().map(|l| (l, de_type))
- },
- )),
- |(header_bytes, (len, de_type))| {
- ArrayView::try_from_slice(header_bytes).map(|header_bytes| DeHeader {
- header_bytes,
- contents_len: len,
- de_type,
- })
- },
- );
-
- // multi-byte headers: 0b1LLLLLLL (0b1TTTTTTT)* 0b0TTTTTTT
- // leading 1 in first byte = multibyte format
- // leading 1 in subsequent bytes = there is at least 1 more type bytes
- // leading 0 = this is the last header byte
- // 127-bit length, effectively infinite type bit length
-
- // It's conceivable to have non-canonical extended type sequences where 1 or more leading
- // bytes don't have any bits set (other than the marker hi bit), thereby contributing nothing
- // to the final value.
- // To prevent that, we require that either there be only 1 type byte, or that the first of the
- // multiple type bytes must have a value bit set. It's OK to have no value bits in subsequent
- // type bytes.
-
- let parse_ext_de_header = combinator::map_opt(
- combinator::consumed(sequence::pair(
- // length byte w/ leading 1
- combinator::map_res(
- combinator::verify(number::complete::u8::<&[u8], _>, |&b| hi_bit_set(b)),
- // snag the lower 7 bits
- |b| (b & 0x7F).try_into(),
- ),
- branch::alt((
- // 1 type byte case
- combinator::recognize(
- // 0-hi-bit type code byte
- combinator::verify(number::complete::u8, |&b| !hi_bit_set(b)),
- ),
- // multiple type byte case: leading type byte must have at least 1 value bit
- combinator::recognize(sequence::tuple((
- // hi bit and at least 1 value bit, otherwise it would be non-canonical
- combinator::verify(number::complete::u8, |&b| {
- hi_bit_set(b) && (b & 0x7F != 0)
- }),
- // 0-3 1-hi-bit type code bytes with any bit pattern. Max is 3 since two 7
- // bit type chunks are processed before and after this, for a total of 5,
- // and that's as many 7-bit chunks as are needed to support a 32-bit type.
- bytes::complete::take_while_m_n(0, 3, hi_bit_set),
- // final 0-hi-bit type code byte
- combinator::verify(number::complete::u8, |&b| !hi_bit_set(b)),
- ))),
- )),
- )),
- |(header_bytes, (len, type_bytes))| {
- // snag the low 7 bits of each type byte and accumulate
-
- type_bytes
- .iter()
- .try_fold(0_u32, |accum, b| {
- accum.checked_shl(7).map(|n| n + ((b & 0x7F) as u32))
- })
- .and_then(|type_code| {
- ArrayView::try_from_slice(header_bytes).map(|header_bytes| DeHeader {
- header_bytes,
- contents_len: len,
- de_type: type_code.into(),
- })
- })
- },
- );
+ /// Packages the current state of the deserialization process into a
+ /// `V1AdvertisementContents` representing a fully-deserialized V1 advertisement.
+ ///
+ /// This method should only be called after all sections were either successfully
+ /// decrypted or have had all relevant credentials checked against
+ /// them without obtaining a successful identity-match and/or subsequent
+ /// cryptographic verification of the section contents.
+ fn finished_with_decryption_attempts(mut self) -> V1AdvertisementContents<'adv, M> {
+ // Invalid sections = malformed sections + number of encrypted sections
+ // which we could not manage to decrypt with any of our credentials
+ let invalid_sections_count = self.malformed_sections_count + self.encrypted_sections.len();
- branch::alt((parse_single_byte_de_header, parse_ext_de_header))(input)
+ // Put the deserialized sections back into the original ordering for
+ // the returned `V1AdvertisementContents`
+ // (Note: idx is unique, so unstable sort is ok)
+ self.deserialized_sections.sort_unstable_by_key(|(idx, _section)| *idx);
+ let ordered_sections = self.deserialized_sections.into_iter().map(|(_idx, s)| s).collect();
+ V1AdvertisementContents::new(ordered_sections, invalid_sections_count)
}
}
-/// An intermediate stage in parsing a [DataElement] that lacks `offset`.
+/// The contents of a deserialized and decrypted V1 advertisement.
#[derive(Debug, PartialEq, Eq)]
-struct ProtoDataElement<'d> {
- header: DeHeader,
- /// `len()` must equal `header.contents_len`
- contents: &'d [u8],
+pub struct V1AdvertisementContents<'adv, M: MatchedCredential> {
+ sections: ArrayVecOption<V1DeserializedSection<'adv, M>, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT>,
+ invalid_sections: usize,
}
-impl<'d> ProtoDataElement<'d> {
- fn parse(input: &[u8]) -> nom::IResult<&[u8], ProtoDataElement> {
- let (remaining, header) = DeHeader::parse(input)?;
- let len = header.contents_len;
- combinator::map(bytes::complete::take(len.as_u8()), move |slice| {
- let header_clone = header.clone();
- ProtoDataElement { header: header_clone, contents: slice }
- })(remaining)
+impl<'adv, M: MatchedCredential> V1AdvertisementContents<'adv, M> {
+ fn new(
+ sections: ArrayVecOption<
+ V1DeserializedSection<'adv, M>,
+ NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT,
+ >,
+ invalid_sections: usize,
+ ) -> Self {
+ Self { sections, invalid_sections }
+ }
+
+ /// Destructures this V1 advertisement into just the sections
+ /// which could be successfully deserialized and decrypted
+ pub fn into_sections(
+ self,
+ ) -> ArrayVecOption<V1DeserializedSection<'adv, M>, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT> {
+ self.sections
}
- fn into_data_element(self, offset: v1_salt::DataElementOffset) -> DataElement<'d> {
- DataElement { offset, de_type: self.header.de_type, contents: self.contents }
+ /// The sections that could be successfully deserialized and decrypted
+ pub fn sections(&self) -> impl ExactSizeIterator<Item = &V1DeserializedSection<M>> {
+ self.sections.iter()
}
+
+ /// The number of sections that could not be parsed or decrypted.
+ pub fn invalid_sections_count(&self) -> usize {
+ self.invalid_sections
+ }
+}
+
+/// Advertisement content that was either already plaintext or has been decrypted.
+#[derive(Debug, PartialEq, Eq)]
+pub enum V1DeserializedSection<'adv, M: MatchedCredential> {
+ /// Section that was plaintext in the original advertisement
+ Plaintext(PlaintextSection<'adv>),
+ /// Section that was ciphertext in the original advertisement, and has been decrypted
+ /// with the credential in the [MatchedCredential]
+ Decrypted(WithMatchedCredential<M, DecryptedSection<'adv>>),
}
/// The level of integrity protection in an encrypted section
@@ -749,125 +446,13 @@ pub enum VerificationMode {
Signature,
}
-/// The identity used to successfully decrypt and validate an encrypted section
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct EncryptedSectionIdentity {
- identity_type: EncryptedIdentityDataElementType,
- validation_mode: VerificationMode,
- metadata_key: MetadataKey,
-}
-
-impl EncryptedSectionIdentity {
- /// The type of identity DE used in the section
- pub fn identity_type(&self) -> EncryptedIdentityDataElementType {
- self.identity_type
- }
- /// The validation mode used when decrypting and verifying the section
- pub fn verification_mode(&self) -> VerificationMode {
- self.validation_mode
- }
- /// The decrypted metadata key from the section's identity DE
- pub fn metadata_key(&self) -> MetadataKey {
- self.metadata_key
- }
-}
-
-/// A deserialized data element in a section.
-///
-/// The DE has been processed to the point of exposing a DE type and its contents as a `&[u8]`, but
-/// no DE-type-specific processing has been performed.
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct DataElement<'adv> {
- offset: v1_salt::DataElementOffset,
- de_type: DeType,
- contents: &'adv [u8],
-}
-
-impl<'adv> DataElement<'adv> {
- /// The offset of the DE in its containing Section.
- ///
- /// Used with the section salt to derive per-DE salt.
- pub fn offset(&self) -> v1_salt::DataElementOffset {
- self.offset
- }
- /// The type of the DE
- pub fn de_type(&self) -> DeType {
- self.de_type
- }
- /// The contents of the DE
- pub fn contents(&self) -> &'adv [u8] {
- self.contents
- }
-}
-
-#[derive(PartialEq, Eq, Debug, Clone)]
-pub(crate) struct EncryptionInfo {
- pub bytes: [u8; 19],
-}
-
-impl EncryptionInfo {
- // 2-byte header, 1-byte encryption scheme, 16-byte salt
- pub(crate) const TOTAL_DE_LEN: usize = 19;
- const CONTENTS_LEN: usize = 17;
- const ENCRYPTION_INFO_SCHEME_MASK: u8 = 0b01111000;
-
- fn parse_signature(input: &[u8]) -> nom::IResult<&[u8], EncryptionInfo> {
- Self::parser_for_scheme(SIGNATURE_ENCRYPTION_SCHEME)(input)
- }
-
- fn parse_mic(input: &[u8]) -> nom::IResult<&[u8], EncryptionInfo> {
- Self::parser_for_scheme(MIC_ENCRYPTION_SCHEME)(input)
- }
-
- fn parser_for_scheme(
- expected_scheme: u8,
- ) -> impl Fn(&[u8]) -> nom::IResult<&[u8], EncryptionInfo> {
- move |input| {
- combinator::map_res(
- combinator::consumed(combinator::map_parser(
- combinator::map(
- combinator::verify(ProtoDataElement::parse, |de| {
- de.header.de_type == ENCRYPTION_INFO_DE_TYPE
- && de.contents.len() == Self::CONTENTS_LEN
- }),
- |de| de.contents,
- ),
- sequence::tuple((
- combinator::verify(number::complete::be_u8, |scheme: &u8| {
- expected_scheme == (Self::ENCRYPTION_INFO_SCHEME_MASK & scheme)
- }),
- bytes::complete::take(16_usize),
- )),
- )),
- |(bytes, _contents)| bytes.try_into(),
- )(input)
- }
- }
-
- fn salt(&self) -> RawV1Salt {
- RawV1Salt(
- self.bytes[Self::TOTAL_DE_LEN - 16..]
- .try_into()
- .expect("a 16 byte slice will always fit into a 16 byte array"),
- )
- }
-}
-
-impl TryFrom<&[u8]> for EncryptionInfo {
- type Error = TryFromSliceError;
-
- fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
- value.try_into().map(|fixed_bytes: [u8; 19]| Ok(Self { bytes: fixed_bytes }))?
- }
-}
-
#[derive(PartialEq, Eq, Debug)]
pub(crate) struct SectionMic {
- mic: [u8; 16],
+ mic: [u8; Self::CONTENTS_LEN],
}
impl SectionMic {
- // 16-byte metadata key
+ /// 16-byte MIC
pub(crate) const CONTENTS_LEN: usize = 16;
}
@@ -886,57 +471,6 @@ impl TryFrom<&[u8]> for SectionMic {
}
}
-#[derive(PartialEq, Eq, Debug)]
-struct PublicIdentity;
-
-impl PublicIdentity {
- fn parse(input: &[u8]) -> nom::IResult<&[u8], PublicIdentity> {
- combinator::map(
- combinator::verify(DeHeader::parse, |deh| {
- deh.de_type == IdentityDataElementType::Public.type_code()
- && deh.contents_len.as_u8() == 0
- }),
- |_| PublicIdentity,
- )(input)
- }
-}
-
-/// Parsed form of an encrypted identity DE before its contents are decrypted.
-/// Metadata key is stored in the enclosing section.
-#[derive(PartialEq, Eq, Debug)]
-pub(crate) struct EncryptedIdentityMetadata {
- pub(crate) offset: v1_salt::DataElementOffset,
- /// The original DE header from the advertisement.
- /// Encrypted identity should always be a len=2 header.
- pub(crate) header_bytes: [u8; 2],
- pub(crate) identity_type: EncryptedIdentityDataElementType,
-}
-
-impl EncryptedIdentityMetadata {
- // 2-byte header, 16-byte metadata key
- pub(crate) const TOTAL_DE_LEN: usize = 18;
-
- /// Returns a parser function that parses an [`EncryptedIdentityMetadata`] using the provided DE `offset`.
- fn parser_at_offset(
- offset: v1_salt::DataElementOffset,
- ) -> impl Fn(&[u8]) -> nom::IResult<&[u8], EncryptedIdentityMetadata> {
- move |input| {
- combinator::map_opt(ProtoDataElement::parse, |de| {
- EncryptedIdentityDataElementType::from_type_code(de.header.de_type).and_then(
- |identity_type| {
- de.header.header_bytes.as_slice().try_into().ok().and_then(|header_bytes| {
- de.contents.try_into().ok().map(|_metadata_key_ciphertext: [u8; 16]| {
- // ensure the ciphertext is the right size, then discard
- EncryptedIdentityMetadata { header_bytes, offset, identity_type }
- })
- })
- },
- )
- })(input)
- }
- }
-}
-
fn hi_bit_set(b: u8) -> bool {
b & 0x80 > 0
}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/parse_tests.rs b/nearby/presence/np_adv/src/extended/deserialize/parse_tests.rs
deleted file mode 100644
index 41eb054..0000000
--- a/nearby/presence/np_adv/src/extended/deserialize/parse_tests.rs
+++ /dev/null
@@ -1,703 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-use super::*;
-use crate::extended::deserialize::encrypted_section::{
- MicEncryptedSection, SignatureEncryptedSection,
-};
-use crate::extended::deserialize::test_stubs::IntermediateSectionExt;
-use rand::rngs::StdRng;
-use rand::seq::SliceRandom;
-use rand::{Rng, SeedableRng};
-use std::vec;
-
-#[test]
-fn parse_adv_ext_public_identity() {
- // 2 sections, 3 DEs each
- let mut adv_body = vec![];
- // section
- adv_body.push(10);
- // public identity
- adv_body.push(0x03);
- // de 1 byte header, type 5, len 5
- adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
- // de 2 byte header, type 6, len 1
- adv_body.extend_from_slice(&[0x81, 0x06, 0x01]);
-
- let parsed_sections =
- parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap().into_vec();
- assert_eq!(
- vec![IntermediateSection::from(PlaintextSection::new(
- PlaintextIdentityMode::Public,
- SectionContents::new(10, &adv_body[2..], 1)
- ))],
- parsed_sections,
- );
- let expected_des = [
- // 1 byte header, len 5
- DataElement {
- offset: 1_u8.into(),
- de_type: 5_u8.into(),
- contents: &[0x01, 0x02, 0x03, 0x04, 0x05],
- },
- // 2 byte header, len 1
- DataElement { offset: 2_u8.into(), de_type: 6_u8.into(), contents: &[0x01] },
- ];
-
- assert_eq!(
- &expected_des[..],
- &parsed_sections[0].as_plaintext().unwrap().collect_data_elements().unwrap()
- );
-}
-
-#[test]
-fn parse_adv_ext_identity() {
- // 3 sections
- let mut adv_body = vec![];
- // section - 48 bytes total
- adv_body.push(19 + 18 + 10);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x08, // scheme (signature)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // private identity -- 2 + 16x 0x33
- adv_body.extend_from_slice(&[
- 0x90, 0x01, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x33,
- ]);
- // 10 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 10]);
-
- // section - 49 bytes total
- adv_body.push(19 + 18 + 11);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x08, // scheme (signature)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // trusted identity -- 2 + 16x 0x55
- adv_body.extend_from_slice(&[
- 0x90, 0x02, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55,
- ]);
- // 11 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 11]);
-
- // section - 50 bytes total
- adv_body.push(19 + 18 + 12);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x08, // scheme (signature)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // provisioned identity -- 2 + 16x 0x77
- adv_body.extend_from_slice(&[
- 0x90, 0x04, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
- 0x77, 0x77, 0x77,
- ]);
- // 12 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 12]);
-
- let adv_header = V1Header { header_byte: 0x20 };
- let encryption_info = EncryptionInfo {
- bytes: [
- 0x91, 0x10, // header bytes
- 0x08, // scheme (signature)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11,
- ],
- };
- let expected_sections = [
- SignatureEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 47,
- adv_header,
- encryption_info: encryption_info.clone(),
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x01],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Private,
- },
- // skip section header + encryption info + identity header -> end of section
- all_ciphertext: &adv_body[1 + 19 + 2..48],
- },
- },
- SignatureEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 48,
- adv_header,
- encryption_info: encryption_info.clone(),
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x02],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Trusted,
- },
- all_ciphertext: &adv_body[48 + 1 + 19 + 2..97],
- },
- },
- SignatureEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 49,
- adv_header,
- encryption_info,
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x04],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Provisioned,
- },
- all_ciphertext: &adv_body[97 + 1 + 19 + 2..],
- },
- },
- ];
- let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
- assert_eq!(parsed_sections.into_vec(), expected_sections.map(IntermediateSection::from));
-}
-
-#[test]
-fn parse_adv_ext_mic_identity() {
- // 3 sections
- let mut adv_body = vec![];
- // section - 64 bytes total
- adv_body.push(19 + 18 + 10 + 16);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x00, // scheme (mic)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // private identity -- 2 + 16x 0x55
- adv_body.extend_from_slice(&[
- 0x90, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55,
- ]);
- // 10 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 10]);
- // mic - 16x 0x33
- adv_body.extend_from_slice(&[
- 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33,
- ]);
-
- // section - 65 bytes total
- adv_body.push(19 + 18 + 11 + 16);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x00, // scheme (mic)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // trusted identity -- 2 + 16x 0x77
- adv_body.extend_from_slice(&[
- 0x90, 0x02, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
- 0x77, 0x77, 0x77,
- ]);
- // 11 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 11]);
- // mic - 16x 0x66
- adv_body.extend_from_slice(&[
- 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
- 0x66,
- ]);
-
- // section - 66 bytes total
- adv_body.push(19 + 18 + 12 + 16);
- // encryption info -- 2 + 1 + 16x 0x11
- adv_body.extend_from_slice(&[
- 0x91, 0x10, // header
- 0x00, // scheme (mic)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, // salt
- ]);
- // provisioned identity -- 2 + 16x 0xAA
- adv_body.extend_from_slice(&[
- 0x90, 0x04, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- 0xAA, 0xAA, 0xAA,
- ]);
- // 12 bytes of 0xFF ciphertext
- adv_body.extend_from_slice(&[0xFF; 12]);
- // mic - 16x 0x99
- adv_body.extend_from_slice(&[
- 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
- 0x99,
- ]);
-
- let adv_header = V1Header { header_byte: 0x20 };
- let encryption_info = EncryptionInfo {
- bytes: [
- 0x91, 0x10, // header bytes
- 0x00, // scheme (mic)
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11,
- ],
- };
- let expected_sections = [
- MicEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 63,
- adv_header,
- encryption_info: encryption_info.clone(),
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x01],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Private,
- },
- // skip section header + encryption info + identity header -> end of ciphertext
- all_ciphertext: &adv_body[1 + 19 + 2..64 - 16],
- },
- mic: SectionMic::from([0x33; 16]),
- },
- MicEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 64,
- adv_header,
- encryption_info: encryption_info.clone(),
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x02],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Trusted,
- },
- all_ciphertext: &adv_body[64 + 1 + 19 + 2..129 - 16],
- },
- mic: SectionMic::from([0x66; 16]),
- },
- MicEncryptedSection {
- contents: EncryptedSectionContents {
- section_header: 65,
- adv_header,
- encryption_info,
- identity: EncryptedIdentityMetadata {
- header_bytes: [0x90, 0x04],
- offset: 1_u8.into(),
- identity_type: EncryptedIdentityDataElementType::Provisioned,
- },
- all_ciphertext: &adv_body[129 + 1 + 19 + 2..195 - 16],
- },
- mic: SectionMic::from([0x99; 16]),
- },
- ];
- let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
- assert_eq!(parsed_sections.into_vec(), &expected_sections.map(IntermediateSection::from));
-}
-
-#[test]
-fn parse_de_with_1_byte_header() {
- let data = [0x51, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[6..],
- ProtoDataElement {
- header: DeHeader {
- de_type: 1_u8.into(),
- header_bytes: ArrayView::try_from_slice(&[0x51]).unwrap(),
- contents_len: 5_u8.try_into().unwrap()
- },
- contents: &data[1..6]
- }
- )),
- ProtoDataElement::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_with_2_byte_header() {
- let data = [0x85, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[7..],
- ProtoDataElement {
- header: DeHeader {
- de_type: 1_u8.into(),
- header_bytes: ArrayView::try_from_slice(&[0x85, 0x01]).unwrap(),
- contents_len: 5_u8.try_into().unwrap()
- },
- contents: &data[2..7]
- }
- )),
- ProtoDataElement::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_with_3_byte_header() {
- let data = [0x85, 0xC1, 0x41, 0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[8..],
- ProtoDataElement {
- header: DeHeader {
- header_bytes: ArrayView::try_from_slice(&[0x85, 0xC1, 0x41]).unwrap(),
- contents_len: 5_u8.try_into().unwrap(),
- de_type: 0b0000_0000_0000_0000_0010_0000_1100_0001_u32.into(),
- },
- contents: &data[3..8]
- }
- )),
- ProtoDataElement::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_header_1_byte() {
- let data = [0x51, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[1..],
- DeHeader {
- de_type: 1_u8.into(),
- contents_len: 5_u8.try_into().unwrap(),
- header_bytes: ArrayView::try_from_slice(&[0x51]).unwrap(),
- }
- )),
- DeHeader::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_header_2_bytes() {
- let data = [0x83, 0x01, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[2..],
- DeHeader {
- de_type: 1_u8.into(),
- contents_len: 3_u8.try_into().unwrap(),
- header_bytes: ArrayView::try_from_slice(&[0x83, 0x01]).unwrap(),
- }
- )),
- DeHeader::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_header_3_bytes() {
- let data = [0x83, 0xC1, 0x41, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[3..],
- DeHeader {
- de_type: 0b0000_0000_0000_0000_0010_0000_1100_0001_u32.into(),
- contents_len: 3_u8.try_into().unwrap(),
- header_bytes: ArrayView::try_from_slice(&[0x83, 0xC1, 0x41]).unwrap(),
- }
- )),
- DeHeader::parse(&data)
- );
-}
-
-#[test]
-fn parse_de_header_4_bytes() {
- let data = [0x83, 0xC1, 0xC1, 0x41, 0xFF, 0xFF];
- assert_eq!(
- Ok((
- &data[4..],
- DeHeader {
- de_type: 0b0000_0000_0001_0000_0110_0000_1100_0001_u32.into(),
- contents_len: 3_u8.try_into().unwrap(),
- header_bytes: ArrayView::try_from_slice(&[0x83, 0xC1, 0xC1, 0x41]).unwrap(),
- }
- )),
- DeHeader::parse(&data)
- );
-}
-
-#[test]
-fn public_identity_not_first_de_error() {
- let mut adv_body = vec![];
- // section
- adv_body.push(3 + 1);
- // misc other DE
- adv_body.extend_from_slice(&[0x81, 0x70, 0xFF]);
- // public identity after another DE
- adv_body.push(0x03);
-
- assert_eq!(
- nom::Err::Error(error::Error { input: &adv_body[1..], code: error::ErrorKind::Verify }),
- parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap_err()
- );
-}
-
-#[test]
-fn invalid_public_section() {
- let mut rng = StdRng::from_entropy();
- for _ in 0..100 {
- let mut adv_body = vec![];
- // Add section length
- let remove_section_len = rng.gen_bool(0.5);
- // Add public identity
- let add_public_identity = rng.gen_bool(0.5);
- // Add DEs
- let add_des = rng.gen_bool(0.5);
- // Shuffle adv
- let shuffle = rng.gen_bool(0.5);
-
- adv_body.push(0);
- if add_public_identity {
- adv_body[0] += 1;
- adv_body.push(0x03);
- }
- if add_des {
- adv_body[0] += 1;
- adv_body.extend_from_slice(&[0x81]);
- }
- if remove_section_len {
- let _ = adv_body.remove(0);
- }
-
- let ordered_adv = adv_body.clone();
-
- if shuffle {
- adv_body.shuffle(&mut rng);
- }
- // A V1 public section is invalid if
- // * section length is missing
- // * the section is empty
- // * the section identity is missing
- // * the identity does not follow the section length
- // * the section length is 0
- if remove_section_len || !add_public_identity || (ordered_adv != adv_body) {
- let _ = parse_sections(V1Header { header_byte: 0x20 }, &adv_body)
- .expect_err("Expected to fail because of missing section length or identity");
- }
- }
-}
-
-// There can only be one identity DE
-#[test]
-fn public_identity_after_public_identity_error() {
- let mut adv_body = vec![];
- // section
- adv_body.push(1 + 3 + 1);
- // public identity after another DE
- adv_body.push(0x03);
- // misc other DE
- adv_body.extend_from_slice(&[0x81, 0x70, 0xFF]);
- // public identity after another DE
- adv_body.push(0x03);
-
- let sections = parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap();
- assert_eq!(sections.len(), 1);
- assert_eq!(
- DataElementParseError::DuplicateIdentityDataElement,
- sections[0].as_plaintext().unwrap().collect_data_elements().unwrap_err()
- );
-}
-
-#[test]
-fn salt_public_identity_error() {
- let mut adv_body = vec![];
- // section
- adv_body.push(3 + 1 + 3);
- // salt - 1 + 2x 0x22 (invalid: must be first DE)
- adv_body.extend_from_slice(&[0x20, 0x22, 0x22]);
- // public identity
- adv_body.push(0x03);
- // misc other DE
- adv_body.extend_from_slice(&[0x81, 0x70, 0xFF]);
-
- assert_eq!(
- nom::Err::Error(error::Error {
- input: &adv_body[1..],
- // Eof because all_consuming is used to ensure complete section is parsed
- code: error::ErrorKind::Verify
- }),
- parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap_err()
- );
-}
-
-#[test]
-fn salt_mic_public_identity_error() {
- let mut adv_body = vec![];
- // section
- adv_body.push(3 + 18 + 1 + 3);
- // salt - 1 + 2x 0x22 (invalid: must be first DE)
- adv_body.extend_from_slice(&[0x20, 0x22, 0x22]);
- // mic - 2 + 16x 0x33
- adv_body.extend_from_slice(&[
- 0x90, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x33,
- ]);
- // public identity
- adv_body.push(0x03);
- // misc other DE
- adv_body.extend_from_slice(&[0x81, 0x70, 0xFF]);
-
- assert_eq!(
- nom::Err::Error(error::Error {
- input: &adv_body[1..],
- // Eof because all_consuming is used to ensure complete section is parsed
- code: error::ErrorKind::Verify
- }),
- parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap_err()
- );
-}
-
-#[test]
-fn parse_adv_no_identity() {
- let adv_body = vec![0x55, 0x01, 0x02, 0x03, 0x04, 0x05];
- assert_eq!(
- nom::Err::Error(error::Error { input: &adv_body[1..], code: error::ErrorKind::Eof }),
- parse_sections(V1Header { header_byte: 0x20 }, &adv_body).unwrap_err()
- );
-}
-
-#[test]
-fn parse_empty_section() {
- // empty section - should return an EOF error
- let input = [];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read section contents
- input: input.as_slice(),
- code: error::ErrorKind::Eof
- }),
- IntermediateSection::parser_encrypted_with_header(V1Header { header_byte: 0x20 })(&input)
- .unwrap_err()
- );
-}
-
-#[test]
-fn parse_de_header_non_canonical_multi_byte() {
- // length 1, type 1
- // first byte of type doesn't have any bits in it so it contributes nothing
- let input = [0b1000_0001, 0b1000_0000, 0b0000_0001];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read first type byte
- input: &input.as_slice()[1..],
- code: error::ErrorKind::Verify
- }),
- DeHeader::parse(&input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_section_length_zero() {
- // Section length of 0 - should return a verification error
- let input = [0x00];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read section contents
- input: input.as_slice(),
- code: error::ErrorKind::Verify
- }),
- IntermediateSection::parser_encrypted_with_header(V1Header { header_byte: 0x20 })(&input)
- .unwrap_err()
- );
-}
-
-#[test]
-fn parse_section_length_overrun() {
- // section of length 0xF0 - legal but way longer than 3
- let input = [0xF0, 0x01, 0x02, 0x03];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read section contents
- input: &input.as_slice()[1..],
- code: error::ErrorKind::Eof
- }),
- IntermediateSection::parser_encrypted_with_header(V1Header { header_byte: 0x20 })(&input)
- .unwrap_err()
- );
-}
-
-#[test]
-fn parse_de_single_byte_header_length_overrun() {
- // length 7, type 0x03
- let input = [0b0111_0011, 0x01, 0x02];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read DE contents
- input: &input.as_slice()[1..],
- code: error::ErrorKind::Eof
- }),
- ProtoDataElement::parse(&input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_de_multi_byte_header_length_overrun() {
- // length 7, type 0x0F
- let input = [0b1000_0111, 0x0F, 0x01, 0x02];
- assert_eq!(
- nom::Err::Error(error::Error {
- // attempted to read DE contents
- input: &input.as_slice()[2..],
- code: error::ErrorKind::Eof
- }),
- ProtoDataElement::parse(&input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_adv_signature_encrypted_plaintext_mix() {
- // 2 sections
- let mut adv_body = vec![];
-
- // section 1 - plaintext - 10 bytes
- adv_body.push(10);
- // public identity
- adv_body.push(0x03);
- // de 1 byte header, type 5, len 5
- adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
- // de 2 byte header, type 6, len 1
- adv_body.extend_from_slice(&[0x81, 0x06, 0x01]);
-
- // section 2 - plaintext - 10 bytes
- adv_body.push(10);
- // public identity
- adv_body.push(0x03);
- // de 1 byte header, type 5, len 5
- adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
- // de 2 byte header, type 6, len 1
- adv_body.extend_from_slice(&[0x81, 0x06, 0x01]);
-
- let adv_header = V1Header { header_byte: 0x20 };
-
- assert_eq!(
- nom::Err::Error(error::Error { input: &adv_body[11..], code: error::ErrorKind::Eof }),
- parse_sections(adv_header, &adv_body).unwrap_err()
- );
-}
-
-// for convenient .into() in expected test data
-
-impl<'a> From<SignatureEncryptedSection<'a>> for IntermediateSection<'a> {
- fn from(s: SignatureEncryptedSection<'a>) -> Self {
- IntermediateSection::Ciphertext(CiphertextSection::SignatureEncryptedIdentity(s))
- }
-}
-
-impl<'a> From<MicEncryptedSection<'a>> for IntermediateSection<'a> {
- fn from(s: MicEncryptedSection<'a>) -> Self {
- IntermediateSection::Ciphertext(CiphertextSection::MicEncryptedIdentity(s))
- }
-}
-
-impl<'a> From<PlaintextSection<'a>> for IntermediateSection<'a> {
- fn from(s: PlaintextSection<'a>) -> Self {
- IntermediateSection::Plaintext(s)
- }
-}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/section/header/mod.rs b/nearby/presence/np_adv/src/extended/deserialize/section/header/mod.rs
new file mode 100644
index 0000000..cb6a955
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/section/header/mod.rs
@@ -0,0 +1,141 @@
+// 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.
+
+//! High-level, early-stage parsed structures for a section: the header, then everything else.
+
+use crate::extended::{
+ deserialize, salt::ShortV1Salt, V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN, V1_ENCODING_UNENCRYPTED,
+ V1_IDENTITY_TOKEN_LEN,
+};
+use crate::helpers::parse_byte_array;
+use nom::{combinator, error, number, sequence};
+use np_hkdf::v1_salt::{ExtendedV1Salt, EXTENDED_SALT_LEN};
+
+#[cfg(test)]
+mod tests;
+
+#[derive(PartialEq, Eq, Debug)]
+pub(crate) enum SectionHeader {
+ Unencrypted,
+ Encrypted(EncryptedSectionHeader),
+}
+
+impl SectionHeader {
+ /// Returns the parsed header and the remaining length of the section contents
+ ///
+ /// This structure makes it easy to get a slice of the entire header with
+ /// [combinator::consumed] for later inclusion in signatures etc, but also
+ /// to [nom::bytes::complete::take] the rest of the section with a minimum of
+ /// error-prone length calculations.
+ pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], (&[u8], Self, u8)> {
+ // Consume first 1-2 bytes of format
+ // 0bERRRSSSS first header byte
+ let (input, (format_bytes, (first_header_byte, maybe_second_byte))) =
+ combinator::consumed(nom::branch::alt((
+ // Extended bit not set, verify all reserved bits are 0
+ combinator::map(
+ combinator::verify(number::complete::u8, |b| {
+ !deserialize::hi_bit_set(*b) && (*b & 0x70) == 0
+ }),
+ |b| (b, None),
+ ),
+ // Extended bit is set, take another byte and verify all reserved bits are 0
+ combinator::map(
+ nom::sequence::pair(
+ combinator::verify(number::complete::u8, |b| {
+ deserialize::hi_bit_set(*b) && (*b & 0x70) == 0
+ }),
+ combinator::verify(number::complete::u8, |second_byte| *second_byte == 0u8),
+ ),
+ |(b1, b2)| (b1, Some(b2)),
+ ),
+ )))(input)?;
+
+ let encoding = first_header_byte & 0x0F;
+
+ let (input, section_header) = match (encoding, maybe_second_byte) {
+ (V1_ENCODING_UNENCRYPTED, None) => Ok((input, (SectionHeader::Unencrypted))),
+ (V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN, None) => combinator::map(
+ sequence::tuple((ShortV1Salt::parse, CiphertextExtendedIdentityToken::parse)),
+ |(salt, token)| {
+ SectionHeader::Encrypted(EncryptedSectionHeader::MicShortSalt { salt, token })
+ },
+ )(input),
+ (V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN, None) => combinator::map(
+ sequence::tuple((parse_v1_extended_salt, CiphertextExtendedIdentityToken::parse)),
+ |(salt, token)| {
+ SectionHeader::Encrypted(EncryptedSectionHeader::MicExtendedSalt {
+ salt,
+ token,
+ })
+ },
+ )(input),
+ (V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN, None) => {
+ combinator::map(
+ sequence::tuple((
+ parse_v1_extended_salt,
+ CiphertextExtendedIdentityToken::parse,
+ )),
+ |(salt, token)| {
+ SectionHeader::Encrypted(EncryptedSectionHeader::SigExtendedSalt {
+ salt,
+ token,
+ })
+ },
+ )(input)
+ }
+ _ => Err(nom::Err::Error(error::Error::new(input, error::ErrorKind::Alt))),
+ }?;
+
+ //finally parse the section payload length, this is the same regardless of encoding scheme
+ let (input, section_len) = combinator::verify(number::complete::u8, |b| {
+ // length cannot be 0 for an unencrypted section as this is meaningless
+ !(encoding == V1_ENCODING_UNENCRYPTED && *b == 0u8)
+ })(input)?;
+
+ Ok((input, (format_bytes, section_header, section_len)))
+ }
+}
+
+fn parse_v1_extended_salt(input: &[u8]) -> nom::IResult<&[u8], ExtendedV1Salt> {
+ combinator::map(parse_byte_array::<{ EXTENDED_SALT_LEN }>, ExtendedV1Salt::from)(input)
+}
+
+#[allow(clippy::enum_variant_names)]
+#[derive(PartialEq, Eq, Debug)]
+pub(crate) enum EncryptedSectionHeader {
+ MicShortSalt { salt: ShortV1Salt, token: CiphertextExtendedIdentityToken },
+ MicExtendedSalt { salt: ExtendedV1Salt, token: CiphertextExtendedIdentityToken },
+ SigExtendedSalt { salt: ExtendedV1Salt, token: CiphertextExtendedIdentityToken },
+}
+
+/// 16-byte identity token, straight out of the section.
+///
+/// If identity resolution succeeds, decrypted to an [ExtendedIdentityToken](crate::extended::V1IdentityToken).
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) struct CiphertextExtendedIdentityToken(pub(crate) [u8; V1_IDENTITY_TOKEN_LEN]);
+
+impl CiphertextExtendedIdentityToken {
+ pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Self> {
+ combinator::map(parse_byte_array::<V1_IDENTITY_TOKEN_LEN>, Self)(input)
+ }
+}
+
+impl From<[u8; V1_IDENTITY_TOKEN_LEN]> for CiphertextExtendedIdentityToken {
+ fn from(value: [u8; V1_IDENTITY_TOKEN_LEN]) -> Self {
+ Self(value)
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/section/header/tests.rs b/nearby/presence/np_adv/src/extended/deserialize/section/header/tests.rs
new file mode 100644
index 0000000..92cd5da
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/section/header/tests.rs
@@ -0,0 +1,194 @@
+// 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.
+
+mod happy_path {
+ use super::super::*;
+ use alloc::vec;
+
+ #[test]
+ fn parse_extended_bit_not_set() {
+ assert_eq!(
+ SectionHeader::parse(&[0b0000_0000, 3]).expect("Parsing should succeed"),
+ ([].as_slice(), (&[0u8][..], SectionHeader::Unencrypted, 3u8))
+ );
+ }
+
+ #[test]
+ fn parse_with_extended_bit_set() {
+ let _ = SectionHeader::parse(&[0b1000_0000, 0b0000_0000, 4])
+ .expect_err("Extended bits should not be parsed at this time");
+ }
+
+ #[test]
+ fn parse_section_header_mic_with_short_salt() {
+ let mut section_header = vec![];
+ section_header.push(0b0000_0001u8); //format
+ section_header.extend_from_slice(&[0xFF; 2]); // short salt
+ section_header.extend_from_slice(&[0xCC; 16]); // identity token
+ section_header.push(100); // payload length
+
+ assert_eq!(
+ SectionHeader::parse(section_header.as_slice()).expect("Parsing should succeed"),
+ (
+ [].as_slice(),
+ (
+ &[0b0000_0001u8][..],
+ SectionHeader::Encrypted(EncryptedSectionHeader::MicShortSalt {
+ salt: [0xFF; 2].into(),
+ token: [0xCC; 16].into(),
+ }),
+ 100
+ )
+ )
+ );
+ }
+
+ #[test]
+ fn parse_section_header_multi_byte_mic_with_short_salt() {
+ let mut section_header = vec![];
+ section_header.extend_from_slice(&[0b1000_0001u8, 0b0000_0000]); //format
+ section_header.extend_from_slice(&[0xFF; 2]); // short salt
+ section_header.extend_from_slice(&[0xCC; 16]); // identity token
+ section_header.push(100); // payload length
+ let _ = SectionHeader::parse(section_header.as_slice())
+ .expect_err("Extended bit parsing should fail at this time");
+ }
+
+ #[test]
+ fn parse_section_header_mic_with_extended_salt() {
+ let mut section_header = vec![];
+ section_header.push(0b0000_0010u8); //format
+ section_header.extend_from_slice(&[0xFF; 16]); // short salt
+ section_header.extend_from_slice(&[0xCC; 16]); // identity token
+ section_header.push(100); // payload length
+
+ assert_eq!(
+ SectionHeader::parse(section_header.as_slice()).expect("Parsing should succeed"),
+ (
+ [].as_slice(),
+ (
+ &[0b0000_0010u8][..],
+ SectionHeader::Encrypted(EncryptedSectionHeader::MicExtendedSalt {
+ salt: [0xFF; 16].into(),
+ token: [0xCC; 16].into(),
+ }),
+ 100
+ )
+ )
+ );
+ }
+
+ #[test]
+ fn parse_section_header_sig_with_extended_salt() {
+ let mut section_header = vec![];
+ section_header.push(0b0000_0011u8); //format
+ section_header.extend_from_slice(&[0xFF; 16]); // short salt
+ section_header.extend_from_slice(&[0xCC; 16]); // identity token
+ section_header.push(100); // payload length
+
+ assert_eq!(
+ SectionHeader::parse(section_header.as_slice()).expect("Parsing should succeed"),
+ (
+ [].as_slice(),
+ (
+ &[0b0000_0011u8][..],
+ SectionHeader::Encrypted(EncryptedSectionHeader::SigExtendedSalt {
+ salt: [0xFF; 16].into(),
+ token: [0xCC; 16].into(),
+ }),
+ 100
+ )
+ )
+ );
+ }
+}
+
+mod error_condition {
+ use super::super::*;
+ use alloc::vec;
+
+ #[test]
+ fn parse_single_byte_invalid_reserve() {
+ let _ = SectionHeader::parse(&[0b0001_0000, 3])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b0011_0000, 3])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b0111_0000, 3])
+ .expect_err("Invalid reserve bits should fail to parse");
+ }
+
+ #[test]
+ fn parse_multi_byte_invalid_reserve_bits() {
+ let _ = SectionHeader::parse(&[0b1000_0000, 0b1000_0000, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1000_0000, 0b1111_1111, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1000_0000, 0b0000_0001, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1000_0000, 0b0001_0000, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1001_0000, 0b0000_0000, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1100_0000, 0b0000_0000, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ let _ = SectionHeader::parse(&[0b1100_0000, 0b0000_0001, 4])
+ .expect_err("Invalid reserve bits should fail to parse");
+ }
+
+ #[test]
+ fn parse_section_header_unencrypted_encoding_zero_length_payload() {
+ let _ = SectionHeader::parse(&[0b0000_0000, 0])
+ .expect_err("0 is an invalid section length for unencrypted sections");
+ }
+
+ #[test]
+ fn parse_section_header_mic_with_short_salt_too_short() {
+ let _ = SectionHeader::parse(&[0b0000_0001])
+ .expect_err("Not enough bytes present to parse a mic with short salt");
+ }
+
+ #[test]
+ fn parse_section_header_mic_with_short_salt_missing_length() {
+ let mut section_header = vec![];
+ section_header.push(0b0000_0001u8); //format
+ section_header.extend_from_slice(&[0xFF; 2]); // short salt
+ section_header.extend_from_slice(&[0xCC; 16]); // identity token
+
+ let _ = SectionHeader::parse(section_header.as_slice())
+ .expect_err("Section payload length byte is missing");
+ }
+}
+
+mod coverage_gaming {
+ use crate::extended::deserialize::section::header::{
+ CiphertextExtendedIdentityToken, EncryptedSectionHeader,
+ };
+ use alloc::format;
+
+ #[test]
+ fn ct_identity_token_clone() {
+ let token = CiphertextExtendedIdentityToken([0; 16]);
+ #[allow(clippy::clone_on_copy)]
+ let _ = token.clone();
+ }
+
+ #[test]
+ fn encrypted_section_header_debug() {
+ let header = EncryptedSectionHeader::MicShortSalt {
+ salt: [0; 2].into(),
+ token: CiphertextExtendedIdentityToken([0; 16]),
+ };
+ let _ = format!("{:?}", header);
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/mod.rs b/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/mod.rs
new file mode 100644
index 0000000..f998299
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/mod.rs
@@ -0,0 +1,289 @@
+// 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.
+
+//! Covers the first half of section parsing before decryption, if relevant, is
+//! attempted.
+
+use crate::{
+ array_vec::ArrayVecOption,
+ extended::{
+ deserialize::{
+ encrypted_section::{
+ EncryptedSectionContents, MicEncryptedSection, SectionIdentityResolutionContents,
+ SignatureEncryptedSection,
+ },
+ section::header::{
+ CiphertextExtendedIdentityToken, EncryptedSectionHeader, SectionHeader,
+ },
+ DataElementParsingIterator, Section, SectionMic,
+ },
+ salt::MultiSalt,
+ NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT, NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT,
+ },
+ header::V1AdvHeader,
+};
+use crypto_provider::CryptoProvider;
+use nom::{branch, bytes, combinator, error, multi};
+
+use crate::extended::deserialize::data_element::DataElementParseError;
+#[cfg(feature = "devtools")]
+use crate::{
+ credential::v1::V1DiscoveryCryptoMaterial, deserialization_arena::DeserializationArenaAllocator,
+};
+#[cfg(feature = "devtools")]
+use crate::{deserialization_arena::ArenaOutOfSpace, extended::NP_ADV_MAX_SECTION_LEN};
+#[cfg(feature = "devtools")]
+use array_view::ArrayView;
+
+#[cfg(test)]
+pub(crate) mod tests;
+
+/// Parse into [IntermediateSection]s, exposing the underlying parsing errors.
+/// Consumes all of `adv_body`.
+pub(crate) fn parse_sections(
+ adv_header: V1AdvHeader,
+ adv_body: &[u8],
+) -> Result<
+ ArrayVecOption<IntermediateSection, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT>,
+ nom::Err<error::Error<&[u8]>>,
+> {
+ combinator::all_consuming(branch::alt((
+ // Public advertisement
+ multi::fold_many_m_n(
+ 1,
+ NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT,
+ IntermediateSection::parser_unencrypted_section,
+ ArrayVecOption::default,
+ |mut acc, item| {
+ acc.push(item);
+ acc
+ },
+ ),
+ // Encrypted advertisement
+ multi::fold_many_m_n(
+ 1,
+ NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT,
+ IntermediateSection::parser_encrypted_with_header(adv_header),
+ ArrayVecOption::default,
+ |mut acc, item| {
+ acc.push(item);
+ acc
+ },
+ ),
+ )))(adv_body)
+ .map(|(_rem, sections)| sections)
+}
+
+/// A partially processed section that hasn't been decrypted (if applicable) yet.
+#[derive(PartialEq, Eq, Debug)]
+pub(crate) enum IntermediateSection<'a> {
+ /// A section that was not encrypted, e.g. a public identity or no-identity section.
+ Plaintext(PlaintextSection<'a>),
+ /// A section whose contents were encrypted, e.g. a private identity section.
+ Ciphertext(CiphertextSection<'a>),
+}
+
+impl<'a> IntermediateSection<'a> {
+ fn parser_unencrypted_section(
+ np_adv_body: &'a [u8],
+ ) -> nom::IResult<&'a [u8], IntermediateSection<'a>> {
+ combinator::map_opt(SectionContents::parse, |sc| match sc.header {
+ SectionHeader::Unencrypted => {
+ Some(IntermediateSection::Plaintext(PlaintextSection::new(sc.contents)))
+ }
+ SectionHeader::Encrypted(_) => None,
+ })(np_adv_body)
+ }
+
+ pub(crate) fn parser_encrypted_with_header(
+ adv_header: V1AdvHeader,
+ ) -> impl Fn(&'a [u8]) -> nom::IResult<&[u8], IntermediateSection> {
+ move |adv_body| {
+ fn split_at_mic(contents: &[u8]) -> Option<(&[u8], SectionMic)> {
+ contents.len().checked_sub(SectionMic::CONTENTS_LEN).map(|len_before_mic| {
+ let (before_mic, mic) = contents.split_at(len_before_mic);
+ let mic = SectionMic::try_from(mic).expect("MIC length checked above");
+
+ (before_mic, mic)
+ })
+ }
+
+ fn build_mic_section<'a>(
+ adv_header: V1AdvHeader,
+ format_bytes: &'a [u8],
+ salt: MultiSalt,
+ token: CiphertextExtendedIdentityToken,
+ contents_len: u8,
+ contents: &'a [u8],
+ ) -> Option<IntermediateSection<'a>> {
+ split_at_mic(contents).map(|(before_mic, mic)| {
+ IntermediateSection::Ciphertext(CiphertextSection::MicEncrypted(
+ MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ format_bytes,
+ salt,
+ token,
+ contents_len,
+ before_mic,
+ ),
+ mic,
+ },
+ ))
+ })
+ }
+
+ combinator::map_opt(
+ combinator::map_opt(SectionContents::parse, |sc| match sc.header {
+ SectionHeader::Unencrypted => None,
+ SectionHeader::Encrypted(e) => {
+ Some((sc.format_bytes, sc.contents, sc.contents_len, e))
+ }
+ }),
+ move |(format_bytes, contents, contents_len, header)| match header {
+ EncryptedSectionHeader::MicShortSalt { salt, token } => build_mic_section(
+ adv_header,
+ format_bytes,
+ salt.into(),
+ token,
+ contents_len,
+ contents,
+ ),
+ EncryptedSectionHeader::MicExtendedSalt { salt, token } => build_mic_section(
+ adv_header,
+ format_bytes,
+ salt.into(),
+ token,
+ contents_len,
+ contents,
+ ),
+ EncryptedSectionHeader::SigExtendedSalt { salt, token } => {
+ Some(IntermediateSection::Ciphertext(
+ CiphertextSection::SignatureEncrypted(SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ format_bytes,
+ salt,
+ token,
+ contents_len,
+ contents,
+ ),
+ }),
+ ))
+ }
+ },
+ )(adv_body)
+ }
+ }
+}
+
+/// Components of a section after header decode, but before decryption or DE parsing.
+///
+/// This is just the first stage of parsing sections, followed by [IntermediateSection].
+#[derive(PartialEq, Eq, Debug)]
+pub(crate) struct SectionContents<'adv> {
+ /// 1-2 bytes of the format saved for later use in verification
+ pub(crate) format_bytes: &'adv [u8],
+ /// Section header contents which includes salt + identity token
+ pub(crate) header: SectionHeader,
+ /// Contents of the section after the header.
+ /// No validation is performed on the contents.
+ pub(crate) contents: &'adv [u8],
+ /// The length of the contents stored as an u8.
+ pub(crate) contents_len: u8,
+}
+
+impl<'adv> SectionContents<'adv> {
+ pub(crate) fn parse(input: &'adv [u8]) -> nom::IResult<&'adv [u8], Self> {
+ let (input, (format_bytes, header, contents_len)) = SectionHeader::parse(input)?;
+ let (input, contents) = bytes::complete::take(contents_len)(input)?;
+
+ Ok((input, Self { format_bytes, header, contents, contents_len }))
+ }
+}
+
+/// A plaintext section deserialized from a V1 advertisement.
+#[derive(PartialEq, Eq, Debug)]
+pub struct PlaintextSection<'adv> {
+ contents: &'adv [u8],
+}
+
+impl<'adv> PlaintextSection<'adv> {
+ pub(crate) fn new(contents: &'adv [u8]) -> Self {
+ Self { contents }
+ }
+}
+
+impl<'adv> Section<'adv, DataElementParseError> for PlaintextSection<'adv> {
+ type Iterator = DataElementParsingIterator<'adv>;
+
+ fn iter_data_elements(&self) -> Self::Iterator {
+ DataElementParsingIterator::new(self.contents)
+ }
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub(crate) enum CiphertextSection<'a> {
+ SignatureEncrypted(SignatureEncryptedSection<'a>),
+ MicEncrypted(MicEncryptedSection<'a>),
+}
+
+impl<'a> CiphertextSection<'a> {
+ /// Try decrypting into some raw bytes given some raw unsigned crypto-material.
+ #[cfg(feature = "devtools")]
+ pub(crate) fn try_resolve_identity_and_decrypt<
+ C: V1DiscoveryCryptoMaterial,
+ P: CryptoProvider,
+ >(
+ &self,
+ allocator: &mut DeserializationArenaAllocator<'a>,
+ crypto_material: &C,
+ ) -> Option<Result<ArrayView<u8, { NP_ADV_MAX_SECTION_LEN }>, ArenaOutOfSpace>> {
+ match self {
+ CiphertextSection::SignatureEncrypted(x) => {
+ let identity_resolution_material =
+ crypto_material.signed_identity_resolution_material::<P>();
+ x.try_resolve_identity_and_decrypt::<P>(allocator, &identity_resolution_material)
+ }
+ CiphertextSection::MicEncrypted(x) => match x.contents.salt {
+ MultiSalt::Short(_) => x.try_resolve_short_salt_identity_and_decrypt::<P>(
+ allocator,
+ &crypto_material.mic_short_salt_identity_resolution_material::<P>(),
+ ),
+ MultiSalt::Extended(_) => x.try_resolve_extended_salt_identity_and_decrypt::<P>(
+ allocator,
+ &crypto_material.mic_extended_salt_identity_resolution_material::<P>(),
+ ),
+ },
+ }
+ }
+
+ /// Return the data needed to resolve identities.
+ ///
+ /// In the typical case of trying many identities across a few sections,
+ /// these should be calculated once for all relevant sections, then re-used
+ /// for all identity match attempts.
+ pub(crate) fn identity_resolution_contents<C: CryptoProvider>(
+ &self,
+ ) -> SectionIdentityResolutionContents {
+ match self {
+ CiphertextSection::SignatureEncrypted(x) => {
+ x.contents.compute_identity_resolution_contents::<C>()
+ }
+ CiphertextSection::MicEncrypted(x) => {
+ x.contents.compute_identity_resolution_contents::<C>()
+ }
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/tests.rs b/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/tests.rs
new file mode 100644
index 0000000..84ce763
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/section/intermediate/tests.rs
@@ -0,0 +1,725 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+//! Tests for intermediate sections representation and logic - this is the initial stage of parsing
+//! before any ciphertext is actually decrypted.
+
+extern crate std;
+use std::{prelude::rust_2021::*, vec};
+
+use super::*;
+use crate::{
+ extended::{
+ deserialize::{
+ data_element::DataElement,
+ encrypted_section::{
+ EncryptedSectionContents, MicEncryptedSection, SignatureEncryptedSection,
+ },
+ SectionMic,
+ },
+ salt::{ShortV1Salt, SHORT_SALT_LEN},
+ serialize::{AdvBuilder, AdvertisementType},
+ NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT, V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN, V1_ENCODING_UNENCRYPTED,
+ V1_IDENTITY_TOKEN_LEN,
+ },
+ header::V1AdvHeader,
+ NpVersionHeader,
+};
+use crypto_provider_default::CryptoProviderImpl;
+use nom::error;
+use np_hkdf::v1_salt::EXTENDED_SALT_LEN;
+use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng as _};
+
+/// Section header length after the length byte for ext salt + token
+const EXT_SALT_SECTION_HEADER_LEN: usize = 1 + EXTENDED_SALT_LEN + V1_IDENTITY_TOKEN_LEN + 1;
+
+/// Section header length after the length byte for ext salt + token
+const SHORT_SALT_SECTION_HEADER_LEN: usize = 1 + SHORT_SALT_LEN + V1_IDENTITY_TOKEN_LEN + 1;
+
+mod happy_path {
+ use super::*;
+ use crate::{
+ extended::{data_elements::TxPowerDataElement, serialize::UnencryptedSectionEncoder},
+ shared_data::TxPower,
+ };
+ use np_hkdf::v1_salt::ExtendedV1Salt;
+
+ #[test]
+ fn parse_adv_ext_public_identity() {
+ let mut adv_body = vec![];
+ // public identity
+ adv_body.push(V1_ENCODING_UNENCRYPTED);
+ // section len
+ adv_body.push(6 + 3);
+ // de 1 byte header, type 5, len 5
+ adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 22, len 1
+ adv_body.extend_from_slice(&[0x81, 0x16, 0x01]);
+
+ let parsed_sections = parse_sections(V1AdvHeader::new(0x20), &adv_body).unwrap().into_vec();
+ assert_eq!(
+ vec![IntermediateSection::from(PlaintextSection::new(&adv_body[2..]))],
+ parsed_sections,
+ );
+ let expected_des = [
+ // 1 byte header, len 5
+ DataElement::new(0_u8.into(), 5_u8.into(), &[0x01, 0x02, 0x03, 0x04, 0x05]),
+ // 2 byte header, len 1
+ DataElement::new(1_u8.into(), 22_u8.into(), &[0x01]),
+ ];
+
+ assert_eq!(
+ &expected_des[..],
+ &parsed_sections[0].as_plaintext().unwrap().collect_data_elements().unwrap()
+ );
+ }
+
+ #[test]
+ fn do_deserialize_max_number_of_public_sections() {
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ for _ in 0..NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT {
+ let mut section_builder =
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
+ section_builder
+ .add_de(|_salt| TxPowerDataElement::from(TxPower::try_from(7).unwrap()))
+ .unwrap();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+ }
+
+ let adv = adv_builder.into_advertisement();
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+
+ let v1_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+ let sections = parse_sections(v1_header, remaining).unwrap();
+ assert_eq!(NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT, sections.len());
+ }
+
+ #[test]
+ fn max_number_encrypted_sections_mic() {
+ let mut adv_body = vec![];
+ for _ in 0..NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT {
+ let _ = add_mic_short_salt_section_to_adv(&mut adv_body);
+ }
+ let adv_header = V1AdvHeader::new(0x20);
+ assert!(parse_sections(adv_header, &adv_body).is_ok());
+ }
+
+ #[test]
+ fn max_number_encrypted_sections_sig() {
+ let mut adv_body = vec![];
+ for _ in 0..NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT {
+ let _ = add_sig_encrpyted_section(&mut adv_body, 5, &[0x55; EXTENDED_SALT_LEN]);
+ }
+ let adv_header = V1AdvHeader::new(0x20);
+ assert!(parse_sections(adv_header, &adv_body).is_ok());
+ }
+
+ #[test]
+ fn both_mic_and_sig_sections() {
+ let mut adv_body = vec![];
+ let short_salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ let token_bytes = [0x55; V1_IDENTITY_TOKEN_LEN];
+ let extended_salt = ExtendedV1Salt::from([0x55; EXTENDED_SALT_LEN]);
+ let total_section_1_len = add_mic_short_salt_section_to_adv(&mut adv_body);
+ let _ = add_sig_encrpyted_section(&mut adv_body, 5, extended_salt.bytes());
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let section1 = &adv_body[0..total_section_1_len];
+ let section2 = &adv_body[total_section_1_len..];
+ let expected_sections = [
+ IntermediateSection::from(MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section1[..1],
+ short_salt.into(),
+ token_bytes.into(),
+ (10 + SectionMic::CONTENTS_LEN).try_into().unwrap(),
+ &[0xFF; 10],
+ ),
+ mic: SectionMic::from([0x33; SectionMic::CONTENTS_LEN]),
+ }),
+ IntermediateSection::from(SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section2[..1],
+ extended_salt,
+ [0x33; V1_IDENTITY_TOKEN_LEN].into(),
+ 5,
+ &[0xFF; 5],
+ ),
+ }),
+ ];
+ let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
+ assert_eq!(parsed_sections.into_vec(), expected_sections);
+ }
+
+ #[test]
+ fn parse_adv_sig_encrypted_sections() {
+ // 3 sections
+ let mut adv_body = vec![];
+ let salt_bytes = [0x11; EXTENDED_SALT_LEN];
+
+ let section_1_len = add_sig_encrpyted_section(&mut adv_body, 10, &salt_bytes);
+ let section_2_len = add_sig_encrpyted_section(&mut adv_body, 11, &salt_bytes);
+ let _ = add_sig_encrpyted_section(&mut adv_body, 12, &salt_bytes);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let section1 = &adv_body[..section_1_len];
+ let section2 = &adv_body[section_1_len..][..section_2_len];
+ let section3 = &adv_body[(section_1_len + section_2_len)..];
+ let expected_sections = [
+ SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section1[..1],
+ salt_bytes.into(),
+ [0x33; V1_IDENTITY_TOKEN_LEN].into(),
+ 10,
+ &[0xFF; 10],
+ ),
+ },
+ SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section2[..1],
+ salt_bytes.into(),
+ [0x33; V1_IDENTITY_TOKEN_LEN].into(),
+ 11,
+ &[0xFF; 11],
+ ),
+ },
+ SignatureEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section3[..1],
+ salt_bytes.into(),
+ [0x33; V1_IDENTITY_TOKEN_LEN].into(),
+ 12,
+ &[0xFF; 12],
+ ),
+ },
+ ];
+ let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
+ assert_eq!(parsed_sections.into_vec(), expected_sections.map(IntermediateSection::from));
+ }
+
+ #[test]
+ fn parse_adv_ext_salt_mic_sections() {
+ // 3 sections
+ let mut adv_body = vec![];
+ // section
+ adv_body.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ let salt = ExtendedV1Salt::from([0x11; EXTENDED_SALT_LEN]);
+ adv_body.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_1 = [0x55; V1_IDENTITY_TOKEN_LEN];
+ adv_body.extend_from_slice(&token_bytes_1);
+ let section_1_len = EXT_SALT_SECTION_HEADER_LEN as u8 + 10 + SectionMic::CONTENTS_LEN as u8;
+ adv_body.push(10 + SectionMic::CONTENTS_LEN as u8);
+ // 10 bytes of 0xFF ciphertext
+ adv_body.extend_from_slice(&[0xFF; 10]);
+ // mic - 16x 0x33
+ adv_body.extend_from_slice(&[0x33; SectionMic::CONTENTS_LEN]);
+
+ // section
+ adv_body.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ adv_body.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_2 = [0x77; V1_IDENTITY_TOKEN_LEN];
+ adv_body.extend_from_slice(&token_bytes_2);
+ let section_2_len = EXT_SALT_SECTION_HEADER_LEN as u8 + 11 + SectionMic::CONTENTS_LEN as u8;
+ adv_body.push(11 + SectionMic::CONTENTS_LEN as u8);
+ // 11 bytes of 0xFF ciphertext
+ adv_body.extend_from_slice(&[0xFF; 11]);
+ // mic - 16x 0x66
+ adv_body.extend_from_slice(&[0x66; SectionMic::CONTENTS_LEN]);
+
+ // section
+ adv_body.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ adv_body.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_3 = [0xAA; V1_IDENTITY_TOKEN_LEN];
+ adv_body.extend_from_slice(&token_bytes_3);
+ let _ = EXT_SALT_SECTION_HEADER_LEN as u8 + 12 + SectionMic::CONTENTS_LEN as u8;
+ adv_body.push(12 + SectionMic::CONTENTS_LEN as u8);
+ // 12 bytes of 0xFF ciphertext
+ adv_body.extend_from_slice(&[0xFF; 12]);
+ // mic - 16x 0x99
+ adv_body.extend_from_slice(&[0x99; SectionMic::CONTENTS_LEN]);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let section1 = &adv_body[..section_1_len as usize];
+ let section2 = &adv_body[section_1_len as usize..][..section_2_len as usize];
+ let section3 = &adv_body[section_1_len as usize + section_2_len as usize..];
+ let expected_sections = [
+ MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section1[..1],
+ salt.into(),
+ token_bytes_1.into(),
+ (10 + SectionMic::CONTENTS_LEN).try_into().unwrap(),
+ &[0xFF; 10],
+ ),
+ mic: SectionMic::from([0x33; SectionMic::CONTENTS_LEN]),
+ },
+ MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section2[..1],
+ salt.into(),
+ token_bytes_2.into(),
+ (11 + SectionMic::CONTENTS_LEN).try_into().unwrap(),
+ &[0xFF; 11],
+ ),
+ mic: SectionMic::from([0x66; SectionMic::CONTENTS_LEN]),
+ },
+ MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section3[..1],
+ salt.into(),
+ token_bytes_3.into(),
+ (12 + SectionMic::CONTENTS_LEN).try_into().unwrap(),
+ &[0xFF; 12],
+ ),
+ mic: SectionMic::from([0x99; SectionMic::CONTENTS_LEN]),
+ },
+ ];
+ let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
+ assert_eq!(parsed_sections.into_vec(), &expected_sections.map(IntermediateSection::from));
+ }
+
+ #[test]
+ fn parse_adv_short_salt_mic() {
+ // 3 sections
+ let short_salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ let token_bytes = [0x55; V1_IDENTITY_TOKEN_LEN];
+ let mut adv_body = vec![];
+ let section_1_len = add_mic_short_salt_section_to_adv(&mut adv_body);
+ let _ = add_mic_short_salt_section_to_adv(&mut adv_body);
+ let _ = add_mic_short_salt_section_to_adv(&mut adv_body);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let section1 = &adv_body[..(1 + section_1_len)];
+ let mut expected_sections = [None, None, None];
+ for section in &mut expected_sections {
+ *section = Some(MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ adv_header,
+ &section1[..1],
+ short_salt.into(),
+ token_bytes.into(),
+ (10 + SectionMic::CONTENTS_LEN).try_into().unwrap(),
+ &[0xFF; 10],
+ ),
+ mic: SectionMic::from([0x33; SectionMic::CONTENTS_LEN]),
+ })
+ }
+ let expected: Vec<IntermediateSection> =
+ expected_sections.into_iter().map(|x| IntermediateSection::from(x.unwrap())).collect();
+ let parsed_sections = parse_sections(adv_header, &adv_body).unwrap();
+ assert_eq!(parsed_sections.into_vec(), expected);
+ }
+}
+
+mod error_condition {
+ use super::*;
+ #[test]
+ fn parse_adv_too_many_unencrypted() {
+ // 2 sections
+ let mut adv_body = vec![];
+
+ // section 1 - plaintext - 9 bytes
+ adv_body.push(V1_ENCODING_UNENCRYPTED);
+ adv_body.push(6 + 3); // section len
+ // de 1 byte header, type 5, len 5
+ adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 6, len 1
+ adv_body.extend_from_slice(&[0x81, 0x06, 0x01]);
+
+ // section 2 - plaintext - 10 bytes
+ adv_body.push(V1_ENCODING_UNENCRYPTED);
+ adv_body.push(6 + 3); // section len
+ // de 1 byte header, type 5, len 5
+ adv_body.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 6, len 1
+ adv_body.extend_from_slice(&[0x81, 0x06, 0x01]);
+
+ let adv_header = V1AdvHeader::new(0x20);
+
+ assert_eq!(
+ nom::Err::Error(error::Error { input: &adv_body[11..], code: error::ErrorKind::Eof }),
+ parse_sections(adv_header, &adv_body).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_adv_too_many_encrypted() {
+ // 3 sections
+ let mut adv_body = vec![];
+ for _ in 0..NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT + 1 {
+ let _ = add_mic_short_salt_section_to_adv(&mut adv_body);
+ }
+ let adv_header = V1AdvHeader::new(0x20);
+ let _ = parse_sections(adv_header, &adv_body).expect_err("Expected an error");
+ }
+
+ #[test]
+ fn do_deserialize_zero_section_header() {
+ let mut adv: tinyvec::ArrayVec<[u8; 254]> = tinyvec::ArrayVec::new();
+ adv.push(0x20); // V1 Advertisement
+ adv.push(0x00); // Section header of 0
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+ let v1_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+ let _ = parse_sections(v1_header, remaining).expect_err("Expected an error");
+ }
+
+ #[test]
+ fn invalid_public_section() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let mut adv_body = vec![];
+ // Add section length
+ let remove_section_len = rng.gen_bool(0.5);
+ // Add public identity
+ let add_public_identity = rng.gen_bool(0.5);
+ // Add DEs
+ let add_des = rng.gen_bool(0.5);
+ // Shuffle adv
+ let shuffle = rng.gen_bool(0.5);
+
+ adv_body.push(0);
+ if add_public_identity {
+ adv_body[0] += 1;
+ adv_body.push(0x03);
+ }
+ if add_des {
+ adv_body[0] += 1;
+ adv_body.extend_from_slice(&[0x81]);
+ }
+ if remove_section_len {
+ let _ = adv_body.remove(0);
+ }
+
+ let ordered_adv = adv_body.clone();
+
+ if shuffle {
+ adv_body.shuffle(&mut rng);
+ }
+ // A V1 public section is invalid if
+ // * section length is missing
+ // * the section is empty
+ // * the section identity is missing
+ // * the identity does not follow the section length
+ // * the section length is 0
+ if remove_section_len || !add_public_identity || (ordered_adv != adv_body) {
+ let _ = parse_sections(V1AdvHeader::new(0x20), &adv_body)
+ .expect_err("Expected to fail because of missing section length or identity");
+ }
+ }
+ }
+
+ #[test]
+ fn parse_empty_section_as_encrypted() {
+ // empty section - should return an EOF error
+ let input = [];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // attempted to read section contents
+ input: input.as_slice(),
+ code: error::ErrorKind::Eof,
+ }),
+ IntermediateSection::parser_encrypted_with_header(V1AdvHeader::new(0x20))(&input)
+ .unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_unencrypted_as_encrypted() {
+ let mut input = vec![];
+ // public identity
+ input.push(V1_ENCODING_UNENCRYPTED);
+ // section len
+ input.push(6 + 3);
+ // de 1 byte header, type 5, len 5
+ input.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 22, len 1
+ input.extend_from_slice(&[0x81, 0x16, 0x01]);
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // attempted to read section contents
+ input: input.as_slice(),
+ code: error::ErrorKind::MapOpt,
+ }),
+ IntermediateSection::parser_encrypted_with_header(V1AdvHeader::new(0x20))(&input)
+ .unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_section_length_overrun() {
+ // section of length 0xF0 - legal but way longer than 2
+ let input = [V1_ENCODING_UNENCRYPTED, 0xF0, 0x10, 0x11];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ // attempted to read section contents after parsing header
+ input: &input.as_slice()[2..],
+ code: error::ErrorKind::Eof,
+ }),
+ SectionContents::parse(&input).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn do_deserialize_empty_section() {
+ let adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ let adv = adv_builder.into_advertisement();
+ let (remaining, header) = NpVersionHeader::parse(adv.as_slice()).unwrap();
+ let v1_header = if let NpVersionHeader::V1(h) = header {
+ h
+ } else {
+ panic!("incorrect header");
+ };
+ let _ = parse_sections(v1_header, remaining).expect_err("Expected an error");
+ }
+
+ #[test]
+ fn parse_adv_sig_encrypted_section_with_short_salt() {
+ // 3 sections
+ let mut adv_body = vec![];
+ let salt_bytes = [0x11; SHORT_SALT_LEN];
+ let section_len = EXT_SALT_SECTION_HEADER_LEN as u8 + 10;
+ adv_body.push(section_len);
+ adv_body.push(V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN);
+ adv_body.extend_from_slice(&salt_bytes);
+ adv_body.extend_from_slice(&[0x33; V1_IDENTITY_TOKEN_LEN]);
+ adv_body.extend_from_slice(&[0x22; 10]);
+ let adv_header = V1AdvHeader::new(0x20);
+ let parsed_sections = parse_sections(adv_header, &adv_body);
+ assert!(parsed_sections.is_err());
+ }
+
+ // specify extended salt in the header but adv actual contains short salt
+ #[test]
+ fn parse_adv_mic_encrypted_wrong_salt_for_extended_header() {
+ // 3 sections
+ let mut adv = vec![];
+ let section_len = SHORT_SALT_SECTION_HEADER_LEN as u8 + 10 + SectionMic::CONTENTS_LEN as u8;
+ adv.push(section_len);
+ adv.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ let salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ adv.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_1 = [0x55; V1_IDENTITY_TOKEN_LEN];
+ adv.extend_from_slice(&token_bytes_1);
+ // 10 bytes of 0xFF ciphertext
+ adv.extend_from_slice(&[0xFF; 10]);
+ // mic - 16x 0x33
+ adv.extend_from_slice(&[0x33; SectionMic::CONTENTS_LEN]);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let parsed_sections = parse_sections(adv_header, &adv);
+ assert!(parsed_sections.is_err());
+ }
+
+ // specify extended salt in the header but adv actual contains short salt
+ #[test]
+ fn encrypted_then_unencrpyted_fails_to_parse() {
+ // 3 sections
+ let mut adv = vec![];
+ let section_len = SHORT_SALT_SECTION_HEADER_LEN as u8 + 10 + SectionMic::CONTENTS_LEN as u8;
+ adv.push(section_len);
+ adv.push(V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN);
+ let salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ adv.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_1 = [0x55; V1_IDENTITY_TOKEN_LEN];
+ adv.extend_from_slice(&token_bytes_1);
+ // 10 bytes of 0xFF ciphertext
+ adv.extend_from_slice(&[0xFF; 10]);
+ // mic - 16x 0x33
+ adv.extend_from_slice(&[0x33; SectionMic::CONTENTS_LEN]);
+
+ // Now add public section
+ // section len
+ adv.push(1 + 6 + 3);
+ // public identity
+ adv.push(V1_ENCODING_UNENCRYPTED);
+ // de 1 byte header, type 5, len 5
+ adv.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 6, len 1
+ adv.extend_from_slice(&[0x81, 0x06, 0x01]);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let parsed_sections = parse_sections(adv_header, &adv);
+ assert!(parsed_sections.is_err());
+ }
+
+ // specify extended salt in the header but adv actual contains short salt
+ #[test]
+ fn unencrypted_then_encrpyted_fails_to_parse() {
+ let mut adv = vec![];
+
+ // Public section
+ // section len
+ adv.push(1 + 6 + 3);
+ // public identity
+ adv.push(V1_ENCODING_UNENCRYPTED);
+ // de 1 byte header, type 5, len 5
+ adv.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
+ // de 2 byte header, type 6, len 1
+ adv.extend_from_slice(&[0x81, 0x06, 0x01]);
+
+ // mic encrypted section
+ let section_len = SHORT_SALT_SECTION_HEADER_LEN as u8 + 10 + SectionMic::CONTENTS_LEN as u8;
+ adv.push(section_len);
+ adv.push(V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN);
+ let salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ adv.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_1 = [0x55; V1_IDENTITY_TOKEN_LEN];
+ adv.extend_from_slice(&token_bytes_1);
+ // 10 bytes of 0xFF ciphertext
+ adv.extend_from_slice(&[0xFF; 10]);
+ // mic - 16x 0x33
+ adv.extend_from_slice(&[0x33; SectionMic::CONTENTS_LEN]);
+
+ let adv_header = V1AdvHeader::new(0x20);
+ let parsed_sections = parse_sections(adv_header, &adv);
+ assert!(parsed_sections.is_err());
+ }
+}
+
+mod coverage_gaming {
+ use super::*;
+ use alloc::format;
+
+ #[test]
+ fn section_contents() {
+ let sc = SectionContents {
+ format_bytes: &[],
+ header: SectionHeader::Unencrypted,
+ contents: &[],
+ contents_len: 0,
+ };
+ let _ = format!("{:?}", sc);
+ assert_eq!(sc, sc);
+ }
+
+ #[test]
+ fn intermediate_section() {
+ let is = IntermediateSection::Plaintext(PlaintextSection::new(&[]));
+ let _ = format!("{:?}", is);
+ }
+ #[test]
+ fn ciphertext_section() {
+ let ms = MicEncryptedSection {
+ contents: EncryptedSectionContents::new(
+ V1AdvHeader::new(1),
+ &[],
+ ShortV1Salt::from([0x00; 2]).into(),
+ CiphertextExtendedIdentityToken([0x00; 16]),
+ 0,
+ &[],
+ ),
+ mic: [0x00; 16].into(),
+ };
+ let cs = CiphertextSection::MicEncrypted(ms);
+ let _ = format!("{:?}", cs);
+ }
+}
+
+pub(crate) trait IntermediateSectionExt<'adv> {
+ /// Returns `Some` if `self` is `Plaintext`
+ fn as_plaintext(&self) -> Option<&PlaintextSection<'adv>>;
+ /// Returns `Some` if `self` is `Ciphertext`
+ fn as_ciphertext(&self) -> Option<&CiphertextSection<'adv>>;
+}
+
+impl<'adv> IntermediateSectionExt<'adv> for IntermediateSection<'adv> {
+ fn as_plaintext(&self) -> Option<&PlaintextSection<'adv>> {
+ match self {
+ IntermediateSection::Plaintext(s) => Some(s),
+ IntermediateSection::Ciphertext(_) => None,
+ }
+ }
+
+ fn as_ciphertext(&self) -> Option<&CiphertextSection<'adv>> {
+ match self {
+ IntermediateSection::Plaintext(_) => None,
+ IntermediateSection::Ciphertext(s) => Some(s),
+ }
+ }
+}
+
+// returns the number of bytes appended to adv
+fn add_mic_short_salt_section_to_adv(adv: &mut Vec<u8>) -> usize {
+ // section
+ adv.push(V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN);
+ let salt = ShortV1Salt::from([0x11; SHORT_SALT_LEN]);
+ adv.extend_from_slice(salt.bytes().as_slice());
+ let token_bytes_1 = [0x55; V1_IDENTITY_TOKEN_LEN];
+ adv.extend_from_slice(&token_bytes_1);
+ let section_len = 10 + SectionMic::CONTENTS_LEN as u8;
+ adv.push(section_len);
+ // 10 bytes of 0xFF ciphertext
+ adv.extend_from_slice(&[0xFF; 10]);
+ // mic - 16x 0x33
+ adv.extend_from_slice(&[0x33; SectionMic::CONTENTS_LEN]);
+ 1 + SHORT_SALT_LEN + V1_IDENTITY_TOKEN_LEN + 1 + 10 + SectionMic::CONTENTS_LEN
+}
+
+// returns the total number of bytes appended to adv
+fn add_sig_encrpyted_section(
+ adv_body: &mut Vec<u8>,
+ len: u8,
+ salt_bytes: &[u8; EXTENDED_SALT_LEN],
+) -> usize {
+ adv_body.push(V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN);
+ adv_body.extend_from_slice(salt_bytes);
+ adv_body.extend_from_slice(&[0x33; V1_IDENTITY_TOKEN_LEN]);
+ adv_body.push(len);
+ // len bytes of 0xFF ciphertext -- in a real adv this would include the
+ // signature, but for the purposes of this parser, it's all just ciphertext
+ for _ in 0..len {
+ adv_body.push(0xFF);
+ }
+ 1 + EXTENDED_SALT_LEN + V1_IDENTITY_TOKEN_LEN + 1 + len as usize
+}
+
+// for convenient .into() in expected test data
+impl<'a> From<SignatureEncryptedSection<'a>> for IntermediateSection<'a> {
+ fn from(s: SignatureEncryptedSection<'a>) -> Self {
+ IntermediateSection::Ciphertext(CiphertextSection::SignatureEncrypted(s))
+ }
+}
+
+impl<'a> From<MicEncryptedSection<'a>> for IntermediateSection<'a> {
+ fn from(s: MicEncryptedSection<'a>) -> Self {
+ IntermediateSection::Ciphertext(CiphertextSection::MicEncrypted(s))
+ }
+}
+
+impl<'a> From<PlaintextSection<'a>> for IntermediateSection<'a> {
+ fn from(s: PlaintextSection<'a>) -> Self {
+ IntermediateSection::Plaintext(s)
+ }
+}
diff --git a/nearby/presence/ldt_np_adv_ffi/src/no_std.rs b/nearby/presence/np_adv/src/extended/deserialize/section/mod.rs
index 524bc3d..1020e8d 100644
--- a/nearby/presence/ldt_np_adv_ffi/src/no_std.rs
+++ b/nearby/presence/np_adv/src/extended/deserialize/section/mod.rs
@@ -11,15 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-// mod to handle all of the impls needed for no_std
-
-extern crate panic_abort;
-
-use libc_alloc::LibcAlloc;
-
-#[global_allocator]
-static ALLOCATOR: LibcAlloc = LibcAlloc;
-#[lang = "eh_personality"]
-extern "C" fn eh_personality() {}
+pub(crate) mod header;
+pub(crate) mod intermediate;
diff --git a/nearby/presence/np_adv/src/extended/deserialize/section_tests.rs b/nearby/presence/np_adv/src/extended/deserialize/section_tests.rs
deleted file mode 100644
index 5fa2dbe..0000000
--- a/nearby/presence/np_adv/src/extended/deserialize/section_tests.rs
+++ /dev/null
@@ -1,622 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-
-use super::*;
-use crate::deserialization_arena;
-use crate::deserialization_arena::DeserializationArena;
-use crate::extended::serialize::AdvertisementType;
-use crate::extended::NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT;
-use crate::{
- credential::{
- source::{DiscoveryCredentialSource, SliceCredentialSource},
- v1::{SignedBroadcastCryptoMaterial, SimpleSignedBroadcastCryptoMaterial, V1},
- DiscoveryCryptoMaterial, EmptyMatchedCredential, MatchableCredential,
- MetadataMatchedCredential, SimpleBroadcastCryptoMaterial,
- },
- extended::{
- data_elements::GenericDataElement,
- deserialize::{test_stubs::IntermediateSectionExt, DataElement},
- serialize::{
- self, AdvBuilder, MicEncryptedSectionEncoder, PublicSectionEncoder, SectionBuilder,
- SignedEncryptedSectionEncoder, WriteDataElement,
- },
- MAX_DE_LEN,
- },
- parse_adv_header, AdvHeader, WithMatchedCredential,
-};
-use core::borrow::Borrow;
-use core::convert::Into;
-use crypto_provider::{CryptoProvider, CryptoRng};
-use crypto_provider_default::CryptoProviderImpl;
-use rand::{seq::SliceRandom as _, Rng as _, SeedableRng as _};
-use std::prelude::rust_2021::*;
-use std::vec;
-
-type KeyPair = np_ed25519::KeyPair<CryptoProviderImpl>;
-
-#[test]
-fn deserialize_public_identity_section() {
- do_deserialize_section_unencrypted::<PublicSectionEncoder>(
- PublicSectionEncoder::default(),
- PlaintextIdentityMode::Public,
- 1,
- );
-}
-
-// due to lifetime issues, this is somewhat challenging to share with the 90% identical signature
-// test, but if someone feels like putting in the tinkering to make it happen, please do
-#[test]
-fn deserialize_mic_encrypted_rand_identities_finds_correct_one() {
- let mut rng = rand::rngs::StdRng::from_entropy();
- let mut crypto_rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
- for _ in 0..100 {
- let identities = (0..100).map(|_| (rng.gen(), KeyPair::generate())).collect::<Vec<_>>();
-
- let chosen_index = rng.gen_range(0..identities.len());
- let (chosen_key_seed, _chosen_key_pair) = &identities[chosen_index];
-
- // share a metadata key to emphasize that we're _only_ using the identity to
- // differentiate
- let metadata_key: [u8; 16] = rng.gen();
- let metadata_key = MetadataKey(metadata_key);
-
- let creds = identities
- .iter()
- .map(|(key_seed, key_pair)| {
- SimpleSignedBroadcastCryptoMaterial::new(
- *key_seed,
- metadata_key,
- key_pair.private_key(),
- )
- })
- .enumerate()
- .map(|(index, broadcast_cm)| {
- let match_data = MetadataMatchedCredential::<Vec<u8>>::encrypt_from_plaintext::<
- _,
- _,
- CryptoProviderImpl,
- >(&broadcast_cm, &[index as u8]);
-
- let discovery_credential =
- broadcast_cm.derive_v1_discovery_credential::<CryptoProviderImpl>();
-
- MatchableCredential { discovery_credential, match_data }
- })
- .collect::<Vec<_>>();
-
- let cred_source = SliceCredentialSource::new(&creds);
-
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(*chosen_key_seed, metadata_key);
-
- let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
- &mut crypto_rng,
- identity_type,
- &broadcast_cm,
- ))
- .unwrap();
-
- let mut expected_de_data = vec![];
- let (expected_des, orig_des) =
- fill_section_random_des(&mut rng, &mut expected_de_data, &mut section_builder, 2);
-
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
-
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- let arena = deserialization_arena!();
-
- let section = sections[0].as_ciphertext().unwrap();
- let matched_section =
- try_deserialize_all_creds::<_, CryptoProviderImpl>(arena, section, &cred_source)
- .unwrap()
- .unwrap();
-
- // Verify that the decrypted metadata contains the chosen index
- let decrypted_metadata = matched_section.decrypt_metadata::<CryptoProviderImpl>().unwrap();
- assert_eq!([chosen_index as u8].as_slice(), &decrypted_metadata);
-
- // Verify that the section contents passed through unaltered
- let section = matched_section.contents();
- assert_eq!(section.identity_type(), identity_type);
- assert_eq!(section.verification_mode(), VerificationMode::Mic);
- assert_eq!(section.metadata_key(), metadata_key);
- assert_eq!(
- section.contents.section_header,
- (19 + 2 + 16 + total_de_len(&orig_des) + 16) as u8
- );
- let data_elements = section.collect_data_elements().unwrap();
- assert_eq!(data_elements, expected_des);
- assert_eq!(
- data_elements
- .iter()
- .map(|de| GenericDataElement::try_from(de.de_type(), de.contents()).unwrap())
- .collect::<Vec<_>>(),
- orig_des
- );
- }
-}
-
-#[test]
-fn deserialize_signature_encrypted_rand_identities_finds_correct_one() {
- let mut rng = rand::rngs::StdRng::from_entropy();
- let mut crypto_rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
- for _ in 0..100 {
- let identities = (0..100).map(|_| (rng.gen(), KeyPair::generate())).collect::<Vec<_>>();
-
- let chosen_index = rng.gen_range(0..identities.len());
- let (chosen_key_seed, chosen_key_pair) = &identities[chosen_index];
-
- // share a metadata key to emphasize that we're _only_ using the identity to
- // differentiate
- let metadata_key: [u8; 16] = rng.gen();
- let metadata_key = MetadataKey(metadata_key);
-
- let creds = identities
- .iter()
- .map(|(key_seed, key_pair)| {
- SimpleSignedBroadcastCryptoMaterial::new(
- *key_seed,
- metadata_key,
- key_pair.private_key(),
- )
- })
- .enumerate()
- .map(|(index, broadcast_cm)| {
- let match_data = MetadataMatchedCredential::<Vec<u8>>::encrypt_from_plaintext::<
- _,
- _,
- CryptoProviderImpl,
- >(&broadcast_cm, &[index as u8]);
-
- let discovery_credential =
- broadcast_cm.derive_v1_discovery_credential::<CryptoProviderImpl>();
- MatchableCredential { discovery_credential, match_data }
- })
- .collect::<Vec<_>>();
-
- let cred_source = SliceCredentialSource::new(&creds);
-
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleSignedBroadcastCryptoMaterial::new(
- *chosen_key_seed,
- metadata_key,
- chosen_key_pair.private_key(),
- );
-
- let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
- &mut crypto_rng,
- identity_type,
- &broadcast_cm,
- ))
- .unwrap();
-
- let mut expected_de_data = vec![];
- let (expected_des, orig_des) =
- fill_section_random_des(&mut rng, &mut expected_de_data, &mut section_builder, 2);
-
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
-
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let arena = deserialization_arena!();
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- let section = sections[0].as_ciphertext().unwrap();
- let matched_section =
- try_deserialize_all_creds::<_, CryptoProviderImpl>(arena, section, &cred_source)
- .unwrap()
- .unwrap();
-
- // Verify that the decrypted metadata contains the chosen index
- let decrypted_metadata = matched_section.decrypt_metadata::<CryptoProviderImpl>().unwrap();
- assert_eq!([chosen_index as u8].as_slice(), &decrypted_metadata);
-
- // Verify that the section contents passed through unaltered
- let section = matched_section.contents();
- assert_eq!(section.identity_type(), identity_type);
- assert_eq!(section.verification_mode(), VerificationMode::Signature);
- assert_eq!(section.metadata_key(), metadata_key);
- assert_eq!(
- section.contents.section_header,
- (19 + 2 + 16 + 64 + total_de_len(&orig_des)) as u8
- );
- let data_elements = section.collect_data_elements().unwrap();
- assert_eq!(data_elements, expected_des);
- assert_eq!(
- data_elements
- .iter()
- .map(|de| GenericDataElement::try_from(de.de_type(), de.contents()).unwrap())
- .collect::<Vec<_>>(),
- orig_des
- );
- }
-}
-
-#[test]
-fn deserialize_encrypted_no_matching_identities_finds_nothing() {
- let mut rng = rand::rngs::StdRng::from_entropy();
- let mut crypto_rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
- for _ in 0..100 {
- let signed = rng.gen();
- let mut identities = (0..100).map(|_| (rng.gen(), KeyPair::generate())).collect::<Vec<_>>();
-
- let chosen_index = rng.gen_range(0..identities.len());
- // remove so they won't be found later
- let (chosen_key_seed, chosen_key_pair) = identities.remove(chosen_index);
-
- // share a metadata key to emphasize that we're _only_ using the identity to
- // differentiate
- let metadata_key: [u8; 16] = rng.gen();
- let metadata_key = MetadataKey(metadata_key);
-
- let credentials = identities
- .iter()
- .map(|(key_seed, key_pair)| {
- SimpleSignedBroadcastCryptoMaterial::new(
- *key_seed,
- metadata_key,
- key_pair.private_key(),
- )
- .derive_v1_discovery_credential::<CryptoProviderImpl>()
- })
- .map(|discovery_credential| MatchableCredential {
- discovery_credential,
- match_data: EmptyMatchedCredential,
- })
- .collect::<Vec<_>>();
-
- let cred_source = SliceCredentialSource::new(&credentials);
-
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
- let broadcast_cm = SimpleSignedBroadcastCryptoMaterial::new(
- chosen_key_seed,
- metadata_key,
- chosen_key_pair.private_key(),
- );
-
- // awkward split because SectionEncoder isn't object-safe, so we can't just have a
- // Box<dyn SectionEncoder> and use that in one code path
- if signed {
- let identity = SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
- &mut crypto_rng,
- identity_type,
- &broadcast_cm,
- );
- let mut section_builder = adv_builder.section_builder(identity).unwrap();
- let mut expected_de_data = vec![];
- let _ =
- fill_section_random_des(&mut rng, &mut expected_de_data, &mut section_builder, 2);
- section_builder.add_to_advertisement();
- } else {
- let identity = MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
- &mut crypto_rng,
- identity_type,
- &broadcast_cm,
- );
- let mut section_builder = adv_builder.section_builder(identity).unwrap();
- let mut expected_de_data = vec![];
- let _ =
- fill_section_random_des(&mut rng, &mut expected_de_data, &mut section_builder, 2);
- section_builder.add_to_advertisement();
- };
-
- let adv = adv_builder.into_advertisement();
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
-
- assert!(try_deserialize_all_creds::<_, CryptoProviderImpl>(
- deserialization_arena!(),
- sections[0].as_ciphertext().unwrap(),
- &cred_source,
- )
- .unwrap()
- .is_none());
- }
-}
-
-#[test]
-fn section_des_expose_correct_data() {
- // 2 sections, 3 DEs each
- let mut de_data = vec![];
- // de 1 byte header, type 5, len 5
- de_data.extend_from_slice(&[0x55, 0x01, 0x02, 0x03, 0x04, 0x05]);
- // de 2 byte header, type 16, len 1
- de_data.extend_from_slice(&[0x81, 0x10, 0x01]);
-
- let section = SectionContents {
- section_header: 99,
- de_region_excl_identity: &de_data,
- data_element_start_offset: 2,
- };
-
- // extract out the parts of the DE we care about
- let des = section.iter_data_elements().collect::<Result<Vec<_>, _>>().unwrap();
- assert_eq!(
- vec![
- DataElement {
- offset: 2.into(),
- de_type: 5_u32.into(),
- contents: &[0x01, 0x02, 0x03, 0x04, 0x05]
- },
- DataElement { offset: 3.into(), de_type: 16_u32.into(), contents: &[0x01] },
- ],
- des
- );
-}
-
-#[test]
-fn do_deserialize_zero_section_header() {
- let mut adv: tinyvec::ArrayVec<[u8; 254]> = tinyvec::ArrayVec::new();
- adv.push(0x20); // V1 Advertisement
- adv.push(0x00); // Section header of 0
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
- let _ = parse_sections(v1_header, remaining).expect_err("Expected an error");
-}
-
-#[test]
-fn do_deserialize_empty_section() {
- let adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let adv = adv_builder.into_advertisement();
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
- let _ = parse_sections(v1_header, remaining).expect_err("Expected an error");
-}
-
-#[test]
-fn do_deserialize_max_number_of_public_sections() {
- let adv_builder = build_dummy_advertisement_sections(NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT);
- let adv = adv_builder.into_advertisement();
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT, sections.len());
-}
-
-#[test]
-fn try_deserialize_over_max_number_of_public_sections() {
- let adv_builder = build_dummy_advertisement_sections(NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT);
- let mut adv = adv_builder.into_advertisement().as_slice().to_vec();
-
- // Push an extra section
- adv.extend_from_slice(
- [
- 0x01, // Section header
- 0x03, // Public identity
- ]
- .as_slice(),
- );
-
- let (remaining, header) = parse_adv_header(&adv).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
- let _ = parse_sections(v1_header, remaining)
- .expect_err("Expected an error because number of sections is over limit");
-}
-
-pub(crate) fn random_de<R: rand::Rng>(rng: &mut R) -> GenericDataElement {
- let mut array = [0_u8; MAX_DE_LEN];
- rng.fill(&mut array[..]);
- let data: ArrayView<u8, MAX_DE_LEN> =
- ArrayView::try_from_array(array, rng.gen_range(0..=MAX_DE_LEN)).unwrap();
- // skip the first few DEs that Google uses
- GenericDataElement::try_from(rng.gen_range(20_u32..1000).into(), data.as_slice()).unwrap()
-}
-
-fn do_deserialize_section_unencrypted<I: serialize::SectionEncoder>(
- identity: I,
- expected_identity: PlaintextIdentityMode,
- de_offset: usize,
-) {
- let mut rng = rand::rngs::StdRng::from_entropy();
-
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(identity).unwrap();
-
- let mut expected_de_data = vec![];
- let (expected_des, orig_des) =
- fill_section_random_des(&mut rng, &mut expected_de_data, &mut section_builder, de_offset);
-
- section_builder.add_to_advertisement();
-
- let adv = adv_builder.into_advertisement();
-
- let (remaining, header) = parse_adv_header(adv.as_slice()).unwrap();
-
- let v1_header = if let AdvHeader::V1(h) = header {
- h
- } else {
- panic!("incorrect header");
- };
-
- let sections = parse_sections(v1_header, remaining).unwrap();
- assert_eq!(1, sections.len());
- let section = sections[0].as_plaintext().unwrap();
-
- assert_eq!(section.identity(), expected_identity);
- let data_elements = section.collect_data_elements().unwrap();
- assert_eq!(data_elements, expected_des);
- assert_eq!(
- data_elements
- .iter()
- .map(|de| GenericDataElement::try_from(de.de_type(), de.contents()).unwrap())
- .collect::<Vec<_>>(),
- orig_des
- );
-}
-
-fn fill_section_random_des<'adv, R: rand::Rng, I: serialize::SectionEncoder>(
- mut rng: &mut R,
- sink: &'adv mut Vec<u8>,
- section_builder: &mut SectionBuilder<&mut AdvBuilder, I>,
- de_offset: usize,
-) -> (Vec<DataElement<'adv>>, Vec<GenericDataElement>) {
- let mut expected_des = vec![];
- let mut orig_des = vec![];
- let mut de_ranges = vec![];
-
- for _ in 0..rng.gen_range(1..10) {
- let de = random_de(&mut rng);
-
- let de_clone = de.clone();
- if section_builder.add_de(|_| de_clone).is_err() {
- break;
- }
-
- let orig_len = sink.len();
- de.write_de_contents(sink).unwrap();
- let contents_len = sink.len() - orig_len;
- de_ranges.push(orig_len..orig_len + contents_len);
- orig_des.push(de);
- }
-
- for (index, (de, range)) in orig_des.iter().zip(de_ranges).enumerate() {
- expected_des.push(DataElement {
- offset: u8::try_from(index + de_offset).unwrap().into(),
- de_type: de.de_header().de_type,
- contents: &sink[range],
- });
- }
- (expected_des, orig_des)
-}
-
-fn total_de_len(des: &[GenericDataElement]) -> usize {
- des.iter()
- .map(|de| {
- let mut buf = vec![];
- let _ = de.write_de_contents(&mut buf);
- de.de_header().serialize().len() + buf.len()
- })
- .sum()
-}
-
-type TryDeserOutput<'adv, M> = Option<WithMatchedCredential<M, DecryptedSection<'adv>>>;
-
-/// Returns:
-/// - `Ok(Some)` if a matching credential was found
-/// - `Ok(None)` if no matching credential was found, or if `cred_source` provides no credentials
-/// - `Err` if an error occurred.
-fn try_deserialize_all_creds<'a, S, P>(
- arena: DeserializationArena<'a>,
- section: &'a CiphertextSection,
- cred_source: &'a S,
-) -> Result<TryDeserOutput<'a, S::Matched>, BatchSectionDeserializeError>
-where
- S: DiscoveryCredentialSource<'a, V1>,
- P: CryptoProvider,
-{
- let mut allocator = arena.into_allocator();
- for (crypto_material, match_data) in cred_source.iter() {
- match section
- .try_resolve_identity_and_deserialize::<_, P>(&mut allocator, crypto_material.borrow())
- {
- Ok(s) => {
- let metadata_nonce = crypto_material.metadata_nonce::<P>();
- return Ok(Some(WithMatchedCredential::new(match_data, metadata_nonce, s)));
- }
- Err(e) => match e {
- SectionDeserializeError::IncorrectCredential => continue,
- SectionDeserializeError::ParseError => {
- return Err(BatchSectionDeserializeError::ParseError)
- }
- SectionDeserializeError::ArenaOutOfSpace => {
- return Err(BatchSectionDeserializeError::ArenaOutOfSpace)
- }
- },
- }
- }
-
- Ok(None)
-}
-
-fn build_dummy_advertisement_sections(number_of_sections: usize) -> AdvBuilder {
- let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- for _ in 0..number_of_sections {
- let section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
- section_builder.add_to_advertisement();
- }
- adv_builder
-}
-
-#[derive(Debug, PartialEq, Eq)]
-enum BatchSectionDeserializeError {
- /// Advertisement data is malformed
- ParseError,
- /// The given arena is not large enough to hold the decrypted data
- ArenaOutOfSpace,
-}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/test_stubs.rs b/nearby/presence/np_adv/src/extended/deserialize/test_stubs.rs
deleted file mode 100644
index 68b6f5d..0000000
--- a/nearby/presence/np_adv/src/extended/deserialize/test_stubs.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.
-
-extern crate std;
-
-use std::prelude::rust_2021::*;
-
-use crate::{
- extended::deserialize::{CiphertextSection, PlaintextSection},
- IntermediateSection,
-};
-
-pub(crate) trait IntermediateSectionExt<'adv> {
- /// Returns `Some` if `self` is `Plaintext`
- fn as_plaintext(&self) -> Option<&PlaintextSection<'adv>>;
- /// Returns `Some` if `self` is `Ciphertext`
- fn as_ciphertext(&self) -> Option<&CiphertextSection<'adv>>;
-}
-
-impl<'adv> IntermediateSectionExt<'adv> for IntermediateSection<'adv> {
- fn as_plaintext(&self) -> Option<&PlaintextSection<'adv>> {
- match self {
- IntermediateSection::Plaintext(s) => Some(s),
- IntermediateSection::Ciphertext(_) => None,
- }
- }
-
- fn as_ciphertext(&self) -> Option<&CiphertextSection<'adv>> {
- match self {
- IntermediateSection::Plaintext(_) => None,
- IntermediateSection::Ciphertext(s) => Some(s),
- }
- }
-}
diff --git a/nearby/presence/np_adv/src/extended/deserialize/tests.rs b/nearby/presence/np_adv/src/extended/deserialize/tests.rs
new file mode 100644
index 0000000..3164c2b
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/deserialize/tests.rs
@@ -0,0 +1,145 @@
+// 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.
+
+//! Unit tests for top level credential iteration and adv deserialization
+
+#![allow(clippy::unwrap_used)]
+
+use crate::{
+ credential::book::CredentialBook,
+ deserialization_arena,
+ deserialization_arena::ArenaOutOfSpace,
+ extended::serialize::{AddSectionError, AdvBuilder, AdvertisementType},
+ header::NpVersionHeader,
+ tests::deser_v1_tests::{
+ add_mic_rand_salt_to_adv, add_sig_rand_salt_to_adv, SectionConfig, TestIdentity,
+ },
+};
+use crypto_provider_default::CryptoProviderImpl;
+use rand::{prelude::StdRng, seq::IteratorRandom, SeedableRng};
+
+#[test]
+fn v1_arena_out_of_space_error_sig() {
+ v1_arena_out_of_space_error_encrypted_adv(
+ // Need to use many DE's to be sure we go over the arena limit
+ add_sig_rand_salt_to_adv::<StdRng, CryptoProviderImpl, 5>,
+ )
+}
+
+#[test]
+fn v1_arena_out_of_space_error_mic() {
+ v1_arena_out_of_space_error_encrypted_adv(
+ // Need to use many DE's to be sure we go over the arena limit
+ add_mic_rand_salt_to_adv::<StdRng, CryptoProviderImpl, 5>,
+ )
+}
+
+fn v1_arena_out_of_space_error_encrypted_adv(
+ add_to_adv: impl for<'a> Fn(
+ &mut StdRng,
+ &'a TestIdentity,
+ &mut AdvBuilder,
+ ) -> Result<SectionConfig<'a>, AddSectionError>,
+) {
+ let mut rng = StdRng::from_entropy();
+ let mut builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let identities =
+ crate::tests::deser_v1_tests::TestIdentities::generate::<1, _, CryptoProviderImpl>(
+ &mut rng,
+ );
+ let _ = add_to_adv(&mut rng, &identities.0[0], &mut builder);
+ let adv = builder.into_advertisement().as_slice().to_vec();
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+
+ let (remaining, header) = NpVersionHeader::parse(&adv).unwrap();
+
+ let h =
+ if let NpVersionHeader::V1(v1_header) = header { Some(v1_header) } else { None }.unwrap();
+
+ let mut sections_in_processing =
+ crate::extended::deserialize::SectionsInProcessing::<'_, _>::from_advertisement_contents::<
+ CryptoProviderImpl,
+ >(h, remaining)
+ .unwrap();
+
+ // fill up allocator so we will run out of space
+ let arena = deserialization_arena!();
+ let mut allocator = arena.into_allocator();
+ let _ = allocator.allocate(250).unwrap();
+
+ let (crypto_material, match_data) = cred_book.v1_iter().choose(&mut rng).unwrap();
+
+ let res = sections_in_processing.try_decrypt_with_credential::<_, CryptoProviderImpl>(
+ &mut allocator,
+ crypto_material,
+ match_data,
+ );
+ assert_eq!(Err(ArenaOutOfSpace), res);
+}
+
+mod coverage_gaming {
+ use crate::{
+ array_vec::ArrayVecOption,
+ credential::matched::EmptyMatchedCredential,
+ extended::{
+ deserialize::{
+ section::intermediate::PlaintextSection, DecryptedSection, SectionDeserializeError,
+ V1AdvertisementContents, V1DeserializedSection, VerificationMode,
+ },
+ salt::MultiSalt,
+ },
+ };
+ use alloc::format;
+
+ #[test]
+ fn decrypted_section_derives() {
+ let d = DecryptedSection::new(
+ VerificationMode::Mic,
+ MultiSalt::Extended([0u8; 16].into()),
+ [0u8; 16].into(),
+ &[],
+ );
+ let _ = format!("{:?}", d);
+ }
+
+ #[test]
+ fn section_deserialize_error_derives() {
+ let e = SectionDeserializeError::IncorrectCredential;
+ assert_eq!(e, e);
+ let _ = format!("{:?}", e);
+ }
+
+ #[test]
+ fn adv_contents_derives() {
+ let c: V1AdvertisementContents<'_, EmptyMatchedCredential> =
+ V1AdvertisementContents::new(ArrayVecOption::default(), 0);
+ let _ = format!("{:?}", c);
+ assert_eq!(c, c);
+ }
+
+ #[test]
+ fn deserialized_section_derives() {
+ let d: V1DeserializedSection<'_, EmptyMatchedCredential> =
+ V1DeserializedSection::Plaintext(PlaintextSection::new(&[]));
+ assert_eq!(d, d);
+ let _ = format!("{:?}", d);
+ }
+
+ #[test]
+ fn verification_mode_derives() {
+ let m = VerificationMode::Signature;
+ #[allow(clippy::clone_on_copy)]
+ let _ = format!("{:?}", m.clone());
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/mod.rs b/nearby/presence/np_adv/src/extended/mod.rs
index 68b16c3..4a13ea5 100644
--- a/nearby/presence/np_adv/src/extended/mod.rs
+++ b/nearby/presence/np_adv/src/extended/mod.rs
@@ -13,18 +13,20 @@
// limitations under the License.
//! V1 advertisement support.
-use crate::extended::de_type::DeType;
use crate::DeLengthOutOfRange;
use array_view::ArrayView;
+use crypto_provider::CryptoRng;
pub mod data_elements;
pub mod de_type;
pub mod deserialize;
+pub mod salt;
pub mod section_signature_payload;
pub mod serialize;
+// TODO make this easy to use w/ configurable arena size
/// Maximum size of an NP advertisement, including the adv header
-pub const BLE_ADV_SVC_CONTENT_LEN: usize = 254
+pub const BLE_5_ADV_SVC_MAX_CONTENT_LEN: usize = 254
// length and type bytes for svc data TLV
- 1 - 1
// NP UUID
@@ -36,16 +38,81 @@ pub const NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT: usize = 8;
/// Maximum number of public sections in an advertisement
pub const NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT: usize = 1;
-/// Maximum size of a NP section, including its header byte
-pub const NP_ADV_MAX_SECTION_LEN: usize = BLE_ADV_SVC_CONTENT_LEN
- // adv header byte
- - 1;
+/// Maximum size of a NP section, including its length header byte
+pub const NP_ADV_MAX_SECTION_LEN: usize = NP_ADV_MAX_SECTION_CONTENTS_LEN + 1;
+
+// TODO should this be 255 (or 256, if we +1 the length)?
+/// Maximum hypothetical size of a NP section's contents, excluding its header
+/// byte. This is longer than can fit in a BLE 5 extended adv, but other media
+/// could fit it, like mDNS.
+const NP_ADV_MAX_SECTION_CONTENTS_LEN: usize = 255;
+
+/// Size of a V1 identity token
+pub const V1_IDENTITY_TOKEN_LEN: usize = 16;
+
+// 4-bit encoding ids
+/// Encoding ID for unencrypted sections with no salt
+pub const V1_ENCODING_UNENCRYPTED: u8 = 0x00;
+/// Encoding ID for encrypted sections with a MIC and a short salt
+pub const V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN: u8 = 0x01;
+/// Encoding ID for encrypted sections with a MIC and an extended salt
+pub const V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN: u8 = 0x02;
+/// Encoding ID for encrypted sections with a signature and an extended salt
+pub const V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN: u8 = 0x03;
+
+// The maximum de length that fits into a non-extended de header
+const MAX_NON_EXTENDED_LEN: u8 = 7;
+// The maximum type code that fits into a non-extended de header
+const MAX_NON_EXTENDED_TYPE_CODE: u32 = 15;
+
+fn de_requires_extended_bit(type_code: u32, de_len: u8) -> bool {
+ de_len > MAX_NON_EXTENDED_LEN || type_code > MAX_NON_EXTENDED_TYPE_CODE
+}
+
+/// 16-byte plaintext identity token.
+///
+/// Identity tokens are present in encrypted form in a section's header.
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub struct V1IdentityToken([u8; V1_IDENTITY_TOKEN_LEN]);
+
+impl From<[u8; V1_IDENTITY_TOKEN_LEN]> for V1IdentityToken {
+ fn from(value: [u8; V1_IDENTITY_TOKEN_LEN]) -> Self {
+ Self(value)
+ }
+}
+
+impl V1IdentityToken {
+ /// Returns a reference to the inner byte array
+ pub fn bytes(&self) -> &[u8; V1_IDENTITY_TOKEN_LEN] {
+ &self.0
+ }
+
+ /// Returns the inner byte array
+ pub const fn into_bytes(self) -> [u8; V1_IDENTITY_TOKEN_LEN] {
+ self.0
+ }
+
+ /// Returns the token bytes as a slice
+ pub fn as_slice(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl AsRef<[u8]> for V1IdentityToken {
+ fn as_ref(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl crypto_provider::FromCryptoRng for V1IdentityToken {
+ fn new_random<R: CryptoRng>(rng: &mut R) -> Self {
+ Self(rng.gen())
+ }
+}
/// Max V1 DE length (7 bit length field).
pub(crate) const MAX_DE_LEN: usize = 127;
-const METADATA_KEY_LEN: usize = 16;
-
/// Length of a DE's content -- must be in `[0, 127]`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct DeLength {
@@ -82,7 +149,7 @@ impl TryFrom<usize> for DeLength {
}
/// Convert a tinyvec into an equivalent ArrayView
-fn to_array_view<T, const N: usize>(vec: tinyvec::ArrayVec<[T; N]>) -> ArrayView<T, N>
+pub(crate) fn to_array_view<T, const N: usize>(vec: tinyvec::ArrayVec<[T; N]>) -> ArrayView<T, N>
where
[T; N]: tinyvec::Array,
{
@@ -90,4 +157,15 @@ where
ArrayView::try_from_array(vec.into_inner(), len).expect("len is from original vec")
}
-pub(crate) const ENCRYPTION_INFO_DE_TYPE: DeType = DeType::const_from(0x10);
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use rand::{distributions, Rng};
+
+ // support randomly generating tokens just for tests
+ impl distributions::Distribution<V1IdentityToken> for distributions::Standard {
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> V1IdentityToken {
+ V1IdentityToken::from(rng.gen::<[u8; V1_IDENTITY_TOKEN_LEN]>())
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/salt.rs b/nearby/presence/np_adv/src/extended/salt.rs
new file mode 100644
index 0000000..b35275f
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/salt.rs
@@ -0,0 +1,113 @@
+// 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.
+
+//! Various representations of salts for extended advertisements.
+
+use nom::combinator;
+
+use crypto_provider::{aes::ctr::AesCtrNonce, CryptoProvider, CryptoRng, FromCryptoRng};
+use np_hkdf::v1_salt::ExtendedV1Salt;
+
+use crate::helpers::parse_byte_array;
+
+/// Common behavior for V1 section salts.
+pub trait V1Salt: Copy + Into<MultiSalt> {
+ /// Derive the nonce used for section encryption.
+ ///
+ /// Both kinds of salts can compute the nonce needed for de/encrypting a
+ /// section, but only extended salts can have data derived from them.
+ fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce;
+}
+
+impl V1Salt for ExtendedV1Salt {
+ fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
+ self.derive::<12, C>(None).expect("AES-CTR nonce is a valid HKDF size")
+ }
+}
+
+pub(crate) const SHORT_SALT_LEN: usize = 2;
+
+/// A byte buffer the size of a V1 short salt
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct ShortV1Salt([u8; SHORT_SALT_LEN]);
+
+impl From<[u8; SHORT_SALT_LEN]> for ShortV1Salt {
+ fn from(value: [u8; SHORT_SALT_LEN]) -> Self {
+ Self(value)
+ }
+}
+
+impl ShortV1Salt {
+ pub(crate) fn bytes(&self) -> &[u8; SHORT_SALT_LEN] {
+ &self.0
+ }
+
+ pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Self> {
+ combinator::map(parse_byte_array::<SHORT_SALT_LEN>, Self)(input)
+ }
+}
+
+impl V1Salt for ShortV1Salt {
+ fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
+ np_hkdf::extended_mic_section_short_salt_nonce::<C>(self.0)
+ }
+}
+
+impl FromCryptoRng for ShortV1Salt {
+ fn new_random<R: CryptoRng>(rng: &mut R) -> Self {
+ rng.gen::<[u8; SHORT_SALT_LEN]>().into()
+ }
+}
+
+/// Either a short or extended salt.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum MultiSalt {
+ /// A 2-byte salt
+ Short(ShortV1Salt),
+ /// A 16-byte salt
+ Extended(ExtendedV1Salt),
+}
+
+impl MultiSalt {
+ /// Salt bytes as a slice, for when variable-size access is sensible
+ pub fn as_slice(&self) -> &[u8] {
+ match self {
+ MultiSalt::Short(s) => s.bytes().as_slice(),
+ MultiSalt::Extended(s) => s.bytes().as_slice(),
+ }
+ }
+}
+
+impl From<ExtendedV1Salt> for MultiSalt {
+ fn from(value: ExtendedV1Salt) -> Self {
+ Self::Extended(value)
+ }
+}
+
+impl From<ShortV1Salt> for MultiSalt {
+ fn from(value: ShortV1Salt) -> Self {
+ Self::Short(value)
+ }
+}
+
+impl V1Salt for MultiSalt {
+ /// Both kinds of salts can compute the nonce needed for decrypting an
+ /// advertisement, but only extended salts can have data derived from them.
+ fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
+ match self {
+ Self::Short(s) => V1Salt::compute_nonce::<C>(s),
+ Self::Extended(s) => s.compute_nonce::<C>(),
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/section_signature_payload.rs b/nearby/presence/np_adv/src/extended/section_signature_payload.rs
index d8ec93c..3cdaead 100644
--- a/nearby/presence/np_adv/src/extended/section_signature_payload.rs
+++ b/nearby/presence/np_adv/src/extended/section_signature_payload.rs
@@ -16,40 +16,31 @@
//! after the included context bytes, and utilities for
//! performing signatures and signature verification.
-use crate::extended::deserialize::EncryptionInfo;
-use crate::MetadataKey;
-use crate::NP_SVC_UUID;
-use crypto_provider::{aes::ctr::AesCtrNonce, CryptoProvider};
+use crate::header::VERSION_HEADER_V1;
+use crypto_provider::{
+ aes::ctr::AesCtrNonce,
+ ed25519::{Ed25519Provider, PrivateKey, PublicKey, Signature},
+};
use sink::{Sink, SinkWriter};
+use crate::NP_SVC_UUID;
+
/// A struct representing the necessary contents
/// of an v1 advertisement section np_ed25519 signature payload which
/// come after the context prefix (shared among all advs).
pub(crate) struct SectionSignaturePayload<'a> {
- /// Advertisement header byte
- adv_header_byte: u8,
- /// Header byte for the v1 section being signed
- section_header: u8,
- /// Reference to the complete contents of the [`EncryptionInfo`] DE.
- encryption_info: &'a [u8; EncryptionInfo::TOTAL_DE_LEN],
- /// Reference to the derived salt (IV) for the section
- nonce_ref: &'a AesCtrNonce,
- /// Reference to all remaining information after the derived salt, but
- /// not including the signature itself [which gets tacked onto the end].
- after_iv_info: AfterIVInfo<'a>,
-}
-
-/// Representation of the plaintext information in an advertisement
-/// signature payload which comes after the derived salt
-enum AfterIVInfo<'a> {
- /// Reference to a raw byte array containing all information
- /// to be included in the signature payload after the derived salt,
- /// and before the signature itself.
- Raw(&'a [u8]),
- /// Plaintext identity DE header followed by the metadata key,
- /// then the rest of the section plaintext (including
- /// the plaintext identity DE payload).
- IdentityHeaderMetadataKeyAndRemainder([u8; 2], MetadataKey, &'a [u8]),
+ /// first 1-2 bytes of format
+ format_bytes: &'a [u8],
+ /// Salt bytes
+ salt_bytes: &'a [u8],
+ /// Nonce for en/decrypting the section
+ nonce: &'a AesCtrNonce,
+ /// plaintext identity token
+ plaintext_identity_token: &'a [u8],
+ /// the len of the rest of the section contents stored as an u8
+ section_payload_len: u8,
+ /// plaintext identity token
+ plaintext_data_elements: &'a [u8],
}
const ADV_SIGNATURE_CONTEXT: np_ed25519::SignatureContext = {
@@ -60,66 +51,48 @@ const ADV_SIGNATURE_CONTEXT: np_ed25519::SignatureContext = {
};
impl<'a> SectionSignaturePayload<'a> {
- /// Construct a section signature payload using parts typically found during
- /// deserialization of advertisements.
- pub(crate) fn from_deserialized_parts(
- adv_header_byte: u8,
- section_header: u8,
- encryption_info: &'a [u8; EncryptionInfo::TOTAL_DE_LEN],
- nonce_ref: &'a AesCtrNonce,
- identity_header: [u8; 2],
- plaintext_metadata_key: MetadataKey,
- raw_plaintext_remainder: &'a [u8],
+ /// Construct a section signature payload with separate section len and
+ /// remaining contents of the section header.
+ ///
+ /// The section header should be in its on-the-wire form.
+ pub(crate) fn new(
+ format_bytes: &'a [u8],
+ salt_bytes: &'a [u8],
+ nonce: &'a AesCtrNonce,
+ plaintext_identity_token: &'a [u8],
+ section_payload_len: u8,
+ plaintext_data_elements: &'a [u8],
) -> Self {
Self {
- adv_header_byte,
- section_header,
- encryption_info,
- nonce_ref,
- after_iv_info: AfterIVInfo::IdentityHeaderMetadataKeyAndRemainder(
- identity_header,
- plaintext_metadata_key,
- raw_plaintext_remainder,
- ),
- }
- }
-
- /// Construct a section signature payload using parts typically found during
- /// serialization of advertisements.
- pub(crate) fn from_serialized_parts(
- adv_header_byte: u8,
- section_header: u8,
- encryption_info: &'a [u8; EncryptionInfo::TOTAL_DE_LEN],
- nonce_ref: &'a AesCtrNonce,
- raw_after_iv_info: &'a [u8],
- ) -> Self {
- Self {
- adv_header_byte,
- section_header,
- encryption_info,
- nonce_ref,
- after_iv_info: AfterIVInfo::Raw(raw_after_iv_info),
+ format_bytes,
+ salt_bytes,
+ nonce,
+ plaintext_identity_token,
+ section_payload_len,
+ plaintext_data_elements,
}
}
/// Generates a signature for this section signing payload using
/// the given Ed25519 key-pair.
- pub(crate) fn sign<C: CryptoProvider>(
- self,
- key_pair: &np_ed25519::KeyPair<C>,
- ) -> np_ed25519::Signature<C> {
- key_pair
- .sign_with_context(&ADV_SIGNATURE_CONTEXT, self)
+ pub(crate) fn sign<E: Ed25519Provider>(self, private_key: &PrivateKey) -> Signature {
+ np_ed25519::sign_with_context::<E, _>(private_key, &ADV_SIGNATURE_CONTEXT, self)
.expect("section signature payloads should fit in signature buffer")
}
+
/// Verifies a signature for this section signing payload using
/// the given Ed25519 public key.
- pub(crate) fn verify<C: CryptoProvider>(
+ pub(crate) fn verify<E: Ed25519Provider>(
self,
- signature: &np_ed25519::Signature<C>,
- public_key: &np_ed25519::PublicKey<C>,
+ signature: Signature,
+ public_key: &PublicKey,
) -> Result<(), np_ed25519::SignatureVerificationError> {
- public_key.verify_signature_with_context(&ADV_SIGNATURE_CONTEXT, self, signature)
+ np_ed25519::verify_signature_with_context::<E, _>(
+ public_key,
+ &ADV_SIGNATURE_CONTEXT,
+ self,
+ signature,
+ )
}
}
@@ -128,23 +101,12 @@ impl<'a> SinkWriter for SectionSignaturePayload<'a> {
fn write_payload<S: Sink<u8> + ?Sized>(self, sink: &mut S) -> Option<()> {
sink.try_extend_from_slice(&NP_SVC_UUID)?;
- sink.try_push(self.adv_header_byte)?;
- sink.try_push(self.section_header)?;
- sink.try_extend_from_slice(self.encryption_info)?;
- sink.try_extend_from_slice(self.nonce_ref)?;
-
- // identity DE and the rest of the DEs except for the suffix
- match self.after_iv_info {
- AfterIVInfo::Raw(s) => sink.try_extend_from_slice(s),
- AfterIVInfo::IdentityHeaderMetadataKeyAndRemainder(
- identity_header,
- metadata_key,
- remainder,
- ) => {
- sink.try_extend_from_slice(&identity_header)?;
- sink.try_extend_from_slice(&metadata_key.0)?;
- sink.try_extend_from_slice(remainder)
- }
- }
+ sink.try_push(VERSION_HEADER_V1)?;
+ sink.try_extend_from_slice(self.format_bytes)?;
+ sink.try_extend_from_slice(self.salt_bytes)?;
+ sink.try_extend_from_slice(self.nonce)?;
+ sink.try_extend_from_slice(self.plaintext_identity_token)?;
+ sink.try_push(self.section_payload_len)?;
+ sink.try_extend_from_slice(self.plaintext_data_elements)
}
}
diff --git a/nearby/presence/np_adv/src/extended/serialize/adv_tests.rs b/nearby/presence/np_adv/src/extended/serialize/adv_tests.rs
index ee44c75..f094992 100644
--- a/nearby/presence/np_adv/src/extended/serialize/adv_tests.rs
+++ b/nearby/presence/np_adv/src/extended/serialize/adv_tests.rs
@@ -16,92 +16,107 @@
extern crate std;
use super::*;
+use crate::extended::serialize::section::header::SectionHeader;
use crate::extended::serialize::section_tests::{fill_section_builder, DummyDataElement};
-use np_hkdf::v1_salt::DataElementOffset;
+use crate::extended::V1_ENCODING_UNENCRYPTED;
+use crypto_provider_default::CryptoProviderImpl;
use std::{prelude::rust_2021::*, vec};
#[test]
-fn adv_encode_no_salt() {
+fn adv_encode_unencrypted() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
let mut public_identity_section_builder =
- adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
public_identity_section_builder
.add_de(|_| DummyDataElement { de_type: 30_u32.into(), data: vec![] })
.unwrap();
- public_identity_section_builder.add_to_advertisement();
+ public_identity_section_builder.add_to_advertisement::<CryptoProviderImpl>();
assert_eq!(
&[
- 0x20, // adv header
- 0x3, // section header
- 0x3, // public identity
- 0x80, 30, // de header
+ 0x20, // NP version header
+ V1_ENCODING_UNENCRYPTED,
+ 0x02, // section len
+ 0x80, // de header, 0 length
+ 30,
],
adv_builder.into_advertisement().as_slice()
)
}
#[test]
-fn adding_any_allowed_section_length_always_works_for_single_section() {
- // up to section len - 1 to leave room for section header
- for section_contents_len in 0..NP_ADV_MAX_SECTION_LEN - 1 {
+fn adding_any_ble5_allowed_section_length_always_works_for_single_section() {
+ // up to section len - 2 to leave room for NP version header, section length,
+ // and header
+ for section_contents_len in 0..=BLE_5_ADV_SVC_MAX_CONTENT_LEN - 3 {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder =
- adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
- fill_section_builder(section_contents_len, &mut section_builder);
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
+ fill_section_builder(section_contents_len, &mut section_builder).unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
assert_eq!(
- section_contents_len + 1 + 1 + 1, // adv and section headers and identity
+ section_contents_len + 1 + 1 + 1, // NP version header, section length, section header
adv.as_slice().len(),
"adv: {:?}\nsection contents len: {}",
adv.as_slice(),
section_contents_len
);
}
+
+ // one longer won't fit, though
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
+ assert_eq!(
+ AddDataElementError::InsufficientSectionSpace,
+ fill_section_builder(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 2, &mut section_builder).unwrap_err()
+ );
}
#[test]
-fn building_capacity_0_section_works() {
+fn building_capacity_0_ble5_section_works() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
- // leave room for section header and the public identity
- fill_section_builder(NP_ADV_MAX_SECTION_LEN - 2, &mut section_builder);
+ // leave room for NP version header, section length and header
+ fill_section_builder(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 3, &mut section_builder).unwrap();
- assert_eq!(NP_ADV_MAX_SECTION_LEN, section_builder.section.capacity);
- assert_eq!(NP_ADV_MAX_SECTION_LEN, section_builder.section.len());
+ // this section can fill everything except the NP version header
+ assert_eq!(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 1, section_builder.section.capacity);
+ assert_eq!(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 1, section_builder.section.len());
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
- assert_eq!(BLE_ADV_SVC_CONTENT_LEN, adv_builder.into_advertisement().as_slice().len());
+ assert_eq!(BLE_5_ADV_SVC_MAX_CONTENT_LEN, adv_builder.into_advertisement().as_slice().len());
}
+// TODO tests for other encoding types interacting with maximum possible section len
+
/// A placeholder identity with a huge prefix
#[derive(Default, PartialEq, Eq, Debug)]
struct EnormousIdentity {}
impl SectionEncoder for EnormousIdentity {
- const PREFIX_LEN: usize = 200;
const SUFFIX_LEN: usize = 0;
- const INITIAL_DE_OFFSET: DataElementOffset = DataElementOffset::ZERO;
const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Plaintext;
+ type DerivedSalt = ();
- fn postprocess(
+ fn header(&self) -> SectionHeader {
+ unimplemented!("Should never be hit")
+ }
+ fn postprocess<C: CryptoProvider>(
&mut self,
- _adv_header_byte: u8,
- _section_header: u8,
- _section_contents: &mut [u8],
+ _section_header_without_length: &mut [u8],
+ _section_len: u8,
+ _remaining_content_bytes: &mut [u8],
) {
panic!("should never be called, just used for its huge prefix")
}
- type DerivedSalt = ();
fn de_salt(&self, _de_offset: DataElementOffset) -> Self::DerivedSalt {
panic!("should never be called, just used for its huge prefix")
}
diff --git a/nearby/presence/np_adv/src/extended/serialize/de_header_tests.rs b/nearby/presence/np_adv/src/extended/serialize/de_header_tests.rs
index cb6c9ef..515ae97 100644
--- a/nearby/presence/np_adv/src/extended/serialize/de_header_tests.rs
+++ b/nearby/presence/np_adv/src/extended/serialize/de_header_tests.rs
@@ -17,7 +17,6 @@
use super::*;
use crate::extended::deserialize;
use core::cmp;
-use rand_ext::rand;
use rand_ext::rand::{distributions, Rng as _};
#[test]
@@ -69,10 +68,14 @@ fn de_header_special_values() {
assert_eq!(header_len as usize, buf.len());
- let (_, deser) = deserialize::DeHeader::parse(buf.as_slice()).unwrap();
+ let (_, deser) = deserialize::data_element::DeHeader::parse(buf.as_slice()).unwrap();
assert_eq!(
- deserialize::DeHeader { de_type, contents_len: len, header_bytes: buf },
+ deserialize::data_element::DeHeader {
+ de_type,
+ contents_len: len,
+ header_bytes: buf
+ },
deser
)
}
@@ -89,10 +92,10 @@ fn de_header_random_roundtrip() {
let header_len = expected_header_len(hdr);
assert_eq!(header_len as usize, buf.len());
- let (_, deser) = deserialize::DeHeader::parse(buf.as_slice()).unwrap();
+ let (_, deser) = deserialize::data_element::DeHeader::parse(buf.as_slice()).unwrap();
assert_eq!(
- deserialize::DeHeader {
+ deserialize::data_element::DeHeader {
de_type: hdr.de_type,
contents_len: hdr.len,
header_bytes: buf
diff --git a/nearby/presence/np_adv/src/extended/serialize/mod.rs b/nearby/presence/np_adv/src/extended/serialize/mod.rs
index 9d82273..d94fee2 100644
--- a/nearby/presence/np_adv/src/extended/serialize/mod.rs
+++ b/nearby/presence/np_adv/src/extended/serialize/mod.rs
@@ -19,15 +19,15 @@
//! Serialize some DEs without an adv salt:
//!
//! ```
+//! use crypto_provider_default::CryptoProviderImpl;
//! use np_adv::{
-//! extended::{data_elements::*, serialize::*, de_type::DeType },
-//! PublicIdentity
+//! extended::{data_elements::*, serialize::*, de_type::DeType, V1_ENCODING_UNENCRYPTED},
+//! shared_data::TxPower
//! };
-//! use np_adv::shared_data::TxPower;
//!
//! // no section identities or DEs need salt in this example
//! let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
-//! let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+//! let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
//!
//! section_builder.add_de(|_salt| TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
//!
@@ -36,13 +36,13 @@
//! GenericDataElement::try_from( DeType::from(1000_u32), &[10, 11, 12, 13])
//! ).unwrap();
//!
-//! section_builder.add_to_advertisement();
+//! section_builder.add_to_advertisement::<CryptoProviderImpl>();
//!
//! assert_eq!(
//! &[
-//! 0x20, // adv header
-//! 10, // section header
-//! 0x03, // public identity
+//! 0x20, // version header
+//! V1_ENCODING_UNENCRYPTED, //section format
+//! 0x09, // section length
//! 0x15, 3, // tx power
//! 0x84, 0x87, 0x68, 10, 11, 12, 13, // other DE
//! ],
@@ -54,34 +54,32 @@
//!
//! ```
//! use np_adv::{
-//! credential::{SimpleBroadcastCryptoMaterial, v1::V1},
-//! de_type::EncryptedIdentityDataElementType,
-//! extended::{data_elements::*, serialize::*, de_type::DeType },
-//! MetadataKey,
+//! credential::{ v1::{V1, V1BroadcastCredential}},
+//! extended::{data_elements::*, serialize::*, de_type::DeType, V1IdentityToken },
//! };
//! use rand::{Rng as _, SeedableRng as _};
-//! use crypto_provider::{CryptoProvider, CryptoRng};
+//! use crypto_provider::{CryptoProvider, CryptoRng, ed25519};
//! use crypto_provider_default::CryptoProviderImpl;
//! use np_adv::shared_data::TxPower;
//!
//! let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
//!
-//! // these would come from the credential//!
+//! // these would come from the credential
+//!
//! let mut rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
-//! let metadata_key: [u8; 16] = rng.gen();
-//! let metadata_key = MetadataKey(metadata_key);
+//! let identity_token = rng.gen();
//! let key_seed: [u8; 32] = rng.gen();
//! // use your preferred crypto impl
//! let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
//!
-//! let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(
+//! let broadcast_cm = V1BroadcastCredential::new(
//! key_seed,
-//! metadata_key,
+//! identity_token,
+//! ed25519::PrivateKey::generate::<<CryptoProviderImpl as CryptoProvider>::Ed25519>(),
//! );
//!
-//! let mut section_builder = adv_builder.section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+//! let mut section_builder = adv_builder.section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<CryptoProviderImpl>(
//! &mut rng,
-//! EncryptedIdentityDataElementType::Private,
//! &broadcast_cm,
//! )).unwrap();
//!
@@ -91,10 +89,10 @@
//! section_builder.add_de_res(|salt|
//! GenericDataElement::try_from(
//! DeType::from(1000_u32),
-//! &do_fancy_crypto(salt.derive::<16>().expect("16 is a valid HKDF length")))
+//! &do_fancy_crypto(salt.derive::<16, CryptoProviderImpl>().expect("16 is a valid HKDF length")))
//! ).unwrap();
//!
-//! section_builder.add_to_advertisement();
+//! section_builder.add_to_advertisement::<CryptoProviderImpl>();
//!
//! // can't assert much about this since most of it is random
//! assert_eq!(
@@ -111,35 +109,32 @@
//! .try_into().expect("array sizes match")
//! }
//! ```
-use crate::extended::{NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT, NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT};
-use crate::{
- credential::{
- v1::{SignedBroadcastCryptoMaterial, V1},
- BroadcastCryptoMaterial,
- },
- de_type::{EncryptedIdentityDataElementType, IdentityDataElementType},
- extended::{
- data_elements::EncryptionInfoDataElement,
- de_type::{DeType, ExtendedDataElementType},
- deserialize::{EncryptedIdentityMetadata, EncryptionInfo, SectionMic},
- section_signature_payload::*,
- to_array_view, DeLength, BLE_ADV_SVC_CONTENT_LEN, NP_ADV_MAX_SECTION_LEN,
- },
- DeLengthOutOfRange, MetadataKey, NP_SVC_UUID,
-};
-use array_view::ArrayView;
use core::fmt::{self, Display};
-use crypto_provider::{
- aes::{
- ctr::{AesCtr, AesCtrNonce, NonceAndCounter},
- Aes128Key,
+
+use array_view::ArrayView;
+use crypto_provider::CryptoProvider;
+use np_hkdf::v1_salt::{DataElementOffset, ExtendedV1Salt};
+use sink::Sink;
+
+use crate::extended::{
+ de_requires_extended_bit, de_type::DeType, serialize::section::EncodedSection, to_array_view,
+ DeLength, BLE_5_ADV_SVC_MAX_CONTENT_LEN, NP_ADV_MAX_SECTION_LEN,
+ NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT, NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT,
+};
+
+mod section;
+
+use crate::header::VERSION_HEADER_V1;
+pub use section::{
+ encoder::{
+ MicEncryptedSectionEncoder, SectionEncoder, SignedEncryptedSectionEncoder,
+ UnencryptedSectionEncoder,
},
- hmac::Hmac,
- CryptoProvider, CryptoRng,
+ AddDataElementError, SectionBuilder,
};
-use np_hkdf::v1_salt;
-use np_hkdf::v1_salt::{DataElementOffset, V1Salt};
-use sink::Sink;
+
+#[cfg(test)]
+use crate::header::V1AdvHeader;
#[cfg(test)]
pub(crate) mod adv_tests;
@@ -153,8 +148,9 @@ mod test_vectors;
/// Builder for V1 advertisements.
#[derive(Debug)]
pub struct AdvBuilder {
+ // TODO make this configurable, and test making sections whose length is not restricted by BLE limitations
/// Contains the adv header byte
- adv: tinyvec::ArrayVec<[u8; BLE_ADV_SVC_CONTENT_LEN]>,
+ adv: tinyvec::ArrayVec<[u8; BLE_5_ADV_SVC_MAX_CONTENT_LEN]>,
/// To track the number of sections that are in the advertisement
section_count: usize,
/// Advertisement type: Public or Encrypted
@@ -171,46 +167,10 @@ impl AdvBuilder {
/// Build an [AdvBuilder].
pub fn new(advertisement_type: AdvertisementType) -> Self {
let mut adv = tinyvec::ArrayVec::new();
- // version 1, 0bVVVRRRRR
- adv.push(0b00100000);
+ adv.push(VERSION_HEADER_V1);
Self { adv, section_count: 0, advertisement_type }
}
- fn prepare_section_builder_buffer_and_de_offset<SE: SectionEncoder>(
- &self,
- ) -> Result<(CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>, DataElementOffset), AddSectionError>
- {
- // section header and identity prefix
- let prefix_len = 1 + SE::PREFIX_LEN;
- let minimum_section_len = prefix_len + SE::SUFFIX_LEN;
- // the max overall len available to the section
- let available_len = self.adv.capacity() - self.adv.len();
-
- if available_len < minimum_section_len {
- return Err(AddSectionError::InsufficientAdvSpace);
- }
-
- if self.section_count >= self.advertisement_type.max_sections() {
- return Err(AddSectionError::MaxSectionCountExceeded);
- }
-
- if self.advertisement_type != SE::ADVERTISEMENT_TYPE {
- return Err(AddSectionError::IncompatibleSectionType);
- }
-
- let mut section: tinyvec::ArrayVec<[u8; 249]> = tinyvec::ArrayVec::new();
- // placeholder for section header and identity prefix
- section.resize(prefix_len, 0);
-
- let section = CapacityLimitedVec {
- vec: section,
- // won't underflow: checked above
- capacity: available_len - SE::SUFFIX_LEN,
- };
- let next_de_offset = SE::INITIAL_DE_OFFSET;
- Ok((section, next_de_offset))
- }
-
/// Create a section builder whose contents may be added to this advertisement.
///
/// The builder will not accept more DEs than can fit given the space already used in the
@@ -222,10 +182,8 @@ impl AdvBuilder {
&mut self,
section_encoder: SE,
) -> Result<SectionBuilder<&mut AdvBuilder, SE>, AddSectionError> {
- let (section, next_de_offset) =
- self.prepare_section_builder_buffer_and_de_offset::<SE>()?;
-
- Ok(SectionBuilder { section, section_encoder, adv_builder: self, next_de_offset })
+ let (header_len, contents) = self.prepare_section_builder_buffer(&section_encoder)?;
+ Ok(SectionBuilder::new(header_len, contents, section_encoder, self))
}
/// Create a section builder which actually takes ownership of this advertisement builder.
@@ -239,9 +197,9 @@ impl AdvBuilder {
self,
section_encoder: SE,
) -> Result<SectionBuilder<AdvBuilder, SE>, (AdvBuilder, AddSectionError)> {
- match self.prepare_section_builder_buffer_and_de_offset::<SE>() {
- Ok((section, next_de_offset)) => {
- Ok(SectionBuilder { section, section_encoder, adv_builder: self, next_de_offset })
+ match self.prepare_section_builder_buffer::<SE>(&section_encoder) {
+ Ok((header_len, section)) => {
+ Ok(SectionBuilder::new(header_len, section, section_encoder, self))
}
Err(err) => Err((self, err)),
}
@@ -258,6 +216,37 @@ impl AdvBuilder {
self.section_count
}
+ /// Returns the length of the header (excluding the leading length byte),
+ /// and a buffer already populated with a placeholder section length byte and the rest
+ /// of the header.
+ fn prepare_section_builder_buffer<SE: SectionEncoder>(
+ &self,
+ section_encoder: &SE,
+ ) -> Result<(usize, CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>), AddSectionError> {
+ if self.section_count >= self.advertisement_type.max_sections() {
+ return Err(AddSectionError::MaxSectionCountExceeded);
+ }
+ if self.advertisement_type != SE::ADVERTISEMENT_TYPE {
+ return Err(AddSectionError::IncompatibleSectionType);
+ }
+
+ // The header contains all the header bytes except for the final length byte.
+ let header = section_encoder.header();
+ let header_slice = header.as_slice();
+
+ // the max overall len available to the section
+ let available_len = self.adv.capacity() - self.adv.len();
+
+ let mut prefix = available_len
+ .checked_sub(SE::SUFFIX_LEN)
+ .and_then(CapacityLimitedVec::new)
+ .ok_or(AddSectionError::InsufficientAdvSpace)?;
+ prefix.try_extend_from_slice(header_slice).ok_or(AddSectionError::InsufficientAdvSpace)?;
+ // Placeholder for section length, which we do not know yet
+ prefix.try_push(0).ok_or(AddSectionError::InsufficientAdvSpace)?;
+ Ok((header_slice.len(), prefix))
+ }
+
/// Add the section, which must have come from a SectionBuilder generated from this, into this
/// advertisement.
fn add_section(&mut self, section: EncodedSection) {
@@ -267,8 +256,9 @@ impl AdvBuilder {
self.section_count += 1;
}
- fn header_byte(&self) -> u8 {
- self.adv[0]
+ #[cfg(test)]
+ fn adv_header(&self) -> V1AdvHeader {
+ V1AdvHeader::new(self.adv[0])
}
}
@@ -287,7 +277,7 @@ impl Display for AddSectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AddSectionError::InsufficientAdvSpace => {
- write!(f, "The advertisement (max {BLE_ADV_SVC_CONTENT_LEN} bytes) doesn't have enough remaining space to hold the section")
+ write!(f, "The advertisement (max {BLE_5_ADV_SVC_MAX_CONTENT_LEN} bytes) doesn't have enough remaining space to hold the section")
}
AddSectionError::MaxSectionCountExceeded => {
write!(f, "The advertisement can only hold a maximum of {NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT} number of sections")
@@ -302,7 +292,7 @@ impl Display for AddSectionError {
/// An encoded NP V1 advertisement, starting with the NP advertisement header byte.
#[derive(Debug, PartialEq, Eq)]
pub struct EncodedAdvertisement {
- adv: ArrayView<u8, BLE_ADV_SVC_CONTENT_LEN>,
+ adv: ArrayView<u8, BLE_5_ADV_SVC_MAX_CONTENT_LEN>,
}
impl EncodedAdvertisement {
@@ -310,155 +300,13 @@ impl EncodedAdvertisement {
pub fn as_slice(&self) -> &[u8] {
self.adv.as_slice()
}
-}
-
-/// The encoded form of an advertisement section
-type EncodedSection = ArrayView<u8, NP_ADV_MAX_SECTION_LEN>;
-
-/// Accumulates data elements and encodes them into a section.
-#[derive(Debug)]
-pub struct SectionBuilder<R: AsMut<AdvBuilder>, SE: SectionEncoder> {
- /// Contains the section header, the identity-specified overhead, and any DEs added
- pub(crate) section: CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>,
- section_encoder: SE,
- /// mut ref-able to enforce only one active section builder at a time
- adv_builder: R,
- next_de_offset: DataElementOffset,
-}
-
-impl<'a, SE: SectionEncoder> SectionBuilder<&'a mut AdvBuilder, SE> {
- /// Add this builder to the advertisement that created it.
- pub fn add_to_advertisement(self) {
- let _ = self.add_to_advertisement_internal();
- }
-}
-
-impl<SE: SectionEncoder> SectionBuilder<AdvBuilder, SE> {
- /// Gets the 0-based index of the section currently under construction
- /// in the context of the containing advertisement.
- pub fn section_index(&self) -> usize {
- self.adv_builder.section_count()
- }
- /// Add this builder to the advertisement that created it,
- /// and returns the containing advertisement back to the caller.
- pub fn add_to_advertisement(self) -> AdvBuilder {
- self.add_to_advertisement_internal()
- }
-}
-
-impl<R: AsMut<AdvBuilder>, SE: SectionEncoder> SectionBuilder<R, SE> {
- /// Add this builder to the advertisement that created it.
- /// Returns the mut-refable to the advertisement builder
- /// which the contents of this section builder were added to.
- fn add_to_advertisement_internal(mut self) -> R {
- let adv_builder = self.adv_builder.as_mut();
- let adv_builder_header_byte = adv_builder.header_byte();
- adv_builder.add_section(Self::build_section(
- adv_builder_header_byte,
- self.section.into_inner(),
- self.section_encoder,
- ));
- self.adv_builder
- }
-
- /// Gets the derived salt which will be employed for the next DE offset.
- ///
- /// Suitable for scenarios (like FFI) where a closure would be inappropriate
- /// for DE construction, and interaction with the client is preferred.
- pub fn next_de_salt(&self) -> SE::DerivedSalt {
- self.section_encoder.de_salt(self.next_de_offset)
- }
-
- /// Add a data element to the section with a closure that returns a `Result`.
- ///
- /// The provided `build_de` closure will be invoked with the derived salt for this DE.
- pub fn add_de_res<W: WriteDataElement, E, F: FnOnce(SE::DerivedSalt) -> Result<W, E>>(
- &mut self,
- build_de: F,
- ) -> Result<(), AddDataElementError<E>> {
- let writer = build_de(self.next_de_salt()).map_err(AddDataElementError::BuildDeError)?;
-
- let orig_len = self.section.len();
- // since we own the writer, and it's immutable, no race risk writing header w/ len then
- // the contents as long as it's not simply an incorrect impl
- let de_header = writer.de_header();
- let content_len = self
- .section
- .try_extend_from_slice(de_header.serialize().as_slice())
- .ok_or(AddDataElementError::InsufficientSectionSpace)
- .and_then(|_| {
- let after_header_len = self.section.len();
- writer
- .write_de_contents(&mut self.section)
- .ok_or(AddDataElementError::InsufficientSectionSpace)
- .map(|_| self.section.len() - after_header_len)
- })
- .map_err(|e| {
- // if anything went wrong, truncate any partial writes (e.g. just the header)
- self.section.truncate(orig_len);
- e
- })?;
-
- if content_len != usize::from(de_header.len.as_u8()) {
- panic!(
- "Buggy WriteDataElement impl: header len {}, actual written len {}",
- de_header.len.as_u8(),
- content_len
- );
- }
-
- self.next_de_offset = self.next_de_offset.incremented();
-
- Ok(())
- }
-
- /// Add a data element to the section with a closure that returns the data element directly.
- ///
- /// The provided `build_de` closure will be invoked with the derived salt for this DE.
- pub fn add_de<W: WriteDataElement, F: FnOnce(SE::DerivedSalt) -> W>(
- &mut self,
- build_de: F,
- ) -> Result<(), AddDataElementError<()>> {
- self.add_de_res(|derived_salt| Ok::<_, ()>(build_de(derived_salt)))
- }
-
- /// Convert a section builder's contents into an encoded section.
- ///
- /// Implemented without self to avoid partial-move issues.
- fn build_section(
- adv_builder_header_byte: u8,
- mut section_contents: tinyvec::ArrayVec<[u8; NP_ADV_MAX_SECTION_LEN]>,
- mut section_encoder: SE,
- ) -> EncodedSection {
- // there is space because the capacity for DEs was restricted to allow it
- section_contents.resize(section_contents.len() + SE::SUFFIX_LEN, 0);
-
- section_contents[0] = section_contents
- .len()
- .try_into()
- .ok()
- .and_then(|len: u8| len.checked_sub(1))
- .expect("section length is always <=255 and non-negative");
-
- section_encoder.postprocess(
- adv_builder_header_byte,
- section_contents[0],
- &mut section_contents[1..],
- );
-
- to_array_view(section_contents)
+ /// Converts this encoded advertisement into
+ /// a raw byte-array.
+ pub fn into_array_view(self) -> ArrayView<u8, BLE_5_ADV_SVC_MAX_CONTENT_LEN> {
+ self.adv
}
}
-/// Errors for adding a DE to a section
-#[derive(Debug, PartialEq, Eq)]
-pub enum AddDataElementError<E> {
- /// An error occurred when invoking the DE builder closure.
- BuildDeError(E),
- /// Too much data to fit into the section
- InsufficientSectionSpace,
-}
-
/// The advertisement type, which dictates what sections can exist
#[derive(Debug, PartialEq, Eq)]
pub enum AdvertisementType {
@@ -477,294 +325,18 @@ impl AdvertisementType {
}
}
-/// Everything needed to properly encode a section
-pub trait SectionEncoder {
- /// How much space needs to be reserved for this identity's prefix bytes after the section
- /// header and before other DEs
- const PREFIX_LEN: usize;
-
- /// How much space needs to be reserved after the DEs
- const SUFFIX_LEN: usize;
-
- /// The DE offset to use for any DEs added to the section
- const INITIAL_DE_OFFSET: DataElementOffset;
-
- /// The advertisement type that can support this section
- const ADVERTISEMENT_TYPE: AdvertisementType;
-
- /// Postprocess the contents of the section (the data after the section header byte), which will
- /// start with [Self::PREFIX_LEN] bytes set aside for the identity's use, and similarly end with
- /// [Self::SUFFIX_LEN] bytes, with DEs (if any) in the middle.
- fn postprocess(&mut self, adv_header_byte: u8, section_header: u8, section_contents: &mut [u8]);
-
- /// The type of derived salt produced for a DE sharing a section with this identity.
- type DerivedSalt;
-
- /// Produce a `Self::Output` salt for a DE.
- fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt;
-}
-
-/// Public section for plaintext data elements
-#[derive(Default, Debug)]
-pub struct PublicSectionEncoder {}
-impl SectionEncoder for PublicSectionEncoder {
- /// 1 byte of public identity DE header
- const PREFIX_LEN: usize = 1;
- const SUFFIX_LEN: usize = 0;
- /// Room for the public DE
- const INITIAL_DE_OFFSET: DataElementOffset = DataElementOffset::ZERO.incremented();
- const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Plaintext;
- fn postprocess(
- &mut self,
- _adv_header_byte: u8,
- _section_header: u8,
- section_contents: &mut [u8],
- ) {
- section_contents[0..1].copy_from_slice(
- DeHeader { len: DeLength::ZERO, de_type: IdentityDataElementType::Public.type_code() }
- .serialize()
- .as_slice(),
- )
- }
- type DerivedSalt = ();
- fn de_salt(&self, _de_offset: DataElementOffset) -> Self::DerivedSalt {}
-}
-
-/// Encrypts the data elements and protects integrity with an np_ed25519 signature
-/// using key material derived from an NP identity.
-pub struct SignedEncryptedSectionEncoder<C: CryptoProvider> {
- identity_type: EncryptedIdentityDataElementType,
- salt: V1Salt<C>,
- metadata_key: MetadataKey,
- key_pair: np_ed25519::KeyPair<C>,
- aes_key: Aes128Key,
-}
-
-impl<C: CryptoProvider> SignedEncryptedSectionEncoder<C> {
- /// Build a [SignedEncryptedSectionEncoder] from an identity type,
- /// some broadcast crypto-material, and with a random salt.
- pub fn new_random_salt<B: SignedBroadcastCryptoMaterial>(
- rng: &mut C::CryptoRng,
- identity_type: EncryptedIdentityDataElementType,
- crypto_material: &B,
- ) -> Self {
- let salt: V1Salt<C> = rng.gen::<[u8; 16]>().into();
- Self::new(identity_type, salt, crypto_material)
- }
-
- /// Build a [SignedEncryptedSectionEncoder] from an identity type,
- /// a provided salt, and some broadcast crypto-material.
- pub(crate) fn new<B: SignedBroadcastCryptoMaterial>(
- identity_type: EncryptedIdentityDataElementType,
- salt: V1Salt<C>,
- crypto_material: &B,
- ) -> Self {
- let metadata_key = crypto_material.metadata_key();
- let key_seed = crypto_material.key_seed();
- let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
- let private_key = crypto_material.signing_key();
- let key_pair = np_ed25519::KeyPair::<C>::from_private_key(&private_key);
- let aes_key = key_seed_hkdf.extended_signed_section_aes_key();
- Self { identity_type, salt, metadata_key, key_pair, aes_key }
- }
-}
-
-impl<C: CryptoProvider> SectionEncoder for SignedEncryptedSectionEncoder<C> {
- const PREFIX_LEN: usize =
- EncryptionInfo::TOTAL_DE_LEN + EncryptedIdentityMetadata::TOTAL_DE_LEN;
- /// Ed25519 signature
- const SUFFIX_LEN: usize = crypto_provider::ed25519::SIGNATURE_LENGTH;
- /// Room for the encryption info and identity DEs
- const INITIAL_DE_OFFSET: DataElementOffset =
- DataElementOffset::ZERO.incremented().incremented();
- const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Encrypted;
-
- fn postprocess(
- &mut self,
- adv_header_byte: u8,
- section_header: u8,
- section_contents: &mut [u8],
- ) {
- let encryption_info_bytes = EncryptionInfoDataElement::signature(
- self.salt.as_slice().try_into().expect("Salt should be 16 bytes"),
- )
- .serialize();
- section_contents[0..19].copy_from_slice(&encryption_info_bytes);
-
- let identity_header = identity_de_header(self.identity_type, self.metadata_key);
- section_contents[19..21].copy_from_slice(identity_header.serialize().as_slice());
- section_contents[21..37].copy_from_slice(&self.metadata_key.0);
-
- let nonce: AesCtrNonce = self
- .de_salt(v1_salt::DataElementOffset::from(1))
- .derive()
- .expect("AES-CTR nonce is a valid HKDF length");
-
- let (before_sig, sig) =
- section_contents.split_at_mut(section_contents.len() - Self::SUFFIX_LEN);
- let (encryption_info, after_encryption_info) =
- before_sig.split_at(EncryptionInfo::TOTAL_DE_LEN);
-
- let encryption_info: &[u8; EncryptionInfo::TOTAL_DE_LEN] =
- encryption_info.try_into().expect("encryption info should always be the correct size");
-
- // we need to sign the 16-byte IV, which doesn't have to actually fit in the adv, but we
- // don't need a bigger buffer here since we won't be including the 66 bytes for the sig +
- // header.
- // If the stack usage ever becomes a problem, we can investigate pre hashing for the
- // signature.
- let nonce_ref = &nonce;
- let section_signature_payload = SectionSignaturePayload::from_serialized_parts(
- adv_header_byte,
- section_header,
- encryption_info,
- nonce_ref,
- after_encryption_info,
- );
-
- let signature = section_signature_payload.sign(&self.key_pair);
-
- sig[0..64].copy_from_slice(&signature.to_bytes());
-
- let mut cipher = C::AesCtr128::new(&self.aes_key, NonceAndCounter::from_nonce(nonce));
-
- // encrypt just the part that should be ciphertext: identity DE contents and subsequent DEs
- cipher.apply_keystream(&mut section_contents[21..]);
- }
-
- type DerivedSalt = DeSalt<C>;
-
- fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
- DeSalt { salt: V1Salt::from(*self.salt.as_array_ref()), de_offset }
- }
-}
-
-/// Encrypts the data elements and protects integrity with a MIC using key material derived from
-/// an NP identity.
-pub struct MicEncryptedSectionEncoder<C: CryptoProvider> {
- identity_type: EncryptedIdentityDataElementType,
- salt: V1Salt<C>,
- metadata_key: MetadataKey,
- aes_key: Aes128Key,
- mic_hmac_key: np_hkdf::NpHmacSha256Key<C>,
-}
-
-impl<C: CryptoProvider> MicEncryptedSectionEncoder<C> {
- /// Build a [MicEncryptedSectionEncoder] from the provided identity
- /// info with a random salt.
- pub fn new_random_salt<B: BroadcastCryptoMaterial<V1>>(
- rng: &mut C::CryptoRng,
- identity_type: EncryptedIdentityDataElementType,
- crypto_material: &B,
- ) -> Self {
- let salt: V1Salt<C> = rng.gen::<[u8; 16]>().into();
- Self::new(identity_type, salt, crypto_material)
- }
-
- /// Build a [MicEncryptedSectionEncoder] from the provided identity info.
- pub(crate) fn new<B: BroadcastCryptoMaterial<V1>>(
- identity_type: EncryptedIdentityDataElementType,
- salt: V1Salt<C>,
- crypto_material: &B,
- ) -> Self {
- let metadata_key = crypto_material.metadata_key();
- let key_seed = crypto_material.key_seed();
- let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
- let aes_key = np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf);
- let mic_hmac_key = np_hkdf::UnsignedSectionKeys::hmac_key(&key_seed_hkdf);
-
- Self { identity_type, salt, metadata_key, aes_key, mic_hmac_key }
- }
-
- /// Build a [MicEncrypedSectionEncoder] from the provided identity info.
- /// Exposed outside of this crate for testing purposes only, since this
- /// does not handle the generation of random salts.
- #[cfg(any(test, feature = "testing"))]
- pub fn new_for_testing<B: BroadcastCryptoMaterial<V1>>(
- identity_type: EncryptedIdentityDataElementType,
- salt: V1Salt<C>,
- crypto_material: &B,
- ) -> Self {
- Self::new(identity_type, salt, crypto_material)
- }
-}
-
-impl<C: CryptoProvider> SectionEncoder for MicEncryptedSectionEncoder<C> {
- const PREFIX_LEN: usize =
- EncryptionInfo::TOTAL_DE_LEN + EncryptedIdentityMetadata::TOTAL_DE_LEN;
- /// Length of mic
- const SUFFIX_LEN: usize = SectionMic::CONTENTS_LEN;
- /// Room for the mic, encryption info, and identity DEs
- const INITIAL_DE_OFFSET: DataElementOffset =
- DataElementOffset::ZERO.incremented().incremented();
-
- const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Encrypted;
-
- fn postprocess(
- &mut self,
- adv_header_byte: u8,
- section_header: u8,
- section_contents: &mut [u8],
- ) {
- // prefix byte layout:
- // 0-18: Encryption Info DE (header + scheme + salt)
- // 19-20: Identity DE header
- // 21-36: Identity DE contents (metadata key)
- // Encryption Info DE
- let encryption_info_bytes = EncryptionInfoDataElement::mic(
- self.salt.as_slice().try_into().expect("Salt should be 16 bytes"),
- )
- .serialize();
- section_contents[0..19].copy_from_slice(&encryption_info_bytes);
- // Identity DE
- let identity_header = identity_de_header(self.identity_type, self.metadata_key);
- section_contents[19..21].copy_from_slice(identity_header.serialize().as_slice());
- section_contents[21..37].copy_from_slice(&self.metadata_key.0);
- // DE offset for identity is 1: Encryption Info DE, Identity DE, then other DEs
- let nonce: AesCtrNonce = self
- .de_salt(v1_salt::DataElementOffset::from(1))
- .derive()
- .expect("AES-CTR nonce is a valid HKDF length");
- let mut cipher = C::AesCtr128::new(&self.aes_key, NonceAndCounter::from_nonce(nonce));
- let ciphertext_end = section_contents.len() - SectionMic::CONTENTS_LEN;
- // encrypt just the part that should be ciphertext: identity DE contents and subsequent DEs
- cipher.apply_keystream(&mut section_contents[21..ciphertext_end]);
- // calculate MAC per the spec
- let mut section_hmac = self.mic_hmac_key.build_hmac();
- // svc uuid
- section_hmac.update(NP_SVC_UUID.as_slice());
- // adv header
- section_hmac.update(&[adv_header_byte]);
- // section header
- section_hmac.update(&[section_header]);
- // encryption info
- section_hmac.update(&encryption_info_bytes);
- // derived salt
- section_hmac.update(&nonce);
- // identity header + ciphertext
- section_hmac.update(&section_contents[19..ciphertext_end]);
- let mic: [u8; 32] = section_hmac.finalize();
- // write truncated MIC
- section_contents[ciphertext_end..].copy_from_slice(&mic[..SectionMic::CONTENTS_LEN]);
- }
- type DerivedSalt = DeSalt<C>;
- fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
- DeSalt { salt: V1Salt::from(*self.salt.as_array_ref()), de_offset }
- }
-}
-
/// Derived salt for an individual data element.
-pub struct DeSalt<C: CryptoProvider> {
- salt: V1Salt<C>,
+pub struct DeSalt {
+ salt: ExtendedV1Salt,
de_offset: DataElementOffset,
}
-impl<C: CryptoProvider> DeSalt<C> {
+impl DeSalt {
/// Derive salt of the requested length.
///
/// The length must be a valid HKDF-SHA256 length.
- pub fn derive<const N: usize>(&self) -> Option<[u8; N]> {
- self.salt.derive(Some(self.de_offset))
+ pub fn derive<const N: usize, C: CryptoProvider>(&self) -> Option<[u8; N]> {
+ self.salt.derive::<N, C>(Some(self.de_offset))
}
}
@@ -823,7 +395,7 @@ impl DeHeader {
let de_type = self.de_type.as_u32();
let hi_bit = 0x80_u8;
let len = self.len.len;
- if len < 8 && de_type < 16 {
+ if !de_requires_extended_bit(de_type, len) {
buffer[0] = len << 4 | de_type as u8;
ArrayView::try_from_array(buffer, 1).expect("1 is a valid length")
} else {
@@ -867,22 +439,6 @@ impl DeHeader {
}
}
-fn identity_de_header(
- id_type: EncryptedIdentityDataElementType,
- metadata_key: MetadataKey,
-) -> DeHeader {
- DeHeader {
- de_type: id_type.type_code(),
- len: metadata_key
- .0
- .len()
- .try_into()
- .map_err(|_e| DeLengthOutOfRange)
- .and_then(|len: u8| len.try_into())
- .expect("metadata key is a valid DE length"),
- }
-}
-
/// A wrapper around a fixed-size tinyvec that can have its capacity further constrained to handle
/// dynamic size limits.
#[derive(Debug)]
@@ -893,7 +449,7 @@ where
<[T; N] as tinyvec::Array>::Item: fmt::Debug + Clone,
{
/// constraint on the occupied space in `vec`.
- /// Invariant: `vec.len() <= constraint` and `vec.capacity() >= capacity`.
+ /// Invariant: `vec.len() <= capacity` and `vec.capacity() >= capacity`.
capacity: usize,
vec: tinyvec::ArrayVec<[T; N]>,
}
@@ -904,6 +460,15 @@ where
[T; N]: tinyvec::Array + fmt::Debug,
<[T; N] as tinyvec::Array>::Item: fmt::Debug + Clone,
{
+ /// Returns `None` if `capacity > N`
+ pub(crate) fn new(capacity: usize) -> Option<Self> {
+ if capacity <= N {
+ Some(Self { capacity, vec: tinyvec::ArrayVec::new() })
+ } else {
+ None
+ }
+ }
+
pub(crate) fn len(&self) -> usize {
self.vec.len()
}
@@ -916,7 +481,7 @@ where
self.vec.truncate(len);
}
- fn into_inner(self) -> tinyvec::ArrayVec<[T; N]> {
+ pub(crate) fn into_inner(self) -> tinyvec::ArrayVec<[T; N]> {
self.vec
}
}
@@ -946,24 +511,3 @@ where
}
}
}
-
-impl<T, const N: usize> AsRef<[<[T; N] as tinyvec::Array>::Item]> for CapacityLimitedVec<T, N>
-where
- T: fmt::Debug + Clone,
- [T; N]: tinyvec::Array + fmt::Debug,
- <[T; N] as tinyvec::Array>::Item: fmt::Debug + Clone,
-{
- fn as_ref(&self) -> &[<[T; N] as tinyvec::Array>::Item] {
- self.vec.as_slice()
- }
-}
-impl<T, const N: usize> AsMut<[<[T; N] as tinyvec::Array>::Item]> for CapacityLimitedVec<T, N>
-where
- T: fmt::Debug + Clone,
- [T; N]: tinyvec::Array + fmt::Debug,
- <[T; N] as tinyvec::Array>::Item: fmt::Debug + Clone,
-{
- fn as_mut(&mut self) -> &mut [<[T; N] as tinyvec::Array>::Item] {
- self.vec.as_mut_slice()
- }
-}
diff --git a/nearby/presence/np_adv/src/extended/serialize/section/encoder.rs b/nearby/presence/np_adv/src/extended/serialize/section/encoder.rs
new file mode 100644
index 0000000..85f55bc
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/serialize/section/encoder.rs
@@ -0,0 +1,429 @@
+// 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.
+
+use crate::credential::v1::V1BroadcastCredential;
+use crate::extended::salt::{MultiSalt, ShortV1Salt, V1Salt};
+use crate::header::VERSION_HEADER_V1;
+use crate::{
+ extended::{
+ deserialize::SectionMic,
+ section_signature_payload::SectionSignaturePayload,
+ serialize::{section::header::SectionHeader, AdvertisementType, DeSalt},
+ V1IdentityToken, V1_IDENTITY_TOKEN_LEN,
+ },
+ NP_SVC_UUID,
+};
+use crypto_provider::{
+ aes,
+ aes::ctr::{AesCtr as _, AesCtrNonce, NonceAndCounter},
+ ed25519,
+ hmac::Hmac,
+ CryptoProvider, CryptoRng as _,
+};
+use np_hkdf::v1_salt::EXTENDED_SALT_LEN;
+use np_hkdf::{
+ v1_salt::{DataElementOffset, ExtendedV1Salt},
+ DerivedSectionKeys,
+};
+
+/// Everything needed to properly encode a section
+pub trait SectionEncoder {
+ /// How much space needs to be reserved after the DEs
+ const SUFFIX_LEN: usize;
+
+ /// The advertisement type that can support this section
+ const ADVERTISEMENT_TYPE: AdvertisementType;
+
+ /// The type of derived salt produced for a DE sharing a section with this identity.
+ type DerivedSalt;
+
+ /// Header to write at the start of the section contents
+ fn header(&self) -> SectionHeader;
+
+ /// Postprocess the contents of the section (the data after the section header byte), which will
+ /// start with the contents of [Self::header()], and similarly end with
+ /// [Self::SUFFIX_LEN] bytes, with DEs (if any) in the middle.
+ ///
+ /// `section_header_without_length` is the bytes of the section header up until but not
+ /// including the length byte
+ /// `section_len` is the length of the contents that come after the length byte which includes
+ /// the de contents + the suffix. This is the length of `remaining_content_bytes` stored as an u8
+ /// `remaining_content_bytes` are the bytes of the rest of the contents that come after section length
+ fn postprocess<C: CryptoProvider>(
+ &mut self,
+ section_header_without_length: &mut [u8],
+ section_len: u8,
+ remaining_content_bytes: &mut [u8],
+ );
+
+ /// Produce a `Self::Output` salt for a DE.
+ fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt;
+}
+
+/// Encoder for plaintext data elements
+#[derive(Debug)]
+pub struct UnencryptedSectionEncoder;
+
+impl UnencryptedSectionEncoder {}
+
+impl SectionEncoder for UnencryptedSectionEncoder {
+ const SUFFIX_LEN: usize = 0;
+ const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Plaintext;
+
+ type DerivedSalt = ();
+
+ fn header(&self) -> SectionHeader {
+ SectionHeader::unencrypted()
+ }
+ fn postprocess<C: CryptoProvider>(
+ &mut self,
+ _section_header_without_length: &mut [u8],
+ _section_len: u8,
+ _remaining_content_bytes: &mut [u8],
+ ) {
+ // no op
+ }
+
+ fn de_salt(&self, _de_offset: DataElementOffset) -> Self::DerivedSalt {}
+}
+
+/// Encrypts the data elements and protects integrity with an np_ed25519 signature
+/// using key material derived from an NP identity.
+pub struct SignedEncryptedSectionEncoder {
+ pub(crate) salt: ExtendedV1Salt,
+ identity_token: V1IdentityToken,
+ private_key: ed25519::PrivateKey,
+ aes_key: aes::Aes128Key,
+}
+
+impl SignedEncryptedSectionEncoder {
+ /// Build a [SignedEncryptedSectionEncoder] from an identity type,
+ /// some broadcast crypto-material, and with a random salt.
+ pub fn new_random_salt<C: CryptoProvider>(
+ rng: &mut C::CryptoRng,
+ crypto_material: &V1BroadcastCredential,
+ ) -> Self {
+ let salt: ExtendedV1Salt = rng.gen::<[u8; 16]>().into();
+ Self::new::<C>(salt, crypto_material)
+ }
+
+ /// Build a [SignedEncryptedSectionEncoder] from an identity type,
+ /// a provided salt, and some broadcast crypto-material.
+ pub(crate) fn new<C: CryptoProvider>(
+ salt: ExtendedV1Salt,
+ crypto_material: &V1BroadcastCredential,
+ ) -> Self {
+ let identity_token = crypto_material.identity_token();
+ let key_seed = crypto_material.key_seed();
+ let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
+ let private_key = crypto_material.signing_key();
+ let aes_key = key_seed_hkdf.v1_signature_keys().aes_key();
+ Self { salt, identity_token, private_key, aes_key }
+ }
+}
+
+impl SectionEncoder for SignedEncryptedSectionEncoder {
+ /// Ed25519 signature
+ const SUFFIX_LEN: usize = crypto_provider::ed25519::SIGNATURE_LENGTH;
+ const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Encrypted;
+
+ type DerivedSalt = DeSalt;
+
+ fn header(&self) -> SectionHeader {
+ SectionHeader::encrypted_signature_extended_salt(&self.salt, &self.identity_token)
+ }
+
+ fn postprocess<C: CryptoProvider>(
+ &mut self,
+ section_header_without_length: &mut [u8],
+ section_len: u8,
+ remaining_contents: &mut [u8],
+ ) {
+ let nonce: AesCtrNonce = self.salt.compute_nonce::<C>();
+ let mut cipher = C::AesCtr128::new(&self.aes_key, NonceAndCounter::from_nonce(nonce));
+
+ let start_of_identity_token = section_header_without_length.len() - V1_IDENTITY_TOKEN_LEN;
+ let (format_and_salt_bytes, identity_token) =
+ section_header_without_length.split_at_mut(start_of_identity_token);
+ debug_assert!(identity_token.len() == V1_IDENTITY_TOKEN_LEN);
+
+ let start_of_salt = format_and_salt_bytes.len() - EXTENDED_SALT_LEN;
+ let (format_bytes, salt_bytes) = format_and_salt_bytes.split_at_mut(start_of_salt);
+ debug_assert!(salt_bytes.len() == EXTENDED_SALT_LEN);
+ debug_assert!((1..=2).contains(&format_bytes.len()));
+
+ let start_of_signature = remaining_contents.len() - Self::SUFFIX_LEN;
+ let (plaintext_data_elements, sig) = remaining_contents.split_at_mut(start_of_signature);
+ debug_assert!(sig.len() == Self::SUFFIX_LEN);
+
+ let section_signature_payload = SectionSignaturePayload::new(
+ format_bytes,
+ salt_bytes,
+ &nonce,
+ identity_token,
+ section_len,
+ plaintext_data_elements,
+ );
+
+ sig.copy_from_slice(
+ &section_signature_payload.sign::<C::Ed25519>(&self.private_key).to_bytes(),
+ );
+
+ cipher.apply_keystream(identity_token);
+ cipher.apply_keystream(plaintext_data_elements);
+ cipher.apply_keystream(sig);
+ }
+
+ fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
+ DeSalt { salt: self.salt, de_offset }
+ }
+}
+
+/// Encrypts the data elements and protects integrity with a MIC using key material derived from
+/// an NP identity.
+pub struct MicEncryptedSectionEncoder<S> {
+ pub(crate) salt: S,
+ identity_token: V1IdentityToken,
+ aes_key: aes::Aes128Key,
+ mic_hmac_key: np_hkdf::NpHmacSha256Key,
+}
+
+impl<S: MicSectionEncoderSalt> MicEncryptedSectionEncoder<S> {
+ /// Build a [MicEncryptedSectionEncoder] from the provided identity info.
+ pub(crate) fn new<C: CryptoProvider>(
+ salt: S,
+ broadcast_credential: &V1BroadcastCredential,
+ ) -> Self {
+ let identity_token = broadcast_credential.identity_token();
+ let key_seed = broadcast_credential.key_seed();
+ let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
+ let aes_key = salt.derive_aes_key(&key_seed_hkdf);
+ let mic_hmac_key = salt.derive_mic_hmac_key(&key_seed_hkdf);
+
+ Self { salt, identity_token, aes_key, mic_hmac_key }
+ }
+
+ /// Build a [MicEncryptedSectionEncoder] from the provided identity info.
+ /// Exposed outside of this crate for testing purposes only, since this
+ /// does not handle the generation of random salts.
+ #[cfg(any(test, feature = "testing", feature = "devtools"))]
+ pub fn new_with_salt<C: CryptoProvider>(
+ salt: S,
+ broadcast_credential: &V1BroadcastCredential,
+ ) -> Self {
+ Self::new::<C>(salt, broadcast_credential)
+ }
+}
+
+impl MicEncryptedSectionEncoder<ExtendedV1Salt> {
+ /// Build a [MicEncryptedSectionEncoder] from the provided identity
+ /// info with a random extended salt.
+ pub fn new_random_salt<C: CryptoProvider>(
+ rng: &mut C::CryptoRng,
+ broadcast_credential: &V1BroadcastCredential,
+ ) -> Self {
+ Self::new::<C>(rng.gen(), broadcast_credential)
+ }
+}
+
+impl MicEncryptedSectionEncoder<MultiSalt> {
+ /// Build a [MicEncryptedSectionEncoder] from the provided identity
+ /// info with a random extended salt wrapped in [MultiSalt].
+ ///
+ /// Prefer [Self::new_random_salt] unless there is a need for the type
+ /// parameter to be [MultiSalt].
+ pub fn new_wrapped_salt<C: CryptoProvider>(
+ rng: &mut C::CryptoRng,
+ broadcast_credential: &V1BroadcastCredential,
+ ) -> Self {
+ Self::new::<C>(rng.gen::<ExtendedV1Salt>().into(), broadcast_credential)
+ }
+}
+
+impl<S: MicSectionEncoderSalt> SectionEncoder for MicEncryptedSectionEncoder<S> {
+ /// Length of mic
+ const SUFFIX_LEN: usize = SectionMic::CONTENTS_LEN;
+
+ const ADVERTISEMENT_TYPE: AdvertisementType = AdvertisementType::Encrypted;
+
+ type DerivedSalt = S::DerivedSalt;
+
+ fn header(&self) -> SectionHeader {
+ self.salt.header(&self.identity_token)
+ }
+
+ fn postprocess<C: CryptoProvider>(
+ &mut self,
+ section_header_without_length: &mut [u8],
+ section_len: u8,
+ remaining_contents: &mut [u8],
+ ) {
+ let nonce: AesCtrNonce = self.salt.compute_nonce::<C>();
+ let mut cipher = C::AesCtr128::new(&self.aes_key, NonceAndCounter::from_nonce(nonce));
+
+ let start_of_identity_token = section_header_without_length.len() - V1_IDENTITY_TOKEN_LEN;
+ let (format_and_salt_bytes, identity_token) =
+ section_header_without_length.split_at_mut(start_of_identity_token);
+ debug_assert!(identity_token.len() == V1_IDENTITY_TOKEN_LEN);
+ // format can be 1-2 bytes
+ debug_assert!((1 + self.salt.into().as_slice().len()
+ ..=2 + self.salt.into().as_slice().len())
+ .contains(&format_and_salt_bytes.len()));
+
+ let start_of_mic = remaining_contents.len() - Self::SUFFIX_LEN;
+ let (data_element_contents, mic) = remaining_contents.split_at_mut(start_of_mic);
+ debug_assert!(mic.len() == Self::SUFFIX_LEN);
+
+ // First encrypt the identity token
+ cipher.apply_keystream(identity_token);
+
+ // Now encrypt the rest of the ciphertext bytes that come after the section length byte
+ cipher.apply_keystream(data_element_contents);
+
+ // calculate MAC per the spec
+ let mut section_hmac = self.mic_hmac_key.build_hmac::<C>();
+ // svc uuid
+ section_hmac.update(NP_SVC_UUID.as_slice());
+ // adv header
+ section_hmac.update(&[VERSION_HEADER_V1]);
+ // section format and salt
+ section_hmac.update(format_and_salt_bytes);
+ // nonce
+ section_hmac.update(&nonce);
+ // encrypted identity token
+ section_hmac.update(identity_token);
+ // section len
+ section_hmac.update(&[section_len]);
+ // rest of the ciphertext
+ section_hmac.update(data_element_contents);
+
+ // write truncated MIC
+ mic.copy_from_slice(&section_hmac.finalize()[..SectionMic::CONTENTS_LEN]);
+ }
+
+ fn de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
+ self.salt.derive_de_salt(de_offset)
+ }
+}
+
+/// Behavior for salts used with MIC sections.
+pub trait MicSectionEncoderSalt: V1Salt {
+ /// The type of derived data produced, or `()` if no data can be derived.
+ type DerivedSalt;
+
+ /// Build the appropriate header for the type of salt used
+ fn header(&self, identity_token: &V1IdentityToken) -> SectionHeader;
+
+ /// Derive a DE salt at the specified offset.
+ fn derive_de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt;
+
+ /// Derive the AES key suitable for this salt type
+ fn derive_aes_key<C: CryptoProvider>(&self, hkdf: &np_hkdf::NpKeySeedHkdf<C>)
+ -> aes::Aes128Key;
+
+ /// Derive the MIC HMAC key suitable for this salt type
+ fn derive_mic_hmac_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> np_hkdf::NpHmacSha256Key;
+}
+
+impl MicSectionEncoderSalt for ExtendedV1Salt {
+ type DerivedSalt = DeSalt;
+
+ fn header(&self, identity_token: &V1IdentityToken) -> SectionHeader {
+ SectionHeader::encrypted_mic_extended_salt(self, identity_token)
+ }
+
+ fn derive_de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
+ DeSalt { salt: *self, de_offset }
+ }
+
+ fn derive_aes_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> aes::Aes128Key {
+ hkdf.v1_mic_extended_salt_keys().aes_key()
+ }
+
+ fn derive_mic_hmac_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> np_hkdf::NpHmacSha256Key {
+ hkdf.v1_mic_extended_salt_keys().mic_hmac_key()
+ }
+}
+
+// TODO is this impl used?
+impl MicSectionEncoderSalt for ShortV1Salt {
+ type DerivedSalt = ();
+
+ fn header(&self, identity_token: &V1IdentityToken) -> SectionHeader {
+ SectionHeader::encrypted_mic_short_salt(*self, identity_token)
+ }
+
+ fn derive_de_salt(&self, _de_offset: DataElementOffset) -> Self::DerivedSalt {}
+
+ fn derive_aes_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> aes::Aes128Key {
+ hkdf.v1_mic_short_salt_keys().aes_key()
+ }
+
+ fn derive_mic_hmac_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> np_hkdf::NpHmacSha256Key {
+ hkdf.v1_mic_short_salt_keys().mic_hmac_key()
+ }
+}
+
+impl MicSectionEncoderSalt for MultiSalt {
+ type DerivedSalt = Option<DeSalt>;
+
+ fn header(&self, identity_token: &V1IdentityToken) -> SectionHeader {
+ match self {
+ MultiSalt::Short(s) => SectionHeader::encrypted_mic_short_salt(*s, identity_token),
+ MultiSalt::Extended(s) => SectionHeader::encrypted_mic_extended_salt(s, identity_token),
+ }
+ }
+
+ fn derive_de_salt(&self, de_offset: DataElementOffset) -> Self::DerivedSalt {
+ match self {
+ MultiSalt::Short(_) => None,
+ MultiSalt::Extended(s) => Some(DeSalt { salt: *s, de_offset }),
+ }
+ }
+
+ fn derive_aes_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> aes::Aes128Key {
+ match self {
+ MultiSalt::Short(_) => hkdf.v1_mic_short_salt_keys().aes_key(),
+ MultiSalt::Extended(_) => hkdf.v1_mic_extended_salt_keys().aes_key(),
+ }
+ }
+
+ fn derive_mic_hmac_key<C: CryptoProvider>(
+ &self,
+ hkdf: &np_hkdf::NpKeySeedHkdf<C>,
+ ) -> np_hkdf::NpHmacSha256Key {
+ match self {
+ MultiSalt::Short(_) => hkdf.v1_mic_short_salt_keys().mic_hmac_key(),
+ MultiSalt::Extended(_) => hkdf.v1_mic_extended_salt_keys().mic_hmac_key(),
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/serialize/section/header.rs b/nearby/presence/np_adv/src/extended/serialize/section/header.rs
new file mode 100644
index 0000000..5e8b2e4
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/serialize/section/header.rs
@@ -0,0 +1,164 @@
+// 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.
+
+use crate::extended::salt::ShortV1Salt;
+use crate::extended::{
+ V1IdentityToken, V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN, V1_ENCODING_UNENCRYPTED,
+};
+use np_hkdf::v1_salt::ExtendedV1Salt;
+
+/// Format || salt || token
+pub(crate) const SECTION_HEADER_MAX_LEN: usize = 2 + 16 + 16;
+
+/// Assembles the header bytes for a section after the section length, before postprocessing by
+/// a [SectionEncoder](crate::extended::serialize::section::SectionEncoder).
+///
+/// Does not include the overall NP header byte that defines the adv version.
+pub struct SectionHeader {
+ /// The section header
+ /// Invariant: always has at least 1 byte
+ header_bytes: tinyvec::ArrayVec<[u8; SECTION_HEADER_MAX_LEN]>,
+}
+
+impl SectionHeader {
+ pub(crate) fn unencrypted() -> Self {
+ let mut header_bytes = tinyvec::ArrayVec::new();
+ header_bytes.push(V1_ENCODING_UNENCRYPTED);
+ Self { header_bytes }
+ }
+
+ pub(crate) fn encrypted_mic_short_salt(salt: ShortV1Salt, token: &V1IdentityToken) -> Self {
+ let mut header_bytes = tinyvec::ArrayVec::new();
+ header_bytes.push(V1_ENCODING_ENCRYPTED_MIC_WITH_SHORT_SALT_AND_TOKEN);
+ header_bytes.extend_from_slice(salt.bytes().as_slice());
+ header_bytes.extend_from_slice(token.bytes().as_slice());
+ Self { header_bytes }
+ }
+
+ pub(crate) fn encrypted_mic_extended_salt(
+ salt: &ExtendedV1Salt,
+ token: &V1IdentityToken,
+ ) -> Self {
+ let mut header_bytes = tinyvec::ArrayVec::new();
+ header_bytes.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ header_bytes.extend_from_slice(salt.bytes().as_slice());
+ header_bytes.extend_from_slice(token.bytes().as_slice());
+ Self { header_bytes }
+ }
+
+ pub(crate) fn encrypted_signature_extended_salt(
+ salt: &ExtendedV1Salt,
+ token: &V1IdentityToken,
+ ) -> Self {
+ let mut header_bytes = tinyvec::ArrayVec::new();
+ header_bytes.push(V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN);
+ header_bytes.extend_from_slice(salt.bytes().as_slice());
+ header_bytes.extend_from_slice(token.bytes().as_slice());
+ Self { header_bytes }
+ }
+
+ pub(crate) fn as_slice(&self) -> &[u8] {
+ self.header_bytes.as_slice()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::extended::V1_IDENTITY_TOKEN_LEN;
+ use ldt_np_adv::V0_SALT_LEN;
+ use np_hkdf::v1_salt::EXTENDED_SALT_LEN;
+
+ const SHORT_SALT_BYTES: [u8; V0_SALT_LEN] = [0x10, 0x11];
+ const EXTENDED_SALT_BYTES: [u8; EXTENDED_SALT_LEN] = [
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x1F,
+ ];
+ const TOKEN_BYTES: [u8; V1_IDENTITY_TOKEN_LEN] = [
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
+ 0x2F,
+ ];
+
+ #[test]
+ fn unencrypted_slice() {
+ assert_eq!(&[V1_ENCODING_UNENCRYPTED], SectionHeader::unencrypted().as_slice());
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn encrypted_mic_short_salt_slice() {
+ assert_eq!(
+ &[
+ // format
+ 0x01,
+ // salt
+ 0x10, 0x11,
+ // token
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
+ 0x2C, 0x2D, 0x2E, 0x2F,
+ ],
+ SectionHeader::encrypted_mic_short_salt(
+ SHORT_SALT_BYTES.into(),
+ &TOKEN_BYTES.into()
+ )
+ .as_slice()
+ );
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn encrypted_mic_extended_salt_slice() {
+ assert_eq!(
+ &[
+ // format
+ 0x02,
+ // salt
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F,
+ // token
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
+ 0x2C, 0x2D, 0x2E, 0x2F,
+ ],
+ SectionHeader::encrypted_mic_extended_salt(
+ &EXTENDED_SALT_BYTES.into(),
+ &TOKEN_BYTES.into()
+ )
+ .as_slice()
+ );
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn encrypted_sig_extended_salt_slice() {
+ assert_eq!(
+ &[
+ // format
+ 0x03,
+ // salt
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F,
+ // token
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
+ 0x2C, 0x2D, 0x2E, 0x2F,
+ ],
+ SectionHeader::encrypted_signature_extended_salt(
+ &EXTENDED_SALT_BYTES.into(),
+ &TOKEN_BYTES.into()
+ )
+ .as_slice()
+ );
+ }
+}
diff --git a/nearby/presence/np_adv/src/extended/serialize/section/mod.rs b/nearby/presence/np_adv/src/extended/serialize/section/mod.rs
new file mode 100644
index 0000000..8fb76ab
--- /dev/null
+++ b/nearby/presence/np_adv/src/extended/serialize/section/mod.rs
@@ -0,0 +1,204 @@
+// 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.
+
+use array_view::ArrayView;
+use crypto_provider::CryptoProvider;
+use np_hkdf::v1_salt::DataElementOffset;
+use sink::Sink as _;
+
+use crate::extended::{
+ serialize::{
+ section::encoder::SectionEncoder, AdvBuilder, CapacityLimitedVec, WriteDataElement,
+ },
+ to_array_view, NP_ADV_MAX_SECTION_LEN,
+};
+
+pub(crate) mod encoder;
+pub(crate) mod header;
+
+/// Accumulates data elements and encodes them into a section.
+#[derive(Debug)]
+pub struct SectionBuilder<R: AsMut<AdvBuilder>, SE: SectionEncoder> {
+ /// The length of the header produced by `section_encoder`
+ pub(crate) header_len: usize,
+ /// Contains the section header, the identity-specified overhead, and any DEs added
+ pub(crate) section: CapacityLimitedVec<u8, { NP_ADV_MAX_SECTION_LEN }>,
+ pub(crate) section_encoder: SE,
+ /// mut ref-able to enforce only one active section builder at a time
+ pub(crate) adv_builder: R,
+ next_de_offset: DataElementOffset,
+}
+
+impl<'a, SE: SectionEncoder> SectionBuilder<&'a mut AdvBuilder, SE> {
+ /// Add this builder to the advertisement that created it.
+ pub fn add_to_advertisement<C: CryptoProvider>(self) {
+ let _ = self.add_to_advertisement_internal::<C>();
+ }
+}
+
+impl<SE: SectionEncoder> SectionBuilder<AdvBuilder, SE> {
+ /// Gets the 0-based index of the section currently under construction
+ /// in the context of the containing advertisement.
+ pub fn section_index(&self) -> usize {
+ self.adv_builder.section_count()
+ }
+ /// Add this builder to the advertisement that created it,
+ /// and returns the containing advertisement back to the caller.
+ pub fn add_to_advertisement<C: CryptoProvider>(self) -> AdvBuilder {
+ self.add_to_advertisement_internal::<C>()
+ }
+}
+
+impl<R: AsMut<AdvBuilder>, SE: SectionEncoder> SectionBuilder<R, SE> {
+ pub(crate) fn new(
+ header_len: usize,
+ section: CapacityLimitedVec<u8, NP_ADV_MAX_SECTION_LEN>,
+ section_encoder: SE,
+ adv_builder: R,
+ ) -> Self {
+ Self {
+ header_len,
+ section,
+ section_encoder,
+ adv_builder,
+ next_de_offset: DataElementOffset::ZERO,
+ }
+ }
+
+ /// Add this builder to the advertisement that created it.
+ /// Returns the mut-refable to the advertisement builder
+ /// which the contents of this section builder were added to.
+ //TODO: make this fallible, if the section being added is invalid, right now it is possible to
+ // create invalid adv's that don't parse
+ fn add_to_advertisement_internal<C: CryptoProvider>(mut self) -> R {
+ let adv_builder = self.adv_builder.as_mut();
+ adv_builder.add_section(Self::build_section::<C>(
+ self.header_len,
+ self.section.into_inner(),
+ self.section_encoder,
+ ));
+ self.adv_builder
+ }
+
+ /// Gets the derived salt which will be employed for the next DE offset.
+ ///
+ /// Suitable for scenarios (like FFI) where a closure would be inappropriate
+ /// for DE construction, and interaction with the client is preferred.
+ pub fn next_de_salt(&self) -> SE::DerivedSalt {
+ self.section_encoder.de_salt(self.next_de_offset)
+ }
+
+ /// Add a data element to the section with a closure that returns a `Result`.
+ ///
+ /// The provided `build_de` closure will be invoked with the derived salt for this DE.
+ pub fn add_de_res<W: WriteDataElement, E, F: FnOnce(SE::DerivedSalt) -> Result<W, E>>(
+ &mut self,
+ build_de: F,
+ ) -> Result<(), AddDataElementError<E>> {
+ let writer = build_de(self.next_de_salt()).map_err(AddDataElementError::BuildDeError)?;
+
+ let orig_len = self.section.len();
+ // since we own the writer, and it's immutable, no race risk writing header w/ len then
+ // the contents as long as it's not simply an incorrect impl
+ let de_header = writer.de_header();
+ let content_len = self
+ .section
+ .try_extend_from_slice(de_header.serialize().as_slice())
+ .ok_or(AddDataElementError::InsufficientSectionSpace)
+ .and_then(|_| {
+ let after_header_len = self.section.len();
+ writer
+ .write_de_contents(&mut self.section)
+ .ok_or(AddDataElementError::InsufficientSectionSpace)
+ .map(|_| self.section.len() - after_header_len)
+ })
+ .map_err(|e| {
+ // if anything went wrong, truncate any partial writes (e.g. just the header)
+ self.section.truncate(orig_len);
+ e
+ })?;
+
+ if content_len != usize::from(de_header.len.as_u8()) {
+ // TODO eliminate this possibility by keeping a 127-byte buffer
+ // to write DEs into, then calculating the written length, so the
+ // DE impl doesn't have to do it
+ panic!(
+ "Buggy WriteDataElement impl: header len {}, actual written len {}",
+ de_header.len.as_u8(),
+ content_len
+ );
+ }
+
+ self.next_de_offset = self.next_de_offset.incremented();
+
+ Ok(())
+ }
+
+ /// Add a data element to the section with a closure that returns the data element directly.
+ ///
+ /// The provided `build_de` closure will be invoked with the derived salt for this DE.
+ pub fn add_de<W: WriteDataElement, F: FnOnce(SE::DerivedSalt) -> W>(
+ &mut self,
+ build_de: F,
+ ) -> Result<(), AddDataElementError<()>> {
+ self.add_de_res(|derived_salt| Ok::<_, ()>(build_de(derived_salt)))
+ }
+
+ /// Convert a section builder's contents into an encoded section.
+ ///
+ /// `section_contents` must have size > 0.
+ ///
+ /// `header_len` is the length of the prefix of `section_contents` that has been populated
+ /// with the data returned from [SectionEncoder::header()] which does NOT include the length byte.
+ ///
+ /// Implemented without self to avoid partial-move issues.
+ pub(crate) fn build_section<C: CryptoProvider>(
+ header_len: usize,
+ mut section_contents: tinyvec::ArrayVec<[u8; NP_ADV_MAX_SECTION_LEN]>,
+ mut section_encoder: SE,
+ ) -> EncodedSection {
+ // there is space because the capacity for DEs was restricted to allow it
+ section_contents.resize(section_contents.len() + SE::SUFFIX_LEN, 0);
+
+ let (format_and_salt_and_identity_token, rest_of_contents) =
+ section_contents.split_at_mut(header_len);
+
+ let (section_length_byte, rest_of_contents) = rest_of_contents.split_at_mut(1);
+
+ let section_len = rest_of_contents.len().try_into().expect(
+ "section length will always fit into a u8 and has been validated by the section builder",
+ );
+ // set the section length byte
+ section_length_byte[0] = section_len;
+ section_encoder.postprocess::<C>(
+ format_and_salt_and_identity_token,
+ section_len,
+ rest_of_contents,
+ );
+
+ to_array_view(section_contents)
+ }
+}
+
+/// Errors for adding a DE to a section
+#[derive(Debug, PartialEq, Eq)]
+pub enum AddDataElementError<E> {
+ /// An error occurred when invoking the DE builder closure.
+ BuildDeError(E),
+ /// Too much data to fit into the section
+ InsufficientSectionSpace,
+}
+
+/// The encoded form of an advertisement section
+pub(crate) type EncodedSection = ArrayView<u8, NP_ADV_MAX_SECTION_LEN>;
diff --git a/nearby/presence/np_adv/src/extended/serialize/section_tests.rs b/nearby/presence/np_adv/src/extended/serialize/section_tests.rs
index 3a6a5f9..e1e90b7 100644
--- a/nearby/presence/np_adv/src/extended/serialize/section_tests.rs
+++ b/nearby/presence/np_adv/src/extended/serialize/section_tests.rs
@@ -17,28 +17,46 @@
extern crate std;
use super::*;
-use crate::credential::{
- v1::{SimpleSignedBroadcastCryptoMaterial, V1},
- SimpleBroadcastCryptoMaterial,
+use crate::extended::{
+ V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN,
+ V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN, V1_ENCODING_UNENCRYPTED,
+};
+use crate::{
+ credential::v1::V1BroadcastCredential,
+ extended::{
+ data_elements::{GenericDataElement, GenericDataElementError},
+ deserialize::SectionMic,
+ salt::V1Salt,
+ section_signature_payload::SectionSignaturePayload,
+ serialize::AddSectionError::MaxSectionCountExceeded,
+ V1IdentityToken, V1_IDENTITY_TOKEN_LEN,
+ },
+ NP_SVC_UUID,
+};
+use crypto_provider::ed25519;
+use crypto_provider::ed25519::SIGNATURE_LENGTH;
+use crypto_provider::{
+ aes::ctr::{AesCtr, NonceAndCounter},
+ hmac::Hmac,
+ CryptoRng,
};
-use crate::extended::data_elements::GenericDataElement;
-use crate::extended::serialize::AddSectionError::MaxSectionCountExceeded;
-use crypto_provider::aes::ctr::AES_CTR_NONCE_LEN;
use crypto_provider_default::CryptoProviderImpl;
-use np_hkdf::v1_salt::V1Salt;
-use rand::rngs::StdRng;
-use rand::{prelude::SliceRandom as _, Rng as _, SeedableRng as _};
+use np_hkdf::v1_salt::EXTENDED_SALT_LEN;
+use np_hkdf::DerivedSectionKeys;
+use rand::{rngs::StdRng, Rng as _, SeedableRng as _};
use std::{prelude::rust_2021::*, vec};
-use strum::IntoEnumIterator as _;
-type KeyPair = np_ed25519::KeyPair<CryptoProviderImpl>;
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
#[test]
-fn public_identity_section_empty() {
+fn unencrypted_section_empty() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
- assert_eq!(&[1_u8, 0x03], section_builder.into_section().as_slice());
+ assert_eq!(
+ &[V1_ENCODING_UNENCRYPTED, 0_u8],
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
+ );
}
#[test]
@@ -64,101 +82,81 @@ fn mic_encrypted_identity_section_random_des() {
})
.collect::<Vec<_>>();
- let metadata_key = rng.gen();
- let metadata_key = MetadataKey(metadata_key);
+ let identity_token: V1IdentityToken = crypto_rng.gen();
let key_seed = rng.gen();
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
-
- let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
- &mut crypto_rng,
- identity_type,
- &broadcast_cm,
- ))
- .unwrap();
- let section_salt = V1Salt::<CryptoProviderImpl>::from(
- *section_builder.section_encoder.salt.as_array_ref(),
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
);
+ let mut section_builder =
+ adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<
+ CryptoProviderImpl,
+ >(&mut crypto_rng, &broadcast_cred))
+ .unwrap();
+ let section_salt = section_builder.section_encoder.salt;
+
for de in extra_des.iter() {
section_builder.add_de(|_| de).unwrap();
}
- // length 53: 19 for encryption info, 18 for identity, 16 for MIC
- let section_length = 53
- + extra_des
- .iter()
- .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
- .sum::<u8>();
-
- let encryption_info = [
- &[
- 0x91, 0x10, // header
- 0x00, // scheme (mic)
- ],
- section_salt.as_slice(),
- ]
- .concat();
+ let section_length = mic_section_len(&extra_des);
- let identity_de_header =
- DeHeader { len: 16_u8.try_into().unwrap(), de_type: identity_type.type_code() };
-
- let mut hmac = np_hkdf::UnsignedSectionKeys::hmac_key(&key_seed_hkdf).build_hmac();
- // just to be sure, we'll construct our test hmac all in one update() call
- let mut hmac_input = vec![];
- hmac_input.extend_from_slice(NP_SVC_UUID.as_slice());
- hmac_input.push(0b00100000); // v1
-
- // section header
- hmac_input.push(section_length);
- hmac_input.extend_from_slice(&encryption_info);
- let nonce = section_salt.derive::<{ AES_CTR_NONCE_LEN }>(Some(1.into())).unwrap();
- hmac_input.extend_from_slice(nonce.as_slice());
-
- hmac_input.extend_from_slice(identity_de_header.serialize().as_slice());
+ let mut hmac = key_seed_hkdf
+ .v1_mic_extended_salt_keys()
+ .mic_hmac_key()
+ .build_hmac::<CryptoProviderImpl>();
+ let nonce = section_salt.compute_nonce::<CryptoProviderImpl>();
let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf),
+ &key_seed_hkdf.v1_mic_extended_salt_keys().aes_key(),
NonceAndCounter::from_nonce(nonce),
);
- let mut plaintext = metadata_key.0.as_slice().to_vec();
+ // encrypt identity token and de contents
+ let mut plaintext_identity_token = identity_token.as_slice().to_vec();
+ cipher.apply_keystream(&mut plaintext_identity_token);
+ let ct_identity_token = plaintext_identity_token;
+
+ let mut de_contents = Vec::new();
for de in extra_des {
- plaintext.extend_from_slice(de.de_header().serialize().as_slice());
- let _ = de.write_de_contents(&mut plaintext);
+ de_contents.extend_from_slice(de.de_header().serialize().as_slice());
+ let _ = de.write_de_contents(&mut de_contents);
}
+ cipher.apply_keystream(&mut de_contents);
- cipher.apply_keystream(&mut plaintext);
- let ciphertext = plaintext;
-
- hmac_input.extend_from_slice(&ciphertext);
-
+ // just to be sure, we'll construct our test hmac all in one update() call
+ let mut hmac_input = vec![];
+ hmac_input.extend_from_slice(NP_SVC_UUID.as_slice());
+ hmac_input.push(VERSION_HEADER_V1);
+ hmac_input.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ hmac_input.extend_from_slice(section_salt.as_slice());
+ hmac_input.extend_from_slice(nonce.as_slice());
+ hmac_input.extend_from_slice(&ct_identity_token);
+ hmac_input.push(section_length);
+ hmac_input.extend_from_slice(&de_contents);
hmac.update(&hmac_input);
let mic = hmac.finalize();
let mut expected = vec![];
+ expected.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ expected.extend_from_slice(section_salt.as_slice());
+ expected.extend_from_slice(&ct_identity_token);
expected.push(section_length);
- expected.extend_from_slice(&encryption_info);
- expected.extend_from_slice(identity_de_header.serialize().as_slice());
- expected.extend_from_slice(&ciphertext);
+ expected.extend_from_slice(&de_contents);
expected.extend_from_slice(&mic[..16]);
- assert_eq!(&expected, section_builder.into_section().as_slice());
+ assert_eq!(&expected, section_builder.into_section::<CryptoProviderImpl>().as_slice());
}
}
#[test]
-fn signature_encrypted_identity_section_empty() {
- do_signature_encrypted_identity_fixed_key_material_test::<DummyDataElement>(&[]);
-}
-
-#[test]
fn signature_encrypted_identity_section_random_des() {
let mut rng = StdRng::from_entropy();
let mut crypto_rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
@@ -166,31 +164,23 @@ fn signature_encrypted_identity_section_random_des() {
for _ in 0..1_000 {
let num_des = rng.gen_range(1..=5);
- let metadata_key = MetadataKey(rng.gen());
+ let identity_token = V1IdentityToken(rng.gen());
let key_seed = rng.gen();
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let key_pair = KeyPair::generate();
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
- let broadcast_cm = SimpleSignedBroadcastCryptoMaterial::new(
- key_seed,
- metadata_key,
- key_pair.private_key(),
- );
+ let broadcast_cred =
+ V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- identity_type,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
- let section_salt = V1Salt::<CryptoProviderImpl>::from(
- *section_builder.section_encoder.salt.as_array_ref(),
- );
+ let section_salt = section_builder.section_encoder.salt;
let extra_des = (0..num_des)
.map(|_| {
@@ -204,32 +194,8 @@ fn signature_encrypted_identity_section_random_des() {
.filter_map(|de| section_builder.add_de(|_| de.clone()).ok().map(|_| de))
.collect::<Vec<_>>();
- // 19 for encryption info, 18 for identity, 64 for signature
- let section_length = 19
- + 18
- + 64
- + extra_des
- .iter()
- .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
- .sum::<u8>();
-
- let encryption_info = [
- &[
- 0x91, 0x10, // header
- 0x08, // scheme (signature)
- ],
- section_salt.as_slice(),
- ]
- .concat();
- let encryption_info: [u8; EncryptionInfo::TOTAL_DE_LEN] =
- encryption_info.try_into().unwrap();
-
- let identity_de_header =
- DeHeader { len: 16_u8.try_into().unwrap(), de_type: identity_type.type_code() };
- let identity_de_header: [u8; 2] =
- identity_de_header.serialize().as_slice().try_into().unwrap();
-
- let nonce = section_salt.derive::<{ AES_CTR_NONCE_LEN }>(Some(1.into())).unwrap();
+ let section_length = sig_section_len(&extra_des);
+ let nonce = section_salt.compute_nonce::<CryptoProviderImpl>();
let mut section_body = Vec::new();
for de in extra_des {
@@ -237,34 +203,41 @@ fn signature_encrypted_identity_section_random_des() {
let _ = de.write_de_contents(&mut section_body);
}
- let sig_payload = SectionSignaturePayload::from_deserialized_parts(
- 0x20,
- section_length,
- &encryption_info,
+ let mut section_header = vec![];
+ section_header
+ .extend_from_slice(&[V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN]);
+ section_header.extend_from_slice(section_salt.as_slice());
+ section_header.extend_from_slice(identity_token.as_slice());
+
+ let sig_payload = SectionSignaturePayload::new(
+ &[V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN],
+ section_salt.as_slice(),
&nonce,
- identity_de_header,
- metadata_key,
+ identity_token.as_slice(),
+ section_length,
&section_body,
);
- let mut plaintext = metadata_key.0.as_slice().to_vec();
- plaintext.extend_from_slice(section_body.as_slice());
+ let mut plaintext = section_body.as_slice().to_vec();
+ plaintext
+ .extend_from_slice(&sig_payload.sign::<Ed25519ProviderImpl>(&private_key).to_bytes());
- plaintext.extend_from_slice(&sig_payload.sign(&key_pair).to_bytes());
-
- <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &key_seed_hkdf.extended_signed_section_aes_key(),
+ let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
+ &key_seed_hkdf.v1_signature_keys().aes_key(),
NonceAndCounter::from_nonce(nonce),
- )
- .apply_keystream(&mut plaintext);
+ );
+ let start_of_identity_token = section_header.len() - V1_IDENTITY_TOKEN_LEN;
+ cipher.apply_keystream(&mut section_header[start_of_identity_token..]);
+
+ cipher.apply_keystream(&mut plaintext);
let ciphertext = plaintext;
- let mut expected = vec![section_length];
- expected.extend_from_slice(&encryption_info);
- expected.extend_from_slice(&identity_de_header);
+ let mut expected = vec![];
+ expected.extend_from_slice(&section_header);
+ expected.push(section_length);
expected.extend_from_slice(&ciphertext);
- assert_eq!(&expected, section_builder.into_section().as_slice());
+ assert_eq!(&expected, section_builder.into_section::<CryptoProviderImpl>().as_slice());
}
}
@@ -276,24 +249,26 @@ fn section_builder_too_full_doesnt_advance_de_index() {
let key_seed = [22; 32];
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key = MetadataKey([33; 16]);
+ let identity_token = V1IdentityToken([33; 16]);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Trusted,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
- let salt =
- V1Salt::<CryptoProviderImpl>::from(*section_builder.section_encoder.salt.as_array_ref());
+ let salt = section_builder.section_encoder.salt;
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 100_u32.into(),
- data: de_salt.derive::<100>().unwrap().to_vec(),
+ data: de_salt.derive::<100, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
@@ -303,7 +278,7 @@ fn section_builder_too_full_doesnt_advance_de_index() {
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 101_u32.into(),
- data: de_salt.derive::<100>().unwrap().to_vec(),
+ data: de_salt.derive::<100, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap_err()
);
@@ -311,35 +286,38 @@ fn section_builder_too_full_doesnt_advance_de_index() {
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 102_u32.into(),
- data: de_salt.derive::<10>().unwrap().to_vec(),
+ data: de_salt.derive::<10, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let mut expected = vec![];
- // metadata key
- expected.extend_from_slice(&metadata_key.0);
+ // identity token
+ expected.extend_from_slice(&identity_token.0);
+ // section len
+ expected.push(2 + 100 + 2 + 10u8 + u8::try_from(SectionMic::CONTENTS_LEN).unwrap());
// de header
expected.extend_from_slice(&[0x80 + 100, 100]);
- // section 0 de 2
- expected.extend_from_slice(&salt.derive::<100>(Some(2.into())).unwrap());
+ // section 0 de 0
+ expected.extend_from_slice(&salt.derive::<100, CryptoProviderImpl>(Some(0.into())).unwrap());
// de header
expected.extend_from_slice(&[0x80 + 10, 102]);
- // section 0 de 3
- expected.extend_from_slice(&salt.derive::<10>(Some(3.into())).unwrap());
+ // section 0 de 1
+ expected.extend_from_slice(&salt.derive::<10, CryptoProviderImpl>(Some(1.into())).unwrap());
let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf),
- NonceAndCounter::from_nonce(salt.derive(Some(1.into())).unwrap()),
+ &key_seed_hkdf.v1_mic_extended_salt_keys().aes_key(),
+ NonceAndCounter::from_nonce(salt.compute_nonce::<CryptoProviderImpl>()),
);
- cipher.apply_keystream(&mut expected);
+ cipher.apply_keystream(&mut expected[..V1_IDENTITY_TOKEN_LEN]);
+ cipher.apply_keystream(&mut expected[V1_IDENTITY_TOKEN_LEN + 1..]);
let adv_bytes = adv_builder.into_advertisement();
// ignoring the MIC, etc, since that's tested elsewhere
- let ciphertext_end = adv_bytes.as_slice().len() - 16;
- assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + 19 + 2..ciphertext_end])
+ let ciphertext_end = adv_bytes.as_slice().len() - SectionMic::CONTENTS_LEN;
+ assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + EXTENDED_SALT_LEN..ciphertext_end])
}
#[test]
@@ -349,9 +327,10 @@ fn section_de_fits_exactly() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
// fill up space to produce desired capacity
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
- // leave space for adv header, 1 section headers, 1 section identity and fill almost full
- fill_section_builder(BLE_ADV_SVC_CONTENT_LEN - 1 - 1 - 1 - 1, &mut section_builder);
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
+ // leave space for adv header, 1 section len, 1 section header and 1 extra byte
+ fill_section_builder(BLE_5_ADV_SVC_MAX_CONTENT_LEN - 1 - 1 - 1 - 1, &mut section_builder)
+ .unwrap();
assert_eq!(1, section_builder.section.capacity() - section_builder.section.len(), "capacity: ");
// can't add a 2 byte DE
@@ -373,24 +352,26 @@ fn section_builder_build_de_error_doesnt_advance_de_index() {
let key_seed = [22; 32];
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key = MetadataKey([33; 16]);
+ let identity_token = V1IdentityToken([33; 16]);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Trusted,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
- let salt =
- V1Salt::<CryptoProviderImpl>::from(*section_builder.section_encoder.salt.as_array_ref());
+ let salt = section_builder.section_encoder.salt;
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 100_u32.into(),
- data: de_salt.derive::<100>().unwrap().to_vec(),
+ data: de_salt.derive::<100, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
@@ -402,35 +383,38 @@ fn section_builder_build_de_error_doesnt_advance_de_index() {
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 103_u32.into(),
- data: de_salt.derive::<10>().unwrap().to_vec(),
+ data: de_salt.derive::<10, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let mut expected = vec![];
- // metadata key
- expected.extend_from_slice(&metadata_key.0);
+ // identity_token
+ expected.extend_from_slice(identity_token.as_slice());
+ //section len
+ expected.push(2 + 100 + 2 + 10 + u8::try_from(SectionMic::CONTENTS_LEN).unwrap());
// de header
expected.extend_from_slice(&[0x80 + 100, 100]);
- // section 0 de 2
- expected.extend_from_slice(&salt.derive::<100>(Some(2.into())).unwrap());
+ // section 0 de 0
+ expected.extend_from_slice(&salt.derive::<100, CryptoProviderImpl>(Some(0.into())).unwrap());
// de header
expected.extend_from_slice(&[0x80 + 10, 103]);
- // section 0 de 3
- expected.extend_from_slice(&salt.derive::<10>(Some(3.into())).unwrap());
+ // section 0 de 1
+ expected.extend_from_slice(&salt.derive::<10, CryptoProviderImpl>(Some(1.into())).unwrap());
let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf),
- NonceAndCounter::from_nonce(salt.derive(Some(1.into())).unwrap()),
+ &key_seed_hkdf.v1_mic_extended_salt_keys().aes_key(),
+ NonceAndCounter::from_nonce(salt.compute_nonce::<CryptoProviderImpl>()),
);
- cipher.apply_keystream(&mut expected);
+ cipher.apply_keystream(&mut expected[..V1_IDENTITY_TOKEN_LEN]);
+ cipher.apply_keystream(&mut expected[V1_IDENTITY_TOKEN_LEN + 1..]);
let adv_bytes = adv_builder.into_advertisement();
// ignoring the MIC, etc, since that's tested elsewhere
- let ciphertext_end = adv_bytes.as_slice().len() - 16;
- assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + 19 + 2..ciphertext_end])
+ let ciphertext_end = adv_bytes.as_slice().len() - SectionMic::CONTENTS_LEN;
+ assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + EXTENDED_SALT_LEN..ciphertext_end])
}
#[test]
@@ -441,58 +425,63 @@ fn add_multiple_de_correct_de_offsets_mic_encrypted_identity() {
let key_seed = [22; 32];
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key = MetadataKey([33; 16]);
+ let identity_token = V1IdentityToken([33; 16]);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Trusted,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
- let salt =
- V1Salt::<CryptoProviderImpl>::from(*section_builder.section_encoder.salt.as_array_ref());
+ let salt = section_builder.section_encoder.salt;
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 64_u32.into(),
- data: de_salt.derive::<16>().unwrap().to_vec(),
+ data: de_salt.derive::<16, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 65_u32.into(),
- data: de_salt.derive::<16>().unwrap().to_vec(),
+ data: de_salt.derive::<16, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let mut expected = vec![];
- // metadata key
- expected.extend_from_slice(&metadata_key.0);
+ // identity_token
+ expected.extend_from_slice(identity_token.as_slice());
+ // section len, 2 des of 18 bytes each + section mic length
+ expected.push((18 * 2u8) + u8::try_from(SectionMic::CONTENTS_LEN).unwrap());
// de header
expected.extend_from_slice(&[0x90, 0x40]);
- // section 0 de 2
- expected.extend_from_slice(&salt.derive::<16>(Some(2.into())).unwrap());
+ // section 0 de 0
+ expected.extend_from_slice(&salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap());
// de header
expected.extend_from_slice(&[0x90, 0x41]);
- // section 0 de 3
- expected.extend_from_slice(&salt.derive::<16>(Some(3.into())).unwrap());
+ // section 0 de 1
+ expected.extend_from_slice(&salt.derive::<16, CryptoProviderImpl>(Some(1.into())).unwrap());
let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf),
- NonceAndCounter::from_nonce(salt.derive(Some(1.into())).unwrap()),
+ &key_seed_hkdf.v1_mic_extended_salt_keys().aes_key(),
+ NonceAndCounter::from_nonce(salt.derive::<12, CryptoProviderImpl>(None).unwrap()),
);
- cipher.apply_keystream(&mut expected);
+ cipher.apply_keystream(&mut expected[..V1_IDENTITY_TOKEN_LEN]);
+ cipher.apply_keystream(&mut expected[V1_IDENTITY_TOKEN_LEN + 1..]);
let adv_bytes = adv_builder.into_advertisement();
// ignoring the MIC, etc, since that's tested elsewhere
let ciphertext_end = adv_bytes.as_slice().len() - 16;
- assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + 19 + 2..ciphertext_end])
+ assert_eq!(&expected, &adv_bytes.as_slice()[1 + 1 + 16..ciphertext_end])
}
#[test]
@@ -503,61 +492,62 @@ fn add_multiple_de_correct_de_offsets_signature_encrypted_identity() {
let key_seed = [22; 32];
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key = MetadataKey([33; 16]);
- let key_pair = KeyPair::generate();
+ let identity_token = V1IdentityToken([33; 16]);
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cred = V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Trusted,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
- let salt =
- V1Salt::<CryptoProviderImpl>::from(*section_builder.section_encoder.salt.as_array_ref());
+ let salt = section_builder.section_encoder.salt;
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 64_u32.into(),
- data: de_salt.derive::<16>().unwrap().to_vec(),
+ data: de_salt.derive::<16, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
section_builder
.add_de(|de_salt| DummyDataElement {
de_type: 65_u32.into(),
- data: de_salt.derive::<16>().unwrap().to_vec(),
+ data: de_salt.derive::<16, CryptoProviderImpl>().unwrap().to_vec(),
})
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let mut expected = vec![];
- // metadata key
- expected.extend_from_slice(&metadata_key.0);
+ // identity token
+ expected.extend_from_slice(&identity_token.0);
+ //len
+ expected.push((18 * 2) + u8::try_from(SIGNATURE_LENGTH).unwrap());
// de header
expected.extend_from_slice(&[0x90, 0x40]);
- // section 0 de 2
- expected.extend_from_slice(&salt.derive::<16>(Some(2.into())).unwrap());
+ // section 0 de 0
+ expected.extend_from_slice(&salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap());
// de header
expected.extend_from_slice(&[0x90, 0x41]);
- // section 0 de 3
- expected.extend_from_slice(&salt.derive::<16>(Some(3.into())).unwrap());
+ // section 0 de 1
+ expected.extend_from_slice(&salt.derive::<16, CryptoProviderImpl>(Some(1.into())).unwrap());
- <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &key_seed_hkdf.extended_signed_section_aes_key(),
- NonceAndCounter::from_nonce(salt.derive(Some(1.into())).unwrap()),
- )
- .apply_keystream(&mut expected);
+ let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
+ &key_seed_hkdf.v1_signature_keys().aes_key(),
+ NonceAndCounter::from_nonce(salt.derive::<12, CryptoProviderImpl>(None).unwrap()),
+ );
+
+ cipher.apply_keystream(&mut expected[..V1_IDENTITY_TOKEN_LEN]);
+ cipher.apply_keystream(&mut expected[V1_IDENTITY_TOKEN_LEN + 1..]);
let adv_bytes = adv_builder.into_advertisement();
// ignoring the signature since that's tested elsewhere
assert_eq!(
&expected,
- // adv header + salt + section header + encryption info + identity header
- &adv_bytes.as_slice()[1 + 1 + 19 + 2..adv_bytes.as_slice().len() - 64]
+ // skip adv header + section header + salt
+ &adv_bytes.as_slice()[1 + 1 + 16..adv_bytes.as_slice().len() - 64]
)
}
@@ -568,17 +558,15 @@ fn signature_encrypted_section_de_lengths_allow_room_for_suffix() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
let key_seed = [22; 32];
- let metadata_key = MetadataKey([33; 16]);
- let key_pair = KeyPair::generate();
+ let metadata_key = V1IdentityToken([33; 16]);
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cred = V1BroadcastCredential::new(key_seed, metadata_key, private_key.clone());
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>(
&mut crypto_rng,
- EncryptedIdentityDataElementType::Trusted,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
@@ -596,7 +584,7 @@ fn signature_encrypted_section_de_lengths_allow_room_for_suffix() {
section_builder
.add_de(|_| DummyDataElement {
de_type: 100_u32.into(),
- data: vec![0; max_total_de_len - 100 - 1]
+ data: vec![0; max_total_de_len - 100 - 1],
})
.unwrap_err()
);
@@ -607,7 +595,7 @@ fn signature_encrypted_section_de_lengths_allow_room_for_suffix() {
section_builder
.add_de(|_| DummyDataElement {
de_type: 100_u32.into(),
- data: vec![0; max_total_de_len - 100 - 2]
+ data: vec![0; max_total_de_len - 100 - 2],
})
.unwrap_err()
);
@@ -617,152 +605,142 @@ fn signature_encrypted_section_de_lengths_allow_room_for_suffix() {
fn serialize_max_number_of_public_sections() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
for _ in 0..NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT {
- let mut section_builder =
- adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de(|_| DummyDataElement { de_type: 100_u32.into(), data: vec![0; 98] })
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
}
assert_eq!(
- adv_builder.section_builder(PublicSectionEncoder::default()).unwrap_err(),
+ adv_builder.section_builder(UnencryptedSectionEncoder).unwrap_err(),
MaxSectionCountExceeded
);
}
fn do_mic_encrypted_identity_fixed_key_material_test<W: WriteDataElement>(extra_des: &[W]) {
- let metadata_key = MetadataKey([1; 16]);
+ let identity_token = V1IdentityToken([1; 16]);
let key_seed = [2; 32];
let adv_header_byte = 0b00100000;
- let section_salt: V1Salt<CryptoProviderImpl> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
+ let section_salt: ExtendedV1Salt = [3; 16].into();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- V1Salt::from(*section_salt.as_array_ref()),
- &broadcast_cm,
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ section_salt,
+ &broadcast_cred,
))
.unwrap();
-
for de in extra_des {
section_builder.add_de(|_| de).unwrap();
}
- // length 53: 19 for encryption info, 18 for identity, 16 for MIC
- let section_length = 53
- + extra_des
- .iter()
- .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
- .sum::<u8>();
-
- let encryption_info = [
- &[
- 0x91, 0x10, // header
- 0x00, // scheme (mic)
- ],
- section_salt.as_slice(),
- ]
- .concat();
+ // now construct expected bytes
+ // mic length + length of des
+ let section_length = mic_section_len(extra_des);
- let identity_de_header =
- DeHeader { len: 16_u8.try_into().unwrap(), de_type: identity_type.type_code() };
-
- let mut hmac = np_hkdf::UnsignedSectionKeys::hmac_key(&key_seed_hkdf).build_hmac();
- // just to be sure, we'll construct our test hmac all in one update() call
- let mut hmac_input = vec![];
- hmac_input.extend_from_slice(NP_SVC_UUID.as_slice());
- hmac_input.push(adv_header_byte);
- // section header
- hmac_input.push(section_length);
- hmac_input.extend_from_slice(&encryption_info);
- let nonce = section_salt.derive::<{ AES_CTR_NONCE_LEN }>(Some(1.into())).unwrap();
- hmac_input.extend_from_slice(nonce.as_slice());
-
- hmac_input.extend_from_slice(identity_de_header.serialize().as_slice());
+ let mut hmac =
+ key_seed_hkdf.v1_mic_extended_salt_keys().mic_hmac_key().build_hmac::<CryptoProviderImpl>();
+ let nonce = section_salt.compute_nonce::<CryptoProviderImpl>();
let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf),
+ &key_seed_hkdf.v1_mic_extended_salt_keys().aes_key(),
NonceAndCounter::from_nonce(nonce),
);
- let mut plaintext = metadata_key.0.as_slice().to_vec();
+ // encrypt identity token and de contents
+ let mut plaintext_identity_token = identity_token.as_slice().to_vec();
+ cipher.apply_keystream(&mut plaintext_identity_token);
+ let ct_identity_token = plaintext_identity_token;
+
+ let mut de_contents = Vec::new();
for de in extra_des {
- plaintext.extend_from_slice(de.de_header().serialize().as_slice());
- let _ = de.write_de_contents(&mut plaintext);
+ de_contents.extend_from_slice(de.de_header().serialize().as_slice());
+ let _ = de.write_de_contents(&mut de_contents);
}
+ cipher.apply_keystream(&mut de_contents);
- cipher.apply_keystream(&mut plaintext);
- let ciphertext = plaintext;
-
- hmac_input.extend_from_slice(&ciphertext);
-
+ // just to be sure, we'll construct our test hmac all in one update() call
+ let mut hmac_input = vec![];
+ hmac_input.extend_from_slice(NP_SVC_UUID.as_slice());
+ hmac_input.push(adv_header_byte);
+ hmac_input.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ hmac_input.extend_from_slice(section_salt.as_slice());
+ hmac_input.extend_from_slice(nonce.as_slice());
+ hmac_input.extend_from_slice(&ct_identity_token);
+ hmac_input.push(section_length);
+ hmac_input.extend_from_slice(&de_contents);
hmac.update(&hmac_input);
let mic = hmac.finalize();
let mut expected = vec![];
+ expected.push(V1_ENCODING_ENCRYPTED_MIC_WITH_EXTENDED_SALT_AND_TOKEN);
+ expected.extend_from_slice(section_salt.as_slice());
+ expected.extend_from_slice(&ct_identity_token);
expected.push(section_length);
- expected.extend_from_slice(&encryption_info);
- expected.extend_from_slice(identity_de_header.serialize().as_slice());
- expected.extend_from_slice(&ciphertext);
+ expected.extend_from_slice(&de_contents);
expected.extend_from_slice(&mic[..16]);
- assert_eq!(&expected, section_builder.into_section().as_slice());
+ assert_eq!(&expected, section_builder.into_section::<CryptoProviderImpl>().as_slice());
+}
+
+/// Returns the length of a mic section containing `extra_des`
+fn mic_section_len<W: WriteDataElement>(extra_des: &[W]) -> u8 {
+ u8::try_from(SectionMic::CONTENTS_LEN).unwrap()
+ + extra_des
+ .iter()
+ .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
+ .sum::<u8>()
+}
+
+/// Returns the length of a signed section containing `extra_des`
+fn sig_section_len<W: WriteDataElement>(extra_des: &[W]) -> u8 {
+ u8::try_from(crypto_provider::ed25519::SIGNATURE_LENGTH).unwrap()
+ + extra_des
+ .iter()
+ .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
+ .sum::<u8>()
+}
+
+#[test]
+fn signature_encrypted_identity_section_empty() {
+ do_signature_encrypted_identity_fixed_key_material_test::<DummyDataElement>(&[]);
}
fn do_signature_encrypted_identity_fixed_key_material_test<W: WriteDataElement>(extra_des: &[W]) {
- let metadata_key = MetadataKey([1; 16]);
+ // input fixed credential data used to encode the adv
+ let identity_token = V1IdentityToken::from([1; 16]);
let key_seed = [2; 32];
- let adv_header_byte = 0b00100000;
- let section_salt: V1Salt<CryptoProviderImpl> = [3; 16].into();
- let identity_type = EncryptedIdentityDataElementType::Private;
+ let section_salt: ExtendedV1Salt = [3; 16].into();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let key_pair = KeyPair::generate();
-
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
+ let broadcast_cred = V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
+ // Build an adv given the provided DEs in extra_des
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
-
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- V1Salt::from(*section_salt.as_array_ref()),
- &broadcast_cm,
+ .section_builder(SignedEncryptedSectionEncoder::new::<CryptoProviderImpl>(
+ section_salt,
+ &broadcast_cred,
))
.unwrap();
-
for de in extra_des {
section_builder.add_de(|_| de).unwrap();
}
+ let section = section_builder.into_section::<CryptoProviderImpl>();
- // 19 for encryption info, 18 for identity, 64 for sig
- let section_length = 19
- + 18
- + 64
- + extra_des
- .iter()
- .map(|de| de.de_header().serialize().len() as u8 + de.de_header().len.as_u8())
- .sum::<u8>();
-
- let encryption_info = [
- &[
- 0x91, 0x10, // header
- 0x08, // scheme (signature)
- ],
- section_salt.as_slice(),
- ]
- .concat();
- let encryption_info: [u8; EncryptionInfo::TOTAL_DE_LEN] = encryption_info.try_into().unwrap();
-
- let identity_de_header =
- DeHeader { len: 16_u8.try_into().unwrap(), de_type: identity_type.type_code() };
- let identity_de_header: [u8; 2] = identity_de_header.serialize().as_slice().try_into().unwrap();
+ // now manually construct the expected output
+ let format = [V1_ENCODING_ENCRYPTED_SIGNATURE_WITH_EXTENDED_SALT_AND_TOKEN];
+ let salt_bytes = section_salt.as_slice();
+ let identity_token_bytes = identity_token.as_slice();
+ // len of de contents + signature
+ let section_length = sig_section_len(extra_des);
let mut section_body = Vec::new();
for de in extra_des {
@@ -770,49 +748,55 @@ fn do_signature_encrypted_identity_fixed_key_material_test<W: WriteDataElement>(
let _ = de.write_de_contents(&mut section_body);
}
- let nonce = section_salt.derive(Some(1.into())).unwrap();
+ let nonce = section_salt.compute_nonce::<CryptoProviderImpl>();
- let sig_payload = SectionSignaturePayload::from_deserialized_parts(
- adv_header_byte,
- section_length,
- &encryption_info,
+ let sig_payload = SectionSignaturePayload::new(
+ format.as_slice(),
+ salt_bytes,
&nonce,
- identity_de_header,
- metadata_key,
+ identity_token.as_slice(),
+ section_length,
&section_body,
);
+ let sig = sig_payload.sign::<Ed25519ProviderImpl>(&private_key).to_bytes();
- let mut plaintext = metadata_key.0.as_slice().to_vec();
- plaintext.extend_from_slice(section_body.as_slice());
- plaintext.extend_from_slice(&sig_payload.sign(&key_pair).to_bytes());
-
- <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
- &key_seed_hkdf.extended_signed_section_aes_key(),
+ let mut cipher = <CryptoProviderImpl as CryptoProvider>::AesCtr128::new(
+ &key_seed_hkdf.v1_signature_keys().aes_key(),
NonceAndCounter::from_nonce(nonce),
- )
- .apply_keystream(&mut plaintext);
- let ciphertext = plaintext;
+ );
+
+ let mut expected = vec![];
+ expected.extend_from_slice(&format);
+ expected.extend_from_slice(salt_bytes);
+
+ let mut ct_identity_token = Vec::new();
+ ct_identity_token.extend_from_slice(identity_token_bytes);
+ cipher.apply_keystream(&mut ct_identity_token);
+
+ expected.extend_from_slice(&ct_identity_token);
+ expected.push(section_length);
- let mut expected = vec![section_length];
+ let mut remaining_ct = Vec::new();
+ remaining_ct.extend_from_slice(&section_body);
+ remaining_ct.extend_from_slice(&sig);
+ cipher.apply_keystream(&mut remaining_ct);
- expected.extend_from_slice(&encryption_info);
- expected.extend_from_slice(&identity_de_header);
- expected.extend_from_slice(&ciphertext);
+ expected.extend_from_slice(&remaining_ct);
- assert_eq!(&expected, section_builder.into_section().as_slice());
+ assert_eq!(&expected, section.as_slice());
}
-/// Write `section_contents_len` bytes of DE and header into `section_builder`
+/// Write `section_contents_len` bytes of DE into `section_builder`
pub(crate) fn fill_section_builder<I: SectionEncoder>(
section_contents_len: usize,
section_builder: &mut SectionBuilder<&mut AdvBuilder, I>,
-) {
+) -> Result<(), AddDataElementError<GenericDataElementError>> {
+ let original_len = section_builder.section.len();
// DEs can only go up to 127, so we'll need multiple for long sections
for _ in 0..(section_contents_len / 100) {
let de_contents = vec![0x33; 98];
section_builder
- .add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &de_contents))
- .unwrap();
+ .add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &de_contents))?;
}
let remainder_len = section_contents_len % 100;
@@ -822,25 +806,24 @@ pub(crate) fn fill_section_builder<I: SectionEncoder>(
}
1 => {
// 1 byte header
- section_builder
- .add_de_res(|_| GenericDataElement::try_from(3_u32.into(), &[]))
- .unwrap();
+ section_builder.add_de_res(|_| GenericDataElement::try_from(3_u32.into(), &[]))?;
}
2 => {
// 2 byte header
- section_builder
- .add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &[]))
- .unwrap();
+ section_builder.add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &[]))?;
}
_ => {
// 2 byte header + contents as needed
- // leave room for section and DE headers
+ // leave room for section length, section header, and DE headers
let de_contents = vec![0x44; remainder_len - 2];
section_builder
- .add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &de_contents))
- .unwrap();
+ .add_de_res(|_| GenericDataElement::try_from(100_u32.into(), &de_contents))?;
}
}
+
+ assert_eq!(section_contents_len, section_builder.section.len() - original_len);
+
+ Ok(())
}
#[derive(Clone)]
@@ -860,17 +843,12 @@ impl WriteDataElement for DummyDataElement {
}
pub(crate) trait SectionBuilderExt {
- fn into_section(self) -> EncodedSection;
+ fn into_section<C: CryptoProvider>(self) -> EncodedSection;
}
impl<R: AsMut<AdvBuilder>, I: SectionEncoder> SectionBuilderExt for SectionBuilder<R, I> {
/// Convenience method for tests
- fn into_section(mut self) -> EncodedSection {
- let adv_builder_header_byte = self.adv_builder.as_mut().header_byte();
- Self::build_section(
- adv_builder_header_byte,
- self.section.into_inner(),
- self.section_encoder,
- )
+ fn into_section<C: CryptoProvider>(self) -> EncodedSection {
+ Self::build_section::<C>(self.header_len, self.section.into_inner(), self.section_encoder)
}
}
diff --git a/nearby/presence/np_adv/src/extended/serialize/test_vectors.rs b/nearby/presence/np_adv/src/extended/serialize/test_vectors.rs
index d03ad9b..829123c 100644
--- a/nearby/presence/np_adv/src/extended/serialize/test_vectors.rs
+++ b/nearby/presence/np_adv/src/extended/serialize/test_vectors.rs
@@ -16,31 +16,31 @@
extern crate std;
+use crate::credential::v1::V1BroadcastCredential;
+use crate::extended::de_type::DeType;
+use crate::extended::salt::V1Salt;
use crate::extended::serialize::AdvertisementType;
-use crate::{
- credential::{v1::V1, SimpleBroadcastCryptoMaterial},
- de_type::EncryptedIdentityDataElementType,
- extended::serialize::{
- section_tests::{DummyDataElement, SectionBuilderExt},
- AdvBuilder, MicEncryptedSectionEncoder,
- },
- MetadataKey,
+use crate::extended::serialize::{
+ section_tests::{DummyDataElement, SectionBuilderExt},
+ AdvBuilder, MicEncryptedSectionEncoder,
};
+use crate::extended::V1IdentityToken;
+use alloc::format;
use anyhow::anyhow;
-use crypto_provider::{aes::ctr::AES_CTR_NONCE_LEN, aes::AesKey};
+use crypto_provider::{aes::ctr::AES_CTR_NONCE_LEN, aes::AesKey, ed25519, CryptoProvider};
use crypto_provider_default::CryptoProviderImpl;
-use np_hkdf::v1_salt;
-use np_hkdf::v1_salt::V1Salt;
-use rand_ext::rand::{prelude::SliceRandom as _, Rng as _, SeedableRng as _};
+use np_hkdf::{v1_salt, DerivedSectionKeys};
use serde_json::json;
use std::{fs, io::Read as _, prelude::rust_2021::*, println};
-use strum::IntoEnumIterator as _;
use test_helper::extract_key_array;
+use test_vector_hkdf::TestVectorHkdf;
+
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
#[test]
fn mic_encrypted_test_vectors() -> Result<(), anyhow::Error> {
let full_path = test_helper::get_data_file(
- "presence/np_adv/resources/test/mic-encrypted-test-vectors.json",
+ "presence/np_adv/resources/test/mic-extended-salt-encrypted-test-vectors.json",
);
let mut file = fs::File::open(full_path)?;
let mut data = String::new();
@@ -54,12 +54,11 @@ fn mic_encrypted_test_vectors() -> Result<(), anyhow::Error> {
for tc in test_cases {
{
let key_seed = extract_key_array::<32>(&tc, "key_seed");
- let metadata_key = MetadataKey(extract_key_array::<16>(&tc, "metadata_key"));
+ let identity_token =
+ V1IdentityToken::from(extract_key_array::<16>(&tc, "identity_token"));
let adv_header_byte = extract_key_array::<1>(&tc, "adv_header_byte")[0];
- let section_salt = v1_salt::V1Salt::<CryptoProviderImpl>::from(
- extract_key_array::<16>(&tc, "section_salt"),
- );
- let identity_type = tc["identity_type"].as_str().map(identity_type_from_label).unwrap();
+ let section_salt =
+ v1_salt::ExtendedV1Salt::from(extract_key_array::<16>(&tc, "section_salt"));
let data_elements = tc["data_elements"]
.as_array()
.unwrap()
@@ -74,28 +73,31 @@ fn mic_encrypted_test_vectors() -> Result<(), anyhow::Error> {
assert_eq!(
extract_key_array::<16>(&tc, "aes_key").as_slice(),
- np_hkdf::UnsignedSectionKeys::aes_key(&hkdf).as_slice()
+ hkdf.v1_mic_extended_salt_keys().aes_key().as_slice()
);
assert_eq!(
extract_key_array::<32>(&tc, "section_mic_hmac_key").as_slice(),
- np_hkdf::UnsignedSectionKeys::hmac_key(&hkdf).as_bytes()
+ hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes()
);
assert_eq!(
extract_key_array::<{ AES_CTR_NONCE_LEN }>(&tc, "nonce").as_slice(),
- section_salt.derive::<{ AES_CTR_NONCE_LEN }>(Some(1.into())).unwrap()
+ section_salt.compute_nonce::<CryptoProviderImpl>()
);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
// make an adv builder in the configuration we need
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- assert_eq!(adv_header_byte, adv_builder.header_byte());
+ assert_eq!(adv_header_byte, adv_builder.adv_header().contents());
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
section_salt,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
@@ -105,7 +107,7 @@ fn mic_encrypted_test_vectors() -> Result<(), anyhow::Error> {
assert_eq!(
hex::decode(tc["encoded_section"].as_str().unwrap()).unwrap(),
- section_builder.into_section().as_slice()
+ section_builder.into_section::<CryptoProviderImpl>().as_slice()
);
}
}
@@ -116,41 +118,57 @@ fn mic_encrypted_test_vectors() -> Result<(), anyhow::Error> {
#[ignore]
#[test]
fn gen_mic_encrypted_test_vectors() {
- let mut rng = rand::rngs::StdRng::from_entropy();
-
let mut array = Vec::<serde_json::Value>::new();
- for _ in 0..100 {
- let num_des = rng.gen_range(0..=5);
-
- let extra_des = (0..num_des)
- .map(|_| {
- let de_len = rng.gen_range(0..=30);
- DummyDataElement {
- de_type: rng.gen_range(0_u32..=1_000).into(),
- data: rand_ext::random_vec_rc(&mut rng, de_len),
- }
- })
- .collect::<Vec<_>>();
-
- let metadata_key = MetadataKey(rng.gen());
- let key_seed = rng.gen();
+ for i in 0_u32..100 {
+ let test_vector_seed_hkdf = TestVectorHkdf::<CryptoProviderImpl>::new(
+ "NP V1 MIC test vectors HpakGBH8I+zbcEdxEanIT1r3bkgmL+mWI/kMrPiCzPw",
+ &i.to_be_bytes(),
+ );
+
+ let num_des = test_vector_seed_hkdf.derive_range_element("num des", 0_u64..=5);
+
+ let extra_des =
+ (0..num_des)
+ .map(|de_index| {
+ let de_len = test_vector_seed_hkdf
+ .derive_range_element(&format!("de len {}", de_index), 0..=30);
+ let data = test_vector_seed_hkdf
+ .derive_vec(&format!("de data {}", de_index), de_len.try_into().unwrap());
+ DummyDataElement {
+ de_type: DeType::from(
+ u32::try_from(test_vector_seed_hkdf.derive_range_element(
+ &format!("de type {}", de_index),
+ 0_u64..=1_000,
+ ))
+ .unwrap(),
+ ),
+ data,
+ }
+ })
+ .collect::<Vec<_>>();
+
+ let identity_token =
+ V1IdentityToken::from(test_vector_seed_hkdf.derive_array("identity token"));
+ let key_seed = test_vector_seed_hkdf.derive_array("key seed");
let adv_header_byte = 0b00100000;
- let identity_type =
- *EncryptedIdentityDataElementType::iter().collect::<Vec<_>>().choose(&mut rng).unwrap();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V1>::new(key_seed, metadata_key);
+ let broadcast_cred = V1BroadcastCredential::new(
+ key_seed,
+ identity_token,
+ ed25519::PrivateKey::generate::<Ed25519ProviderImpl>(),
+ );
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
- let section_salt = v1_salt::V1Salt::<CryptoProviderImpl>::from(rng.gen::<[u8; 16]>());
+ let section_salt =
+ v1_salt::ExtendedV1Salt::from(test_vector_seed_hkdf.derive_array::<16>("salt"));
let mut section_builder = adv_builder
- .section_builder(MicEncryptedSectionEncoder::<CryptoProviderImpl>::new(
- identity_type,
- V1Salt::from(*section_salt.as_array_ref()),
- &broadcast_cm,
+ .section_builder(MicEncryptedSectionEncoder::<_>::new::<CryptoProviderImpl>(
+ section_salt,
+ &broadcast_cred,
))
.unwrap();
@@ -158,42 +176,24 @@ fn gen_mic_encrypted_test_vectors() {
section_builder.add_de(|_| de).unwrap();
}
- let nonce = section_salt.derive::<{ AES_CTR_NONCE_LEN }>(Some(1.into())).unwrap();
-
- array
- .push(json!({
- "key_seed": hex::encode_upper(key_seed),
- "metadata_key": hex::encode_upper(metadata_key.0),
- "adv_header_byte": hex::encode_upper([adv_header_byte]),
- "section_salt": hex::encode_upper(section_salt.as_slice()),
- "identity_type": identity_type_label(identity_type),
- "data_elements": extra_des.iter().map(|de| json!({
- "de_type": de.de_type.as_u32(),
- "contents": hex::encode_upper(&de.data)
- })).collect::<Vec<_>>(),
- "aes_key": hex::encode_upper(np_hkdf::UnsignedSectionKeys::aes_key(&key_seed_hkdf).as_slice()),
- "nonce": hex::encode_upper(nonce),
- "section_mic_hmac_key": hex::encode_upper(np_hkdf::UnsignedSectionKeys::hmac_key(&key_seed_hkdf).as_bytes()),
- "encoded_section": hex::encode_upper(section_builder.into_section().as_slice())
- }));
+ let nonce = section_salt.compute_nonce::<CryptoProviderImpl>();
+ let keys = key_seed_hkdf.v1_mic_extended_salt_keys();
+ array.push(json!({
+ "key_seed": hex::encode_upper(key_seed),
+ "identity_token": hex::encode_upper(identity_token.as_slice()),
+ "adv_header_byte": hex::encode_upper([adv_header_byte]),
+ "section_salt": hex::encode_upper(section_salt.as_slice()),
+ "data_elements": extra_des.iter().map(|de| json!({
+ "de_type": de.de_type.as_u32(),
+ "contents": hex::encode_upper(&de.data)
+ })).collect::<Vec<_>>(),
+ "aes_key": hex::encode_upper(keys.aes_key().as_slice()),
+ "nonce": hex::encode_upper(nonce),
+ "section_mic_hmac_key": hex::encode_upper(keys.mic_hmac_key().as_bytes()),
+ "encoded_section": hex::encode_upper(section_builder.into_section::<CryptoProviderImpl>().as_slice())
+ }));
}
println!("{}", serde_json::ser::to_string_pretty(&array).unwrap());
-}
-
-fn identity_type_label(t: EncryptedIdentityDataElementType) -> &'static str {
- match t {
- EncryptedIdentityDataElementType::Private => "private",
- EncryptedIdentityDataElementType::Trusted => "trusted",
- EncryptedIdentityDataElementType::Provisioned => "provisioned",
- }
-}
-
-fn identity_type_from_label(label: &str) -> EncryptedIdentityDataElementType {
- match label {
- "private" => EncryptedIdentityDataElementType::Private,
- "trusted" => EncryptedIdentityDataElementType::Trusted,
- "provisioned" => EncryptedIdentityDataElementType::Provisioned,
- _ => panic!("unknown label: {}", label),
- }
+ panic!("Don't leave this test enabled. Meanwhile, enjoy the text output above.");
}
diff --git a/nearby/presence/np_adv/src/filter/mod.rs b/nearby/presence/np_adv/src/filter/mod.rs
index a2b2d9c..e2b37e7 100644
--- a/nearby/presence/np_adv/src/filter/mod.rs
+++ b/nearby/presence/np_adv/src/filter/mod.rs
@@ -16,21 +16,18 @@
//! a valid Nearby Presence advertisement and if so which was its corresponding identity
//! it matched with. Used as a first pass option to quickly check if a buffer should
//! further processed.
-use crate::credential::MatchedCredential;
+use crate::credential::matched::MatchedCredential;
+use crate::header::{NpVersionHeader, V0Encoding, V1AdvHeader};
use crate::legacy::data_elements::DataElementDeserializeError;
+use crate::legacy::deserialize::intermediate::{IntermediateAdvContents, LdtAdvContents};
use crate::legacy::deserialize::DecryptedAdvContents;
use crate::{
credential::{book::CredentialBook, v0::V0DiscoveryCryptoMaterial},
- legacy,
legacy::{
- actions,
- actions::ActionsDataElement,
- deserialize::{
- DecryptError, EncryptedAdvContents, IntermediateAdvContents, PlainDataElement,
- },
+ data_elements::actions::{self, ActionsDataElement},
+ deserialize::{DecryptError, DeserializedDataElement},
PacketFlavor,
},
- parse_adv_header, AdvHeader, V1Header,
};
use array_view::ArrayView;
use core::fmt::Debug;
@@ -91,7 +88,7 @@ pub struct V0DataElementsFilter {
}
/// The total number of unique boolean action types
-const NUM_ACTIONS: usize = 7;
+const NUM_ACTIONS: usize = 6;
/// Specify which specific actions bits to filter on, will filter on if any of the specified
/// actions are matched
@@ -117,17 +114,17 @@ impl FilterOptions {
B: CredentialBook<'a>,
P: CryptoProvider,
{
- parse_adv_header(adv)
+ NpVersionHeader::parse(adv)
.map(|(remaining, header)| match header {
- AdvHeader::V0 => {
+ NpVersionHeader::V0(encoding) => {
let filter = match self {
FilterOptions::V0FilterOptions(filter) => filter,
FilterOptions::Either(filter, _) => filter,
_ => return Err(NoMatch),
};
- filter.match_v0_adv::<B, P>(cred_book, remaining)
+ filter.match_v0_adv::<B, P>(encoding, cred_book, remaining)
}
- AdvHeader::V1(header) => {
+ NpVersionHeader::V1(header) => {
let filter = match self {
FilterOptions::V1FilterOptions(filter) => filter,
FilterOptions::Either(_, filter) => filter,
@@ -145,6 +142,7 @@ impl V0Filter {
/// match the filter criteria
fn match_v0_adv<'a, B, P>(
&self,
+ encoding: V0Encoding,
cred_book: &'a B,
remaining: &[u8],
) -> Result<FilterResult<B::Matched>, NoMatch>
@@ -153,16 +151,16 @@ impl V0Filter {
P: CryptoProvider,
{
let contents =
- legacy::deserialize::deserialize_adv_contents::<P>(remaining).map_err(|_| NoMatch)?;
+ IntermediateAdvContents::deserialize::<P>(encoding, remaining).map_err(|_| NoMatch)?;
match contents {
- IntermediateAdvContents::Plaintext(p) => match self.identity {
+ IntermediateAdvContents::Unencrypted(p) => match self.identity {
IdentityFilterType::Public | IdentityFilterType::Any => self
.data_elements
.match_v0_legible_adv(|| p.data_elements())
.map(|()| FilterResult::Public),
_ => Err(NoMatch),
},
- IntermediateAdvContents::Ciphertext(c) => match self.identity {
+ IntermediateAdvContents::Ldt(c) => match self.identity {
IdentityFilterType::Private | IdentityFilterType::Any => {
let (legible_adv, m) = try_decrypt_and_match::<B, P>(cred_book.v0_iter(), &c)?;
self.data_elements
@@ -177,7 +175,7 @@ impl V0Filter {
fn try_decrypt_and_match<'cred, B, P>(
v0_creds: B::V0Iterator,
- adv: &EncryptedAdvContents,
+ adv: &LdtAdvContents,
) -> Result<(DecryptedAdvContents, B::Matched), NoMatch>
where
B: CredentialBook<'cred>,
@@ -189,9 +187,6 @@ where
Ok(c) => return Ok((c, m)),
Err(e) => match e {
DecryptError::DecryptOrVerifyError => continue,
- DecryptError::DeserializeError(_) => {
- return Err(NoMatch);
- }
},
}
}
@@ -203,12 +198,14 @@ impl V0DataElementsFilter {
fn match_v0_legible_adv<F, I>(&self, data_elements: impl Fn() -> I) -> Result<(), NoMatch>
where
F: PacketFlavor,
- I: Iterator<Item = Result<PlainDataElement<F>, DataElementDeserializeError>>,
+ I: Iterator<Item = Result<DeserializedDataElement<F>, DataElementDeserializeError>>,
{
match &self.contains_tx_power {
None => Ok(()),
Some(c) => {
- if c == &data_elements().any(|de| matches!(de, Ok(PlainDataElement::TxPower(_)))) {
+ if c == &data_elements()
+ .any(|de| matches!(de, Ok(DeserializedDataElement::TxPower(_))))
+ {
Ok(())
} else {
Err(NoMatch)
@@ -224,7 +221,7 @@ impl V0DataElementsFilter {
}
// find if an actions DE exists, if so match on the provided action filter
let actions = data_elements().find_map(|de| match de {
- Ok(PlainDataElement::Actions(actions)) => Some(actions),
+ Ok(DeserializedDataElement::Actions(actions)) => Some(actions),
_ => None,
});
if let Some(actions) = actions {
@@ -262,11 +259,7 @@ impl V0ActionsFilter {
actions: &ActionsDataElement<F>,
) -> Result<(), NoMatch> {
for action in self.actions.as_slice().iter() {
- if actions
- .action
- .has_action(&action.expect("This will always contain Some"))
- .unwrap_or(false)
- {
+ if actions.action.has_action(action.expect("This will always contain Some")) {
return Ok(());
}
}
@@ -285,7 +278,7 @@ impl V1Filter {
&self,
_cred_book: &'a B,
_remaining: &[u8],
- _header: V1Header,
+ _header: V1AdvHeader,
) -> Result<FilterResult<B::Matched>, NoMatch>
where
B: CredentialBook<'a>,
diff --git a/nearby/presence/np_adv/src/filter/tests/actions_filter_tests.rs b/nearby/presence/np_adv/src/filter/tests/actions_filter_tests.rs
index ffdeeb9..c395124 100644
--- a/nearby/presence/np_adv/src/filter/tests/actions_filter_tests.rs
+++ b/nearby/presence/np_adv/src/filter/tests/actions_filter_tests.rs
@@ -15,8 +15,10 @@
#![allow(clippy::unwrap_used)]
use super::super::*;
-use crate::legacy::actions::{ActionBits, InstantTethering, NearbyShare};
+use crate::legacy::data_elements::actions::{ActionBits, InstantTethering, NearbyShare};
use crate::legacy::{Ciphertext, Plaintext};
+use alloc::vec::Vec;
+use strum::IntoEnumIterator;
#[test]
fn new_v0_actions_invalid_length() {
@@ -28,7 +30,7 @@ fn new_v0_actions_invalid_length() {
#[test]
fn new_v0_actions() {
- let actions = [actions::ActionType::ActiveUnlock; 7];
+ let actions = [actions::ActionType::ActiveUnlock; 5];
let result = V0ActionsFilter::new_from_slice(&actions);
assert!(result.is_ok());
}
@@ -55,16 +57,8 @@ fn test_actions_filter_all_actions_not_present() {
// default is all 0 bits
let action_bits = ActionBits::<Plaintext>::default();
- let filter = V0ActionsFilter::new_from_slice(&[
- actions::ActionType::ActiveUnlock,
- actions::ActionType::NearbyShare,
- actions::ActionType::InstantTethering,
- actions::ActionType::PhoneHub,
- actions::ActionType::Finder,
- actions::ActionType::FastPairSass,
- actions::ActionType::PresenceManager,
- ])
- .expect("7 is a valid length");
+ let filter = V0ActionsFilter::new_from_slice(&actions::ActionType::iter().collect::<Vec<_>>())
+ .expect("5 is a valid length");
assert_eq!(filter.match_v0_actions(&action_bits.into()), Err(NoMatch))
}
@@ -75,16 +69,8 @@ fn test_actions_filter_single_action_present() {
let mut action_bits = ActionBits::<Plaintext>::default();
action_bits.set_action(NearbyShare::from(true));
- let filter = V0ActionsFilter::new_from_slice(&[
- actions::ActionType::ActiveUnlock,
- actions::ActionType::NearbyShare,
- actions::ActionType::InstantTethering,
- actions::ActionType::PhoneHub,
- actions::ActionType::Finder,
- actions::ActionType::FastPairSass,
- actions::ActionType::PresenceManager,
- ])
- .expect("7 is a valid length");
+ let filter = V0ActionsFilter::new_from_slice(&actions::ActionType::iter().collect::<Vec<_>>())
+ .expect("5 is a valid length");
assert_eq!(filter.match_v0_actions(&action_bits.into()), Ok(()))
}
@@ -96,14 +82,12 @@ fn test_actions_filter_desired_action_not_present() {
action_bits.set_action(NearbyShare::from(true));
let filter = V0ActionsFilter::new_from_slice(&[
+ actions::ActionType::CallTransfer,
actions::ActionType::ActiveUnlock,
actions::ActionType::InstantTethering,
actions::ActionType::PhoneHub,
- actions::ActionType::Finder,
- actions::ActionType::FastPairSass,
- actions::ActionType::PresenceManager,
])
- .expect("6 is a valid length");
+ .expect("4 is a valid length");
assert_eq!(filter.match_v0_actions(&action_bits.into()), Err(NoMatch))
}
@@ -136,3 +120,8 @@ fn test_multiple_actions_set_both_present() {
assert_eq!(filter.match_v0_actions(&action_bits.into()), Ok(()))
}
+
+#[test]
+fn num_actions_is_correct() {
+ assert_eq!(actions::ActionType::iter().count(), NUM_ACTIONS);
+}
diff --git a/nearby/presence/np_adv/src/filter/tests/data_elements_filter_tests.rs b/nearby/presence/np_adv/src/filter/tests/data_elements_filter_tests.rs
index 4a893a2..0b83831 100644
--- a/nearby/presence/np_adv/src/filter/tests/data_elements_filter_tests.rs
+++ b/nearby/presence/np_adv/src/filter/tests/data_elements_filter_tests.rs
@@ -13,10 +13,16 @@
// limitations under the License.
use super::super::*;
-use crate::legacy::actions::{ActionBits, ActiveUnlock};
-use crate::legacy::data_elements::TxPowerDataElement;
-use crate::legacy::{Ciphertext, Plaintext};
-use crate::shared_data::TxPower;
+use crate::{
+ legacy::{
+ data_elements::{
+ actions::{ActionBits, ActiveUnlock},
+ tx_power::TxPowerDataElement,
+ },
+ Ciphertext, Plaintext,
+ },
+ shared_data::TxPower,
+};
#[test]
fn match_contains_tx_power() {
@@ -24,7 +30,7 @@ fn match_contains_tx_power() {
let tx_power = TxPower::try_from(5).expect("within range");
let result = filter.match_v0_legible_adv(|| {
- [Ok(PlainDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power.clone())))]
+ [Ok(DeserializedDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power)))]
.into_iter()
});
assert_eq!(result, Ok(()))
@@ -44,7 +50,7 @@ fn match_not_contains_actions() {
let filter = V0DataElementsFilter { contains_tx_power: None, actions_filter: Some(filter) };
let tx_power = TxPower::try_from(5).expect("within range");
let result = filter.match_v0_legible_adv(|| {
- [Ok(PlainDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power.clone())))]
+ [Ok(DeserializedDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power)))]
.into_iter()
});
assert_eq!(result, Err(NoMatch))
@@ -62,8 +68,8 @@ fn match_contains_actions() {
let result = filter.match_v0_legible_adv(|| {
[
- Ok(PlainDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power.clone()))),
- Ok(PlainDataElement::Actions(action_bits.into())),
+ Ok(DeserializedDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power))),
+ Ok(DeserializedDataElement::Actions(action_bits.into())),
]
.into_iter()
});
@@ -83,8 +89,8 @@ fn match_contains_both() {
let result = filter.match_v0_legible_adv(|| {
[
- Ok(PlainDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power.clone()))),
- Ok(PlainDataElement::Actions(action_bits.into())),
+ Ok(DeserializedDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power))),
+ Ok(DeserializedDataElement::Actions(action_bits.into())),
]
.into_iter()
});
@@ -100,7 +106,7 @@ fn match_contains_either() {
let tx_power = TxPower::try_from(5).expect("within range");
let result = filter.match_v0_legible_adv(|| {
- [Ok(PlainDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power.clone())))]
+ [Ok(DeserializedDataElement::<Ciphertext>::TxPower(TxPowerDataElement::from(tx_power)))]
.into_iter()
});
assert_eq!(result, Err(NoMatch))
diff --git a/nearby/presence/np_adv/src/filter/tests/mod.rs b/nearby/presence/np_adv/src/filter/tests/mod.rs
index 29d3e7c..42ab177 100644
--- a/nearby/presence/np_adv/src/filter/tests/mod.rs
+++ b/nearby/presence/np_adv/src/filter/tests/mod.rs
@@ -13,11 +13,13 @@
// limitations under the License.
use crate::credential::book::CredentialBookBuilder;
-use crate::credential::KeySeedMatchedCredential;
+use crate::credential::matched::KeySeedMatchedCredential;
+use crate::extended::V1_ENCODING_UNENCRYPTED;
use crate::filter::IdentityFilterType::Any;
use crate::filter::{
FilterOptions, FilterResult, NoMatch, V0DataElementsFilter, V0Filter, V1Filter,
};
+use crate::header::{VERSION_HEADER_V0_UNENCRYPTED, VERSION_HEADER_V1};
use crypto_provider_default::CryptoProviderImpl;
mod actions_filter_tests;
@@ -42,9 +44,9 @@ fn top_level_match_v0_adv() {
let result = filter.match_advertisement::<_, CryptoProviderImpl>(
&empty_cred_book,
&[
- 0x0, // adv header
- 0x03, // public DE
- 0x16, 0x00, // actions
+ VERSION_HEADER_V0_UNENCRYPTED,
+ 0x16,
+ 0x00, // actions
],
);
@@ -69,9 +71,9 @@ fn top_level_match_v0_adv_either() {
let result = filter.match_advertisement::<_, CryptoProviderImpl>(
&empty_cred_book,
&[
- 0x0, // adv header
- 0x03, // public DE
- 0x16, 0x00, // actions
+ VERSION_HEADER_V0_UNENCRYPTED,
+ 0x16,
+ 0x00, // actions
],
);
@@ -96,10 +98,11 @@ fn top_level_no_match_v0_adv() {
let result = filter.match_advertisement::<_, CryptoProviderImpl>(
&empty_cred_book,
&[
- 0x20, // V1 Advertisement header
+ VERSION_HEADER_V1,
0x03, // Section Header
- 0x03, // Public Identity DE header
- 0x15, 0x03, // Length 1 Tx Power DE with value 3
+ V1_ENCODING_UNENCRYPTED,
+ 0x15,
+ 0x03, // Length 1 Tx Power DE with value 3
],
);
diff --git a/nearby/presence/np_adv/src/filter/tests/v0_filter_tests.rs b/nearby/presence/np_adv/src/filter/tests/v0_filter_tests.rs
index 971a39e..9c60e2f 100644
--- a/nearby/presence/np_adv/src/filter/tests/v0_filter_tests.rs
+++ b/nearby/presence/np_adv/src/filter/tests/v0_filter_tests.rs
@@ -12,27 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#![allow(clippy::unwrap_used)]
+
use super::super::*;
use crate::credential::book::CredentialBookBuilder;
+use crate::credential::matched::{KeySeedMatchedCredential, ReferencedMatchedCredential};
use crate::credential::v0::{V0DiscoveryCredential, V0};
-use crate::credential::{
- KeySeedMatchedCredential, MatchableCredential, ReferencedMatchedCredential,
-};
+use crate::credential::{v0::V0BroadcastCredential, MatchableCredential};
use crate::filter::IdentityFilterType::{Any, Private, Public};
+use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+use crate::legacy::serialize::{AdvBuilder, LdtEncoder};
+use crate::shared_data::TxPower;
+use alloc::vec::Vec;
use crypto_provider_default::CryptoProviderImpl;
-use ldt_np_adv::NP_LEGACY_METADATA_KEY_LEN;
+use ldt_np_adv::V0_IDENTITY_TOKEN_LEN;
-const METADATA_KEY: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
+const IDENTITY_TOKEN: [u8; V0_IDENTITY_TOKEN_LEN] = [0x33; V0_IDENTITY_TOKEN_LEN];
const KEY_SEED: [u8; 32] = [0x11_u8; 32];
-const PRIVATE_IDENTITY_V0_ADV_CONTENTS: [u8; 19] = [
- 0x21, // private DE
- 0x22, 0x22, // salt
- // ciphertext
- 0x85, 0xBF, 0xA8, 0x83, 0x58, 0x7C, 0x50, 0xCF, 0x98, 0x38, 0xA7, 0x8A, 0xC0, 0x1C, 0x96, 0xF9,
-];
-const PUBLIC_IDENTITY_V0_ADV_CONTENTS: [u8; 3] = [
- 0x03, // public DE
+const PUBLIC_IDENTITY_V0_ADV_CONTENTS: [u8; 2] = [
0x16, 0x00, // actions
];
@@ -49,8 +47,11 @@ fn test_contains_public_identity() {
CryptoProviderImpl,
>(&[], &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PUBLIC_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &cred_book,
+ &PUBLIC_IDENTITY_V0_ADV_CONTENTS,
+ );
assert_eq!(result, Ok(FilterResult::Public));
}
@@ -68,8 +69,11 @@ fn test_not_contains_private() {
CryptoProviderImpl,
>(&[], &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PUBLIC_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ &PUBLIC_IDENTITY_V0_ADV_CONTENTS,
+ );
assert_eq!(result, Err(NoMatch));
}
@@ -87,8 +91,11 @@ fn test_contains_any_public() {
CryptoProviderImpl,
>(&[], &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PUBLIC_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &cred_book,
+ &PUBLIC_IDENTITY_V0_ADV_CONTENTS,
+ );
assert_eq!(result, Ok(FilterResult::Public));
}
@@ -106,8 +113,11 @@ fn test_not_contains_public_identity() {
CryptoProviderImpl,
>(&[], &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PRIVATE_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ v0_adv_contents().as_slice(),
+ );
assert_eq!(result, Err(NoMatch));
}
@@ -121,11 +131,12 @@ fn test_contains_private_identity() {
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&KEY_SEED);
let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&METADATA_KEY);
- let discovery_credential = V0DiscoveryCredential::new(KEY_SEED, metadata_key_hmac);
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&IDENTITY_TOKEN);
let match_data: KeySeedMatchedCredential = KEY_SEED.into();
- let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] =
- [MatchableCredential { discovery_credential, match_data: match_data.clone() }];
+ let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] = [MatchableCredential {
+ discovery_credential: V0DiscoveryCredential::new(KEY_SEED, metadata_key_hmac),
+ match_data: match_data.clone(),
+ }];
let cred_book = CredentialBookBuilder::<KeySeedMatchedCredential>::build_cached_slice_book::<
0,
@@ -133,8 +144,11 @@ fn test_contains_private_identity() {
CryptoProviderImpl,
>(&v0_creds, &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PRIVATE_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ v0_adv_contents().as_slice(),
+ );
assert_eq!(result, Ok(FilterResult::Private(ReferencedMatchedCredential::from(&match_data))));
}
@@ -148,11 +162,12 @@ fn test_contains_any_private_identity() {
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&KEY_SEED);
let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&METADATA_KEY);
- let discovery_credential = V0DiscoveryCredential::new(KEY_SEED, metadata_key_hmac);
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&IDENTITY_TOKEN);
let match_data: KeySeedMatchedCredential = KEY_SEED.into();
- let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] =
- [MatchableCredential { discovery_credential, match_data: match_data.clone() }];
+ let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] = [MatchableCredential {
+ discovery_credential: V0DiscoveryCredential::new(KEY_SEED, metadata_key_hmac),
+ match_data: match_data.clone(),
+ }];
let cred_book = CredentialBookBuilder::<KeySeedMatchedCredential>::build_cached_slice_book::<
0,
@@ -160,8 +175,11 @@ fn test_contains_any_private_identity() {
CryptoProviderImpl,
>(&v0_creds, &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PRIVATE_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ v0_adv_contents().as_slice(),
+ );
assert_eq!(result, Ok(FilterResult::Private(ReferencedMatchedCredential::from(&match_data))));
}
@@ -180,10 +198,11 @@ fn test_contains_private_identity_no_matching_credential() {
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&METADATA_KEY);
- let discovery_credential = V0DiscoveryCredential::new(key_seed, metadata_key_hmac);
- let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] =
- [MatchableCredential { discovery_credential, match_data: KEY_SEED.into() }];
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&IDENTITY_TOKEN);
+ let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] = [MatchableCredential {
+ discovery_credential: V0DiscoveryCredential::new(key_seed, metadata_key_hmac),
+ match_data: KEY_SEED.into(),
+ }];
let cred_book = CredentialBookBuilder::<KeySeedMatchedCredential>::build_cached_slice_book::<
0,
@@ -191,8 +210,11 @@ fn test_contains_private_identity_no_matching_credential() {
CryptoProviderImpl,
>(&v0_creds, &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PRIVATE_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ v0_adv_contents().as_slice(),
+ );
assert_eq!(result, Err(NoMatch));
}
@@ -204,9 +226,10 @@ fn test_contains_private_identity_invalid_hmac_match() {
data_elements: V0DataElementsFilter { contains_tx_power: None, actions_filter: None },
};
- let discovery_credential = V0DiscoveryCredential::new(KEY_SEED, [0u8; 32]);
- let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] =
- [MatchableCredential { discovery_credential, match_data: KEY_SEED.into() }];
+ let v0_creds: [MatchableCredential<V0, KeySeedMatchedCredential>; 1] = [MatchableCredential {
+ discovery_credential: V0DiscoveryCredential::new(KEY_SEED, [0u8; 32]),
+ match_data: KEY_SEED.into(),
+ }];
let cred_book = CredentialBookBuilder::<KeySeedMatchedCredential>::build_cached_slice_book::<
0,
@@ -214,8 +237,21 @@ fn test_contains_private_identity_invalid_hmac_match() {
CryptoProviderImpl,
>(&v0_creds, &[]);
- let result =
- filter.match_v0_adv::<_, CryptoProviderImpl>(&cred_book, &PRIVATE_IDENTITY_V0_ADV_CONTENTS);
+ let result = filter.match_v0_adv::<_, CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &cred_book,
+ v0_adv_contents().as_slice(),
+ );
assert_eq!(result, Err(NoMatch));
}
+
+/// Returns the contents of an advertisement after the version header.
+fn v0_adv_contents() -> Vec<u8> {
+ let broadcast_cm = V0BroadcastCredential::new(KEY_SEED, IDENTITY_TOKEN.into());
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new([0x22; 2].into(), &broadcast_cm));
+
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
+ builder.into_advertisement().unwrap().as_slice()[1..].to_vec()
+}
diff --git a/nearby/presence/np_adv/src/header.rs b/nearby/presence/np_adv/src/header.rs
new file mode 100644
index 0000000..dc0b96f
--- /dev/null
+++ b/nearby/presence/np_adv/src/header.rs
@@ -0,0 +1,165 @@
+// 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.
+
+//! NP version header (the first byte) support.
+//!
+//! The version header byte is 3 bits of version followed by 5 reserved bits.
+//!
+//! For V0 (`0b000`), the first 3 of the reserved bits identify the encoding
+//! scheme used, and the last 2 are still reserved.
+
+use nom::{combinator, number};
+
+// 3-bit versions (high 3 bits in version header)
+const PROTOCOL_VERSION_LEGACY: u8 = 0;
+const PROTOCOL_VERSION_EXTENDED: u8 = 1;
+
+// 3-bit encoding ids (3 bits after version, leaving 2 reserved bits)
+const V0_ENCODING_SCHEME_ID_UNENCRYPTED: u8 = 0;
+const V0_ENCODING_SCHEME_ID_LDT: u8 = 1;
+
+/// Version header byte for V1
+pub const VERSION_HEADER_V1: u8 = PROTOCOL_VERSION_EXTENDED << 5;
+
+/// Version header byte for V0 with the unencrypted encoding
+pub const VERSION_HEADER_V0_UNENCRYPTED: u8 =
+ (PROTOCOL_VERSION_LEGACY << 5) | (V0_ENCODING_SCHEME_ID_UNENCRYPTED << 2);
+
+/// Version header byte for V0 with the LDT encoding
+pub const VERSION_HEADER_V0_LDT: u8 =
+ (PROTOCOL_VERSION_LEGACY << 5) | (V0_ENCODING_SCHEME_ID_LDT << 2);
+
+/// The first byte in the NP svc data. It defines which version of the protocol
+/// is used for the rest of the svc data.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub(crate) enum NpVersionHeader {
+ V0(V0Encoding),
+ V1(V1AdvHeader),
+}
+
+impl NpVersionHeader {
+ /// Parse a NP advertisement header.
+ ///
+ /// This can be used on all versions of advertisements since it's the header that determines the
+ /// version.
+ ///
+ /// Returns a `nom::IResult` with the parsed header and the remaining bytes of the advertisement.
+ pub(crate) fn parse(adv: &[u8]) -> nom::IResult<&[u8], Self> {
+ combinator::map_opt(number::complete::u8, |version_header| match version_header {
+ VERSION_HEADER_V0_UNENCRYPTED => Some(NpVersionHeader::V0(V0Encoding::Unencrypted)),
+ VERSION_HEADER_V0_LDT => Some(NpVersionHeader::V0(V0Encoding::Ldt)),
+ VERSION_HEADER_V1 => Some(NpVersionHeader::V1(V1AdvHeader::new(version_header))),
+ _ => None,
+ })(adv)
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub(crate) enum V0Encoding {
+ Unencrypted,
+ Ldt,
+}
+
+/// A parsed NP Version Header that indicates the V1 protocol is in use.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub struct V1AdvHeader {
+ header_byte: u8,
+}
+
+impl V1AdvHeader {
+ pub(crate) fn new(header_byte: u8) -> Self {
+ Self { header_byte }
+ }
+
+ /// The version header byte
+ pub(crate) fn contents(&self) -> u8 {
+ self.header_byte
+ }
+}
+
+#[cfg(test)]
+#[allow(clippy::unwrap_used)]
+mod tests {
+ use super::*;
+
+ extern crate std;
+
+ use nom::error;
+
+ #[test]
+ fn parse_header_v0_unencrypted() {
+ let (_, header) = NpVersionHeader::parse(&[0x00]).unwrap();
+ assert_eq!(NpVersionHeader::V0(V0Encoding::Unencrypted), header);
+ }
+
+ #[test]
+ fn parse_header_v0_ldt() {
+ let (_, header) = NpVersionHeader::parse(&[0x04]).unwrap();
+ assert_eq!(NpVersionHeader::V0(V0Encoding::Ldt), header);
+ }
+
+ #[test]
+ fn parse_header_v0_nonzero_invalid_encoding() {
+ let input = &[0x08];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ input: input.as_slice(),
+ code: error::ErrorKind::MapOpt,
+ }),
+ NpVersionHeader::parse(input).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_header_v0_nonzero_reserved() {
+ let input = &[0x01];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ input: input.as_slice(),
+ code: error::ErrorKind::MapOpt,
+ }),
+ NpVersionHeader::parse(input).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_header_v1_nonzero_reserved() {
+ let input = &[0x30];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ input: input.as_slice(),
+ code: error::ErrorKind::MapOpt,
+ }),
+ NpVersionHeader::parse(input).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_header_bad_version() {
+ let input = &[0x80];
+ assert_eq!(
+ nom::Err::Error(error::Error {
+ input: input.as_slice(),
+ code: error::ErrorKind::MapOpt,
+ }),
+ NpVersionHeader::parse(input).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn parse_header_v1() {
+ let (_, header) = NpVersionHeader::parse(&[0x20]).unwrap();
+ assert_eq!(NpVersionHeader::V1(V1AdvHeader::new(0x20)), header);
+ }
+}
diff --git a/nearby/presence/np_adv/src/header_parse_tests.rs b/nearby/presence/np_adv/src/header_parse_tests.rs
deleted file mode 100644
index f6b5533..0000000
--- a/nearby/presence/np_adv/src/header_parse_tests.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-use super::*;
-
-extern crate std;
-
-use nom::error;
-
-#[test]
-fn parse_header_v0() {
- let (_, header) = parse_adv_header(&[0x00]).unwrap();
- assert_eq!(AdvHeader::V0, header);
-}
-
-#[test]
-fn parse_header_v0_nonzero_reserved() {
- let input = &[0x01];
- assert_eq!(
- nom::Err::Error(error::Error { input: input.as_slice(), code: error::ErrorKind::Verify }),
- parse_adv_header(input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_header_v1_nonzero_reserved() {
- let input = &[0x30];
- assert_eq!(
- nom::Err::Error(error::Error { input: input.as_slice(), code: error::ErrorKind::Verify }),
- parse_adv_header(input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_header_bad_version() {
- let input = &[0x80];
- assert_eq!(
- nom::Err::Error(error::Error { input: input.as_slice(), code: error::ErrorKind::Verify }),
- parse_adv_header(input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_header_v1() {
- let (_, header) = parse_adv_header(&[0x20]).unwrap();
- assert_eq!(AdvHeader::V1(V1Header { header_byte: 0x20 }), header);
-}
diff --git a/nearby/presence/np_adv/src/helpers.rs b/nearby/presence/np_adv/src/helpers.rs
new file mode 100644
index 0000000..f76fb9a
--- /dev/null
+++ b/nearby/presence/np_adv/src/helpers.rs
@@ -0,0 +1,39 @@
+// 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.
+
+use nom::{bytes, combinator};
+
+/// Nom parser for a `[u8; N]`.
+pub(crate) fn parse_byte_array<const N: usize>(input: &[u8]) -> nom::IResult<&[u8], [u8; N]> {
+ combinator::map_res(bytes::complete::take(N), |slice: &[u8]| slice.try_into())(input)
+}
+
+#[allow(clippy::unwrap_used)]
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn parse_empty_array() {
+ assert_eq!(([1_u8, 2, 3].as_slice(), []), parse_byte_array::<0>(&[1, 2, 3]).unwrap())
+ }
+
+ #[test]
+ fn parse_nonempty_array() {
+ assert_eq!(
+ ([4_u8, 5, 6].as_slice(), [1, 2, 3]),
+ parse_byte_array::<3>(&[1, 2, 3, 4, 5, 6]).unwrap()
+ )
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/actions/tests.rs b/nearby/presence/np_adv/src/legacy/actions/tests.rs
deleted file mode 100644
index 6e68211..0000000
--- a/nearby/presence/np_adv/src/legacy/actions/tests.rs
+++ /dev/null
@@ -1,368 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-
-use crate::legacy::{
- actions::*, serialize::ToDataElementBundle, Ciphertext, PacketFlavorEnum, Plaintext,
-};
-use std::collections;
-
-#[test]
-fn set_context_sync_works() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- actions.set_action(ContextSyncSeqNum::try_from(15).unwrap());
- assert_eq_hex(0xF0000000, actions.bits);
-
- assert_eq!(actions.bits_for_type(&ActionType::ContextSyncSeqNum), 15);
-}
-
-#[test]
-fn set_context_sync_doesnt_clobber_neighboring_bit() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- // set bit just below
- actions.bits |= 0x8000000;
-
- actions.set_action(ContextSyncSeqNum::try_from(15).unwrap());
- assert_eq_hex(0xF8000000, actions.bits);
-
- assert_eq!(actions.bits_for_type(&ActionType::ContextSyncSeqNum), 15);
-}
-
-#[test]
-fn unset_context_sync_works() {
- let mut actions = ActionBits::<Plaintext> {
- // all 1s
- bits: u32::MAX,
- ..Default::default()
- };
-
- actions.set_action(ContextSyncSeqNum::try_from(0).unwrap());
- assert_eq_hex(0x0FFFFFFF, actions.bits);
-
- assert_eq!(actions.bits_for_type(&ActionType::ContextSyncSeqNum), 0);
-}
-
-#[test]
-fn set_ns_works() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- actions.set_action(NearbyShare::from(true));
- assert_eq_hex(0x00400000, actions.bits);
-
- assert_eq!(actions.bits_for_type(&ActionType::NearbyShare), 1);
- assert_eq!(actions.bits_for_type(&ActionType::ActiveUnlock), 0);
- assert_eq!(actions.bits_for_type(&ActionType::InstantTethering), 0);
-}
-
-#[test]
-fn set_ns_doesnt_clobber_others() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- // set neighboring bits
- actions.bits |= 0x00120000;
-
- actions.set_action(NearbyShare::from(true));
- assert_eq_hex(0x00520000, actions.bits);
-
- assert_eq!(actions.bits_for_type(&ActionType::NearbyShare), 1);
- assert_eq!(actions.bits_for_type(&ActionType::PhoneHub), 1);
- assert_eq!(actions.bits_for_type(&ActionType::FastPairSass), 1);
-}
-
-#[test]
-fn unset_ns_works() {
- let mut actions = ActionBits::<Plaintext> {
- // all 1s
- bits: u32::MAX,
- ..Default::default()
- };
-
- actions.set_action(NearbyShare::from(false));
- assert_eq_hex(0xFFBFFFFF, actions.bits);
-}
-
-#[test]
-fn set_last_bit_works() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- actions.set_action(LastBit::from(true));
- assert_eq_hex(0x0100, actions.bits);
-}
-
-#[test]
-fn set_last_bit_doesnt_clobber_others() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- // set neighboring bits
- actions.bits |= 0x200;
-
- actions.set_action(LastBit::from(true));
- assert_eq_hex(0x300, actions.bits);
-}
-
-#[test]
-fn unset_last_bit_works() {
- let mut actions = ActionBits::<Plaintext> {
- // all 1s
- bits: u32::MAX,
- ..Default::default()
- };
-
- actions.set_action(LastBit::from(false));
- assert_eq_hex(0xFFFFFEFF, actions.bits);
-}
-
-#[test]
-fn bytes_used_works() {
- let mut actions = ActionBits::<Plaintext>::default();
-
- // Special-case: All-zeroes should lead to a single byte being used.
- assert_eq!(1, actions.bytes_used());
-
- actions.set_action(ContextSyncSeqNum::try_from(3).unwrap());
- assert_eq!(1, actions.bytes_used());
-
- actions.set_action(NearbyShare::from(true));
- assert_eq!(2, actions.bytes_used());
-
- actions.set_action(LastBit::from(true));
- assert_eq!(3, actions.bytes_used());
-
- actions.set_action(LastBit::from(false));
- assert_eq!(2, actions.bytes_used());
-}
-
-#[test]
-fn write_de_empty_actions() {
- // The special case of no action bits set should still occupy one byte [of all zeroes].
- let de = ActionsDataElement::<Plaintext>::from(ActionBits::default()).to_de_bundle();
-
- assert_eq!(&[0x00], de.contents_as_slice());
-}
-
-#[test]
-fn write_de_one_action_byte() {
- let mut action = ActionBits::default();
- action.set_action(ContextSyncSeqNum::try_from(7).unwrap());
- let de = ActionsDataElement::<Plaintext>::from(action).to_de_bundle();
-
- assert_eq!(&[0x70], de.contents_as_slice());
-}
-
-#[test]
-fn write_de_three_action_bytes() {
- let mut action = ActionBits::default();
- action.set_action(LastBit::from(true));
- let de = ActionsDataElement::<Plaintext>::from(action).to_de_bundle();
-
- assert_eq!(&[0, 0, 1], de.contents_as_slice());
-}
-
-#[test]
-fn write_de_all_plaintext_actions() {
- let mut action = all_plaintext_actions();
- action.set_action(LastBit::from(true));
- let de = ActionsDataElement::<Plaintext>::from(action).to_de_bundle();
-
- // byte 0: context sync
- // byte 1: nearby share, finder, fp sass
- // byte 2: last bit
- assert_eq!(&[0x90, 0x46, 0x01], de.contents_as_slice());
-}
-
-#[test]
-fn write_de_all_encrypted_actions() {
- let mut action = all_ciphertext_actions();
- action.set_action(LastBit::from(true));
- let de = ActionsDataElement::<Ciphertext>::from(action).to_de_bundle();
-
- // byte 1: context sync num = 9, 4 unused bits
- // byte 2: active unlock, nearby share, instant tethering, phone hub,
- // presence manager, last 3 bits unused
- // byte 3: last bit
- assert_eq!(&[0x90, 0xF8, 0x01], de.contents_as_slice());
-}
-
-#[test]
-fn action_element_nonzero_len() {
- for t in ActionType::iter() {
- assert!(t.bits_len() > 0);
- }
-}
-
-#[test]
-fn action_element_bits_dont_overlap() {
- let type_to_bits =
- ActionType::iter().map(|t| (t, t.all_bits())).collect::<collections::HashMap<_, _>>();
-
- for t in ActionType::iter() {
- let bits = type_to_bits.get(&t).unwrap();
-
- for (_, other_bits) in type_to_bits.iter().filter(|(other_type, _)| t != **other_type) {
- assert_eq!(0, bits & other_bits, "type {t:?}");
- }
- }
-}
-
-#[test]
-fn action_type_all_bits() {
- assert_eq!(0xF0000000, ActionType::ContextSyncSeqNum.all_bits());
- assert_eq!(0x00800000, ActionType::ActiveUnlock.all_bits());
- assert_eq!(0x00020000, ActionType::FastPairSass.all_bits());
-}
-
-#[test]
-fn action_type_all_bits_in_per_type_masks() {
- for t in ActionType::iter().filter(|t| t.supports_flavor(PacketFlavorEnum::Plaintext)) {
- assert_eq!(t.all_bits(), t.all_bits() & *ALL_PLAINTEXT_ELEMENT_BITS);
- }
- for t in ActionType::iter().filter(|t| t.supports_flavor(PacketFlavorEnum::Ciphertext)) {
- assert_eq!(t.all_bits(), t.all_bits() & *ALL_CIPHERTEXT_ELEMENT_BITS);
- }
-}
-
-#[test]
-fn action_bits_try_from_flavor_mismatch_plaintext() {
- assert_eq!(
- FlavorNotSupported { flavor: PacketFlavorEnum::Plaintext },
- ActionBits::<Plaintext>::try_from(ActionType::PresenceManager.all_bits()).unwrap_err()
- );
- assert_eq!(
- 0xF0000000,
- ActionBits::<Plaintext>::try_from(ActionType::ContextSyncSeqNum.all_bits()).unwrap().bits
- );
-}
-
-#[test]
-fn actions_de_deser_plaintext_with_ciphertext_action() {
- assert_eq!(
- DataElementDeserializeError::FlavorNotSupported {
- de_type: DataElementType::Actions,
- flavor: PacketFlavorEnum::Plaintext
- },
- <ActionsDataElement<Plaintext> as DataElement>::deserialize::<Plaintext>(&[
- // active unlock bit set
- 0x00, 0x80, 0x00,
- ])
- .unwrap_err()
- );
-}
-
-#[test]
-fn actions_de_deser_ciphertext_with_plaintext_action() {
- assert_eq!(
- DataElementDeserializeError::FlavorNotSupported {
- de_type: DataElementType::Actions,
- flavor: PacketFlavorEnum::Ciphertext
- },
- <ActionsDataElement<Ciphertext> as DataElement>::deserialize::<Ciphertext>(&[
- // Finder bit set
- 0x00, 0x00, 0x80,
- ])
- .unwrap_err()
- );
-}
-
-#[test]
-fn context_sync_seq_num_works() {
- let mut action_bits = ActionBits::<Plaintext>::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(15).unwrap());
- let action_de = ActionsDataElement::from(action_bits);
- assert_eq!(15, action_de.action.context_sync_seq_num().as_u8());
-}
-
-#[test]
-fn context_sync_seq_num_default_zero() {
- let action_bits = ActionBits::<Plaintext>::default();
- let action_de = ActionsDataElement::from(action_bits);
- assert_eq!(0, action_de.action.context_sync_seq_num().as_u8());
-}
-
-#[test]
-fn has_action_plaintext_works() {
- let mut action_bits = ActionBits::<Plaintext>::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(15).unwrap());
- action_bits.set_action(NearbyShare::from(true));
- let action_de = ActionsDataElement::from(action_bits);
- assert_eq!(action_de.action.has_action(&ActionType::NearbyShare), Some(true));
- assert_eq!(action_de.action.has_action(&ActionType::ActiveUnlock), Some(false));
- assert_eq!(action_de.action.has_action(&ActionType::PhoneHub), Some(false));
-}
-
-#[test]
-fn has_action_encrypted_works() {
- let mut action_bits = ActionBits::<Ciphertext>::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(15).unwrap());
- action_bits.set_action(NearbyShare::from(true));
- action_bits.set_action(ActiveUnlock::from(true));
- let action_de = ActionsDataElement::from(action_bits);
- assert_eq!(action_de.action.has_action(&ActionType::NearbyShare), Some(true));
- assert_eq!(action_de.action.has_action(&ActionType::ActiveUnlock), Some(true));
- assert_eq!(action_de.action.has_action(&ActionType::PhoneHub), Some(false));
- assert_eq!(action_de.action.has_action(&ActionType::ContextSyncSeqNum), None);
-}
-
-// hypothetical action using the last bit
-#[derive(Debug)]
-struct LastBit {
- enabled: bool,
-}
-impl From<bool> for LastBit {
- fn from(value: bool) -> Self {
- LastBit { enabled: value }
- }
-}
-impl ActionElement for LastBit {
- const HIGH_BIT_INDEX: u32 = 23;
- const BITS_LEN: u32 = 1;
-
- // don't want to add a variant for this test only type
- const ACTION_TYPE: ActionType = ActionType::ActiveUnlock;
-
- fn supports_flavor(_flavor: PacketFlavorEnum) -> bool {
- true
- }
-}
-
-macros::boolean_element_to_plaintext_element!(LastBit);
-macros::boolean_element_to_encrypted_element!(LastBit);
-
-fn assert_eq_hex(expected: u32, actual: u32) {
- assert_eq!(expected, actual, "{expected:#010X} != {actual:#010X}");
-}
-
-pub(crate) fn all_plaintext_actions() -> ActionBits<Plaintext> {
- let mut action = ActionBits::default();
- action.set_action(ContextSyncSeqNum::try_from(9).unwrap());
- action.set_action(NearbyShare::from(true));
- action.set_action(Finder::from(true));
- action.set_action(FastPairSass::from(true));
- action
-}
-
-pub(crate) fn all_ciphertext_actions() -> ActionBits<Ciphertext> {
- let mut action = ActionBits::default();
- action.set_action(ContextSyncSeqNum::try_from(9).unwrap());
- action.set_action(ActiveUnlock::from(true));
- action.set_action(NearbyShare::from(true));
- action.set_action(InstantTethering::from(true));
- action.set_action(PhoneHub::from(true));
- action.set_action(PresenceManager::from(true));
- action
-}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements.rs b/nearby/presence/np_adv/src/legacy/data_elements.rs
deleted file mode 100644
index c97cb25..0000000
--- a/nearby/presence/np_adv/src/legacy/data_elements.rs
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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.
-
-//! V0 data elements and core trait impls.
-use nom::error::{ErrorKind, FromExternalError};
-
-use crate::legacy::{
- de_type::{DataElementType, PlainDataElementType},
- serialize::{DataElementBundle, ToDataElementBundle},
- PacketFlavor, PacketFlavorEnum,
-};
-use crate::shared_data::*;
-
-/// Core behavior for data elements.
-///
-/// See also [ToDataElementBundle] for flavor-specific, infallible serialization.
-pub trait DataElement: Sized {
- /// The corresponding DataElementType variant.
- const DE_TYPE_VARIANT: DataElementType;
-
- /// Return true if the DE supports serialization and deserialization for the provided flavor.
- fn supports_flavor(flavor: PacketFlavorEnum) -> bool;
-
- /// Returns `Err` if the flavor is not supported or if parsing fails.
- ///
- /// `<F>` is the flavor of the packet being deserialized.
- fn deserialize<F: PacketFlavor>(
- de_contents: &[u8],
- ) -> Result<Self, DataElementDeserializeError>;
-}
-
-/// Errors possible when deserializing a DE
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub enum DataElementDeserializeError {
- /// The data element doesn't support the [PacketFlavor] of the advertisement packet.
- FlavorNotSupported {
- /// The DE type attempting to be deserialized
- de_type: DataElementType,
- /// The flavor that was not supported
- flavor: PacketFlavorEnum,
- },
- /// The data element couldn't be deserialized from the supplied data.
- DeserializeError {
- /// The DE type attempting to be deserialized
- de_type: DataElementType,
- },
- /// Only one identity data element is allowed in an advertisement, but a duplicate is found
- /// while parsing.
- DuplicateIdentityDataElement,
- /// There is unexpected data remaining in the incoming payload.
- UnexpectedDataRemaining,
- /// Parsing error returned from Nom.
- NomError(nom::error::ErrorKind),
-}
-
-impl FromExternalError<&[u8], DataElementDeserializeError> for DataElementDeserializeError {
- fn from_external_error(
- _input: &[u8],
- _kind: ErrorKind,
- e: DataElementDeserializeError,
- ) -> Self {
- e
- }
-}
-
-impl nom::error::ParseError<&[u8]> for DataElementDeserializeError {
- /// Creates an error from the input position and an [ErrorKind]
- fn from_error_kind(_input: &[u8], kind: ErrorKind) -> Self {
- Self::NomError(kind)
- }
-
- /// Combines an existing error with a new one created from the input
- /// position and an [ErrorKind]. This is useful when backtracking
- /// through a parse tree, accumulating error context on the way
- fn append(_input: &[u8], kind: ErrorKind, _other: Self) -> Self {
- Self::NomError(kind)
- }
-}
-
-/// Data element holding a [TxPower].
-#[derive(Debug, PartialEq, Eq)]
-pub struct TxPowerDataElement {
- /// The tx power value
- pub tx_power: TxPower,
-}
-
-impl TxPowerDataElement {
- /// Gets the underlying Tx Power value
- pub fn tx_power_value(&self) -> i8 {
- self.tx_power.as_i8()
- }
-}
-
-impl From<TxPower> for TxPowerDataElement {
- fn from(tx_power: TxPower) -> Self {
- Self { tx_power }
- }
-}
-
-impl<F: PacketFlavor> ToDataElementBundle<F> for TxPowerDataElement {
- fn to_de_bundle(&self) -> DataElementBundle<F> {
- let tx_power = self.tx_power.as_i8();
- DataElementBundle::try_from(
- PlainDataElementType::TxPower,
- tx_power.to_be_bytes().as_slice(),
- )
- .expect("Length < max DE size")
- }
-}
-
-impl DataElement for TxPowerDataElement {
- const DE_TYPE_VARIANT: DataElementType = DataElementType::TxPower;
-
- fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
- match flavor {
- PacketFlavorEnum::Plaintext => true,
- PacketFlavorEnum::Ciphertext => true,
- }
- }
- fn deserialize<F: PacketFlavor>(
- de_contents: &[u8],
- ) -> Result<Self, DataElementDeserializeError> {
- de_contents
- .try_into()
- .ok()
- .and_then(|arr: [u8; 1]| TxPower::try_from(i8::from_be_bytes(arr)).ok())
- .map(|tx_power| Self { tx_power })
- .ok_or(DataElementDeserializeError::DeserializeError {
- de_type: DataElementType::TxPower,
- })
- }
-}
diff --git a/nearby/presence/np_adv/src/legacy/actions/macros.rs b/nearby/presence/np_adv/src/legacy/data_elements/actions/macros.rs
index db241d6..3d1ab48 100644
--- a/nearby/presence/np_adv/src/legacy/actions/macros.rs
+++ b/nearby/presence/np_adv/src/legacy/data_elements/actions/macros.rs
@@ -38,9 +38,8 @@ macro_rules! boolean_element_struct_from_bool {
macro_rules! boolean_element_action_element_impl_shared {
($type_name:ident, $index:expr) => {
const HIGH_BIT_INDEX: u32 = $index;
- const BITS_LEN: u32 = 1;
- const ACTION_TYPE: $crate::legacy::actions::ActionType =
- $crate::legacy::actions::ActionType::$type_name;
+ const ACTION_TYPE: $crate::legacy::data_elements::actions::ActionType =
+ $crate::legacy::data_elements::actions::ActionType::$type_name;
};
}
@@ -49,11 +48,11 @@ macro_rules! boolean_element_action_element_impl_shared {
/// impls.
macro_rules! boolean_element {
($type_name:ident, $index:expr, ciphertext_only) => {
- $crate::legacy::actions::macros::boolean_element_struct!($type_name);
- $crate::legacy::actions::macros::boolean_element_struct_from_bool!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_struct!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_struct_from_bool!($type_name);
- impl $crate::legacy::actions::ActionElement for $type_name {
- $crate::legacy::actions::macros::boolean_element_action_element_impl_shared!(
+ impl $crate::legacy::data_elements::actions::ActionElement for $type_name {
+ $crate::legacy::data_elements::actions::macros::boolean_element_action_element_impl_shared!(
$type_name, $index
);
@@ -63,16 +62,20 @@ macro_rules! boolean_element {
$crate::legacy::PacketFlavorEnum::Ciphertext => true,
}
}
+
+ fn bits(&self) -> u8 {
+ self.enabled as u8
+ }
}
- $crate::legacy::actions::macros::boolean_element_to_encrypted_element!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_to_encrypted_element!($type_name);
};
($type_name:ident, $index:expr, plaintext_and_ciphertext) => {
- $crate::legacy::actions::macros::boolean_element_struct!($type_name);
- $crate::legacy::actions::macros::boolean_element_struct_from_bool!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_struct!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_struct_from_bool!($type_name);
- impl $crate::legacy::actions::ActionElement for $type_name {
- $crate::legacy::actions::macros::boolean_element_action_element_impl_shared!(
+ impl $crate::legacy::data_elements::actions::ActionElement for $type_name {
+ $crate::legacy::data_elements::actions::macros::boolean_element_action_element_impl_shared!(
$type_name, $index
);
@@ -82,31 +85,33 @@ macro_rules! boolean_element {
$crate::legacy::PacketFlavorEnum::Ciphertext => true,
}
}
+
+ fn bits(&self) -> u8 {
+ self.enabled as u8
+ }
}
- $crate::legacy::actions::macros::boolean_element_to_plaintext_element!($type_name);
- $crate::legacy::actions::macros::boolean_element_to_encrypted_element!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_to_plaintext_element!($type_name);
+ $crate::legacy::data_elements::actions::macros::boolean_element_to_encrypted_element!($type_name);
};
}
-/// Create a [`ToActionElement<Encrypted>`](super::ToActionElement) impl with the given index and length 1.
+/// Create a [`ToActionElement<Encrypted>`](super::ActionElementFlavor) impl with the given index and length 1.
macro_rules! boolean_element_to_encrypted_element {
( $type_name:ident) => {
- impl $crate::legacy::actions::ToActionElement<$crate::legacy::Ciphertext> for $type_name {
- fn bits(&self) -> u8 {
- self.enabled as u8
- }
+ impl $crate::legacy::data_elements::actions::ActionElementFlavor<$crate::legacy::Ciphertext>
+ for $type_name
+ {
}
};
}
-/// Create a [`ToActionElement<Plaintext>`](super::ToActionElement) impl with the given index and length 1.
+/// Create a [`ToActionElement<Plaintext>`](super::ActionElementFlavor) impl with the given index and length 1.
macro_rules! boolean_element_to_plaintext_element {
( $type_name:ident) => {
- impl $crate::legacy::actions::ToActionElement<$crate::legacy::Plaintext> for $type_name {
- fn bits(&self) -> u8 {
- self.enabled as u8
- }
+ impl $crate::legacy::data_elements::actions::ActionElementFlavor<$crate::legacy::Plaintext>
+ for $type_name
+ {
}
};
}
diff --git a/nearby/presence/np_adv/src/legacy/actions/mod.rs b/nearby/presence/np_adv/src/legacy/data_elements/actions/mod.rs
index e0f4514..36ac35d 100644
--- a/nearby/presence/np_adv/src/legacy/actions/mod.rs
+++ b/nearby/presence/np_adv/src/legacy/data_elements/actions/mod.rs
@@ -17,19 +17,24 @@
//! This DE is somewhat more complex than other DEs. Whether or not it supports a particular flavor
//! depends on the actions set, so it has to be treated as two separate types based on which
//! flavor type parameter is used.
+use crate::legacy::data_elements::{DirectMapPredicate, DirectMapper, LengthMapper};
use crate::{
legacy::{
- data_elements::{DataElement, DataElementDeserializeError},
- de_type::{DataElementType, PlainDataElementType},
- serialize::{DataElementBundle, ToDataElementBundle},
- Ciphertext, PacketFlavor, PacketFlavorEnum, Plaintext,
+ data_elements::{
+ de_type::{DeActualLength, DeEncodedLength, DeTypeCode},
+ DataElementDeserializeError, DataElementSerializationBuffer, DataElementSerializeError,
+ DeserializeDataElement, SerializeDataElement,
+ },
+ PacketFlavor, PacketFlavorEnum,
},
- shared_data::ContextSyncSeqNum,
+ private::Sealed,
};
+
#[cfg(feature = "devtools")]
use core::ops::Range;
-use core::{marker, num, ops};
+use core::{marker, ops};
use nom::{bytes, combinator, error};
+use sink::Sink;
use strum::IntoEnumIterator as _;
mod macros;
@@ -40,39 +45,40 @@ pub(crate) mod tests;
/// Only as many DE payload bytes will be present as needed to represent all set bits that are encoded,
/// with a lower bound of 1 byte in the special case of no set action bits, and an upper bound
/// of 3 bytes occupied by the DE payload.
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ActionsDataElement<F: PacketFlavor> {
/// The action bits
pub action: ActionBits<F>,
}
+/// Max length of an actions DE contents
pub(crate) const ACTIONS_MAX_LEN: usize = 3;
+/// Range of valid actual lengths
+pub(crate) const ACTIONS_VALID_ACTUAL_LEN: ops::RangeInclusive<usize> = 1..=ACTIONS_MAX_LEN;
impl<F> ActionsDataElement<F>
where
F: PacketFlavor,
- ActionsDataElement<F>: DataElement,
{
- pub(crate) const ACTIONS_LEN: ops::RangeInclusive<usize> = (1..=ACTIONS_MAX_LEN);
-
- /// Generic deserialize, not meant to be called directly -- use [DataElement] impls instead.
+ /// Generic deserialize, not meant to be called directly -- use [DeserializeDataElement] impls instead.
+ #[allow(clippy::assertions_on_constants)]
fn deserialize(de_contents: &[u8]) -> Result<Self, DataElementDeserializeError> {
combinator::all_consuming::<&[u8], _, error::Error<&[u8]>, _>(combinator::map(
bytes::complete::take_while_m_n(0, ACTIONS_MAX_LEN, |_| true),
|bytes: &[u8]| {
+ // pack bits into u32 for convenient access
+ debug_assert!(4 >= ACTIONS_MAX_LEN, "Actions must fit in u32");
let mut action_bytes = [0_u8; 4];
action_bytes[..bytes.len()].copy_from_slice(bytes);
u32::from_be_bytes(action_bytes)
},
))(de_contents)
- .map_err(|_| DataElementDeserializeError::DeserializeError {
- de_type: Self::DE_TYPE_VARIANT,
- })
+ .map_err(|_| DataElementDeserializeError::DeserializeError { de_type: Self::DE_TYPE_CODE })
.map(|(_remaining, actions)| actions)
.and_then(|action_bits_num| {
let action = ActionBits::try_from(action_bits_num).map_err(|e| {
DataElementDeserializeError::FlavorNotSupported {
- de_type: Self::DE_TYPE_VARIANT,
+ de_type: Self::DE_TYPE_CODE,
flavor: e.flavor,
}
})?;
@@ -87,62 +93,57 @@ impl<F: PacketFlavor> From<ActionBits<F>> for ActionsDataElement<F> {
}
}
-impl<F: PacketFlavor> ToDataElementBundle<F> for ActionsDataElement<F> {
- fn to_de_bundle(&self) -> DataElementBundle<F> {
- let action_byte_len = self.action.bytes_used();
- let slice = &self.action.bits.to_be_bytes()[..action_byte_len];
+impl<F: PacketFlavor> Sealed for ActionsDataElement<F> {}
- DataElementBundle::try_from(PlainDataElementType::Actions, slice)
- .expect("Length < max DE size")
+impl<F: PacketFlavor> SerializeDataElement<F> for ActionsDataElement<F> {
+ fn de_type_code(&self) -> DeTypeCode {
+ ActionsDataElement::<F>::DE_TYPE_CODE
}
-}
-impl DataElement for ActionsDataElement<Plaintext> {
- const DE_TYPE_VARIANT: DataElementType = DataElementType::Actions;
-
- fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
- match flavor {
- PacketFlavorEnum::Plaintext => true,
- PacketFlavorEnum::Ciphertext => false,
- }
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ <Self as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual_len)
}
- fn deserialize<F: PacketFlavor>(
- de_contents: &[u8],
- ) -> Result<Self, DataElementDeserializeError> {
- match F::ENUM_VARIANT {
- PacketFlavorEnum::Plaintext => ActionsDataElement::deserialize(de_contents),
- PacketFlavorEnum::Ciphertext => Err(DataElementDeserializeError::FlavorNotSupported {
- de_type: DataElementType::Actions,
- flavor: F::ENUM_VARIANT,
- }),
- }
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ let used = self.action.bytes_used();
+ sink.try_extend_from_slice(&self.action.bits.to_be_bytes()[..used])
+ .ok_or(DataElementSerializeError::InsufficientSpace)
}
}
-impl DataElement for ActionsDataElement<Ciphertext> {
- const DE_TYPE_VARIANT: DataElementType = DataElementType::Actions;
+impl<E: PacketFlavor> DeserializeDataElement for ActionsDataElement<E> {
+ const DE_TYPE_CODE: DeTypeCode = match DeTypeCode::try_from(0b0110) {
+ Ok(t) => t,
+ Err(_) => unreachable!(),
+ };
- fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
- match flavor {
- PacketFlavorEnum::Plaintext => false,
- PacketFlavorEnum::Ciphertext => true,
- }
- }
+ type LengthMapper = DirectMapper<ActionsLengthPredicate>;
fn deserialize<F: PacketFlavor>(
de_contents: &[u8],
) -> Result<Self, DataElementDeserializeError> {
- match F::ENUM_VARIANT {
- PacketFlavorEnum::Plaintext => Err(DataElementDeserializeError::FlavorNotSupported {
- de_type: DataElementType::Actions,
+ if E::ENUM_VARIANT == F::ENUM_VARIANT {
+ ActionsDataElement::deserialize(de_contents)
+ } else {
+ Err(DataElementDeserializeError::FlavorNotSupported {
+ de_type: Self::DE_TYPE_CODE,
flavor: F::ENUM_VARIANT,
- }),
- PacketFlavorEnum::Ciphertext => ActionsDataElement::deserialize(de_contents),
+ })
}
}
}
+pub(in crate::legacy) struct ActionsLengthPredicate;
+
+impl DirectMapPredicate for ActionsLengthPredicate {
+ fn is_valid(len: usize) -> bool {
+ ACTIONS_VALID_ACTUAL_LEN.contains(&len)
+ }
+}
+
/// Container for the 24 bits defined for "actions" (feature flags and the like).
/// This internally stores a u32, but only the 24 highest bits of this
/// field will actually ever be populated.
@@ -162,14 +163,8 @@ impl<F: PacketFlavor> ActionBits<F> {
/// Return whether a boolean action type is set in this data element, or `None` if the given
/// action type does not represent a boolean.
- pub fn has_action(&self, action_type: &ActionType) -> Option<bool> {
- (action_type.bits_len() == 1).then_some(self.bits_for_type(action_type) != 0)
- }
-
- /// Return the context sync sequence number.
- pub fn context_sync_seq_num(&self) -> ContextSyncSeqNum {
- ContextSyncSeqNum::try_from(self.bits_for_type(&ActionType::ContextSyncSeqNum) as u8)
- .expect("Masking with ActionType::ContextSyncSeqNum should always be in range")
+ pub fn has_action(&self, action_type: ActionType) -> bool {
+ self.bits_for_type(action_type) != 0
}
}
@@ -223,29 +218,28 @@ impl<F: PacketFlavor> ActionBits<F> {
/// Set the bits for the provided element.
/// Bits outside the range set by the action will be unaffected.
- pub fn set_action<E: ToActionElement<F>>(&mut self, to_element: E) {
- let element = to_element.to_action_element();
- let len = element.len.get();
+ pub fn set_action<E: ActionElementFlavor<F>>(&mut self, action_element: E) {
+ let bits = action_element.bits();
// validate that the element is not horribly broken
- debug_assert!(len + element.index <= 32);
- // must not have bits set past the high `len` bits
- debug_assert_eq!(0, element.bits >> (8 - len));
+ debug_assert!(E::HIGH_BIT_INDEX < 32);
+ // must not have bits set past the low `len` bits
+ debug_assert_eq!(0, bits >> 1);
// 0-extend to u32
- let byte_extended = element.bits as u32;
+ let byte_extended = bits as u32;
// Shift so that the high bit is at the desired index.
// Won't overflow since length > 0.
- let bits_in_position = byte_extended << (32 - len - element.index);
+ let bits_in_position = byte_extended << (31 - E::HIGH_BIT_INDEX);
// We want to effectively clear out the bits already in place, so we don't want to just |=.
// Instead, we construct a u32 with all 1s above and below the relevant bits and &=, so that
// if the new bits are 0, the stored bits will be cleared.
// avoid overflow when index = 0 -- need zero 1 bits to the left in that case
- let left_1s = u32::MAX.checked_shl(32 - element.index).unwrap_or(0);
+ let left_1s = u32::MAX.checked_shl(32 - E::HIGH_BIT_INDEX).unwrap_or(0);
// avoid underflow when index + len = 32 -- zero 1 bits to the right
- let right_1s = u32::MAX.checked_shr(element.index + len).unwrap_or(0);
+ let right_1s = u32::MAX.checked_shr(E::HIGH_BIT_INDEX + 1).unwrap_or(0);
let mask = left_1s | right_1s;
let bits_for_other_actions = self.bits & mask;
self.bits = bits_for_other_actions | bits_in_position;
@@ -254,7 +248,7 @@ impl<F: PacketFlavor> ActionBits<F> {
/// How many bytes (1-3) are needed to represent the set bits, starting from the most
/// significant bit. The lower bound of 1 is because the unique special case of
/// an actions field of all zeroes is required by the spec to occupy exactly one byte.
- pub(crate) fn bytes_used(&self) -> usize {
+ fn bytes_used(&self) -> usize {
let bits_used = 32 - self.bits.trailing_zeros();
let raw_count = (bits_used as usize + 7) / 8;
if raw_count == 0 {
@@ -268,94 +262,52 @@ impl<F: PacketFlavor> ActionBits<F> {
///
/// For example, when extracting the bits `B` from `0bXXXXXXXXXXBBBBBBXXXXXXXXXXXXXXXX`, the
/// return value will be `0b00000000000000000000000000BBBBBB`.
- pub fn bits_for_type(&self, action_type: &ActionType) -> u32 {
- self.bits << action_type.high_bit_index() >> (32 - action_type.bits_len())
+ pub fn bits_for_type(&self, action_type: ActionType) -> u32 {
+ self.bits << action_type.high_bit_index() >> (31)
}
}
-/// The encoded form of an individual action element.
-#[derive(Debug, Clone, Copy)]
-pub struct ActionElementBits<F: PacketFlavor> {
- /// Offset from the high bit in `ActionBits.bits`, which would be bit 0 of byte 0 of the big-endian
- /// representation.
- /// Must leave enough room for `len` bits in a u32; that is, `index + len <= 32`.
- index: u32,
- /// Number of bits used.
- /// `len + index <= 32` must be true.
- len: num::NonZeroU32,
- /// Returns the bits to set as the lower `len` bits of the byte.
- bits: u8,
- /// Marker for whether it can be used in plaintext or encrypted data elements.
- flavor: marker::PhantomData<F>,
-}
-
/// Core trait for an individual action
pub trait ActionElement {
- /// The offset from the high bit in the eventual bit sequence of all actions.
- /// See [ActionElementBits.index].
+ /// The assigned offset for this type from the high bit in the eventual bit sequence of all
+ /// actions.
///
- /// Each implementation must have a non-overlapping sequence of bits defined by
- /// `HIGH_BIT_INDEX` and `BITS_LEN` w.r.t every other implementation.
+ /// Each implementation must have a non-conflicting index defined by
+ /// [Self::HIGH_BIT_INDEX]
const HIGH_BIT_INDEX: u32;
- /// The number of high bits in a `u8` that should be used when assembling the complete
- /// action bit vector.
- ///
- /// Must be >0.
- const BITS_LEN: u32;
+
/// Forces implementations to have a matching enum variant so the enum can be kept up to date.
const ACTION_TYPE: ActionType;
- /// Returns whether or not this action supports the provided `flavor`.
+ /// Returns whether this action supports the provided `flavor`.
///
- /// Must match the implementations of [ToActionElement].
+ /// Must match the implementations of [ActionElementFlavor].
fn supports_flavor(flavor: PacketFlavorEnum) -> bool;
- /// Returns true if the bits for this element are all zero, or if the flavor is supported.
- fn action_is_supported_or_not_set(bits: u32, flavor: PacketFlavorEnum) -> bool {
- let shifted = bits << Self::HIGH_BIT_INDEX;
- let masked = shifted & (!(u32::MAX >> Self::BITS_LEN));
-
- (masked == 0) || Self::supports_flavor(flavor)
- }
-}
-
-/// An analog of `Into` tailored to converting structs modeling specific action elements into the
-/// representation needed by [ActionBits].
-pub trait ToActionElement<F: PacketFlavor>: ActionElement {
- /// Convert the high-level representation of an element into the literal bits needed.
- fn to_action_element(&self) -> ActionElementBits<F> {
- ActionElementBits {
- index: Self::HIGH_BIT_INDEX,
- len: Self::BITS_LEN.try_into().expect("all elements must have nonzero len"),
- bits: self.bits(),
- flavor: marker::PhantomData,
- }
- }
-
- /// Returns the bits that should be set starting at `Self::INDEX`.
- ///
- /// Must not have more than the low `len()` bits set.
+ /// Returns the low bit that should be included in the final bit vector
+ /// starting at [Self::HIGH_BIT_INDEX].
fn bits(&self) -> u8;
}
+/// Marker trait indicating support for a particular [PacketFlavor].
+pub trait ActionElementFlavor<F: PacketFlavor>: ActionElement {}
+
/// Provides a way to iterate over all action types.
#[derive(Clone, Copy, strum_macros::EnumIter, PartialEq, Eq, Hash, Debug)]
#[allow(missing_docs)]
pub enum ActionType {
- ContextSyncSeqNum,
+ CrossDevSdk,
+ CallTransfer,
ActiveUnlock,
NearbyShare,
InstantTethering,
PhoneHub,
- Finder,
- FastPairSass,
- PresenceManager,
}
impl ActionType {
/// A u32 with all possible bits for this action type set
const fn all_bits(&self) -> u32 {
- (u32::MAX << (32_u32 - self.bits_len())) >> self.high_bit_index()
+ (u32::MAX << (31_u32)) >> self.high_bit_index()
}
/// Get the range of the bits occupied used by this bit index. For example, if the action type
@@ -364,80 +316,36 @@ impl ActionType {
#[cfg(feature = "devtools")]
pub const fn bits_range_for_devtools(&self) -> Range<u32> {
let high_bit_index = self.high_bit_index();
- high_bit_index..high_bit_index + self.bits_len()
+ high_bit_index..high_bit_index + 1
}
const fn high_bit_index(&self) -> u32 {
match self {
- ActionType::ContextSyncSeqNum => ContextSyncSeqNum::HIGH_BIT_INDEX,
+ ActionType::CrossDevSdk => CrossDevSdk::HIGH_BIT_INDEX,
+ ActionType::CallTransfer => CallTransfer::HIGH_BIT_INDEX,
ActionType::ActiveUnlock => ActiveUnlock::HIGH_BIT_INDEX,
ActionType::NearbyShare => NearbyShare::HIGH_BIT_INDEX,
ActionType::InstantTethering => InstantTethering::HIGH_BIT_INDEX,
ActionType::PhoneHub => PhoneHub::HIGH_BIT_INDEX,
- ActionType::Finder => Finder::HIGH_BIT_INDEX,
- ActionType::FastPairSass => FastPairSass::HIGH_BIT_INDEX,
- ActionType::PresenceManager => PresenceManager::HIGH_BIT_INDEX,
- }
- }
-
- const fn bits_len(&self) -> u32 {
- match self {
- ActionType::ContextSyncSeqNum => ContextSyncSeqNum::BITS_LEN,
- ActionType::ActiveUnlock => ActiveUnlock::BITS_LEN,
- ActionType::NearbyShare => NearbyShare::BITS_LEN,
- ActionType::InstantTethering => InstantTethering::BITS_LEN,
- ActionType::PhoneHub => PhoneHub::BITS_LEN,
- ActionType::Finder => Finder::BITS_LEN,
- ActionType::FastPairSass => FastPairSass::BITS_LEN,
- ActionType::PresenceManager => PresenceManager::BITS_LEN,
}
}
pub(crate) fn supports_flavor(&self, flavor: PacketFlavorEnum) -> bool {
match self {
- ActionType::ContextSyncSeqNum => ContextSyncSeqNum::supports_flavor(flavor),
+ ActionType::CrossDevSdk => CrossDevSdk::supports_flavor(flavor),
+ ActionType::CallTransfer => CallTransfer::supports_flavor(flavor),
ActionType::ActiveUnlock => ActiveUnlock::supports_flavor(flavor),
ActionType::NearbyShare => NearbyShare::supports_flavor(flavor),
ActionType::InstantTethering => InstantTethering::supports_flavor(flavor),
ActionType::PhoneHub => PhoneHub::supports_flavor(flavor),
- ActionType::Finder => Finder::supports_flavor(flavor),
- ActionType::FastPairSass => FastPairSass::supports_flavor(flavor),
- ActionType::PresenceManager => PresenceManager::supports_flavor(flavor),
}
}
}
-impl ActionElement for ContextSyncSeqNum {
- const HIGH_BIT_INDEX: u32 = 0;
- const BITS_LEN: u32 = 4;
- const ACTION_TYPE: ActionType = ActionType::ContextSyncSeqNum;
-
- fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
- match flavor {
- PacketFlavorEnum::Plaintext => true,
- PacketFlavorEnum::Ciphertext => true,
- }
- }
-}
-
-impl ToActionElement<Plaintext> for ContextSyncSeqNum {
- fn bits(&self) -> u8 {
- self.as_u8()
- }
-}
-
-impl ToActionElement<Ciphertext> for ContextSyncSeqNum {
- fn bits(&self) -> u8 {
- self.as_u8()
- }
-}
-
// enabling an element for public adv requires privacy approval due to fingerprinting risk
-
+macros::boolean_element!(CrossDevSdk, 1, plaintext_and_ciphertext);
+macros::boolean_element!(CallTransfer, 4, ciphertext_only);
macros::boolean_element!(ActiveUnlock, 8, ciphertext_only);
macros::boolean_element!(NearbyShare, 9, plaintext_and_ciphertext);
macros::boolean_element!(InstantTethering, 10, ciphertext_only);
macros::boolean_element!(PhoneHub, 11, ciphertext_only);
-macros::boolean_element!(PresenceManager, 12, ciphertext_only);
-macros::boolean_element!(Finder, 13, plaintext_and_ciphertext);
-macros::boolean_element!(FastPairSass, 14, plaintext_and_ciphertext);
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/actions/tests.rs b/nearby/presence/np_adv/src/legacy/data_elements/actions/tests.rs
new file mode 100644
index 0000000..b96f94a
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/actions/tests.rs
@@ -0,0 +1,690 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+extern crate std;
+
+use crate::{
+ legacy::{
+ data_elements::{
+ actions::{self, *},
+ tests::macros::de_roundtrip_test,
+ },
+ serialize::encode_de_header,
+ serialize::tests::serialize,
+ Ciphertext, Plaintext,
+ },
+ DeLengthOutOfRange,
+};
+use rand::seq::SliceRandom;
+use rand::Rng;
+use std::collections;
+use std::panic;
+use std::prelude::rust_2021::*;
+
+#[test]
+fn setting_action_only_changes_that_actions_bits() {
+ fn do_test<F: PacketFlavor>(
+ set_ones: impl Fn(ActionType, &mut ActionBits<F>),
+ set_zeros: impl Fn(ActionType, &mut ActionBits<F>),
+ ) {
+ for t in supported_action_types(F::ENUM_VARIANT) {
+ let other_types = supported_action_types(F::ENUM_VARIANT)
+ .into_iter()
+ .filter(|t2| *t2 != t)
+ .collect::<Vec<_>>();
+
+ let mut actions = ActionBits::<F>::default();
+ set_ones(t, &mut actions);
+
+ // only the correct bits are set internally
+ assert_eq!(t.all_bits(), actions.as_u32());
+ // we can extract those bits
+ assert_eq!(t.all_bits() >> (31 - t.high_bit_index()), actions.bits_for_type(t));
+ // consider context sync (None) to be "set" for our purposes
+ assert!(actions.has_action(t));
+ // other types aren't set
+ for &t2 in &other_types {
+ assert_eq!(0, actions.bits_for_type(t2))
+ }
+
+ // now check that unsetting works
+ actions.bits = u32::MAX;
+ set_zeros(t, &mut actions);
+
+ assert_eq!(!t.all_bits(), actions.as_u32());
+ assert_eq!(0, actions.bits_for_type(t));
+ assert!(!actions.has_action(t));
+ // other types are set
+ for &t2 in &other_types {
+ assert_eq!(t2.all_bits() >> (31 - t2.high_bit_index()), actions.bits_for_type(t2));
+ }
+ }
+ }
+
+ do_test(
+ |t, bits| set_plaintext_action(t, true, bits),
+ |t, bits| set_plaintext_action(t, false, bits),
+ );
+ do_test(
+ |t, bits| set_ciphertexttext_action(t, true, bits),
+ |t, bits| set_ciphertexttext_action(t, false, bits),
+ );
+}
+
+#[test]
+fn random_combos_of_actions_have_correct_bits_set() {
+ fn do_test<F: PacketFlavor>(set_ones: impl Fn(ActionType, &mut ActionBits<F>)) {
+ let all_types = supported_action_types(F::ENUM_VARIANT);
+ let mut rng = rand::thread_rng();
+
+ for _ in 0..1000 {
+ let len = rng.gen_range(0..=all_types.len());
+ let selected = all_types.choose_multiple(&mut rng, len).copied().collect::<Vec<_>>();
+ let not_selected =
+ all_types.iter().filter(|t| !selected.contains(t)).copied().collect::<Vec<_>>();
+
+ let mut actions = ActionBits::<F>::default();
+ for &t in &selected {
+ set_ones(t, &mut actions);
+ }
+
+ for &t in &selected {
+ assert_ne!(0, actions.bits_for_type(t));
+ }
+ for &t in &not_selected {
+ assert_eq!(0, actions.bits_for_type(t));
+ }
+
+ assert_eq!(selected.iter().fold(0, |accum, t| accum | t.all_bits()), actions.bits);
+ }
+ }
+
+ do_test::<Plaintext>(|t, bits| set_plaintext_action(t, true, bits));
+ do_test::<Ciphertext>(|t, bits| set_ciphertexttext_action(t, true, bits));
+}
+
+#[test]
+fn set_last_bit_works() {
+ let mut actions = ActionBits::<Plaintext>::default();
+
+ actions.set_action(LastBit::from(true));
+ assert_eq_hex(0x0100, actions.bits);
+}
+
+#[test]
+fn set_last_bit_doesnt_clobber_others() {
+ let mut actions = ActionBits::<Plaintext>::default();
+
+ // set neighboring bits
+ actions.bits |= 0x200;
+
+ actions.set_action(LastBit::from(true));
+ assert_eq_hex(0x300, actions.bits);
+}
+
+#[test]
+fn unset_last_bit_works() {
+ let mut actions = ActionBits::<Plaintext> {
+ // all 1s
+ bits: u32::MAX,
+ ..Default::default()
+ };
+
+ actions.set_action(LastBit::from(false));
+ assert_eq_hex(0xFFFFFEFF, actions.bits);
+}
+
+#[test]
+fn bytes_used_works() {
+ let mut actions = ActionBits::<Plaintext>::default();
+
+ // Special-case: All-zeroes should lead to a single byte being used.
+ assert_eq!(1, actions.bytes_used());
+
+ actions.set_action(NearbyShare::from(true));
+ assert_eq!(2, actions.bytes_used());
+
+ actions.set_action(LastBit::from(true));
+ assert_eq!(3, actions.bytes_used());
+
+ actions.set_action(LastBit::from(false));
+ assert_eq!(2, actions.bytes_used());
+}
+
+#[test]
+fn write_de_empty_actions() {
+ // The special case of no action bits set should still occupy one byte [of all zeroes].
+
+ assert_eq!(
+ &[actions_de_header_byte(1), 0x00],
+ serialize(&ActionsDataElement::<Plaintext>::from(ActionBits::default())).as_slice()
+ );
+}
+
+#[test]
+fn write_de_one_action_byte() {
+ let mut action = ActionBits::default();
+ action.set_action(FirstBit::from(true));
+
+ assert_eq!(
+ &[actions_de_header_byte(1), 0b1000_0000],
+ serialize(&ActionsDataElement::<Plaintext>::from(action)).as_slice()
+ );
+}
+
+#[test]
+fn write_de_three_action_bytes() {
+ let mut action = ActionBits::default();
+ action.set_action(LastBit::from(true));
+
+ assert_eq!(
+ &[actions_de_header_byte(3), 0, 0, 1],
+ serialize(&ActionsDataElement::<Plaintext>::from(action)).as_slice()
+ );
+}
+
+#[test]
+fn write_de_all_plaintext_actions() {
+ let mut action = all_plaintext_actions_set();
+ action.set_action(LastBit::from(true));
+
+ // byte 0: cross dev sdk = 1
+ // byte 1: nearby share
+ // byte 2: last bit
+ assert_eq!(
+ &[actions_de_header_byte(3), 0x40, 0x40, 0x01],
+ serialize(&ActionsDataElement::<Plaintext>::from(action)).as_slice()
+ );
+}
+
+#[test]
+fn write_de_all_encrypted_actions() {
+ let mut action = all_ciphertext_actions_set();
+ action.set_action(LastBit::from(true));
+
+ // byte 1: cross dev sdk = 1, call transfer = 4
+ // byte 2: active unlock, nearby share, instant tethering, phone hub,
+ // byte 3: last bit
+ assert_eq!(
+ &[actions_de_header_byte(3), 0x48, 0xF0, 0x01],
+ serialize(&ActionsDataElement::<Ciphertext>::from(action)).as_slice()
+ );
+}
+
+#[test]
+fn roundtrip_de_random_action_combos() {
+ fn do_test<F>(set_ones: impl Fn(ActionType, &mut ActionBits<F>))
+ where
+ F: PacketFlavor,
+ ActionsDataElement<F>: DeserializeDataElement,
+ {
+ let all_types = supported_action_types(F::ENUM_VARIANT);
+ let mut rng = rand::thread_rng();
+
+ for _ in 0..1000 {
+ let len = rng.gen_range(0..=all_types.len());
+ let selected = all_types.choose_multiple(&mut rng, len).copied().collect::<Vec<_>>();
+
+ let mut actions = ActionBits::<F>::default();
+ for &t in &selected {
+ set_ones(t, &mut actions);
+ }
+
+ let de = ActionsDataElement::<F>::from(actions);
+ let serialized = serialize(&de);
+ // skip header
+ let contents = &serialized.as_slice()[1..];
+ let deserialized = ActionsDataElement::<F>::deserialize(contents).unwrap();
+
+ assert_eq!(de.action, deserialized.action);
+ }
+ }
+
+ do_test::<Plaintext>(|t, bits| set_plaintext_action(t, true, bits));
+ do_test::<Ciphertext>(|t, bits| set_ciphertexttext_action(t, true, bits));
+}
+
+#[test]
+fn action_element_bits_dont_overlap() {
+ let type_to_bits =
+ ActionType::iter().map(|t| (t, t.all_bits())).collect::<collections::HashMap<_, _>>();
+
+ for t in ActionType::iter() {
+ let bits = type_to_bits.get(&t).unwrap();
+
+ for (_, other_bits) in type_to_bits.iter().filter(|(other_type, _)| t != **other_type) {
+ assert_eq!(0, bits & other_bits, "type {t:?}");
+ }
+ }
+}
+
+#[test]
+fn action_type_all_bits_masks() {
+ assert_eq!(0x08000000, ActionType::CallTransfer.all_bits());
+ assert_eq!(0x00800000, ActionType::ActiveUnlock.all_bits());
+ assert_eq!(0x00400000, ActionType::NearbyShare.all_bits());
+ assert_eq!(0x00200000, ActionType::InstantTethering.all_bits());
+ assert_eq!(0x00100000, ActionType::PhoneHub.all_bits());
+}
+
+#[test]
+fn action_type_all_bits_in_per_type_masks() {
+ for t in supported_action_types(PacketFlavorEnum::Plaintext) {
+ assert_eq!(t.all_bits(), t.all_bits() & *ALL_PLAINTEXT_ELEMENT_BITS);
+ }
+ for t in supported_action_types(PacketFlavorEnum::Ciphertext) {
+ assert_eq!(t.all_bits(), t.all_bits() & *ALL_CIPHERTEXT_ELEMENT_BITS);
+ }
+}
+
+#[test]
+fn action_bits_try_from_flavor_mismatch_plaintext() {
+ assert_eq!(
+ FlavorNotSupported { flavor: PacketFlavorEnum::Plaintext },
+ ActionBits::<Plaintext>::try_from(ActionType::CallTransfer.all_bits()).unwrap_err()
+ );
+}
+
+#[test]
+fn actions_de_deser_plaintext_with_ciphertext_action() {
+ assert_eq!(
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Plaintext,
+ },
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::deserialize::<Plaintext>(&[
+ // active unlock bit set
+ 0x00, 0x80, 0x00,
+ ])
+ .unwrap_err()
+ );
+}
+
+#[test]
+fn actions_de_deser_ciphertext_with_plaintext_action() {
+ assert_eq!(
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Ciphertext,
+ },
+ <ActionsDataElement<Ciphertext> as DeserializeDataElement>::deserialize::<Ciphertext>(&[
+ // Finder bit set
+ 0x00, 0x00, 0x80,
+ ])
+ .unwrap_err()
+ );
+}
+
+#[test]
+fn actions_de_deser_plaintext_with_ciphertext_error() {
+ assert_eq!(
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Plaintext,
+ },
+ <ActionsDataElement<Ciphertext> as DeserializeDataElement>::deserialize::<Plaintext>(&[
+ 0x00
+ ])
+ .unwrap_err()
+ );
+}
+
+#[test]
+fn actions_de_deser_ciphertext_with_plaintext_error() {
+ assert_eq!(
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Ciphertext,
+ },
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::deserialize::<Ciphertext>(&[
+ 0x00
+ ])
+ .unwrap_err()
+ );
+}
+
+#[test]
+fn deserialize_content_too_long_error() {
+ assert_eq!(
+ DataElementDeserializeError::DeserializeError {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE
+ },
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::deserialize::<Plaintext>(
+ &[0x00; 10]
+ )
+ .unwrap_err()
+ );
+}
+
+#[test]
+fn actions_min_len_unencrypted() {
+ let actions = ActionBits::<Plaintext>::default();
+
+ let (_de, ser) = de_roundtrip_test!(
+ ActionsDataElement<Plaintext>,
+ Actions,
+ Actions,
+ Plaintext,
+ serialize(&actions::ActionsDataElement::from(actions))
+ );
+
+ assert_eq!(
+ &[
+ encode_de_header(
+ ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ DeEncodedLength::from(1),
+ ),
+ 0
+ ],
+ ser.as_slice()
+ );
+}
+
+#[test]
+fn actions_min_len_ldt() {
+ let actions = ActionBits::<Ciphertext>::default();
+
+ let (_de, ser) = de_roundtrip_test!(
+ ActionsDataElement<Ciphertext>,
+ Actions,
+ Actions,
+ Ciphertext,
+ serialize(&actions::ActionsDataElement::from(actions))
+ );
+
+ // header and 1 DE contents byte
+ assert_eq!(2, ser.as_slice().len());
+}
+
+#[test]
+fn actions_de_contents_normal_actions_roundtrip_unencrypted() {
+ let actions = all_plaintext_actions_set();
+
+ let _ = de_roundtrip_test!(
+ ActionsDataElement<Plaintext>,
+ Actions,
+ Actions,
+ Plaintext,
+ serialize(&actions::ActionsDataElement::from(actions))
+ );
+}
+
+#[test]
+fn actions_de_contents_normal_actions_roundtrip_ldt() {
+ let actions = all_ciphertext_actions_set();
+
+ let _ = de_roundtrip_test!(
+ ActionsDataElement<Ciphertext>,
+ Actions,
+ Actions,
+ Ciphertext,
+ serialize(&actions::ActionsDataElement::from(actions))
+ );
+}
+
+#[test]
+fn has_action_plaintext_works() {
+ let mut action_bits = ActionBits::<Plaintext>::default();
+ action_bits.set_action(NearbyShare::from(true));
+ let action_de = ActionsDataElement::from(action_bits);
+ assert!(action_de.action.has_action(ActionType::NearbyShare));
+ assert!(!action_de.action.has_action(ActionType::ActiveUnlock));
+ assert!(!action_de.action.has_action(ActionType::PhoneHub));
+}
+
+#[test]
+fn has_action_encrypted_works() {
+ let mut action_bits = ActionBits::<Ciphertext>::default();
+ action_bits.set_action(NearbyShare::from(true));
+ action_bits.set_action(ActiveUnlock::from(true));
+ let action_de = ActionsDataElement::from(action_bits);
+ assert!(action_de.action.has_action(ActionType::NearbyShare));
+ assert!(action_de.action.has_action(ActionType::ActiveUnlock));
+ assert!(!action_de.action.has_action(ActionType::PhoneHub));
+}
+
+#[test]
+fn actual_length_must_be_in_range() {
+ let de = ActionsDataElement::<Plaintext>::from(ActionBits::default());
+
+ for l in [0, ACTIONS_MAX_LEN + 1] {
+ let actual = DeActualLength::try_from(l).unwrap();
+ let _ = panic::catch_unwind(|| de.map_actual_len_to_encoded_len(actual)).unwrap_err();
+ }
+
+ for l in ACTIONS_VALID_ACTUAL_LEN {
+ assert_eq!(
+ l,
+ de.map_actual_len_to_encoded_len(DeActualLength::try_from(l).unwrap()).as_usize()
+ )
+ }
+}
+
+#[test]
+fn encoded_length_must_be_in_range() {
+ for l in [0, ACTIONS_MAX_LEN + 1] {
+ assert_eq!(
+ DeLengthOutOfRange,
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(
+ DeEncodedLength::try_from(l as u8).unwrap()
+ )
+ .unwrap_err()
+ )
+ }
+
+ for l in ACTIONS_VALID_ACTUAL_LEN {
+ assert_eq!(
+ l,
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(
+ DeEncodedLength::try_from(l as u8).unwrap()
+ )
+ .unwrap()
+ .as_usize()
+ );
+ }
+}
+
+mod coverage_gaming {
+ use crate::legacy::data_elements::actions::*;
+ use crate::legacy::Plaintext;
+ use alloc::format;
+
+ #[test]
+ fn actions_de_debug() {
+ let actions = ActionsDataElement::<Plaintext>::from(ActionBits::default());
+ let _ = format!("{:?}", actions);
+ }
+
+ #[test]
+ fn flavor_not_supported_debug() {
+ let _ = format!("{:?}", FlavorNotSupported { flavor: PacketFlavorEnum::Plaintext });
+ }
+
+ #[test]
+ fn action_type_clone_debug() {
+ let _ = format!("{:?}", ActionType::CallTransfer.clone());
+ }
+
+ #[test]
+ fn actions_debug() {
+ let _ = format!("{:?}", CallTransfer::from(true));
+ let _ = format!("{:?}", ActiveUnlock::from(true));
+ let _ = format!("{:?}", NearbyShare::from(true));
+ let _ = format!("{:?}", InstantTethering::from(true));
+ let _ = format!("{:?}", PhoneHub::from(true));
+ }
+}
+
+// Test only action which uses the first bit
+#[derive(Debug)]
+pub(crate) struct FirstBit {
+ enabled: bool,
+}
+
+impl From<bool> for FirstBit {
+ fn from(value: bool) -> Self {
+ FirstBit { enabled: value }
+ }
+}
+
+impl ActionElement for FirstBit {
+ const HIGH_BIT_INDEX: u32 = 0;
+ // don't want to add a variant for this test only type
+ const ACTION_TYPE: ActionType = ActionType::ActiveUnlock;
+
+ fn supports_flavor(_flavor: PacketFlavorEnum) -> bool {
+ true
+ }
+
+ fn bits(&self) -> u8 {
+ self.enabled as u8
+ }
+}
+
+macros::boolean_element_to_plaintext_element!(FirstBit);
+macros::boolean_element_to_encrypted_element!(FirstBit);
+
+// hypothetical action using the last bit
+#[derive(Debug)]
+pub(crate) struct LastBit {
+ enabled: bool,
+}
+
+impl From<bool> for LastBit {
+ fn from(value: bool) -> Self {
+ LastBit { enabled: value }
+ }
+}
+
+impl ActionElement for LastBit {
+ const HIGH_BIT_INDEX: u32 = 23;
+ // don't want to add a variant for this test only type
+ const ACTION_TYPE: ActionType = ActionType::ActiveUnlock;
+
+ fn supports_flavor(_flavor: PacketFlavorEnum) -> bool {
+ true
+ }
+
+ fn bits(&self) -> u8 {
+ self.enabled as u8
+ }
+}
+
+macros::boolean_element_to_plaintext_element!(LastBit);
+macros::boolean_element_to_encrypted_element!(LastBit);
+
+// An action that only supports plaintext, to allow testing that error case
+pub(in crate::legacy) struct PlaintextOnly {
+ enabled: bool,
+}
+
+impl From<bool> for PlaintextOnly {
+ fn from(value: bool) -> Self {
+ Self { enabled: value }
+ }
+}
+
+impl ActionElement for PlaintextOnly {
+ const HIGH_BIT_INDEX: u32 = 22;
+
+ const ACTION_TYPE: ActionType = ActionType::ActiveUnlock;
+
+ fn supports_flavor(flavor: PacketFlavorEnum) -> bool {
+ match flavor {
+ PacketFlavorEnum::Plaintext => true,
+ PacketFlavorEnum::Ciphertext => false,
+ }
+ }
+
+ fn bits(&self) -> u8 {
+ self.enabled as u8
+ }
+}
+
+macros::boolean_element_to_plaintext_element!(PlaintextOnly);
+// sneakily allow serializing it, but deserializing will fail due to supports_flavor above
+macros::boolean_element_to_encrypted_element!(PlaintextOnly);
+
+fn assert_eq_hex(expected: u32, actual: u32) {
+ assert_eq!(expected, actual, "{expected:#010X} != {actual:#010X}");
+}
+
+pub(crate) fn all_plaintext_actions_set() -> ActionBits<Plaintext> {
+ let mut action = ActionBits::default();
+ action.set_action(CrossDevSdk::from(true));
+ action.set_action(NearbyShare::from(true));
+
+ assert!(supported_action_types(PacketFlavorEnum::Plaintext)
+ .into_iter()
+ .all(|t| t.all_bits() & action.bits != 0));
+
+ action
+}
+
+pub(crate) fn all_ciphertext_actions_set() -> ActionBits<Ciphertext> {
+ let mut action = ActionBits::default();
+ action.set_action(CrossDevSdk::from(true));
+ action.set_action(CallTransfer::from(true));
+ action.set_action(ActiveUnlock::from(true));
+ action.set_action(NearbyShare::from(true));
+ action.set_action(InstantTethering::from(true));
+ action.set_action(PhoneHub::from(true));
+
+ assert!(supported_action_types(PacketFlavorEnum::Ciphertext)
+ .into_iter()
+ .all(|t| t.all_bits() & action.bits != 0));
+
+ action
+}
+
+fn supported_action_types(flavor: PacketFlavorEnum) -> Vec<ActionType> {
+ ActionType::iter().filter(|t| t.supports_flavor(flavor)).collect()
+}
+
+/// Encode a DE header byte with the provided type and actual len, transforming into an encoded
+/// len appropriately.
+fn actions_de_header_byte(actual_len: u8) -> u8 {
+ encode_de_header(
+ ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ DeEncodedLength::try_from(actual_len).unwrap(),
+ )
+}
+
+pub(crate) fn set_plaintext_action(t: ActionType, value: bool, bits: &mut ActionBits<Plaintext>) {
+ match t {
+ ActionType::CrossDevSdk => bits.set_action(CrossDevSdk::from(value)),
+ ActionType::NearbyShare => bits.set_action(NearbyShare::from(value)),
+ ActionType::CallTransfer
+ | ActionType::PhoneHub
+ | ActionType::ActiveUnlock
+ | ActionType::InstantTethering => panic!(),
+ }
+}
+
+pub(crate) fn set_ciphertexttext_action(
+ t: ActionType,
+ value: bool,
+ bits: &mut ActionBits<Ciphertext>,
+) {
+ match t {
+ ActionType::CrossDevSdk => bits.set_action(CrossDevSdk::from(value)),
+ ActionType::CallTransfer => bits.set_action(CallTransfer::from(value)),
+ ActionType::ActiveUnlock => bits.set_action(ActiveUnlock::from(value)),
+ ActionType::NearbyShare => bits.set_action(NearbyShare::from(value)),
+ ActionType::InstantTethering => bits.set_action(InstantTethering::from(value)),
+ ActionType::PhoneHub => bits.set_action(PhoneHub::from(value)),
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/de_type/mod.rs b/nearby/presence/np_adv/src/legacy/data_elements/de_type/mod.rs
new file mode 100644
index 0000000..e5dd153
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/de_type/mod.rs
@@ -0,0 +1,127 @@
+// 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.
+
+//! V0 data element types.
+//!
+//! In V0, there are only 16 DE types total, and parsing unknown types is not possible, so we can
+//! represent all known DE types in enums without needing to handle the "unknown type" case.
+
+use crate::{legacy::NP_MAX_DE_CONTENT_LEN, DeLengthOutOfRange};
+use strum_macros::EnumIter;
+
+#[cfg(test)]
+mod tests;
+
+/// A V0 DE type in `[0, 15]`.
+#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
+pub struct DeTypeCode {
+ /// The code used in a V0 adv header
+ code: u8,
+}
+
+impl DeTypeCode {
+ /// Returns a u8 in `[0, 15`].
+ pub(crate) fn as_u8(&self) -> u8 {
+ self.code
+ }
+
+ pub(crate) const fn try_from(value: u8) -> Result<Self, DeTypeCodeOutOfRange> {
+ if value < 16 {
+ Ok(Self { code: value })
+ } else {
+ Err(DeTypeCodeOutOfRange)
+ }
+ }
+}
+
+/// The DE type code is out of range for v0 DE types.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub(crate) struct DeTypeCodeOutOfRange;
+
+/// The actual length of a DE's contents, not the encoded representation.
+///
+/// See [DeEncodedLength] for the encoded length.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DeActualLength {
+ /// Invariant: <= [NP_MAX_DE_CONTENT_LEN].
+ len: u8,
+}
+
+impl DeActualLength {
+ pub(crate) fn try_from(value: usize) -> Result<Self, DeLengthOutOfRange> {
+ if value <= NP_MAX_DE_CONTENT_LEN {
+ Ok(Self { len: value as u8 })
+ } else {
+ Err(DeLengthOutOfRange)
+ }
+ }
+
+ pub(crate) fn as_u8(&self) -> u8 {
+ self.len
+ }
+
+ pub(crate) fn as_usize(&self) -> usize {
+ self.len.into()
+ }
+}
+
+/// Maximum encoded length value
+pub(crate) const MAX_DE_ENCODED_LEN: u8 = 15;
+
+/// The encoded length of a DE, not the actual length of the DE contents.
+///
+/// See [DeActualLength] for the length of the contents.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DeEncodedLength {
+ /// Invariant: `len <= 0x0F` (15, aka 4 bits)
+ len: u8,
+}
+
+impl DeEncodedLength {
+ pub(crate) fn try_from(value: u8) -> Result<Self, DeLengthOutOfRange> {
+ if value <= MAX_DE_ENCODED_LEN {
+ Ok(Self { len: value })
+ } else {
+ Err(DeLengthOutOfRange)
+ }
+ }
+
+ /// Test-only helper that panics for less unwrapping in tests.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `value` is invalid.
+ #[cfg(test)]
+ pub(in crate::legacy) fn from(value: u8) -> Self {
+ Self::try_from(value).expect("Invalid len")
+ }
+
+ /// Returns a u8 in `[0, 15]`
+ pub(crate) fn as_u8(&self) -> u8 {
+ self.len
+ }
+
+ /// Returns a usize in `[0, 15]`
+ pub(crate) fn as_usize(&self) -> usize {
+ self.len as usize
+ }
+}
+
+/// Corresponds to the normal data element types.
+#[derive(EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
+#[allow(missing_docs)]
+pub(in crate::legacy) enum DataElementType {
+ TxPower,
+ Actions,
+}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/de_type/tests.rs b/nearby/presence/np_adv/src/legacy/data_elements/de_type/tests.rs
new file mode 100644
index 0000000..72c8482
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/de_type/tests.rs
@@ -0,0 +1,153 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+extern crate std;
+
+use super::*;
+use crate::legacy::data_elements::{DeserializeDataElement, LengthMapper};
+use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
+use crate::legacy::{Ciphertext, PacketFlavor};
+use crate::{
+ legacy::{
+ data_elements::{
+ actions::{ActionBits, ActionsDataElement},
+ tx_power::TxPowerDataElement,
+ SerializeDataElement,
+ },
+ Plaintext,
+ },
+ shared_data::TxPower,
+};
+use alloc::vec;
+use core::panic::{RefUnwindSafe, UnwindSafe};
+use std::{collections, panic};
+
+#[test]
+fn de_type_code_in_range_ok() {
+ assert_eq!(3, DeTypeCode::try_from(3).unwrap().code);
+}
+
+#[test]
+fn de_type_code_out_of_range_err() {
+ assert_eq!(DeTypeCodeOutOfRange, DeTypeCode::try_from(30).unwrap_err());
+}
+
+#[test]
+fn de_actual_length_in_range_ok() {
+ assert_eq!(3, DeActualLength::try_from(3).unwrap().len);
+}
+
+#[test]
+fn de_actual_length_out_of_range_err() {
+ assert_eq!(
+ DeLengthOutOfRange,
+ DeActualLength::try_from(NP_MAX_DE_CONTENT_LEN + 1).unwrap_err()
+ );
+}
+
+#[test]
+fn de_encoded_length_in_range_ok() {
+ assert_eq!(3, DeEncodedLength::from(3).len);
+}
+
+#[test]
+fn de_encoded_length_out_of_range_err() {
+ assert_eq!(DeLengthOutOfRange, DeEncodedLength::try_from(MAX_DE_ENCODED_LEN + 1).unwrap_err());
+}
+
+#[test]
+fn de_length_actual_encoded_round_trip() {
+ fn do_de_length_test<
+ F: PacketFlavor,
+ D: DeserializeDataElement + SerializeDataElement<F> + UnwindSafe + RefUnwindSafe,
+ >(
+ de: D,
+ ) {
+ // for all possible lengths, calculate actual -> encoded and the inverse
+ let actual_to_encoded = (0_u8..=255)
+ .filter_map(|num| DeActualLength::try_from(usize::from(num)).ok())
+ .filter_map(|actual: DeActualLength| {
+ panic::catch_unwind(|| de.map_actual_len_to_encoded_len(actual))
+ .ok()
+ .map(|encoded| (actual, encoded))
+ })
+ .collect::<collections::HashMap<_, _>>();
+
+ let encoded_to_actual = (0_u8..=255)
+ .filter_map(|num| DeEncodedLength::try_from(num).ok())
+ .filter_map(|encoded: DeEncodedLength| {
+ D::LengthMapper::map_encoded_len_to_actual_len(encoded)
+ .ok()
+ .map(|actual| (encoded, actual))
+ })
+ .collect::<collections::HashMap<_, _>>();
+
+ // ensure the two maps are inverses of each other
+ assert_eq!(
+ actual_to_encoded,
+ encoded_to_actual.into_iter().map(|(encoded, actual)| (actual, encoded)).collect(),
+ );
+ }
+
+ do_de_length_test::<Plaintext, _>(TxPowerDataElement::from(TxPower::try_from(1).unwrap()));
+ do_de_length_test(ActionsDataElement::<Plaintext>::from(ActionBits::default()));
+ do_de_length_test(ActionsDataElement::<Ciphertext>::from(ActionBits::default()));
+
+ // might as well make sure our test DEs behave as well
+ do_de_length_test::<Plaintext, _>(ShortDataElement::new(vec![]));
+ do_de_length_test::<Plaintext, _>(LongDataElement::new(vec![]));
+}
+
+mod coverage_gaming {
+ use crate::legacy::data_elements::de_type::{
+ DataElementType, DeActualLength, DeEncodedLength, DeTypeCode, DeTypeCodeOutOfRange,
+ };
+
+ extern crate std;
+
+ use std::{collections, format};
+
+ #[test]
+ fn de_type_code_debug_hash_clone() {
+ let code = DeTypeCode::try_from(3).unwrap();
+ let _ = format!("{:?}", code.clone());
+ let _ = collections::HashSet::from([code]);
+ }
+
+ #[test]
+ fn de_type_code_out_of_range() {
+ // debug, clone
+ let _ = format!("{:?}", DeTypeCodeOutOfRange.clone());
+ }
+
+ #[test]
+ fn de_actual_length() {
+ // debug, clone
+ let _ = format!("{:?}", DeActualLength::try_from(3).unwrap().clone());
+ }
+
+ #[test]
+ fn de_encoded_length() {
+ // debug, clone
+ let _ = format!("{:?}", DeEncodedLength::from(3).clone());
+ }
+
+ #[test]
+ fn de_type() {
+ // debug, clone
+ let _ = format!("{:?}", DataElementType::TxPower.clone());
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/mod.rs b/nearby/presence/np_adv/src/legacy/data_elements/mod.rs
new file mode 100644
index 0000000..5dd0587
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/mod.rs
@@ -0,0 +1,266 @@
+// 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.
+
+//! V0 data elements and core trait impls.
+
+use crate::{
+ extended::serialize::CapacityLimitedVec,
+ legacy::{
+ data_elements::de_type::{DeActualLength, DeEncodedLength, DeTypeCode},
+ PacketFlavor, PacketFlavorEnum, NP_MAX_ADV_CONTENT_LEN,
+ },
+ private::Sealed,
+ DeLengthOutOfRange,
+};
+use core::marker;
+use nom::error::{self};
+use sink::Sink;
+
+pub mod actions;
+pub mod de_type;
+pub mod tx_power;
+
+#[cfg(test)]
+pub(in crate::legacy) mod tests;
+
+/// Deserialization for a specific data element type.
+///
+/// See also [SerializeDataElement] for flavor-specific, infallible serialization.
+pub(in crate::legacy) trait DeserializeDataElement: Sized + Sealed {
+ const DE_TYPE_CODE: DeTypeCode;
+
+ /// Define how length mapping is done for this DE type
+ type LengthMapper: LengthMapper;
+
+ /// Deserialize `Self` from the provided DE contents (not including the
+ /// DE header).
+ ///
+ /// Returns `Err` if the flavor is not supported or if parsing fails.
+ ///
+ /// `<F>` is the flavor of the packet being deserialized.
+ fn deserialize<F: PacketFlavor>(
+ de_contents: &[u8],
+ ) -> Result<Self, DataElementDeserializeError>;
+}
+
+/// Errors possible when deserializing a DE
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum DataElementDeserializeError {
+ /// The data element doesn't support the [PacketFlavor] of the advertisement packet.
+ FlavorNotSupported {
+ /// The DE type attempting to be deserialized
+ de_type: DeTypeCode,
+ /// The flavor that was not supported
+ flavor: PacketFlavorEnum,
+ },
+ /// The data element couldn't be deserialized from the supplied data.
+ DeserializeError {
+ /// The DE type attempting to be deserialized
+ de_type: DeTypeCode,
+ },
+ /// Invalid DE type
+ InvalidDeType {
+ /// The unknown type
+ de_type: DeTypeCode,
+ },
+ /// Invalid DE length
+ InvalidDeLength {
+ /// The DE type attempting to be deserialized
+ de_type: DeTypeCode,
+ /// The invalid length
+ len: DeEncodedLength,
+ },
+ /// Other parse error, e.g. the adv is truncated
+ InvalidStructure,
+}
+
+impl error::FromExternalError<&[u8], DataElementDeserializeError> for DataElementDeserializeError {
+ fn from_external_error(
+ _input: &[u8],
+ _kind: error::ErrorKind,
+ e: DataElementDeserializeError,
+ ) -> Self {
+ e
+ }
+}
+
+impl error::ParseError<&[u8]> for DataElementDeserializeError {
+ /// Creates an error from the input position and an [error::ErrorKind]
+ fn from_error_kind(_input: &[u8], _kind: error::ErrorKind) -> Self {
+ Self::InvalidStructure
+ }
+
+ /// Combines an existing error with a new one created from the input
+ /// position and an [error::ErrorKind]. This is useful when backtracking
+ /// through a parse tree, accumulating error context on the way
+ fn append(_input: &[u8], _kind: error::ErrorKind, _other: Self) -> Self {
+ Self::InvalidStructure
+ }
+}
+
+/// Serialization of a DE for a particular flavor.
+///
+/// The flavor is a type parameter on the trait, rather than on the method,
+/// so that a DE can indicate its flavor support by implementing this trait
+/// only with the relevant flavors. Deserialization, on the other hand, can
+/// express "flavor not supported" for invalid input.
+pub trait SerializeDataElement<F: PacketFlavor>: Sealed {
+ /// Returns the DE type code this DE uses in the header.
+ fn de_type_code(&self) -> DeTypeCode;
+
+ /// Convert the actual DE content length to the encoded length included in the header.
+ ///
+ /// This has a `&self` receiver only so that it can be object-safe; it
+ /// should not be relevant in the calculation.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the actual length is invalid for this DE type, or if the
+ /// encoded length cannot fit in [DeEncodedLength], either of which means
+ /// that the serialization impl is broken.
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength;
+
+ /// Serialize the data element's data (not including the header) into the sink.
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError>;
+}
+
+/// Errors possible when serializing a DE
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum DataElementSerializeError {
+ /// Not enough available space
+ InsufficientSpace,
+}
+
+/// Buffer to serialize a DE, including the header, into.
+pub struct DataElementSerializationBuffer {
+ vec: CapacityLimitedVec<u8, NP_MAX_ADV_CONTENT_LEN>,
+}
+
+impl DataElementSerializationBuffer {
+ /// Returns `None` if `capacity` exceeds [NP_MAX_ADV_CONTENT_LEN].
+ pub(crate) fn new(capacity: usize) -> Option<Self> {
+ CapacityLimitedVec::new(capacity).map(|vec| Self { vec })
+ }
+
+ pub(crate) fn len(&self) -> usize {
+ self.vec.len()
+ }
+
+ pub(crate) fn into_inner(self) -> CapacityLimitedVec<u8, NP_MAX_ADV_CONTENT_LEN> {
+ self.vec
+ }
+}
+
+impl Sink<u8> for DataElementSerializationBuffer {
+ fn try_extend_from_slice(&mut self, items: &[u8]) -> Option<()> {
+ Sink::try_extend_from_slice(&mut self.vec, items)
+ }
+
+ fn try_push(&mut self, item: u8) -> Option<()> {
+ Sink::try_push(&mut self.vec, item)
+ }
+}
+
+/// Trait object reference to a `ToDataElementBundle<I>` with lifetime `'a`.
+/// Implements [SerializeDataElement] by deferring to the wrapped trait object.
+pub struct DynamicSerializeDataElement<'a, I: PacketFlavor> {
+ wrapped: &'a dyn SerializeDataElement<I>,
+}
+
+impl<'a, I: PacketFlavor> From<&'a dyn SerializeDataElement<I>>
+ for DynamicSerializeDataElement<'a, I>
+{
+ fn from(wrapped: &'a dyn SerializeDataElement<I>) -> Self {
+ DynamicSerializeDataElement { wrapped }
+ }
+}
+
+impl<'a, F: PacketFlavor> Sealed for DynamicSerializeDataElement<'a, F> {}
+
+impl<'a, F: PacketFlavor> SerializeDataElement<F> for DynamicSerializeDataElement<'a, F> {
+ fn de_type_code(&self) -> DeTypeCode {
+ self.wrapped.de_type_code()
+ }
+
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ self.wrapped.map_actual_len_to_encoded_len(actual_len)
+ }
+
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ self.wrapped.serialize_contents(sink)
+ }
+}
+
+/// Maps encoded to actual lengths and vice versa.
+///
+/// Each v0 DE type has their own length mapping rules.
+pub(in crate::legacy) trait LengthMapper {
+ /// Convert the encoded DE content length in the header to the actual length to consume from
+ /// the advertisement, or an error if the encoded length is invalid for the DE type.
+ fn map_encoded_len_to_actual_len(
+ encoded_len: DeEncodedLength,
+ ) -> Result<DeActualLength, DeLengthOutOfRange>;
+
+ /// Convert the actual DE content length to the encoded length included in the header.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the actual length is invalid for this DE type, or if the
+ /// encoded length cannot fit in [DeEncodedLength], either of which means
+ /// that the serialization impl is broken.
+ fn map_actual_len_to_encoded_len(actual_len: DeActualLength) -> DeEncodedLength;
+}
+
+/// A length predicate used with [DirectMapper].
+pub(in crate::legacy) trait DirectMapPredicate {
+ /// Return `true` iff the len is valid as a DE encoded len _and_ actual len.
+ fn is_valid(len: usize) -> bool;
+}
+
+/// A [LengthMapper] that maps the input number directly to the output number without any scaling or
+/// shifting.
+///
+/// Iff `predicate` evaluates to true, the input number will be transformed into the output type,
+/// for both directions.
+pub(in crate::legacy) struct DirectMapper<P: DirectMapPredicate> {
+ _marker: marker::PhantomData<P>,
+}
+
+impl<P: DirectMapPredicate> LengthMapper for DirectMapper<P> {
+ fn map_encoded_len_to_actual_len(
+ encoded_len: DeEncodedLength,
+ ) -> Result<DeActualLength, DeLengthOutOfRange> {
+ let enc = encoded_len.as_usize();
+ if P::is_valid(enc) {
+ DeActualLength::try_from(enc)
+ } else {
+ Err(DeLengthOutOfRange)
+ }
+ }
+
+ fn map_actual_len_to_encoded_len(actual_len: DeActualLength) -> DeEncodedLength {
+ assert!(
+ P::is_valid(actual_len.as_usize()),
+ "Broken DE implementation produced invalid length"
+ );
+ DeEncodedLength::try_from(actual_len.as_u8())
+ .expect("Actual length has already been validated")
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/tests.rs b/nearby/presence/np_adv/src/legacy/data_elements/tests.rs
new file mode 100644
index 0000000..d3f3061
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/tests.rs
@@ -0,0 +1,304 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+use alloc::boxed::Box;
+
+use crate::header::VERSION_HEADER_V0_UNENCRYPTED;
+use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement};
+use crate::legacy::serialize::{encode_de_header, AdvBuilder, UnencryptedEncoder};
+use crate::legacy::Plaintext;
+
+use super::*;
+
+#[test]
+fn dynamic_de_works() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ let actions: Box<dyn SerializeDataElement<Plaintext>> =
+ Box::new(ActionsDataElement::<Plaintext>::from(ActionBits::default()));
+ builder.add_data_element(DynamicSerializeDataElement::from(actions.as_ref())).unwrap();
+
+ assert_eq!(
+ &[
+ VERSION_HEADER_V0_UNENCRYPTED,
+ encode_de_header(
+ ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ DeEncodedLength::from(1),
+ ),
+ 0
+ ],
+ builder.into_advertisement().unwrap().as_slice()
+ );
+}
+
+pub(in crate::legacy) mod macros {
+ use alloc::vec::Vec;
+
+ use crate::legacy::data_elements::de_type::DataElementType;
+ use crate::legacy::deserialize::{DeIterator, DeserializedDataElement};
+ use crate::legacy::serialize::SerializedDataElement;
+ use crate::legacy::PacketFlavor;
+
+ /// Test method body that creates an array, deserializes it into a DE, serializes it,
+ /// and asserts that the same bytes are produced.
+ ///
+ /// Evaluates to (the deserialized DE, the serialized form of the DE).
+ macro_rules! de_roundtrip_test {
+ ($de_type:ty, $type_variant:ident, $de_variant:ident, $flavor:ty, $bytes:expr) => {{
+ let parsed_de_enum =
+ crate::legacy::data_elements::tests::macros::construct_and_parse_de::<
+ $flavor,
+ >(crate::legacy::data_elements::de_type::DataElementType::$type_variant, &$bytes);
+ if let crate::legacy::deserialize::DeserializedDataElement::$de_variant(de) =
+ parsed_de_enum
+ {
+ // skip DE header byte
+ let expected = <$de_type as crate::legacy::data_elements::DeserializeDataElement>
+ ::deserialize::<$flavor>(&$bytes.as_slice()[1..]).unwrap();
+ assert_eq!(expected, de);
+
+ let serialized = crate::legacy::serialize::tests::serialize::<$flavor, _>(&de);
+ assert_eq!($bytes.as_slice(), serialized.as_slice());
+
+ (de, serialized)
+ } else {
+ panic!("Unexpected variant: {:?}", parsed_de_enum);
+ }
+ }};
+ }
+
+ pub(in crate::legacy) use de_roundtrip_test;
+
+ /// Construct the serialized DE and parse it
+ pub(in crate::legacy) fn construct_and_parse_de<F>(
+ de_type: DataElementType,
+ contents: &SerializedDataElement,
+ ) -> DeserializedDataElement<F>
+ where
+ F: PacketFlavor,
+ {
+ let mut plain_des =
+ DeIterator::new(contents.as_slice()).collect::<Result<Vec<_>, _>>().unwrap();
+ assert_eq!(1, plain_des.len());
+ let de = plain_des.swap_remove(0);
+ assert_eq!(
+ de_type,
+ match de {
+ DeserializedDataElement::Actions(_) => DataElementType::Actions,
+ DeserializedDataElement::TxPower(_) => DataElementType::TxPower,
+ }
+ );
+ de
+ }
+}
+
+mod coverage_gaming {
+ use alloc::format;
+
+ use nom::error;
+ use nom::error::ParseError;
+
+ use crate::legacy::data_elements::de_type::DeTypeCode;
+ use crate::legacy::data_elements::{DataElementDeserializeError, DataElementSerializeError};
+
+ #[test]
+ fn data_element_serialize_error_debug_eq_clone() {
+ let _ = format!("{:?}", DataElementSerializeError::InsufficientSpace.clone());
+ assert_eq!(
+ DataElementSerializeError::InsufficientSpace,
+ DataElementSerializeError::InsufficientSpace
+ );
+ }
+
+ #[test]
+ fn data_element_deserialize_error_debug_clone() {
+ let _ = format!("{:?}", DataElementDeserializeError::InvalidStructure.clone());
+ }
+
+ #[test]
+ fn data_element_deserialize_error_append() {
+ assert_eq!(
+ DataElementDeserializeError::InvalidStructure,
+ DataElementDeserializeError::append(
+ &[0_u8],
+ error::ErrorKind::CrLf,
+ DataElementDeserializeError::InvalidDeType {
+ de_type: DeTypeCode::try_from(10).unwrap()
+ },
+ )
+ );
+ }
+}
+
+pub(in crate::legacy) mod test_des {
+ use alloc::vec;
+
+ use rand::distributions;
+ use strum_macros::EnumIter;
+
+ use crate::legacy::data_elements::de_type::{
+ DeActualLength, DeEncodedLength, DeTypeCode, MAX_DE_ENCODED_LEN,
+ };
+ use crate::legacy::data_elements::{
+ DataElementDeserializeError, DataElementSerializationBuffer, DataElementSerializeError,
+ DeserializeDataElement, LengthMapper, SerializeDataElement,
+ };
+ use crate::legacy::deserialize::{DataElementDeserializer, LengthError, RawDataElement};
+ use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
+ use crate::legacy::{PacketFlavor, NP_MAX_DE_CONTENT_LEN};
+ use crate::private::Sealed;
+
+ /// A [DataElementDeserializer] that can deserialize the test stubs [ShortDataElement] and
+ /// [LongDataElement].
+ pub(in crate::legacy) struct TestDeDeserializer;
+
+ impl DataElementDeserializer for TestDeDeserializer {
+ type DeTypeDisambiguator = TestDataElementType;
+ type Deserialized<F: PacketFlavor> = TestDataElement;
+
+ fn map_encoded_len_to_actual_len(
+ de_type: DeTypeCode,
+ encoded_len: DeEncodedLength,
+ ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError> {
+ match de_type {
+ ShortDataElement::DE_TYPE_CODE => {
+ <ShortDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
+ .map(|l| (TestDataElementType::Short, l))
+ .map_err(|e| e.into())
+ }
+ LongDataElement::DE_TYPE_CODE => {
+ <LongDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
+ .map(|l| (TestDataElementType::Long, l))
+ .map_err(|e| e.into())
+ }
+ _ => Err(LengthError::InvalidType),
+ }
+ }
+
+ fn deserialize_de<F: PacketFlavor>(
+ raw_de: RawDataElement<Self>,
+ ) -> Result<Self::Deserialized<F>, DataElementDeserializeError> {
+ match raw_de.de_type {
+ TestDataElementType::Short => {
+ ShortDataElement::deserialize::<F>(raw_de.contents).map(TestDataElement::Short)
+ }
+ TestDataElementType::Long => {
+ LongDataElement::deserialize::<F>(raw_de.contents).map(TestDataElement::Long)
+ }
+ }
+ }
+ }
+
+ #[derive(EnumIter, Debug, Clone, Copy)]
+ pub(in crate::legacy) enum TestDataElementType {
+ Short,
+ Long,
+ }
+
+ #[derive(Debug, PartialEq, Eq, Clone)]
+ pub(in crate::legacy) enum TestDataElement {
+ Short(ShortDataElement),
+ Long(LongDataElement),
+ }
+
+ impl From<ShortDataElement> for TestDataElement {
+ fn from(value: ShortDataElement) -> Self {
+ Self::Short(value)
+ }
+ }
+
+ impl From<LongDataElement> for TestDataElement {
+ fn from(value: LongDataElement) -> Self {
+ Self::Long(value)
+ }
+ }
+
+ impl Sealed for TestDataElement {}
+
+ // Not representative of how the main [DeserializedDataElement] would be used, but handy
+ // in tests to be able to directly serialize the deserialized representation
+ impl<F: PacketFlavor> SerializeDataElement<F> for TestDataElement {
+ fn de_type_code(&self) -> DeTypeCode {
+ match self {
+ TestDataElement::Short(s) => {
+ <ShortDataElement as SerializeDataElement<F>>::de_type_code(s)
+ }
+ TestDataElement::Long(l) => {
+ <LongDataElement as SerializeDataElement<F>>::de_type_code(l)
+ }
+ }
+ }
+
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ match self {
+ TestDataElement::Short(s) => {
+ <ShortDataElement as SerializeDataElement<F>>::map_actual_len_to_encoded_len(
+ s, actual_len,
+ )
+ }
+ TestDataElement::Long(l) => {
+ <LongDataElement as SerializeDataElement<F>>::map_actual_len_to_encoded_len(
+ l, actual_len,
+ )
+ }
+ }
+ }
+
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ match self {
+ TestDataElement::Short(s) => {
+ <ShortDataElement as SerializeDataElement<F>>::serialize_contents(s, sink)
+ }
+ TestDataElement::Long(l) => {
+ <LongDataElement as SerializeDataElement<F>>::serialize_contents(l, sink)
+ }
+ }
+ }
+ }
+
+ impl distributions::Distribution<ShortDataElement> for distributions::Standard {
+ fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ShortDataElement {
+ let len = rng.gen_range(0_usize..MAX_DE_ENCODED_LEN.into());
+ let mut data = vec![0; len];
+ rng.fill(&mut data[..]);
+ ShortDataElement::new(data)
+ }
+ }
+
+ impl distributions::Distribution<LongDataElement> for distributions::Standard {
+ fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> LongDataElement {
+ let len = rng.gen_range(LongDataElement::OFFSET..NP_MAX_DE_CONTENT_LEN);
+ let mut data = vec![0; len];
+ rng.fill(&mut data[..]);
+ LongDataElement::new(data)
+ }
+ }
+
+ /// Generate a random instance of the requested de type, or `None` if that type does not support
+ /// plaintext.
+ pub(crate) fn random_test_de<R>(de_type: TestDataElementType, rng: &mut R) -> TestDataElement
+ where
+ R: rand::Rng,
+ {
+ match de_type {
+ TestDataElementType::Short => TestDataElement::Short(rng.gen()),
+ TestDataElementType::Long => TestDataElement::Long(rng.gen()),
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/data_elements/tx_power.rs b/nearby/presence/np_adv/src/legacy/data_elements/tx_power.rs
new file mode 100644
index 0000000..e8c787e
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/data_elements/tx_power.rs
@@ -0,0 +1,189 @@
+// 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.
+
+//! Data element for TX Power.
+
+use crate::legacy::data_elements::de_type::{DeActualLength, DeEncodedLength, DeTypeCode};
+use crate::legacy::data_elements::{
+ DataElementDeserializeError, DataElementSerializationBuffer, DataElementSerializeError,
+ DeserializeDataElement, DirectMapPredicate, DirectMapper, LengthMapper, SerializeDataElement,
+};
+use crate::legacy::PacketFlavor;
+use crate::private::Sealed;
+use crate::shared_data::TxPower;
+use sink::Sink;
+
+/// Data element holding a [TxPower].
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct TxPowerDataElement {
+ /// The tx power value
+ pub tx_power: TxPower,
+}
+
+impl TxPowerDataElement {
+ /// Gets the underlying Tx Power value
+ pub fn tx_power_value(&self) -> i8 {
+ self.tx_power.as_i8()
+ }
+}
+
+impl From<TxPower> for TxPowerDataElement {
+ fn from(tx_power: TxPower) -> Self {
+ Self { tx_power }
+ }
+}
+
+impl Sealed for TxPowerDataElement {}
+
+impl<F: PacketFlavor> SerializeDataElement<F> for TxPowerDataElement {
+ fn de_type_code(&self) -> DeTypeCode {
+ TxPowerDataElement::DE_TYPE_CODE
+ }
+
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ <Self as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual_len)
+ }
+
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ sink.try_extend_from_slice(self.tx_power.as_i8().to_be_bytes().as_slice())
+ .ok_or(DataElementSerializeError::InsufficientSpace)
+ }
+}
+
+impl DeserializeDataElement for TxPowerDataElement {
+ const DE_TYPE_CODE: DeTypeCode = match DeTypeCode::try_from(0b0101) {
+ Ok(t) => t,
+ Err(_) => unreachable!(),
+ };
+
+ type LengthMapper = DirectMapper<TxPowerLengthPredicate>;
+
+ fn deserialize<F: PacketFlavor>(
+ de_contents: &[u8],
+ ) -> Result<Self, DataElementDeserializeError> {
+ de_contents
+ .try_into()
+ .ok()
+ .and_then(|arr: [u8; 1]| TxPower::try_from(i8::from_be_bytes(arr)).ok())
+ .map(|tx_power| Self { tx_power })
+ .ok_or(DataElementDeserializeError::DeserializeError { de_type: Self::DE_TYPE_CODE })
+ }
+}
+
+pub(in crate::legacy) struct TxPowerLengthPredicate;
+
+impl DirectMapPredicate for TxPowerLengthPredicate {
+ fn is_valid(len: usize) -> bool {
+ len == 1
+ }
+}
+
+#[allow(clippy::unwrap_used)]
+#[cfg(test)]
+mod tests {
+ use crate::legacy::data_elements::de_type::{DeActualLength, DeEncodedLength};
+ use crate::legacy::data_elements::tests::macros::de_roundtrip_test;
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::data_elements::{DeserializeDataElement, LengthMapper};
+ use crate::legacy::serialize::tests::serialize;
+ use crate::legacy::{Ciphertext, Plaintext};
+ use crate::{shared_data, DeLengthOutOfRange};
+ use std::panic;
+
+ extern crate std;
+
+ #[test]
+ fn actual_length_must_be_1() {
+ for l in [0, 2] {
+ let actual = DeActualLength::try_from(l).unwrap();
+ let _ = panic::catch_unwind(|| {
+ <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual)
+ })
+ .unwrap_err();
+ }
+
+ assert_eq!(
+ 1,
+ <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(
+ DeActualLength::try_from(1).unwrap(),
+ )
+ .as_u8()
+ )
+ }
+
+ #[test]
+ fn encoded_length_must_be_1() {
+ for l in [0, 2] {
+ assert_eq!(
+ DeLengthOutOfRange,
+ <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(
+ DeEncodedLength::try_from(l).unwrap()
+ )
+ .unwrap_err()
+ )
+ }
+
+ assert_eq!(
+ 1,
+ <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(
+ DeEncodedLength::from(1)
+ )
+ .unwrap()
+ .as_u8()
+ );
+ }
+
+ #[test]
+ fn tx_power_de_contents_roundtrip_unencrypted() {
+ let tx = shared_data::TxPower::try_from(-10).unwrap();
+ let _ = de_roundtrip_test!(
+ TxPowerDataElement,
+ TxPower,
+ TxPower,
+ Plaintext,
+ serialize::<Plaintext, _>(&TxPowerDataElement::from(tx))
+ );
+ }
+
+ #[test]
+ fn tx_power_de_contents_roundtrip_ldt() {
+ let tx = shared_data::TxPower::try_from(-10).unwrap();
+
+ let _ = de_roundtrip_test!(
+ TxPowerDataElement,
+ TxPower,
+ TxPower,
+ Ciphertext,
+ serialize::<Ciphertext, _>(&TxPowerDataElement::from(tx))
+ );
+ }
+
+ mod coverage_gaming {
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::shared_data::TxPower;
+ use alloc::format;
+
+ #[test]
+ fn tx_power_de() {
+ let de = TxPowerDataElement::from(TxPower::try_from(3).unwrap());
+ // debug
+ let _ = format!("{:?}", de);
+ // trivial accessor
+ assert_eq!(3, de.tx_power_value());
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/de_type/mod.rs b/nearby/presence/np_adv/src/legacy/de_type/mod.rs
deleted file mode 100644
index 304347d..0000000
--- a/nearby/presence/np_adv/src/legacy/de_type/mod.rs
+++ /dev/null
@@ -1,356 +0,0 @@
-// 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.
-
-//! V0 data element types.
-//!
-//! In V0, there are only 16 DE types total, and parsing unknown types is not possible, so we can
-//! represent all known DE types in enums without needing to handle the "unknown type" case.
-
-use crate::{
- de_type::IdentityDataElementType,
- legacy::{
- actions::ActionsDataElement,
- data_elements::{DataElement as _, TxPowerDataElement},
- Ciphertext, PacketFlavorEnum, Plaintext, NP_MAX_DE_CONTENT_LEN,
- },
- DeLengthOutOfRange,
-};
-use core::ops;
-use ldt_np_adv::NP_LEGACY_METADATA_KEY_LEN;
-use strum_macros::EnumIter;
-
-#[cfg(test)]
-mod tests;
-
-/// A V0 DE type in `[0, 15]`.
-#[derive(Debug, PartialEq, Eq, Hash)]
-pub(crate) struct DeTypeCode {
- /// The code used in a V0 adv header
- code: u8,
-}
-
-impl DeTypeCode {
- /// Returns a u8 in `[0, 15`].
- pub(crate) fn as_u8(&self) -> u8 {
- self.code
- }
-}
-
-/// The DE type code is out of range for v0 DE types.
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub(crate) struct DeTypeCodeOutOfRange;
-
-impl TryFrom<u8> for DeTypeCode {
- type Error = DeTypeCodeOutOfRange;
-
- fn try_from(value: u8) -> Result<Self, Self::Error> {
- if value < 16 {
- Ok(Self { code: value })
- } else {
- Err(DeTypeCodeOutOfRange)
- }
- }
-}
-
-/// The actual length of a DE, not the encoded representation.
-///
-/// See [DeEncodedLength] for the encoded length.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub(crate) struct DeActualLength {
- /// Invariant: <= `NP_MAX_DE_CONTENT_LEN`.
- len: u8,
-}
-
-impl DeActualLength {
- pub(crate) const ZERO: DeActualLength = DeActualLength { len: 0 };
-
- pub(crate) fn as_usize(&self) -> usize {
- self.len as usize
- }
-}
-
-impl TryFrom<u8> for DeActualLength {
- type Error = DeLengthOutOfRange;
-
- fn try_from(value: u8) -> Result<Self, Self::Error> {
- if (value as usize) <= NP_MAX_DE_CONTENT_LEN {
- Ok(Self { len: value })
- } else {
- Err(DeLengthOutOfRange)
- }
- }
-}
-
-impl TryFrom<usize> for DeActualLength {
- type Error = DeLengthOutOfRange;
-
- fn try_from(value: usize) -> Result<Self, Self::Error> {
- if value <= NP_MAX_DE_CONTENT_LEN {
- Ok(Self { len: value as u8 })
- } else {
- Err(DeLengthOutOfRange)
- }
- }
-}
-
-/// The encoded length of a DE, not the actual length of the DE contents.
-///
-/// See [DeActualLength] for the length of the contents.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub(crate) struct DeEncodedLength {
- /// Invariant: `len <= 0x0F` (15, aka 4 bits)
- len: u8,
-}
-
-impl DeEncodedLength {
- /// Returns a u8 in `[0, 15]`
- pub(crate) fn as_u8(&self) -> u8 {
- self.len
- }
-
- /// Returns a usize in `[0, 15]`
- pub(crate) fn as_usize(&self) -> usize {
- self.len as usize
- }
-}
-
-impl TryFrom<u8> for DeEncodedLength {
- type Error = DeLengthOutOfRange;
-
- fn try_from(value: u8) -> Result<Self, Self::Error> {
- if value < 16 {
- Ok(Self { len: value })
- } else {
- Err(DeLengthOutOfRange)
- }
- }
-}
-
-/// DE types for normal DEs (not an identity).
-///
-/// May be contained in identity DEs (see [IdentityDataElementType]). Must not overlap with
-/// [IdentityDataElementType].
-#[derive(EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum PlainDataElementType {
- TxPower,
- Actions,
-}
-
-impl PlainDataElementType {
- pub(crate) fn as_generic_de_type(&self) -> DataElementType {
- match self {
- PlainDataElementType::TxPower => DataElementType::TxPower,
- PlainDataElementType::Actions => DataElementType::Actions,
- }
- }
-
- pub(crate) fn supports_flavor(&self, flavor: PacketFlavorEnum) -> bool {
- match self {
- PlainDataElementType::Actions => {
- // Actions is effectively two different DEs based on which actions it can
- // contain, so we have to check them separately. The Plaintext one obviously
- // supports plaintext, and vice versa, so we could just say `true` here, but we
- // spell it out to be consistent with the other DE types.
- match flavor {
- PacketFlavorEnum::Plaintext => {
- ActionsDataElement::<Plaintext>::supports_flavor(flavor)
- }
- PacketFlavorEnum::Ciphertext => {
- ActionsDataElement::<Ciphertext>::supports_flavor(flavor)
- }
- }
- }
- PlainDataElementType::TxPower => TxPowerDataElement::supports_flavor(flavor),
- }
- }
-}
-
-/// Corresponds to the different implementations of [DataElement].
-///
-/// It's intended for use cases that don't care if a DE is a plain or identity DE. Every variant
-/// corresponds to either a [PlainDataElementType] or a [IdentityDataElementType].
-#[derive(EnumIter, Debug, Clone, Copy, PartialEq, Eq)]
-#[allow(missing_docs)]
-#[doc(hidden)]
-pub enum DataElementType {
- PrivateIdentity,
- TrustedIdentity,
- PublicIdentity,
- ProvisionedIdentity,
- TxPower,
- Actions,
-}
-
-const DE_TYPES_BY_CODE: [Option<DataElementType>; 16] = [
- None, // 0b0000
- Some(DataElementType::PrivateIdentity), // 0b0001
- Some(DataElementType::TrustedIdentity), // 0b0010
- Some(DataElementType::PublicIdentity), // 0b0011
- Some(DataElementType::ProvisionedIdentity), // 0b0100
- Some(DataElementType::TxPower), // 0b0101
- Some(DataElementType::Actions), // 0b0110
- None, // 0b0111
- None, // 0b1000
- None, // 0b1001
- None, // 0b1010
- None, // 0b1011
- None, // 0b1100
- None, // 0b1101
- None, // 0b1110
- None, // 0b1111
-];
-
-impl DataElementType {
- /// Salt + key + at least 2 bytes of DE to make LDT ciphertext min length
- const VALID_ENCRYPTED_IDENTITY_DE_ACTUAL_LEN: ops::RangeInclusive<usize> =
- (2 + NP_LEGACY_METADATA_KEY_LEN + 2..=NP_MAX_DE_CONTENT_LEN);
- const VALID_ENCRYPTED_IDENTITY_DE_HEADER_LEN: ops::RangeInclusive<usize> = (2..=6);
-
- /// If there is a corresponding [ContainerDataElementType], returns it, otherwise None.
- pub(crate) fn try_as_identity_de_type(&self) -> Option<IdentityDataElementType> {
- match self {
- DataElementType::PrivateIdentity => Some(IdentityDataElementType::Private),
- DataElementType::TrustedIdentity => Some(IdentityDataElementType::Trusted),
- DataElementType::PublicIdentity => Some(IdentityDataElementType::Public),
- DataElementType::ProvisionedIdentity => Some(IdentityDataElementType::Provisioned),
- DataElementType::TxPower | DataElementType::Actions => None,
- }
- }
-
- /// If there is a corresponding [PlainDataElementType], returns it, otherwise None.
- pub(crate) fn try_as_plain_de_type(&self) -> Option<PlainDataElementType> {
- match self {
- DataElementType::TxPower => Some(PlainDataElementType::TxPower),
- DataElementType::Actions => Some(PlainDataElementType::Actions),
- DataElementType::PrivateIdentity
- | DataElementType::TrustedIdentity
- | DataElementType::PublicIdentity
- | DataElementType::ProvisionedIdentity => None,
- }
- }
-
- /// Returns the matching type for the code, else `None`
- pub(crate) fn from_type_code(de_type: DeTypeCode) -> Option<Self> {
- DE_TYPES_BY_CODE.get(de_type.as_u8() as usize).and_then(|o| *o)
- }
-
- /// A type code in `[0,15]` for use in the high bits of the DE header byte.
- pub(crate) fn type_code(&self) -> DeTypeCode {
- match self {
- DataElementType::PrivateIdentity => IdentityDataElementType::Private.shared_type_code(),
- DataElementType::TrustedIdentity => IdentityDataElementType::Trusted.shared_type_code(),
- DataElementType::PublicIdentity => IdentityDataElementType::Public.shared_type_code(),
- DataElementType::ProvisionedIdentity => {
- IdentityDataElementType::Provisioned.shared_type_code()
- }
- DataElementType::TxPower => 0b0101,
- DataElementType::Actions => 0b0110,
- }
- .try_into()
- .expect("hardcoded type codes are valid")
- }
-
- /// Convert the actual DE length to the encoded length included in the header.
- ///
- /// Returns `Err` if the actual length is invalid for the type, or the corresponding encoded length is out of range.
- pub(crate) fn encoded_len_for_actual_len(
- &self,
- actual_len: DeActualLength,
- ) -> Result<DeEncodedLength, DeLengthOutOfRange> {
- match self {
- // TODO 0-length provisioned
- DataElementType::PrivateIdentity
- | DataElementType::TrustedIdentity
- | DataElementType::ProvisionedIdentity => {
- if !Self::VALID_ENCRYPTED_IDENTITY_DE_ACTUAL_LEN.contains(&actual_len.as_usize()) {
- Err(DeLengthOutOfRange)
- } else {
- actual_len
- .len
- .checked_sub(16)
- .ok_or(DeLengthOutOfRange)
- .and_then(|n| n.try_into())
- }
- }
- DataElementType::PublicIdentity => {
- if actual_len.len != 0 {
- Err(DeLengthOutOfRange)
- } else {
- actual_len.len.try_into()
- }
- }
- DataElementType::TxPower => {
- if actual_len.len != 1 {
- Err(DeLengthOutOfRange)
- } else {
- actual_len.len.try_into()
- }
- }
- DataElementType::Actions => {
- // doesn't matter which variant is used
- if !ActionsDataElement::<Plaintext>::ACTIONS_LEN.contains(&actual_len.as_usize()) {
- Err(DeLengthOutOfRange)
- } else {
- actual_len.len.try_into()
- }
- }
- }
- }
-
- /// Convert the length in the header to the actual DE length.
- ///
- /// Returns `Err` if the encoded length is invalid for the type, or the corresponding actual length is out of range.
- pub(crate) fn actual_len_for_encoded_len(
- &self,
- header_len: DeEncodedLength,
- ) -> Result<DeActualLength, DeLengthOutOfRange> {
- match self {
- DataElementType::PrivateIdentity
- | DataElementType::TrustedIdentity
- // TODO provisioned 0 length
- | DataElementType::ProvisionedIdentity => {
- if !Self::VALID_ENCRYPTED_IDENTITY_DE_HEADER_LEN.contains(&header_len.as_usize()) {
- Err(DeLengthOutOfRange)
- } else {
- header_len
- .len
- .checked_add(16)
- .ok_or(DeLengthOutOfRange)
- .and_then(|n| n.try_into())
- }
- }
- DataElementType::PublicIdentity => {
- if header_len.len != 0 {
- Err(DeLengthOutOfRange)
- } else {
- header_len.len.try_into()
- }
- }
- DataElementType::TxPower => {
- if header_len.len != 1 {
- Err(DeLengthOutOfRange)
- } else {
- header_len.len.try_into()
- }
- }
- DataElementType::Actions => {
- if !ActionsDataElement::<Plaintext>::ACTIONS_LEN.contains(&header_len.as_usize()) {
- Err(DeLengthOutOfRange)
- } else {
- header_len.len.try_into()
- }
- }
- }
- }
-}
diff --git a/nearby/presence/np_adv/src/legacy/de_type/tests.rs b/nearby/presence/np_adv/src/legacy/de_type/tests.rs
deleted file mode 100644
index fc64321..0000000
--- a/nearby/presence/np_adv/src/legacy/de_type/tests.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-
-use super::*;
-use crate::legacy::serialize::id_de_type_as_generic_de_type;
-use std::{collections, vec::Vec};
-use strum::IntoEnumIterator as _;
-
-#[test]
-fn no_plain_vs_identity_type_overlap() {
- let plain_types =
- PlainDataElementType::iter().map(|t| t.as_generic_de_type()).collect::<Vec<_>>();
- let identity_types =
- IdentityDataElementType::iter().map(id_de_type_as_generic_de_type).collect::<Vec<_>>();
-
- for plain_de_type in plain_types.iter() {
- assert!(!identity_types.iter().any(|i| i == plain_de_type));
- assert_eq!(None, plain_de_type.try_as_identity_de_type());
- }
-
- for id_de_type in identity_types.iter() {
- assert!(!plain_types.iter().any(|p| p == id_de_type));
- assert_eq!(None, id_de_type.try_as_plain_de_type());
- }
-}
-
-#[test]
-fn generic_type_is_either_plain_or_identity() {
- let generic_types = DataElementType::iter().collect::<Vec<_>>();
-
- for g in generic_types.iter() {
- let total = g.try_as_identity_de_type().map(|_| 1).unwrap_or(0)
- + g.try_as_plain_de_type().map(|_| 1).unwrap_or(0);
-
- assert_eq!(1, total);
- }
-}
-
-#[test]
-fn generic_de_type_codes_are_consistent() {
- for det in DataElementType::iter() {
- let actual = DataElementType::from_type_code(det.type_code());
- assert_eq!(Some(det), actual)
- }
-}
-
-#[test]
-fn generic_de_distinct_type_codes() {
- let codes =
- DataElementType::iter().map(|det| det.type_code()).collect::<collections::HashSet<_>>();
- assert_eq!(codes.len(), DataElementType::iter().count());
-}
-
-#[test]
-fn generic_de_no_accidentally_mapped_type_codes() {
- let codes =
- DataElementType::iter().map(|det| det.type_code()).collect::<collections::HashSet<_>>();
- for possible_code in 0..=15 {
- if codes.contains(&possible_code.try_into().unwrap()) {
- continue;
- }
-
- assert_eq!(None, DataElementType::from_type_code(possible_code.try_into().unwrap()));
- }
-}
-
-#[test]
-fn actions_de_length_zero_rejected() {
- let encoded = DeEncodedLength::try_from(0).unwrap();
- let maybe_actual_len = DataElementType::Actions.actual_len_for_encoded_len(encoded);
- assert_eq!(Err(DeLengthOutOfRange), maybe_actual_len);
-}
-
-#[test]
-fn de_length_actual_encoded_round_trip() {
- for de_type in DataElementType::iter() {
- // for all possible lengths, calculate actual -> encoded and the inverse
- let actual_to_encoded = (0_u8..=255)
- .filter_map(|num| num.try_into().ok())
- .filter_map(|actual: DeActualLength| {
- de_type.encoded_len_for_actual_len(actual).ok().map(|encoded| (actual, encoded))
- })
- .collect::<collections::HashMap<_, _>>();
-
- let encoded_to_actual = (0_u8..=255)
- .filter_map(|num| num.try_into().ok())
- .filter_map(|encoded: DeEncodedLength| {
- de_type.actual_len_for_encoded_len(encoded).ok().map(|actual| (encoded, actual))
- })
- .collect::<collections::HashMap<_, _>>();
-
- // ensure the two maps are inverses of each other
- assert_eq!(
- actual_to_encoded,
- encoded_to_actual.into_iter().map(|(encoded, actual)| (actual, encoded)).collect(),
- "de type: {de_type:?}"
- );
- }
-}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/intermediate/mod.rs b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/mod.rs
new file mode 100644
index 0000000..13ede05
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/mod.rs
@@ -0,0 +1,146 @@
+// 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.
+
+//! The first stage of deserialization: just header data (if any) and the bulk contents of the
+//! advertisement, with no disaggregation into individual data elements.
+
+use crate::header::V0Encoding;
+use crate::helpers::parse_byte_array;
+use crate::legacy::deserialize::{
+ AdvDeserializeError, DeIterator, DecryptError, DecryptedAdvContents,
+};
+#[cfg(test)]
+use crate::legacy::deserialize::{DataElementDeserializer, GenericDeIterator};
+use crate::legacy::{Plaintext, NP_MIN_ADV_CONTENT_LEN};
+use crypto_provider::CryptoProvider;
+use ldt_np_adv::V0Salt;
+use nom::combinator;
+
+#[cfg(test)]
+mod tests;
+
+/// The header components, if any, and the bytes that will later be decrypted and/or parsed into DEs.
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) enum IntermediateAdvContents<'d> {
+ /// Plaintext advertisements
+ Unencrypted(UnencryptedAdvContents<'d>),
+ /// Ciphertext advertisements
+ Ldt(LdtAdvContents<'d>),
+}
+
+impl<'d> IntermediateAdvContents<'d> {
+ #[cfg(test)]
+ pub(crate) fn as_unencrypted(&self) -> Option<&UnencryptedAdvContents<'d>> {
+ match self {
+ IntermediateAdvContents::Unencrypted(c) => Some(c),
+ IntermediateAdvContents::Ldt(_) => None,
+ }
+ }
+
+ #[cfg(test)]
+ pub(crate) fn as_ldt(&self) -> Option<&LdtAdvContents<'d>> {
+ match self {
+ IntermediateAdvContents::Unencrypted(_) => None,
+ IntermediateAdvContents::Ldt(c) => Some(c),
+ }
+ }
+
+ /// Performs basic structural checks on header and content, but doesn't deserialize DEs or
+ /// decrypt.
+ pub(crate) fn deserialize<C: CryptoProvider>(
+ encoding: V0Encoding,
+ input: &[u8],
+ ) -> Result<IntermediateAdvContents<'_>, AdvDeserializeError> {
+ match encoding {
+ V0Encoding::Unencrypted => {
+ if input.len() < NP_MIN_ADV_CONTENT_LEN {
+ return Err(AdvDeserializeError::NoDataElements);
+ }
+ Ok(IntermediateAdvContents::Unencrypted(UnencryptedAdvContents { data: input }))
+ }
+ V0Encoding::Ldt => {
+ let (ciphertext, salt) =
+ parse_v0_salt(input).map_err(|_| AdvDeserializeError::InvalidStructure)?;
+ LdtAdvContents::new::<C>(salt, ciphertext)
+ .ok_or(AdvDeserializeError::InvalidStructure)
+ .map(IntermediateAdvContents::Ldt)
+ }
+ }
+ }
+}
+
+/// The contents of a plaintext advertisement.
+#[derive(Debug, PartialEq, Eq)]
+pub struct UnencryptedAdvContents<'d> {
+ /// Contents of the advertisement after the version header.
+ ///
+ /// Contents are at least [NP_MIN_ADV_CONTENT_LEN].
+ data: &'d [u8],
+}
+
+impl<'d> UnencryptedAdvContents<'d> {
+ /// Returns an iterator over the v0 data elements
+ pub fn data_elements(&self) -> DeIterator<'d, Plaintext> {
+ DeIterator::new(self.data)
+ }
+
+ #[cfg(test)]
+ pub(in crate::legacy) fn generic_data_elements<D: DataElementDeserializer>(
+ &self,
+ ) -> GenericDeIterator<Plaintext, D> {
+ GenericDeIterator::new(self.data)
+ }
+}
+
+/// Contents of an encrypted advertisement before decryption.
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) struct LdtAdvContents<'d> {
+ /// Salt from the advertisement, converted into a padder.
+ /// Pre-calculated so it's only derived once across multiple decrypt attempts.
+ salt_padder: ldt::XorPadder<{ crypto_provider::aes::BLOCK_SIZE }>,
+ /// The salt instance used for encryption of this advertisement.
+ salt: V0Salt,
+ /// Ciphertext containing the identity token and any data elements.
+ /// Must be a valid length for LDT.
+ ciphertext: &'d [u8],
+}
+
+impl<'d> LdtAdvContents<'d> {
+ /// Returns `None` if `ciphertext` is not a valid LDT-XTS-AES ciphertext length.
+ pub(crate) fn new<C: CryptoProvider>(salt: V0Salt, ciphertext: &'d [u8]) -> Option<Self> {
+ if !ldt_np_adv::VALID_INPUT_LEN.contains(&ciphertext.len()) {
+ return None;
+ }
+ Some(Self { salt_padder: ldt_np_adv::salt_padder::<C>(salt), salt, ciphertext })
+ }
+
+ /// Try decrypting with an identity's LDT cipher and deserializing the resulting data elements.
+ ///
+ /// Returns the decrypted data if decryption and verification succeeded and the resulting DEs could be parsed
+ /// successfully, otherwise `Err`.
+ pub(crate) fn try_decrypt<C: CryptoProvider>(
+ &self,
+ cipher: &ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C>,
+ ) -> Result<DecryptedAdvContents, DecryptError> {
+ let (identity_token, plaintext) = cipher
+ .decrypt_and_verify(self.ciphertext, &self.salt_padder)
+ .map_err(|_e| DecryptError::DecryptOrVerifyError)?;
+
+ Ok(DecryptedAdvContents::new(identity_token, self.salt, plaintext))
+ }
+}
+
+fn parse_v0_salt(input: &[u8]) -> nom::IResult<&[u8], V0Salt> {
+ combinator::map(parse_byte_array::<2>, V0Salt::from)(input)
+}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/error_conditions.rs b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/error_conditions.rs
new file mode 100644
index 0000000..5cbd784
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/error_conditions.rs
@@ -0,0 +1,85 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+mod unencrypted_encoder {
+ use crate::header::V0Encoding;
+ use crate::legacy::deserialize::intermediate::IntermediateAdvContents;
+ use crate::legacy::deserialize::AdvDeserializeError;
+ use crypto_provider_default::CryptoProviderImpl;
+
+ #[test]
+ fn parse_zero_len_error() {
+ assert_eq!(
+ AdvDeserializeError::NoDataElements,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &[],
+ )
+ .unwrap_err()
+ );
+ }
+}
+
+mod ldt_encoder {
+ use crate::header::V0Encoding;
+ use crate::legacy::deserialize::intermediate::IntermediateAdvContents;
+ use crate::legacy::deserialize::AdvDeserializeError;
+ use alloc::vec;
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt_np_adv::{V0_IDENTITY_TOKEN_LEN, V0_SALT_LEN};
+
+ #[test]
+ fn all_below_min_ldt_len_error() {
+ for len in 0..(V0_SALT_LEN + ldt_np_adv::VALID_INPUT_LEN.start) {
+ assert_eq!(
+ AdvDeserializeError::InvalidStructure,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &vec![0; len],
+ )
+ .unwrap_err()
+ );
+ }
+
+ // 1 more byte is enough
+ let data = &[0; ldt_np_adv::VALID_INPUT_LEN.start + V0_SALT_LEN];
+ assert!(IntermediateAdvContents::deserialize::<CryptoProviderImpl>(V0Encoding::Ldt, data)
+ .is_ok())
+ }
+
+ #[test]
+ fn above_max_ldt_len_error() {
+ let salt = [0x55; V0_SALT_LEN];
+ // this is longer than can fit in a BLE 4.2 adv, but we're just testing LDT limits here
+ let payload_len = 2 + crypto_provider::aes::BLOCK_SIZE;
+ let data =
+ &[&salt, [0x11; V0_IDENTITY_TOKEN_LEN].as_slice(), &vec![0xCC; payload_len]].concat();
+ // 1 byte long
+ assert_eq!(V0_SALT_LEN + ldt_np_adv::VALID_INPUT_LEN.end, data.len());
+
+ assert_eq!(
+ AdvDeserializeError::InvalidStructure,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(V0Encoding::Ldt, data)
+ .unwrap_err()
+ );
+
+ // 1 fewer byte is enough
+ let data = &[&salt, [0x11; V0_IDENTITY_TOKEN_LEN].as_slice(), &vec![0xCC; payload_len - 1]]
+ .concat();
+ assert!(IntermediateAdvContents::deserialize::<CryptoProviderImpl>(V0Encoding::Ldt, data)
+ .is_ok())
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/happy_path.rs b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/happy_path.rs
new file mode 100644
index 0000000..f74c1a9
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/happy_path.rs
@@ -0,0 +1,106 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+mod unencrypted_encoder {
+ use crate::header::V0Encoding;
+ use crate::legacy::data_elements::de_type::{DeEncodedLength, DeTypeCode, MAX_DE_ENCODED_LEN};
+ use crate::legacy::deserialize::intermediate::IntermediateAdvContents;
+ use crate::legacy::serialize::encode_de_header;
+ use crate::legacy::NP_MAX_DE_CONTENT_LEN;
+ use crypto_provider_default::CryptoProviderImpl;
+
+ #[test]
+ fn parse_min_len() {
+ let header = encode_de_header(DeTypeCode::try_from(14).unwrap(), DeEncodedLength::from(0));
+ assert_eq!(
+ &[header],
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &[header],
+ )
+ .unwrap()
+ .as_unencrypted()
+ .unwrap()
+ .data
+ )
+ }
+
+ #[test]
+ fn parse_max_len() {
+ let header = encode_de_header(
+ DeTypeCode::try_from(15).unwrap(),
+ DeEncodedLength::try_from(MAX_DE_ENCODED_LEN).unwrap(),
+ );
+ let data = &[&[header], [0x22; NP_MAX_DE_CONTENT_LEN].as_slice()].concat();
+ assert_eq!(
+ data,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ data,
+ )
+ .unwrap()
+ .as_unencrypted()
+ .unwrap()
+ .data
+ )
+ }
+}
+
+mod ldt_encoder {
+ use crate::header::V0Encoding;
+ use crate::legacy::deserialize::intermediate::{IntermediateAdvContents, LdtAdvContents};
+ use crate::legacy::NP_MAX_ADV_CONTENT_LEN;
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt::LdtCipher;
+ use ldt_np_adv::{salt_padder, V0_IDENTITY_TOKEN_LEN, V0_SALT_LEN};
+
+ #[test]
+ fn parse_min_len() {
+ // not going to bother to make it look like encrypted DEs since this layer doesn't care
+ let salt = [0x55; V0_SALT_LEN];
+ let data = &[&salt, [0x11; V0_IDENTITY_TOKEN_LEN].as_slice(), &[0xCC; 2]].concat();
+ assert_eq!(
+ V0_SALT_LEN
+ + ldt_np_adv::NpLdtEncryptCipher::<CryptoProviderImpl>::VALID_INPUT_LEN.start,
+ data.len()
+ );
+
+ assert_ldt_contents(salt, data);
+ }
+
+ #[test]
+ fn parse_max_len() {
+ let salt = [0x55; V0_SALT_LEN];
+ let data = &[&salt, [0x11; V0_IDENTITY_TOKEN_LEN].as_slice(), &[0xCC; 7]].concat();
+ assert_eq!(NP_MAX_ADV_CONTENT_LEN, data.len());
+
+ assert_ldt_contents(salt, data);
+ }
+
+ fn assert_ldt_contents(salt: [u8; V0_SALT_LEN], data: &[u8]) {
+ assert_eq!(
+ &LdtAdvContents {
+ salt_padder: salt_padder::<CryptoProviderImpl>(salt.into()),
+ salt: salt.into(),
+ ciphertext: &data[V0_SALT_LEN..],
+ },
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(V0Encoding::Ldt, data)
+ .unwrap()
+ .as_ldt()
+ .unwrap()
+ );
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/mod.rs b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/mod.rs
new file mode 100644
index 0000000..289fdd8
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/intermediate/tests/mod.rs
@@ -0,0 +1,16 @@
+// 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.
+
+mod error_conditions;
+mod happy_path;
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/mod.rs b/nearby/presence/np_adv/src/legacy/deserialize/mod.rs
index d6c6b36..d305b57 100644
--- a/nearby/presence/np_adv/src/legacy/deserialize/mod.rs
+++ b/nearby/presence/np_adv/src/legacy/deserialize/mod.rs
@@ -16,323 +16,147 @@
//!
//! This module only deals with the _contents_ of an advertisement, not the advertisement header.
+use core::fmt;
use core::marker::PhantomData;
+use crate::legacy::data_elements::tx_power::TxPowerDataElement;
use crate::{
credential::v0::V0,
- de_type::EncryptedIdentityDataElementType,
legacy::{
- actions,
- data_elements::{DataElement, *},
- de_type::{DataElementType, DeEncodedLength, DeTypeCode, PlainDataElementType},
- Ciphertext, PacketFlavor, Plaintext, ShortMetadataKey, NP_MAX_DE_CONTENT_LEN,
+ data_elements::{
+ actions,
+ de_type::{DeEncodedLength, DeTypeCode},
+ DataElementDeserializeError, DeserializeDataElement, LengthMapper,
+ },
+ Ciphertext, PacketFlavor,
},
- HasIdentityMatch, PlaintextIdentityMode,
+ DeLengthOutOfRange,
};
use array_view::ArrayView;
-use crypto_provider::CryptoProvider;
-use ldt_np_adv::{LegacySalt, NP_LEGACY_METADATA_KEY_LEN};
-use nom::{bytes, combinator, number, sequence};
-
-use super::BLE_ADV_SVC_CONTENT_LEN;
+use ldt_np_adv::{V0IdentityToken, V0Salt, NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN};
+use nom::{bytes, combinator, number, Finish};
#[cfg(test)]
mod tests;
-/// Deserialize an advertisement into data elements (if plaintext) or an identity type and
-/// ciphertext.
-pub(crate) fn deserialize_adv_contents<C: CryptoProvider>(
- input: &[u8],
-) -> Result<IntermediateAdvContents<'_>, AdvDeserializeError> {
- parse_raw_adv_contents::<C>(input).and_then(|raw_adv| match raw_adv {
- RawAdvertisement::Plaintext(adv_contents) => {
- if adv_contents.data_elements().next().is_none() {
- return Err(AdvDeserializeError::NoPublicDataElements);
- }
+pub(crate) mod intermediate;
- Ok(IntermediateAdvContents::Plaintext(adv_contents))
- }
- RawAdvertisement::Ciphertext(eac) => Ok(IntermediateAdvContents::Ciphertext(eac)),
- })
-}
-
-/// Parse an advertisement's contents to the level of raw data elements (i.e no decryption,
-/// no per-type deserialization, etc).
-///
-/// Consumes the entire input.
-fn parse_raw_adv_contents<C: CryptoProvider>(
- input: &[u8],
-) -> Result<RawAdvertisement, AdvDeserializeError> {
- if input.is_empty() {
- return Err(AdvDeserializeError::MissingIdentity);
- }
- match parse_de(input) {
- Ok((rem, identity_de)) => {
- if let Some(identity_de_type) = identity_de.de_type.try_as_identity_de_type() {
- match identity_de_type.as_encrypted_identity_de_type() {
- Some(encrypted_de_type) => {
- if matches!(parse_de(rem), Err(nom::Err::Error(..))) {
- match encrypted_de_type {
- // TODO handle length=0 provisioned identity DEs
- EncryptedIdentityDataElementType::Private
- | EncryptedIdentityDataElementType::Trusted
- | EncryptedIdentityDataElementType::Provisioned => combinator::map(
- parse_encrypted_identity_de_contents,
- |(salt, payload)| {
- RawAdvertisement::Ciphertext(EncryptedAdvContents {
- identity_type: encrypted_de_type,
- salt_padder: ldt_np_adv::salt_padder::<16, C>(salt),
- salt,
- ciphertext: payload,
- })
- },
- )(
- identity_de.contents,
- )
- .map(|(_rem, contents)| contents)
- .map_err(|_e| AdvDeserializeError::AdvertisementDeserializeError),
- }
- } else {
- Err(AdvDeserializeError::TooManyTopLevelDataElements)
- }
- }
- // It's an identity de, but not encrypted, so it must be public, and the rest
- // must be plain
- None => Ok(RawAdvertisement::Plaintext(PlaintextAdvContents {
- identity_type: PlaintextIdentityMode::Public,
- data: rem,
- })),
- }
- } else {
- Err(AdvDeserializeError::MissingIdentity)
- }
- }
- Err(nom::Err::Error(_)) | Err(nom::Err::Failure(_)) => {
- Err(AdvDeserializeError::AdvertisementDeserializeError)
- }
- Err(nom::Err::Incomplete(_)) => {
- panic!("Should not hit Incomplete when using nom::complete parsers")
- }
- }
-}
+use crate::credential::matched::HasIdentityMatch;
+use crate::legacy::data_elements::actions::ActionsDataElement;
+use crate::legacy::data_elements::de_type::{DataElementType, DeActualLength};
+use crate::legacy::Plaintext;
+/// exposed because the unencrypted case isn't just for intermediate: no further processing is needed
+pub use intermediate::UnencryptedAdvContents;
/// Legacy advertisement parsing errors
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum AdvDeserializeError {
- /// Parsing the overall advertisement or DE structure failed
- AdvertisementDeserializeError,
- /// Must not have any other top level data elements if there is an encrypted identity DE
- TooManyTopLevelDataElements,
- /// Missing identity DE
- MissingIdentity,
- /// Non-identity DE contents must not be empty
- NoPublicDataElements,
-}
-
-/// Parse an individual DE into its header and contents.
-fn parse_de(input: &[u8]) -> nom::IResult<&[u8], RawDataElement, DataElementDeserializeError> {
- let (remaining, (de_type, actual_len)) =
- combinator::map_opt(number::complete::u8, |de_header| {
- // header: LLLLTTTT
- let len = de_header >> 4;
- let de_type = de_header & 0x0F;
- DeTypeCode::try_from(de_type).ok().and_then(DataElementType::from_type_code).and_then(
- |de_type| {
- len.try_into()
- .ok()
- .and_then(|len: DeEncodedLength| {
- de_type.actual_len_for_encoded_len(len).ok()
- })
- .map(|len| (de_type, len))
- },
- )
- })(input)?;
-
- combinator::map(bytes::complete::take(actual_len.as_usize()), move |contents| RawDataElement {
- de_type,
- contents,
- })(remaining)
-}
-
-/// Parse legacy encrypted identity DEs (private, trusted, provisioned) into salt and ciphertext
-/// (encrypted metadata key and at least 2 bytes of DEs).
-///
-/// Consumes the entire input.
-fn parse_encrypted_identity_de_contents(
- de_contents: &[u8],
-) -> nom::IResult<&[u8], (ldt_np_adv::LegacySalt, &[u8])> {
- combinator::all_consuming(sequence::tuple((
- // 2-byte salt
- combinator::map(
- combinator::map_res(bytes::complete::take(2_usize), |slice: &[u8]| slice.try_into()),
- |arr: [u8; 2]| arr.into(),
- ),
- // 14-byte encrypted metadata key plus encrypted DEs, which must together be at least 16
- // bytes (AES block size), and at most a full DE minus the size of the salt.
- bytes::complete::take_while_m_n(16_usize, NP_MAX_DE_CONTENT_LEN - 2, |_| true),
- )))(de_contents)
+ /// Header or other structure was invalid
+ InvalidStructure,
+ /// DE contents must not be empty
+ NoDataElements,
}
/// A data element with content length determined and validated per its type's length rules, but
/// no further decoding performed.
#[derive(Debug, PartialEq, Eq)]
-struct RawDataElement<'d> {
- de_type: DataElementType,
+pub(in crate::legacy) struct RawDataElement<'d, D: DataElementDeserializer> {
+ pub(in crate::legacy) de_type: D::DeTypeDisambiguator,
/// Byte array payload of the data element, without the DE header.
- contents: &'d [u8],
+ pub(in crate::legacy) contents: &'d [u8],
}
-/// An advertisement broken down into data elements, but before decryption or mapping to higher
-/// level DE representations.
-#[derive(Debug, PartialEq, Eq)]
-enum RawAdvertisement<'d> {
- Plaintext(PlaintextAdvContents<'d>),
- Ciphertext(EncryptedAdvContents<'d>),
+impl<'d, D: DataElementDeserializer> RawDataElement<'d, D> {
+ /// Parse an individual DE into its header and contents.
+ fn parse(input: &'d [u8]) -> nom::IResult<&[u8], Self, DataElementDeserializeError> {
+ let (input, (de_type, actual_len)) = combinator::map_res(
+ combinator::map_opt(number::complete::u8, |de_header| {
+ // header: LLLLTTTT
+ let len = de_header >> 4;
+ let de_type_num = de_header & 0x0F;
+
+ // these can't fail since both inputs are 4 bits and will fit
+ DeTypeCode::try_from(de_type_num).ok().and_then(|de_type| {
+ DeEncodedLength::try_from(len).ok().map(|encoded_len| (de_type, encoded_len))
+ })
+ }),
+ |(de_type, encoded_len)| {
+ D::map_encoded_len_to_actual_len(de_type, encoded_len).map_err(|e| match e {
+ LengthError::InvalidLength => {
+ DataElementDeserializeError::InvalidDeLength { de_type, len: encoded_len }
+ }
+ LengthError::InvalidType => {
+ DataElementDeserializeError::InvalidDeType { de_type }
+ }
+ })
+ },
+ )(input)?;
+
+ combinator::map(bytes::complete::take(actual_len.as_usize()), move |contents| {
+ RawDataElement { de_type, contents }
+ })(input)
+ }
}
/// An iterator that parses the given data elements iteratively. In environments
/// where memory is not severely constrained, it is usually safer to collect
-/// this into `Result<Vec<PlainDataElement>>` so the validity of the whole
+/// this into `Result<Vec<DeserializedDataElement>>` so the validity of the whole
/// advertisement can be checked before proceeding with further processing.
#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct PlainDeIterator<'d, F>
-where
- F: PacketFlavor,
- actions::ActionsDataElement<F>: DataElement,
-{
- /// Data to be parsed, containing a sequence of data elements in serialized
- /// form. This should not contain the identity data elements.
- data: &'d [u8],
- _marker: PhantomData<F>,
+pub struct DeIterator<'d, F> {
+ delegate: GenericDeIterator<'d, F, StandardDeserializer>,
}
-impl<'d, F> PlainDeIterator<'d, F>
-where
- F: PacketFlavor,
- actions::ActionsDataElement<F>: DataElement,
-{
- fn raw_de_to_plain_de(
- raw_de: RawDataElement<'d>,
- ) -> Result<PlainDataElement<F>, DataElementDeserializeError> {
- let de_type = raw_de
- .de_type
- .try_as_plain_de_type()
- .ok_or(DataElementDeserializeError::DuplicateIdentityDataElement)?;
- (RawPlainDataElement { de_type, contents: raw_de.contents }).try_deserialize()
+impl<'d, F> DeIterator<'d, F> {
+ pub(in crate::legacy) fn new(data: &'d [u8]) -> Self {
+ Self { delegate: GenericDeIterator::new(data) }
}
}
-impl<'d, F> Iterator for PlainDeIterator<'d, F>
-where
- F: PacketFlavor,
- actions::ActionsDataElement<F>: DataElement,
-{
- type Item = Result<PlainDataElement<F>, DataElementDeserializeError>;
+impl<'d, F: PacketFlavor> Iterator for DeIterator<'d, F> {
+ type Item = Result<DeserializedDataElement<F>, DataElementDeserializeError>;
fn next(&mut self) -> Option<Self::Item> {
- let parse_result = nom::combinator::cut(nom::combinator::map_res(
- parse_de,
- Self::raw_de_to_plain_de,
- ))(self.data);
- match parse_result {
- Ok((rem, de)) => {
- self.data = rem;
- Some(Ok(de))
- }
- Err(nom::Err::Error(_)) => {
- panic!("All Errors are turned into Failures with `cut` above");
- }
- Err(nom::Err::Failure(DataElementDeserializeError::NomError(
- nom::error::ErrorKind::Eof,
- ))) => {
- if self.data.is_empty() {
- None
- } else {
- Some(Err(DataElementDeserializeError::UnexpectedDataRemaining))
- }
- }
- Err(nom::Err::Failure(e)) => Some(Err(e)),
- Err(nom::Err::Incomplete(_)) => {
- panic!("Incomplete unexpected when using nom::complete APIs")
- }
- }
+ self.delegate.next()
}
}
-/// A "plain" data element (not a container) without parsing the content.
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) struct RawPlainDataElement<'d> {
- de_type: PlainDataElementType,
- /// Byte array payload of the data element, without the DE header.
- contents: &'d [u8],
+/// The generified innards of [DeIterator] so that it's possible to also use test-only
+/// deserializers.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub(in crate::legacy) struct GenericDeIterator<'d, F, D> {
+ /// Data to be parsed, containing a sequence of data elements in serialized
+ /// form.
+ data: &'d [u8],
+ _flavor_marker: PhantomData<F>,
+ _deser_marker: PhantomData<D>,
}
-impl<'d> RawPlainDataElement<'d> {
- /// Deserialize into a [PlainDataElement] to expose DE-type-specific data representations.
- ///
- /// Returns `None` if the contents of the raw DE can't be deserialized into the corresponding
- /// DE's representation.
- fn try_deserialize<F>(&self) -> Result<PlainDataElement<F>, DataElementDeserializeError>
- where
- F: PacketFlavor,
- actions::ActionsDataElement<F>: DataElement,
- {
- match self.de_type {
- PlainDataElementType::Actions => {
- actions::ActionsDataElement::deserialize::<F>(self.contents)
- .map(PlainDataElement::Actions)
- }
- PlainDataElementType::TxPower => {
- TxPowerDataElement::deserialize::<F>(self.contents).map(PlainDataElement::TxPower)
- }
- }
+impl<'d, F, D> GenericDeIterator<'d, F, D> {
+ fn new(data: &'d [u8]) -> Self {
+ Self { data, _flavor_marker: Default::default(), _deser_marker: Default::default() }
}
}
-/// Contents of an encrypted advertisement before decryption.
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) struct EncryptedAdvContents<'d> {
- identity_type: EncryptedIdentityDataElementType,
- /// Salt from the advertisement, converted into a padder.
- /// Pre-calculated so it's only derived once across multiple decrypt attempts.
- salt_padder: ldt::XorPadder<{ crypto_provider::aes::BLOCK_SIZE }>,
- /// The salt instance used for encryption of this advertisement.
- salt: LegacySalt,
- /// Ciphertext containing the metadata key and any data elements
- ciphertext: &'d [u8],
-}
+impl<'d, F: PacketFlavor, D: DataElementDeserializer> Iterator for GenericDeIterator<'d, F, D> {
+ type Item = Result<D::Deserialized<F>, DataElementDeserializeError>;
-impl<'d> EncryptedAdvContents<'d> {
- /// Try decrypting with an identity's LDT cipher and deserializing the resulting data elements.
- ///
- /// Returns the decrypted data if decryption and verification succeeded and the resulting DEs could be parsed
- /// successfully, otherwise `Err`.
- pub(crate) fn try_decrypt<C: CryptoProvider>(
- &self,
- cipher: &ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C>,
- ) -> Result<DecryptedAdvContents, DecryptError> {
- let plaintext = cipher
- .decrypt_and_verify(self.ciphertext, &self.salt_padder)
- .map_err(|_e| DecryptError::DecryptOrVerifyError)?;
-
- // plaintext starts with 14 bytes of metadata key, then DEs.
- let (remaining, metadata_key) = combinator::map_res(
- bytes::complete::take(NP_LEGACY_METADATA_KEY_LEN),
- |slice: &[u8]| slice.try_into(),
- )(plaintext.as_slice())
- .map_err(|_e: nom::Err<nom::error::Error<&[u8]>>| {
- DecryptError::DeserializeError(AdvDeserializeError::AdvertisementDeserializeError)
- })?;
-
- let remaining_arr = ArrayView::try_from_slice(remaining)
- .expect("Max remaining = 31 - 14 = 17 bytes < BLE_ADV_SVC_CONTENT_LEN");
-
- Ok(DecryptedAdvContents::new(
- self.identity_type,
- ShortMetadataKey(metadata_key),
- self.salt,
- remaining_arr,
- ))
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.data.is_empty() {
+ return None;
+ }
+ let parse_result = combinator::cut(combinator::map_res(
+ RawDataElement::parse,
+ D::deserialize_de,
+ ))(self.data);
+
+ match parse_result.finish() {
+ Ok((rem, de)) => {
+ self.data = rem;
+ Some(Ok(de))
+ }
+ Err(e) => Some(Err(e)),
+ }
}
}
@@ -341,124 +165,171 @@ impl<'d> EncryptedAdvContents<'d> {
pub(crate) enum DecryptError {
/// Decrypting or verifying the advertisement ciphertext failed
DecryptOrVerifyError,
- /// Decrypting succeeded, but deserializing from the plaintext failed
- DeserializeError(AdvDeserializeError),
-}
-
-impl From<AdvDeserializeError> for DecryptError {
- fn from(e: AdvDeserializeError) -> Self {
- DecryptError::DeserializeError(e)
- }
}
-/// All v0 normal DE types with deserialized contents.
-#[derive(Debug, PartialEq, Eq)]
+/// All v0 DE types with deserialized contents.
+#[derive(Debug, PartialEq, Eq, Clone)]
#[allow(missing_docs)]
-pub enum PlainDataElement<F: PacketFlavor> {
+pub enum DeserializedDataElement<F: PacketFlavor> {
Actions(actions::ActionsDataElement<F>),
TxPower(TxPowerDataElement),
}
-impl<F: PacketFlavor> PlainDataElement<F> {
+impl<F: PacketFlavor> DeserializedDataElement<F> {
/// Returns the DE type as a u8
#[cfg(feature = "devtools")]
pub fn de_type_code(&self) -> u8 {
match self {
- PlainDataElement::Actions(_) => DataElementType::Actions.type_code().as_u8(),
- PlainDataElement::TxPower(_) => DataElementType::TxPower.type_code().as_u8(),
+ DeserializedDataElement::Actions(_) => ActionsDataElement::<F>::DE_TYPE_CODE.as_u8(),
+ DeserializedDataElement::TxPower(_) => TxPowerDataElement::DE_TYPE_CODE.as_u8(),
}
}
/// Returns the serialized contents of the DE
#[cfg(feature = "devtools")]
- pub fn de_contents(&self) -> alloc::vec::Vec<u8> {
- use crate::legacy::serialize::{DataElementBundle, ToDataElementBundle};
+ #[allow(clippy::unwrap_used)]
+ pub fn de_contents(&self) -> alloc::vec::Vec<u8>
+ where
+ actions::ActionsDataElement<F>: crate::legacy::data_elements::SerializeDataElement<F>,
+ {
+ use crate::legacy::data_elements::{DataElementSerializationBuffer, SerializeDataElement};
+
+ let mut sink = DataElementSerializationBuffer::new(super::NP_MAX_ADV_CONTENT_LEN).unwrap();
match self {
- PlainDataElement::Actions(a) => {
- let bundle: DataElementBundle<F> = a.to_de_bundle();
- bundle.contents_as_slice().to_vec()
- }
- PlainDataElement::TxPower(t) => {
- let bundle: DataElementBundle<F> = t.to_de_bundle();
- bundle.contents_as_slice().to_vec()
+ DeserializedDataElement::Actions(a) => a.serialize_contents(&mut sink),
+ DeserializedDataElement::TxPower(t) => {
+ SerializeDataElement::<F>::serialize_contents(t, &mut sink)
}
}
+ .unwrap();
+ sink.into_inner().into_inner().as_slice().to_vec()
}
}
-/// The contents of a plaintext advertisement after deserializing DE contents
-#[derive(Debug, PartialEq, Eq)]
-pub struct PlaintextAdvContents<'d> {
- identity_type: PlaintextIdentityMode,
- /// Contents of the advertisement excluding the identity DE
- data: &'d [u8],
-}
-
-impl<'d> PlaintextAdvContents<'d> {
- /// Returns the identity type used for the advertisement
- pub fn identity(&self) -> PlaintextIdentityMode {
- self.identity_type
- }
-
- /// Returns an iterator over the v0 data elements
- pub fn data_elements(&self) -> PlainDeIterator<'d, Plaintext> {
- PlainDeIterator { data: self.data, _marker: PhantomData }
- }
-}
-
-/// Contents of an encrypted advertisement after decryption and deserializing DEs.
+/// Contents of an LDT advertisement after decryption.
#[derive(Debug, PartialEq, Eq)]
pub struct DecryptedAdvContents {
- identity_type: EncryptedIdentityDataElementType,
- metadata_key: ShortMetadataKey,
- salt: LegacySalt,
- /// The decrypted data in this advertisement. This should be a sequence of
- /// serialized data elements, excluding the identity DE.
- data: ArrayView<u8, { BLE_ADV_SVC_CONTENT_LEN }>,
+ identity_token: V0IdentityToken,
+ salt: V0Salt,
+ /// The decrypted data in this advertisement after the identity token.
+ /// This is hopefully a sequence of serialized data elements, but that hasn't been validated
+ /// yet at construction time.
+ data: ArrayView<u8, { NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN }>,
}
impl DecryptedAdvContents {
/// Returns a new DecryptedAdvContents with the provided contents.
fn new(
- identity_type: EncryptedIdentityDataElementType,
- metadata_key: ShortMetadataKey,
- salt: LegacySalt,
- data: ArrayView<u8, { BLE_ADV_SVC_CONTENT_LEN }>,
+ metadata_key: V0IdentityToken,
+ salt: V0Salt,
+ data: ArrayView<u8, { NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN }>,
) -> Self {
- Self { identity_type, metadata_key, salt, data }
- }
-
- /// The type of identity DE used in the advertisement.
- pub fn identity_type(&self) -> EncryptedIdentityDataElementType {
- self.identity_type
+ Self { identity_token: metadata_key, salt, data }
}
/// Iterator over the data elements in an advertisement, except for any DEs related to resolving
/// the identity or otherwise validating the payload (e.g. any identity DEs like Private
/// Identity).
- pub fn data_elements(&self) -> PlainDeIterator<Ciphertext> {
- PlainDeIterator { data: self.data.as_slice(), _marker: PhantomData }
+ pub fn data_elements(&self) -> DeIterator<Ciphertext> {
+ DeIterator::new(self.data.as_slice())
}
/// The salt used for decryption of this advertisement.
- pub fn salt(&self) -> LegacySalt {
+ pub fn salt(&self) -> V0Salt {
self.salt
}
+
+ #[cfg(test)]
+ pub(in crate::legacy) fn generic_data_elements<D: DataElementDeserializer>(
+ &self,
+ ) -> GenericDeIterator<Ciphertext, D> {
+ GenericDeIterator::new(self.data.as_slice())
+ }
}
impl HasIdentityMatch for DecryptedAdvContents {
type Version = V0;
- fn metadata_key(&self) -> ShortMetadataKey {
- self.metadata_key
+ fn identity_token(&self) -> V0IdentityToken {
+ self.identity_token
}
}
-/// The contents of an advertisement after plaintext DEs, if any, have been deserialized, but
-/// before any decryption is done.
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) enum IntermediateAdvContents<'d> {
- /// Plaintext advertisements
- Plaintext(PlaintextAdvContents<'d>),
- /// Ciphertext advertisements
- Ciphertext(EncryptedAdvContents<'d>),
+/// Overall strategy for deserializing adv contents (once decrypted, if applicable) into data
+/// elements
+pub(in crate::legacy) trait DataElementDeserializer: Sized {
+ /// Disambiguates the intermediate form of a DE
+ type DeTypeDisambiguator: Copy;
+ /// The fully deserialized form of a DE
+ type Deserialized<F: PacketFlavor>: fmt::Debug + PartialEq + Eq + Clone;
+
+ /// Map the encoded len found in a DE header to the actual len that should be consumed from the
+ /// advertisement payload
+ fn map_encoded_len_to_actual_len(
+ de_type: DeTypeCode,
+ encoded_len: DeEncodedLength,
+ ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError>;
+
+ /// Deserialize into a [Self::Deserialized] to expose DE-type-specific data representations.
+ ///
+ /// Returns `Err` if the contents of the raw DE can't be deserialized into the corresponding
+ /// DE's representation.
+ fn deserialize_de<F: PacketFlavor>(
+ raw_de: RawDataElement<Self>,
+ ) -> Result<Self::Deserialized<F>, DataElementDeserializeError>;
+}
+
+/// Possible errors when mapping DE encoded lengths to actual lengths
+pub(in crate::legacy) enum LengthError {
+ /// The DE type was known, but the encoded length was invalid
+ InvalidLength,
+ /// The DE type was not unrecognized
+ InvalidType,
+}
+
+impl From<DeLengthOutOfRange> for LengthError {
+ fn from(_value: DeLengthOutOfRange) -> Self {
+ Self::InvalidLength
+ }
+}
+
+/// The default deserialization strategy that maps type codes to [DataElementType], and deserializes
+/// to [DeserializedDataElement].
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct StandardDeserializer;
+
+impl DataElementDeserializer for StandardDeserializer {
+ type DeTypeDisambiguator = DataElementType;
+ type Deserialized<F: PacketFlavor> = DeserializedDataElement<F>;
+
+ fn map_encoded_len_to_actual_len(
+ de_type: DeTypeCode,
+ encoded_len: DeEncodedLength,
+ ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError> {
+ match de_type {
+ TxPowerDataElement::DE_TYPE_CODE => {
+ <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
+ .map_err(|e| e.into())
+ .map(|l| (DataElementType::TxPower, l))
+ }
+ ActionsDataElement::<Plaintext>::DE_TYPE_CODE => {
+ <ActionsDataElement<Plaintext> as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
+ .map_err(|e| e.into())
+ .map(|l| (DataElementType::Actions, l))
+ }
+ _ => Err(LengthError::InvalidType),
+ }
+ }
+
+ fn deserialize_de<F: PacketFlavor>(
+ raw_de: RawDataElement<Self>,
+ ) -> Result<Self::Deserialized<F>, DataElementDeserializeError> {
+ match raw_de.de_type {
+ DataElementType::Actions => {
+ actions::ActionsDataElement::deserialize::<F>(raw_de.contents)
+ .map(DeserializedDataElement::Actions)
+ }
+ DataElementType::TxPower => TxPowerDataElement::deserialize::<F>(raw_de.contents)
+ .map(DeserializedDataElement::TxPower),
+ }
+ }
}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/tests.rs b/nearby/presence/np_adv/src/legacy/deserialize/tests.rs
deleted file mode 100644
index 3dfecd1..0000000
--- a/nearby/presence/np_adv/src/legacy/deserialize/tests.rs
+++ /dev/null
@@ -1,818 +0,0 @@
-// 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.
-
-#![allow(unused_results, clippy::unwrap_used)]
-
-extern crate alloc;
-extern crate std;
-
-use super::*;
-use crate::{
- credential::{v0::V0, SimpleBroadcastCryptoMaterial},
- de_type::IdentityDataElementType,
- legacy::{
- actions::{self, ActionBits, ActionsDataElement, Finder, NearbyShare},
- de_type::DeActualLength,
- random_data_elements::{random_de_ciphertext, random_de_plaintext},
- serialize::{
- encode_de_header_actual_len, id_de_type_as_generic_de_type, AdvBuilder,
- DataElementBundle, Identity, LdtIdentity, ToDataElementBundle,
- },
- PacketFlavorEnum, BLE_ADV_SVC_CONTENT_LEN,
- },
- parse_adv_header, shared_data,
- shared_data::TxPower,
- AdvHeader, PublicIdentity,
-};
-use alloc::vec::Vec;
-use array_view::ArrayView;
-use crypto_provider_default::CryptoProviderImpl;
-use ldt_np_adv::LdtEncrypterXtsAes128;
-use nom::error::{self, ErrorKind};
-use rand_ext::rand::{prelude::SliceRandom, Rng as _};
-use std::vec;
-use strum::IntoEnumIterator as _;
-
-#[test]
-fn parse_empty_raw_adv() {
- let adv_data = parse_raw_adv_contents::<CryptoProviderImpl>(&[]);
- assert_eq!(AdvDeserializeError::MissingIdentity, adv_data.unwrap_err());
-}
-
-#[test]
-fn parse_raw_adv_1_de_long_private_identity() {
- // 3 bytes of payload after metadata key
- let adv = parse_raw_adv_contents::<CryptoProviderImpl>(&[
- 0x31, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
- 0x0F, 0x10, 0x11, 0x12, 0x13,
- ])
- .unwrap();
- assert_eq!(
- RawAdvertisement::Ciphertext(EncryptedAdvContents {
- identity_type: EncryptedIdentityDataElementType::Private,
- salt_padder: ldt_np_adv::salt_padder::<16, CryptoProviderImpl>(
- ldt_np_adv::LegacySalt::from([0x01, 0x02])
- ),
- salt: ldt_np_adv::LegacySalt::from([0x01, 0x02]),
- ciphertext: &[
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
- 0x11, 0x12, 0x13
- ]
- }),
- adv
- );
-}
-
-#[test]
-fn parse_raw_adv_3_de_public_identity() {
- let adv = parse_raw_adv_contents::<CryptoProviderImpl>(&[
- 0x03, // public identity
- 0x15, 0x05, // tx power 5
- 0x26, 0x00, 0x44, // actions
- ])
- .unwrap();
- match adv {
- RawAdvertisement::Plaintext(plaintext) => {
- assert_eq!(PlaintextIdentityMode::Public, plaintext.identity_type);
- let mut action_bits = ActionBits::default();
- action_bits.set_action(NearbyShare::from(true));
- action_bits.set_action(Finder::from(true));
- assert_eq!(
- vec![
- PlainDataElement::<Plaintext>::TxPower(TxPowerDataElement::from(
- TxPower::try_from(5).unwrap()
- )),
- PlainDataElement::Actions(ActionsDataElement::from(action_bits)),
- ],
- plaintext.data_elements().collect::<Result<Vec<_>, _>>().unwrap(),
- );
- }
- RawAdvertisement::Ciphertext(_) => panic!("adv should be plaintext"),
- }
-}
-
-#[test]
-fn parse_raw_adv_0_de_public_identity() {
- let adv = parse_raw_adv_contents::<CryptoProviderImpl>(&[
- 0x03, // public identity
- ])
- .unwrap();
- match adv {
- RawAdvertisement::Plaintext(plaintext) => {
- assert_eq!(PlaintextIdentityMode::Public, plaintext.identity_type);
- assert_eq!(
- Vec::<PlainDataElement<Plaintext>>::new(),
- plaintext.data_elements().collect::<Result<Vec<_>, _>>().unwrap()
- );
- }
- RawAdvertisement::Ciphertext(_) => panic!("adv should be plaintext"),
- }
-}
-
-#[test]
-fn parse_raw_adv_1_de_length_overrun() {
- // battery uses the header length as is
- let input = &[0xFB, 0x01, 0x02, 0x03];
- assert_eq!(
- nom::Err::Error(DataElementDeserializeError::NomError(ErrorKind::MapOpt)),
- parse_de(input).unwrap_err(),
- );
-}
-
-#[test]
-fn parse_raw_adv_public_identity_containing_public_identity() {
- let input = &[
- 0x03, // public identity
- 0x03, // another public identity
- 0x15, 0x03, // tx power de
- ];
- match parse_raw_adv_contents::<CryptoProviderImpl>(input).unwrap() {
- RawAdvertisement::Plaintext(content) => {
- assert_eq!(
- DataElementDeserializeError::DuplicateIdentityDataElement,
- content.data_elements().collect::<Result<Vec<_>, _>>().unwrap_err(),
- );
- }
- RawAdvertisement::Ciphertext(_) => panic!("Adv should be plaintext"),
- }
-}
-
-#[test]
-fn parse_raw_adv_no_identity_containing_public_identity() {
- let input = &[
- 0x15, 0x03, // tx power de
- 0x03, // public identity -- since it's not the first, this is a no identity adv
- 0x15, 0x03, // tx power de
- ];
- assert_eq!(
- AdvDeserializeError::MissingIdentity,
- parse_raw_adv_contents::<CryptoProviderImpl>(input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_raw_adv_1_de_long_private_identity_with_another_top_level_de() {
- let input = &[
- 0x31, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
- 0x0F, 0x10, 0x11, 0x12, 0x13, // private identity
- 0x15, 0x03, // tx power de
- ];
- assert_eq!(
- AdvDeserializeError::TooManyTopLevelDataElements,
- parse_raw_adv_contents::<CryptoProviderImpl>(input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_raw_adv_private_identity_ciphertext_min_length() {
- let short_input = &[
- // private identity w/ salt, len = 1
- 0x11, 0x10, 0x11, // 15 ciphertext bytes, + 2 salt = 17 total
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
- ];
- assert_eq!(
- AdvDeserializeError::AdvertisementDeserializeError,
- parse_raw_adv_contents::<CryptoProviderImpl>(short_input).unwrap_err()
- );
-
- let ok_input = &[
- // private identity w/ salt
- 0x21, 0x10, 0x11, // 16 ciphertext bytes, 18 bytes total de len, encoded len 2
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
- 0x2F,
- ];
- assert_eq!(
- RawAdvertisement::Ciphertext(EncryptedAdvContents {
- identity_type: EncryptedIdentityDataElementType::Private,
- salt: [0x10, 0x11].into(),
- salt_padder: ldt_np_adv::salt_padder::<16, CryptoProviderImpl>([0x10, 0x11].into()),
- ciphertext: &ok_input[3..]
- }),
- parse_raw_adv_contents::<CryptoProviderImpl>(ok_input).unwrap()
- );
-}
-
-#[test]
-fn parse_raw_adv_private_identity_ciphertext_too_long() {
- let long_input = &[
- // private identity w/ salt, len = 7
- 0x71, 0x10, 0x11, // 21 ciphertext bytes, + 2 salt
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
- 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
- ];
- assert_eq!(
- AdvDeserializeError::AdvertisementDeserializeError,
- parse_raw_adv_contents::<CryptoProviderImpl>(long_input).unwrap_err()
- );
-
- // removing 1 byte makes it work
- let ok_input = &[
- // private identity w/ salt, len = 6
- 0x61, 0x10, 0x11, // 20 ciphertext bytes, + 2 salt
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
- 0x2F, 0x30, 0x31, 0x32, 0x33,
- ];
- assert_eq!(
- RawAdvertisement::Ciphertext(EncryptedAdvContents {
- identity_type: EncryptedIdentityDataElementType::Private,
- salt_padder: ldt_np_adv::salt_padder::<16, CryptoProviderImpl>([0x10, 0x11].into()),
- salt: [0x10, 0x11].into(),
- ciphertext: &ok_input[3..]
- }),
- parse_raw_adv_contents::<CryptoProviderImpl>(ok_input).unwrap()
- );
-}
-
-/// Test method body that creates an array, deserializes it into a DE, serializes it,
-/// and asserts that the same bytes are produced.
-///
-/// Evaluates to the deserialized DE.
-macro_rules! de_roundtrip_test {
- ($de_type:ty, $type_variant:ident, $de_variant:ident, $flavor:ty, $bytes:expr) => {{
- let parsed_de_enum = parse_plain_de::<$flavor>(PlainDataElementType::$type_variant, $bytes);
- if let PlainDataElement::$de_variant(de) = parsed_de_enum {
- let expected = <$de_type>::deserialize::<$flavor>($bytes).unwrap();
- assert_eq!(expected, de);
-
- let de_bundle: DataElementBundle<$flavor> = de.to_de_bundle();
- assert_eq!($bytes, de_bundle.contents_as_slice());
-
- de
- } else {
- panic!("Unexpected variant: {:?}", parsed_de_enum);
- }
- }};
-}
-
-#[test]
-fn actions_de_contents_roundtrip_plaintext() {
- let actions = actions::tests::all_plaintext_actions();
- let bundle = actions::ActionsDataElement::from(actions).to_de_bundle();
-
- de_roundtrip_test!(
- actions::ActionsDataElement::<Plaintext>,
- Actions,
- Actions,
- Plaintext,
- bundle.contents_as_slice()
- );
-}
-
-#[test]
-fn actions_de_contents_roundtrip_ciphertext() {
- let actions = actions::tests::all_ciphertext_actions();
- let bundle = actions::ActionsDataElement::from(actions).to_de_bundle();
-
- de_roundtrip_test!(
- actions::ActionsDataElement::<Ciphertext>,
- Actions,
- Actions,
- Ciphertext,
- bundle.contents_as_slice()
- );
-}
-
-#[test]
-fn tx_power_de_contents_roundtrip_plaintext() {
- let tx = shared_data::TxPower::try_from(-10).unwrap();
- let bundle: DataElementBundle<Plaintext> = TxPowerDataElement::from(tx).to_de_bundle();
-
- de_roundtrip_test!(TxPowerDataElement, TxPower, TxPower, Plaintext, bundle.contents_as_slice());
-}
-
-#[test]
-fn tx_power_de_contents_roundtrip_ciphertext() {
- let tx = shared_data::TxPower::try_from(-10).unwrap();
- let bundle: DataElementBundle<Ciphertext> = TxPowerDataElement::from(tx).to_de_bundle();
-
- de_roundtrip_test!(
- TxPowerDataElement,
- TxPower,
- TxPower,
- Ciphertext,
- bundle.contents_as_slice()
- );
-}
-
-#[test]
-fn parse_de_invalid_de_len_error() {
- let input = &[
- // bogus 6-byte battery de -- only allows length = 3
- 0x6B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- ];
-
- assert_eq!(
- nom::Err::Error(DataElementDeserializeError::NomError(ErrorKind::MapOpt)),
- parse_de(&input[..]).unwrap_err()
- );
-}
-
-#[test]
-fn raw_de_to_plain_de_matches_plain_des() {
- assert_eq!(
- PlainDataElement::TxPower(TxPowerDataElement::from(TxPower::try_from(1).unwrap())),
- PlainDeIterator::<Plaintext>::raw_de_to_plain_de(RawDataElement {
- de_type: DataElementType::TxPower,
- contents: &[0x01]
- })
- .unwrap(),
- );
- assert_eq!(
- PlainDataElement::Actions(ActionsDataElement::from(
- ActionBits::try_from(0x00400000).unwrap()
- )),
- PlainDeIterator::<Plaintext>::raw_de_to_plain_de(RawDataElement {
- de_type: DataElementType::Actions,
- contents: &[0x00, 0x40]
- })
- .unwrap(),
- );
-}
-
-#[test]
-fn raw_de_to_plain_de_rejects_identity_de_error() {
- for idet in IdentityDataElementType::iter() {
- assert_eq!(
- DataElementDeserializeError::DuplicateIdentityDataElement,
- PlainDeIterator::<Plaintext>::raw_de_to_plain_de(RawDataElement {
- de_type: id_de_type_as_generic_de_type(idet),
- contents: &[0x02],
- })
- .unwrap_err()
- );
- }
-}
-
-#[test]
-fn parse_encrypted_identity_contents_too_short_error() {
- // 2 byte salt + 15 byte ciphertext: 1 too short
- let mut input = [0u8; 17];
- for (pos, e) in input.iter_mut().enumerate() {
- *e = pos as u8
- }
- assert_eq!(
- nom::Err::Error(error::Error { input: &input[2..], code: error::ErrorKind::TakeWhileMN }),
- parse_encrypted_identity_de_contents(&input).unwrap_err()
- );
-}
-
-#[test]
-fn parse_encrypted_identity_contents_ok() {
- // 2 byte salt + minimum 16 byte ciphertext
- let mut input = [0u8; 18];
- for (pos, e) in input.iter_mut().enumerate() {
- *e = pos as u8
- }
- assert_eq!(
- ([].as_slice(), (ldt_np_adv::LegacySalt::from([0, 1]), &input[2..])),
- parse_encrypted_identity_de_contents(&input).unwrap()
- );
-}
-
-#[test]
-fn deserialize_adv_public_identity_empty_des() {
- let input = &[
- 0x03, // public identity
- ];
- assert_eq!(
- AdvDeserializeError::NoPublicDataElements,
- deserialize_adv_contents::<CryptoProviderImpl>(input).unwrap_err()
- );
-}
-
-#[test]
-fn plaintext_random_adv_contents_round_trip_public() {
- plaintext_random_adv_contents_round_trip(PublicIdentity::default, PlaintextIdentityMode::Public)
-}
-
-#[test]
-fn ciphertext_random_adv_contents_round_trip() {
- let mut rng = rand_ext::seeded_rng();
- let de_types: Vec<PlainDataElementType> = PlainDataElementType::iter()
- .filter(|t| t.supports_flavor(PacketFlavorEnum::Ciphertext))
- .collect();
- let identity_de_types: Vec<EncryptedIdentityDataElementType> =
- EncryptedIdentityDataElementType::iter().collect();
-
- for _ in 0..10_000 {
- let mut des = Vec::new();
-
- let identity_type = *identity_de_types.choose(&mut rng).unwrap();
- let key_seed: [u8; 32] = rng.gen();
- let salt: ldt_np_adv::LegacySalt = rng.gen::<[u8; 2]>().into();
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = rng.gen();
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key);
- let cipher = ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac);
-
- let metadata_key = ShortMetadataKey(metadata_key);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
-
- let mut builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- identity_type,
- salt,
- &broadcast_cm,
- ));
-
- loop {
- let de_type = *de_types.choose(&mut rng).unwrap();
- let (de, bundle) = random_de_ciphertext(de_type, &mut rng).unwrap();
-
- if builder.add_data_element(bundle.clone()).ok().is_none() {
- // out of room
- if des.is_empty() {
- // need at least one, so try again
- continue;
- } else {
- // there's at least one so proceed to serialization
- break;
- }
- }
-
- des.push(de);
- }
-
- let serialized = builder.into_advertisement().unwrap();
- let (remaining, header) = parse_adv_header(serialized.as_slice()).unwrap();
- let parsed_adv = deserialize_adv_contents::<CryptoProviderImpl>(remaining).unwrap();
-
- assert_eq!(AdvHeader::V0, header);
- if let IntermediateAdvContents::Ciphertext(eac) = parsed_adv {
- assert_eq!(
- EncryptedAdvContents {
- identity_type,
- salt_padder: ldt_np_adv::salt_padder::<16, CryptoProviderImpl>(salt),
- salt,
- // skip adv header, de header, salt
- ciphertext: &serialized.as_slice()[4..]
- },
- eac
- );
-
- let contents = eac.try_decrypt(&cipher).unwrap();
- assert_eq!(identity_type, contents.identity_type);
- assert_eq!(metadata_key, contents.metadata_key);
- assert_eq!(salt, contents.salt);
- assert_eq!(des, contents.data_elements().collect::<Result<Vec<_>, _>>().unwrap());
- } else {
- panic!("Unexpected variant: {:?}", parsed_adv);
- }
- }
-}
-
-#[test]
-fn decrypt_and_deserialize_ciphertext_adv_canned() {
- let key_seed = [0x11_u8; 32];
- let salt: ldt_np_adv::LegacySalt = [0x22; 2].into();
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
-
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key);
- let cipher = ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac);
-
- let metadata_key = ShortMetadataKey(metadata_key);
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
-
- let mut builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- EncryptedIdentityDataElementType::Private,
- salt,
- &broadcast_cm,
- ));
-
- let tx = shared_data::TxPower::try_from(3).unwrap();
- builder.add_data_element(TxPowerDataElement::from(tx)).unwrap();
-
- let serialized = builder.into_advertisement().unwrap();
-
- assert_eq!(
- &[
- 0x0, // adv header
- 0x21, // private DE
- 0x22, 0x22, // salt
- // ciphertext
- 0x85, 0xBF, 0xA8, 0x83, 0x58, 0x7C, 0x50, 0xCF, 0x98, 0x38, 0xA7, 0x8A, 0xC0, 0x1C,
- 0x96, 0xF9
- ],
- serialized.as_slice()
- );
-
- let (remaining, header) = parse_adv_header(serialized.as_slice()).unwrap();
- assert_eq!(AdvHeader::V0, header);
-
- let parsed_adv = deserialize_adv_contents::<CryptoProviderImpl>(remaining).unwrap();
- if let IntermediateAdvContents::Ciphertext(eac) = parsed_adv {
- assert_eq!(
- EncryptedAdvContents {
- identity_type: EncryptedIdentityDataElementType::Private,
- salt_padder: ldt_np_adv::salt_padder::<16, CryptoProviderImpl>(salt),
- salt,
- // skip adv header, de header, salt
- ciphertext: &serialized.as_slice()[4..]
- },
- eac
- );
-
- let decrypted = eac.try_decrypt(&cipher).unwrap();
- assert_eq!(EncryptedIdentityDataElementType::Private, decrypted.identity_type);
- assert_eq!(metadata_key, decrypted.metadata_key);
- assert_eq!(salt, decrypted.salt);
- assert_eq!(
- vec![PlainDataElement::TxPower(TxPowerDataElement::from(
- TxPower::try_from(3).unwrap()
- ))],
- decrypted.data_elements().collect::<Result<Vec<_>, _>>().unwrap()
- );
- } else {
- panic!("Unexpected variant: {:?}", parsed_adv);
- }
-}
-
-#[test]
-fn decrypt_and_deserialize_plaintext_adv_canned() {
- let mut builder = AdvBuilder::new(PublicIdentity);
-
- let actions = ActionBits::default();
- builder.add_data_element(ActionsDataElement::from(actions)).unwrap();
-
- let serialized = builder.into_advertisement().unwrap();
-
- assert_eq!(
- &[
- 0x0, // adv header
- 0x03, // public DE
- 0x16, 0x00 // actions
- ],
- serialized.as_slice()
- );
-
- let (remaining, header) = parse_adv_header(serialized.as_slice()).unwrap();
- assert_eq!(AdvHeader::V0, header);
-
- let parsed_adv = deserialize_adv_contents::<CryptoProviderImpl>(remaining).unwrap();
- if let IntermediateAdvContents::Plaintext(adv_contents) = parsed_adv {
- assert_eq!(PlaintextIdentityMode::Public, adv_contents.identity());
- assert_eq!(
- vec![PlainDataElement::<Plaintext>::Actions(ActionsDataElement::from(
- ActionBits::default()
- ))],
- adv_contents.data_elements().collect::<Result<Vec<_>, _>>().unwrap()
- );
- } else {
- panic!("Unexpected variant: {:?}", parsed_adv);
- }
-}
-
-#[test]
-fn decrypt_with_wrong_key_seed_error() {
- let salt = ldt_np_adv::LegacySalt::from([0x22; 2]);
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
- let correct_key_seed = [0x11_u8; 32];
-
- let (adv_content, correct_cipher) =
- build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
- let eac = parse_ciphertext_adv_contents(&correct_cipher, &adv_content.as_slice()[1..]);
-
- // wrong key seed doesn't work (derives wrong ldt key, wrong hmac key)
- let wrong_key_seed_cipher = {
- let key_seed = [0x22_u8; 32];
-
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key);
- ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac)
- };
-
- assert_eq!(
- DecryptError::DecryptOrVerifyError,
- eac.try_decrypt(&wrong_key_seed_cipher,).unwrap_err()
- );
-}
-
-#[test]
-fn decrypt_with_wrong_hmac_key_error() {
- let salt = ldt_np_adv::LegacySalt::from([0x22; 2]);
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
- let correct_key_seed = [0x11_u8; 32];
-
- let (adv_content, correct_cipher_config) =
- build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
- let eac = parse_ciphertext_adv_contents(&correct_cipher_config, &adv_content.as_slice()[1..]);
-
- let wrong_hmac_key_cipher = {
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&[0x10_u8; 32]);
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key);
-
- ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac)
- };
-
- assert_eq!(
- DecryptError::DecryptOrVerifyError,
- eac.try_decrypt::<CryptoProviderImpl>(&wrong_hmac_key_cipher,).unwrap_err()
- );
-}
-
-#[test]
-fn decrypt_with_wrong_hmac_error() {
- let salt = ldt_np_adv::LegacySalt::from([0x22; 2]);
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
- let correct_key_seed = [0x11_u8; 32];
-
- let (adv_content, correct_cipher_config) =
- build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
- let eac = parse_ciphertext_adv_contents(&correct_cipher_config, &adv_content.as_slice()[1..]);
-
- let wrong_hmac_key_cipher = {
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&correct_key_seed);
-
- ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, [0x77; 32])
- };
-
- assert_eq!(
- DecryptError::DecryptOrVerifyError,
- eac.try_decrypt(&wrong_hmac_key_cipher,).unwrap_err()
- );
-}
-
-#[test]
-fn decrypt_and_deserialize_ciphertext_with_public_adv_inside_error() {
- let key_seed = [0x11_u8; 32];
- let salt: ldt_np_adv::LegacySalt = [0x22; 2].into();
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
-
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let ldt_key = hkdf.legacy_ldt_key();
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key);
- let cipher = ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac);
-
- let mut plaintext = vec![];
- plaintext.extend_from_slice(&metadata_key);
-
- let txpower_de = TxPowerDataElement::from(TxPower::try_from(5).unwrap());
-
- plaintext.push(
- encode_de_header_actual_len(DataElementType::TxPower, 1u8.try_into().unwrap()).unwrap(),
- );
-
- let plaintext_de_bundle: DataElementBundle<Plaintext> = txpower_de.to_de_bundle();
- plaintext.extend_from_slice(plaintext_de_bundle.contents_as_slice());
- // forge an otherwise impossible to express public identity
- plaintext.push(
- encode_de_header_actual_len(DataElementType::PublicIdentity, DeActualLength::ZERO).unwrap(),
- );
-
- assert_eq!(17, plaintext.len());
-
- let ldt = LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&ldt_key);
- ldt.encrypt(&mut plaintext, &ldt_np_adv::salt_padder::<16, CryptoProviderImpl>(salt)).unwrap();
- let ciphertext = plaintext;
-
- let mut adv = vec![];
- adv.push(0x00); // adv header
- adv.push(
- encode_de_header_actual_len(
- DataElementType::PrivateIdentity,
- (2 + ciphertext.len()).try_into().unwrap(),
- )
- .unwrap(),
- ); // private DE
- adv.extend_from_slice(&[0x22; 2]); // salt
- adv.extend_from_slice(&ciphertext);
-
- let parsed_adv = deserialize_adv_contents::<CryptoProviderImpl>(&adv[1..]).unwrap();
- if let IntermediateAdvContents::Ciphertext(eac) = parsed_adv {
- assert_eq!(
- DataElementDeserializeError::DuplicateIdentityDataElement,
- eac.try_decrypt(&cipher)
- .unwrap()
- .data_elements()
- .collect::<Result<Vec<_>, _>>()
- .unwrap_err()
- )
- } else {
- panic!("Unexpected variant: {:?}", parsed_adv);
- }
-}
-
-fn build_ciphertext_adv_contents<C: CryptoProvider>(
- salt: ldt_np_adv::LegacySalt,
- metadata_key: &[u8; 14],
- correct_key_seed: [u8; 32],
-) -> (ArrayView<u8, { BLE_ADV_SVC_CONTENT_LEN }>, ldt_np_adv::LdtNpAdvDecrypterXtsAes128<C>) {
- let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&correct_key_seed);
-
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(metadata_key.as_slice());
-
- let correct_cipher = ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac);
-
- let broadcast_cm =
- SimpleBroadcastCryptoMaterial::<V0>::new(correct_key_seed, ShortMetadataKey(*metadata_key));
-
- let mut builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- EncryptedIdentityDataElementType::Private,
- salt,
- &broadcast_cm,
- ));
- builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
- (builder.into_advertisement().unwrap(), correct_cipher)
-}
-
-fn parse_ciphertext_adv_contents<'b>(
- cipher: &ldt_np_adv::LdtNpAdvDecrypterXtsAes128<CryptoProviderImpl>,
- adv_content: &'b [u8],
-) -> EncryptedAdvContents<'b> {
- let eac = match deserialize_adv_contents::<CryptoProviderImpl>(adv_content).unwrap() {
- IntermediateAdvContents::Plaintext(_) => panic!(),
- // quick confirmation that we did get something
- IntermediateAdvContents::Ciphertext(eac) => eac,
- };
-
- // correct cipher works
- assert!(eac.try_decrypt(cipher).is_ok());
-
- eac
-}
-
-/// Construct the serialized DE and parse it
-fn parse_plain_de<F>(de_type: PlainDataElementType, contents: &[u8]) -> PlainDataElement<F>
-where
- F: PacketFlavor,
- actions::ActionsDataElement<F>: DataElement,
-{
- let mut buf = vec![];
- buf.push(
- encode_de_header_actual_len(
- de_type.as_generic_de_type(),
- contents.len().try_into().unwrap(),
- )
- .unwrap(),
- );
- buf.extend_from_slice(contents);
-
- let mut plain_des = PlainDeIterator { data: &buf, _marker: PhantomData }
- .collect::<Result<Vec<_>, _>>()
- .unwrap();
- assert_eq!(1, plain_des.len());
- plain_des.swap_remove(0)
-}
-
-fn plaintext_random_adv_contents_round_trip<I: Identity<Flavor = Plaintext>, F: Fn() -> I>(
- mk_identity: F,
- identity_type: PlaintextIdentityMode,
-) {
- let mut rng = rand_ext::seeded_rng();
- let de_types: Vec<PlainDataElementType> = PlainDataElementType::iter()
- .filter(|t| t.supports_flavor(PacketFlavorEnum::Plaintext))
- .collect();
-
- for _ in 0..10_000 {
- let mut de_tuples = Vec::new();
- let mut builder = AdvBuilder::new(mk_identity());
-
- loop {
- let de_type = *de_types.choose(&mut rng).unwrap();
- let (de, bundle) = random_de_plaintext(de_type, &mut rng).unwrap();
-
- if builder.add_data_element(bundle.clone()).ok().is_none() {
- // out of room
- break;
- }
-
- de_tuples.push((de, de_type, bundle));
- }
-
- let serialized = builder.into_advertisement().unwrap();
-
- let (_rem, header) =
- combinator::all_consuming(parse_adv_header)(&serialized.as_slice()[..1]).unwrap();
- let parsed_adv =
- parse_raw_adv_contents::<CryptoProviderImpl>(&serialized.as_slice()[1..]).unwrap();
-
- assert_eq!(AdvHeader::V0, header);
- if let RawAdvertisement::Plaintext(adv_contents) = parsed_adv {
- assert_eq!(identity_type, adv_contents.identity_type);
- assert_eq!(
- de_tuples.into_iter().map(|(de, _de_type, _bundle)| de).collect::<Vec<_>>(),
- adv_contents.data_elements().collect::<Result<Vec<_>, _>>().unwrap(),
- );
- } else {
- panic!("Unexpected variant: {:?}", parsed_adv);
- }
- }
-}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/tests/error_conditions.rs b/nearby/presence/np_adv/src/legacy/deserialize/tests/error_conditions.rs
new file mode 100644
index 0000000..8230548
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/tests/error_conditions.rs
@@ -0,0 +1,321 @@
+// 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.
+
+mod unencrypted {
+ use crypto_provider_default::CryptoProviderImpl;
+
+ use crate::header::V0Encoding;
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement, ActiveUnlock};
+ use crate::legacy::data_elements::de_type::{DeEncodedLength, DeTypeCode};
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::data_elements::{DataElementDeserializeError, DeserializeDataElement};
+ use crate::legacy::deserialize::intermediate::IntermediateAdvContents;
+ use crate::legacy::serialize::tests::serialize;
+ use crate::legacy::{Ciphertext, PacketFlavorEnum, Plaintext};
+
+ #[test]
+ fn iterate_tx_power_invalid_de_len_error() {
+ assert_deser_error(
+ // bogus 6-byte tx power de -- only allows length = 1
+ &[0x65, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06],
+ DataElementDeserializeError::InvalidDeLength {
+ de_type: TxPowerDataElement::DE_TYPE_CODE,
+ len: DeEncodedLength::from(6),
+ },
+ );
+ }
+
+ #[test]
+ fn iterate_tx_power_invalid_power_error() {
+ assert_deser_error(
+ // power too high
+ &[0x15, 0x7F],
+ DataElementDeserializeError::DeserializeError {
+ de_type: TxPowerDataElement::DE_TYPE_CODE,
+ },
+ );
+ }
+
+ #[test]
+ fn iterate_actions_invalid_de_len_error() {
+ assert_deser_error(
+ // bogus 0-byte actions de
+ &[0x06],
+ DataElementDeserializeError::InvalidDeLength {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ len: DeEncodedLength::from(0),
+ },
+ );
+ }
+
+ #[test]
+ fn iterate_actions_ciphertext_only_bit_error() {
+ let mut bits = ActionBits::default();
+ bits.set_action(ActiveUnlock::from(true));
+ assert_deser_error(
+ serialize(&ActionsDataElement::<Ciphertext>::from(bits)).as_slice(),
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Plaintext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Plaintext,
+ },
+ );
+ }
+
+ #[test]
+ fn iterate_invalid_de_type_error() {
+ assert_deser_error(
+ &[0x0F],
+ DataElementDeserializeError::InvalidDeType {
+ de_type: DeTypeCode::try_from(0x0F).unwrap(),
+ },
+ );
+ }
+
+ #[test]
+ fn iterate_truncated_contents_error() {
+ assert_deser_error(
+ // length 3, but only 2 bytes provided
+ &[0x36, 0x01, 0x02],
+ DataElementDeserializeError::InvalidStructure,
+ );
+ }
+
+ fn assert_deser_error(input: &[u8], err: DataElementDeserializeError) {
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ input,
+ )
+ .unwrap();
+
+ assert_eq!(
+ err,
+ contents.as_unencrypted().unwrap().data_elements().next().unwrap().unwrap_err()
+ );
+ }
+}
+
+mod ldt {
+
+ // see unencrypted tests above for basic things that are the same between unencrypted and ldt,
+ // like how an invalid de type is handled
+
+ use crate::credential::matched::HasIdentityMatch;
+ use crate::credential::v0::V0BroadcastCredential;
+ use crate::header::V0Encoding;
+ use crate::legacy::data_elements::actions::tests::PlaintextOnly;
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement};
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::data_elements::{DataElementDeserializeError, DeserializeDataElement};
+ use crate::legacy::deserialize::intermediate::IntermediateAdvContents;
+ use crate::legacy::deserialize::DecryptError;
+ use crate::legacy::serialize::{AdvBuilder, LdtEncoder};
+ use crate::legacy::{Ciphertext, PacketFlavorEnum};
+ use crate::shared_data::TxPower;
+ use alloc::vec::Vec;
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt_np_adv::{
+ build_np_adv_decrypter, AuthenticatedNpLdtDecryptCipher, V0IdentityToken, V0Salt,
+ V0_IDENTITY_TOKEN_LEN,
+ };
+
+ #[test]
+ fn iterate_actions_invalid_flavor_error() {
+ let mut bits = ActionBits::default();
+ bits.set_action(PlaintextOnly::from(true));
+
+ let key_seed = [0; 32];
+ let identity_token = V0IdentityToken::from([0x33; V0_IDENTITY_TOKEN_LEN]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ builder.add_data_element(ActionsDataElement::from(bits)).unwrap();
+
+ let adv = builder.into_advertisement().unwrap();
+
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &adv.as_slice()[1..],
+ )
+ .unwrap();
+ let ldt = contents.as_ldt().unwrap();
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let identity_token_hmac: [u8; 32] = hkdf
+ .v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice());
+ let decrypter =
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, identity_token_hmac);
+ let decrypted = ldt.try_decrypt(&decrypter).unwrap();
+
+ assert_eq!(salt, decrypted.salt());
+ assert_eq!(identity_token, decrypted.identity_token());
+
+ assert_eq!(
+ DataElementDeserializeError::FlavorNotSupported {
+ de_type: ActionsDataElement::<Ciphertext>::DE_TYPE_CODE,
+ flavor: PacketFlavorEnum::Ciphertext,
+ },
+ decrypted.data_elements().next().unwrap().unwrap_err()
+ )
+ }
+
+ #[test]
+ fn decrypter_wrong_identity_token_hmac_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |adv| adv,
+ |key_seed, _identity_token| {
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(
+ &np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed),
+ [0xFA; 32],
+ )
+ },
+ )
+ }
+
+ #[test]
+ fn decrypter_wrong_key_seed_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |adv| adv,
+ |key_seed, identity_token| {
+ let correct_hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed);
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(
+ // wrong key seed
+ &np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&[0xFA; 32]),
+ correct_hkdf
+ .v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice()),
+ )
+ },
+ )
+ }
+
+ #[test]
+ fn decrypter_wrong_ldt_key_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |adv| adv,
+ |key_seed, identity_token| {
+ let hkdf = &np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed);
+ let bogus_key = ldt::LdtKey::from_concatenated(&[0xFA; 64]);
+ build_np_adv_decrypter(
+ &bogus_key,
+ hkdf.v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice()),
+ hkdf.v0_identity_token_hmac_key(),
+ )
+ },
+ )
+ }
+
+ #[test]
+ fn decrypter_wrong_identity_token_hmac_key_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |adv| adv,
+ |key_seed, identity_token| {
+ let hkdf = &np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed);
+ build_np_adv_decrypter(
+ &hkdf.v0_ldt_key(),
+ hkdf.v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice()),
+ [0xFA; 32].into(),
+ )
+ },
+ )
+ }
+
+ #[test]
+ fn mangled_de_ciphertext_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |mut adv| {
+ *adv.last_mut().unwrap() ^= 0x01;
+ adv
+ },
+ build_correct_decrypter,
+ )
+ }
+
+ #[test]
+ fn mangled_token_ciphertext_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |mut adv| {
+ adv[10] ^= 0x01;
+ adv
+ },
+ build_correct_decrypter,
+ )
+ }
+
+ #[test]
+ fn mangled_salt_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |mut adv| {
+ adv[1] ^= 0x01;
+ adv
+ },
+ build_correct_decrypter,
+ )
+ }
+
+ #[test]
+ fn extended_ciphertext_no_match() {
+ build_and_deser_with_invalid_decrypter_error(
+ |mut adv| {
+ adv.push(0xEE);
+ adv
+ },
+ build_correct_decrypter,
+ )
+ }
+
+ fn build_correct_decrypter(
+ key_seed: &[u8; 32],
+ identity_token: &V0IdentityToken,
+ ) -> AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl> {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed);
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(
+ &hkdf,
+ hkdf.v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice()),
+ )
+ }
+
+ fn build_and_deser_with_invalid_decrypter_error(
+ alter_adv: impl Fn(Vec<u8>) -> Vec<u8>,
+ build_decrypter: impl Fn(
+ &[u8; 32],
+ &V0IdentityToken,
+ ) -> AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl>,
+ ) {
+ let key_seed = [0; 32];
+ let identity_token = V0IdentityToken::from([0x33; V0_IDENTITY_TOKEN_LEN]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(7).unwrap())).unwrap();
+
+ let adv = builder.into_advertisement().unwrap();
+ let altered_adv = alter_adv(adv.as_slice().to_vec());
+
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &altered_adv.as_slice()[1..],
+ )
+ .unwrap();
+ let ldt = contents.as_ldt().unwrap();
+ let decrypter = build_decrypter(&key_seed, &identity_token);
+ assert_eq!(DecryptError::DecryptOrVerifyError, ldt.try_decrypt(&decrypter).unwrap_err());
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/tests/happy_path.rs b/nearby/presence/np_adv/src/legacy/deserialize/tests/happy_path.rs
new file mode 100644
index 0000000..1b07ff9
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/tests/happy_path.rs
@@ -0,0 +1,587 @@
+// 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.
+
+mod unencrypted {
+ extern crate std;
+
+ use rand::prelude::SliceRandom;
+ use std::{prelude::rust_2021::*, vec};
+ use strum::IntoEnumIterator;
+
+ use crypto_provider_default::CryptoProviderImpl;
+
+ use crate::{
+ header::V0Encoding,
+ legacy::{
+ data_elements::{
+ actions::{ActionBits, ActionsDataElement, NearbyShare},
+ de_type::DataElementType,
+ tests::test_des::{
+ random_test_de, TestDataElement, TestDataElementType, TestDeDeserializer,
+ },
+ tx_power::TxPowerDataElement,
+ DynamicSerializeDataElement, SerializeDataElement,
+ },
+ deserialize::{
+ intermediate::IntermediateAdvContents, DataElementDeserializer,
+ DeserializedDataElement, StandardDeserializer,
+ },
+ random_data_elements::random_de_plaintext,
+ serialize::{
+ tests::helpers::{LongDataElement, ShortDataElement},
+ tests::supports_flavor,
+ AddDataElementError, AdvBuilder, SerializedAdv, UnencryptedEncoder,
+ },
+ PacketFlavorEnum, Plaintext, BLE_4_ADV_SVC_MAX_CONTENT_LEN, NP_MAX_DE_CONTENT_LEN,
+ NP_MIN_ADV_CONTENT_LEN,
+ },
+ shared_data::TxPower,
+ };
+
+ #[test]
+ fn parse_min_len_adv() {
+ // 1 byte
+ let de = ShortDataElement::new(vec![]);
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+ builder.add_data_element(de.clone()).unwrap();
+ let data = builder.into_advertisement().unwrap();
+ // extra byte for version header
+ assert_eq!(1 + NP_MIN_ADV_CONTENT_LEN, data.len());
+
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &data.as_slice()[1..],
+ )
+ .unwrap();
+ let unencrypted = contents.as_unencrypted().unwrap();
+
+ assert_eq!(
+ vec![TestDataElement::Short(de)],
+ unencrypted
+ .generic_data_elements::<TestDeDeserializer>()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap()
+ );
+ }
+
+ #[test]
+ fn parse_max_len_adv() {
+ let de = LongDataElement::new(vec![0x22; NP_MAX_DE_CONTENT_LEN]);
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+ builder.add_data_element(de.clone()).unwrap();
+ let data = builder.into_advertisement().unwrap();
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, data.len());
+
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &data.as_slice()[1..],
+ )
+ .unwrap();
+ let unencrypted = contents.as_unencrypted().unwrap();
+
+ assert_eq!(
+ vec![TestDataElement::Long(de)],
+ unencrypted
+ .generic_data_elements::<TestDeDeserializer>()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap()
+ );
+ }
+
+ #[test]
+ fn tx_power() {
+ let de = TxPowerDataElement::from(TxPower::try_from(7).unwrap());
+ let boxed: Box<dyn SerializeDataElement<Plaintext>> = Box::new(de.clone());
+ let _ = assert_build_adv_and_deser(
+ vec![boxed.as_ref().into()],
+ &[DeserializedDataElement::TxPower(de)],
+ );
+ }
+
+ #[test]
+ fn actions_min_len() {
+ let de = ActionsDataElement::from(ActionBits::default());
+
+ let boxed: Box<dyn SerializeDataElement<Plaintext>> = Box::new(de.clone());
+ let data = assert_build_adv_and_deser(
+ vec![boxed.as_ref().into()],
+ &[DeserializedDataElement::Actions(de)],
+ );
+ // version, de header, de contents
+ assert_eq!(3, data.len());
+ }
+
+ #[test]
+ fn typical_tx_power_and_actions() {
+ let tx = TxPowerDataElement::from(TxPower::try_from(7).unwrap());
+ let mut action_bits = ActionBits::default();
+ action_bits.set_action(NearbyShare::from(true));
+ let actions = ActionsDataElement::from(action_bits);
+
+ let tx_boxed: Box<dyn SerializeDataElement<Plaintext>> = Box::new(tx.clone());
+ let actions_boxed: Box<dyn SerializeDataElement<Plaintext>> = Box::new(actions.clone());
+ let expected =
+ vec![DeserializedDataElement::TxPower(tx), DeserializedDataElement::Actions(actions)];
+ let adv = assert_build_adv_and_deser(
+ vec![tx_boxed.as_ref().into(), actions_boxed.as_ref().into()],
+ &expected,
+ );
+
+ let contents = assert_deserialized_contents::<StandardDeserializer>(&expected, &adv);
+ assert_eq!(
+ expected,
+ contents
+ .as_unencrypted()
+ .unwrap()
+ .data_elements()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap()
+ );
+ }
+
+ #[test]
+ fn random_normal_des_rountrip() {
+ do_random_roundtrip_test::<StandardDeserializer, _>(
+ DataElementType::iter()
+ .filter(|t| supports_flavor(*t, PacketFlavorEnum::Plaintext))
+ .collect(),
+ random_de_plaintext,
+ |builder, de| match de {
+ DeserializedDataElement::Actions(a) => builder.add_data_element(a),
+ DeserializedDataElement::TxPower(tx) => builder.add_data_element(tx),
+ },
+ )
+ }
+
+ #[test]
+ fn random_test_des_rountrip() {
+ do_random_roundtrip_test::<TestDeDeserializer, _>(
+ TestDataElementType::iter().collect::<Vec<_>>(),
+ random_test_de,
+ |builder, de| match de {
+ TestDataElement::Short(s) => builder.add_data_element(s),
+ TestDataElement::Long(l) => builder.add_data_element(l),
+ },
+ )
+ }
+
+ fn do_random_roundtrip_test<D, F>(
+ de_types: Vec<D::DeTypeDisambiguator>,
+ build_de: F,
+ add_de: impl Fn(
+ &mut AdvBuilder<UnencryptedEncoder>,
+ D::Deserialized<Plaintext>,
+ ) -> Result<(), AddDataElementError>,
+ ) where
+ D: DataElementDeserializer,
+ F: Fn(D::DeTypeDisambiguator, &mut rand_ext::rand_pcg::Pcg64) -> D::Deserialized<Plaintext>,
+ {
+ let mut rng = rand_ext::seeded_rng();
+
+ for _ in 0..10_000 {
+ let mut des = Vec::new();
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ loop {
+ let de_type = *de_types.choose(&mut rng).unwrap();
+ let de = build_de(de_type, &mut rng);
+
+ let add_res = add_de(&mut builder, de.clone());
+
+ if let Err(e) = add_res {
+ match e {
+ AddDataElementError::InsufficientAdvSpace => {
+ // out of room
+ break;
+ }
+ }
+ }
+
+ des.push(de);
+ }
+
+ let serialized = builder.into_advertisement().unwrap();
+ assert_deserialized_contents::<D>(&des, &serialized);
+ }
+ }
+
+ fn assert_build_adv_and_deser(
+ des: Vec<DynamicSerializeDataElement<Plaintext>>,
+ expected: &[DeserializedDataElement<Plaintext>],
+ ) -> SerializedAdv {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+ for de in des {
+ builder.add_data_element(de).unwrap();
+ }
+ let adv = builder.into_advertisement().unwrap();
+
+ assert_deserialized_contents::<StandardDeserializer>(expected, &adv);
+
+ adv
+ }
+
+ fn assert_deserialized_contents<'a, D: DataElementDeserializer>(
+ expected: &[D::Deserialized<Plaintext>],
+ adv: &'a SerializedAdv,
+ ) -> IntermediateAdvContents<'a> {
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &adv.as_slice()[1..],
+ )
+ .unwrap();
+
+ let unencrypted = contents.as_unencrypted().unwrap();
+ assert_eq!(
+ expected,
+ unencrypted
+ .generic_data_elements::<D>()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap()
+ .as_slice()
+ );
+ contents
+ }
+}
+
+mod ldt {
+ use crate::credential::matched::HasIdentityMatch;
+ use crate::legacy::data_elements::actions::CallTransfer;
+ use crate::{
+ credential::v0::V0BroadcastCredential,
+ header::V0Encoding,
+ legacy::{
+ data_elements::{
+ actions::{ActionBits, ActionsDataElement, NearbyShare},
+ de_type::DataElementType,
+ tests::test_des::{random_test_de, TestDataElementType},
+ tests::test_des::{TestDataElement, TestDeDeserializer},
+ tx_power::TxPowerDataElement,
+ DataElementSerializationBuffer, DynamicSerializeDataElement, SerializeDataElement,
+ },
+ deserialize::{
+ intermediate::IntermediateAdvContents, DecryptedAdvContents,
+ DeserializedDataElement,
+ },
+ deserialize::{DataElementDeserializer, StandardDeserializer},
+ random_data_elements::random_de_ciphertext,
+ serialize::{
+ tests::helpers::ShortDataElement, tests::supports_flavor, AddDataElementError,
+ AdvBuilder, LdtEncoder, SerializedAdv,
+ },
+ Ciphertext, PacketFlavorEnum, BLE_4_ADV_SVC_MAX_CONTENT_LEN, NP_MAX_ADV_CONTENT_LEN,
+ },
+ shared_data::TxPower,
+ };
+ use alloc::boxed::Box;
+ use alloc::vec;
+ use alloc::vec::Vec;
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt_np_adv::{V0IdentityToken, V0Salt, V0_IDENTITY_TOKEN_LEN};
+ use rand::prelude::SliceRandom;
+ use rand::Rng;
+ use strum::IntoEnumIterator;
+
+ #[test]
+ fn parse_min_len() {
+ // 2 bytes total is the minimum
+ let de = ShortDataElement::new(vec![7]);
+ let boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(de.clone());
+ let (adv, _decrypted) = build_and_assert_deserialized_matches::<TestDeDeserializer>(
+ vec![boxed.as_ref().into()],
+ &[TestDataElement::Short(de)],
+ );
+
+ // version and salt
+ assert_eq!(1 + 2 + ldt_np_adv::VALID_INPUT_LEN.start, adv.len());
+ }
+
+ #[test]
+ fn parse_max_len() {
+ // 7 bytes total
+ let de = ShortDataElement::new(vec![1; 6]);
+ let boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(de.clone());
+ let (adv, _decrypted) = build_and_assert_deserialized_matches::<TestDeDeserializer>(
+ vec![boxed.as_ref().into()],
+ &[TestDataElement::Short(de)],
+ );
+
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, adv.len());
+ }
+
+ #[test]
+ fn tx_power() {
+ let de = TxPowerDataElement::from(TxPower::try_from(3).unwrap());
+ let boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(de.clone());
+ let _adv = build_and_assert_deserialized_matches::<StandardDeserializer>(
+ vec![boxed.as_ref().into()],
+ &[DeserializedDataElement::TxPower(de)],
+ );
+ }
+
+ #[test]
+ fn actions_min_len() {
+ let de = ActionsDataElement::from(ActionBits::default());
+ let boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(de.clone());
+ let (adv, _decrypted) = build_and_assert_deserialized_matches::<StandardDeserializer>(
+ vec![boxed.as_ref().into()],
+ &[DeserializedDataElement::Actions(de)],
+ );
+
+ // 2 byte actions DE
+ assert_eq!(1 + 2 + 14 + 2, adv.len());
+ }
+
+ #[test]
+ fn typical_tx_power_and_actions() {
+ let tx = TxPowerDataElement::from(TxPower::try_from(7).unwrap());
+ let mut action_bits = ActionBits::default();
+ action_bits.set_action(NearbyShare::from(true));
+ action_bits.set_action(CallTransfer::from(true));
+ let actions = ActionsDataElement::from(action_bits);
+ let tx_boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(tx.clone());
+ let actions_boxed: Box<dyn SerializeDataElement<Ciphertext>> = Box::new(actions.clone());
+ let expected =
+ [DeserializedDataElement::TxPower(tx), DeserializedDataElement::Actions(actions)];
+ let (_adv, decrypted) = build_and_assert_deserialized_matches::<StandardDeserializer>(
+ vec![tx_boxed.as_ref().into(), actions_boxed.as_ref().into()],
+ &expected,
+ );
+ assert_eq!(
+ &expected,
+ decrypted.data_elements().collect::<Result<Vec<_>, _>>().unwrap().as_slice()
+ );
+ }
+
+ #[test]
+ fn random_normal_des_roundtrip() {
+ do_random_roundtrip_test::<StandardDeserializer, _>(
+ DataElementType::iter()
+ .filter(|t| supports_flavor(*t, PacketFlavorEnum::Ciphertext))
+ .collect(),
+ random_de_ciphertext,
+ |builder, de| match de {
+ DeserializedDataElement::Actions(a) => builder.add_data_element(a),
+ DeserializedDataElement::TxPower(tx) => builder.add_data_element(tx),
+ },
+ |de| match de {
+ DeserializedDataElement::Actions(a) => serialized_len(a),
+ DeserializedDataElement::TxPower(tx) => serialized_len(tx),
+ },
+ )
+ }
+
+ #[test]
+ fn random_test_des_roundtrip() {
+ do_random_roundtrip_test::<TestDeDeserializer, _>(
+ TestDataElementType::iter().collect(),
+ random_test_de,
+ |builder, de| builder.add_data_element(de),
+ serialized_len,
+ )
+ }
+
+ fn do_random_roundtrip_test<D, F>(
+ de_types: Vec<D::DeTypeDisambiguator>,
+ build_de: F,
+ add_de: impl Fn(
+ &mut AdvBuilder<LdtEncoder<CryptoProviderImpl>>,
+ D::Deserialized<Ciphertext>,
+ ) -> Result<(), AddDataElementError>,
+ serialized_len: impl Fn(&D::Deserialized<Ciphertext>) -> usize,
+ ) where
+ D: DataElementDeserializer,
+ F: Fn(
+ D::DeTypeDisambiguator,
+ &mut rand_ext::rand_pcg::Pcg64,
+ ) -> D::Deserialized<Ciphertext>,
+ {
+ let mut rng = rand_ext::seeded_rng();
+
+ for _ in 0..10_000 {
+ let mut added_des = Vec::new();
+ let mut current_len = 0;
+
+ let key_seed: [u8; 32] = rng.gen();
+ let salt: ldt_np_adv::V0Salt = rng.gen::<[u8; 2]>().into();
+ let identity_token = V0IdentityToken::from(rng.gen::<[u8; V0_IDENTITY_TOKEN_LEN]>());
+
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ loop {
+ let de_type = *de_types.choose(&mut rng).unwrap();
+ let de = build_de(de_type, &mut rng);
+
+ if let Err(e) = add_de(&mut builder, de.clone()) {
+ match e {
+ AddDataElementError::InsufficientAdvSpace => {
+ if current_len
+ < ldt_np_adv::VALID_INPUT_LEN.start - V0_IDENTITY_TOKEN_LEN
+ {
+ // keep trying, not enough for LDT
+ continue;
+ }
+ // out of room
+ break;
+ }
+ }
+ }
+
+ current_len += serialized_len(&de);
+ added_des.push(de);
+ }
+
+ let adv = builder.into_advertisement().unwrap();
+ assert_deserialized_contents::<D>(&key_seed, identity_token, salt, &adv, &added_des);
+ }
+ }
+
+ fn build_and_assert_deserialized_matches<D: DataElementDeserializer>(
+ des: Vec<DynamicSerializeDataElement<Ciphertext>>,
+ expected: &[D::Deserialized<Ciphertext>],
+ ) -> (SerializedAdv, DecryptedAdvContents) {
+ let key_seed = [0; 32];
+ let identity_token = V0IdentityToken::from([0x33; V0_IDENTITY_TOKEN_LEN]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ for de in des {
+ builder.add_data_element(de).unwrap();
+ }
+ let adv = builder.into_advertisement().unwrap();
+
+ let decrypted =
+ assert_deserialized_contents::<D>(&key_seed, identity_token, salt, &adv, expected);
+ (adv, decrypted)
+ }
+
+ fn assert_deserialized_contents<D: DataElementDeserializer>(
+ key_seed: &[u8; 32],
+ identity_token: V0IdentityToken,
+ salt: V0Salt,
+ adv: &SerializedAdv,
+ expected: &[D::Deserialized<Ciphertext>],
+ ) -> DecryptedAdvContents {
+ let contents = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &adv.as_slice()[1..],
+ )
+ .unwrap();
+ let ldt = contents.as_ldt().unwrap();
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(key_seed);
+ let identity_token_hmac: [u8; 32] = hkdf
+ .v0_identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.as_slice());
+ let decrypter =
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, identity_token_hmac);
+ let decrypted = ldt.try_decrypt(&decrypter).unwrap();
+
+ assert_eq!(salt, decrypted.salt());
+ assert_eq!(identity_token, decrypted.identity_token());
+
+ assert_eq!(
+ expected,
+ decrypted.generic_data_elements::<D>().collect::<Result<Vec<_>, _>>().unwrap()
+ );
+
+ decrypted
+ }
+
+ /// serialized length including header
+ fn serialized_len<S: SerializeDataElement<Ciphertext>>(de: &S) -> usize {
+ let mut buf = DataElementSerializationBuffer::new(NP_MAX_ADV_CONTENT_LEN).unwrap();
+ de.serialize_contents(&mut buf).unwrap();
+ buf.len() + 1
+ }
+}
+
+mod coverage_gaming {
+ use alloc::format;
+
+ use crypto_provider_default::CryptoProviderImpl;
+
+ use crate::header::V0Encoding;
+ use crate::legacy::data_elements::de_type::DataElementType;
+ use crate::legacy::deserialize::intermediate::{IntermediateAdvContents, LdtAdvContents};
+ use crate::legacy::deserialize::{
+ AdvDeserializeError, DeIterator, RawDataElement, StandardDeserializer,
+ };
+ use crate::legacy::Plaintext;
+
+ #[test]
+ fn iac_debug_eq_test_helpers() {
+ let iac = IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &[0xFF],
+ )
+ .unwrap();
+ let _ = format!("{:?}", iac);
+ assert_eq!(iac, iac);
+ }
+
+ #[test]
+ fn iac_test_helpers() {
+ assert_eq!(
+ None,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Unencrypted,
+ &[0xFF],
+ )
+ .unwrap()
+ .as_ldt()
+ );
+ assert_eq!(
+ None,
+ IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ &[0xFF; 18],
+ )
+ .unwrap()
+ .as_unencrypted()
+ );
+ }
+
+ #[test]
+ fn ade_debug_clone() {
+ let _ = format!("{:?}", AdvDeserializeError::NoDataElements.clone());
+ }
+
+ #[test]
+ fn rde_debug_eq() {
+ let rde = RawDataElement::<'_, StandardDeserializer> {
+ de_type: DataElementType::Actions,
+ contents: &[],
+ };
+
+ let _ = format!("{:?}", rde);
+ assert_eq!(rde, rde);
+ }
+
+ #[test]
+ fn de_iterator_debug_clone_eq() {
+ let i = DeIterator::<'_, Plaintext>::new(&[]);
+ let _ = format!("{:?}", i.clone());
+ assert_eq!(i, i);
+ }
+
+ #[test]
+ fn ldt_adv_contents_debug() {
+ let lac = LdtAdvContents::new::<CryptoProviderImpl>([0; 2].into(), &[0; 16]).unwrap();
+ let _ = format!("{:?}", lac);
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/deserialize/tests/mod.rs b/nearby/presence/np_adv/src/legacy/deserialize/tests/mod.rs
new file mode 100644
index 0000000..0a016e1
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/deserialize/tests/mod.rs
@@ -0,0 +1,194 @@
+// 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.
+
+#![allow(unused_results, clippy::unwrap_used)]
+
+extern crate std;
+
+use super::*;
+use crate::header::V0Encoding;
+use crate::legacy::deserialize::intermediate::{IntermediateAdvContents, LdtAdvContents};
+use crate::{
+ credential::v0::V0BroadcastCredential,
+ legacy::{
+ serialize::{AdvBuilder, LdtEncoder},
+ BLE_4_ADV_SVC_MAX_CONTENT_LEN,
+ },
+ shared_data::TxPower,
+};
+use crypto_provider::CryptoProvider;
+use crypto_provider_default::CryptoProviderImpl;
+use ldt_np_adv::V0_IDENTITY_TOKEN_LEN;
+
+mod error_conditions;
+mod happy_path;
+
+#[test]
+fn decrypt_with_wrong_key_seed_error() {
+ let salt = ldt_np_adv::V0Salt::from([0x22; 2]);
+ let metadata_key: [u8; V0_IDENTITY_TOKEN_LEN] = [0x33; V0_IDENTITY_TOKEN_LEN];
+ let correct_key_seed = [0x11_u8; 32];
+
+ let (adv_content, correct_cipher) =
+ build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
+ let eac = parse_ciphertext_adv_contents(&correct_cipher, &adv_content.as_slice()[1..]);
+
+ // wrong key seed doesn't work (derives wrong ldt key, wrong hmac key)
+ let wrong_key_seed_cipher = {
+ let key_seed = [0x22_u8; 32];
+
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let metadata_key_hmac: [u8; 32] =
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&metadata_key);
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac)
+ };
+
+ assert_eq!(
+ DecryptError::DecryptOrVerifyError,
+ eac.try_decrypt(&wrong_key_seed_cipher).unwrap_err()
+ );
+}
+
+#[test]
+fn decrypt_with_wrong_hmac_key_error() {
+ let salt = ldt_np_adv::V0Salt::from([0x22; 2]);
+ let metadata_key: [u8; V0_IDENTITY_TOKEN_LEN] = [0x33; V0_IDENTITY_TOKEN_LEN];
+ let correct_key_seed = [0x11_u8; 32];
+
+ let (adv_content, correct_cipher_config) =
+ build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
+ let eac = parse_ciphertext_adv_contents(&correct_cipher_config, &adv_content.as_slice()[1..]);
+
+ let wrong_hmac_key_cipher = {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&[0x10_u8; 32]);
+ let metadata_key_hmac: [u8; 32] =
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&metadata_key);
+
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac)
+ };
+
+ assert_eq!(
+ DecryptError::DecryptOrVerifyError,
+ eac.try_decrypt::<CryptoProviderImpl>(&wrong_hmac_key_cipher).unwrap_err()
+ );
+}
+
+#[test]
+fn decrypt_with_wrong_hmac_error() {
+ let salt = ldt_np_adv::V0Salt::from([0x22; 2]);
+ let metadata_key: [u8; V0_IDENTITY_TOKEN_LEN] = [0x33; V0_IDENTITY_TOKEN_LEN];
+ let correct_key_seed = [0x11_u8; 32];
+
+ let (adv_content, correct_cipher_config) =
+ build_ciphertext_adv_contents(salt, &metadata_key, correct_key_seed);
+ let eac = parse_ciphertext_adv_contents(&correct_cipher_config, &adv_content.as_slice()[1..]);
+
+ let wrong_hmac_key_cipher = {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&correct_key_seed);
+
+ ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, [0x77; 32])
+ };
+
+ assert_eq!(
+ DecryptError::DecryptOrVerifyError,
+ eac.try_decrypt(&wrong_hmac_key_cipher).unwrap_err()
+ );
+}
+
+fn build_ciphertext_adv_contents<C: CryptoProvider>(
+ salt: ldt_np_adv::V0Salt,
+ metadata_key: &[u8; 14],
+ correct_key_seed: [u8; 32],
+) -> (
+ ArrayView<u8, { BLE_4_ADV_SVC_MAX_CONTENT_LEN }>,
+ ldt_np_adv::AuthenticatedNpLdtDecryptCipher<C>,
+) {
+ let hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&correct_key_seed);
+
+ let metadata_key_hmac: [u8; 32] =
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<C>(metadata_key.as_slice());
+
+ let correct_cipher = ldt_np_adv::build_np_adv_decrypter_from_key_seed(&hkdf, metadata_key_hmac);
+
+ let broadcast_cred =
+ V0BroadcastCredential::new(correct_key_seed, V0IdentityToken::from(*metadata_key));
+
+ let mut builder = AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
+ (builder.into_advertisement().unwrap(), correct_cipher)
+}
+
+fn parse_ciphertext_adv_contents<'b>(
+ cipher: &ldt_np_adv::AuthenticatedNpLdtDecryptCipher<CryptoProviderImpl>,
+ adv_content: &'b [u8],
+) -> LdtAdvContents<'b> {
+ let eac = match IntermediateAdvContents::deserialize::<CryptoProviderImpl>(
+ V0Encoding::Ldt,
+ adv_content,
+ )
+ .unwrap()
+ {
+ IntermediateAdvContents::Unencrypted(_) => panic!(),
+ // quick confirmation that we did get something
+ IntermediateAdvContents::Ldt(eac) => eac,
+ };
+
+ // correct cipher works
+ assert!(eac.try_decrypt(cipher).is_ok());
+
+ eac
+}
+
+mod coverage_gaming {
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement};
+ use crate::legacy::deserialize::{
+ DecryptError, DecryptedAdvContents, DeserializedDataElement, StandardDeserializer,
+ };
+ use crate::legacy::Plaintext;
+ use alloc::format;
+ use array_view::ArrayView;
+ use ldt_np_adv::{V0_IDENTITY_TOKEN_LEN, V0_SALT_LEN};
+
+ #[test]
+ fn decrypt_error_debug_clone() {
+ let _ = format!("{:?}", DecryptError::DecryptOrVerifyError.clone());
+ }
+
+ #[test]
+ fn deserialized_data_element_debug() {
+ let _ = format!(
+ "{:?}",
+ DeserializedDataElement::<Plaintext>::Actions(ActionsDataElement::from(
+ ActionBits::default()
+ ))
+ );
+ }
+
+ #[test]
+ fn decrypted_adv_contents_debug_partial_eq() {
+ let dac = DecryptedAdvContents::new(
+ [0; V0_IDENTITY_TOKEN_LEN].into(),
+ [0; V0_SALT_LEN].into(),
+ ArrayView::try_from_slice(&[]).unwrap(),
+ );
+ let _ = format!("{:?}", dac);
+ assert_eq!(dac, dac)
+ }
+
+ #[test]
+ fn standard_deserializer_debug_eq_clone() {
+ assert_eq!(StandardDeserializer, StandardDeserializer);
+ let _ = format!("{:?}", StandardDeserializer.clone());
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/mod.rs b/nearby/presence/np_adv/src/legacy/mod.rs
index 59f2308..2bac636 100644
--- a/nearby/presence/np_adv/src/legacy/mod.rs
+++ b/nearby/presence/np_adv/src/legacy/mod.rs
@@ -14,14 +14,20 @@
//! V0 advertisement support.
-use crate::MetadataKey;
+use crate::credential::matched::{MatchedCredential, WithMatchedCredential};
+use crate::legacy::deserialize::intermediate::{IntermediateAdvContents, UnencryptedAdvContents};
+use crate::{
+ credential::{
+ book::CredentialBook, v0::V0DiscoveryCryptoMaterial, DiscoveryMetadataCryptoMaterial,
+ },
+ header::V0Encoding,
+ legacy::deserialize::{DecryptError, DecryptedAdvContents},
+ AdvDeserializationError,
+};
use core::fmt;
use crypto_provider::CryptoProvider;
-use ldt_np_adv::NP_LEGACY_METADATA_KEY_LEN;
-pub mod actions;
pub mod data_elements;
-pub mod de_type;
pub mod deserialize;
pub mod serialize;
@@ -30,34 +36,19 @@ mod random_data_elements;
/// Advertisement capacity after 5 bytes of BLE header and 2 bytes of svc UUID are reserved from a
/// 31-byte advertisement
-pub const BLE_ADV_SVC_CONTENT_LEN: usize = 24;
-/// Maximum possible DE content: packet size minus 2 for adv header & DE header
-const NP_MAX_DE_CONTENT_LEN: usize = BLE_ADV_SVC_CONTENT_LEN - 2;
-
-/// "Short" 14-byte metadata key type employed for V0, which needs to be
-/// expanded to a regular-size 16-byte metadata key to decrypt metadata.
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
-pub struct ShortMetadataKey(pub [u8; NP_LEGACY_METADATA_KEY_LEN]);
-
-impl AsRef<[u8]> for ShortMetadataKey {
- fn as_ref(&self) -> &[u8] {
- &self.0
- }
-}
-
-impl ShortMetadataKey {
- /// Expand this short 14-byte metadata key to a 16-byte metadata key
- /// which may be used to decrypt metadata.
- pub fn expand<C: CryptoProvider>(&self) -> MetadataKey {
- let expanded_bytes = np_hkdf::legacy_metadata_expanded_key::<C>(&self.0);
- MetadataKey(expanded_bytes)
- }
-}
+pub const BLE_4_ADV_SVC_MAX_CONTENT_LEN: usize = 24;
+/// Maximum possible advertisement NP-level content: packet size minus 1 for version header
+const NP_MAX_ADV_CONTENT_LEN: usize = BLE_4_ADV_SVC_MAX_CONTENT_LEN - 1;
+/// Minimum advertisement NP-level content.
+/// Only meaningful for unencrypted advertisements, as LDT advertisements already have salt, token, etc.
+const NP_MIN_ADV_CONTENT_LEN: usize = 1;
+/// Max length of an individual DE's content
+pub(crate) const NP_MAX_DE_CONTENT_LEN: usize = NP_MAX_ADV_CONTENT_LEN - 1;
/// Marker type to allow disambiguating between plaintext and encrypted packets at compile time.
///
/// See also [PacketFlavorEnum] for when runtime flavor checks are more suitable.
-pub trait PacketFlavor: fmt::Debug + Clone + Copy {
+pub trait PacketFlavor: fmt::Debug + Clone + Copy + PartialEq + Eq {
/// The corresponding [PacketFlavorEnum] variant.
const ENUM_VARIANT: PacketFlavorEnum;
}
@@ -80,10 +71,90 @@ impl PacketFlavor for Ciphertext {
/// An enum version of the implementors of [PacketFlavor] for use cases where runtime checking is
/// a better fit than compile time checking.
-#[derive(Debug, Clone, Copy, strum_macros::EnumIter, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PacketFlavorEnum {
/// Corresponds to [Plaintext].
Plaintext,
/// Corresponds to [Ciphertext].
Ciphertext,
}
+
+/// Deserialize and decrypt the contents of a v0 adv after the version header
+pub(crate) fn deser_decrypt_v0<'adv, 'cred, B, P>(
+ encoding: V0Encoding,
+ cred_book: &'cred B,
+ remaining: &'adv [u8],
+) -> Result<V0AdvertisementContents<'adv, B::Matched>, AdvDeserializationError>
+where
+ B: CredentialBook<'cred>,
+ P: CryptoProvider,
+{
+ match IntermediateAdvContents::deserialize::<P>(encoding, remaining)? {
+ IntermediateAdvContents::Unencrypted(p) => Ok(V0AdvertisementContents::Plaintext(p)),
+ IntermediateAdvContents::Ldt(c) => {
+ for (crypto_material, matched) in cred_book.v0_iter() {
+ let ldt = crypto_material.ldt_adv_cipher::<P>();
+ match c.try_decrypt(&ldt) {
+ Ok(c) => {
+ let metadata_nonce = crypto_material.metadata_nonce::<P>();
+ return Ok(V0AdvertisementContents::Decrypted(WithMatchedCredential::new(
+ matched,
+ metadata_nonce,
+ c,
+ )));
+ }
+ Err(e) => match e {
+ DecryptError::DecryptOrVerifyError => continue,
+ },
+ }
+ }
+ Ok(V0AdvertisementContents::NoMatchingCredentials)
+ }
+ }
+}
+
+/// Advertisement content that was either already plaintext or has been decrypted.
+#[derive(Debug, PartialEq, Eq)]
+pub enum V0AdvertisementContents<'adv, M: MatchedCredential> {
+ /// Contents of a plaintext advertisement
+ Plaintext(UnencryptedAdvContents<'adv>),
+ /// Contents that was ciphertext in the original advertisement, and has been decrypted
+ /// with the credential in the [MatchedCredential]
+ Decrypted(WithMatchedCredential<M, DecryptedAdvContents>),
+ /// The advertisement was encrypted, but no credentials matched
+ NoMatchingCredentials,
+}
+
+#[cfg(test)]
+mod tests {
+ mod coverage_gaming {
+ use crate::legacy::{Ciphertext, PacketFlavorEnum, Plaintext};
+
+ extern crate std;
+
+ use std::format;
+
+ #[test]
+ fn plaintext_flavor() {
+ // debug
+ let _ = format!("{:?}", Plaintext);
+ // eq and clone
+ assert_eq!(Plaintext, Plaintext.clone())
+ }
+
+ #[test]
+ fn ciphertext_flavor() {
+ // debug
+ let _ = format!("{:?}", Ciphertext);
+ // eq and clone
+ assert_eq!(Ciphertext, Ciphertext.clone())
+ }
+
+ #[allow(clippy::clone_on_copy)]
+ #[test]
+ fn flavor_enum() {
+ // clone
+ let _ = PacketFlavorEnum::Plaintext.clone();
+ }
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/random_data_elements.rs b/nearby/presence/np_adv/src/legacy/random_data_elements.rs
index aca906b..e3fbde1 100644
--- a/nearby/presence/np_adv/src/legacy/random_data_elements.rs
+++ b/nearby/presence/np_adv/src/legacy/random_data_elements.rs
@@ -16,18 +16,18 @@
extern crate std;
+use crate::legacy::data_elements::actions::tests::{
+ set_ciphertexttext_action, set_plaintext_action,
+};
use crate::{
legacy::{
- actions::*,
- data_elements::*,
- de_type::PlainDataElementType,
- deserialize::PlainDataElement,
- serialize::{DataElementBundle, ToDataElementBundle},
+ data_elements::{actions::*, de_type::DataElementType, tx_power::TxPowerDataElement, *},
+ deserialize::DeserializedDataElement,
Ciphertext, PacketFlavor, PacketFlavorEnum, Plaintext,
},
- shared_data::{ContextSyncSeqNum, TxPower},
+ shared_data::TxPower,
};
-use rand_ext::rand::{self, distributions, prelude::SliceRandom as _};
+use rand_ext::rand::{distributions, prelude::SliceRandom as _};
use std::prelude::rust_2021::*;
use strum::IntoEnumIterator;
@@ -45,25 +45,16 @@ impl distributions::Distribution<ActionsDataElement<Plaintext>> for distribution
let mut bits = ActionBits::default();
for a in selected_actions {
- match a {
- ActionType::ContextSyncSeqNum => {
- bits.set_action(ContextSyncSeqNum::try_from(rng.gen_range(0..=15)).unwrap())
- }
- // generating boolean actions with `true` since we already did our random selection
- // of which actions to use above
- ActionType::NearbyShare => bits.set_action(NearbyShare::from(true)),
- ActionType::Finder => bits.set_action(Finder::from(true)),
- ActionType::FastPairSass => bits.set_action(FastPairSass::from(true)),
- ActionType::ActiveUnlock
- | ActionType::PresenceManager
- | ActionType::InstantTethering
- | ActionType::PhoneHub => unreachable!("not plaintext actions"),
- }
+ // generating boolean actions with `true` since we already did our random selection
+ // of which actions to use above
+
+ set_plaintext_action(*a, true, &mut bits);
}
ActionsDataElement::from(bits)
}
}
+
impl distributions::Distribution<ActionsDataElement<Ciphertext>> for distributions::Standard {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ActionsDataElement<Ciphertext> {
let mut available_actions = ActionType::iter()
@@ -78,20 +69,9 @@ impl distributions::Distribution<ActionsDataElement<Ciphertext>> for distributio
let mut bits = ActionBits::default();
for a in selected_actions {
- match a {
- ActionType::ContextSyncSeqNum => {
- bits.set_action(ContextSyncSeqNum::try_from(rng.gen_range(0..=15)).unwrap())
- }
- ActionType::ActiveUnlock => bits.set_action(ActiveUnlock::from(true)),
- // generating boolean actions with `true` since we already did our random selection
- // of which actions to use above
- ActionType::NearbyShare => bits.set_action(NearbyShare::from(true)),
- ActionType::PresenceManager => bits.set_action(PresenceManager::from(true)),
- ActionType::InstantTethering => bits.set_action(InstantTethering::from(true)),
- ActionType::PhoneHub => bits.set_action(PhoneHub::from(true)),
- ActionType::Finder => bits.set_action(Finder::from(true)),
- ActionType::FastPairSass => bits.set_action(FastPairSass::from(true)),
- }
+ // generating boolean actions with `true` since we already did our random selection
+ // of which actions to use above
+ set_ciphertexttext_action(*a, true, &mut bits);
}
ActionsDataElement::from(bits)
@@ -112,60 +92,45 @@ impl distributions::Distribution<TxPowerDataElement> for distributions::Standard
}
}
-/// Generate a random instance of the requested DE and return it wrapped in [PlainDataElement] along
-/// with its bundle representation.
-pub(crate) fn rand_de_and_bundle<F, D, E, R>(
- to_enum: E,
- rng: &mut R,
-) -> (PlainDataElement<F>, DataElementBundle<F>)
+/// Generate a random instance of the requested DE and return it wrapped in [DeserializedDataElement].
+pub(crate) fn rand_de<F, D, E, R>(to_enum: E, rng: &mut R) -> DeserializedDataElement<F>
where
F: PacketFlavor,
- D: ToDataElementBundle<F>,
- E: Fn(D) -> PlainDataElement<F>,
+ D: SerializeDataElement<F>,
+ E: Fn(D) -> DeserializedDataElement<F>,
R: rand::Rng,
distributions::Standard: distributions::Distribution<D>,
{
let de = rng.gen::<D>();
- let bundle = de.to_de_bundle();
- (to_enum(de), bundle)
+ to_enum(de)
}
/// Generate a random instance of the requested de type, or `None` if that type does not support
/// plaintext.
pub(crate) fn random_de_plaintext<R>(
- de_type: PlainDataElementType,
+ de_type: DataElementType,
rng: &mut R,
-) -> Option<(PlainDataElement<Plaintext>, DataElementBundle<Plaintext>)>
+) -> DeserializedDataElement<Plaintext>
where
R: rand::Rng,
{
- let opt = match de_type {
- PlainDataElementType::TxPower => Some(rand_de_and_bundle(PlainDataElement::TxPower, rng)),
- PlainDataElementType::Actions => Some(rand_de_and_bundle(PlainDataElement::Actions, rng)),
- };
-
- // make sure flavor support is consistent
- assert_eq!(opt.is_some(), de_type.supports_flavor(PacketFlavorEnum::Plaintext));
-
- opt
+ match de_type {
+ DataElementType::TxPower => rand_de(DeserializedDataElement::TxPower, rng),
+ DataElementType::Actions => rand_de(DeserializedDataElement::Actions, rng),
+ }
}
/// Generate a random instance of the requested de type, or `None` if that type does not support
/// ciphertext.
pub(crate) fn random_de_ciphertext<R>(
- de_type: PlainDataElementType,
+ de_type: DataElementType,
rng: &mut R,
-) -> Option<(PlainDataElement<Ciphertext>, DataElementBundle<Ciphertext>)>
+) -> DeserializedDataElement<Ciphertext>
where
R: rand::Rng,
{
- let opt = match de_type {
- PlainDataElementType::TxPower => Some(rand_de_and_bundle(PlainDataElement::TxPower, rng)),
- PlainDataElementType::Actions => Some(rand_de_and_bundle(PlainDataElement::Actions, rng)),
- };
-
- // make sure flavor support is consistent
- assert_eq!(opt.is_some(), de_type.supports_flavor(PacketFlavorEnum::Ciphertext));
-
- opt
+ match de_type {
+ DataElementType::TxPower => rand_de(DeserializedDataElement::TxPower, rng),
+ DataElementType::Actions => rand_de(DeserializedDataElement::Actions, rng),
+ }
}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/header.rs b/nearby/presence/np_adv/src/legacy/serialize/header.rs
new file mode 100644
index 0000000..7859633
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/serialize/header.rs
@@ -0,0 +1,74 @@
+// 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.
+
+use ldt_np_adv::{V0IdentityToken, V0Salt};
+
+/// Format || salt || token
+const ADV_HEADER_MAX_LEN: usize = 1 + 2 + 14;
+
+/// Serializes a V0 header.
+///
+/// Does not include the overall NP version header byte that defines the adv
+/// version.
+pub struct V0Header {
+ header_bytes: tinyvec::ArrayVec<[u8; ADV_HEADER_MAX_LEN]>,
+}
+
+impl V0Header {
+ pub(crate) fn unencrypted() -> Self {
+ let header_bytes = tinyvec::ArrayVec::new();
+ Self { header_bytes }
+ }
+
+ pub(crate) fn ldt_short_salt(salt: V0Salt, identity_token: V0IdentityToken) -> Self {
+ let mut header_bytes = tinyvec::ArrayVec::new();
+ header_bytes.extend_from_slice(salt.bytes().as_slice());
+ header_bytes.extend_from_slice(identity_token.as_slice());
+ Self { header_bytes }
+ }
+
+ /// The returned slice must be shorter than [crate::legacy::BLE_4_ADV_SVC_MAX_CONTENT_LEN] - 1.
+ pub(crate) fn as_slice(&self) -> &[u8] {
+ self.header_bytes.as_slice()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use ldt_np_adv::{V0_IDENTITY_TOKEN_LEN, V0_SALT_LEN};
+
+ const SHORT_SALT_BYTES: [u8; V0_SALT_LEN] = [0x10, 0x11];
+ const TOKEN_BYTES: [u8; V0_IDENTITY_TOKEN_LEN] =
+ [0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D];
+
+ #[test]
+ fn unencrypted_slice() {
+ assert_eq!(&[0_u8; 0], V0Header::unencrypted().as_slice());
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn ldt_short_salt_slice() {
+ assert_eq!(
+ &[
+ // salt
+ 0x10, 0x11,
+ // token
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D
+ ],
+ V0Header::ldt_short_salt(SHORT_SALT_BYTES.into(), TOKEN_BYTES.into()).as_slice()
+ );
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/mod.rs b/nearby/presence/np_adv/src/legacy/serialize/mod.rs
index 3746796..1906fb2 100644
--- a/nearby/presence/np_adv/src/legacy/serialize/mod.rs
+++ b/nearby/presence/np_adv/src/legacy/serialize/mod.rs
@@ -19,10 +19,9 @@
//! Serializing a plaintext advertisement:
//!
//! ```
-//! use np_adv::{legacy::{data_elements::*, serialize::*}, shared_data::*, PublicIdentity};
-//! use np_adv::shared_data::TxPower;
+//! use np_adv::{legacy::{data_elements::tx_power::TxPowerDataElement, serialize::*}, shared_data::*};
//!
-//! let mut builder = AdvBuilder::new(PublicIdentity::default());
+//! let mut builder = AdvBuilder::new(UnencryptedEncoder);
//! builder
//! .add_data_element(TxPowerDataElement::from(TxPower::try_from(3).expect("3 is a valid TxPower value")))
//! .unwrap();
@@ -30,7 +29,6 @@
//! assert_eq!(
//! &[
//! 0x00, // Adv Header
-//! 0x03, // Public DE header
//! 0x15, 0x03, // tx power de
//! ],
//! packet.as_slice()
@@ -40,29 +38,25 @@
//! Serializing an encrypted advertisement:
//!
//! ```
-//! use np_adv::{shared_data::*, de_type::*, legacy::{de_type::*, data_elements::*, serialize::*, *}};
-//! use np_adv::credential::{v0::V0, SimpleBroadcastCryptoMaterial};
+//! use np_adv::{shared_data::*, legacy::{data_elements::de_type::*, data_elements::tx_power::TxPowerDataElement, serialize::*, *}};
+//! use np_adv::credential::{v0::{V0, V0BroadcastCredential}};
//! use crypto_provider::CryptoProvider;
//! use crypto_provider_default::CryptoProviderImpl;
-//! use ldt_np_adv::{salt_padder, LegacySalt, LdtEncrypterXtsAes128};
+//! use ldt_np_adv::{V0Salt, V0IdentityToken};
//!
//! // Generate these from proper CSPRNGs -- using fixed data here
-//! let metadata_key = ShortMetadataKey([0x33; 14]);
-//! let salt = LegacySalt::from([0x01, 0x02]);
+//! let metadata_key = V0IdentityToken::from([0x33; 14]);
+//! let salt = V0Salt::from([0x01, 0x02]);
//! let key_seed = [0x44; 32];
-//! let ldt_enc = LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(
-//! &np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed).legacy_ldt_key()
-//! );
//!
-//! let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(
+//! let broadcast_cred = V0BroadcastCredential::new(
//! key_seed,
//! metadata_key,
//! );
//!
-//! let mut builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
-//! EncryptedIdentityDataElementType::Private,
+//! let mut builder = AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(
//! salt,
-//! &broadcast_cm,
+//! &broadcast_cred,
//! ));
//!
//! builder
@@ -71,195 +65,218 @@
//!
//! let packet = builder.into_advertisement().unwrap();
//! ```
-use crate::credential::{v0::V0, BroadcastCryptoMaterial};
+use core::fmt;
+
+use array_view::ArrayView;
+use crypto_provider::CryptoProvider;
+use ldt::LdtCipher;
+use ldt_np_adv::{V0IdentityToken, V0_IDENTITY_TOKEN_LEN};
+use sink::Sink;
+
+use crate::credential::v0::V0BroadcastCredential;
use crate::{
- de_type::{EncryptedIdentityDataElementType, IdentityDataElementType},
+ extended::to_array_view,
+ header::{VERSION_HEADER_V0_LDT, VERSION_HEADER_V0_UNENCRYPTED},
legacy::{
- de_type::{DataElementType, DeActualLength, DeEncodedLength, PlainDataElementType},
- Ciphertext, PacketFlavor, Plaintext, ShortMetadataKey, BLE_ADV_SVC_CONTENT_LEN,
- NP_MAX_DE_CONTENT_LEN,
+ data_elements::{
+ de_type::{DeActualLength, DeEncodedLength, DeTypeCode},
+ DataElementSerializationBuffer, DataElementSerializeError, SerializeDataElement,
+ },
+ Ciphertext, PacketFlavor, Plaintext, BLE_4_ADV_SVC_MAX_CONTENT_LEN, NP_MAX_ADV_CONTENT_LEN,
+ NP_MIN_ADV_CONTENT_LEN,
},
- DeLengthOutOfRange, PublicIdentity,
};
-use array_view::ArrayView;
-use core::{convert, fmt, marker};
-use crypto_provider::CryptoProvider;
+
+mod header;
#[cfg(test)]
-mod tests;
+pub(crate) mod tests;
-/// An identity used in serializing an advertisement.
-pub trait Identity: fmt::Debug {
+/// An encoder used in serializing an advertisement.
+pub trait AdvEncoder: fmt::Debug {
/// The flavor of packet this identity produces
type Flavor: PacketFlavor;
/// The error returned if postprocessing fails
type Error: fmt::Debug;
- /// How much space needs to be reserved for this identity's prefix bytes
- const OVERHEAD_LEN: usize;
+
+ /// The version header to put at the start of the advertisement.
+ const VERSION_HEADER: u8;
+
+ /// The V0-specific header to be written at the start of the advertisement
+ /// immediately after the version header.
+ fn header(&self) -> header::V0Header;
/// Perform identity-specific manipulation to the serialized DEs to produce the final
/// advertisement format.
///
- /// `buf` is `OVERHEAD_LEN` bytes set aside for the identity's use, followed by all of the DEs
- /// added to a packet. It does not include the NP top level header.
+ /// `buf` has the contents of [Self::header] written at the start, followed
+ /// by all of the DEs added to a packet. It does not include the NP top level header.
+ ///
+ /// The first `header_len` bytes of `buf` are the bytes produced by the call to [Self::header].
///
/// Returns `Ok` if postprocessing was successful and the packet is finished, or `Err` if
/// postprocessing failed and the packet should be discarded.
- fn postprocess(&self, buf: &mut [u8]) -> Result<(), Self::Error>;
+ fn postprocess(&self, header_len: usize, buf: &mut [u8]) -> Result<(), Self::Error>;
}
-lazy_static::lazy_static! {
- // Avoid either a panic-able code path or an error case that never happens by precalculating.
- static ref PUBLIC_IDENTITY_DE_HEADER: u8 =
- encode_de_header_actual_len(DataElementType::PublicIdentity, DeActualLength::ZERO).expect("de length is in range");
-}
+/// An unencrypted encoder with no associated identity.
+#[derive(Debug)]
+pub struct UnencryptedEncoder;
-impl Identity for PublicIdentity {
+impl AdvEncoder for UnencryptedEncoder {
type Flavor = Plaintext;
- type Error = convert::Infallible;
- // 1 byte for public DE header (0 content)
- const OVERHEAD_LEN: usize = 1;
+ type Error = UnencryptedEncodeError;
+ const VERSION_HEADER: u8 = VERSION_HEADER_V0_UNENCRYPTED;
- fn postprocess(&self, buf: &mut [u8]) -> Result<(), Self::Error> {
- buf[0] = *PUBLIC_IDENTITY_DE_HEADER;
+ fn header(&self) -> header::V0Header {
+ header::V0Header::unencrypted()
+ }
- Ok(())
+ fn postprocess(&self, _header_len: usize, buf: &mut [u8]) -> Result<(), Self::Error> {
+ if buf.len() < NP_MIN_ADV_CONTENT_LEN {
+ Err(UnencryptedEncodeError::InvalidLength)
+ } else {
+ Ok(())
+ }
}
}
-/// Identity used for encrypted packets (private, trusted, provisioned) that encrypts other DEs
+/// Unencrypted encoding errors
+#[derive(Debug, PartialEq, Eq)]
+pub enum UnencryptedEncodeError {
+ /// The advertisement content was outside the valid range
+ InvalidLength,
+}
+
+/// Encoder used for encrypted packets (private, trusted, provisioned) that encrypts other DEs
/// (as well as the metadata key).
-pub struct LdtIdentity<C: CryptoProvider> {
- de_type: EncryptedIdentityDataElementType,
- salt: ldt_np_adv::LegacySalt,
- metadata_key: ShortMetadataKey,
- ldt_enc: ldt_np_adv::LdtEncrypterXtsAes128<C>,
+pub struct LdtEncoder<C: CryptoProvider> {
+ salt: ldt_np_adv::V0Salt,
+ identity_token: V0IdentityToken,
+ ldt_enc: ldt_np_adv::NpLdtEncryptCipher<C>,
}
// Exclude sensitive members
-impl<C: CryptoProvider> fmt::Debug for LdtIdentity<C> {
+impl<C: CryptoProvider> fmt::Debug for LdtEncoder<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "LdtIdentity {{ de_type: {:?}, salt: {:X?} }}", self.de_type, self.salt)
+ write!(f, "LdtEncoder {{ salt: {:X?} }}", self.salt)
}
}
-impl<C: CryptoProvider> LdtIdentity<C> {
+impl<C: CryptoProvider> LdtEncoder<C> {
/// Build an `LdtIdentity` for the provided identity type, salt, and
/// broadcast crypto-materials.
- pub fn new<B: BroadcastCryptoMaterial<V0>>(
- de_type: EncryptedIdentityDataElementType,
- salt: ldt_np_adv::LegacySalt,
- crypto_material: &B,
- ) -> Self {
- let metadata_key = crypto_material.metadata_key();
- let key_seed = crypto_material.key_seed();
+ pub fn new(salt: ldt_np_adv::V0Salt, broadcast_cred: &V0BroadcastCredential) -> Self {
+ let identity_token = broadcast_cred.identity_token();
+ let key_seed = broadcast_cred.key_seed();
let key_seed_hkdf = np_hkdf::NpKeySeedHkdf::<C>::new(&key_seed);
- let ldt_key = key_seed_hkdf.legacy_ldt_key();
- let ldt_enc = ldt_np_adv::LdtEncrypterXtsAes128::<C>::new(&ldt_key);
+ let ldt_key = key_seed_hkdf.v0_ldt_key();
+ let ldt_enc = ldt_np_adv::NpLdtEncryptCipher::<C>::new(&ldt_key);
- Self { de_type, salt, metadata_key, ldt_enc }
+ Self { salt, identity_token, ldt_enc }
}
}
-impl<C: CryptoProvider> Identity for LdtIdentity<C> {
+impl<C: CryptoProvider> AdvEncoder for LdtEncoder<C> {
type Flavor = Ciphertext;
- type Error = LdtPostprocessError;
- // Identity DE header + salt + metadata key
- const OVERHEAD_LEN: usize = 17;
-
- fn postprocess(&self, buf: &mut [u8]) -> Result<(), LdtPostprocessError> {
- let de_type = self.de_type.as_identity_data_element_type();
- // there's space for the identity DE header byte, but we don't count that in the DE length
- let actual_len: DeActualLength = buf
- .len()
- .checked_sub(1)
- .ok_or(LdtPostprocessError::InvalidLength)
- .and_then(|len| len.try_into().map_err(|_e| LdtPostprocessError::InvalidLength))?;
- // header
- buf[0] = encode_de_header_actual_len(id_de_type_as_generic_de_type(de_type), actual_len)
- .map_err(|_e| LdtPostprocessError::InvalidLength)?;
- buf[1..3].copy_from_slice(self.salt.bytes().as_slice());
- buf[3..17].copy_from_slice(&self.metadata_key.0);
-
- // encrypt everything after DE header and salt
- self.ldt_enc.encrypt(&mut buf[3..], &ldt_np_adv::salt_padder::<16, C>(self.salt)).map_err(
- |e| match e {
- // too short, not enough DEs -- should be caught by length validation above, though
- ldt::LdtError::InvalidLength(_) => LdtPostprocessError::InvalidLength,
- },
- )
+ type Error = LdtEncodeError;
+ const VERSION_HEADER: u8 = VERSION_HEADER_V0_LDT;
+
+ fn header(&self) -> header::V0Header {
+ header::V0Header::ldt_short_salt(self.salt, self.identity_token)
+ }
+
+ fn postprocess(&self, header_len: usize, buf: &mut [u8]) -> Result<(), LdtEncodeError> {
+ // encrypt everything after v0 format and salt
+ self.ldt_enc
+ .encrypt(
+ &mut buf[header_len - V0_IDENTITY_TOKEN_LEN..],
+ &ldt_np_adv::salt_padder::<C>(self.salt),
+ )
+ .map_err(|e| match e {
+ // too short, not enough DEs
+ ldt::LdtError::InvalidLength(_) => LdtEncodeError::InvalidLength,
+ })
}
}
-/// Something went wrong, or preconditions were not met, during identity postprocessing.
+/// LDT encoding errors
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub enum LdtPostprocessError {
- /// The minimum size (2 bytes) or maximum size (6 bytes) of DE payload was not met
+pub enum LdtEncodeError {
+ /// The minimum size (2 bytes) or maximum size (7 bytes for BLE 4.2
+ /// advertisements) of DE data was not met
InvalidLength,
}
+/// The serialized form of a V0 adv, suitable for setting as the value for the NP UUID svc data.
+pub type SerializedAdv = ArrayView<u8, BLE_4_ADV_SVC_MAX_CONTENT_LEN>;
+
/// Accumulates DEs, then massages the serialized DEs with the configured identity to produce
/// the final advertisement.
#[derive(Debug)]
-pub struct AdvBuilder<I: Identity> {
+pub struct AdvBuilder<E: AdvEncoder> {
/// The first byte is for the adv header, then the next I::OVERHEAD_LEN bytes are set aside for
- /// use by [Identity::postprocess].
- buffer: [u8; BLE_ADV_SVC_CONTENT_LEN],
+ /// use by [AdvEncoder::postprocess].
+ buffer: [u8; BLE_4_ADV_SVC_MAX_CONTENT_LEN],
/// How much of the buffer is consumed.
- /// Always <= buffer length
+ /// Always <= buffer length, and at least 2
len: usize,
- identity: I,
+ /// How long the header was
+ header_len: usize,
+ encoder: E,
}
-impl<I: Identity> AdvBuilder<I> {
+impl<E: AdvEncoder> AdvBuilder<E> {
/// Create an empty AdvBuilder with the provided identity.
- pub fn new(identity: I) -> AdvBuilder<I> {
- // adv header + identity overhead
- let len = 1 + I::OVERHEAD_LEN;
+ pub fn new(encoder: E) -> AdvBuilder<E> {
+ let mut buffer = [0; BLE_4_ADV_SVC_MAX_CONTENT_LEN];
+ buffer[0] = E::VERSION_HEADER;
+
+ // encode the rest of the V0 header
+ let header = encoder.header();
+ let header_len = header.as_slice().len();
+ // len will be at least 1, important for max_de_len safety in add_data_element
+ let len = 1 + header_len;
// check for broken identities
- assert!(len < BLE_ADV_SVC_CONTENT_LEN);
+ debug_assert!(len < buffer.len());
+ buffer[1..=header_len].copy_from_slice(header.as_slice());
+
AdvBuilder {
// conveniently the first byte is already 0, which is the correct header for v0.
// 3 bit version (000 since this is version 0), 5 bit reserved (also all 0)
- buffer: [0; BLE_ADV_SVC_CONTENT_LEN],
+ buffer,
len,
- identity,
+ header_len,
+ encoder,
}
}
/// Add the data element to the packet buffer, if there is space.
- pub fn add_data_element<B: ToDataElementBundle<I::Flavor>>(
+ pub fn add_data_element<D: SerializeDataElement<E::Flavor>>(
&mut self,
- data_element: B,
+ data_element: D,
) -> Result<(), AddDataElementError> {
- let remaining = self.buffer.len() - self.len;
- let bundle = data_element.to_de_bundle();
- // length including header byte
- let de_slice = bundle.contents_as_slice();
- let de_total_len = 1 + de_slice.len();
- if remaining < de_total_len {
- return Err(AddDataElementError::InsufficientAdvSpace);
- }
+ // invariant: self.len <= buffer length
+ debug_assert!(self.len <= self.buffer.len());
+ let dest = &mut self.buffer[self.len..];
+ // because self.len is at least 1, the dest will be no more than
+ // `[BLE_ADV_SVC_CONTENT_LEN] - 1 = [NP_MAX_ADV_CONTENT_LEN]`
+ let de_buf = serialize_de(&data_element, dest.len())?;
+ dest[..de_buf.len()].copy_from_slice(de_buf.as_slice());
+ // invariant: de_buf fit in the remaining space, so adding its length is safe
+ self.len += de_buf.len();
+ debug_assert!(self.len <= self.buffer.len());
- // header
- self.buffer[self.len] =
- encode_de_header(bundle.de_type.as_generic_de_type(), bundle.encoded_len);
- self.len += 1;
- // de contents
- self.buffer[self.len..self.len + de_slice.len()].copy_from_slice(de_slice);
- self.len += de_slice.len();
Ok(())
}
- /// Return the finished advertisement (adv header + DEs), or `None` if the adv could not be
- /// built.
- pub fn into_advertisement(
- mut self,
- ) -> Result<ArrayView<u8, BLE_ADV_SVC_CONTENT_LEN>, I::Error> {
+ /// Return the finished advertisement (version header || V0 header || DEs),
+ /// or `None` if the adv could not be built.
+ pub fn into_advertisement(mut self) -> Result<SerializedAdv, E::Error> {
// encrypt, if applicable
- self.identity
- // skip adv header for postprocessing
- .postprocess(&mut self.buffer[1..self.len])
+ self.encoder
+ // skip NP version header for postprocessing
+ .postprocess(self.header_len, &mut self.buffer[1..self.len])
.map(|_| ArrayView::try_from_array(self.buffer, self.len).expect("len is always valid"))
}
}
@@ -271,131 +288,67 @@ pub enum AddDataElementError {
InsufficientAdvSpace,
}
-/// The serialized form of a data element.
-#[derive(Clone, Debug)]
-pub struct DataElementBundle<F: PacketFlavor> {
- de_type: PlainDataElementType,
- /// Data element payload
- data: DePayload,
- /// The header-encoded form of `data`'s length
- encoded_len: DeEncodedLength,
- /// Type marker for whether this DE can be used in encrypted or plaintext packets.
- flavor: marker::PhantomData<F>,
-}
-
-impl<F: PacketFlavor> DataElementBundle<F> {
- /// Returns `Err` if the provided `data` or requested [PacketFlavor] are not valid for
- /// `de_type`.
- pub(crate) fn try_from(
- de_type: PlainDataElementType,
- data: &[u8],
- ) -> Result<DataElementBundle<F>, DeBundleError> {
- if !de_type.supports_flavor(F::ENUM_VARIANT) {
- return Err(DeBundleError::InvalidFlavor);
+impl From<DataElementSerializeError> for AddDataElementError {
+ fn from(value: DataElementSerializeError) -> Self {
+ match value {
+ DataElementSerializeError::InsufficientSpace => Self::InsufficientAdvSpace,
}
-
- let mut buffer = [0; NP_MAX_DE_CONTENT_LEN];
- buffer
- .get_mut(0..data.len())
- .map(|dest| dest.copy_from_slice(data))
- .ok_or(DeBundleError::InvalidLength)?;
-
- let payload: DePayload = ArrayView::try_from_array(buffer, data.len())
- .expect("data already copied into buffer")
- .into();
-
- // get the encoded length now so we know the length is valid for the DE type
- let encoded_len = de_type
- .as_generic_de_type()
- .encoded_len_for_actual_len(payload.len())
- .map_err(|_| DeBundleError::InvalidLength)?;
-
- Ok(DataElementBundle { de_type, data: payload, encoded_len, flavor: marker::PhantomData })
- }
-
- /// The data contained in the DE, excluding the header byte
- pub(crate) fn contents_as_slice(&self) -> &[u8] {
- self.data.as_slice()
}
}
-/// Errors that can occur when building a [DataElementBundle]
-#[derive(Debug, PartialEq, Eq)]
-pub(crate) enum DeBundleError {
- /// The DE type does not support the requested flavor
- InvalidFlavor,
- /// The data is too long to fit in a DE, or is invalid for the DE type
- InvalidLength,
+/// Encode a DE type and length into a DE header byte.
+pub(crate) fn encode_de_header(code: DeTypeCode, header_len: DeEncodedLength) -> u8 {
+ // 4 high bits are length, 4 low bits are type
+ (header_len.as_u8() << 4) | code.as_u8()
}
-/// Implemented by higher-level types that represent data elements.
-pub trait ToDataElementBundle<F: PacketFlavor> {
- /// Serialize `self` into the impl-specific byte encoding used for that DE type.
- fn to_de_bundle(&self) -> DataElementBundle<F>;
+/// Encode a DE into a buffer.
+///
+/// The buffer will contain the DE header and DE contents, if any, and will
+/// not exceed `max_de_len`.
+///
+/// # Panics
+/// `max_de_len` must be no larger than [NP_MAX_ADV_CONTENT_LEN].
+fn serialize_de<F: PacketFlavor, D: SerializeDataElement<F>>(
+ data_element: &D,
+ max_de_len: usize,
+) -> Result<SerializedDataElement, AddDataElementError> {
+ let mut de_buf = DataElementSerializationBuffer::new(max_de_len)
+ .expect("max_de_len must not exceed NP_MAX_DE_CONTENT_LEN");
+
+ // placeholder for header
+ de_buf.try_push(0).ok_or(AddDataElementError::InsufficientAdvSpace)?;
+ data_element.serialize_contents(&mut de_buf)?;
+
+ let encoded_len = data_element.map_actual_len_to_encoded_len(
+ DeActualLength::try_from(de_buf.len() - 1)
+ .expect("DE fit in buffer after header, so it should be a valid size"),
+ );
+
+ let mut vec = de_buf.into_inner().into_inner();
+ vec[0] = encode_de_header(data_element.de_type_code(), encoded_len);
+
+ debug_assert!(vec.len() <= max_de_len);
+
+ Ok(SerializedDataElement::new(to_array_view(vec)))
}
-// for cases where it's more convenient to already have a DataElementBundle than a DE
-impl<F: PacketFlavor> ToDataElementBundle<F> for DataElementBundle<F> {
- fn to_de_bundle(&self) -> DataElementBundle<F> {
- Self {
- de_type: self.de_type,
- data: self.data.clone(),
- encoded_len: self.encoded_len,
- flavor: marker::PhantomData,
- }
- }
+/// The serialized form of a data element, including its header.
+pub(crate) struct SerializedDataElement {
+ data: ArrayView<u8, NP_MAX_ADV_CONTENT_LEN>,
}
-// Biggest size a DE could possibly be is the entire payload
-#[derive(Clone, PartialEq, Eq, Debug)]
-struct DePayload {
- payload: ArrayView<u8, { NP_MAX_DE_CONTENT_LEN }>,
-}
-
-impl DePayload {
- /// The actual length of the payload
- fn len(&self) -> DeActualLength {
- self.payload
- .len()
- .try_into()
- .expect("Payload is an array of the max size which always has a valid length")
- }
-
- fn as_slice(&self) -> &[u8] {
- self.payload.as_slice()
+impl SerializedDataElement {
+ fn new(data: ArrayView<u8, NP_MAX_ADV_CONTENT_LEN>) -> Self {
+ Self { data }
}
-}
-impl From<ArrayView<u8, { NP_MAX_DE_CONTENT_LEN }>> for DePayload {
- fn from(array: ArrayView<u8, { NP_MAX_DE_CONTENT_LEN }>) -> Self {
- Self { payload: array }
+ /// The serialized DE, starting with the DE header byte
+ pub(crate) fn as_slice(&self) -> &[u8] {
+ self.data.as_slice()
}
-}
-
-/// Encode a DE type and length into a DE header byte.
-pub(crate) fn encode_de_header(de_type: DataElementType, header_len: DeEncodedLength) -> u8 {
- // 4 high bits are length, 4 low bits are type
- (header_len.as_u8() << 4) | de_type.type_code().as_u8()
-}
-
-/// Encode a DE type and length into a DE header byte.
-pub(crate) fn encode_de_header_actual_len(
- de_type: DataElementType,
- header_len: DeActualLength,
-) -> Result<u8, DeLengthOutOfRange> {
- de_type
- .encoded_len_for_actual_len(header_len)
- // 4 high bits are length, 4 low bits are type
- .map(|len| encode_de_header(de_type, len))
-}
-pub(crate) fn id_de_type_as_generic_de_type(
- id_de_type: IdentityDataElementType,
-) -> DataElementType {
- match id_de_type {
- IdentityDataElementType::Private => DataElementType::PrivateIdentity,
- IdentityDataElementType::Trusted => DataElementType::TrustedIdentity,
- IdentityDataElementType::Public => DataElementType::PublicIdentity,
- IdentityDataElementType::Provisioned => DataElementType::ProvisionedIdentity,
+ pub(crate) fn len(&self) -> usize {
+ self.data.len()
}
}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/tests.rs b/nearby/presence/np_adv/src/legacy/serialize/tests.rs
deleted file mode 100644
index 7be30ba..0000000
--- a/nearby/presence/np_adv/src/legacy/serialize/tests.rs
+++ /dev/null
@@ -1,153 +0,0 @@
-// 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.
-
-#![allow(clippy::unwrap_used)]
-
-extern crate std;
-
-use crate::legacy::actions::FastPairSass;
-use crate::legacy::actions::NearbyShare;
-use crate::{
- credential::{v0::V0, SimpleBroadcastCryptoMaterial},
- de_type::EncryptedIdentityDataElementType,
- legacy::{actions::*, data_elements::*, serialize::*},
- shared_data::TxPower,
-};
-use crypto_provider_default::CryptoProviderImpl;
-use ldt_np_adv::{salt_padder, LdtEncrypterXtsAes128, LegacySalt};
-use std::vec;
-
-#[test]
-fn public_identity_packet_serialization() {
- let mut builder = AdvBuilder::new(PublicIdentity);
-
- let tx_power = TxPower::try_from(3).unwrap();
- let mut action = ActionBits::default();
- action.set_action(NearbyShare::from(true));
- builder.add_data_element(TxPowerDataElement::from(tx_power)).unwrap();
- builder.add_data_element(ActionsDataElement::from(action)).unwrap();
-
- let packet = builder.into_advertisement().unwrap();
- assert_eq!(
- &[
- 0x00, // Adv Header
- 0x03, // Public DE header
- 0x15, 0x03, // Tx Power DE with value 3
- 0x26, 0x00, 0x40, // Actions DE w/ bit 9
- ],
- packet.as_slice()
- );
-}
-
-#[test]
-fn packet_limits_capacity() {
- let mut builder = AdvBuilder::new(PublicIdentity);
- // 2 + 1 left out of 24 payload bytes
- builder.len = 21;
- let mut bits = ActionBits::default();
- bits.set_action(NearbyShare::from(true));
- bits.set_action(FastPairSass::from(true));
-
- assert_eq!(Ok(()), builder.add_data_element(ActionsDataElement::from(bits)));
-
- // too small for 2+ 1 DE
- builder.len = 22;
- assert_eq!(
- Err(AddDataElementError::InsufficientAdvSpace),
- builder.add_data_element(ActionsDataElement::from(bits))
- );
-}
-
-#[test]
-fn ldt_packet_serialization() {
- // don't care about the HMAC since we're not decrypting
- let key_seed = [0; 32];
- let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let ldt = LdtEncrypterXtsAes128::<CryptoProviderImpl>::new(&hkdf.legacy_ldt_key());
- let metadata_key = ShortMetadataKey([0x33; 14]);
- let salt = LegacySalt::from([0x01, 0x02]);
-
- let mut ciphertext = vec![];
- ciphertext.extend_from_slice(&metadata_key.0);
- // tx power & action DEs
- ciphertext.extend_from_slice(&[0x15, 0x03, 0x26, 0x00, 0x10]);
- ldt.encrypt(&mut ciphertext, &salt_padder::<16, CryptoProviderImpl>(salt)).unwrap();
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
-
- let mut builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- EncryptedIdentityDataElementType::Private,
- salt,
- &broadcast_cm,
- ));
-
- let tx_power = TxPower::try_from(3).unwrap();
- let mut action = ActionBits::default();
- action.set_action(PhoneHub::from(true));
- builder.add_data_element(TxPowerDataElement::from(tx_power)).unwrap();
- builder.add_data_element(ActionsDataElement::from(action)).unwrap();
-
- let packet = builder.into_advertisement().unwrap();
- // header
- let mut expected = vec![0x00];
- // private header with five bytes after it
- expected.push(0x51);
- expected.extend_from_slice(salt.bytes());
- expected.extend_from_slice(&ciphertext);
- assert_eq!(&expected, packet.as_slice());
-}
-
-#[test]
-fn ldt_packet_cant_encrypt_without_des() {
- let metadata_key = ShortMetadataKey([0x33; 14]);
- let salt = LegacySalt::from([0x01, 0x02]);
- let key_seed = [0xFE; 32];
-
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
-
- let builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- EncryptedIdentityDataElementType::Private,
- salt,
- &broadcast_cm,
- ));
-
- // not enough ciphertext
- assert_eq!(Err(LdtPostprocessError::InvalidLength), builder.into_advertisement());
-}
-
-#[test]
-fn nearby_share_action() {
- let mut builder = AdvBuilder::new(PublicIdentity);
-
- let mut action = ActionBits::default();
- action.set_action(NearbyShare::from(true));
-
- let actions_de = ActionsDataElement::from(action);
- builder.add_data_element(actions_de).unwrap();
-
- let tx_power_de = TxPowerDataElement::from(TxPower::try_from(-100).unwrap());
- builder.add_data_element(tx_power_de).unwrap();
-
- assert_eq!(
- &[
- 0x00, // version 0
- 0x03, // public identity
- 0x26, // length 2, DE type 6 for actions
- 0x00, 0x40, // bit 9 is active
- 0x15, // length 1, DE type 5 for tx power
- 0x9C, // tx power of -100
- ],
- builder.into_advertisement().unwrap().as_slice()
- );
-}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/tests/error_conditions.rs b/nearby/presence/np_adv/src/legacy/serialize/tests/error_conditions.rs
new file mode 100644
index 0000000..572276e
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/serialize/tests/error_conditions.rs
@@ -0,0 +1,193 @@
+// 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.
+
+mod unencrypted_encoder {
+ use alloc::vec;
+ use core::ops::Deref;
+
+ extern crate std;
+
+ use std::prelude::rust_2021::*;
+
+ use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
+ use crate::legacy::serialize::{
+ AddDataElementError, AdvBuilder, UnencryptedEncodeError, UnencryptedEncoder,
+ };
+ use crate::legacy::{BLE_4_ADV_SVC_MAX_CONTENT_LEN, NP_MAX_DE_CONTENT_LEN};
+
+ #[test]
+ fn build_empty_adv_error() {
+ // empty isn't allowed, so 1 byte of payload is the smallest possible
+ let builder = AdvBuilder::new(UnencryptedEncoder);
+
+ assert_eq!(
+ UnencryptedEncodeError::InvalidLength,
+ builder.into_advertisement().unwrap_err()
+ );
+ }
+
+ #[test]
+ fn add_de_when_full_error() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder
+ .add_data_element(LongDataElement::new(vec![1; NP_MAX_DE_CONTENT_LEN].clone()))
+ .unwrap();
+
+ // 1 more byte (DE header) is too much
+ assert_eq!(
+ AddDataElementError::InsufficientAdvSpace,
+ builder.add_data_element(ShortDataElement::new(vec![].clone())).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn add_too_much_de_when_almost_full_error() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ // leave 1 byte of room
+ builder
+ .add_data_element(LongDataElement::new(vec![1; NP_MAX_DE_CONTENT_LEN - 1].clone()))
+ .unwrap();
+
+ // DE header would fit, but 1 byte of DE content is too much
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN - 1, builder.len);
+ assert_eq!(
+ AddDataElementError::InsufficientAdvSpace,
+ builder.add_data_element(ShortDataElement::new(vec![2].clone())).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn broken_de_impl_hits_expected_panic() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ let panic_payload = std::panic::catch_unwind(move || {
+ // This DE type can't represent short lengths
+ builder.add_data_element(LongDataElement::new(vec![]))
+ })
+ .unwrap_err();
+
+ assert_eq!(
+ "Couldn't encode actual len: DeLengthOutOfRange",
+ panic_payload.downcast::<String>().unwrap().deref()
+ );
+ }
+}
+
+mod ldt_encoder {
+ use alloc::string::String;
+ use alloc::vec;
+ use core::ops::Deref;
+
+ extern crate std;
+
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt_np_adv::{V0IdentityToken, V0Salt};
+
+ use crate::credential::v0::V0BroadcastCredential;
+ use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
+ use crate::legacy::serialize::{AddDataElementError, AdvBuilder, LdtEncodeError, LdtEncoder};
+ use crate::legacy::BLE_4_ADV_SVC_MAX_CONTENT_LEN;
+
+ #[test]
+ fn build_empty_adv_error() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let builder = AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ // not enough ciphertext
+ assert_eq!(Err(LdtEncodeError::InvalidLength), builder.into_advertisement());
+ }
+
+ #[test]
+ fn build_adv_one_byte_error() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+ // 1 byte of DE header
+ builder.add_data_element(ShortDataElement::new(vec![])).unwrap();
+
+ // not enough ciphertext
+ assert_eq!(Err(LdtEncodeError::InvalidLength), builder.into_advertisement());
+ }
+
+ #[test]
+ fn add_de_when_full_error() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+ // 7 bytes will fill it
+ builder.add_data_element(ShortDataElement::new(vec![1; 6])).unwrap();
+
+ // 1 more byte is too many
+ assert_eq!(
+ AddDataElementError::InsufficientAdvSpace,
+ builder.add_data_element(ShortDataElement::new(vec![])).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn add_too_much_de_when_almost_full_error() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+ // 6 bytes will leave 1 byte
+ builder.add_data_element(ShortDataElement::new(vec![1; 5])).unwrap();
+
+ // 1 byte would fit, but 2 won't
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN - 1, builder.len);
+ assert_eq!(
+ AddDataElementError::InsufficientAdvSpace,
+ builder.add_data_element(ShortDataElement::new(vec![2])).unwrap_err()
+ );
+ }
+
+ #[test]
+ fn broken_de_impl_hits_expected_panic() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+
+ let panic_payload = std::panic::catch_unwind(move || {
+ // This DE type can't represent short lengths
+ builder.add_data_element(LongDataElement::new(vec![]))
+ })
+ .unwrap_err();
+
+ assert_eq!(
+ "Couldn't encode actual len: DeLengthOutOfRange",
+ panic_payload.downcast::<String>().unwrap().deref()
+ );
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/tests/happy_path.rs b/nearby/presence/np_adv/src/legacy/serialize/tests/happy_path.rs
new file mode 100644
index 0000000..05fc20a
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/serialize/tests/happy_path.rs
@@ -0,0 +1,244 @@
+// 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.
+
+mod unencrypted_encoder {
+ use alloc::vec;
+
+ use crate::header::VERSION_HEADER_V0_UNENCRYPTED;
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement, NearbyShare};
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::serialize::tests::helpers::{LongDataElement, ShortDataElement};
+ use crate::legacy::serialize::{AdvBuilder, UnencryptedEncoder};
+ use crate::legacy::{
+ BLE_4_ADV_SVC_MAX_CONTENT_LEN, NP_MAX_ADV_CONTENT_LEN, NP_MAX_DE_CONTENT_LEN,
+ };
+ use crate::shared_data::TxPower;
+
+ #[test]
+ fn adv_min_size() {
+ // empty isn't allowed, so 1 byte of payload is the smallest possible
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder.add_data_element(ShortDataElement::new(vec![])).unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(&[VERSION_HEADER_V0_UNENCRYPTED, 0x0E], adv.as_slice());
+ }
+
+ #[test]
+ fn adv_max_size_multi_de() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder.add_data_element(ShortDataElement::new(vec![1; 10])).unwrap();
+ // max len after previous DE & headers
+ let de2_contents = vec![2; NP_MAX_ADV_CONTENT_LEN - 1 - 10 - 1];
+ builder.add_data_element(LongDataElement::new(de2_contents.clone())).unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, adv.len());
+ assert_eq!(
+ &[
+ [VERSION_HEADER_V0_UNENCRYPTED, 0xAE].as_slice(),
+ [1; 10].as_slice(),
+ &[0x4F],
+ &de2_contents
+ ]
+ .concat(),
+ adv.as_slice()
+ );
+ }
+
+ #[test]
+ fn adv_max_size_single_de() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder
+ .add_data_element(LongDataElement::new(vec![1; NP_MAX_DE_CONTENT_LEN].clone()))
+ .unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, adv.len());
+ assert_eq!(
+ &[[VERSION_HEADER_V0_UNENCRYPTED, 0xFF].as_slice(), &[1; NP_MAX_DE_CONTENT_LEN],]
+ .concat(),
+ adv.as_slice()
+ );
+ }
+
+ #[rustfmt::skip]
+ #[test]
+ fn typical_tx_power_and_actions() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
+
+ let mut action = ActionBits::default();
+ action.set_action(NearbyShare::from(true));
+ builder.add_data_element(ActionsDataElement::from(action)).unwrap();
+
+ let packet = builder.into_advertisement().unwrap();
+ assert_eq!(
+ &[
+ VERSION_HEADER_V0_UNENCRYPTED,
+ 0x15, 0x03, // Tx Power DE with value 3
+ 0x26, 0x00, 0x40, // Actions DE w/ bit 9
+ ],
+ packet.as_slice()
+ );
+ }
+}
+
+mod ldt_encoder {
+ use alloc::vec;
+
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt::LdtCipher;
+ use ldt_np_adv::{
+ salt_padder, NpLdtEncryptCipher, V0IdentityToken, V0Salt, V0_IDENTITY_TOKEN_LEN,
+ };
+
+ use crate::credential::v0::V0BroadcastCredential;
+ use crate::header::VERSION_HEADER_V0_LDT;
+ use crate::legacy::data_elements::actions::tests::LastBit;
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement, PhoneHub};
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::serialize::tests::helpers::ShortDataElement;
+ use crate::legacy::serialize::{AdvBuilder, LdtEncoder, SerializedAdv};
+ use crate::legacy::BLE_4_ADV_SVC_MAX_CONTENT_LEN;
+ use crate::shared_data::TxPower;
+
+ #[test]
+ fn adv_min_size() {
+ // need at least 2 bytes to make 1 full block
+ let _ = assert_ldt_adv(&[0x1E, 0xAA], |builder| {
+ builder.add_data_element(ShortDataElement::new(vec![0xAA])).unwrap();
+ });
+ }
+
+ #[test]
+ fn adv_max_size_multi_de() {
+ let adv = assert_ldt_adv(&[0x15, 0x03, 0x4E, 0x01, 0x01, 0x01, 0x01], |builder| {
+ builder
+ .add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap()))
+ .unwrap();
+ builder.add_data_element(ShortDataElement::new(vec![1; 4])).unwrap();
+ });
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, adv.len());
+ }
+
+ #[test]
+ fn adv_max_size_single_de() {
+ let adv = assert_ldt_adv(&[0x6E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], |builder| {
+ builder.add_data_element(ShortDataElement::new(vec![1; 6])).unwrap();
+ });
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN, adv.len());
+ }
+
+ #[test]
+ fn adv_tx_power_max_length_actions() {
+ let adv = assert_ldt_adv(&[0x15, 0x03, 0x36, 0x00, 0x00, 0x01], |builder| {
+ builder
+ .add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap()))
+ .unwrap();
+ let mut action = ActionBits::default();
+ action.set_action(LastBit::from(true));
+ builder.add_data_element(ActionsDataElement::from(action)).unwrap();
+ });
+ // TODO this should be the max adv size once action size gets increased
+ assert_eq!(BLE_4_ADV_SVC_MAX_CONTENT_LEN - 1, adv.len());
+ }
+
+ #[test]
+ fn adv_typical_tx_power_and_actions() {
+ let _ = assert_ldt_adv(&[0x15, 0x03, 0x26, 0x00, 0x10], |builder| {
+ builder
+ .add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap()))
+ .unwrap();
+ let mut action = ActionBits::default();
+ action.set_action(PhoneHub::from(true));
+ builder.add_data_element(ActionsDataElement::from(action)).unwrap();
+ });
+ }
+
+ /// Build an LDT advertisement using the DEs provided by `add_des`, and assert that the resulting
+ /// advertisement matches the result of encrypting `identity token || after_identity_token`
+ fn assert_ldt_adv(
+ after_identity_token: &[u8],
+ add_des: impl Fn(&mut AdvBuilder<LdtEncoder<CryptoProviderImpl>>),
+ ) -> SerializedAdv {
+ let key_seed = [0; 32];
+ let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
+ let ldt = NpLdtEncryptCipher::<CryptoProviderImpl>::new(&hkdf.v0_ldt_key());
+ let identity_token = V0IdentityToken::from([0x33; V0_IDENTITY_TOKEN_LEN]);
+ let salt = V0Salt::from([0x01, 0x02]);
+
+ let mut plaintext = identity_token.as_slice().to_vec();
+ plaintext.extend_from_slice(after_identity_token);
+ ldt.encrypt(&mut plaintext, &salt_padder::<CryptoProviderImpl>(salt)).unwrap();
+ let ciphertext = plaintext;
+
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+
+ let mut builder =
+ AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred));
+ add_des(&mut builder);
+
+ let adv = builder.into_advertisement().unwrap();
+
+ let mut expected = vec![VERSION_HEADER_V0_LDT];
+ expected.extend_from_slice(&salt.bytes());
+ expected.extend_from_slice(&ciphertext);
+ assert_eq!(&expected, adv.as_slice());
+ adv
+ }
+}
+
+mod tx_de {
+ use crate::header::VERSION_HEADER_V0_UNENCRYPTED;
+ use crate::legacy::data_elements::tx_power::TxPowerDataElement;
+ use crate::legacy::serialize::{AdvBuilder, UnencryptedEncoder};
+ use crate::shared_data::TxPower;
+
+ #[test]
+ fn tx_power_produces_1_byte() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(&[VERSION_HEADER_V0_UNENCRYPTED, 0x15, 0x03], adv.as_slice());
+ }
+}
+
+mod actions_de {
+ use crate::header::VERSION_HEADER_V0_UNENCRYPTED;
+ use crate::legacy::data_elements::actions::tests::LastBit;
+ use crate::legacy::data_elements::actions::{ActionBits, ActionsDataElement};
+ use crate::legacy::serialize::{AdvBuilder, UnencryptedEncoder};
+
+ #[test]
+ fn no_bits_set_produces_1_byte() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ builder.add_data_element(ActionsDataElement::from(ActionBits::default())).unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(&[VERSION_HEADER_V0_UNENCRYPTED, 0x16, 0x00], adv.as_slice());
+ }
+
+ #[test]
+ fn lowest_bit_set_produces_max_len() {
+ let mut builder = AdvBuilder::new(UnencryptedEncoder);
+
+ let mut bits = ActionBits::default();
+ bits.set_action(LastBit::from(true));
+ builder.add_data_element(ActionsDataElement::from(bits)).unwrap();
+ let adv = builder.into_advertisement().unwrap();
+ assert_eq!(&[VERSION_HEADER_V0_UNENCRYPTED, 0x36, 0x00, 0x00, 0x01], adv.as_slice());
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/tests/helpers.rs b/nearby/presence/np_adv/src/legacy/serialize/tests/helpers.rs
new file mode 100644
index 0000000..ea0c886
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/serialize/tests/helpers.rs
@@ -0,0 +1,176 @@
+// 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.
+
+extern crate std;
+
+use std::prelude::rust_2021::*;
+
+use sink::Sink;
+
+use crate::legacy::data_elements::{
+ DataElementDeserializeError, DeserializeDataElement, DirectMapPredicate, DirectMapper,
+ LengthMapper,
+};
+use crate::{
+ legacy::{
+ data_elements::{
+ de_type::{DeActualLength, DeEncodedLength, DeTypeCode, MAX_DE_ENCODED_LEN},
+ DataElementSerializationBuffer, DataElementSerializeError, SerializeDataElement,
+ },
+ PacketFlavor, NP_MAX_DE_CONTENT_LEN,
+ },
+ private::Sealed,
+ DeLengthOutOfRange,
+};
+
+/// A DE allowing arbitrary data lengths. Encoded length is offset from actual length.
+///
+/// Data longer than [NP_MAX_DE_CONTENT_LEN] or shorter than [NP_MAX_DE_CONTENT_LEN] - [MAX_DE_ENCODED_LEN]
+/// will fail to map the actual length.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub(crate) struct LongDataElement {
+ data: Vec<u8>,
+}
+
+impl LongDataElement {
+ /// The offset lengths are shifted by when encoded
+ // `as usize` is safe since all u8s can fit. Can't use .into() or ::from() in a const.
+ pub(in crate::legacy) const OFFSET: usize =
+ NP_MAX_DE_CONTENT_LEN - (MAX_DE_ENCODED_LEN as usize);
+ pub fn new(data: Vec<u8>) -> Self {
+ Self { data }
+ }
+}
+
+impl Sealed for LongDataElement {}
+
+impl<F: PacketFlavor> SerializeDataElement<F> for LongDataElement {
+ fn de_type_code(&self) -> DeTypeCode {
+ Self::DE_TYPE_CODE
+ }
+
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ <Self as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual_len)
+ }
+
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ sink.try_extend_from_slice(&self.data).ok_or(DataElementSerializeError::InsufficientSpace)
+ }
+}
+
+impl DeserializeDataElement for LongDataElement {
+ const DE_TYPE_CODE: DeTypeCode = match DeTypeCode::try_from(15) {
+ Ok(t) => t,
+ Err(_) => unreachable!(),
+ };
+ type LengthMapper = OffsetMapper<{ Self::OFFSET }>;
+
+ fn deserialize<F: PacketFlavor>(
+ de_contents: &[u8],
+ ) -> Result<Self, DataElementDeserializeError> {
+ Ok(Self { data: de_contents.to_vec() })
+ }
+}
+
+impl From<Vec<u8>> for LongDataElement {
+ fn from(value: Vec<u8>) -> Self {
+ Self { data: value }
+ }
+}
+
+/// Subtracts `O` from actual lengths to yield encoded lengths, and vice versa.
+pub(in crate::legacy) struct OffsetMapper<const O: usize>;
+
+impl<const O: usize> LengthMapper for OffsetMapper<O> {
+ fn map_encoded_len_to_actual_len(
+ encoded_len: DeEncodedLength,
+ ) -> Result<DeActualLength, DeLengthOutOfRange> {
+ DeActualLength::try_from(encoded_len.as_usize() + O)
+ }
+
+ fn map_actual_len_to_encoded_len(actual_len: DeActualLength) -> DeEncodedLength {
+ actual_len
+ .as_u8()
+ .checked_sub(O.try_into().expect("Actual len is too short to use offset"))
+ .ok_or(DeLengthOutOfRange)
+ .and_then(DeEncodedLength::try_from)
+ .expect("Couldn't encode actual len")
+ }
+}
+
+/// A DE allowing arbitrary data with a straightforward actual len = encoded len scheme.
+///
+/// Data longer than [MAX_DE_ENCODED_LEN] will fail when mapping the length.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub(crate) struct ShortDataElement {
+ data: Vec<u8>,
+}
+
+impl ShortDataElement {
+ pub fn new(data: Vec<u8>) -> Self {
+ Self { data }
+ }
+}
+
+impl Sealed for ShortDataElement {}
+
+impl<F: PacketFlavor> SerializeDataElement<F> for ShortDataElement {
+ fn de_type_code(&self) -> DeTypeCode {
+ Self::DE_TYPE_CODE
+ }
+
+ fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
+ <Self as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual_len)
+ }
+
+ fn serialize_contents(
+ &self,
+ sink: &mut DataElementSerializationBuffer,
+ ) -> Result<(), DataElementSerializeError> {
+ sink.try_extend_from_slice(&self.data).ok_or(DataElementSerializeError::InsufficientSpace)
+ }
+}
+
+impl DeserializeDataElement for ShortDataElement {
+ const DE_TYPE_CODE: DeTypeCode = match DeTypeCode::try_from(14) {
+ Ok(t) => t,
+ Err(_) => unreachable!(),
+ };
+
+ type LengthMapper = DirectMapper<YoloLengthPredicate>;
+
+ fn deserialize<F: PacketFlavor>(
+ de_contents: &[u8],
+ ) -> Result<Self, DataElementDeserializeError> {
+ Ok(Self { data: de_contents.to_vec() })
+ }
+}
+
+/// Approves all lengths
+pub(in crate::legacy) struct YoloLengthPredicate;
+
+impl DirectMapPredicate for YoloLengthPredicate {
+ fn is_valid(_len: usize) -> bool {
+ true
+ }
+}
+
+impl From<Vec<u8>> for ShortDataElement {
+ fn from(value: Vec<u8>) -> Self {
+ Self { data: value }
+ }
+}
diff --git a/nearby/presence/np_adv/src/legacy/serialize/tests/mod.rs b/nearby/presence/np_adv/src/legacy/serialize/tests/mod.rs
new file mode 100644
index 0000000..caaa7d8
--- /dev/null
+++ b/nearby/presence/np_adv/src/legacy/serialize/tests/mod.rs
@@ -0,0 +1,95 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+extern crate std;
+
+use crate::legacy::{
+ data_elements::de_type::DataElementType, data_elements::*, serialize::*, PacketFlavorEnum,
+};
+
+mod error_conditions;
+mod happy_path;
+pub(in crate::legacy) mod helpers;
+
+pub(crate) fn serialize<F: PacketFlavor, D: SerializeDataElement<F>>(
+ de: &D,
+) -> SerializedDataElement {
+ serialize_de(de, NP_MAX_ADV_CONTENT_LEN).unwrap()
+}
+
+pub(in crate::legacy) fn supports_flavor(t: DataElementType, flavor: PacketFlavorEnum) -> bool {
+ match t {
+ DataElementType::Actions => match flavor {
+ PacketFlavorEnum::Plaintext => true,
+ PacketFlavorEnum::Ciphertext => true,
+ },
+ DataElementType::TxPower => match flavor {
+ PacketFlavorEnum::Plaintext => true,
+ PacketFlavorEnum::Ciphertext => true,
+ },
+ }
+}
+
+mod coverage_gaming {
+ use crate::credential::v0::V0BroadcastCredential;
+ use crate::legacy::serialize::{
+ AddDataElementError, AdvBuilder, LdtEncodeError, LdtEncoder, UnencryptedEncodeError,
+ UnencryptedEncoder,
+ };
+ use alloc::format;
+ use crypto_provider_default::CryptoProviderImpl;
+ use ldt_np_adv::{V0IdentityToken, V0Salt};
+
+ #[test]
+ fn unencrypted_encoder() {
+ let _ = format!("{:?}", UnencryptedEncoder);
+ }
+
+ #[test]
+ fn unencrypted_encoder_error() {
+ let _ = format!("{:?}", UnencryptedEncodeError::InvalidLength);
+ }
+
+ #[test]
+ fn ldt_encoder_display() {
+ let identity_token = V0IdentityToken::from([0x33; 14]);
+ let salt = V0Salt::from([0x01, 0x02]);
+ let key_seed = [0xFE; 32];
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
+ let ldt_encoder = LdtEncoder::<CryptoProviderImpl>::new(salt, &broadcast_cred);
+
+ // doesn't leak crypto material
+ assert_eq!("LdtEncoder { salt: V0Salt { bytes: [1, 2] } }", format!("{:?}", ldt_encoder));
+ }
+
+ #[test]
+ fn ldt_encoder_error() {
+ // debug, clone
+ let _ = format!("{:?}", LdtEncodeError::InvalidLength.clone());
+ }
+
+ #[test]
+ fn add_data_element_error() {
+ // debug
+ let _ = format!("{:?}", AddDataElementError::InsufficientAdvSpace);
+ }
+
+ #[test]
+ fn adv_builder() {
+ // debug
+ let _ = format!("{:?}", AdvBuilder::new(UnencryptedEncoder));
+ }
+}
diff --git a/nearby/presence/np_adv/src/lib.rs b/nearby/presence/np_adv/src/lib.rs
index 0b6d7ae..eb2ef0f 100644
--- a/nearby/presence/np_adv/src/lib.rs
+++ b/nearby/presence/np_adv/src/lib.rs
@@ -21,56 +21,37 @@
#![no_std]
#![allow(clippy::expect_used, clippy::indexing_slicing, clippy::panic)]
-use crate::{
- credential::{
- book::CredentialBook, v0::V0DiscoveryCryptoMaterial, v0::V0, v1::V1DiscoveryCryptoMaterial,
- v1::V1, DiscoveryCryptoMaterial, MatchedCredential, ProtocolVersion,
- ReferencedMatchedCredential,
- },
- deserialization_arena::ArenaOutOfSpace,
- extended::deserialize::{
- encrypted_section::*, parse_sections, CiphertextSection, DataElementParseError,
- DataElementParsingIterator, DecryptedSection, IntermediateSection, PlaintextSection,
- Section, SectionDeserializeError,
- },
- legacy::deserialize::{
- DecryptError, DecryptedAdvContents, IntermediateAdvContents, PlaintextAdvContents,
- },
-};
-
#[cfg(any(test, feature = "alloc"))]
extern crate alloc;
-#[cfg(any(test, feature = "alloc"))]
-use alloc::vec::Vec;
-use array_vec::ArrayVecOption;
-#[cfg(feature = "devtools")]
-use array_view::ArrayView;
+pub use strum;
+
+use crate::credential::matched::MatchedCredential;
+use crate::extended::deserialize::{deser_decrypt_v1, V1AdvertisementContents};
+use crate::{
+ credential::book::CredentialBook,
+ header::NpVersionHeader,
+ legacy::{deser_decrypt_v0, V0AdvertisementContents},
+};
use core::fmt::Debug;
use crypto_provider::CryptoProvider;
-use deserialization_arena::{DeserializationArena, DeserializationArenaAllocator};
-#[cfg(feature = "devtools")]
-use extended::NP_ADV_MAX_SECTION_LEN;
-use extended::NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT;
-use legacy::{data_elements::DataElementDeserializeError, deserialize::AdvDeserializeError};
-use nom::{combinator, number};
-pub use strum;
+use deserialization_arena::DeserializationArena;
+use legacy::data_elements::DataElementDeserializeError;
-mod array_vec;
-pub mod credential;
-pub mod de_type;
-#[cfg(test)]
-mod deser_v0_tests;
#[cfg(test)]
-mod deser_v1_tests;
+mod tests;
+
+pub mod credential;
pub mod deserialization_arena;
pub mod extended;
pub mod filter;
-#[cfg(test)]
-mod header_parse_tests;
pub mod legacy;
pub mod shared_data;
+mod array_vec;
+mod header;
+mod helpers;
+
/// Canonical form of NP's service UUID.
///
/// Note that UUIDs are encoded in BT frames in little-endian order, so these bytes may need to be
@@ -88,358 +69,18 @@ where
B: CredentialBook<'cred>,
P: CryptoProvider,
{
- let (remaining, header) =
- parse_adv_header(adv).map_err(|_e| AdvDeserializationError::HeaderParseError)?;
+ let (remaining, header) = NpVersionHeader::parse(adv)
+ .map_err(|_e| AdvDeserializationError::VersionHeaderParseError)?;
match header {
- AdvHeader::V0 => {
- deser_decrypt_v0::<B, P>(cred_book, remaining).map(DeserializedAdvertisement::V0)
- }
- AdvHeader::V1(header) => deser_decrypt_v1::<B, P>(arena, cred_book, remaining, header)
- .map(DeserializedAdvertisement::V1),
- }
-}
-
-/// The encryption scheme used for a V1 advertisement.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum V1EncryptionScheme {
- /// Indicates MIC-based encryption and verification.
- Mic,
- /// Indicates signature-based encryption and verification.
- Signature,
-}
-
-/// Error in decryption operations for `deser_decrypt_v1_section_bytes_for_dev_tools`.
-#[cfg(feature = "devtools")]
-#[derive(Debug, Clone)]
-pub enum AdvDecryptionError {
- /// Cannot decrypt because the input section is not encrypted.
- InputNotEncrypted,
- /// Error parsing the given section.
- ParseError,
- /// No suitable credential found to decrypt the given section.
- NoMatchingCredentials,
-}
-
-/// Decrypt, but do not further deserialize the v1 bytes, intended for developer tooling uses only.
-/// Production uses should use [deserialize_advertisement] instead, which deserializes to a
-/// structured format and provides extra type safety.
-#[cfg(feature = "devtools")]
-pub fn deser_decrypt_v1_section_bytes_for_dev_tools<'adv, 'cred, B, P>(
- arena: DeserializationArena<'adv>,
- cred_book: &'cred B,
- header_byte: u8,
- section_bytes: &'adv [u8],
-) -> Result<(ArrayView<u8, NP_ADV_MAX_SECTION_LEN>, V1EncryptionScheme), AdvDecryptionError>
-where
- B: CredentialBook<'cred>,
- P: CryptoProvider,
-{
- let header = V1Header { header_byte };
- let int_sections =
- parse_sections(header, section_bytes).map_err(|_| AdvDecryptionError::ParseError)?;
- let cipher_section = match &int_sections[0] {
- IntermediateSection::Plaintext(_) => Err(AdvDecryptionError::InputNotEncrypted)?,
- IntermediateSection::Ciphertext(section) => section,
- };
-
- let mut allocator = arena.into_allocator();
- for (crypto_material, _) in cred_book.v1_iter() {
- if let Some(plaintext) = cipher_section
- .try_resolve_identity_and_decrypt::<_, P>(&mut allocator, &crypto_material)
- {
- let pt = plaintext.expect(concat!(
- "Should not run out of space because DeserializationArenaAllocator is big ",
- "enough to hold a single advertisement, and we exit immediately upon ",
- "successful decryption",
- ));
-
- let encryption_scheme = match cipher_section {
- CiphertextSection::SignatureEncryptedIdentity(_) => V1EncryptionScheme::Signature,
- CiphertextSection::MicEncryptedIdentity(_) => V1EncryptionScheme::Mic,
- };
- return Ok((pt, encryption_scheme));
- }
- }
- Err(AdvDecryptionError::NoMatchingCredentials)
-}
-
-/// A ciphertext section which has not yet been
-/// resolved to an identity, but for which some
-/// `SectionIdentityResolutionContents` have been
-/// pre-computed for speedy identity-resolution.
-struct ResolvableCiphertextSection<'a> {
- identity_resolution_contents: SectionIdentityResolutionContents,
- ciphertext_section: CiphertextSection<'a>,
-}
-
-/// A collection of possibly-deserialized sections which are separated according
-/// to whether/not they're intermediate encrypted sections (of either type)
-/// or fully-deserialized, with a running count of the number of malformed sections.
-/// Each potentially-valid section is tagged with a 0-based index derived from the original
-/// section ordering as they appeared within the original advertisement to ensure
-/// that the fully-deserialized advertisement may be correctly reconstructed.
-struct SectionsInProcessing<'adv, M: MatchedCredential> {
- deserialized_sections: ArrayVecOption<
- (usize, V1DeserializedSection<'adv, M>),
- { NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT },
- >,
- encrypted_sections: ArrayVecOption<
- (usize, ResolvableCiphertextSection<'adv>),
- { NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT },
- >,
- malformed_sections_count: usize,
-}
-
-impl<'adv, M: MatchedCredential> SectionsInProcessing<'adv, M> {
- /// Attempts to parse a V1 advertisement's contents after the version header
- /// into a collection of not-yet-fully-deserialized sections which may
- /// require credentials to be decrypted.
- fn from_advertisement_contents<C: CryptoProvider>(
- header: V1Header,
- remaining: &'adv [u8],
- ) -> Result<Self, AdvDeserializationError> {
- let int_sections =
- parse_sections(header, remaining).map_err(|_| AdvDeserializationError::ParseError {
- details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError,
- })?;
- let mut deserialized_sections = ArrayVecOption::default();
- let mut encrypted_sections = ArrayVecOption::default();
- // keep track of ordering for later sorting during `self.finished_with_decryption_attempts()`.
- for (idx, s) in int_sections.into_iter().enumerate() {
- match s {
- IntermediateSection::Plaintext(p) => {
- deserialized_sections.push((idx, V1DeserializedSection::Plaintext(p)))
- }
- IntermediateSection::Ciphertext(ciphertext_section) => {
- let identity_resolution_contents =
- ciphertext_section.contents().compute_identity_resolution_contents::<C>();
- let resolvable_ciphertext_section = ResolvableCiphertextSection {
- identity_resolution_contents,
- ciphertext_section,
- };
- encrypted_sections.push((idx, resolvable_ciphertext_section));
- }
- }
- }
- Ok(Self { deserialized_sections, encrypted_sections, malformed_sections_count: 0 })
- }
-
- /// Returns true iff we have resolved all sections to identities.
- fn resolved_all_identities(&self) -> bool {
- self.encrypted_sections.is_empty()
- }
-
- /// Runs through all of the encrypted sections in processing, and attempts
- /// to use the given credential to decrypt them. Suitable for situations
- /// where iterating over credentials is relatively slow compared to
- /// the cost of iterating over sections-in-memory.
- fn try_decrypt_with_credential<C: V1DiscoveryCryptoMaterial, P: CryptoProvider>(
- &mut self,
- arena: &mut DeserializationArenaAllocator<'adv>,
- crypto_material: C,
- match_data: M,
- ) -> Result<(), ArenaOutOfSpace> {
- let mut i = 0;
- while i < self.encrypted_sections.len() {
- let (section_idx, section): &(usize, ResolvableCiphertextSection) =
- &self.encrypted_sections[i];
- // Fast-path: Check for an identity match, ignore if there's no identity match.
- let identity_resolution_contents = &section.identity_resolution_contents;
- let identity_resolution_material = match &section.ciphertext_section {
- CiphertextSection::MicEncryptedIdentity(_) => crypto_material
- .unsigned_identity_resolution_material::<P>()
- .into_raw_resolution_material(),
- CiphertextSection::SignatureEncryptedIdentity(_) => crypto_material
- .signed_identity_resolution_material::<P>()
- .into_raw_resolution_material(),
- };
- match identity_resolution_contents.try_match::<P>(&identity_resolution_material) {
- None => {
- // Try again with another section
- i += 1;
- continue;
- }
- Some(identity_match) => {
- // The identity matched, so now we need to more closely scrutinize
- // the provided ciphertext. Try to decrypt and parse the section.
- let metadata_nonce = crypto_material.metadata_nonce::<P>();
- let deserialization_result = match &section.ciphertext_section {
- CiphertextSection::SignatureEncryptedIdentity(c) => c
- .try_deserialize(
- arena,
- identity_match,
- &crypto_material.signed_verification_material::<P>(),
- )
- .map_err(SectionDeserializeError::from),
- CiphertextSection::MicEncryptedIdentity(c) => c
- .try_deserialize(
- arena,
- identity_match,
- &crypto_material.unsigned_verification_material::<P>(),
- )
- .map_err(SectionDeserializeError::from),
- };
- match deserialization_result {
- Ok(s) => {
- self.deserialized_sections.push((
- *section_idx,
- V1DeserializedSection::Decrypted(WithMatchedCredential::new(
- match_data.clone(),
- metadata_nonce,
- s,
- )),
- ));
- }
- Err(e) => match e {
- SectionDeserializeError::IncorrectCredential => {
- // keep it around to try with another credential
- i += 1;
- continue;
- }
- SectionDeserializeError::ParseError => {
- // the credential worked, but the section itself was bogus
- self.malformed_sections_count += 1;
- }
- SectionDeserializeError::ArenaOutOfSpace => {
- return Err(ArenaOutOfSpace)
- }
- },
- }
- // By default, if we have an identity match, assume that decrypting the section worked,
- // or that the section was somehow invalid.
- // We don't care about maintaining order, so use O(1) remove
- let _ = self.encrypted_sections.swap_remove(i);
- // don't advance i -- it now points to a new element
- }
- }
+ NpVersionHeader::V0(encoding) => deser_decrypt_v0::<B, P>(encoding, cred_book, remaining)
+ .map(DeserializedAdvertisement::V0),
+ NpVersionHeader::V1(header) => {
+ deser_decrypt_v1::<B, P>(arena, cred_book, remaining, header)
+ .map(DeserializedAdvertisement::V1)
}
- Ok(())
- }
-
- /// Packages the current state of the deserialization process into a
- /// `V1AdvertisementContents` representing a fully-deserialized V1 advertisement.
- ///
- /// This method should only be called after all sections were either successfully
- /// decrypted or have had all relevant credentials checked against
- /// them without obtaining a successful identity-match and/or subsequent
- /// cryptographic verification of the section contents.
- fn finished_with_decryption_attempts(mut self) -> V1AdvertisementContents<'adv, M> {
- // Invalid sections = malformed sections + number of encrypted sections
- // which we could not manage to decrypt with any of our credentials
- let invalid_sections_count = self.malformed_sections_count + self.encrypted_sections.len();
-
- // Put the deserialized sections back into the original ordering for
- // the returned `V1AdvertisementContents`
- // (Note: idx is unique, so unstable sort is ok)
- self.deserialized_sections.sort_unstable_by_key(|(idx, _section)| *idx);
- let ordered_sections = self.deserialized_sections.into_iter().map(|(_idx, s)| s).collect();
- V1AdvertisementContents::new(ordered_sections, invalid_sections_count)
}
}
-/// Deserialize and decrypt the contents of a v1 adv after the version header
-fn deser_decrypt_v1<'adv, 'cred, B, P>(
- arena: DeserializationArena<'adv>,
- cred_book: &'cred B,
- remaining: &'adv [u8],
- header: V1Header,
-) -> Result<V1AdvertisementContents<'adv, B::Matched>, AdvDeserializationError>
-where
- B: CredentialBook<'cred>,
- P: CryptoProvider,
-{
- let mut sections_in_processing =
- SectionsInProcessing::<'_, B::Matched>::from_advertisement_contents::<P>(
- header, remaining,
- )?;
-
- let mut allocator = arena.into_allocator();
-
- // Hot loop
- // We assume that iterating credentials is more expensive than iterating sections
- for (crypto_material, match_data) in cred_book.v1_iter() {
- sections_in_processing
- .try_decrypt_with_credential::<_, P>(&mut allocator, crypto_material, match_data)
- .expect(concat!(
- "Should not run out of space because DeserializationArenaAllocator is big ",
- "enough to hold a single advertisement, and we exit immediately upon ",
- "successful decryption",
- ));
- if sections_in_processing.resolved_all_identities() {
- // No need to consider the other credentials
- break;
- }
- }
- Ok(sections_in_processing.finished_with_decryption_attempts())
-}
-
-/// Deserialize and decrypt the contents of a v0 adv after the version header
-fn deser_decrypt_v0<'adv, 'cred, B, P>(
- cred_book: &'cred B,
- remaining: &'adv [u8],
-) -> Result<V0AdvertisementContents<'adv, B::Matched>, AdvDeserializationError>
-where
- B: CredentialBook<'cred>,
- P: CryptoProvider,
-{
- let contents = legacy::deserialize::deserialize_adv_contents::<P>(remaining)?;
- match contents {
- IntermediateAdvContents::Plaintext(p) => Ok(V0AdvertisementContents::Plaintext(p)),
- IntermediateAdvContents::Ciphertext(c) => {
- for (crypto_material, matched) in cred_book.v0_iter() {
- let ldt = crypto_material.ldt_adv_cipher::<P>();
- match c.try_decrypt(&ldt) {
- Ok(c) => {
- let metadata_nonce = crypto_material.metadata_nonce::<P>();
- return Ok(V0AdvertisementContents::Decrypted(WithMatchedCredential::new(
- matched,
- metadata_nonce,
- c,
- )));
- }
- Err(e) => match e {
- DecryptError::DecryptOrVerifyError => continue,
- DecryptError::DeserializeError(e) => {
- return Err(e.into());
- }
- },
- }
- }
- Ok(V0AdvertisementContents::NoMatchingCredentials)
- }
- }
-}
-
-/// Parse a NP advertisement header.
-///
-/// This can be used on all versions of advertisements since it's the header that determines the
-/// version.
-///
-/// Returns a `nom::IResult` with the parsed header and the remaining bytes of the advertisement.
-fn parse_adv_header(adv: &[u8]) -> nom::IResult<&[u8], AdvHeader> {
- // header bits: VVVxxxxx
- let (remaining, (header_byte, version, _low_bits)) = combinator::verify(
- // splitting a byte at a bit boundary to take lower 5 bits
- combinator::map(number::complete::u8, |byte| (byte, byte >> 5, byte & 0x1F)),
- |&(_header_byte, version, low_bits)| match version {
- // reserved bits, for any version, must be zero
- PROTOCOL_VERSION_LEGACY | PROTOCOL_VERSION_EXTENDED => low_bits == 0,
- _ => false,
- },
- )(adv)?;
- match version {
- PROTOCOL_VERSION_LEGACY => Ok((remaining, AdvHeader::V0)),
- PROTOCOL_VERSION_EXTENDED => Ok((remaining, AdvHeader::V1(V1Header { header_byte }))),
- _ => unreachable!(),
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub(crate) enum AdvHeader {
- V0,
- V1(V1Header),
-}
-
/// An NP advertisement with its header parsed.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq)]
@@ -470,219 +111,11 @@ impl<'adv, M: MatchedCredential> DeserializedAdvertisement<'adv, M> {
}
}
-/// The contents of a deserialized and decrypted V1 advertisement.
-#[derive(Debug, PartialEq, Eq)]
-pub struct V1AdvertisementContents<'adv, M: MatchedCredential> {
- sections: ArrayVecOption<V1DeserializedSection<'adv, M>, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT>,
- invalid_sections: usize,
-}
-
-impl<'adv, M: MatchedCredential> V1AdvertisementContents<'adv, M> {
- fn new(
- sections: ArrayVecOption<
- V1DeserializedSection<'adv, M>,
- NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT,
- >,
- invalid_sections: usize,
- ) -> Self {
- Self { sections, invalid_sections }
- }
-
- /// Destructures this V1 advertisement into just the sections
- /// which could be successfully deserialized and decrypted
- pub fn into_sections(
- self,
- ) -> ArrayVecOption<V1DeserializedSection<'adv, M>, NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT> {
- self.sections
- }
-
- /// The sections that could be successfully deserialized and decrypted
- pub fn sections(&self) -> impl ExactSizeIterator<Item = &V1DeserializedSection<M>> {
- self.sections.iter()
- }
-
- /// The number of sections that could not be parsed or decrypted.
- pub fn invalid_sections_count(&self) -> usize {
- self.invalid_sections
- }
-}
-
-/// Advertisement content that was either already plaintext or has been decrypted.
-#[derive(Debug, PartialEq, Eq)]
-pub enum V0AdvertisementContents<'adv, M: MatchedCredential> {
- /// Contents of an originally plaintext advertisement
- Plaintext(PlaintextAdvContents<'adv>),
- /// Contents that was ciphertext in the original advertisement, and has been decrypted
- /// with the credential in the [MatchedCredential]
- Decrypted(WithMatchedCredential<M, DecryptedAdvContents>),
- /// The advertisement was encrypted, but no credentials matched
- NoMatchingCredentials,
-}
-
-/// Advertisement content that was either already plaintext or has been decrypted.
-#[derive(Debug, PartialEq, Eq)]
-pub enum V1DeserializedSection<'adv, M: MatchedCredential> {
- /// Section that was plaintext in the original advertisement
- Plaintext(PlaintextSection<'adv>),
- /// Section that was ciphertext in the original advertisement, and has been decrypted
- /// with the credential in the [MatchedCredential]
- Decrypted(WithMatchedCredential<M, DecryptedSection<'adv>>),
-}
-
-impl<'adv, M> Section<'adv, DataElementParseError> for V1DeserializedSection<'adv, M>
-where
- M: MatchedCredential,
-{
- type Iterator = DataElementParsingIterator<'adv>;
-
- fn iter_data_elements(&self) -> Self::Iterator {
- match self {
- V1DeserializedSection::Plaintext(p) => p.iter_data_elements(),
- V1DeserializedSection::Decrypted(d) => d.contents.iter_data_elements(),
- }
- }
-}
-
-/// 16-byte metadata keys, as employed for metadata decryption.
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
-pub struct MetadataKey(pub [u8; 16]);
-
-impl AsRef<[u8]> for MetadataKey {
- fn as_ref(&self) -> &[u8] {
- &self.0
- }
-}
-
-/// Common trait to deserialized, decrypted V0 advs and V1 sections which
-/// exposes relevant data about matched identities.
-pub trait HasIdentityMatch {
- /// The protocol version for which this advertisement
- /// content has an identity-match.
- type Version: ProtocolVersion;
-
- /// Gets the decrypted plaintext version-specific
- /// metadata key for the associated identity.
- fn metadata_key(&self) -> <Self::Version as ProtocolVersion>::MetadataKey;
-}
-
-impl HasIdentityMatch for legacy::ShortMetadataKey {
- type Version = V0;
- fn metadata_key(&self) -> Self {
- *self
- }
-}
-
-impl HasIdentityMatch for MetadataKey {
- type Version = V1;
- fn metadata_key(&self) -> Self {
- *self
- }
-}
-
-#[cfg(any(test, feature = "alloc"))]
-/// Type for errors from [`WithMatchedCredential#decrypt_metadata`]
-#[derive(Debug)]
-pub enum MatchedMetadataDecryptionError<M: MatchedCredential> {
- /// Retrieving the encrypted metadata failed for one reason
- /// or another, so we didn't get a chance to try decryption.
- RetrievalFailed(<M as MatchedCredential>::EncryptedMetadataFetchError),
- /// The encrypted metadata could be retrieved, but it did
- /// not successfully decrypt against the matched identity.
- /// This could be an indication of data corruption or
- /// of malformed crypto on the sender-side.
- DecryptionFailed,
-}
-
-/// Decrypted advertisement content with the [MatchedCredential] from the credential that decrypted
-/// it, along with any other information which is relevant to the identity-match.
-#[derive(Debug, PartialEq, Eq)]
-pub struct WithMatchedCredential<M: MatchedCredential, T: HasIdentityMatch> {
- matched: M,
- /// The 12-byte metadata nonce as derived from the key-seed HKDF
- /// to be used for decrypting the encrypted metadata in the attached
- /// matched-credential.
- metadata_nonce: [u8; 12],
- contents: T,
-}
-impl<'a, M: MatchedCredential + Clone, T: HasIdentityMatch>
- WithMatchedCredential<ReferencedMatchedCredential<'a, M>, T>
-{
- /// Clones the referenced match-data to update this container
- /// so that the match-data is owned, rather than borrowed.
- pub fn clone_match_data(self) -> WithMatchedCredential<M, T> {
- let matched = self.matched.as_ref().clone();
- let metadata_nonce = self.metadata_nonce;
- let contents = self.contents;
-
- WithMatchedCredential { matched, metadata_nonce, contents }
- }
-}
-impl<M: MatchedCredential, T: HasIdentityMatch> WithMatchedCredential<M, T> {
- fn new(matched: M, metadata_nonce: [u8; 12], contents: T) -> Self {
- Self { matched, metadata_nonce, contents }
- }
- /// Applies the given function to the wrapped contents, yielding
- /// a new instance with the same matched-credential.
- pub fn map<R: HasIdentityMatch>(
- self,
- mapping: impl FnOnce(T) -> R,
- ) -> WithMatchedCredential<M, R> {
- let contents = mapping(self.contents);
- let matched = self.matched;
- let metadata_nonce = self.metadata_nonce;
- WithMatchedCredential { matched, metadata_nonce, contents }
- }
- /// Credential data for the credential that decrypted the content.
- pub fn matched_credential(&self) -> &M {
- &self.matched
- }
- /// The decrypted advertisement content.
- pub fn contents(&self) -> &T {
- &self.contents
- }
-
- #[cfg(any(test, feature = "alloc"))]
- fn decrypt_metadata_from_fetch<C: CryptoProvider>(
- &self,
- encrypted_metadata: &[u8],
- ) -> Result<Vec<u8>, MatchedMetadataDecryptionError<M>> {
- let metadata_key = self.contents.metadata_key();
- <<T as HasIdentityMatch>::Version as ProtocolVersion>::decrypt_metadata::<C>(
- self.metadata_nonce,
- metadata_key,
- encrypted_metadata,
- )
- .map_err(|_| MatchedMetadataDecryptionError::DecryptionFailed)
- }
-
- #[cfg(any(test, feature = "alloc"))]
- /// Attempts to decrypt the encrypted metadata
- /// associated with the matched credential
- /// based on the details of the identity-match.
- pub fn decrypt_metadata<C: CryptoProvider>(
- &self,
- ) -> Result<Vec<u8>, MatchedMetadataDecryptionError<M>> {
- self.matched
- .fetch_encrypted_metadata()
- .map_err(|e| MatchedMetadataDecryptionError::RetrievalFailed(e))
- .and_then(|x| Self::decrypt_metadata_from_fetch::<C>(self, x.as_ref()))
- }
-}
-
-/// Data in a V1 advertisement header.
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub(crate) struct V1Header {
- header_byte: u8,
-}
-
-const PROTOCOL_VERSION_LEGACY: u8 = 0;
-const PROTOCOL_VERSION_EXTENDED: u8 = 1;
-
/// Errors that can occur during advertisement deserialization.
#[derive(PartialEq)]
pub enum AdvDeserializationError {
/// The advertisement header could not be parsed
- HeaderParseError,
+ VersionHeaderParseError,
/// The advertisement content could not be parsed
ParseError {
/// Potentially hazardous details about deserialization errors. Read the documentation for
@@ -694,7 +127,9 @@ pub enum AdvDeserializationError {
impl Debug for AdvDeserializationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
- AdvDeserializationError::HeaderParseError => write!(f, "HeaderParseError"),
+ AdvDeserializationError::VersionHeaderParseError => {
+ write!(f, "VersionHeaderParseError")
+ }
AdvDeserializationError::ParseError { .. } => write!(f, "ParseError"),
}
}
@@ -710,37 +145,24 @@ pub enum AdvDeserializationErrorDetailsHazmat {
AdvertisementDeserializeError,
/// Deserializing an individual DE from its DE contents failed
V0DataElementDeserializeError(DataElementDeserializeError),
- /// Must not have any other top level data elements if there is an encrypted identity DE
- TooManyTopLevelDataElements,
- /// Must not have an identity DE inside an identity DE
- InvalidDataElementHierarchy,
- /// Must have an identity DE
- MissingIdentity,
/// Non-identity DE contents must not be empty
NoPublicDataElements,
}
-impl From<AdvDeserializeError> for AdvDeserializationError {
- fn from(err: AdvDeserializeError) -> Self {
+impl From<legacy::deserialize::AdvDeserializeError> for AdvDeserializationError {
+ fn from(err: legacy::deserialize::AdvDeserializeError) -> Self {
match err {
- AdvDeserializeError::AdvertisementDeserializeError => {
+ legacy::deserialize::AdvDeserializeError::NoDataElements => {
AdvDeserializationError::ParseError {
- details_hazmat:
- AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError,
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::NoPublicDataElements,
}
}
- AdvDeserializeError::TooManyTopLevelDataElements => {
+ legacy::deserialize::AdvDeserializeError::InvalidStructure => {
AdvDeserializationError::ParseError {
details_hazmat:
- AdvDeserializationErrorDetailsHazmat::TooManyTopLevelDataElements,
+ AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError,
}
}
- AdvDeserializeError::MissingIdentity => AdvDeserializationError::ParseError {
- details_hazmat: AdvDeserializationErrorDetailsHazmat::MissingIdentity,
- },
- AdvDeserializeError::NoPublicDataElements => AdvDeserializationError::ParseError {
- details_hazmat: AdvDeserializationErrorDetailsHazmat::NoPublicDataElements,
- },
}
}
}
@@ -750,15 +172,8 @@ impl From<AdvDeserializeError> for AdvDeserializationError {
#[derive(Debug, PartialEq, Eq)]
pub struct DeLengthOutOfRange;
-/// The identity mode for a deserialized plaintext section or advertisement.
-#[derive(PartialEq, Eq, Debug, Clone, Copy)]
-pub enum PlaintextIdentityMode {
- /// A "Public Identity" DE was present in the section
- Public,
+pub(crate) mod private {
+ /// A marker trait to prevent other crates from implementing traits that
+ /// are intended to be only implemented internally.
+ pub trait Sealed {}
}
-
-/// A "public identity" -- a nonspecific "empty identity".
-///
-/// Used when serializing V0 advertisements or V1 sections.
-#[derive(Default, Debug)]
-pub struct PublicIdentity;
diff --git a/nearby/presence/np_adv/src/shared_data.rs b/nearby/presence/np_adv/src/shared_data.rs
index b511ed2..c7d241b 100644
--- a/nearby/presence/np_adv/src/shared_data.rs
+++ b/nearby/presence/np_adv/src/shared_data.rs
@@ -16,7 +16,7 @@
/// Power in dBm, calibrated as per
/// [Eddystone](https://github.com/google/eddystone/tree/master/eddystone-uid#tx-power)
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct TxPower {
/// Power in `[-100, 20]`
power: i8,
@@ -42,7 +42,7 @@ impl TryFrom<i8> for TxPower {
}
/// Tx power was out of the valid range `[-100, 20]`.
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
pub struct TxPowerOutOfRange;
/// MDP's context sync number, used to inform other devices that they have stale context.
@@ -73,5 +73,33 @@ impl TryFrom<u8> for ContextSyncSeqNum {
}
/// Seq num must be in `[0-15]`.
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
pub struct ContextSyncSeqNumOutOfRange;
+
+#[allow(clippy::unwrap_used)]
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn tx_power_out_of_range() {
+ assert_eq!(TxPowerOutOfRange, TxPower::try_from(-101).unwrap_err());
+ assert_eq!(TxPowerOutOfRange, TxPower::try_from(21).unwrap_err());
+ }
+
+ #[test]
+ fn tx_power_ok() {
+ assert_eq!(-100, TxPower::try_from(-100).unwrap().power);
+ assert_eq!(20, TxPower::try_from(20).unwrap().power);
+ }
+
+ #[test]
+ fn context_sync_seq_num_out_of_range() {
+ assert_eq!(ContextSyncSeqNumOutOfRange, ContextSyncSeqNum::try_from(0x10).unwrap_err());
+ }
+
+ #[test]
+ fn context_sync_seq_num_ok() {
+ assert_eq!(0x0F, ContextSyncSeqNum::try_from(0x0F).unwrap().num);
+ }
+}
diff --git a/nearby/presence/np_adv/src/tests.rs b/nearby/presence/np_adv/src/tests.rs
new file mode 100644
index 0000000..eaa7ced
--- /dev/null
+++ b/nearby/presence/np_adv/src/tests.rs
@@ -0,0 +1,16 @@
+// 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.
+
+mod deser_v0_tests;
+pub(crate) mod deser_v1_tests;
diff --git a/nearby/presence/np_adv/src/deser_v0_tests.rs b/nearby/presence/np_adv/src/tests/deser_v0_tests.rs
index f6643de..b9dc6a8 100644
--- a/nearby/presence/np_adv/src/deser_v0_tests.rs
+++ b/nearby/presence/np_adv/src/tests/deser_v0_tests.rs
@@ -18,34 +18,30 @@ use rand::{seq::SliceRandom as _, SeedableRng as _};
extern crate std;
+use crate::credential::matched::{EmptyMatchedCredential, HasIdentityMatch, MatchedCredential};
+use crate::credential::MatchableCredential;
+use crate::legacy::serialize::UnencryptedEncoder;
use crate::{
credential::{
book::{CredentialBook, CredentialBookBuilder},
- v0::{V0DiscoveryCredential, V0},
- EmptyMatchedCredential, MatchableCredential, MatchedCredential,
- SimpleBroadcastCryptoMaterial,
+ v0::{V0BroadcastCredential, V0DiscoveryCredential, V0},
},
- de_type::EncryptedIdentityDataElementType,
deserialization_arena,
deserialization_arena::DeserializationArena,
deserialize_advertisement,
legacy::{
- actions::{ActionBits, ActionsDataElement, ToActionElement},
- data_elements::DataElement,
- deserialize::PlainDataElement,
- serialize::{AdvBuilder, Identity, LdtIdentity},
- ShortMetadataKey, BLE_ADV_SVC_CONTENT_LEN,
+ data_elements::actions::{ActionBits, ActionsDataElement},
+ deserialize::DeserializedDataElement,
+ serialize::{AdvBuilder, AdvEncoder, LdtEncoder},
+ BLE_4_ADV_SVC_MAX_CONTENT_LEN,
},
- shared_data::ContextSyncSeqNum,
- HasIdentityMatch, PlaintextIdentityMode, PublicIdentity, V0AdvertisementContents,
+ V0AdvertisementContents,
};
use array_view::ArrayView;
-use core::marker::PhantomData;
use crypto_provider::CryptoProvider;
use crypto_provider_default::CryptoProviderImpl;
-use ldt_np_adv::LegacySalt;
+use ldt_np_adv::{V0IdentityToken, V0Salt, V0_IDENTITY_TOKEN_LEN};
use std::{prelude::rust_2021::*, vec};
-use strum::IntoEnumIterator as _;
#[test]
fn v0_all_identities_resolvable() {
@@ -58,7 +54,7 @@ fn v0_all_identities_resolvable() {
let creds = identities
.iter()
.map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
+ discovery_credential: i.discovery_credential::<CryptoProviderImpl>(),
match_data: EmptyMatchedCredential,
})
.collect::<Vec<_>>();
@@ -87,7 +83,7 @@ fn v0_only_non_matching_identities_available() {
!adv_config.identity.map(|sci| sci.key_seed == i.key_seed).unwrap_or(false)
})
.map(|i| MatchableCredential {
- discovery_credential: i.discovery_credential(),
+ discovery_credential: i.discovery_credential::<CryptoProviderImpl>(),
match_data: EmptyMatchedCredential,
})
.collect::<Vec<_>>();
@@ -146,13 +142,11 @@ fn assert_adv_equals<M: MatchedCredential + AsRef<EmptyMatchedCredential>>(
match adv_config.identity {
None => match adv {
V0AdvertisementContents::Plaintext(p) => {
- let mut action_bits = ActionBits::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(3).unwrap());
+ let action_bits = ActionBits::default();
let de = ActionsDataElement::from(action_bits);
- assert_eq!(adv_config.plaintext_mode.unwrap(), p.identity());
assert_eq!(
- vec![PlainDataElement::Actions(de)],
+ vec![DeserializedDataElement::Actions(de)],
p.data_elements().collect::<Result<Vec<_>, _>>().unwrap()
)
}
@@ -160,24 +154,17 @@ fn assert_adv_equals<M: MatchedCredential + AsRef<EmptyMatchedCredential>>(
},
Some(_) => match adv {
V0AdvertisementContents::Decrypted(wmc) => {
- assert!(adv_config.plaintext_mode.is_none());
-
// different generic type param, so can't re-use the DE from above
- let mut action_bits = ActionBits::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(3).unwrap());
+ let action_bits = ActionBits::default();
let de = ActionsDataElement::from(action_bits);
assert_eq!(
- vec![PlainDataElement::Actions(de)],
+ vec![DeserializedDataElement::Actions(de)],
wmc.contents().data_elements().collect::<Result<Vec<_>, _>>().unwrap()
);
assert_eq!(
- adv_config.identity.unwrap().identity_type,
- wmc.contents().identity_type()
- );
- assert_eq!(
- adv_config.identity.unwrap().legacy_metadata_key,
- wmc.contents().metadata_key()
+ adv_config.identity.unwrap().identity_token,
+ wmc.contents().identity_token()
);
}
_ => panic!("should be an encrypted adv"),
@@ -203,92 +190,70 @@ where
/// Populate an advertisement with a randomly chosen identity and a DE
fn adv_random_identity<'a, R: rand::Rng>(
mut rng: &mut R,
- identities: &'a Vec<TestIdentity<CryptoProviderImpl>>,
-) -> (ArrayView<u8, { BLE_ADV_SVC_CONTENT_LEN }>, AdvConfig<'a>) {
+ identities: &'a Vec<TestIdentity>,
+) -> (ArrayView<u8, { BLE_4_ADV_SVC_MAX_CONTENT_LEN }>, AdvConfig<'a>) {
let identity = identities.choose(&mut rng).unwrap();
if rng.gen_bool(0.5) {
- let mut adv_builder = AdvBuilder::new(PublicIdentity);
+ let mut adv_builder = AdvBuilder::new(UnencryptedEncoder);
add_de(&mut adv_builder);
- (
- adv_builder.into_advertisement().unwrap(),
- AdvConfig::new(None, Some(PlaintextIdentityMode::Public)),
- )
+ (adv_builder.into_advertisement().unwrap(), AdvConfig::new(None))
} else {
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(
- identity.key_seed,
- identity.legacy_metadata_key,
- );
- let mut adv_builder = AdvBuilder::new(LdtIdentity::<CryptoProviderImpl>::new(
- identity.identity_type,
- LegacySalt::from(rng.gen::<[u8; 2]>()),
- &broadcast_cm,
+ let broadcast_cred = V0BroadcastCredential::new(identity.key_seed, identity.identity_token);
+ let mut adv_builder = AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new(
+ V0Salt::from(rng.gen::<[u8; 2]>()),
+ &broadcast_cred,
));
add_de(&mut adv_builder);
- (adv_builder.into_advertisement().unwrap(), AdvConfig::new(Some(identity), None))
+ (adv_builder.into_advertisement().unwrap(), AdvConfig::new(Some(identity)))
}
}
-fn add_de<I>(adv_builder: &mut AdvBuilder<I>)
+fn add_de<E>(adv_builder: &mut AdvBuilder<E>)
where
- I: Identity,
- ActionsDataElement<I::Flavor>: DataElement,
- ContextSyncSeqNum: ToActionElement<I::Flavor>,
+ E: AdvEncoder,
{
- let mut action_bits = ActionBits::default();
- action_bits.set_action(ContextSyncSeqNum::try_from(3).unwrap());
+ let action_bits = ActionBits::default();
let de = ActionsDataElement::from(action_bits);
adv_builder.add_data_element(de).unwrap();
}
-struct TestIdentity<C: CryptoProvider> {
- identity_type: EncryptedIdentityDataElementType,
+struct TestIdentity {
key_seed: [u8; 32],
- legacy_metadata_key: ShortMetadataKey,
- _marker: PhantomData<C>,
+ identity_token: V0IdentityToken,
}
-impl<C: CryptoProvider> TestIdentity<C> {
+impl TestIdentity {
/// Generate a new identity with random crypto material
fn random<R: rand::Rng + rand::CryptoRng>(rng: &mut R) -> Self {
Self {
- identity_type: *EncryptedIdentityDataElementType::iter()
- .collect::<Vec<_>>()
- .choose(rng)
- .unwrap(),
key_seed: rng.gen(),
- legacy_metadata_key: ShortMetadataKey(rng.gen()),
- _marker: PhantomData,
+ identity_token: rng.gen::<[u8; V0_IDENTITY_TOKEN_LEN]>().into(),
}
}
/// Returns a discovery-credential using crypto material from this identity
- fn discovery_credential(&self) -> V0DiscoveryCredential {
- let hkdf = self.hkdf();
+ fn discovery_credential<C: CryptoProvider>(&self) -> V0DiscoveryCredential {
+ let hkdf = self.hkdf::<C>();
V0DiscoveryCredential::new(
self.key_seed,
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&self.legacy_metadata_key.0),
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<C>(&self.identity_token.bytes()),
)
}
- fn hkdf(&self) -> np_hkdf::NpKeySeedHkdf<C> {
+ fn hkdf<C: CryptoProvider>(&self) -> np_hkdf::NpKeySeedHkdf<C> {
np_hkdf::NpKeySeedHkdf::new(&self.key_seed)
}
}
struct AdvConfig<'a> {
/// `Some` iff an encrypted identity should be used
- identity: Option<&'a TestIdentity<CryptoProviderImpl>>,
- /// `Some` iff `identity` is `None`
- plaintext_mode: Option<PlaintextIdentityMode>,
+ identity: Option<&'a TestIdentity>,
}
impl<'a> AdvConfig<'a> {
- fn new(
- identity: Option<&'a TestIdentity<CryptoProviderImpl>>,
- plaintext_mode: Option<PlaintextIdentityMode>,
- ) -> Self {
- Self { identity, plaintext_mode }
+ fn new(identity: Option<&'a TestIdentity>) -> Self {
+ Self { identity }
}
}
diff --git a/nearby/presence/np_adv/src/tests/deser_v1_tests.rs b/nearby/presence/np_adv/src/tests/deser_v1_tests.rs
new file mode 100644
index 0000000..d0865c7
--- /dev/null
+++ b/nearby/presence/np_adv/src/tests/deser_v1_tests.rs
@@ -0,0 +1,485 @@
+// 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.
+
+#![allow(clippy::unwrap_used)]
+
+extern crate std;
+
+use std::{prelude::rust_2021::*, vec};
+
+use rand::{
+ distributions::{Distribution, Standard},
+ random,
+ rngs::StdRng,
+ Rng, SeedableRng as _,
+};
+
+use array_view::ArrayView;
+use crypto_provider::{ed25519, CryptoRng};
+use crypto_provider_default::CryptoProviderImpl;
+use np_hkdf::v1_salt::ExtendedV1Salt;
+
+use crate::{
+ credential::{book::*, matched::*, v0::*, v1::*, *},
+ extended::{
+ data_elements::GenericDataElement,
+ deserialize::{data_element::DataElement, section::intermediate::PlaintextSection, *},
+ salt::MultiSalt,
+ serialize::*,
+ *,
+ },
+ *,
+};
+
+mod happy_path;
+
+mod error_condition;
+
+impl<'adv, M: MatchedCredential> V1DeserializedSection<'adv, M> {
+ fn as_plaintext_section(&self) -> &PlaintextSection {
+ match self {
+ V1DeserializedSection::Plaintext(c) => c,
+ V1DeserializedSection::Decrypted(_) => {
+ panic!("Casting into invalid enum variant")
+ }
+ }
+ }
+
+ fn as_ciphertext_section(&self) -> &WithMatchedCredential<M, DecryptedSection<'adv>> {
+ match self {
+ V1DeserializedSection::Plaintext(_) => panic!("Casting into invalid enum variant"),
+ V1DeserializedSection::Decrypted(wmc) => wmc,
+ }
+ }
+}
+
+fn assert_section_equals(
+ section_config: &SectionConfig,
+ section: &V1DeserializedSection<
+ ReferencedMatchedCredential<MetadataMatchedCredential<Vec<u8>>>,
+ >,
+) {
+ match &section_config.identity_kind {
+ IdentityKind::Plaintext => {
+ let plaintext_section = section.as_plaintext_section();
+ assert_eq!(
+ section_config.data_elements,
+ plaintext_section
+ .iter_data_elements()
+ .map(|de| (&de.unwrap()).into())
+ .collect::<Vec<_>>()
+ )
+ }
+ IdentityKind::Encrypted { verification_mode, identity } => {
+ let enc_section = section.as_ciphertext_section();
+
+ let decrypted_metadata = enc_section.decrypt_metadata::<CryptoProviderImpl>().unwrap();
+ assert_eq!(&identity.plaintext_metadata, &decrypted_metadata);
+
+ let expected_contents =
+ section_config.data_elements.clone().iter().fold(Vec::new(), |mut buf, de| {
+ buf.extend_from_slice(de.de_header().serialize().as_slice());
+ de.write_de_contents(&mut buf).unwrap();
+ buf
+ });
+ let contents = enc_section.contents();
+ assert_eq!(&expected_contents, contents.plaintext());
+
+ assert_eq!(
+ section_config.data_elements,
+ contents
+ .iter_data_elements()
+ .map(|de| (&de.unwrap()).into())
+ .collect::<Vec<GenericDataElement>>()
+ );
+ assert_eq!(&identity.identity_token, enc_section.contents().identity_token());
+ assert_eq!(verification_mode, &enc_section.contents().verification_mode());
+ }
+ }
+}
+
+fn deser_v1_error<'a, B, P>(
+ arena: DeserializationArena<'a>,
+ adv: &'a [u8],
+ cred_book: &'a B,
+) -> AdvDeserializationError
+where
+ B: CredentialBook<'a>,
+ P: CryptoProvider,
+{
+ let v1_contents = match crate::deserialize_advertisement::<_, P>(arena, adv, cred_book) {
+ Err(e) => e,
+ _ => panic!("Expecting an error!"),
+ };
+ v1_contents
+}
+
+fn deser_v1<'adv, B, P>(
+ arena: DeserializationArena<'adv>,
+ adv: &'adv [u8],
+ cred_book: &'adv B,
+) -> V1AdvertisementContents<'adv, B::Matched>
+where
+ B: CredentialBook<'adv>,
+ P: CryptoProvider,
+{
+ crate::deserialize_advertisement::<_, P>(arena, adv, cred_book)
+ .expect("Should be a valid advertisement")
+ .into_v1()
+ .expect("Should be V1")
+}
+
+fn build_empty_cred_book() -> PrecalculatedOwnedCredentialBook<EmptyMatchedCredential> {
+ PrecalculatedOwnedCredentialBook::new(
+ PrecalculatedOwnedCredentialSource::<V0, EmptyMatchedCredential>::new::<CryptoProviderImpl>(
+ Vec::new(),
+ ),
+ PrecalculatedOwnedCredentialSource::<V1, EmptyMatchedCredential>::new::<CryptoProviderImpl>(
+ Vec::new(),
+ ),
+ )
+}
+
+/// Populate a random number of sections with randomly chosen identities and random DEs
+fn fill_plaintext_adv<'a, R: rand::Rng>(
+ rng: &mut R,
+ adv_builder: &mut AdvBuilder,
+) -> SectionConfig<'a> {
+ adv_builder
+ .section_builder(UnencryptedSectionEncoder)
+ .map(|mut s| {
+ let mut sink = Vec::new();
+ // plaintext sections cannot be empty so we need to be sure at least 1 DE is generated
+ let (_, des) = fill_section_random_des::<_, _, 1>(rng, &mut sink, &mut s);
+ s.add_to_advertisement::<CryptoProviderImpl>();
+ SectionConfig::new(IdentityKind::Plaintext, des)
+ })
+ .unwrap()
+}
+
+impl Distribution<VerificationMode> for Standard {
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> VerificationMode {
+ match rng.gen_range(0..=2) {
+ 0 => VerificationMode::Signature,
+ _ => VerificationMode::Mic,
+ }
+ }
+}
+
+pub(crate) fn add_sig_rand_salt_to_adv<'a, R: rand::Rng, C: CryptoProvider, const M: usize>(
+ rng: &mut R,
+ identity: &'a TestIdentity,
+ adv_builder: &mut AdvBuilder,
+) -> Result<SectionConfig<'a>, AddSectionError> {
+ let salt: ExtendedV1Salt = rng.gen::<[u8; 16]>().into();
+ add_sig_with_salt_to_adv::<_, C, M>(rng, identity, adv_builder, salt.into())
+}
+
+fn add_sig_with_salt_to_adv<'a, R: rand::Rng, C: CryptoProvider, const M: usize>(
+ rng: &mut R,
+ identity: &'a crate::tests::deser_v1_tests::TestIdentity,
+ adv_builder: &mut AdvBuilder,
+ salt: MultiSalt,
+) -> Result<crate::tests::deser_v1_tests::SectionConfig<'a>, AddSectionError> {
+ let broadcast_cred = identity.broadcast_credential();
+ let salt = match salt {
+ MultiSalt::Short(_) => {
+ panic!("Invalid salt type for signature encrpted adv")
+ }
+ MultiSalt::Extended(e) => e,
+ };
+ adv_builder.section_builder(SignedEncryptedSectionEncoder::new::<C>(salt, &broadcast_cred)).map(
+ |mut s| {
+ let mut sink = Vec::new();
+ let (_, des) = fill_section_random_des::<_, _, M>(rng, &mut sink, &mut s);
+ s.add_to_advertisement::<C>();
+ SectionConfig::new(
+ IdentityKind::Encrypted {
+ verification_mode: VerificationMode::Signature,
+ identity,
+ },
+ des,
+ )
+ },
+ )
+}
+
+pub(crate) fn add_mic_rand_salt_to_adv<'a, R: rand::Rng, C: CryptoProvider, const M: usize>(
+ rng: &mut R,
+ identity: &'a TestIdentity,
+ adv_builder: &mut AdvBuilder,
+) -> Result<SectionConfig<'a>, AddSectionError> {
+ let salt = if rng.gen_bool(0.5) {
+ MultiSalt::Short(rng.gen::<[u8; 2]>().into())
+ } else {
+ MultiSalt::Extended(rng.gen::<[u8; 16]>().into())
+ };
+
+ add_mic_with_salt_to_adv::<_, C, M>(rng, identity, adv_builder, salt)
+}
+
+pub(crate) fn add_mic_with_salt_to_adv<'a, R: rand::Rng, C: CryptoProvider, const M: usize>(
+ rng: &mut R,
+ identity: &'a TestIdentity,
+ adv_builder: &mut AdvBuilder,
+ salt: MultiSalt,
+) -> Result<crate::tests::deser_v1_tests::SectionConfig<'a>, AddSectionError> {
+ let broadcast_cred = identity.broadcast_credential();
+ adv_builder
+ .section_builder(MicEncryptedSectionEncoder::<_>::new_with_salt::<C>(salt, &broadcast_cred))
+ .map(|mut s| {
+ let mut sink = Vec::new();
+ let (_, des) = fill_section_random_des::<_, _, M>(rng, &mut sink, &mut s);
+ s.add_to_advertisement::<C>();
+ SectionConfig::new(
+ IdentityKind::Encrypted { verification_mode: VerificationMode::Mic, identity },
+ des,
+ )
+ })
+}
+
+/// Populate a random number of sections with randomly chosen identities and random DEs
+fn fill_with_encrypted_sections<'a, R: rand::Rng, C: CryptoProvider>(
+ mut rng: &mut R,
+ identities: &'a TestIdentities,
+ adv_builder: &mut AdvBuilder,
+) -> Vec<SectionConfig<'a>> {
+ let mut expected = Vec::new();
+ for _ in 0..rng.gen_range(1..=NP_V1_ADV_MAX_ENCRYPTED_SECTION_COUNT) {
+ let identity = identities.pick_random_identity(&mut rng);
+ let mode: VerificationMode = random();
+ let res = match mode {
+ VerificationMode::Signature => {
+ add_sig_rand_salt_to_adv::<_, C, 0>(&mut rng, identity, adv_builder)
+ }
+ VerificationMode::Mic => {
+ add_mic_rand_salt_to_adv::<_, C, 0>(&mut rng, identity, adv_builder)
+ }
+ };
+ match res {
+ Ok(tuple) => expected.push(tuple),
+ Err(_) => {
+ // couldn't fit that section; maybe another smaller section will fit
+ continue;
+ }
+ }
+ }
+ expected
+}
+
+#[derive(Clone)]
+pub(crate) struct TestIdentity {
+ key_seed: [u8; 32],
+ identity_token: V1IdentityToken,
+ private_key: ed25519::PrivateKey,
+ plaintext_metadata: Vec<u8>,
+}
+
+impl TestIdentity {
+ /// Generate a new identity with random crypto material
+ fn random<R: rand::Rng, C: CryptoProvider>(rng: &mut R) -> Self {
+ Self {
+ key_seed: rng.gen(),
+ identity_token: rng.gen(),
+ private_key: ed25519::PrivateKey::generate::<C::Ed25519>(),
+ // varying length vec of random bytes
+ plaintext_metadata: (0..rng.gen_range(50..200)).map(|_| rng.gen()).collect(),
+ }
+ }
+ /// Returns a (simple, signed) broadcast credential using crypto material from this identity
+ fn broadcast_credential(&self) -> V1BroadcastCredential {
+ V1BroadcastCredential::new(self.key_seed, self.identity_token, self.private_key.clone())
+ }
+ /// Returns a discovery credential using crypto material from this identity
+ fn discovery_credential<C: CryptoProvider>(&self) -> V1DiscoveryCredential {
+ self.broadcast_credential().derive_discovery_credential::<C>()
+ }
+}
+
+pub(crate) struct SectionConfig<'a> {
+ identity_kind: IdentityKind<'a>,
+ data_elements: Vec<GenericDataElement>,
+}
+
+pub(crate) enum IdentityKind<'a> {
+ Plaintext,
+ Encrypted { verification_mode: VerificationMode, identity: &'a TestIdentity },
+}
+
+impl<'a> SectionConfig<'a> {
+ pub fn new(identity_kind: IdentityKind<'a>, data_elements: Vec<GenericDataElement>) -> Self {
+ Self { identity_kind, data_elements }
+ }
+}
+
+/// Returns the DEs created in both deserialized form ([DataElement]) and
+/// input form ([GenericDataElement]) where `M` is the minimum number of DE's
+/// generated
+fn fill_section_random_des<'adv, R: rand::Rng, I: SectionEncoder, const M: usize>(
+ mut rng: &mut R,
+ sink: &'adv mut Vec<u8>,
+ section_builder: &mut SectionBuilder<&mut AdvBuilder, I>,
+) -> (Vec<DataElement<'adv>>, Vec<GenericDataElement>) {
+ let mut expected_des = vec![];
+ let mut orig_des = vec![];
+ let mut de_ranges = vec![];
+
+ for _ in 0..rng.gen_range(M..=5) {
+ let de = random_de::<MAX_DE_LEN, _>(&mut rng);
+
+ let de_clone = de.clone();
+ if section_builder.add_de(|_| de_clone).is_err() {
+ break;
+ }
+
+ let orig_len = sink.len();
+ de.write_de_contents(sink).unwrap();
+ let contents_len = sink.len() - orig_len;
+ de_ranges.push(orig_len..orig_len + contents_len);
+ orig_des.push(de);
+ }
+
+ for (index, (de, range)) in orig_des.iter().zip(de_ranges).enumerate() {
+ expected_des.push(DataElement::new(
+ u8::try_from(index).unwrap().into(),
+ de.de_header().de_type,
+ &sink[range],
+ ));
+ }
+ (expected_des, orig_des)
+}
+
+/// generates a random DE, where `N` is the max length size of the DE
+fn random_de<const N: usize, R: rand::Rng>(rng: &mut R) -> GenericDataElement {
+ let mut array = [0_u8; MAX_DE_LEN];
+ rng.fill(&mut array[..]);
+ let data: ArrayView<u8, MAX_DE_LEN> =
+ ArrayView::try_from_array(array, rng.gen_range(0..=MAX_DE_LEN)).unwrap();
+ // skip the first few DEs that Google uses
+ GenericDataElement::try_from(rng.gen_range(0_u32..1000).into(), data.as_slice()).unwrap()
+}
+
+#[derive(Clone)]
+pub(crate) struct TestIdentities(pub(crate) Vec<TestIdentity>);
+
+impl TestIdentities {
+ pub(crate) fn generate<const N: usize, R: rand::Rng, C: CryptoProvider>(
+ rng: &mut R,
+ ) -> TestIdentities {
+ TestIdentities((0..N).map(|_| TestIdentity::random::<_, C>(rng)).collect::<Vec<_>>())
+ }
+
+ fn pick_random_identity<R: rand::Rng>(&self, rng: &mut R) -> &TestIdentity {
+ let chosen_index = rng.gen_range(0..self.0.len());
+ &self.0[chosen_index]
+ }
+
+ pub(crate) fn build_cred_book<C: CryptoProvider>(
+ &self,
+ ) -> PrecalculatedOwnedCredentialBook<MetadataMatchedCredential<Vec<u8>>> {
+ let creds = self
+ .0
+ .iter()
+ .map(|identity| {
+ let match_data = MetadataMatchedCredential::<Vec<u8>>::encrypt_from_plaintext::<
+ V1,
+ CryptoProviderImpl,
+ >(
+ &np_hkdf::NpKeySeedHkdf::new(&identity.key_seed),
+ identity.identity_token,
+ &identity.plaintext_metadata,
+ );
+ let discovery_credential = identity.discovery_credential::<C>();
+ MatchableCredential { discovery_credential, match_data }
+ })
+ .collect::<Vec<_>>();
+ let cred_source = PrecalculatedOwnedCredentialSource::new::<CryptoProviderImpl>(creds);
+ PrecalculatedOwnedCredentialBook::new(
+ PrecalculatedOwnedCredentialSource::<V0, MetadataMatchedCredential<Vec<u8>>>::new::<
+ CryptoProviderImpl,
+ >(Vec::new()),
+ cred_source,
+ )
+ }
+}
+
+fn deserialize_rand_identities_finds_correct_one<E, F>(
+ build_encoder: F,
+ expected_mode: VerificationMode,
+) where
+ E: SectionEncoder,
+ F: Fn(&mut <CryptoProviderImpl as CryptoProvider>::CryptoRng, &V1BroadcastCredential) -> E,
+{
+ let mut rng = StdRng::from_entropy();
+ let mut crypto_rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
+
+ for _ in 0..100 {
+ let identities = TestIdentities::generate::<100, _, CryptoProviderImpl>(&mut rng);
+ let identity = identities.pick_random_identity(&mut rng);
+ let book = identities.build_cred_book::<CryptoProviderImpl>();
+
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+
+ let broadcast_cm = identity.broadcast_credential();
+ let mut section_builder =
+ adv_builder.section_builder(build_encoder(&mut crypto_rng, &broadcast_cm)).unwrap();
+
+ let mut expected_de_data = vec![];
+ let (expected_des, orig_des) = fill_section_random_des::<_, _, 0>(
+ &mut rng,
+ &mut expected_de_data,
+ &mut section_builder,
+ );
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
+
+ let section_config = SectionConfig::new(
+ IdentityKind::Encrypted { verification_mode: expected_mode, identity },
+ orig_des.clone(),
+ );
+
+ let adv = adv_builder.into_advertisement();
+
+ let arena = deserialization_arena!();
+ let decrypted_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &book);
+ assert_eq!(0, decrypted_contents.invalid_sections_count());
+ let sections = decrypted_contents.into_sections();
+ assert_eq!(1, sections.len());
+
+ assert_section_equals(&section_config, &sections[0]);
+
+ // verify data elements match original after collecting them from the section
+ let data_elements =
+ sections[0].as_ciphertext_section().contents().collect_data_elements().unwrap();
+ assert_eq!(expected_des, data_elements);
+ }
+}
+
+fn add_plaintext_section<R: rand::Rng>(
+ rng: &mut R,
+ builder: &mut AdvBuilder,
+) -> Result<(), AddSectionError> {
+ builder.section_builder(UnencryptedSectionEncoder).map(|mut sb| {
+ // use an upper bound on the De size to leave room for another section
+ sb.add_de(|_| random_de::<20, _>(rng)).unwrap();
+ sb.add_to_advertisement::<CryptoProviderImpl>();
+ })
+}
+
+fn append_mock_encrypted_section(adv: &mut Vec<u8>) {
+ adv.push(0b0000_0001u8); // format
+ adv.extend_from_slice(&[0xAA; 2]); // short salt
+ adv.extend_from_slice(&[0xBB; 16]); // identity token
+ adv.push(3); // payload length
+ adv.extend_from_slice(&[0xCC; 3]); // payload contents
+}
diff --git a/nearby/presence/np_adv/src/tests/deser_v1_tests/error_condition.rs b/nearby/presence/np_adv/src/tests/deser_v1_tests/error_condition.rs
new file mode 100644
index 0000000..9f91dbd
--- /dev/null
+++ b/nearby/presence/np_adv/src/tests/deser_v1_tests/error_condition.rs
@@ -0,0 +1,257 @@
+// 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.
+
+use super::*;
+use crate::deserialization_arena;
+use rand::SeedableRng;
+
+#[test]
+fn v1_multiple_plaintext_sections() {
+ let mut rng = StdRng::from_entropy();
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ add_plaintext_section(&mut rng, &mut adv_builder).unwrap();
+
+ // append an extra plaintext section
+ let adv = [
+ adv_builder.into_advertisement().as_slice(),
+ &[
+ 0x00, // format unencrypted
+ 0x03, // section len
+ ],
+ &[0xDD; 3], // 3 bytes of de contents
+ ]
+ .concat();
+
+ let arena = deserialization_arena!();
+ let cred_book = build_empty_cred_book();
+ let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, &adv, &cred_book);
+ assert_eq!(
+ v1_error,
+ AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
+ }
+ );
+}
+
+#[test]
+fn v1_plaintext_empty_contents() {
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ let sb = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
+ sb.add_to_advertisement::<CryptoProviderImpl>();
+ let adv = adv_builder.into_advertisement();
+
+ let arena = deserialization_arena!();
+ let cred_book = build_empty_cred_book();
+ let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(
+ v1_error,
+ AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
+ }
+ );
+}
+
+#[test]
+fn v1_adv_no_sections() {
+ let mut rng = StdRng::from_entropy();
+ let identities = TestIdentities::generate::<5, _, CryptoProviderImpl>(&mut rng);
+ let adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let adv = adv_builder.into_advertisement();
+
+ let arena = deserialization_arena!();
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+
+ let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(
+ v1_error,
+ AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
+ }
+ );
+}
+
+#[test]
+fn v1_no_creds_available_ciphertext() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let identities = TestIdentities::generate::<100, _, CryptoProviderImpl>(&mut rng);
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let section_configs = fill_with_encrypted_sections::<_, CryptoProviderImpl>(
+ &mut rng,
+ &identities,
+ &mut adv_builder,
+ );
+ let adv = adv_builder.into_advertisement();
+
+ let cred_book = build_empty_cred_book();
+ let arena = deserialization_arena!();
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(section_configs.len(), v1_contents.invalid_sections_count());
+ assert_eq!(0, v1_contents.sections().len());
+ }
+}
+
+#[test]
+fn v1_only_non_matching_identities_available_ciphertext() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let mut identities = TestIdentities::generate::<100, _, CryptoProviderImpl>(&mut rng);
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let cloned_identities = identities.clone();
+ let section_configs = fill_with_encrypted_sections::<_, CryptoProviderImpl>(
+ &mut rng,
+ &cloned_identities,
+ &mut adv_builder,
+ );
+ let adv = adv_builder.into_advertisement();
+
+ // only retain identities in the book that haven't been used in the constructed adv sections
+ identities.0.retain(|identity| {
+ !section_configs.iter().any(|sc| match &sc.identity_kind {
+ IdentityKind::Plaintext => panic!("There are no plaintext sections"),
+ IdentityKind::Encrypted { identity: section_identity, verification_mode: _ } => {
+ identity.key_seed == section_identity.key_seed
+ }
+ })
+ });
+
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+ let arena = deserialization_arena!();
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(section_configs.len(), v1_contents.invalid_sections_count());
+ assert_eq!(0, v1_contents.sections().len());
+ }
+}
+
+// TODO: this may be valid in future changes and would need to be updated
+#[test]
+fn v1_plaintext_then_encrypted_sections() {
+ let mut rng = StdRng::from_entropy();
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ let identities = TestIdentities::generate::<5, _, CryptoProviderImpl>(&mut rng);
+
+ add_plaintext_section(&mut rng, &mut adv_builder).unwrap();
+ let mut adv = adv_builder.into_advertisement().as_slice().to_vec();
+ append_mock_encrypted_section(&mut adv);
+
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+ let arena = deserialization_arena!();
+
+ let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(
+ v1_error,
+ AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
+ }
+ );
+}
+
+#[test]
+fn v1_encrypted_then_plaintext_sections() {
+ let mut rng = StdRng::from_entropy();
+ let mut builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let identities = TestIdentities::generate::<1, _, CryptoProviderImpl>(&mut rng);
+
+ let _ = add_mic_rand_salt_to_adv::<_, CryptoProviderImpl, 0>(
+ &mut rng,
+ &identities.0[0],
+ &mut builder,
+ )
+ .unwrap();
+ let mut adv = builder.into_advertisement().as_slice().to_vec();
+
+ // Append plaintext section
+ adv.push(V1_ENCODING_UNENCRYPTED); //Header
+ adv.push(3); // section len
+ adv.extend_from_slice(&[0xFF; 3]); //section contents
+
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+ let arena = deserialization_arena!();
+
+ let v1_error = deser_v1_error::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(
+ v1_error,
+ AdvDeserializationError::ParseError {
+ details_hazmat: AdvDeserializationErrorDetailsHazmat::AdvertisementDeserializeError
+ }
+ );
+}
+
+#[test]
+fn v1_encrypted_matching_identity_but_mic_mismatch() {
+ for _ in 0..100 {
+ v1_deserialize_error_test_tampered_adv(
+ add_mic_rand_salt_to_adv::<StdRng, CryptoProviderImpl, 0>,
+ |adv| {
+ // mangle the last 2 bytes of the suffix to invalidate the advertisement.
+ // the identity should still correctly match
+ let adv_len = adv.len();
+ adv[adv_len - 2..].copy_from_slice(&[0xFF; 2]);
+ },
+ )
+ }
+}
+
+#[test]
+fn v1_encrypted_matching_identity_but_sig_mismatch() {
+ v1_deserialize_error_test_tampered_adv(
+ add_sig_rand_salt_to_adv::<StdRng, CryptoProviderImpl, 0>,
+ |adv| {
+ // mangle the last 2 bytes of the suffix to invalidate the advertisement.
+ // the identity should still correctly match
+ let adv_len = adv.len();
+ adv[adv_len - 2..].copy_from_slice(&[0xFF; 2]);
+ },
+ )
+}
+
+#[test]
+fn v1_encrypted_matching_identity_missing_signature() {
+ v1_deserialize_error_test_tampered_adv(
+ add_sig_rand_salt_to_adv::<StdRng, CryptoProviderImpl, 0>,
+ |adv| {
+ // only keep the last 63 byte bytes after the len, which is too short to fit a signature
+ // 1 byte header + 1 byte format + 16 byte salt + 16 byte token + 1 byte len + 63 bytes of contents
+ adv.truncate(1 + 1 + 16 + 16 + 1 + 63);
+ // modify the length byte to account for this otherwise this will fail to parse at all
+ // 1 byte header + 1 byte format + 16 byte salt + 16 byte token
+ let len_byte_index = 1 + 1 + 16 + 16;
+ adv[len_byte_index] = 63;
+ },
+ )
+}
+
+fn v1_deserialize_error_test_tampered_adv(
+ add_to_adv: impl for<'a> Fn(
+ &mut StdRng,
+ &'a TestIdentity,
+ &mut AdvBuilder,
+ ) -> Result<SectionConfig<'a>, AddSectionError>,
+ mangle_adv: impl Fn(&mut Vec<u8>),
+) {
+ let mut rng = StdRng::from_entropy();
+ let mut builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let identities = TestIdentities::generate::<1, _, CryptoProviderImpl>(&mut rng);
+
+ let _ = add_to_adv(&mut rng, &identities.0[0], &mut builder);
+ let mut adv = builder.into_advertisement().as_slice().to_vec();
+
+ mangle_adv(&mut adv);
+
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+ let arena = deserialization_arena!();
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(1, v1_contents.invalid_sections_count());
+ assert_eq!(0, v1_contents.sections().len());
+}
diff --git a/nearby/presence/np_adv/src/tests/deser_v1_tests/happy_path.rs b/nearby/presence/np_adv/src/tests/deser_v1_tests/happy_path.rs
new file mode 100644
index 0000000..2171bd6
--- /dev/null
+++ b/nearby/presence/np_adv/src/tests/deser_v1_tests/happy_path.rs
@@ -0,0 +1,227 @@
+// 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.
+
+extern crate std;
+
+use super::*;
+use crate::{deserialization_arena, extended::salt::*};
+use rand::SeedableRng;
+
+#[test]
+fn deserialize_rand_identities_single_section_finds_correct_one_mic_short_salt() {
+ deserialize_rand_identities_finds_correct_one(
+ |_rng, bc| {
+ let salt = ShortV1Salt::from([0x3; 2]);
+ MicEncryptedSectionEncoder::<_>::new_with_salt::<CryptoProviderImpl>(salt, bc)
+ },
+ VerificationMode::Mic,
+ )
+}
+
+#[test]
+fn deserialize_rand_identities_single_section_finds_correct_one_mic_extended_salt() {
+ deserialize_rand_identities_finds_correct_one(
+ |rng, bc| {
+ let salt: ExtendedV1Salt = rng.gen();
+ MicEncryptedSectionEncoder::<_>::new_with_salt::<CryptoProviderImpl>(salt, bc)
+ },
+ VerificationMode::Mic,
+ )
+}
+
+#[test]
+fn deserialize_rand_identities_single_section_finds_correct_one_signed() {
+ deserialize_rand_identities_finds_correct_one(
+ SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>,
+ VerificationMode::Signature,
+ )
+}
+
+#[test]
+fn v1_plaintext() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
+ let section_config = fill_plaintext_adv(&mut rng, &mut adv_builder);
+ let adv = adv_builder.into_advertisement();
+ let arena = deserialization_arena!();
+ let cred_book =
+ CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(&[], &[]);
+
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(0, v1_contents.invalid_sections_count());
+ assert_eq!(1, v1_contents.sections().len());
+ let sections = v1_contents.into_sections();
+ assert_section_equals(&section_config, &sections[0]);
+ }
+}
+
+#[test]
+fn v1_all_identities_resolvable_ciphertext() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let identities = TestIdentities::generate::<100, _, CryptoProviderImpl>(&mut rng);
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let section_configs = fill_with_encrypted_sections::<_, CryptoProviderImpl>(
+ &mut rng,
+ &identities,
+ &mut adv_builder,
+ );
+ let adv = adv_builder.into_advertisement();
+
+ let arena = deserialization_arena!();
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+ assert_eq!(0, v1_contents.invalid_sections_count());
+ assert_eq!(section_configs.len(), v1_contents.sections().len());
+ for (section_config, section) in section_configs.iter().zip(v1_contents.sections()) {
+ assert_section_equals(section_config, section);
+ }
+ }
+}
+
+#[test]
+fn v1_only_some_matching_identities_available_ciphertext() {
+ let mut rng = StdRng::from_entropy();
+ for _ in 0..100 {
+ let mut identities = TestIdentities::generate::<100, _, CryptoProviderImpl>(&mut rng);
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+ let cloned_identities = identities.clone();
+ let section_configs = fill_with_encrypted_sections::<_, CryptoProviderImpl>(
+ &mut rng,
+ &cloned_identities,
+ &mut adv_builder,
+ );
+ let adv = adv_builder.into_advertisement();
+
+ // Hopefully one day we can use extract_if instead: https://github.com/rust-lang/rust/issues/43244
+ let mut removed = vec![];
+ // Remove some of the identities which have been used to build the adv
+ identities.0.retain(|identity| {
+ let res = !section_configs.iter().any(|sc| match &sc.identity_kind {
+ IdentityKind::Plaintext => panic!("There are no plaintext sections"),
+ IdentityKind::Encrypted { identity: section_identity, verification_mode: _ } => {
+ // only remove half the identities that were used
+ (identity.key_seed == section_identity.key_seed) && rng.gen()
+ }
+ });
+ if !(res) {
+ removed.push(identity.clone());
+ }
+ res
+ });
+
+ // Need to account for how many sections were affected since the same identity could be used
+ // to encode multiple different sections
+ let affected_sections = section_configs
+ .iter()
+ .filter(|sc| match sc.identity_kind {
+ IdentityKind::Plaintext => {
+ panic!("There are no plaintext sections")
+ }
+ IdentityKind::Encrypted { identity: si, verification_mode: _ } => {
+ removed.iter().any(|i| i.key_seed == si.key_seed)
+ }
+ })
+ .count();
+
+ let arena = deserialization_arena!();
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+ let v1_contents = deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book);
+
+ assert_eq!(affected_sections, v1_contents.invalid_sections_count());
+ assert_eq!(section_configs.len() - affected_sections, v1_contents.sections().len());
+
+ for (section_config, section) in section_configs
+ .iter()
+ // skip sections w/ removed identities
+ .filter(|sc| match sc.identity_kind {
+ IdentityKind::Plaintext => {
+ panic!("There are no plaintext sections")
+ }
+ IdentityKind::Encrypted { identity: si, verification_mode: _ } => {
+ !removed.iter().any(|i| i.key_seed == si.key_seed)
+ }
+ })
+ .zip(v1_contents.sections())
+ {
+ assert_section_equals(section_config, section);
+ }
+ }
+}
+
+#[test]
+fn v1_decrypted_mic_short_salt_matches() {
+ let mut rng = StdRng::from_entropy();
+ let salt = MultiSalt::Short(rng.gen::<[u8; 2]>().into());
+ v1_decrypted_adv_salt_matches(
+ &mut rng,
+ salt,
+ add_mic_with_salt_to_adv::<_, CryptoProviderImpl, 0>,
+ );
+}
+
+#[test]
+fn v1_decrypted_mic_extended_salt_matches() {
+ let mut rng = StdRng::from_entropy();
+ let salt = MultiSalt::Extended(rng.gen::<[u8; 16]>().into());
+ v1_decrypted_adv_salt_matches(
+ &mut rng,
+ salt,
+ add_mic_with_salt_to_adv::<_, CryptoProviderImpl, 0>,
+ );
+}
+
+#[test]
+fn v1_decrypted_sig_extended_salt_matches() {
+ let mut rng = StdRng::from_entropy();
+ let salt = MultiSalt::Extended(rng.gen::<[u8; 16]>().into());
+ v1_decrypted_adv_salt_matches(
+ &mut rng,
+ salt,
+ add_sig_with_salt_to_adv::<_, CryptoProviderImpl, 0>,
+ );
+}
+
+fn v1_decrypted_adv_salt_matches(
+ rng: &mut StdRng,
+ salt: MultiSalt,
+ add_to_adv: impl for<'a> Fn(
+ &mut StdRng,
+ &'a TestIdentity,
+ &mut AdvBuilder,
+ MultiSalt,
+ ) -> Result<SectionConfig<'a>, AddSectionError>,
+) {
+ let identities = TestIdentities::generate::<1, _, CryptoProviderImpl>(rng);
+ let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
+
+ let _ = add_to_adv(rng, &identities.0[0], &mut adv_builder, salt);
+
+ let adv = adv_builder.into_advertisement();
+ let arena = deserialization_arena!();
+ let cred_book = identities.build_cred_book::<CryptoProviderImpl>();
+
+ let sections =
+ deser_v1::<_, CryptoProviderImpl>(arena, adv.as_slice(), &cred_book).into_sections();
+ let section = &sections[0];
+ let decrypted = match section {
+ V1DeserializedSection::Plaintext(_) => {
+ panic!("section is encrypted")
+ }
+ V1DeserializedSection::Decrypted(d) => d,
+ };
+ assert_eq!(salt, *decrypted.contents().salt())
+}
diff --git a/nearby/presence/np_adv/test.json b/nearby/presence/np_adv/test.json
deleted file mode 100644
index 953eebf..0000000
--- a/nearby/presence/np_adv/test.json
+++ /dev/null
@@ -1,24122 +0,0 @@
-[
- {
- "adv_header_byte": "30",
- "adv_salt": "8CDE04CBC59C9134F37B1FFBCF5C1136",
- "aes_key": "0C04AAE1338E928EA903CAF2FD806749",
- "data_elements": [
- {
- "contents": "3DF2D0883246D50B5C981ADB",
- "de_type": 163
- },
- {
- "contents": "5628511D93E01312D69F5484",
- "de_type": 317
- },
- {
- "contents": "C255FFF1D4F8501E3467B084BDD124DF26",
- "de_type": 721
- }
- ],
- "encoded_section": "69901356E7F8215A0B45D559EFD0EE88A6398B911000C807A0FFE7C79ABD61B1862AFBD097AF9001D042A9F585F02B4DE34C7412A717A08034ECDC1862BB599B6CD7CD3F95D191135555C01A0D1A71EBF2593213E9439552D625736E024EADFA950BA7B78D6AD844AD0A",
- "identity_type": "private",
- "iv": "2170459EF8C3E6DB3BFB808B62A5D03E",
- "key_seed": "43A340DE5AFC350888FB696FC77D8CB0467668F18E7EDCB8CC3AC2F59F075ACB",
- "metadata_key": "593580A4B65DEF1E6B117C8055CB6257",
- "section_mic_hmac_key": "CDB8526FA8BEC42B51495EEA23F347B2F8E07A757DF63FE9C5C9100E8EB39435",
- "section_salt": "C807A0FFE7C79ABD61B1862AFBD097AF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8630E9D33F2AB78558BB4AF5C09F4C9E",
- "aes_key": "E9FE3EF4069698F338256E23AAC08029",
- "data_elements": [
- {
- "contents": "C70548D64F0D131D8551D3C2B3",
- "de_type": 448
- },
- {
- "contents": "E4EAA94038A8B4A0D46C83695DABC05262C7DA5ED2395B673527C5C337",
- "de_type": 859
- }
- ],
- "encoded_section": "6790134C7B6E97BE50C21ADAEE4D5EC611313B911000A6C0ECE0A9D25663F329C6C218D07CB59004603C46143E88C0F872F341BE2C06FB4DF9ECF1A970CAFBCD5315C9D8389770E627D3C913690256AA8BD753910DBB4FEA57E8AC5125E5B906CA0E0DF17081F34D",
- "identity_type": "provisioned",
- "iv": "39201C314CBC2D3F88EE094E627E7ADC",
- "key_seed": "83FEF3C4A9E58DAA566F19AECC7C9CEE6EA4BA37F360EE8A40A26FBB99938F4B",
- "metadata_key": "90A529D185FE0105D76179ED5AC841C8",
- "section_mic_hmac_key": "8466111DFC334299442A84F91E3F6616C1023F2A29C72670C483F2445C18B75A",
- "section_salt": "A6C0ECE0A9D25663F329C6C218D07CB5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6FB3720F743A68E6474B1459990DFAC6",
- "aes_key": "A2E0437B429330BF82B8BA3B2B762770",
- "data_elements": [
- {
- "contents": "13851601256B24E7",
- "de_type": 404
- },
- {
- "contents": "82FAAF4977AE0B80EAAC",
- "de_type": 81
- },
- {
- "contents": "C9B19F78DDF6FD66AA623267E9656C2E1EEB9F0F8253B1041626",
- "de_type": 152
- },
- {
- "contents": "EFD96E20D81B0ACD",
- "de_type": 474
- },
- {
- "contents": "2120F35E2B9EB9D5027BDC",
- "de_type": 264
- }
- ],
- "encoded_section": "8490137D769DEFAA2E8B1BCD01332139B1F4F99110008F7DCA2DC4146183C14177A6F847468B90043E07B7A107CC2C88A183F2D8D5A6C4A6119DFCB0603F251F3994F0468C56F2014A98BEF0881B342F28E7E83B89EBB28E2E54D88B0AAFEB4FDE73F8C8D918E818ED997A0CFB3ED6344189D0A06F4FDD3F780FC6E87421578FF68B06E6E0",
- "identity_type": "provisioned",
- "iv": "52A7C3FC58494668CB193C7C583AB583",
- "key_seed": "D0B97B7B4CB8CF85A9E707ADD592E017BD7B3964F59801EA9A08DEB3E8A3EA47",
- "metadata_key": "6AF91918569B21EC14C90B099284EEED",
- "section_mic_hmac_key": "EA04A0F8FF46882A8B759E7E9D53CAAF2D847C393B5A47F6AA4284DA1BF8CF11",
- "section_salt": "8F7DCA2DC4146183C14177A6F847468B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6F144BE070388B857B001873992CA0EF",
- "aes_key": "0165985CBCA678350F250112E1354FCE",
- "data_elements": [
- {
- "contents": "B6D2CE67C704514BB9F370812B470A56BA4BDD",
- "de_type": 164
- },
- {
- "contents": "49DCA454994B399B9914768E457F",
- "de_type": 701
- },
- {
- "contents": "FBD41AC2FCBB9B47F6B04863B8139AE83A9AF049A137F2A766",
- "de_type": 466
- },
- {
- "contents": "73A400CB6E36EB45BD1AE7",
- "de_type": 172
- },
- {
- "contents": "1113B990D3D4B31D4CEEFB849F8CAFD01A82968A61",
- "de_type": 725
- }
- ],
- "encoded_section": "A09013988012579D82091B81D39640A1F4B47891100077789262A428CFE712797C28D85A644A90021BBE826D956C08B86149427A8EFA6D801523C348FA78AF09433AF1A947269D58CDCA26055838209A01615CB0FFD9C55234D2EF9805FCB1FF8ED66137B2DE6A8C34F57F6FAC98645D1C482E851C77BFB1ACBB5A22E2CA297BAD14CAD0C08E4C8424C7A6E683C7EE8392A091DD9217DD6E5396D3644F01EF3CAE",
- "identity_type": "trusted",
- "iv": "7BAE887BD9B8BE99864343D585848A63",
- "key_seed": "70CC58965C36307BE580E2793ACDC8D792FCFE8B17392B4F0B7A6ABC31D3CF02",
- "metadata_key": "E503087FCE974FEDCC3290C2ABC2AF15",
- "section_mic_hmac_key": "173560AC7513A51677C06801D39CE68B2E32F6BA7C02364800EF73AE27916ACC",
- "section_salt": "77789262A428CFE712797C28D85A644A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BD864BCB86CC4FAFA1DF15D05C693F70",
- "aes_key": "B7A853164A7D88165F7044725DE648FC",
- "data_elements": [
- {
- "contents": "B6A9A4926FEDFDE5D8D870BA06144690",
- "de_type": 175
- },
- {
- "contents": "B8C403AC879A7EBB6D69458D",
- "de_type": 720
- }
- ],
- "encoded_section": "5990139BE32BB50428F39C6510AB0BCAE0A4519110002542EBE3983FF77643536AF98A47BDFE9001D2EFF80C4D9A6391063A16F2E989F5C02424E527596A15A5E2424EEA7317214FEEC57E1C28E1F47C8BE40C43839BD6CC2EE1",
- "identity_type": "private",
- "iv": "F1411FAE6BBB7AF0F798EF7898C1A026",
- "key_seed": "15C3A38E12E82DE3D05867A72C09259B2F163E0F7E2B900013FD9589E4FCB08B",
- "metadata_key": "BEF599A91BB40E6A3A12D69AA8AA40D5",
- "section_mic_hmac_key": "B268F77855AAFA3A0AEC62CEF115FAF98C4616536512F7AD13EBAA17CC36237E",
- "section_salt": "2542EBE3983FF77643536AF98A47BDFE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4112B2B6BC0C275800AF30E221E029A",
- "aes_key": "CB3E8DA92E33B125E206698CCDDB4E17",
- "data_elements": [
- {
- "contents": "99A2BBD12EA3D487BA35A47215",
- "de_type": 374
- },
- {
- "contents": "3B4AD8B0AC9370A0DBECE41039A7C136D66AE40E251A274483E1E04B",
- "de_type": 322
- },
- {
- "contents": "3B5465ABD3AB9E51E37FE1825D19EBCB6D75",
- "de_type": 882
- },
- {
- "contents": "C3303DEB37C1CBF6F2D83CF60B5AAE7343",
- "de_type": 508
- },
- {
- "contents": "5AC15AF945563810514171B4D3CF13EB7CD056ED84CC4AD84E5C8C",
- "de_type": 734
- }
- ],
- "encoded_section": "AD9013C80618AEF0E93826CCBB9F1FC3CA1D2E911000BA4390D760820DE7D19BDD18E12105A99001E4F5385E499355B62DC8EB87A3B4B44BF0A799A099FF59F83CF7042DC080D469575ECB02FD8DC04FB60539411A4142E3386DDB945F456D90F6104B6D5893E7697CCB294A98597A07EDA2FA2A1B5C92DC85F720DCCC7B4F25639F1A8E912041148020E7EF5DBFDB6455C1DEF20F9B7A14218826843B218FA12FEC92D0AC0C0664304BF11B3962",
- "identity_type": "private",
- "iv": "E39A28DAC41BAE56D9C38A90DE18970E",
- "key_seed": "F8956985D12A7454C239C35BD7F5B98FED6987FE6097F27888DC942E9B4F5BAE",
- "metadata_key": "0DFAB0A1A5C1F1FB82F4E19C387EF630",
- "section_mic_hmac_key": "D52D92CED4F96F98A96CDE0CBCBA70D22D695FE28A792490C9EC8AD3D7C512E4",
- "section_salt": "BA4390D760820DE7D19BDD18E12105A9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8281FAD7EBE43124AD3E52A64BDFC08",
- "aes_key": "37FEED11494EC97655A7CDFAAFA0B332",
- "data_elements": [
- {
- "contents": "2FEB5C0E9CB50EA61479D2",
- "de_type": 182
- },
- {
- "contents": "",
- "de_type": 76
- },
- {
- "contents": "EDFE252EC0AF1BCF3203E68626BD87DC210591FB4087E5",
- "de_type": 186
- },
- {
- "contents": "F3B28EE0AA3540",
- "de_type": 53
- }
- ],
- "encoded_section": "6A901326C139F9297299F3291C4C5449667C1E9110001C4A655CE96B261144D0DC30EEB06E819001ED20997FF72B0145678564A0823492B38F82A2908345E56312025794BFAB4154F007A7B8B672F38D5D78E5E201BB839A44D8E5819E8EE1563FF02619DBB4F3179D5719",
- "identity_type": "private",
- "iv": "6DD5002B0EC75F051EC1C94C9C5BD7DC",
- "key_seed": "4E462ABDDDE34121284FE9958F24C16DBA38929E38A34F2019783CDAD5E08706",
- "metadata_key": "AFEB6946137C5F406D7849DBC57AEA66",
- "section_mic_hmac_key": "8C3FF0042FD0E1C4145EFCD9A7A84D636B6A58BE736B10AF391C72DB7B4CE6B7",
- "section_salt": "1C4A655CE96B261144D0DC30EEB06E81"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E64361FB1C8C7325B408FAEE1E49547A",
- "aes_key": "7BBC46B2F18B3D283060D0A697FD11CD",
- "data_elements": [
- {
- "contents": "9E4B0F0E1E5F8B4A48E6E85204B7B761BB77C2B8E9D87A",
- "de_type": 398
- },
- {
- "contents": "4DA86FD08563540F21F4D25BC7B6C8FFE5D0C256F695231A9758CB",
- "de_type": 536
- },
- {
- "contents": "0EF79DA8BA03209867C317EE62ED67FE793C10338A07C7509E5B394A",
- "de_type": 892
- },
- {
- "contents": "E5282DD8F645D9C437993F0B64E1C0126B51",
- "de_type": 44
- }
- ],
- "encoded_section": "A2901389A25CC355CD62CBE4A5003ACDF8EE059110002E283829FBEBE221CF9A1F91C1B0BD1D900171AB8293D624A4D2BE56FDE47583BBD8845F3855B25932CD6A1DCA7098797D301AFBFCF9A4A8A806E391C54F110D1B9D80A21CB9769249E819530E57270E20135F0406FC4C0BB0BBFB5EF126993AEE724E98B9E92A5B6992F8298B8C4FDC7D631588EAB84DD79BD92555DCD93E5FACC5EC36EB8B9F8DF0AB62F718",
- "identity_type": "private",
- "iv": "A926171CE5153CBD347A51C9978CE93F",
- "key_seed": "F36B60BF6F555557AA212FC62B5C02A13C9C2BA4DF41EDD5A72F16AE66D236AD",
- "metadata_key": "BB668D0081DBF606A285AD033DE92814",
- "section_mic_hmac_key": "91908BF2F777B922CC1CC476A770C7FCAECCE0DE0B2A8F95FE44D507024B93A2",
- "section_salt": "2E283829FBEBE221CF9A1F91C1B0BD1D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9DB5D8E94ABD7216DABD6C8F66C5F52F",
- "aes_key": "75EB4826F32F9F8B7328CB265FDE141A",
- "data_elements": [],
- "encoded_section": "379013542EB74608EA671B4B9C539D5DAC9E0B911000371E5AA6A854D8B34632AF62FB16F9E39002958BD9049E4B9D49DB40BFB15A1DEB0C",
- "identity_type": "trusted",
- "iv": "FE2F66ADC508DBE090043C56A1D4CC2F",
- "key_seed": "5694BC71EA736D6F1C9F9CB3F7359AF337754178D62E0CB2C8305813F7334036",
- "metadata_key": "D7DF4817E2E00574C1CF3B5BA51411C3",
- "section_mic_hmac_key": "B6CF96993547CD0B865BA29ACD9E7989CCA2A2CCFD940E81C97A613423F34D2B",
- "section_salt": "371E5AA6A854D8B34632AF62FB16F9E3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "815CAF890EB0DEA3D861BE22C7BE8485",
- "aes_key": "34D85A4581FF6A69DBBD8CD74D881E2A",
- "data_elements": [
- {
- "contents": "8E976835BD38B761F8F5C5E3",
- "de_type": 175
- }
- ],
- "encoded_section": "469013F70BA8EF34F0B010A6EDFF3E02486FFB91100057434E8D7DA6137D885EE4B43DA850B09001367A8D04108F605A363DDE7A55DBC6D28C92FE23A27E7D70FF072A469793CD",
- "identity_type": "private",
- "iv": "0F43CBDBB69194C72762C45B8A959AE2",
- "key_seed": "9DCDB616C7824FE6E29EDEE371A1F019AB9035DEA6A2FAEED01086EB7C7BA56E",
- "metadata_key": "386504600FDC6BB6D29B931F997569C3",
- "section_mic_hmac_key": "40CCE5D2E8BD439CE407FADC7D03C1E5E3EE7BDB2AE09C3DAEEDBCD383994AAC",
- "section_salt": "57434E8D7DA6137D885EE4B43DA850B0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "20AA489B07F54A47398F0D452085BA80",
- "aes_key": "70E8FE98FC7B2F2BAF0F571C5A6CA285",
- "data_elements": [
- {
- "contents": "895FC4C4D7C5327B823935153EE5",
- "de_type": 603
- }
- ],
- "encoded_section": "489013E548BFD8D8BF4BABE9BBA791575D88F0911000EA0BC8652F833AA286C9B67BDBEEFFDD90012C035FA41FD24BC9E2154A4A746EC39BD898F5AC0D626F6FDC9EC1625F4A6E0278",
- "identity_type": "private",
- "iv": "27675AE693055520D818FA2DF75BA1DD",
- "key_seed": "7BE2B5351B3AF721D834EFC7D92EDCFBB356CD30C149CFF13FFA6BB9E9EB4E9E",
- "metadata_key": "C51BF8A84C682176009DAFC96E45E52A",
- "section_mic_hmac_key": "63BB6F972081FE41233CC4657536A17D3DA9AC374FCCAAE4A390FBB9467E6B10",
- "section_salt": "EA0BC8652F833AA286C9B67BDBEEFFDD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E7BF03DDA652D45DE79BEC7C63C52888",
- "aes_key": "DEC78F8DAAD1135EDA4BA73CA2EDDE93",
- "data_elements": [
- {
- "contents": "CA",
- "de_type": 831
- },
- {
- "contents": "0681689828FE001F46FB",
- "de_type": 640
- },
- {
- "contents": "A0",
- "de_type": 925
- },
- {
- "contents": "6EF5787D1B7E",
- "de_type": 821
- }
- ],
- "encoded_section": "559013122F1A904EE013BF5054BD17CB565C7B911000BA917BAFABA916680B68E584D7B3C74F9002124726B3336C5A2E714BDA406F4ECAE6942867CFB87D060B7CA2B90E553A7980483C575AA8F669191B6652D622FF",
- "identity_type": "trusted",
- "iv": "5623FFAEE945A52FED893932E2C2831B",
- "key_seed": "EB421B623B6601022B06C3B84A805B0BECB369AC96BDDB227D35F720BB88E54D",
- "metadata_key": "481736D7E51E562209CB88D5098D7AB8",
- "section_mic_hmac_key": "73839ABE23D964F432D5109E0FD1AF2B7458ACA6C4FC8C81B00F17697ADC7140",
- "section_salt": "BA917BAFABA916680B68E584D7B3C74F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4F478C39E6822FD65B039A579058329",
- "aes_key": "942E583271C5BAB68F5A289F13B4AD3D",
- "data_elements": [
- {
- "contents": "6740DA0B7D7422B46668B2A4748EF1723D4740177B561E28",
- "de_type": 25
- },
- {
- "contents": "57673A8C3CA46CFBA015193726BA9D1B87C155F230",
- "de_type": 157
- },
- {
- "contents": "966C4FDAFD61602A93A588FCC9E9",
- "de_type": 997
- }
- ],
- "encoded_section": "7A9013E8068D3273AD4073892EC5B38DFE7A85911000F20408CF4792B57C5EAB5F364D498024900485D9D787000902A41BF9B32EBE0B9BC5457E424445793F00C68FF17BA783444CED2BC3DF3E7FD930C5D53A8FF8A279DBD838FEA95D0DB5047C90A20128D099424453872597B42EC79617D8460C78EFCDD06166",
- "identity_type": "provisioned",
- "iv": "97A725CAFF2ECB63466FC4FE92F1D93F",
- "key_seed": "3B1148D64481A45A5ED6A0C71204CE9EFBBBFB24772F4376D14A60809095A80C",
- "metadata_key": "E356AB5D0B7B4A162CFFB3DC9200B03E",
- "section_mic_hmac_key": "622F90CBC74C39F7E270CCFEDC73CC2501A788B6233CE65018C90D315EB1B5BC",
- "section_salt": "F20408CF4792B57C5EAB5F364D498024"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E3E029E6CCC13E76F6537200F6FE6609",
- "aes_key": "13395363678EB859D922B0AC513D569D",
- "data_elements": [
- {
- "contents": "E88903",
- "de_type": 1
- },
- {
- "contents": "9177F23C1703",
- "de_type": 498
- }
- ],
- "encoded_section": "449013DAEF852821B69637E7ECB1814AA11E6E911000C35F60118757A8DC6AC94A3145568E2C900258CBCB74090D6AEB5721940B6889ED4C3C225551A6693E6011097D84BD",
- "identity_type": "trusted",
- "iv": "FECC334DA28A05283126BB74D6D86328",
- "key_seed": "836FC0759CA3CBB83B1DC440AAC7EA8832723A1804CCF55FA82B3DE62CF6EF94",
- "metadata_key": "108F487561268EC3E2139081F2C18B93",
- "section_mic_hmac_key": "1FAB84D97BFBBA1E719918D561F9F49A7190014740FDD66FD6521884BF997D91",
- "section_salt": "C35F60118757A8DC6AC94A3145568E2C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ED9AB8CBA38B0378A57060CAEEB7DC37",
- "aes_key": "85016D4CE263E72594660319A4008F5C",
- "data_elements": [],
- "encoded_section": "37901315D82A68468424FC66C3F583A599E184911000484C4A72DC77F3D141DFD0251501313C900421DAA8789829C8B74D5A81CD5E003B97",
- "identity_type": "provisioned",
- "iv": "91A3EBC0493D70CC75CD52A15EDE7EE1",
- "key_seed": "DC9A2935DA138DBA468602F58BA4C10B2CA2073931C2CD76EB89BE9E0C62EC35",
- "metadata_key": "6B7B939EC1DFD9DFB28A5AF4834D9837",
- "section_mic_hmac_key": "A37F2450D25ECFEB5F5BA3B902280E75A8CD266E134AFA52489EC23247D191A0",
- "section_salt": "484C4A72DC77F3D141DFD0251501313C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AA01BEF21050FC2F2E10253E8D1C1976",
- "aes_key": "EC5750863DC5A63EE6C924204FDA7434",
- "data_elements": [
- {
- "contents": "C9FB1F10A5EECEB78957471B0E9F5DD4F6B378",
- "de_type": 843
- },
- {
- "contents": "4E43DF33AFBCD1D9659E19B0A90FCB04634B",
- "de_type": 419
- },
- {
- "contents": "4F3484030125E7350D12E9663A",
- "de_type": 51
- },
- {
- "contents": "",
- "de_type": 39
- },
- {
- "contents": "7604411E964954B0FC27",
- "de_type": 233
- }
- ],
- "encoded_section": "809013E0B47E9EE5B8805FAE10443E6B5463BF911000DB703DF2D395F42E99EA0544CF85C1F790025E4F401EDB54B36B8CBE582AA5BD19FE4C2671F43DAA3F4E1A060E06AE4A7922BB500BF7E27485959C1A3129450249D0909ABE0F1C34BCED066AFF0140262A2007FA37F2617803C68B429540B65383073558874972F06DE286",
- "identity_type": "trusted",
- "iv": "9B68EF8ED1D81A8E00D41A8EDF863F8B",
- "key_seed": "1D03BFEAD804837303B5363C8F089C79B3FAEC4D566803A636C8C566180D9587",
- "metadata_key": "3F72F934C211CFBDE074CCB0A54DCD50",
- "section_mic_hmac_key": "331F932E99A5D100F95C6DA9ABBDE9486649FA13D9F40B6075C678B1FD02E42F",
- "section_salt": "DB703DF2D395F42E99EA0544CF85C1F7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "75A2C0202C54B148B3A8325523E39AC4",
- "aes_key": "62C0EBC73039A209769197670BA21D32",
- "data_elements": [
- {
- "contents": "1053D13B0CD897",
- "de_type": 913
- },
- {
- "contents": "08D336BE6750FAADCC063556753748C6D80E7BFE3AA5016139DC9EE23054",
- "de_type": 385
- },
- {
- "contents": "CA9FA19B1A1D2662477670DBAC88B27E484B45A21A4EB0",
- "de_type": 78
- },
- {
- "contents": "150352672FC7AD44BA4F3AD0AE8F1FB86B342072982DCA44D8C028",
- "de_type": 246
- }
- ],
- "encoded_section": "9990130900396AEDFDC487B3C663EED8CEB672911000607C74788B6319F4BEB5D1B4CB02D7BD900118F1E3D46294A4BA21D910380DE516BE171072179B90364446BA39519AA03E30382BAD7560A891FFB6F72D1F17D6C6385762460985DCBBBF3C890F8AAE57BE0BBBA483917D4CCA0A6837669F7B00D710D0CC2E760E3E0B4903CDCF5AC83DE4CC1995FB93278C9E0EE2667A93387B1ADBA08C",
- "identity_type": "private",
- "iv": "F2C95E5EC2FA105C282643BA7C800549",
- "key_seed": "4B6810C7997D7DDE597C9268442CE989762AAD10290801679FF4594198DEA08B",
- "metadata_key": "83562D42E58C363E0E48127F1B3897B2",
- "section_mic_hmac_key": "43A0F588C743498AB2FC9BCEB915A1BCD353E02B9AB75CB952A6430C4D6C9062",
- "section_salt": "607C74788B6319F4BEB5D1B4CB02D7BD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "212440B8E8D36B2CC1327699BFC93206",
- "aes_key": "6A2AD6F934FAFA71982F6C4AA26A4F56",
- "data_elements": [],
- "encoded_section": "379013D5557C5A6CE2CAF81CE036A91EF70A3E9110009DC45FD603A6B020B509B8D9BFC969DB90041218B5589E2AB40D4B0B82061756E4DB",
- "identity_type": "provisioned",
- "iv": "F72C452B0E570EB5B9DE952C4791095A",
- "key_seed": "47B2C609DC4A2F6785197E6EA791FEAFF65BA00A43E5A18A677933ED15386ADA",
- "metadata_key": "8F209D0C0585905DF5DE92BD3B654667",
- "section_mic_hmac_key": "D9FA303E247451D08056ADF12DBDD9EC49332E3AC4CA3E301069728FE0063569",
- "section_salt": "9DC45FD603A6B020B509B8D9BFC969DB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "433465189236D09078373B8ED0CCCCAC",
- "aes_key": "E43BC17300BCFBEB25108453100382C2",
- "data_elements": [],
- "encoded_section": "379013A40450E97B1E7F305B04EEA1CC6C6FF7911000858846A0F9FD9E2E0611D97BF2EF06469002A3D2D64941BB2C16BE63E6233FA8BBD9",
- "identity_type": "trusted",
- "iv": "5FFB8A197BE6260CBE3EF3F5A69D6F9A",
- "key_seed": "950084CE1A17C18014492E2D819E1A4A8918E418B5D793D41CE40AC01962AB45",
- "metadata_key": "F3105517DA032D58D69A3604C768A207",
- "section_mic_hmac_key": "81F142D0B4A95BBF07A155889C7B253A70BE5AD20EBEE9E38B730A9201FADD47",
- "section_salt": "858846A0F9FD9E2E0611D97BF2EF0646"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AE407D2A8A6A0F933972D7926F06C555",
- "aes_key": "6684D1C9DA338DD00813CE3BACA74FDF",
- "data_elements": [
- {
- "contents": "BA4B31050C802CCFD9F9",
- "de_type": 261
- },
- {
- "contents": "A07F15",
- "de_type": 533
- },
- {
- "contents": "3D59A78F9181304C3974C28F99BA56FC",
- "de_type": 680
- },
- {
- "contents": "BF97709E54F7",
- "de_type": 452
- }
- ],
- "encoded_section": "6690134F1022868C775755B32E82021EA423C39110001F7DE96605E9315D3517A53C620C9DFD900485ED9FED88BAEA7D0F7F2649C5C60EF3A8B1985EAC9CA0670D89222827DA233F046290021C3D90C872AAA85B5DAA376E3EF6359C0B865FBDCB1DE9AC211D91",
- "identity_type": "provisioned",
- "iv": "7CB6244938A943AE0C2223EE5478D9F0",
- "key_seed": "2DF4F998B4046363F13903E444563666752112E7A50CCA849AA20A1B632BA11C",
- "metadata_key": "81D88DAABD6499A41CC39A0B69C88149",
- "section_mic_hmac_key": "2579AC31B40E6259D86560A179396A8C8D2460B065479AD84D1672A8E6AAF100",
- "section_salt": "1F7DE96605E9315D3517A53C620C9DFD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6BEFDA99ED6531BCC16097D12D8E054F",
- "aes_key": "5EAB15A140D70A229BB83A187E9F02CB",
- "data_elements": [
- {
- "contents": "0F0E43C4406FA2936FA381",
- "de_type": 236
- },
- {
- "contents": "08C74C0A5E82AB",
- "de_type": 569
- },
- {
- "contents": "B739FE96118484",
- "de_type": 911
- }
- ],
- "encoded_section": "5990133C1C7C478A9872741B2CACDCE6EF85F59110005F03C93641025F2C7C9AFE7A14A9CCD590040783A8D0F38BBB63558E4FD0359A1ED0479EB554E8FB8D695366CEAC447857027FF727D304764FE2A2033DC87C56017725F3",
- "identity_type": "provisioned",
- "iv": "3DBA7081144B735EA26C11843C84939A",
- "key_seed": "A6E1BBB65242EF0297CFD3F36A26E92131DF8AE1124785A313A03CBA129A5708",
- "metadata_key": "B756D4BB650054A9B555F945179AC0BF",
- "section_mic_hmac_key": "672FD0220AD1CE18CB5C2865E369343213F98286F70F932B6864E77878042155",
- "section_salt": "5F03C93641025F2C7C9AFE7A14A9CCD5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "936F85512A5DA1B653FB8A2DCF27EBF9",
- "aes_key": "212B797347439C09143EDEE8D49D1145",
- "data_elements": [
- {
- "contents": "4C46272C464F1F327ABA",
- "de_type": 300
- },
- {
- "contents": "90DFEBBD2FD42483D8",
- "de_type": 576
- },
- {
- "contents": "9C67",
- "de_type": 590
- },
- {
- "contents": "54EE",
- "de_type": 237
- }
- ],
- "encoded_section": "5A9013FEC4DE90AE4B04DB998D69D7B9DAB3B6911000071925257522B40B840ADEA964E0F8549002A053445506418A7BF78DB30EAF544AC34AD6F4B2298373091CF13DB14519C86BEA5E5241124929BC2DF6F87314D8C22DE90D9A",
- "identity_type": "trusted",
- "iv": "2575BE3DB96C9E3EB6C7635C6F6B0E7A",
- "key_seed": "F57E01ED4A19496DC227DE1B016B09C1EBE135D484ED8B80DD00C6EC31ED5B5D",
- "metadata_key": "DEC2CABDD66E55B71A83AFC163D7FADB",
- "section_mic_hmac_key": "4D01BAE5168047AD89DA9A7126549672887F9CDDA5442E356BED3D6B00AAEBFD",
- "section_salt": "071925257522B40B840ADEA964E0F854"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7E7DA96580420BA0D659EC43121322D8",
- "aes_key": "A8FB66F215BC84C5FE083146B193AB8D",
- "data_elements": [
- {
- "contents": "FFB586B557659859",
- "de_type": 397
- },
- {
- "contents": "4263",
- "de_type": 671
- },
- {
- "contents": "E0886DD5892A663968BF0F850FDBC48C32E2C0C1268AD368AA794D",
- "de_type": 612
- }
- ],
- "encoded_section": "65901376D02BAAF38EA4CB4BDD1C73BC3871AC91100051AEC209767B8CAA7980A3BD7C3FAFF29001AF29552C93754001FD0D837E2314FDCAAB5F3F83221EBEAA38EE14E5DEB24E81B4DD949B42A0A8AF3FA573DFD9B28FF81902561D21E508C845551668B4A9",
- "identity_type": "private",
- "iv": "17EBA64E62386CD3B3A3DFCAA57C8990",
- "key_seed": "598D2245CA116C288DD7F884902FD6966A3EAE9F42C0836BE31CE29C29AE3EF8",
- "metadata_key": "05686049146A99EB4A1FE87216DCAB1B",
- "section_mic_hmac_key": "6FA0EF16D9CAA4AC317B88DC23341FDB92AF5B2B4EBAB09202AB3CA30C38CB75",
- "section_salt": "51AEC209767B8CAA7980A3BD7C3FAFF2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4E5974753C765E7C366AE0ABD13B6032",
- "aes_key": "B33B94CD44650B66F7ADBC2EE729BB6E",
- "data_elements": [
- {
- "contents": "86DD5BAF9A7C3DDD8447254F3203CA9E",
- "de_type": 588
- },
- {
- "contents": "AD60D51F76FB590E2E783C7120C160E0DC15543848D74BD898BF21",
- "de_type": 887
- },
- {
- "contents": "46F5356343E961455A3F74",
- "de_type": 584
- }
- ],
- "encoded_section": "7690133360E0A798FBD58AC2C9E37CEA3A383E911000FE2C7ED573CD9CBA19F2AA6AFDD623299001A71787DF83BE1DE49338E1ACF15530E60197A15D7D3007AC410A6D443BBE7F7694D2B54E3FF5BDB62ABF52F85A5180C014FB86A8DE0315F7CF97F2FEA63E21EAB45758898AD526D9AB8B38726E9315",
- "identity_type": "private",
- "iv": "06E07BBF2D5201688926629511421FDA",
- "key_seed": "66E4D540348E429F58155175C858A8BD1E7CB0999B49781D348A321AA6138173",
- "metadata_key": "48A307411309490BED28B84E99A5557E",
- "section_mic_hmac_key": "1BBC012E6C6D7955641BC6D4D06550739840EAA718C15AD3A19816957E58528C",
- "section_salt": "FE2C7ED573CD9CBA19F2AA6AFDD62329"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "74CB68B7EA1E95E04B832182154B0A91",
- "aes_key": "B022EAFEFB9FF1B5C2F98A40B9ACC3D4",
- "data_elements": [
- {
- "contents": "7E37E828730AB3F87C1EB99B8E",
- "de_type": 787
- },
- {
- "contents": "9135DA70E02D2232DED4F3F5568A0371",
- "de_type": 420
- },
- {
- "contents": "C89D3EC94DD71F",
- "de_type": 236
- },
- {
- "contents": "07F52CFFDEF1D58177543155723441BEDF06D3",
- "de_type": 980
- },
- {
- "contents": "CEE968AC8F1B700C2BB3019A4E9472CA7E",
- "de_type": 169
- }
- ],
- "encoded_section": "8E90134F49609F3C0B6286BCD6BB68D9F4E24E91100052CAF10EC936B174958042A90C112E5B9001ECDBEFA0B57D0456BF272B7A1D20269C96F6B666647AC239FAED67E348F463D9B7DF48FAF7A27BD87A9CF5E6B66F7AEE194A485F76350003AFFDEE337DDFCA1DA36D0CC1BE171B72A48C70809218513429B567E3465E8FF5E2033367E102CA20AAC3F702B0DC1A",
- "identity_type": "private",
- "iv": "A5C0BD5B8496CED016A2AF10A6F91FB1",
- "key_seed": "BFBC7FF2263EBED86F9C96A09FC127CE977C9239CC08316F8287B00DBD0B3498",
- "metadata_key": "A832A816BD5B77EDA8EECCA1EBABB014",
- "section_mic_hmac_key": "710B9F30D232D15E9DE12974DA748A32F65D122AD460B292ABAFB60338BBB60E",
- "section_salt": "52CAF10EC936B174958042A90C112E5B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BCCA0E7341FBF76B2B5F5BA041CF1E5A",
- "aes_key": "D12B503A2F126AF19D0AF97566785ABF",
- "data_elements": [
- {
- "contents": "64749203BD66A2F9ECBBE0D588092B4354",
- "de_type": 19
- },
- {
- "contents": "C163763F7A4D635495BD26B704AA19D140DAA82EC06DDAC118",
- "de_type": 908
- },
- {
- "contents": "60B0B36271380D99A2A25F",
- "de_type": 222
- },
- {
- "contents": "796D6F2B775593F100B9",
- "de_type": 760
- },
- {
- "contents": "3A0B8533F323DE0B7C2B5DE29F34DF3D265C6CE5190AA0F958811D",
- "de_type": 994
- }
- ],
- "encoded_section": "9F90136082051F8CBEAA0CCBC6113961AF0C93911000B90142AFBFD356D46AC2B2720D1F8481900205E87BF19BCF1B2CFCED4986FC2A31A121106BDD978C20BC7E027FD26CB2AA0052C1DBB34B42F03C324129015E97C6FE9694ACE4FD254641272F6873CA455E6863D3025F03D209F1C554D250F0EF5BDC10CDCD01CF4831D8C9F30EB2586D41A2CC2D6CDECF4F42AAC02C1B985BE84A98831A26B00B27596A",
- "identity_type": "trusted",
- "iv": "4765E55F52DA037253303C93F66A6DCD",
- "key_seed": "50CA1651529AAF0D0E3874C19E7EE47519CBEEB16DB1A7EF99F69315502A02C6",
- "metadata_key": "70AEC06B61DD252B459F5BE7FC72F7E8",
- "section_mic_hmac_key": "598AC0D450A9FDAD2DD86DAFDA3011B9179E56DE268CBD38AB8B9B9726B0B2D0",
- "section_salt": "B90142AFBFD356D46AC2B2720D1F8481"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2C14A845A98E4C0EC1D3D37E7770C558",
- "aes_key": "A68054A9CC008CCE3091CECA4B305A11",
- "data_elements": [
- {
- "contents": "DCB2B2ABBEAB26EA71BB01D24C",
- "de_type": 12
- },
- {
- "contents": "E3109D",
- "de_type": 799
- },
- {
- "contents": "EA153371A83C3827DE52AF886B3ABDDC5601",
- "de_type": 223
- },
- {
- "contents": "358C051EF89D4B2A70A66557C0E40523E07CEE5D702602A63301",
- "de_type": 466
- },
- {
- "contents": "1E3264B6EDF37242534C9123818D649D38695C4AB285727F7AB64D6D33FE",
- "de_type": 662
- }
- ],
- "encoded_section": "9F90134CFBFA0A7E0F1D95CE9E7DDE4D9D0F119110007C677DA19284373DF76BF8DC23F62A2C90018ED6D11D434C81E0813AE27A8A08FED219D8D2D509FBE4D738C507D35AF118126F68CD7A0CBDB12D6416E38172D47F328DD389DB4AFD0D27028366DF30755D45C06DA90E6A00EE097C5354215144CF3C39D600112B8853736303B3D5589D9690891FD597AFB197D8272C0FF4C4774BB0EE0E8BBD16981621",
- "identity_type": "private",
- "iv": "0BCB734C4A958CAA0BD6818BFC616225",
- "key_seed": "52E8480972975E4BA2FE7605453EA8349E9BC5A94E29540433F860556F01884C",
- "metadata_key": "8FC6598BCE8ADD3790D7EBDAF49D0103",
- "section_mic_hmac_key": "ECCEEA279B282C887A23EC16580BE97CDD50135DEA36DCAB5DF44156A29C1607",
- "section_salt": "7C677DA19284373DF76BF8DC23F62A2C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "229EEACD212DC405EE4811F9A977F2CF",
- "aes_key": "B650D65C7FBB23472BB72579A77181E7",
- "data_elements": [],
- "encoded_section": "379013D438766EAF4C661EDD88BAA0FCB42A1E911000855BD2F01023E6A57B6E71DD49DAA2AE90041D6AFAB5B808B58855F9C7AA4F4D7EE8",
- "identity_type": "provisioned",
- "iv": "9902444F8F3857B3E0BEA260972F28B6",
- "key_seed": "80897CE9046AAA4A739B63E163EB437BCFF71E3E3653B6EF46E3C6AA06D7A121",
- "metadata_key": "34683AD177E872DCBD2A5E7E63EE0A3B",
- "section_mic_hmac_key": "BAB117F9C1BD11C895F4602EE9EF166CFDB9267B3954B5CB5D84D4737676E3E5",
- "section_salt": "855BD2F01023E6A57B6E71DD49DAA2AE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A0C8512737C3A026EA6F37CB99230EC",
- "aes_key": "9E758D2B63DDD9875440E40B527116E7",
- "data_elements": [
- {
- "contents": "EB02C160F935EC11145161E1CE4018A85DC6C6B87E",
- "de_type": 947
- },
- {
- "contents": "",
- "de_type": 273
- },
- {
- "contents": "513989E8F256F4BB4833E9",
- "de_type": 980
- }
- ],
- "encoded_section": "60901342D70D1E94399CE4FFC098059653E5939110001D9723326BB9045D0FA8AD2D055AB7E290013A4BC24317039BC6F6742EDF1BE1FF740DDA42AA9D246BFDB1004EE8CCADE443AEDB88834895F0E1DE5C71512B93FB850303B6C36838EBADFC",
- "identity_type": "private",
- "iv": "A498D9B0ABD9DF7BAE1C56730B8EE99D",
- "key_seed": "007973A9512305072C4B09ADE63EE2B1473CC8800EE101C3B15B7601A53CA570",
- "metadata_key": "7D44DCD6C2EAC7C368BF131C16F56757",
- "section_mic_hmac_key": "FE60C7116D645B0830D381EF145EEF0D76CED5639BDD5BE55BD6796495102AE7",
- "section_salt": "1D9723326BB9045D0FA8AD2D055AB7E2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AA5C563E4C1823D73563F7C3706AFDB3",
- "aes_key": "C999C60B91C13F5DFAF5217C0D5B5C34",
- "data_elements": [
- {
- "contents": "A5A7EBAC14D1B41520E40AC51864A16754521D4A7E54F92A7D",
- "de_type": 88
- }
- ],
- "encoded_section": "52901375BA880AD3ED961F78870D04157CE0E6911000EE361CB440B15CE82D93E0C1DA85A9379004C2FF0F23A2FF140F44ADBE468A1A74B9F702645EB8D1D9A8BE0BC82F88D404479CE665DFF4AE98007DC791",
- "identity_type": "provisioned",
- "iv": "538C25B23A3C86BCDA97A0CFD35A6FC6",
- "key_seed": "ED88849FC0BDA24F6E40D9DE41DA1E13D489B4532491DC76DF1FA6B2119AACB7",
- "metadata_key": "FB3E3B0DC3A793B84A8BAA8B76C66339",
- "section_mic_hmac_key": "8B61AC0A77B70BD562BECA6B9EC68D3AE19A43F75E7C20DCBBB772E72335031F",
- "section_salt": "EE361CB440B15CE82D93E0C1DA85A937"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "619C4C8EF05A933823C2D65A31B92B00",
- "aes_key": "9A57A7F7C65D4129320E88946A9DC223",
- "data_elements": [
- {
- "contents": "CE0E4BE0690C0A5BF044",
- "de_type": 831
- },
- {
- "contents": "BCA982D5431D61B73230868E555B97C3464366E2A4267F64",
- "de_type": 200
- },
- {
- "contents": "C82659D54B9B19F6C502A2",
- "de_type": 338
- },
- {
- "contents": "45B4B7C9A022B79136DE",
- "de_type": 197
- }
- ],
- "encoded_section": "7A90136D731B5176129F207201B4A5D0F6673A91100096D3507A4EC35496932F887BD27700429002BD18C7C64DBAFDF85D34F178917F923C0656AB4C77BD56DA1FDFD011885B997312645D52617E2F428FAA6CBD6CFE285AC1713EFAC1A641DAA3856D5F455D08BCDFE7F308E22A41706C5556B5E8996955934EC0",
- "identity_type": "trusted",
- "iv": "8D39404C79316D7EA939A237B0DA32A8",
- "key_seed": "25C985FC227F539121AA167BFA906D05760D8AEFF52102154CBC785FDBD64514",
- "metadata_key": "14318D2A0E05B5E1A77A50CDEABFA81F",
- "section_mic_hmac_key": "123A5EAAE2B67C4169444F1235E071BBD36804622722A7DCAB1A321F22507A81",
- "section_salt": "96D3507A4EC35496932F887BD2770042"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ADA623A6380A3F4522EE69542E99D25E",
- "aes_key": "331F18CC2ECBE380C1590D5DBCB4E970",
- "data_elements": [
- {
- "contents": "0174A015",
- "de_type": 588
- },
- {
- "contents": "9D5A034F0AFBAF",
- "de_type": 17
- },
- {
- "contents": "E0AAFAD94D19113E64B96863147869E9859DE50FDE4270216231B3184D",
- "de_type": 99
- },
- {
- "contents": "F24EB6B5AEB4FEA479F5083B7F028FA4B5B8D4DA82AE263A34",
- "de_type": 356
- },
- {
- "contents": "F8911686E780BA27D8516A00999512CFA3BDA6B6",
- "de_type": 955
- }
- ],
- "encoded_section": "9990132880845C490110E6A5557732B923E92D911000621BC78DBCDEABAF66E6D1402BC169059001AB11D8A9FF159246AF50E950BD8E400E4D615242ABF1080B0B75A379AA4368ACDBCA95F2010F3841D150725F8A670CA3FFE83412241EDF6EC0C12D1A5CB71D15F9C121E2B378017E5D61F6C1036A8B25790B193380C3897B66D488FA4DA297E39DBB71D3F430B4035F7EBF539DF3F5296380",
- "identity_type": "private",
- "iv": "C98BFAFEF62296B28CD51297CF787F52",
- "key_seed": "86109574BBFC42BC1D620F4EA1018967D9B48E655E5C6DFEC0FB6773CCA774E8",
- "metadata_key": "8D07E48C35FB78B8A5513345B3C40C9A",
- "section_mic_hmac_key": "70AD2654896DB69E49246717749BA8FE8262F0A9EEBEF5D947BCB5253224BE17",
- "section_salt": "621BC78DBCDEABAF66E6D1402BC16905"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "397D6D6B5613F8AC2FAEA44797C0A638",
- "aes_key": "632129B34E30FEC65D800EA6BE5F7A61",
- "data_elements": [
- {
- "contents": "796EE13738E80BD71145D729",
- "de_type": 756
- },
- {
- "contents": "1D7E9E3DF4EBC7615F0923B7C6352829DDD5E4E295F9695E3E75",
- "de_type": 960
- },
- {
- "contents": "C9308827A08A7B53E73C3D8FB9DDC3A9C61E50425623FFF66B7DAB5FA9",
- "de_type": 391
- },
- {
- "contents": "3740A8AA731F460FCBF8D08E17437A92EEBE2554CA90D8E5B063165D199A",
- "de_type": 666
- }
- ],
- "encoded_section": "A490134F9B86D148E83C40F686AEA68DECE504911000FFB3EB0B6BBD03AACDE886D4B64963A790046E990FA420DBE8370E20B582D0F390FC2EB3B4027A44D55BE09DF6AED7C73280D7B271397917B220A8E81422893C7FD705E02ED8A0D672DEF820343A46C18FF08611639060A1324C24DEFC5B4E8BCE9F9CBAF58E48EAC6DCFE80A916FB7CDE7582422D06E9287896BF6F4211D2395A5028690E94F6CC2136252D8A7105",
- "identity_type": "provisioned",
- "iv": "5276C1A1ED1B081D2A2A6F5DEA96F665",
- "key_seed": "D95BE815CD7B0FD68B3E7446B8B2D79E348D548C6183AAA1BC4AEA344738987D",
- "metadata_key": "25302242FB45A172D3B3FF58EBB4068C",
- "section_mic_hmac_key": "CF8906BE97A01B93944A42FB2DB4610CD87BD1678F8C88F0486D9BC527FC41C4",
- "section_salt": "FFB3EB0B6BBD03AACDE886D4B64963A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AF24B060AFFEAC233E864603EE00A9CD",
- "aes_key": "D93AAFC5986BC8683E27129BE1E82563",
- "data_elements": [],
- "encoded_section": "379013E9112895D9EA079C03219B88C45A925D91100033555799B45F9C4B35FC02644ED660DA90026A0D952277833EE72223017DD0D09AF3",
- "identity_type": "trusted",
- "iv": "768BFD528B829A1EBA49204A0CCB4B02",
- "key_seed": "970EB18227C61CEC00A2A05F5263593CB7C0495397DD0F533DE7CFDA67180147",
- "metadata_key": "122A3B297DC2A96CDB5B3BBB05D6B536",
- "section_mic_hmac_key": "2192C8F4C87ECD29422DF7A686A1EE7DA0943B83F89D81442550BD786F1F648B",
- "section_salt": "33555799B45F9C4B35FC02644ED660DA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "82B9B8A6DE7077940685F5FAA7DF422F",
- "aes_key": "7BFD4D7DF1E0E9C478A06570E9B9CD94",
- "data_elements": [
- {
- "contents": "ADB48AB0F67DA8D5A9618BA4253EAAE7D39E310D5BD37BC56AFCF41F",
- "de_type": 461
- },
- {
- "contents": "9A86354A04BF30E00DBE8C414A9FB24C86C8EEB7FC83E460",
- "de_type": 936
- }
- ],
- "encoded_section": "71901316B26D715D337B501770721CCBE8D13B9110002C99BBEA9A300BAA95863AB8AB9A9BD39001FF44AFBB9D1C0A28266B562AE0E7B38C1BDA2D66BC2DEED15F33F3034E934A9D7FF8E3718F68A23361EB574956A6D723F38EE0575D4A922AD0DB7DCECAE52CF2C44BB26E1E71DC16BCAE",
- "identity_type": "private",
- "iv": "7718D52D9D5CC851A7B2C047E8E56916",
- "key_seed": "2C2905CFE0366D03717F4F8084FEBD30602C7CB22BAE0F5E8AC4902C762AC880",
- "metadata_key": "35E0C0C417D995CC800143D9A392B94A",
- "section_mic_hmac_key": "A8AC22011356C040DDDD1830F1881474FAE157EDF4D0129D5DC616244F495E51",
- "section_salt": "2C99BBEA9A300BAA95863AB8AB9A9BD3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D49E9CD1D20A4B4F340A593D6BCD93A9",
- "aes_key": "A8BD4420579EA3F0F63C1BC03F9F6893",
- "data_elements": [
- {
- "contents": "3B986384C79F675F",
- "de_type": 650
- },
- {
- "contents": "",
- "de_type": 640
- },
- {
- "contents": "40EB0279736AAA9A100E2C26941448AE2277AB",
- "de_type": 990
- },
- {
- "contents": "",
- "de_type": 470
- },
- {
- "contents": "91318CF7EE4B2E35241F",
- "de_type": 694
- }
- ],
- "encoded_section": "6B9013DDCFA87C6ECA5D9778AE29ED4AFDE2FE911000182084A74C01395449B1A065B30D8080900433A6E91CED224E8632C5205DBE49C3C810CC5A826F3F058111AF85E8729E0900EDEAFE67BA46EBDD09A8D9390F47EF040498143310AB8776ECAC80461AFD91D2A5318B82",
- "identity_type": "provisioned",
- "iv": "134179E764FCE0DF7ADA95F934D30276",
- "key_seed": "BDF4556FC6C4D53488D013E20A98C17524875EAD68B64ED0BE9E0EB9DA2B7BBB",
- "metadata_key": "F4DC6D1E64678F9606BDF71B0EA52BB9",
- "section_mic_hmac_key": "96D8CA32AD841897F0AE2C292B9359E901760A16B9FEA999490FA1CC80C944E5",
- "section_salt": "182084A74C01395449B1A065B30D8080"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F6A8AA713174F7D9C61E5328D2FBC88A",
- "aes_key": "C2221BD4696591A3CEB7806807E54F5B",
- "data_elements": [
- {
- "contents": "BA4C375C376640ACC08AA1864AF3BE5AEB9A59",
- "de_type": 667
- },
- {
- "contents": "54F3E1E4DDDA",
- "de_type": 390
- },
- {
- "contents": "3F3851F502FC37945B512B2DA0398A6AF6299C08DF21A49A",
- "de_type": 664
- },
- {
- "contents": "BF39F68C7BECA2FA6D4A56E4F01589339D619761",
- "de_type": 425
- },
- {
- "contents": "53B006EABB64D1206347779AEC7E47CC",
- "de_type": 177
- }
- ],
- "encoded_section": "9B9013E2396E53181A2D3263100883209CC1C2911000A30816D0EE95944953EAED4DF1C8E2069004407CB081B3ECF537ECDC12A2C42A866F9CAD0593863B3C5FB9425336A46BEC045CA6EFEC8439DAAF4C7107C4A09A5678FF4787379C733C9D71E520F141F7E1C9D048E2C6C56C0B7E1AE04A11CBB9EC7DAD91F8B8B3A783DCAB0CBE44B354B19F2D205E3550BE0CA3E25FB15F8368D0AD060D1BDC",
- "identity_type": "provisioned",
- "iv": "49DDF471C624612F805C254CACC512DF",
- "key_seed": "9B73B7B20095CE1A1B91186605AFA5C48463E2A93E1F3163AAA0DC4ABA51D273",
- "metadata_key": "7755D72850CB417465414B8AD50BC492",
- "section_mic_hmac_key": "E15A4CC4DC3E2E1AFFEE0D584E82999BDC30D6BEC9C1143A236A4354598E69FD",
- "section_salt": "A30816D0EE95944953EAED4DF1C8E206"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B7820F847BAB14663F5B9729C770A903",
- "aes_key": "ED1C41116C53D174E700C90465D29FB8",
- "data_elements": [
- {
- "contents": "40980514A48D57566E6CEDBC1F13125EBF242B6BE09C",
- "de_type": 982
- },
- {
- "contents": "31CC3F9A09A2163C86581D7A795A2C7D3BE9AFD63F00D797A4",
- "de_type": 304
- },
- {
- "contents": "6D85FA25468C5164AF6E8D7A5CCFE94DD7759B684850E0D007",
- "de_type": 633
- },
- {
- "contents": "191D0F07EF",
- "de_type": 686
- }
- ],
- "encoded_section": "90901336A6FD32C63BAB8221AA293FA3979ADA9110004FBD36EB5BE03713867E3B3B06A4B53C9004C4F0B8515D402330041A6614E4BA859F1A6444377518C0289C14D01EDEE0939FA2BE910809ECEBDD265B2E89B26C60B42428084CA567C85EB2B76C8035DD8B8787E94AB3C760DBD281CD84D0C8CF8F281E486096E34230F0DE44456677971EDCC5A2F5DA4E0ACFBD94",
- "identity_type": "provisioned",
- "iv": "C157C8C8BAF421A7020E0F5AD4399A7C",
- "key_seed": "0D5FD7A0EB16F50FB1C3CBB0ED4EFEB3C022AC15566F7481FBD9DFADF9BFE596",
- "metadata_key": "26294EA549B9B814C43F866176D22280",
- "section_mic_hmac_key": "676112EF0807098F45519595990076B83DFCBD0E55B9414225990D9A6046FCD7",
- "section_salt": "4FBD36EB5BE03713867E3B3B06A4B53C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4A8D0B8F6B7F9E6221EDCAB57C36BFEF",
- "aes_key": "B9A82BE9DF86E2FCD72839955485B828",
- "data_elements": [
- {
- "contents": "2B0FE4B16D2740AF13A500",
- "de_type": 209
- },
- {
- "contents": "BBB807A186D2C3F87855",
- "de_type": 999
- },
- {
- "contents": "8A34F77DD5A61121C4917A48AA085776ABE1",
- "de_type": 323
- },
- {
- "contents": "ABC7CC",
- "de_type": 138
- },
- {
- "contents": "7A5C43A5C1B70C0403E055FCDFE81A5297DA1FD729C47776DC5D5F",
- "de_type": 499
- }
- ],
- "encoded_section": "8B901302D13FE7AC33AFF3924F23BB90E9D53891100058FD054F518764F7FFA68EDC5E76897C9002C8019C9BDB34ED694F527F1A74A171D4DB910B76FD198A047FF0A723356BCAC3F103689FC91F58B627B3E1E761849E237D9F28D154025D4153CA2D22555EF4351328FB3B9473CD12972BB2B2EACBB1B8612525B21BF117E283394DF7A464BFF56D7CE298",
- "identity_type": "trusted",
- "iv": "8BD5C8CF29932090561C480D4AEB8E36",
- "key_seed": "321AF261DCA753BEE3CBAF5D7DE64DCBFB04C0585F7FA27D20D11CC0059712D9",
- "metadata_key": "F0BE3BEB618DA219C8DF306367CD47F4",
- "section_mic_hmac_key": "00F983CFCF9D1F0F4E8D74A6FA26E6F8A13E7EC53388C10E81EF31FFECAEEE87",
- "section_salt": "58FD054F518764F7FFA68EDC5E76897C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C7BA44249D8BFABFAB9B54F90B12F222",
- "aes_key": "A56D794C950BB5A50D04EDB2699B967E",
- "data_elements": [
- {
- "contents": "773856891169289C79ACE48945E05618FC738071",
- "de_type": 799
- }
- ],
- "encoded_section": "4E9013B45A17060677E85EA10D75DDE8C12D3C911000CADE7094733167FAC6390816307D14159004DE8DE98CF28805D142425AE5F24F616AAB3BF83AD109A4F753E55F37D7AC1E6FCF6534806D9740",
- "identity_type": "provisioned",
- "iv": "BD0CD0756F90453E808F180E923758EC",
- "key_seed": "E0440C8BB83D2E4A5ADFD1B123A1D55AE0C78ED8F14C14DD9CF1AA5B3CF3D650",
- "metadata_key": "5CA211769EFD29892C0058779633355F",
- "section_mic_hmac_key": "36CE6C896028CCE6845B791384FFE622B9E8774F12F44C00CF410FDD543D7EE1",
- "section_salt": "CADE7094733167FAC6390816307D1415"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EC717CB0D92304E7C8A5886A78DB5034",
- "aes_key": "7E9A8C8DE80E37F263D24E3DDF281A86",
- "data_elements": [
- {
- "contents": "34E5A87FF8650308",
- "de_type": 954
- },
- {
- "contents": "FB132CF4999537D6DBECC9CE4D88BC0E0C66437891091F49E137569E20C0",
- "de_type": 277
- }
- ],
- "encoded_section": "639013E9DEC88D9D254BAF7E818338DB5B69699110006B1150D7267D5DA8573E97C7DE07E1A89004FBAA70C03E33206A3417BD94DB9CF1B17A1C2B7968732BE4326A647FE22B4F2CEFF689ADAA4B278FA37931CB60D22363385B4816C4736F2A05A6EE28",
- "identity_type": "provisioned",
- "iv": "9D13A28391F3EC75EAB2C424E505FD99",
- "key_seed": "CC5C727CB341CB25BC5AEFBC7D49177263FB4978B4E4E5186BABE100E5F3212D",
- "metadata_key": "6616F3E1AB67EEAAB018CAF0368EE6EB",
- "section_mic_hmac_key": "BB1DA65CC10CE54179F3E39CED7BC4A00CDE225FE15A11E2A0B26A01C2EF00AE",
- "section_salt": "6B1150D7267D5DA8573E97C7DE07E1A8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F817848433DAE38015DA750CED78183B",
- "aes_key": "020009EC448EF1E4CEB74B078296868E",
- "data_elements": [
- {
- "contents": "5946AA9A7E7F78583A2593221E",
- "de_type": 819
- },
- {
- "contents": "F3FCAA87BBFFBB6DAC6D",
- "de_type": 396
- },
- {
- "contents": "7616F64C32BEB7A3",
- "de_type": 848
- }
- ],
- "encoded_section": "5F9013C1CEAC79565703663F399E1968C2470D9110007BD86A32FF05C5A3467AC4770AD53060900405E742BD974A141B76639EDE0CF231F727BD196A8C863E60EB8B78E51632632F66AC501B2AC22B50F5EC417B9140C81BD8DA0070E2381DAF",
- "identity_type": "provisioned",
- "iv": "69D2FD8DE211E9C5BB873A2D7D2B6CB9",
- "key_seed": "A0334C2F26179EF4E774DCB7CD5A391CC98BFF20B494B723245929CF735448DF",
- "metadata_key": "9851F80BA3762814A9E72D468DEBFA61",
- "section_mic_hmac_key": "15D84B9D02BDE9C0C9DA6AC3EC67292ACD5D8630CCEF4641DB19DD4CC8D895C5",
- "section_salt": "7BD86A32FF05C5A3467AC4770AD53060"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E40CA7C0648E07D9192133CC75F0615E",
- "aes_key": "28081717F56B17979C8FA959D1705DEA",
- "data_elements": [
- {
- "contents": "3684845D716D939E",
- "de_type": 119
- },
- {
- "contents": "5947145E79893A962656DB4C59AD50EEAD01F1",
- "de_type": 727
- },
- {
- "contents": "5978AE5D485DCFFB9867D2F0",
- "de_type": 641
- },
- {
- "contents": "962B9E9370A4C36C43FEEC0528002B35ECC2ED",
- "de_type": 938
- },
- {
- "contents": "EB29C1",
- "de_type": 186
- }
- ],
- "encoded_section": "829013293A19BEAE341B678E05CA9E75DBA8BC91100057B76CE356A06E76CFA8BB68D107FDC39004037C94F1AFD8F33D737F2064155467C3207485B5F71525974A812736FB82850AB38C76D001D5E5CD0B4328D0671D515BD3A96875EE561D2771F74DB2AFAF4EFABB0F0F12B7A17E237FB068C81260B34C1A1BAF706519F3803E23C0",
- "identity_type": "provisioned",
- "iv": "40F169746958A56E53FED40BF97B2393",
- "key_seed": "D49D918900133822B62FD10A29B94E6BE3A2292AD816F2E70BDBC54D028FE522",
- "metadata_key": "D4AE0FE4DCC55363A8466CF3B4F51435",
- "section_mic_hmac_key": "1D49C1AD9F730E0160754250778275FFD5799B819699A89B58EF2B3A41903A8B",
- "section_salt": "57B76CE356A06E76CFA8BB68D107FDC3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "757EE18FCEFF081F4652936C61C98FA4",
- "aes_key": "402C0F4BDF07820EDD02DB5D70184906",
- "data_elements": [
- {
- "contents": "16023C5646467C0D21089216EBCD2C5413BCEF76CE991FCF661FC4D0C699",
- "de_type": 362
- }
- ],
- "encoded_section": "589013F1FC637B2DE2561AD1B961848A1C31DE91100012709EC52C322E758DD1D4B3347B16299001DBD653A91D6CFA3EB9D465D9633FBD9D86F1ABE4C9CD01BA0EF5AC6DDFD32AD069F6A6AFA8B424DE31F9D096DDF88B5517",
- "identity_type": "private",
- "iv": "94F193ED7C3685CBF02FBCAC1BD8AB90",
- "key_seed": "01466D478F60FB0CA89BE406E370ED7BF41C0BDC1B4E3C00A21D639968FAEC72",
- "metadata_key": "55850F8341492920ABD7B9F783E48899",
- "section_mic_hmac_key": "969F5321DEDA0678199C25C7FD9428994949F8553438F227114C2E2E2DC84599",
- "section_salt": "12709EC52C322E758DD1D4B3347B1629"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "42BBB939A0B851EBB455B0B9CC6CA629",
- "aes_key": "3A239E17B2D8469E47B47F8AD8026A61",
- "data_elements": [
- {
- "contents": "A85630426C2034091E33C8805C8470161D9E03FBE5FFC6DA16",
- "de_type": 1000
- },
- {
- "contents": "",
- "de_type": 680
- },
- {
- "contents": "22B766878655BAE8D17D60104A",
- "de_type": 203
- }
- ],
- "encoded_section": "66901361BFCCAF1C31DC52F1BCBDE2CA129C719110008D11CCCA32A98B153EAE11A9A82D5B8B90011EE1A3D2126B9947D2B7738A2AAFDFE4AB95B394A7152262808E7E30B50085DAEFD42870EE6C929F3D694215247C54659972A9EDBEFA4504FC8A8E44174522",
- "identity_type": "private",
- "iv": "B4592168B5F6432ED7AA739A5EFD1BEA",
- "key_seed": "B80CF25126E7DF740A3C7A4C3F070220ECED0A230C46D4166786B7924A3EB873",
- "metadata_key": "AEC4D47281DFB8882A751CD4D30AC338",
- "section_mic_hmac_key": "8505CF64E272040C22176713164AB15E9A59595E77793D79E4FA517901E5619E",
- "section_salt": "8D11CCCA32A98B153EAE11A9A82D5B8B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7FA90676A637142CF7CB5C912AC1F98F",
- "aes_key": "DA5F3DD4DA5B5420500EB8F9CAF9807B",
- "data_elements": [],
- "encoded_section": "3790139616C2562B842335B3474F07B4D10A81911000F24039339EF2187F8D6958E05AAE8D2B9002DA1F8883F7B4BD72A21F62487E578D60",
- "identity_type": "trusted",
- "iv": "F24D530E53213A55CF5A6DE13E8BDEF6",
- "key_seed": "217B43E5524A922F4BA6D492809942BB9021143D3337961443AF613301210AB0",
- "metadata_key": "83202E063706BD296D9F1E4A7F1C7951",
- "section_mic_hmac_key": "234DA6C4D3E64D80479D48A109F449C888A444DB541E0CDF9E6ED02303C82A84",
- "section_salt": "F24039339EF2187F8D6958E05AAE8D2B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "67D52BBE900B7D4B9C3689669C4574BE",
- "aes_key": "CF50974C04B44AF21E8DA91AB769E3C5",
- "data_elements": [],
- "encoded_section": "3790134F982E377F44CCE5EDD47A02E14D0074911000EC29B4AC8612C65A3910C4F542341B169002F16B78F5F6A227EB47469338E73B5591",
- "identity_type": "trusted",
- "iv": "DCA9FA6379C1592FCBF87CF2C356022C",
- "key_seed": "BB1C2824578A27C5BD463EEA37C51DBF8380C9C418DA31629EFB9BC3E2E1E5AF",
- "metadata_key": "F716A36DE6F63EF6280780B52950B263",
- "section_mic_hmac_key": "36DB68165CFBE7D58747A358D101CA6BCFEEFF26F6071452017AFEDB64EF411E",
- "section_salt": "EC29B4AC8612C65A3910C4F542341B16"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A8166ADB4DAE7D4B20347694120671F9",
- "aes_key": "ABD91B9CED37FF55564836110D6582FE",
- "data_elements": [
- {
- "contents": "E5ED8A82CCC764F7A2223F9C6D4701FB4E",
- "de_type": 485
- },
- {
- "contents": "30A7FADE0C23C8528D5CF2043572EAB8D6981184",
- "de_type": 430
- },
- {
- "contents": "2697",
- "de_type": 607
- },
- {
- "contents": "C8052125E93A57796DC2FE0A560176FA099D06309581D8CF0349DCD63D",
- "de_type": 175
- },
- {
- "contents": "E7D9B6F5BF4B0A7321F2A3BB4CFA955BB0723229527586F2D8AFD286",
- "de_type": 802
- }
- ],
- "encoded_section": "A6901329A398A67801759F9CA6A0FE27829740911000B048311CB6B2A4B7CE2518E1CD9356239002F002B86EE8DE89899528BB9568107ADE1966E76715DFF2DCBD3149DEEFA21EDFB4FCC9E4BD0099887239950EAA3AE6245C379A2EA7A2010F82B5966FD9BD4791D3B9281A622EE0C21C089EB54F342574EE043B87CC8C9CDC920EFA3C1026B277E34B6D8A19A9A54F8E4D7461781F87F64B697AEAAFDE058D2D68A0600E6FF3",
- "identity_type": "trusted",
- "iv": "ED7F17674307775199068DBF510647C7",
- "key_seed": "D0BCE2863FDBABA82CBA792D89EA4DB95642305B5967BC96C22D5936E155CE1C",
- "metadata_key": "6993BBC4A4D2A05F8938EF1CA65CB545",
- "section_mic_hmac_key": "6E7BB863EB3E1B0026872D4487C94E020D0BD53572D65D7C0D6C860A8D6D0479",
- "section_salt": "B048311CB6B2A4B7CE2518E1CD935623"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EE774E050991C3C3C9021112F6F6EC06",
- "aes_key": "AE6E6D8F193D0262BC994CF38FA772DB",
- "data_elements": [
- {
- "contents": "442095408DF056",
- "de_type": 170
- },
- {
- "contents": "85CA4D8451F85564A337E66E3D",
- "de_type": 101
- }
- ],
- "encoded_section": "50901385B9A090D6F00D94495AC0F8196830709110006141474D448BDE019B1ACCD97B5898A29001B076A9F616D35B3F67A9324816D2268BC4F1884707102D3D23202C966E0647ED7FAB056222AD712CE5",
- "identity_type": "private",
- "iv": "069306DBC724AD554F5241390602AA31",
- "key_seed": "9CC25445803440DBF96652CC28DA5AFA1735953DCA314BB7EC9FC1C11C3E4DD1",
- "metadata_key": "541C17F0B1EFF90F37B511C84CB01D06",
- "section_mic_hmac_key": "6E7AC64E36AC9A870E06118382D82BC2B47D35820715A53DD9954F4BE868517D",
- "section_salt": "6141474D448BDE019B1ACCD97B5898A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D51174BCF89730FA639EF480EB430A8F",
- "aes_key": "DA6B7E261E3C36E6FCF07C079887B799",
- "data_elements": [
- {
- "contents": "7E03CE74C8591B567A1EDA2A366C7E",
- "de_type": 734
- },
- {
- "contents": "66ABCE0999131CDE50E7C35DB2D8BE895D9938E4E658D37B9A4601",
- "de_type": 511
- }
- ],
- "encoded_section": "679013CAFCD53B1A04DDA344493191C7EAC7B99110004A952640E5B79A89A0655B00CF018DAC900446881055D48B06AA711F6C8DC456BAACAC13BFF4D46C5A85AC0102A2DC9BF94DC1F012EE6198AA698214B30A1414C363E1020F23A4822AE91A04BA2FE48AD10E",
- "identity_type": "provisioned",
- "iv": "07F3DB13F74CCEBDB585C022ED0F4B56",
- "key_seed": "33B0E0FBAB31D8FE35848E2F78C9D5390DD11ED65F7E4BA39C71D748E92438C7",
- "metadata_key": "D695C5430C16E9EA343D065570644C0E",
- "section_mic_hmac_key": "93952E5EEE989B740674ADE0A44A2C64D6A4CF9AFBA3446C07967C14FF5F72DC",
- "section_salt": "4A952640E5B79A89A0655B00CF018DAC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "774C0D533FE66410BDD55592E3036A0F",
- "aes_key": "18AE71C0EE69346777AB7B1E8C253B3B",
- "data_elements": [],
- "encoded_section": "3790135D1CB9ACA8C85EBA088DAEEB5F7B2F0F911000B88681185AA3C583D44424B27FE983BD9001D1435474765A6D46A2E1DB20190EC0B5",
- "identity_type": "private",
- "iv": "DD2B97D25158EEDC1E23AE53BFAFC480",
- "key_seed": "58339EC9EAC03D85F9E049005AFC9CB869C91E42AD1579F9B483A94AF53AEF85",
- "metadata_key": "3849D3FB177823CF145390B303471646",
- "section_mic_hmac_key": "9514FBB9156CFFA72FB2B0D83B2E1A7F8F12E1089A54B602A1B6E1954BA75500",
- "section_salt": "B88681185AA3C583D44424B27FE983BD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A4628CF753A8EA365C9B865A1882111",
- "aes_key": "A155E6D506D2F148E0AB36A972E814BC",
- "data_elements": [
- {
- "contents": "8C77898782AFDD3BBB5415BD",
- "de_type": 639
- },
- {
- "contents": "7B0C5D7023C73B8522C9EA75",
- "de_type": 903
- },
- {
- "contents": "9CDB06ED0CA5436E486401F2BD230C0BFB4C",
- "de_type": 421
- },
- {
- "contents": "B7841BAB20AA8DFFAFDBE875C19C0479189092AB",
- "de_type": 914
- },
- {
- "contents": "7DBC5D",
- "de_type": 13
- }
- ],
- "encoded_section": "859013018B2B85208E151D0AE32ACE1338E72C9110005F4F13AE0A18955384461083CBDD4808900253E05D4D34C0F0AE7B49116B244A88D9A46A108C9CC629BB2425C7FFA06C65B8776B3F14DB40950B88A64CB748A51F9774EB4D520DEAB00ACCEA9B8C21BBCD78DE99503D58C3180C74D9975717039336048301DA335326C27A515D26BA18",
- "identity_type": "trusted",
- "iv": "D19E93815AF20322A04DA98F0C71E960",
- "key_seed": "EFAE9C42B2580C7BD3B6F72022C14514C52214F90B4592AE55DBA17AECC21CA9",
- "metadata_key": "D8DA27FC09648F9A7B03CE89C6C0E73B",
- "section_mic_hmac_key": "C9B288EA8BD044EF4F94D580F71B5411A511D4BF8731FAA43760FFE5854D690B",
- "section_salt": "5F4F13AE0A18955384461083CBDD4808"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "63C164C01739526FDFF320C932DF63AA",
- "aes_key": "6571AF72F4E833E632EA672CD1ED748F",
- "data_elements": [
- {
- "contents": "E3590FC9ED1455080A7F9141290E3A7A86CF07E56EC946",
- "de_type": 158
- },
- {
- "contents": "DCEC6A40CE44EBB393E18282D6EC2942AF3E4C0ECA67ECD01CD450",
- "de_type": 331
- },
- {
- "contents": "E7",
- "de_type": 627
- },
- {
- "contents": "550A",
- "de_type": 213
- }
- ],
- "encoded_section": "7890135C8416F66FBF8296AFC54C0B51DD9D54911000C730E6814F61380EFAEF16F4AC12251B9002290C795417F652150706F2122E017A644903C036E3A38349C982CA8A03D481CAC715B9B95F40189FE7470117B3D7097D8DF2B09187190A285B937C7CAB276D0801AE6B224F710CBB80585C3A66EDF99293",
- "identity_type": "trusted",
- "iv": "23C8041707E666CDD9B92CE4E16390C6",
- "key_seed": "E54B5923FBCAC75CF05EBA91DF3C5A62DEF8A88671EAE2D9261C30FD83245BB4",
- "metadata_key": "DB91F1262351AD353C9CEF87EC701A18",
- "section_mic_hmac_key": "0A44BEDF00C054D356FEC008D901B583FC99CECB4DD06FF16BABD31C7595312F",
- "section_salt": "C730E6814F61380EFAEF16F4AC12251B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D6A2EAD0DBDFF521DB943F9164E9ABF5",
- "aes_key": "BD03B9DA72C3E8AFC6C0E7E62F02D66E",
- "data_elements": [
- {
- "contents": "FB62FA28DE416B3FF7C32CDE250E503A38AC512010D9A11E21ED08",
- "de_type": 580
- },
- {
- "contents": "5B6053833E7DA425451F",
- "de_type": 86
- }
- ],
- "encoded_section": "619013B8C630B2133545FF1C0C09F167B63A769110005DBAE9CE6653D2E2B9466DE1F81BE8BA90022F5C1D5F8C8B84AE9E2988700331EC43097F2B12FC61E105086BCDF84D27411E91717096B8EFDA92630445AE4D2F984A2863C71CBA45AC3290A8",
- "identity_type": "trusted",
- "iv": "E82975873E9953E02212AF85698F56A9",
- "key_seed": "88F7698955CC78F3019EA531FB78FB1DB904390B04C10F42F19257F35001FA89",
- "metadata_key": "66E54B6B9FB695DBD3CA8C66C5FDF514",
- "section_mic_hmac_key": "C739EE6C7D4FDF5A76FADA66C0872E628EE444761679A4005F45F01CD1A748CC",
- "section_salt": "5DBAE9CE6653D2E2B9466DE1F81BE8BA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BAF192B97D33369E018E81BC50AC8F7A",
- "aes_key": "325B3B524F9BF9100439F3089DA3C7FA",
- "data_elements": [
- {
- "contents": "B0",
- "de_type": 856
- }
- ],
- "encoded_section": "3B901356FF1D5E7200783B9778078D010BA13D9110001FC604425A47F60D3C1CC80624EC40139004A2EB00B81AE9CE42819E6CBB1CDA25BC43B99433",
- "identity_type": "provisioned",
- "iv": "5BC3D50F1BBEC06A2B6B68DA3D21075B",
- "key_seed": "449CF830F890204B2D836B34548904080906F492D5CF84FC0C2C82D782CAB553",
- "metadata_key": "79C0215D30C0B475C608D77C570B4CE8",
- "section_mic_hmac_key": "6B3F15514E22EE373A70F39F81516BE169F8AF5458E35CBB3C5B60AC036A6E64",
- "section_salt": "1FC604425A47F60D3C1CC80624EC4013"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "719A721598179D4D4B26E2ADC7E3C50F",
- "aes_key": "ABADECB605978F38B860C1AC618EF22E",
- "data_elements": [
- {
- "contents": "2B481F57DBA2E4528AADB3F65A2E0A10FD912A517252F49806DC",
- "de_type": 452
- },
- {
- "contents": "7EDA82863D",
- "de_type": 366
- },
- {
- "contents": "8A8868E25778C9D2DBF3E428",
- "de_type": 541
- }
- ],
- "encoded_section": "6B9013B2C0BE2B338651F83C9DEE9FF7A5E9B3911000320082AFF78C58B12275134DD71800779002E109918D72EB73A7CF12E71CB578633A99BBE624409264B989AD42AD9FF7386B107AB874BE50CEDC6C193CC56FB20F9986CF982065C0867E248B792655F223FB1B99B268",
- "identity_type": "trusted",
- "iv": "EACEF787A9AA0D378B47AF7B7BAACC41",
- "key_seed": "8C96ADE771F0EC82E8A65EAB09768E0D2779DC80D10AC3A93C69EDADA363C9D6",
- "metadata_key": "980207617795323129DA7B883489A471",
- "section_mic_hmac_key": "878F73081377F28C1DCD6BA7A3C9CCDB12B2F9D0577D37F2217558C7D5B560B7",
- "section_salt": "320082AFF78C58B12275134DD7180077"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "898AF84E18B19268BF0066E1B843DB2A",
- "aes_key": "D18AA5914985AE77CE2FCE7552F09B46",
- "data_elements": [
- {
- "contents": "4615409B344399237B3ABDB8F670E5B8655C8EF5449E5DE40A9A015E197A",
- "de_type": 851
- },
- {
- "contents": "3D6EBF61130ADEE935CA18BFEFECD70BD2F9C05F276F52860E6C",
- "de_type": 516
- },
- {
- "contents": "9E",
- "de_type": 916
- }
- ],
- "encoded_section": "79901393C3CD52AE720625794E99D501168018911000B225FB4D96E5A2AD5966E0201447323F9002B0CE58BA8230AE27D19688FCA438C5C94AAD5E60F0750EB7F63D98739E51CDCC0AEFF8E374AD8CA4B87E671B1163F8075511F02B94493CE489C0BFD6626FFCD80A78A99F869E6D048D89A29D7EE9DC94572B",
- "identity_type": "trusted",
- "iv": "0F973AE8405A878AAF91F3F3030CCDB5",
- "key_seed": "FC64BAB5EBFD28BCC2DF64A332591AC18E67D4F0D8D04B09D15BE99F992BD0F6",
- "metadata_key": "2817DC0D3018C8208062F9F09F0217C5",
- "section_mic_hmac_key": "DFAB6D5BBC1AEEDC067EC644D7AB15D0A0FBBFA0FF766A45BC6AE217B00C1A76",
- "section_salt": "B225FB4D96E5A2AD5966E0201447323F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6CA09CF038262F0B86AFC0F196F079A1",
- "aes_key": "DC35D7E7C27384B92F1F218AA96E5815",
- "data_elements": [
- {
- "contents": "F11DD7ACEED992",
- "de_type": 439
- },
- {
- "contents": "19CA080B4B458E94D3973AEBE5",
- "de_type": 120
- },
- {
- "contents": "",
- "de_type": 973
- },
- {
- "contents": "138501DB6DF8DE97",
- "de_type": 122
- }
- ],
- "encoded_section": "5D901335901EB3DFE18DDCC333E258CEBC67A6911000C453204CA5BF1BE8A080F58E1E046BDB90013A59DFC6058F6E641E7F6BCE6B71D94D022FF601B5D7CB45AE24E902357B8AB7332484AFB64A5EE9B2D654B67879279632B8226CD83A",
- "identity_type": "private",
- "iv": "C4013A2D4DCC401351902092CA23D50E",
- "key_seed": "9C31224BE4354E49AFB6CCD5EE02E4CD13A1E57ABE9FD2CE2501A039B51E6425",
- "metadata_key": "7A67555F40D8FA75031A57BFCA376901",
- "section_mic_hmac_key": "32FA238989BD8A58E646578F6ABF19C7A49B10F8A626BBAA984C7163A6129896",
- "section_salt": "C453204CA5BF1BE8A080F58E1E046BDB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1AD93C4DB2AA2956308F6B40D2227DE4",
- "aes_key": "702409CD2C1478EA23213540CAD5A499",
- "data_elements": [
- {
- "contents": "A104DBE9FC480BD7403A4F2488AA305DB6CDC31C85923D7F71B751",
- "de_type": 441
- },
- {
- "contents": "3AC2773587350DE26099CF",
- "de_type": 827
- },
- {
- "contents": "320622",
- "de_type": 969
- }
- ],
- "encoded_section": "699013A36C4D395FF98F721DECC40BC9CE7A96911000687BD81DC1D918FE6F5EA0EA6871D83590016D763DF756CE03623E713A3A5CEFC54FB9A77EDA7C91BA0072023850ABE73DE6F6E4CA176F830D0E0A33FA5D169D172F2B50ECC62C75A95C5A9BACBE4FAB29A3DB7A",
- "identity_type": "private",
- "iv": "AF815000B11B4D2338590EE859E43B26",
- "key_seed": "BCF8775858AF8BB34B9296C2B9CB9604AA68CEAF0E015FC23F88F60CA73E0EC1",
- "metadata_key": "22AD97286075323B5D9C97A18C8516C2",
- "section_mic_hmac_key": "E59A1CB6BD1ADF2BF24F4C657428105B097C70A80EE4F707ED96551FE4FE834C",
- "section_salt": "687BD81DC1D918FE6F5EA0EA6871D835"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF0F5C6FF715661FDD243EEFCC3DF000",
- "aes_key": "465940811F2D7624AF1BC24ECF583A31",
- "data_elements": [
- {
- "contents": "ED5B2856E0",
- "de_type": 480
- },
- {
- "contents": "5C9037389AE1E052391238AFA847305B8D52F177ACF119F8F5958475C1DD",
- "de_type": 458
- },
- {
- "contents": "F1207137",
- "de_type": 42
- },
- {
- "contents": "9EA01A",
- "de_type": 627
- }
- ],
- "encoded_section": "6C901358A772231DD98A3887EE3F43DBADB5219110002BC0BF28D21A7964B7F0993AE4F5B0EB90013C3E4A659C9FF925633BE6B56F540526D0F5ECDCA82350FE06A01B7DF9180909C186D3892E87DFE229957C59982999EE546326D04870BA1F7D953C8F4E7BC2A62F0940C9C1",
- "identity_type": "private",
- "iv": "668CB07C7E17BBC9C738DB7DDE67F0B8",
- "key_seed": "D86A2754D9774433632916979DA1EBB2D15DEBE68568D976D6F611E7767C6CD4",
- "metadata_key": "7D9BBF1CBA464E5B3D3E1132C99C3D2D",
- "section_mic_hmac_key": "16C2939D01D4B63ADDBC2CE217C412B1DB240E79171BDF904BF90A2F0E5DD55D",
- "section_salt": "2BC0BF28D21A7964B7F0993AE4F5B0EB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A4F08E8443AAE40F4E7DAC88701D0A61",
- "aes_key": "E32648F00DE2B1472DF2AC0C21D46D41",
- "data_elements": [
- {
- "contents": "67ADC5EFF86C7C6823C644A2",
- "de_type": 245
- },
- {
- "contents": "A2FE5429988C99F4608621F625D2",
- "de_type": 446
- },
- {
- "contents": "CDD480DE03360DAE07242D23F079",
- "de_type": 236
- },
- {
- "contents": "66517DDF7ABCB8577D19413F67E25F",
- "de_type": 307
- }
- ],
- "encoded_section": "7A90138693FA8FDE6BC60CA1E4714073108989911000C10DC9C0C4A68B9018C3488D10740CBB90044E395EF33AEC517158560D95A90F95FD4F901983D6F8FFDDB7B22CA5054BADD29B844F5E589C81D03EB39FC74D0E88B8D6D708CB0A8A8073FEBC2DC580146760537167FD194907D3DE050A6CD1807E2A7B2BC9",
- "identity_type": "provisioned",
- "iv": "40B3E8038361FDC0CA520885C4BA45EE",
- "key_seed": "12CA6E10625D8A743F3980FF5B82786D1E11A0B2E7095D1C60B6500947C7A80F",
- "metadata_key": "47D63E40F400537213FA6C39741EA95A",
- "section_mic_hmac_key": "C2DC1307FFA2E742682513F21A7F585D155EB98549978992A6561DA4F9C2779D",
- "section_salt": "C10DC9C0C4A68B9018C3488D10740CBB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7F3B4AC49A6859D7121614C35F5B54B0",
- "aes_key": "A0E754DDBDC126DED5C2E5BD3ED151A8",
- "data_elements": [],
- "encoded_section": "379013F66D7FA47F0BF107AF009FBD4FD70BD3911000FD6B5B75A82F46AD1EE3944D6229D1059004094FD3464A10B7EBB9FD171DB106A835",
- "identity_type": "provisioned",
- "iv": "5F212B399449367351A9BE5E8CC87ACD",
- "key_seed": "687577B839C89F80ABB09A60CB09330F201F7E109C18AABCF5B7CE3ACCEB7C9D",
- "metadata_key": "9190921467B2FCFC928327A128A00D5D",
- "section_mic_hmac_key": "EE0BE709ACDA6445F99E7F9709367F1970CC0FF034BB9BAB2525B06838192DE4",
- "section_salt": "FD6B5B75A82F46AD1EE3944D6229D105"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1D2E3A430DA547BCCC40814B7CB98093",
- "aes_key": "EB9DE857753B905D9DAD3D6D68B97845",
- "data_elements": [
- {
- "contents": "7D25",
- "de_type": 960
- }
- ],
- "encoded_section": "3C90138C32DC48034E13962C03225C7CCC98E19110001F9ECD3C6A5399AE4A22D21D04D50F3D90022E75DADE997D7635B4AB53D54DB577263C8E60D0F7",
- "identity_type": "trusted",
- "iv": "DE93D4114DE77843376E66C9C1FED8C8",
- "key_seed": "FF1AD1F98E7A02BFD970E2E6D969E4BAB06F89AAE1D901C5158ECEA444EE7569",
- "metadata_key": "0A83D4CB8541829EB4E13989DEE85722",
- "section_mic_hmac_key": "336BE3349032B9BE9AC4E030B439CA29C22300C39C29A768E5429DFDD59CB347",
- "section_salt": "1F9ECD3C6A5399AE4A22D21D04D50F3D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95EF9550DD4E6DAB348F32EC6ACE9ACE",
- "aes_key": "9282028C74EA00E0A695AA0127941CD4",
- "data_elements": [
- {
- "contents": "014FD0938269F334",
- "de_type": 26
- },
- {
- "contents": "B419499BCF2AD0B5",
- "de_type": 732
- },
- {
- "contents": "998BF95EF3754B4684BA80",
- "de_type": 84
- },
- {
- "contents": "61BB19",
- "de_type": 525
- },
- {
- "contents": "E911B16D15B9D70D53BCD3B27705427D11C34D8EC29011A6FC33A1205D",
- "de_type": 9
- }
- ],
- "encoded_section": "7E9013F9317F3EF17F72D0E6E671B482D48FE8911000A5E06CFDFE69CCD42F56062A56578B739004E967DC13B2AEFE2F508828E75102BA7D102B73D8563823F379ACE502595F925B51489A8A865904136429350CA3FC0E80475D5EF603BFBBF13483E718CC349627424499020BA3738BF25127BCF7FB6122FFA582FC9D4806",
- "identity_type": "provisioned",
- "iv": "0B48A691BEE1A64AC8D64656A4C6E8F5",
- "key_seed": "BAC80598D5D058B07BAB96DD55772405A2E8A8F533907534D9A0E3FAA9F30F8A",
- "metadata_key": "F759E495DD16BC4B4536A72A4FD88C2E",
- "section_mic_hmac_key": "A69B4595E2EF8D19BDD30DB2B3A6C6890840D061A2516C12B9C137832906B7FD",
- "section_salt": "A5E06CFDFE69CCD42F56062A56578B73"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "70F3562E36D87A53735B298C8920DCCE",
- "aes_key": "2A04329E89E63A6EEE1E5B9FE26FF072",
- "data_elements": [
- {
- "contents": "E26993B71A36032D7B6BD3BE1DFC1A916A6BFDE486468C",
- "de_type": 619
- },
- {
- "contents": "4E4B6D3471BA6DE8958649F7A8F3F2D1D8B858BACA4F9D737E622F",
- "de_type": 159
- },
- {
- "contents": "0C30D8A9B7F50CE9EC",
- "de_type": 992
- },
- {
- "contents": "D682BEFA334E31CC3D253BC9B8F9E7",
- "de_type": 379
- }
- ],
- "encoded_section": "8D90137C433C789FC67F116E0B42170BBE1A2C911000ACC738CA77736DA78E61AE2F8BFD56EF90029BDCB44AB171091ADCABA9B4C47698F06A60E7785AE6EB868FA0D3508C4028357D558423ABD64E685A53B84E7CEFBA04B41B7AFE9701E27C2A655BB0FD8E4BACEED81D020887BDEAD433D10A2ECC65781E33C048D8FB20599660EF16CA4964D39E1775E80970",
- "identity_type": "trusted",
- "iv": "1AA5C3111877402AB12DF3A5D98BE228",
- "key_seed": "23FE203BEE209B85F8FBFF96FFD45C5CBBBA541638C875E7D3E882407E75BF0A",
- "metadata_key": "9D984FDB62E86B53E9D7DF7A14C9961F",
- "section_mic_hmac_key": "3D5C46804EE11C44B04E69BD02A26FC9F8140A98E0BF5B6B28601D9BA19223AE",
- "section_salt": "ACC738CA77736DA78E61AE2F8BFD56EF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E17588ABD3AE8E7D6C334D1B0AF92891",
- "aes_key": "EC4481D436C1713129486151E496D152",
- "data_elements": [],
- "encoded_section": "3790139A5DA17E993C1658DBFA6658604A3001911000D08F272BBAB54B86764CDE901B979BE09002B897890E043267F8EE1F98C5F9BBDD30",
- "identity_type": "trusted",
- "iv": "251B33B9AF829B6ED1ABDA627054F6F7",
- "key_seed": "EAEC6309BB2C6EFFBCB0C2BE01F11E4F90F5E7B8887E818D5AC1D4A7DB57069A",
- "metadata_key": "F542D812841B2DD775BBB4A8410C492E",
- "section_mic_hmac_key": "F67EF00325C91A6AB801927DA0B6796DD8DC33C90329FA717824EE7E180C1760",
- "section_salt": "D08F272BBAB54B86764CDE901B979BE0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2345A6D584F3974CF098E8C192904039",
- "aes_key": "4DB8F7C88764BB94D3A3ABE8A1F8AA20",
- "data_elements": [
- {
- "contents": "FBD07BACA069E273FABEB5458519AC66",
- "de_type": 270
- }
- ],
- "encoded_section": "4A9013928EE6E8ECEFE0F28379CF5C9032291991100098A4C16E5FDCB9E737355B6BF7EAB38D90028A111BA84A1E974CF9DEB93971DA7789A71713E4BFAEB4AC83415674B15BAB0CF85A89",
- "identity_type": "trusted",
- "iv": "212CD8997AAA9236F1FDA4DB9BD918A7",
- "key_seed": "67E2C8B99AAEE6CFD7809BF4BE4439021C1917798195E90C095AB601C718CE52",
- "metadata_key": "F1FEE18C49BA92C3F2F65E445A273F17",
- "section_mic_hmac_key": "76ED254493D473BDC8188E855AE215771406C7EAD2655C0699E1408905F39146",
- "section_salt": "98A4C16E5FDCB9E737355B6BF7EAB38D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F9AC3BDFBD989B3B7B99227F4A75895E",
- "aes_key": "F4A4A68E314433E1525A20A7CE56CF0D",
- "data_elements": [
- {
- "contents": "8953B51DCADD4B6DDAE1F254D6FF075F023EE782962BA2E5EC3F",
- "de_type": 51
- },
- {
- "contents": "3B90B29DDDB595115F94",
- "de_type": 474
- },
- {
- "contents": "3AE3DC2B64E42DEE4591D3017A373707622603E768FF",
- "de_type": 420
- },
- {
- "contents": "606367570FAEE5",
- "de_type": 567
- },
- {
- "contents": "8058E4",
- "de_type": 400
- }
- ],
- "encoded_section": "899013F28C4419C0F39FEF91816ED59BB640CF9110008A20C8F8A8F8066BCC1BE4A65AC5792A900117084AF29AE92FD19FA96EBE5C8A2A42563981458E841FB326A570E844CB1C9DF86C5ECD71E381212CA1AB349CBAB6E08E587987A237010D73012F12DA01137A6DB31DC714AC92A7E6ABD3D25D66DDD4A3F017E36180B1BC81BE906A37A7E5847306",
- "identity_type": "private",
- "iv": "001886333197146B65A467C6A5ADABD0",
- "key_seed": "9FD56F525349238F02680E5213FA5A0976841E232787AF705FBCBC9B20064E11",
- "metadata_key": "688DE85D9D408FA2DE99A56F603BA664",
- "section_mic_hmac_key": "496FC8B5DDFF85EA5AFB6257048F16A63C38E6B1B0B6880B6DC982AC06F61F5C",
- "section_salt": "8A20C8F8A8F8066BCC1BE4A65AC5792A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "82BA44E40EE515F4EDB7BD0835B26BCA",
- "aes_key": "E63C191EBB567BB2A374A6C5CA7789B9",
- "data_elements": [
- {
- "contents": "936AD5B9E6439EFB69339392A4FD2913",
- "de_type": 897
- },
- {
- "contents": "BB64D6B15EE9AAA7A2A4E90CD9D3D7DFF853855652F3C314",
- "de_type": 128
- }
- ],
- "encoded_section": "659013898A83F5E4A7D3DB3F24B83BBAF8FF0C911000A9BAAB812351BFBC259E10C891B67FB490020580A146D32401847A52599D99C1059DFC1B9E2C00E18BE478924C134C5EF2FCB007EF712EDB4C8A69389EA6AAE580B3A3D549891C657768EE03112B204B",
- "identity_type": "trusted",
- "iv": "A40BE5CD2ED5BB0EBB4725421B8DCAC5",
- "key_seed": "3A2C30261D095C238E882B56F8D8CD61B607E7386D35FE3DF3C577A501D583B2",
- "metadata_key": "39DB2F2278DB54194F32AF85B1E78C21",
- "section_mic_hmac_key": "DDBDFB689EFB7F278636DAA76509101635BD2F29F5374C2FE5FF61C0BC7777A8",
- "section_salt": "A9BAAB812351BFBC259E10C891B67FB4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A8B3C773BB49A28374AB878083EF4DD0",
- "aes_key": "A7AE16ABAAB4F23FE69F81219078B6B3",
- "data_elements": [
- {
- "contents": "941B67D98B",
- "de_type": 482
- },
- {
- "contents": "B56226DF686EE11F00F46D8EAC2FA6B3",
- "de_type": 124
- },
- {
- "contents": "1DAEF38ACABF3F7F72E0C36D95CE462F",
- "de_type": 451
- },
- {
- "contents": "C5AE1183996F56207CB46CCF9292D5FE2076EC2FC7DCB8BC5B5C",
- "de_type": 200
- }
- ],
- "encoded_section": "8190131E760FF2E9791B7C00259DE6622D097B9110008F7B71C5430C84A4A66BA8D98FB94F4B900234D15FEF96C1A3789732CCB516DA820979DAC80D2385402A65AE0C15A2234225C44833EB9FF44685B5C5F63331C9A54DD49754676E9A9EFA33BC008618F6FF6EFDA711690EB21B15E1FDD560000C2914756DE9B3ED6F3E26972B",
- "identity_type": "trusted",
- "iv": "A3F606AB7B1C0576ECD16E9FE421CDD9",
- "key_seed": "9B041D4F0C1EF90F3FA1F40CC00F8E2B5F76237D87E8A3532B59953F72C44806",
- "metadata_key": "654C72908F7B826008996F7F055E37BA",
- "section_mic_hmac_key": "9F368D4991C333653B18B8E47BC2228B4B8AF094D9B0CFAAB697EAA4BDDD0EDB",
- "section_salt": "8F7B71C5430C84A4A66BA8D98FB94F4B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3FF717A2F51020F0A8E7EEF5A58FF598",
- "aes_key": "6B159573A0B1AD7A064F2B0C7E112009",
- "data_elements": [
- {
- "contents": "170495D7E094775F3FE95D8B687AEED4201D2565013BB6D143B4368AB3",
- "de_type": 261
- }
- ],
- "encoded_section": "579013C0015142640B5256342482B97540A7F3911000391F6DD321079B0843F5D827A33F72FC9004DC8B35CA45AA35A6FBD7B3775EE4A1E612928B2B6F7915B574AF3B76C69D151D7B6948E811B99489CC62D223399F4007",
- "identity_type": "provisioned",
- "iv": "DB8D8BB540FE93482C143E02B46DBB41",
- "key_seed": "2A25270DBE2575BF55DCA0EAE26CFBF9B57CD40F4F3676A108C187C20D4A6F26",
- "metadata_key": "970D974CABAEDE9ECFE8B1A9CC874879",
- "section_mic_hmac_key": "405D13A8D5CD5035A191FDB35DD6D3EEB16ACDD4253098B9DF5626EDD56F7329",
- "section_salt": "391F6DD321079B0843F5D827A33F72FC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C604ED2EC8A3D1C29EC5A827AE9EDDA2",
- "aes_key": "52795E8FBEF4F5EB97CC11774B1B3C3B",
- "data_elements": [
- {
- "contents": "3E",
- "de_type": 834
- },
- {
- "contents": "682F12CA13A8346A46FF",
- "de_type": 549
- },
- {
- "contents": "11DD9D8544F5BF2CA35D580E223AD090D48C62E3085AB6CFF4A756",
- "de_type": 194
- },
- {
- "contents": "A949786794EB5D",
- "de_type": 543
- }
- ],
- "encoded_section": "70901355836184F4627B8EC7B78B6BB25D230A911000B462B56430FA636C4A6077DAE3E8490C90014B885213D89DC53C660697E09A405EEF027A56F667D32250711FB9AF57E6B173293D4EC62278A5047EE2D95D71CF8297D0BB81882856A9C03855BE2759368C3B68A19E2B7D4926DDF6",
- "identity_type": "private",
- "iv": "9FB083D020CF0194A51614C38F4CB78E",
- "key_seed": "BB328C2C3773B18C637890F7F307C4D5EE297251BD0A3F101061B7C7DDE4436B",
- "metadata_key": "2044D85EFE05830A56C3828A60E1B22F",
- "section_mic_hmac_key": "9296C374AAF9CFC2E968F9D212EA9FAA10E7CA1712E740F8C423F58377DEBEA6",
- "section_salt": "B462B56430FA636C4A6077DAE3E8490C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E4AE638B1788F6A4A7AE8A95A170217D",
- "aes_key": "F86260862227268C0AC94B2821714BEE",
- "data_elements": [
- {
- "contents": "095F42586EFFA90A02AD1377438DC0FB442F8BC36B084071A340",
- "de_type": 991
- },
- {
- "contents": "21D38A40C8F0CC8CD37E8B99E395",
- "de_type": 663
- },
- {
- "contents": "0610976CBF91C272697FF6F3DF90CDBF",
- "de_type": 331
- },
- {
- "contents": "C46F54",
- "de_type": 806
- }
- ],
- "encoded_section": "7E901310E81093792AB0299A1F5B9AAEDC438A911000FE1897EC2C7F696F9A12BA2E3AB8FF109001BD9694097F3C01B81BBAE58DC0AE45DCEEE6725DEF44E95C4651F50683E6E1452ECE362EB210B8F69E64C2147D7ACCB82C7A8FFBB1872CFB90BD33A33CB73837084C658664373AB183EFDE54555E374E0282DBE99F4FA4",
- "identity_type": "private",
- "iv": "0B8F21A0532C5CC2183796C8116C1AB2",
- "key_seed": "144F46384687F7622633B6BF79597124B6602947F71FE56D358D8255FE706F75",
- "metadata_key": "FBA8A028F20EDC2617B4EFF42F1B6449",
- "section_mic_hmac_key": "6842368E240421D08BB41E23656533362CC290661EF54E887756D7BDE52E90A6",
- "section_salt": "FE1897EC2C7F696F9A12BA2E3AB8FF10"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "21D9EBBF5909A89E702560D71E29B2C4",
- "aes_key": "81CA1370B0438486CCDB17555BB775B0",
- "data_elements": [
- {
- "contents": "111FCD56D62B43",
- "de_type": 52
- },
- {
- "contents": "C15A18724AC7E528B46E9E35F7554B1209E7F902A60333061B5381",
- "de_type": 424
- }
- ],
- "encoded_section": "5E9013D9B742F3C9077E30BF514C324378A6A6911000074399230FFE3522BF65A0E4DCCEEF149002A212E54AD7F78EE74E021C037C9C0B3A4493EE50C04B6BD43D728CCD62DF48707D3D3503E56426ED0CEC9DC87AC7FC6596B8DC23D4E10B",
- "identity_type": "trusted",
- "iv": "BD67CFC964A067113164BA2579085C26",
- "key_seed": "63FB25167C581FE8ADE6766A9CBB04B2D734564EA92161E6DF67C3776B7589E7",
- "metadata_key": "93081F4B0D4644A3EEFB094ACADCDB72",
- "section_mic_hmac_key": "B01F9FFC04A6ABDFA23B54EE3A0855251B07ECBA387FAC32783C2D1E31502187",
- "section_salt": "074399230FFE3522BF65A0E4DCCEEF14"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "376F7973FB47B8DE4EFBB10BA01B4CAD",
- "aes_key": "AC46F566457606055B133DAA5632FDA9",
- "data_elements": [
- {
- "contents": "4FABE07C139A4BB10FED0547",
- "de_type": 717
- },
- {
- "contents": "B0A28EBF12",
- "de_type": 337
- },
- {
- "contents": "2EC51325F981AF5E505025CF2432078896A5A4C5079CC2AF4067C5A9",
- "de_type": 565
- },
- {
- "contents": "B50C",
- "de_type": 246
- }
- ],
- "encoded_section": "72901355710202686237786A7FAB75ED3F998E91100094670B48A85C57471200A7A15C35EF2D90044551AD5E4D9C0F656F0D5A1EF39F021CF714060E5F72C5E4165827B2D33B39A68AD8E0B747C2FCB223D61B51C4CD32C0C14273A496135AD4459FC8615EF2D076B9942FB9D6A3F6A39F8152",
- "identity_type": "provisioned",
- "iv": "1F042222693F97550BC695DE068B0F27",
- "key_seed": "B7CCCD49D67B3D822F0EB6389CD28D0D0F709EBCE75A1D41CF78BDAB9C649F8E",
- "metadata_key": "D484AF3D402DCE7C7765AFE667044B4E",
- "section_mic_hmac_key": "9D04723E57927BB0E47023BFFFB73D7ACD3A75807E62C48D34D81F47DCD2213C",
- "section_salt": "94670B48A85C57471200A7A15C35EF2D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "633A93C20610A1F816E80581D99A8B3E",
- "aes_key": "4371A9D1A3EB70A57E84488A54E24687",
- "data_elements": [
- {
- "contents": "AD8C2BC724A8477BCDABB0118A33D84A98C8807FB87D9CEF9FCAA3D1",
- "de_type": 853
- },
- {
- "contents": "01B3970FC3FDD7E7ED030AD7AAF1AD72863B93FA61",
- "de_type": 658
- },
- {
- "contents": "8780D33466F56DB455D0D46E24CC32AE0695308F2F63BC6548B4",
- "de_type": 728
- },
- {
- "contents": "8F76",
- "de_type": 45
- },
- {
- "contents": "94F61429E70AEF3E8003487BAB3AE1D6319FC95FD097672D626F",
- "de_type": 65
- }
- ],
- "encoded_section": "AB9013195BA9A9F3767992302308D00CC1C1EE911000D293112ABD9E9E2DE6C9580BFBF3EEC590047F67987EF7E1FA205D9F59BFD255EF665258B5DA63CDD2CA567DA31D331C085AAB47056FB34C5637C13EC88A08BD9D7D96250A8CE4B314B4FAA00870BBCB5F2B060BE6492B524821708BD765303EB55C2C3DE721F34C3249BDD36AE5595B6AD9E9BAE6925E0BBEFEF7D5400A5BB802BD8F96D54B15C2F0A4E672174CEA6E0EE5C2030648",
- "identity_type": "provisioned",
- "iv": "EF05D22E05D50648CE4B24BAB3070391",
- "key_seed": "63626EA34F2C9B87028C0977809D2F7768E73DD48D9D4BC4E9A8AA6AB63E51CF",
- "metadata_key": "A028CF69452B18E0B48C12F43A92BFFC",
- "section_mic_hmac_key": "CC71E5A17B3F67FC8293349047F85966CC1D2107A6C9A868904CE012FF6D1EB7",
- "section_salt": "D293112ABD9E9E2DE6C9580BFBF3EEC5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A2FAFCF0C3D4653B115D3C2BE07661CB",
- "aes_key": "D3F0BD209D67F0C6793F151852DEBD06",
- "data_elements": [
- {
- "contents": "82A3CE3347A4",
- "de_type": 831
- },
- {
- "contents": "F3AAF8D0",
- "de_type": 633
- }
- ],
- "encoded_section": "4790130DB30D981DE33703A0264019ADBDA644911000B76D1505FDE3A6DB5745C79C2ED803CA9001486C1A884EB0CACB9ADF1F0D7FF508AB81EE16696136F0FA512B4FD6C6A16B9E",
- "identity_type": "private",
- "iv": "A35D9428CEF6CA021B52076EA6DCB262",
- "key_seed": "CA2DD34D998FEE70368831DD2798E0F1936A589B1C1A5B60FA3D0A4C8D4E0FF4",
- "metadata_key": "599B29224832981BD60E11082FC157C3",
- "section_mic_hmac_key": "5095030D99F2E81933347E8311CE3391BD1FB3C0B5F9397915FD1ACBC0B1494B",
- "section_salt": "B76D1505FDE3A6DB5745C79C2ED803CA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FE6A04FEB87E30414222FE02FC1DED3C",
- "aes_key": "AD143FFF025A7B908F3028F255017A0F",
- "data_elements": [
- {
- "contents": "B41FFF16CE",
- "de_type": 692
- },
- {
- "contents": "C5EE2285043F76FF038B30EF5EC3888A9D9EEFAF6EF2C4A7F1",
- "de_type": 275
- },
- {
- "contents": "4F22FC1B2C68EFEA",
- "de_type": 389
- }
- ],
- "encoded_section": "669013AF4FE79DE836E8BAC2A418D44693F4EC9110005DE51155F2A2EE8C7E16026723F4B81E900295FCF7C7A95DA0AADD01DF2EF798AC707CB88138553B4DECBF061D353A6206561B4756BEBFB3536AF66EC01D29C4842F1522AC4894BE7B69927FA6DE2F5B7F",
- "identity_type": "trusted",
- "iv": "983E35C1E9170FF4EB62F9C900BFDE14",
- "key_seed": "3894FC2EE542091EBD73841E9C92E846682B47EE41ABC7BFC9A6CFB9C7EC4282",
- "metadata_key": "0C17FCFFDA6B8AB386C3D801A33DDC7E",
- "section_mic_hmac_key": "310376D63A925F217B048D0E4C6908764C80444503F89A3AA1763951A33FCAFB",
- "section_salt": "5DE51155F2A2EE8C7E16026723F4B81E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CEB2DB3907DA1426F9AEE8AAD33216DC",
- "aes_key": "33F5AB96D76920C2F144DE4962D862ED",
- "data_elements": [
- {
- "contents": "0E094C04A66FF6909AD423192740",
- "de_type": 511
- }
- ],
- "encoded_section": "48901337DBFB04B30BCF0A8422AEED7BE57B73911000636EAA5C104EB02DDC7F6EE4968AD387900179756A7F8E031AA7411DC75308F251B330B7FE2D754B5E999D9DB499716B48AE6E",
- "identity_type": "private",
- "iv": "79A3FE62EBD753E71B1445F203F5F781",
- "key_seed": "B2B7DDAC8583B3D6E27434EE969DEBA37C310AC0764D86B202280244015F4D4B",
- "metadata_key": "4E807DECBB61C3EF3A3530264B354C38",
- "section_mic_hmac_key": "50A2AF48A3375502973C8E59A22E83359F137EE2391724F8CEA70E71D7DA9FD8",
- "section_salt": "636EAA5C104EB02DDC7F6EE4968AD387"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8581CCA00A9614D0A2F3F513490ADC2",
- "aes_key": "9B6D1622C67BFCD29AC65E8A5B503A9D",
- "data_elements": [
- {
- "contents": "A1AF",
- "de_type": 717
- }
- ],
- "encoded_section": "3C9013926DC8C5AB1FAD70EA31134CAFD3EDA9911000ACBE394BCE0BA06BEBA61EE1737000CA9004A9631597C4C3F54FB2DE97D60CB38982950678FB41",
- "identity_type": "provisioned",
- "iv": "82EAD32BC4E1860FD17E049036F408A2",
- "key_seed": "F6B2520AAEB47FCC56D10059ACB35A41937374E73497583FC997CD9643E2E0D2",
- "metadata_key": "312D0D394B55AF6328C2527FA2754E92",
- "section_mic_hmac_key": "077FE6345CE01680AACD3CD7514C8B248F35325D8EDDA3BB4AE284D01068340B",
- "section_salt": "ACBE394BCE0BA06BEBA61EE1737000CA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A8936F1979C158886EA3687E6802647A",
- "aes_key": "C123C7A271606C99EB7F65A90594DB01",
- "data_elements": [
- {
- "contents": "503EB3",
- "de_type": 360
- },
- {
- "contents": "DCEEE7F22896FC9B32B55C34A0FEBD5443F897062EDF",
- "de_type": 693
- }
- ],
- "encoded_section": "569013AF54CE1D3CBE08F7711B3755799477B3911000546E3934E379D2D397491FE39A9C82FB90028608200CA18E4F6256DDE1C34367161B23C14E639155B0D9A24AD8EDAC13316CBBB6F45BFE2DC243C9259D8E66ED46",
- "identity_type": "trusted",
- "iv": "5BCD15EE9166022B1383FA6733B14C25",
- "key_seed": "21E6F589CF96987FE3A3CB4FBF3EAF56F057D19B1E95A312AC51A43C4F810A0A",
- "metadata_key": "13E4BB8217379D14813705DD1D830EB7",
- "section_mic_hmac_key": "0349739276968E6FCFFE70B6CA646BE03C7BA2A905B676C37AC67C9174C5023B",
- "section_salt": "546E3934E379D2D397491FE39A9C82FB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1BD514F1002291FC8579AAF845DF2230",
- "aes_key": "DD4891029D9730B48DE4C95DC2B32849",
- "data_elements": [
- {
- "contents": "2DD2428876819B13D3",
- "de_type": 842
- }
- ],
- "encoded_section": "4390131A15BD6E7E99C7DF950BA8486CE47426911000A3C9342FBF29A1B56D1BF70A126385899004066176CFC62D6CDBA8BDABF873C1B76C928C16281576D8EC953B356C",
- "identity_type": "provisioned",
- "iv": "DBC1EC47C39EED7FC5BACFCBD3E50F33",
- "key_seed": "119A29D81C336C1450B9A52B08D5FA1C82BEA2F7EA53EADBDC786F17EA5174EC",
- "metadata_key": "A11144C257937AA9AB72AF4D400943AE",
- "section_mic_hmac_key": "77495025D48B3D4BA26ABCB62AC9489A8CF1EEEA8540E85B22F44F6F70302EBE",
- "section_salt": "A3C9342FBF29A1B56D1BF70A12638589"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7CB42CD67E6B64297634ED57EE9A84FC",
- "aes_key": "80748A341D96F6CF336DF1A491AB1DB6",
- "data_elements": [
- {
- "contents": "96DA066AD9185B22D2E69A26F2D47377",
- "de_type": 529
- },
- {
- "contents": "8C54B317A75F31CF50FC60B0FC7E1BC16E",
- "de_type": 943
- },
- {
- "contents": "63FB812B761B5EA081E0E7743F2BFDCFBCF360083F3C46",
- "de_type": 638
- },
- {
- "contents": "26",
- "de_type": 4
- }
- ],
- "encoded_section": "7A90132D1AB37039B085A7A9C70BE256B8094A9110001CA7C89408F3F729EAFB6FF60C3AFD049004AE29327125D2A449F33B1E6A8A7AABF9FF1B96CCE102DA7B3D0D8F9F828163A7D7BF775250D2C8EBD9C2DFE30CBE79A1AD0F5D3F40868351D67A6D0D4BDB8EE0408FB6E59CA2C19EC94D81A05DC10B685D26B4",
- "identity_type": "provisioned",
- "iv": "14C33DEE0CD9255F91CB3DB918642ADD",
- "key_seed": "E0C0046701BC9386E772D494429939639AF9845521C2718C1ADCC28BACDBFFBA",
- "metadata_key": "B16130046B39490E2360E8249AEBA2F5",
- "section_mic_hmac_key": "77D4D3388B0329728C3D684A0513235BFDF00100185824A42A29F1833081B293",
- "section_salt": "1CA7C89408F3F729EAFB6FF60C3AFD04"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D3B33E595721C50D2105135754F892D4",
- "aes_key": "6759279E5AF9E480F163DE933C79D7CA",
- "data_elements": [
- {
- "contents": "5A",
- "de_type": 459
- },
- {
- "contents": "876A88BB07E3",
- "de_type": 919
- },
- {
- "contents": "650357",
- "de_type": 366
- },
- {
- "contents": "3965C8AACA7BE822FD421DCDD5416DEF11A5ED",
- "de_type": 182
- }
- ],
- "encoded_section": "609013E4263C83FBE154EBE9B418C8E1F92A2E9110001C68B664FC0B6735A00A9C32DAC328FE90023E487DCF351F9A4B55726B5324627617478B27454D994520BE41E126B4F0FC225770EECBCE400FDA160986F267A97446F5EE178DB730669B5C",
- "identity_type": "trusted",
- "iv": "FC06614343EE9CF8E5A4D06EB3594318",
- "key_seed": "5F6F3840D07D9C758A5D3FA6CF48325B79DCA9357C30DEA1E35AD885916612A4",
- "metadata_key": "7C701457BE076B13A91CB3033AADA84F",
- "section_mic_hmac_key": "0964A5F27C3EE5BC3CB8DD22F71FCE6F30C9B15BB4DACDF2D04FC5EA4F909881",
- "section_salt": "1C68B664FC0B6735A00A9C32DAC328FE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4A0B5B35DBA6225783403F4DE018659",
- "aes_key": "473B79E267C0D84E4412A4093255563D",
- "data_elements": [
- {
- "contents": "33B53C95303F25",
- "de_type": 993
- }
- ],
- "encoded_section": "419013AAFF2B02E2B22C8C7AB49138C7BBBD129110000517504587FC306540BE7FE50F18898F900444C2F40376DAC920EBFA282D8EFF436D9A36B53B58D5BD48ED08",
- "identity_type": "provisioned",
- "iv": "7CD1649D9693811DA48B34243B254D09",
- "key_seed": "FC839072ED4097D2EE824442D37A0F95B80BE907398E946F0085ACF1709B5013",
- "metadata_key": "F62052D0301C5441B3A568D4294A8523",
- "section_mic_hmac_key": "282471379DA6B963F2436B4AE2C5FC3348826856CDC1FB0F8253115B208F8B2D",
- "section_salt": "0517504587FC306540BE7FE50F18898F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "93CC5E3BEDD29966EBFE44F20068ABD0",
- "aes_key": "0E7C22653A3C4E73E38247BD04BBA53B",
- "data_elements": [
- {
- "contents": "AE8F1926F17DC55FDA14D4D112FF57872DCE3C90D5",
- "de_type": 532
- }
- ],
- "encoded_section": "4F9013DD23F4E8CEE064993278A409CED7F59D91100024B889D2BAC8DFE8490B8DB914A2C6179002B9CCEADF1CCCE30FF715B151BF3376ADBA9A4C086F89C357AD894C88A85EE085EF3E4A11802A2A78",
- "identity_type": "trusted",
- "iv": "3EC81F59D1FCB6D4F75A7027CE96B1A4",
- "key_seed": "0C290657B22EAA068CC79DE1762BD7AE049F34DC9801C029C183C20B7641E2C3",
- "metadata_key": "9D8BBD240583337C47347E2E3527305C",
- "section_mic_hmac_key": "C8887D8C621FB6A6FDFB0BCC033014D68EE1D6E4B3587EA4BE7DDE9F3981C430",
- "section_salt": "24B889D2BAC8DFE8490B8DB914A2C617"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C5CBBCC948D1D87B9AFD66807377E695",
- "aes_key": "8A9C73FDE45E8AACA4CD44F6DD70418B",
- "data_elements": [
- {
- "contents": "9A2BC2BCFEA2",
- "de_type": 48
- }
- ],
- "encoded_section": "3F9013A5F912E862C431DAFC9EC3B5E8E7A958911000F7F65F4A4F260B1A6FEB1A59AD18C1139004F28E1460E2D4086FEF3182AE2343658F4D6A362C6F3D7A3E",
- "identity_type": "provisioned",
- "iv": "2D897492AACFDE004CC854FB0837712C",
- "key_seed": "7EA6A1B03842D637543676B12E61F6D9F1C60C9FE015E30D53AEF8D698F317C2",
- "metadata_key": "EB718446E9F62D1D5E1C71FE9DA626C9",
- "section_mic_hmac_key": "3B4CFB52E8711CE0B1154C45AD7C1A05C36F26307463C4DB5AD8A584EBB74487",
- "section_salt": "F7F65F4A4F260B1A6FEB1A59AD18C113"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "65A047E0391416283B7306BDCBD0DB41",
- "aes_key": "E5AC27A9E1CFD23C71098444F5FEAFB6",
- "data_elements": [
- {
- "contents": "FE46A0590767816BEBF65CD0A06F0248F6060C86C6552155942B12",
- "de_type": 53
- },
- {
- "contents": "04DB45",
- "de_type": 573
- },
- {
- "contents": "4120206B315914CFE259150DCC0643146D86",
- "de_type": 269
- }
- ],
- "encoded_section": "6F90134653404B3A826DA5D63380AE51571889911000434EDD9F18AE06EBB1887589C846F4E19002F724DF5E9B4A15ABDD0C93D42FBA6E44D5B0C564A2364B59B4F8AF594071B81F429CEA6A6A97D2808C57378A1660A528C7813D9FE4AF8E6A8A82C2F0EBD3CF4D95E4DEBF15C2EB22",
- "identity_type": "trusted",
- "iv": "940185F0052AE8B5655BEF6A900141CE",
- "key_seed": "725E4D87BD5610F4BE9F424729C7BC6F3B89C7A5FBB5FB976A405BAEC28865C7",
- "metadata_key": "5529FCAEF9E42680CC37BCF7A52CB571",
- "section_mic_hmac_key": "1072211CFEE4A9B080F5CE4A682975C8C702B0D25FFB50ED39673238EF61AAD6",
- "section_salt": "434EDD9F18AE06EBB1887589C846F4E1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "11B8A815C96272426FE670EBD95F2A74",
- "aes_key": "9CC50A2EB9DC906838B319D6F635B290",
- "data_elements": [
- {
- "contents": "CF8CA8F97258BDAA03C9F47FE93C73628555F7B7188DD071",
- "de_type": 863
- },
- {
- "contents": "50DDF94F9A90AF06402A8EE4E5E0440C068557",
- "de_type": 140
- },
- {
- "contents": "FD530CD016",
- "de_type": 560
- },
- {
- "contents": "3EC44909478F",
- "de_type": 565
- },
- {
- "contents": "9322306E45BE",
- "de_type": 259
- }
- ],
- "encoded_section": "829013111DE9F4FC976D1FCB172FF6475BC43C9110000DA35B02A62A0DFD3EEEF6F0C95B67169002D299BC5DEACAF00803395A88EBC7286257F4B34EED000A0D84C2B5697992CD343E351FC180BAB101781C0002BEBF9FAF4332F2D568B6E928BD2F3C990094FF1EF912B8EBC584A544FF6D769A320755F673C8F82964AE77516FB951",
- "identity_type": "trusted",
- "iv": "8AAC6F64AF5CD7541A317ED78BDDB48A",
- "key_seed": "BB9F80C0E138923EBB663EFC182D0643EB8B9C4A58A98D58C3837AACBB2752C8",
- "metadata_key": "F9A2A06EB5CAF1152BF79B6E21E842AA",
- "section_mic_hmac_key": "4095220E1316503E17A6FDE2D4E6CDF34BEFC40685288156F7446D5068CFA9BC",
- "section_salt": "0DA35B02A62A0DFD3EEEF6F0C95B6716"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A4808B2F62685B5F55475AB574E7E26",
- "aes_key": "AEC76AC229D0DE42E296D372873706DD",
- "data_elements": [
- {
- "contents": "A8CBB6C27EE05402885DDF07B4B192AA53C304C6",
- "de_type": 822
- }
- ],
- "encoded_section": "4E901339AEC7384257FE89C3AAEB488B1E2D289110006ADF613C2421616F31B9639D876AC2B99002EFD645D79149ABCBBB2BAB3C0B00BBD1720EAF50BC23D78FA75B236C51B304C40863AD3FC62F6C",
- "identity_type": "trusted",
- "iv": "AB8EB79353453909672FF436216919D1",
- "key_seed": "50201DD1C8E2AC7B1A62572253D3B22E09BC1F9ED9B3B435CC4A4C3A654771C8",
- "metadata_key": "BF749E18C5E02BEE9705A1E2A8EDAF8E",
- "section_mic_hmac_key": "3DC9AAA970DB8BF9EDDF51BC73AA81AED4227BEFE5B4FB374D33464C9B1C845E",
- "section_salt": "6ADF613C2421616F31B9639D876AC2B9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1F59D9660522D8FBA3B16883F70F11C9",
- "aes_key": "370A64FE5AD9B1FB602447BF4BF9D514",
- "data_elements": [
- {
- "contents": "F67DBEA2F3E590F21C3A313915",
- "de_type": 734
- },
- {
- "contents": "7E112C",
- "de_type": 336
- },
- {
- "contents": "56D3B96A1D91F0CF57",
- "de_type": 138
- },
- {
- "contents": "00EE1F",
- "de_type": 336
- }
- ],
- "encoded_section": "5F901339F817C69D4CF580D378EE7E242984BD911000A71C128E5EBBB0E4FDF891F77639D1E490010D5F79F998BDD9BDF1F7BC2EFECC5EE2F9F994830D2FBA0C803101745C51A41E07AA18ABD1312F3D56CF58841BA20A60D7FE34E36DB0F27B",
- "identity_type": "private",
- "iv": "B092FA4BCCA953F068CC959747D83639",
- "key_seed": "692463627EBDE72CAF060DBA5FDD40E032568C3B81C9DFE4B20DC148D32F7035",
- "metadata_key": "71DF47545B930AF7861785B2A0519571",
- "section_mic_hmac_key": "9FDD7949219C0824705B41969A6B0B39564EB3C376A443F740F9F3983CD9B3F4",
- "section_salt": "A71C128E5EBBB0E4FDF891F77639D1E4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BE2BAFF188D27B3DEBB76D55424CF7A8",
- "aes_key": "11519220C41A2431E087DA954F82DD2A",
- "data_elements": [
- {
- "contents": "AC894032C14D4442280719211CDA8F42A8FC90497439B5A14529",
- "de_type": 146
- }
- ],
- "encoded_section": "5490139DD2CF23FADFFE0C94A6E8E327F720A7911000B38B64D0469A8468D3CAA65B8BB04228900224C6C7A8B2C73344F312ED7FCFF642112C0E3F95526AEBB29729E203C85BC3D9AFCF3050772AF4D320820A0883",
- "identity_type": "trusted",
- "iv": "069FD992E0C1DE2F9D197CC3D0342099",
- "key_seed": "FD4AA1F19FAA7BC4F26ED6AF2153079A6D9F6BF4F144C95E609947E620E07BDE",
- "metadata_key": "C092C09E74DAD832EA8DD576E23BF873",
- "section_mic_hmac_key": "F721743C7C61BDBC19597A30DF414CE7EA3D9BE816140712FC23440F473F1DEB",
- "section_salt": "B38B64D0469A8468D3CAA65B8BB04228"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "77549089D6D3867FA06DA36615503637",
- "aes_key": "AF5B34E65AD38943EFBCC3B3870CFA0E",
- "data_elements": [],
- "encoded_section": "3790139B1BECE4655A5CB45B6D3A30BFE6730B9110001F22305A25CC405B049D1131AA3B46559002410D700D2FE5856E61E834BADD1FF8DA",
- "identity_type": "trusted",
- "iv": "5714AD90F45BAD10E57F8C79C0D16BED",
- "key_seed": "71F4BEA99646F1706EA4A84397EB43CE6B44E381874992EF972617EB640B3A36",
- "metadata_key": "53A2FBE800F5224390B2F5417E7F9C1D",
- "section_mic_hmac_key": "600452BABA57916415DF1C59CEC4E50D72E1BC14B9DBA7842BDC4A3AAAE81384",
- "section_salt": "1F22305A25CC405B049D1131AA3B4655"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AA4A1FB44833A27A2820C26ED4EDA010",
- "aes_key": "C1F9AF7702938F9DADD7257B4478BFAC",
- "data_elements": [
- {
- "contents": "7AED34",
- "de_type": 407
- },
- {
- "contents": "7784760988FFAC4996",
- "de_type": 189
- }
- ],
- "encoded_section": "49901306DC71C77895654B6FA9840DF88823F5911000026B34871390A27E60707AA4CBEE91A190025B45B3472ECEB8587465A76CD0C08AB383049E0E095AFE3EA26DB78E9DD412A1E1BF",
- "identity_type": "trusted",
- "iv": "4883588693CA0745A10C85CF49823C55",
- "key_seed": "75295A1F3E2689CA79744BB328404DB873F3C4BDECCE9FE9C2781494B59D96EB",
- "metadata_key": "4F1AC34364D0257D3CA00300DFB1F1F8",
- "section_mic_hmac_key": "AC27EC75005A294F6A63263B6B4B15981A6FC481B65646FF315A9FD7E1C72468",
- "section_salt": "026B34871390A27E60707AA4CBEE91A1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "078DDE8D05FD1B537A238D6645219040",
- "aes_key": "2766ADE6816F4045B273D4E1CBAEF9E5",
- "data_elements": [
- {
- "contents": "6EBC1F8D58C1565541E9F64D5460BB5C0A95ED1DFC9E29FBBB",
- "de_type": 808
- },
- {
- "contents": "3135E9387E084FCC35B173C0E9F9AB",
- "de_type": 347
- },
- {
- "contents": "DB92249A54ABB93E6797CA85039FA215647FB4",
- "de_type": 21
- },
- {
- "contents": "79288DD2716427CA78A9194491",
- "de_type": 721
- },
- {
- "contents": "73EDF5",
- "de_type": 529
- }
- ],
- "encoded_section": "90901373F65B3C85D86824F42F83B84048C6229110009E38512BAFDF12A3783C75D6C694F62790015B99A08B9D7A88AF8172BFBEE70CAE42260C83F0F60F06B79C125D77323EB12D7F5FD27ED9B916562485B9C9DC9E2DFF08F5B19FCF7CF8CFFEB6B99D95AB5D5EA00384953D3A053681FA63BB86B565B479EB49282780CE91FBA3C2976BC7F7B945BCC3E8A59A6C7F55",
- "identity_type": "private",
- "iv": "EF43F76400A48297E2B662EDDF34027C",
- "key_seed": "4EF8A2BA84737FB0150841C23EC25D43C47FF933FA9AB2C5927D5B507C87EA2D",
- "metadata_key": "378AD8906BDB267835B3C09C96A19575",
- "section_mic_hmac_key": "A7C12070CDA75EBCBC890C8F85E21D6069C91006B0350065806CC188E5409CCA",
- "section_salt": "9E38512BAFDF12A3783C75D6C694F627"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95BE8BAF31EC4BB917CC3A2C7FB03DD4",
- "aes_key": "212A4DB3EDB93B86E38661EAB32D3899",
- "data_elements": [
- {
- "contents": "",
- "de_type": 657
- },
- {
- "contents": "46CD03FCCE18F7504C5C855CF189298CB67858A974ADB18500437642",
- "de_type": 190
- },
- {
- "contents": "3676B5CE1A207A",
- "de_type": 142
- },
- {
- "contents": "28383F354FEADE799572E4D15C96B4F6F0",
- "de_type": 145
- }
- ],
- "encoded_section": "7790135ECAF5AAE1BA1C64EE01424B51C2867D911000CDD06ECFAAA6F2401AD94229ACCA991590048D658DFC9B60B28E0997C8D85E975BA9D0B823487BA20A7C004379A82C97193F06260554E7B6D51C198EF01120BFD7284EC9963828D910D83D90812C2772E3357505FAC4036F483231B41124A3A8DBF2",
- "identity_type": "provisioned",
- "iv": "4B39E2AC421BF39FF32CB77ADA2A7923",
- "key_seed": "653C200BFC98321AF11AD97638B4088CDF44F10D20996A2E39B6AA52628D81E0",
- "metadata_key": "9328E95CDBAEB26EF1D330AB07A34FEC",
- "section_mic_hmac_key": "10D58DADD334BB6D030EC8703174E882455E4C6626AA29BF6032013EB5CCAC41",
- "section_salt": "CDD06ECFAAA6F2401AD94229ACCA9915"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7A7BC9104E4F6277DB44B83EC568D7A2",
- "aes_key": "1E4B737CF0D3DE9B0AB7B23C62E19000",
- "data_elements": [
- {
- "contents": "82C5DC605CC0B0C534A07204CF6EE9800C258F5876A2BB4D67BE97FA",
- "de_type": 53
- },
- {
- "contents": "0BAA5558",
- "de_type": 865
- },
- {
- "contents": "",
- "de_type": 15
- }
- ],
- "encoded_section": "5D901316F449431385886874B56F21C6EF076D911000CF9BB4939F48BC5B870C1274DB7FE0EF90029BCFE0E6FB66D97C97B97146DC9923FF872C1C82F9E6D58075046BD6EAAC9BC620B1087C9766192D38AA2B9B02D703637EF7434C1F95",
- "identity_type": "trusted",
- "iv": "5EDF27336329967B430B8BBC6511B3AF",
- "key_seed": "6EEA708F4D7A23E95A290D0F7C7C2C1FABCCB06E2BEDDAB673FCF52531CB9949",
- "metadata_key": "D58071E30F1F4F280A52547C0D940B6B",
- "section_mic_hmac_key": "748BB640722F4197BE2AB67B25D10B13D0463BDA9651A7A09D072B29B678034B",
- "section_salt": "CF9BB4939F48BC5B870C1274DB7FE0EF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6B2784661C35BE0A3E429A2C6964C55C",
- "aes_key": "B7A7DD23E0BA11F990A724517482CDE2",
- "data_elements": [],
- "encoded_section": "379013D9B173EADBD3B3B83EFDA96221945EF591100013800CD344B3A2AE1F5013E1DFAD3CB090046474715969917E830F5BE55D47CFF831",
- "identity_type": "provisioned",
- "iv": "4A91BFEB38EDE9B000D0E68B1789117C",
- "key_seed": "4272E95BD5A3F9E55FCAF98D88C776F3F43860BA57169089F0F43923F9743AD6",
- "metadata_key": "D5513C47ECE8FC6A0544F3F67055C101",
- "section_mic_hmac_key": "34C33FCC3774716A479B5A1B646C375BB563B045C8E1B020594E0C6CC637B402",
- "section_salt": "13800CD344B3A2AE1F5013E1DFAD3CB0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "129B711CE9903C07E3C79E0C66953083",
- "aes_key": "018DF0C4092B2887012CC0E3FA06138D",
- "data_elements": [
- {
- "contents": "36166C05E659A86C25318FF5",
- "de_type": 486
- },
- {
- "contents": "C9113E4284307544D5452CF918",
- "de_type": 207
- },
- {
- "contents": "113DF414AC6D1ED5005B46712D2C585BDC195F836C545B4C9D63B8E3F7",
- "de_type": 59
- },
- {
- "contents": "DB7FEE8E34B1106ECFC83CD95F05",
- "de_type": 278
- }
- ],
- "encoded_section": "8690132D01834FE1F90892354A8D60F469D69A911000723A408BDAF7D502315A69861DBE19359001E5557F8FFBBA84A06E145068D2B755EF7C628F44909A90F69A26ACE41CC47C7A5CDB5ED9276B167EAAF20B92CBE3FDAD487F587119D70BC069CFB0709ABEDA42D6C799F4BAF2A0FE359CC18BC2C8CF16937F30BD382B6D5EA6590E94366134",
- "identity_type": "private",
- "iv": "A804F89694F4348DE72BE6DA40146DE2",
- "key_seed": "3A3D0F62E7DB4E7B35A2BED010905C168A5BF029F93487B4B70FE06DBFD8F336",
- "metadata_key": "6A4DECAE9A088A4100B25933DE8CE454",
- "section_mic_hmac_key": "965B4BFCCC2FB9473AB9E3BCC41A5DD7C74311C9A8E54F6E59D7644D2686388F",
- "section_salt": "723A408BDAF7D502315A69861DBE1935"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E0CA1AA3AF1191E3819741B3DEFFAFDE",
- "aes_key": "1D5E8EDC48783BA37E4B1799FABB4ABE",
- "data_elements": [
- {
- "contents": "7FDFE51E7ACA9FD4E4D768319A58337D53CDE7B59C0C13D39C91",
- "de_type": 315
- },
- {
- "contents": "066D6DC387C291",
- "de_type": 697
- }
- ],
- "encoded_section": "5E9013C567A94B8DEB58041FA6003F6984B55E9110004FA8AEFE32E28F03CA08C323146179A8900481AB869FF38C4A4AC07EBA8593D4078D298254845195108E6EDC6A46E534309A92E2C2EE6B7E585F2F80192B922F7A1B1E27205153D5A8",
- "identity_type": "provisioned",
- "iv": "1A49425E07C48D0C622000F534815E10",
- "key_seed": "E3A4AC9730A13980D92CD512ECA0E6FB9C005C05DD4EC6CF1B16AB10BE9BF0EE",
- "metadata_key": "6EFD60E02792E27FF514484A55667047",
- "section_mic_hmac_key": "D1E5D811FB30478207868A6B7F75BC379740BC5FE2D67928A9BF1C27287F5729",
- "section_salt": "4FA8AEFE32E28F03CA08C323146179A8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4370155ACF139B1128FB84304A5528CA",
- "aes_key": "2F204AEAFF274885B403599787146CFF",
- "data_elements": [],
- "encoded_section": "3790136E72A2B54E54872677EB0711B10EC0F6911000CD2155E85F2D8011E7CC8A841B84663B90043BD0BFF11972D8A321CC2FEA6CDD5D3D",
- "identity_type": "provisioned",
- "iv": "5899873C8E3AA02A04117D7944F99F79",
- "key_seed": "9117DBFBC2B7828BD194A841123189D3EFAE7883292BE6D930D5DC654DE163E6",
- "metadata_key": "2A711976FD8AA71BA52B4E0C159B57EA",
- "section_mic_hmac_key": "E62B18C7ADA86D2F488DFEB4F44226604EBB71CA197B52611CBC971436E4F416",
- "section_salt": "CD2155E85F2D8011E7CC8A841B84663B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E1396C2167C2EA23035DDE7F637A22E7",
- "aes_key": "DF1174BCE2216174DB0591EF868BCC00",
- "data_elements": [
- {
- "contents": "C47031946FBC56732583D99C55B6E1B7521BF87FD7",
- "de_type": 142
- },
- {
- "contents": "BE62881EC8915D5545B185E4",
- "de_type": 854
- },
- {
- "contents": "847F051E569E3050817AE714F1CFBC836A",
- "de_type": 460
- },
- {
- "contents": "F5A734560E04909565F8EE8D110FCF79CCE8441355DB69E248324AC1648B",
- "de_type": 674
- }
- ],
- "encoded_section": "9390137EFF576731E303EC0E67FA37528CF42D9110009AF304AEC06D6F647D0A6E7F9496F1EF900287E198A1643D026A2A57FB2CC6BB455BD96E7BFFA40AE2E0F9BFEBE079F650D4D224D6E94A45361D5E07FB6B1F607E183CC2740C4219AB4C920CF3E07894945D049586FF2C414ECB417B5A09BFFF01767922EDE5660AA194C03678B4956DF45C18C6D98272A2E20FA9C89F2B",
- "identity_type": "trusted",
- "iv": "2F57A532E27C6BB9EFAADD309841DCB9",
- "key_seed": "F1B9E7ED359076DBA893F8BCCE52A92DED14DBDBF49FF9AC463049AB69D6E69F",
- "metadata_key": "C2681503C3157A0ECA4ABF5BC029ADC9",
- "section_mic_hmac_key": "2533F7CA4EB0FA17F8F5EA530CFC482EFDDF3E7E17C7634BADAF773AB0FDC314",
- "section_salt": "9AF304AEC06D6F647D0A6E7F9496F1EF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C033469A194C17D236D3799F6F810289",
- "aes_key": "D583C2344A2A9FFFA466F6636DEDCECD",
- "data_elements": [
- {
- "contents": "ED3C30FB7E039894503CCBF3372AE73F62E6BA062DC86BA80D5C",
- "de_type": 321
- },
- {
- "contents": "56A50CF71ECD4A4D6F8C657A3ED1044F4EB9E8ACB5B67928",
- "de_type": 329
- },
- {
- "contents": "5C249B18B1A02CE7C5E369D4768F374C94F96FB97EF7E20C566B",
- "de_type": 781
- },
- {
- "contents": "11914865B2C8E598C7ED5BDDC4009B7552F7B8",
- "de_type": 392
- },
- {
- "contents": "5E8574C9496DB164C59CBD836C60",
- "de_type": 421
- }
- ],
- "encoded_section": "B39013058AE9E776265CFBF3FEA5B70CE54268911000FE248957483BBFB171D44B82FFF83FBE900179E4BBF07C901D822A2D5DC2540F5D6B7B32E8150931481CA5299DDFCA680E80EF5554527CF0BB2A857809C703A7594CF02E853D3A713F1C5729A4B37493F64998A0DCD4526C5E1618DE6D16B4307D7843DCFCA192300FF4756FC138BA4B2E157A6D2B5EBEC21DB497053C9717F18250C715CA28DA39F9C1F0C0FBC213AC70DC09308014136458565B01A59E",
- "identity_type": "private",
- "iv": "2BB4BDD29DAC7BF3D31AF7575D4373BC",
- "key_seed": "82E084D15CD7B6C70978DE7DE19596B673CF3EE29A36A32B713496FD67F6F0A7",
- "metadata_key": "ABF22A200F57CB114D5BEFFD477200A7",
- "section_mic_hmac_key": "95AB213F52D4E447B6FA5CC544650DDEFB78F285502122175C2F5A103EAD2243",
- "section_salt": "FE248957483BBFB171D44B82FFF83FBE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D9B6B1F0A69B7B9FE27E8F80069567C0",
- "aes_key": "C84D0EFD9E47A5D90640A9D7088C5021",
- "data_elements": [
- {
- "contents": "09E6F8330E760D01400A2CFA",
- "de_type": 572
- },
- {
- "contents": "D2B4",
- "de_type": 911
- },
- {
- "contents": "761F7E",
- "de_type": 72
- }
- ],
- "encoded_section": "509013BACCDFD8DB04ECC45DA02B6F1463200C9110006BE4250FD8E960F073C28F3C812DD785900480B27E5A6720404EDD1A03BD7FE9ED984422FE604E77EFA797683D4C65FF1848E25775431C5CBC0D0F",
- "identity_type": "provisioned",
- "iv": "568C52B6699A1EFE8632D2AA7CA08F1E",
- "key_seed": "D80152B000A2814B443ECCC3D861C7480435D9A4AE7C76B354627BE49B903022",
- "metadata_key": "235F082A46F70C6D07D056CD8302E590",
- "section_mic_hmac_key": "77249D32B9918E829AB8EE9AB7F1690521BFE9444D8E1C6631D0F3CA0E7A97B0",
- "section_salt": "6BE4250FD8E960F073C28F3C812DD785"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9622F4D79E9333730B78B9BC45D018D8",
- "aes_key": "EBB969EA5208D59DC720981E0D7165B2",
- "data_elements": [
- {
- "contents": "8910331A35E52B5CEDF5475C",
- "de_type": 49
- },
- {
- "contents": "C44C8D",
- "de_type": 1000
- },
- {
- "contents": "58AA13",
- "de_type": 182
- },
- {
- "contents": "FFA1715C6158",
- "de_type": 988
- },
- {
- "contents": "C738C7E2",
- "de_type": 195
- }
- ],
- "encoded_section": "6190131EBFEC19E821203A81CBA5997277B45391100018A3D32C6D68ECCE86C2636223BC415590041D5D7AF03942C18470CD2FB24DE76784722AD38725E712ADBDF3C681731E6A071438027266CF94D0DCF8B6977AF5EF09433D569ECD90BDC280C1",
- "identity_type": "provisioned",
- "iv": "2E0E4A900067722E740C48782D2727F4",
- "key_seed": "34CA6A5E14C31E2B58FD467CA282371F135FC0E6488219FEEC3D194361416ED3",
- "metadata_key": "1534AC915B12F7B14CFEC07E905B70B4",
- "section_mic_hmac_key": "D1B3305F817AB4E6EDA0079FF3B8CA3E7466641381F5D38F31D4DD6336A97C42",
- "section_salt": "18A3D32C6D68ECCE86C2636223BC4155"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B456A45D23A5C23B3FC7D4FCC2E17915",
- "aes_key": "0793945D13EB6A7D4F00A59FC158C557",
- "data_elements": [
- {
- "contents": "AF",
- "de_type": 339
- }
- ],
- "encoded_section": "3B9013DBC90F36C9F1FF8E9371E022326D96C8911000D1988E9F53E270167134FE84104498EE9002A2C66A9C2629C64B6F3CF8EA1BD17FA32F63DD11",
- "identity_type": "trusted",
- "iv": "B44C9675A36625470E2D7A5A381596E0",
- "key_seed": "5E555C4138D5A22C3A975EF93D7C88FBB90B32618661D9EF2A66B14E19E1169C",
- "metadata_key": "81744A6BBE8C683D7D720AF41783148E",
- "section_mic_hmac_key": "6E96EBA658E9B9630FC00A38353E4B124102370FD3ED8183ADF0D746326AD0EB",
- "section_salt": "D1988E9F53E270167134FE84104498EE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "865DB128D0ED615465C4AF33ED747467",
- "aes_key": "83F6665949CEA0499C06623CE213A83B",
- "data_elements": [
- {
- "contents": "648059EC9A6D7DBA28F98FAD7AEEC6532CE97E6BFF447DEF",
- "de_type": 114
- },
- {
- "contents": "6E640399BB35A3B4306409C94E87FC01",
- "de_type": 668
- },
- {
- "contents": "A93CB545FAB30A4742664D4149",
- "de_type": 830
- },
- {
- "contents": "A3232B62A0E5C5AF352A143BAAE7C285A135A7D4EA5D61",
- "de_type": 853
- }
- ],
- "encoded_section": "8E90138829246CDB07510CF107652C06222C6E911000668D1D8BCC2E706445B18633C2B2A6E99002285B7692049B38967A46FAAAC9E3B962F961FE806B1FF948E425BA1A82F01DCC601E4AF2000370385A54669989A6D2845E984A850B9FA9FBB5CEA3A4FFD736DBAF48FB432EE5BB8D3F696604B4E133E0543D383D46966C1D47265E1EAFF9FB5D9EEC945343CBB6",
- "identity_type": "trusted",
- "iv": "D300ED57F1F0333ED617F9A48A54D00E",
- "key_seed": "E8CEAB1757CFB2ACB155DD5BBE2A45EBC383B29CC512CD445BA0D4B323F3D50D",
- "metadata_key": "BE82E42542AAED90F4D6ED5B276C9865",
- "section_mic_hmac_key": "21EFE7D3CEC8D334C1F5CFDBE2EDD1E3F9B164D8949D629F21348FCFFE479B3C",
- "section_salt": "668D1D8BCC2E706445B18633C2B2A6E9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7C9D65E47B5C2E0CFA5E700CAE8565D3",
- "aes_key": "9652732429DBDC4E2E1991C0C86D0399",
- "data_elements": [
- {
- "contents": "603A05EB6CDE557F2181CE8F5C8DE566F7AD9A4EBEB2",
- "de_type": 755
- },
- {
- "contents": "916FD503DE6BFDA7FB44FCAC3AC2D01E5F9737401235A13BC3965C9660",
- "de_type": 197
- }
- ],
- "encoded_section": "7090134C8A120B8D74F21503A3F4A924CDC7E59110001C3CF25827D6B07C3DA29410FB3E65889001DE17683402ED39894A9F8D8D73A1379C3177626B72CC7E228915BA9E59842F22EC52A4F12DE1C87B505E41B7F197448F7208E9CCDE7B332E7362B1EDDA249FEA891DA5E428BA7F3B8A",
- "identity_type": "private",
- "iv": "D9839CC6B5FA3B7F43F0359AAB386887",
- "key_seed": "048EB4D544BC85B8026222BB3BF8E829BA5A1D9732B000747C831471D8F584F2",
- "metadata_key": "98B4B953B6639A1E2E9C264A98BB0247",
- "section_mic_hmac_key": "A84D8352E99395F20F3B254C761D0647E4CE0D0F5E731F1F02A32D63F721B4E5",
- "section_salt": "1C3CF25827D6B07C3DA29410FB3E6588"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "396496EE83B2146F12878D5AECFA7945",
- "aes_key": "701449FA0ED699CB50D88C55F912595F",
- "data_elements": [
- {
- "contents": "3D46DBD04F9E743F41453ACAF24A",
- "de_type": 797
- },
- {
- "contents": "EDA9FF21CF420BB69ACDFCB00E088703575C",
- "de_type": 220
- }
- ],
- "encoded_section": "5D9013ECEDE0D46A9124E3C806AC962EF9EC6591100037B25A8B910D21BEC099277838BE0E4B900425DE05F6E9A7D84E24D37D2F7A4307188B1F1E4086A13339E08BB3FD2EB4347B2C3063C09619BEEB61AC53A22B95FEF1EE53A1B8BCB0",
- "identity_type": "provisioned",
- "iv": "04D50AADBF5216FEE365473AC14EFF04",
- "key_seed": "4ED429772F3805E33E327BF674F122DB7E906C7295C6094808E1E775EE2AC748",
- "metadata_key": "F5BB3CF730A57E58B11EAAB014887EBC",
- "section_mic_hmac_key": "8B6143DD499724FE80FF2A1CD6186E62D7C8D583265147D222D13BE276EA5B76",
- "section_salt": "37B25A8B910D21BEC099277838BE0E4B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7E8AE3C9278DEAAB44A0549F62B2AF72",
- "aes_key": "BCA92DE9B6063961D1F84ECA0C7F6C93",
- "data_elements": [
- {
- "contents": "2CAB785B1AFCD27B65CE80FDD46ED10B10290AB73C307F67EB",
- "de_type": 542
- },
- {
- "contents": "C74E88BE9C94",
- "de_type": 979
- },
- {
- "contents": "6DF7B3CD8E17AB4EC4BC118E66622D75",
- "de_type": 321
- },
- {
- "contents": "23B264B671089BF640B146674E",
- "de_type": 287
- },
- {
- "contents": "D8526CAB4734644BBFB165AFF944B3DE",
- "de_type": 396
- }
- ],
- "encoded_section": "92901352EDBA6D632939142BBC95D1B5F6F3B5911000BFF4B3C12EE83E3D7E4D8D334B07650490047DD8DD4231311B1DB06638CBB34F60AB25275FFA10D6C82C325EB5607166A808122420D469489946DD0ED9FF8011AA5F665A5BD3260D64248A48EE3C212CF15EF03DB424536E1AB2CCE9826A89CC0F597C747787A078D98D614D33A71AB3BD1A8F06E6A85EAD38875BB7B0",
- "identity_type": "provisioned",
- "iv": "B2938060C2FB3A233E0B0441629A5D54",
- "key_seed": "A9C66A81FA32BF7736824A6052703C683CDAB0690363FEBB064EC5BF5EAE2D85",
- "metadata_key": "14F59D0003905680A8E6A3F9F03710EE",
- "section_mic_hmac_key": "D34BC3D1F158A7340C574C280BFF773A087BFB40DA47AD5C9D59781A5CD6B9FF",
- "section_salt": "BFF4B3C12EE83E3D7E4D8D334B076504"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "58D90C3496D916C45B1F9629D196FE3E",
- "aes_key": "3F254DF7C078D8B9BE085F49D44FCE1A",
- "data_elements": [
- {
- "contents": "DAAC6DB1",
- "de_type": 269
- },
- {
- "contents": "20B5",
- "de_type": 92
- }
- ],
- "encoded_section": "4290135841F4D3C484D6F0F42B623604D620519110002E6A604207A7F9600BA8826B040124D29001A9A00D43983AEF2049A5CC3D6139B73A1FC6DF1F28DA3B526D64A3",
- "identity_type": "private",
- "iv": "A2F7257D7DBBB78925E177FBB9F3E6A6",
- "key_seed": "5D9A4B660496D7408099AD3AF204A372D5E1B90B5DA37B518FABA1FC72EB29ED",
- "metadata_key": "E483E747549C5E8FF2E43903A508FF7D",
- "section_mic_hmac_key": "006E79B19C1D3EB14ADA776B34A4D7601ABF822FD8E69A1BE6F354245E4FEF69",
- "section_salt": "2E6A604207A7F9600BA8826B040124D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2EA5530CA0FDCA0E3D26F54B36C63756",
- "aes_key": "C944C8581944D3A7B2145C20572A48BD",
- "data_elements": [
- {
- "contents": "87",
- "de_type": 543
- },
- {
- "contents": "624BD963E5CD706B8CEA97FFE4F19FEB72164DEC299F657830EE771F40",
- "de_type": 38
- },
- {
- "contents": "1F73",
- "de_type": 693
- },
- {
- "contents": "0E690425BDF2F9697C793C79D9A4B31BA621D37550295D8DEA1650",
- "de_type": 455
- }
- ],
- "encoded_section": "7D901303D613B4D65DBD34B0C37617F6403DAE911000A90775A9B65F4CEC0DC078F9EC5AE2EB900165055500DB14C4C9DF1475CB2947DAC616B755A1DC498623CBD1E5876A143201343233A2795172250398353EA567A343F7545CFF7D0D47CC7FA7C78040C5AD20AA8A802F2D5931EE0C69B984A697B56C19A71AE99BB9",
- "identity_type": "private",
- "iv": "8CB642644013FC19152A421C7AA99747",
- "key_seed": "160F89D53618D964B47995A7DDB753A8A5E48A1C3252E469E57AE50C1CAEB0BD",
- "metadata_key": "5CE66B8C2BEE9225C1AB9CC4C80A166F",
- "section_mic_hmac_key": "F22F3AB674F0F89BE488643EF7D0AF9B0DC35E89EADE13A9D1563250970962B6",
- "section_salt": "A90775A9B65F4CEC0DC078F9EC5AE2EB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1D51D1DA179BF1915279BF30DE1F4B03",
- "aes_key": "BCEBEE8528219B39A7950E3D66C9B154",
- "data_elements": [
- {
- "contents": "50528FD9150AD0773ADB5E08436CAD30C30FDA",
- "de_type": 592
- },
- {
- "contents": "C44A41",
- "de_type": 561
- },
- {
- "contents": "561F383B33C5EEBDABBDA184A1A4605A82",
- "de_type": 814
- }
- ],
- "encoded_section": "67901398BBC302C18E49799FA9EEBE11B8FBF1911000C2261F071C3C3CACB7699B63CD49EA1F900142DF2A9BFB0F1A01DEC1A14194866B92A2374755F6DFC853AD50A93FD547E6BFE9FBDEF421A6A18B3D882669EAAE1E4A4C4379BF01D5B44003CA2A66BA38CEB4",
- "identity_type": "private",
- "iv": "E7FC9AA29E2E9B3025EF3BBF9D18E508",
- "key_seed": "28CCFC888CCB929D63843492569B71440F998A36D7F006F7E724F777B5B6EBB5",
- "metadata_key": "AEC3202A86B1814AE764DD7C97BA19AA",
- "section_mic_hmac_key": "7443E143DD31C1C97B1BF6E1932D9FC76E5796BE5D2B088062FA5958F4E2ECDA",
- "section_salt": "C2261F071C3C3CACB7699B63CD49EA1F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B33B26F42720F3F275CAFFE124CD7B60",
- "aes_key": "B6BF74F4EA862207D56E4B42492C3CF5",
- "data_elements": [],
- "encoded_section": "3790135B9259B281BE3914623875BF9E184F98911000C3391346E87D492348FBE56098116AF89002D57C10A9667412E9067FB677AB7A26CA",
- "identity_type": "trusted",
- "iv": "45217E0F0C06D7B7918C468D9F0CF490",
- "key_seed": "175D317E4277BD3F2EDC5F019D5EE8617624648F818058FBA3D605EE3666DC14",
- "metadata_key": "B92E7217A6255FD283368724DAC465DD",
- "section_mic_hmac_key": "CB3E7306030B4707AAC625998DD40082CB446835BED1A2B78DE401CAEB39D842",
- "section_salt": "C3391346E87D492348FBE56098116AF8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "872CE0191545242D5BF00528AB6C7091",
- "aes_key": "8032D6560A386D2B603442FE39BA3C7F",
- "data_elements": [
- {
- "contents": "629E6EF672C12AB58DE63B36856CF2EA31E8B9AB20",
- "de_type": 508
- },
- {
- "contents": "74C4F6C190C2",
- "de_type": 354
- },
- {
- "contents": "53C627E2262407A36E657CB2D4BE0F4254F68754752D7F76EDEA38BEB0",
- "de_type": 585
- },
- {
- "contents": "9FCFCD14189045E1EA71527C23E0",
- "de_type": 36
- }
- ],
- "encoded_section": "889013BA20D5744F0A5B0D208F3FE3875B284D911000FE0E258981EF48CE93EBC213AF3008509001345EBC4DB96528D67C20FEB41E9D7546D0146497B05D4701A172C2B41AED376F0450242A7F99BE6C14749DC04AAD3C3F2FA1E2531C1B7723D1D8651D0360252A83CC256B1001FB12EA9977FBF620BF8D461649F3F0171A3A457F84660A0B61CB9F",
- "identity_type": "private",
- "iv": "B31619F16E2A96F0C1834F1CD39193EB",
- "key_seed": "9B06F9933F5497ED81E7115DFADFC68121B611E0AEC678B4DF8DD3CB4BAEE49A",
- "metadata_key": "5C8F5F80BB667FAD70D156F07AC0C375",
- "section_mic_hmac_key": "98FAC07C93E48317E374F2C0AA92E9794BDCE4C9323684D245EF332F0A032D28",
- "section_salt": "FE0E258981EF48CE93EBC213AF300850"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "086B1E981485B9E1899F0EC60EB9E83D",
- "aes_key": "AE86A76940D9517BC921B369256E4DDA",
- "data_elements": [
- {
- "contents": "E0D97D47C6C09CD6A1DB96F46DBBD02BB351713DF1F2B0",
- "de_type": 882
- },
- {
- "contents": "FC3BD546F065A256DC995A5FD110C59F231A47A65CAF7020C7D582E0E6",
- "de_type": 867
- }
- ],
- "encoded_section": "7190130F2D843A93FC1F1CBBECF81D2A1C6FC0911000495249EE8F8F7ECDCE556774EF54D8B590045C25EAAEDA1187C4C0786320BB35C0FAB443CF096A783348E054BD52DE5D813AFFC6E9E04F9119B64BFDF45ED2D9C410CBDD53B9E6B0056F89AEEAC6702F71FF0F1A03E872EA10D42028",
- "identity_type": "provisioned",
- "iv": "15CA63A0FB423A4345E9E1C6B9A5702F",
- "key_seed": "3DDFBC62D50D8068946200951BF0019D32100459E073453DCB6AD714BBB239B8",
- "metadata_key": "88E6A925FF482DFDBEF5286BE14362E0",
- "section_mic_hmac_key": "C0AAF2B1691A87BF9585A47B1C43F73D15657247D75AA873CB27DC2717A16956",
- "section_salt": "495249EE8F8F7ECDCE556774EF54D8B5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4AA9E6490E510E2078D1C0C3C39A8FE2",
- "aes_key": "00B42CF723FFB9E400D6E279979133A7",
- "data_elements": [
- {
- "contents": "7EDDDB47C2233581E9E08E",
- "de_type": 172
- },
- {
- "contents": "29FF84",
- "de_type": 411
- },
- {
- "contents": "465EEA463E31B716E8F836EF7AA2F4F3841FC0DB6397C2",
- "de_type": 297
- },
- {
- "contents": "E547C85EC74056696A",
- "de_type": 916
- },
- {
- "contents": "115F4417",
- "de_type": 682
- }
- ],
- "encoded_section": "78901348721D68E725F93B39C9A8583F2A65179110000941A104B100C80468194C862B7044DB9004D6BDEE7AA257D998A85D7415504BF0A40A6748CBF0B55C1EA5F7D5D2B9D0D48052FCE5A679E9BABA967262CE798ACF31397983254EF161DCCAC8789DFD88D052C33592CA3682E9DC143104E4506C0CF0F1",
- "identity_type": "provisioned",
- "iv": "F9428E5DFFEE82FC83DA408FAD488BA6",
- "key_seed": "DC69ED874663A6D1321BD38B4FBDE1469EF8033DA98BFA2ED613C62BDEAC381C",
- "metadata_key": "EE6FDA87A6449B99DB62777CDAB5A388",
- "section_mic_hmac_key": "E227F098FB6C323970409D263B84AF7F8CDB64BA4D5F13DE8AE304534DE8B2A1",
- "section_salt": "0941A104B100C80468194C862B7044DB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AB93EA96A6733359BAD13F6BBCBF7B61",
- "aes_key": "A52EF583D412622DA1C23480D23A385D",
- "data_elements": [
- {
- "contents": "29DB99B161DA96A74C67E613",
- "de_type": 62
- },
- {
- "contents": "714F915FE037AF3F5CB8",
- "de_type": 420
- },
- {
- "contents": "06F14F79DE3048918C71D3",
- "de_type": 843
- },
- {
- "contents": "D522C29C",
- "de_type": 635
- }
- ],
- "encoded_section": "679013C6C4FC258307EFA7BCB4439224E74253911000AC7EDAD03EA393EFAE096E5CEFB2CE65900449CEC3FDE6A1D76BAAA872A48CDEC69967A588F62B2BB08A7F9171FAAB1DC49C863FEBEFFCBB817EC29D18DE97FBCAC780743BC6A83E9B5F508B25EC0E51EFFB",
- "identity_type": "provisioned",
- "iv": "51A074E8F49F530A81C6ECEA74E8CDCF",
- "key_seed": "1522F314EAA2926513648D2B83271A75BFEBAAD5387061BE1230F1D8EDC66652",
- "metadata_key": "E758C77E18404342F1376AC800912CDF",
- "section_mic_hmac_key": "0F67209BF8099626E6B190676AA37C880BCFF6FB3276D2F9E0A831DB10E4781D",
- "section_salt": "AC7EDAD03EA393EFAE096E5CEFB2CE65"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "095CA3F2D80C77F0418F84F670BFE4DD",
- "aes_key": "E98006F8F0DBC0CC557E88A28C8BFCC2",
- "data_elements": [
- {
- "contents": "42DF097BBAED32E65BDAD093BB844FF43E4AC0350B7936287FD513A3",
- "de_type": 462
- },
- {
- "contents": "856C428A8B8613E12BEDA66CC0B14F80E4AE91625DFB55",
- "de_type": 846
- },
- {
- "contents": "5722372800A0436D655ABCCE6E1AFC666D996774BB8F5749633D",
- "de_type": 434
- },
- {
- "contents": "B4",
- "de_type": 989
- },
- {
- "contents": "17C86D",
- "de_type": 843
- }
- ],
- "encoded_section": "97901310C6A1E0973AA6302F83F5AE781EF3479110009D8967ED6923306F238BB3006CDA188D9001041B76BACDB753CFFBE885494E2B902326FCC7B845B95EB51BF31D16FDB3B8F1A31165528F6B88DC94C53FD7BE2034E003BD25E0258E27874EC2A30DEF2CB678D1D2B3155A6801CF086B3CC55E9777C651643D5ABC9E09397E8760C20DAA9749047403B15F28F2ECE9504BD5E926697B",
- "identity_type": "private",
- "iv": "8BD95493B557D0D6BEE013DF112FB494",
- "key_seed": "37CBFD8DB4C74643FE9E7DB197BCB40CCD42B5F18E9F2B7D992F3E85FA23E11E",
- "metadata_key": "FFE4710FD8DE1B837916E1876A10EA14",
- "section_mic_hmac_key": "51F1387A1CD7B6E8FA54715C4D49B041B88B1EC083BFE9196EF4C3159ED8B240",
- "section_salt": "9D8967ED6923306F238BB3006CDA188D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D627C02EC7A9E006CB069B3BD4087015",
- "aes_key": "DE628F5616A31A91575202E224BF8654",
- "data_elements": [
- {
- "contents": "CE3B7D68CEC6826B",
- "de_type": 768
- },
- {
- "contents": "4B98C12698675C54D6BFFA3284320DA49C",
- "de_type": 307
- },
- {
- "contents": "6C472F7D1F024972817EBF5D9CFBFDE075C093A2C147460E4E34407E78",
- "de_type": 501
- },
- {
- "contents": "01D2ECEF31D5DC0647092519E4B01200DC",
- "de_type": 579
- },
- {
- "contents": "6E88C150DDC8756487059C8509B830ECE39A6650B9A50E795E96C8E48B4E",
- "de_type": 7
- }
- ],
- "encoded_section": "AA90130868EE3BB2CC54975E92D446C82484A1911000973274E6978EEB00588121FF8F3D27239001954DEF19883BF50F4EC920B26896C66CA5E39D8CCADCEC933FEF576ABBF18F03128EC12C963F80262C6B34F00F850047928D6C145AC20B109AFECB4CF1964254EBCB825846E26C4C1F9D25B68B86955F4AB0C176BB905BCF2DFFD31CB7DF833FEA3BC9FB1E7ACA47E0A4F2469A3DF5AC4A4182C1E20E84EE649F09FDE92FDF7B4DEF91",
- "identity_type": "private",
- "iv": "6917AB8BD905BB352E8079F1F88931DC",
- "key_seed": "DE1289A8ED8D1DF4BDF85AB82ED562ACFFA82F00634CDA0A87DE125DC862B0DE",
- "metadata_key": "DB5CAFC921FD2A72293660D037EC29B0",
- "section_mic_hmac_key": "DB3248777D235AC436DD5D78A6601B8391D75E9D13FEDFCC95E5A7EF5E1D5793",
- "section_salt": "973274E6978EEB00588121FF8F3D2723"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95C2D7868282E5790EBDDCC89759B4C1",
- "aes_key": "CD7F86C35D2BD47F9DF1F0929CDF7123",
- "data_elements": [],
- "encoded_section": "3790138A13FBFBECC148589176B2F090064A779110003FE8296502CF32A8202018AFC04A52159004B1DCE781C276A9FC00F5380DC9399063",
- "identity_type": "provisioned",
- "iv": "413A5B6B45F312FDF51C8DAAECF692F0",
- "key_seed": "21C30C7548CC08332F259C493F122582C9D2CE04E2E3F22E715F9EDCB12D7100",
- "metadata_key": "2AECD34AD9CC88413723844F52128EB3",
- "section_mic_hmac_key": "D31EB890A1B0AC8F46E70771ED9F20D0FA173F33613BEC221A9502FA131B07D3",
- "section_salt": "3FE8296502CF32A8202018AFC04A5215"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E96C90F3BE79939E8784E2DC5B31BDFE",
- "aes_key": "775282A7208DBB1E7F6605D293E01569",
- "data_elements": [
- {
- "contents": "A40AE87570892CED908675E9B1",
- "de_type": 353
- },
- {
- "contents": "C003",
- "de_type": 516
- }
- ],
- "encoded_section": "4C901368AC6D32D83AE84E55E96F8D2AF048B89110001B662351BB4DEF5C1AA42CDB493A8B36900133373940E3DE0962AAC26099DEF282AEE69427FEAB5A78CFC17FAB668BE3863DD7E13207E5",
- "identity_type": "private",
- "iv": "957E38A6D3C646EF05B80926BAC32F8F",
- "key_seed": "FFEAF2E7E81186AA1F7546BF64C02F19B713424698C2D27230B0C18D0FA88778",
- "metadata_key": "76052E1B1E33C77A468457355A7A480C",
- "section_mic_hmac_key": "171933B371C424F5B76BA421F60FCAF87DDA0B96E37278E25F336724BE96573C",
- "section_salt": "1B662351BB4DEF5C1AA42CDB493A8B36"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7134809DD3BCC616EC1193B90257A9CD",
- "aes_key": "4F8BFC75339A3481169241E6142BD16E",
- "data_elements": [
- {
- "contents": "813D3DB42909EEB672E0068FFF5D5C11FF27862ED0A7B49C2DF69A1096BC",
- "de_type": 368
- }
- ],
- "encoded_section": "589013C03A5C09B42E407DFBEF97C62255E63691100075B3832C1FDAE86E2FC3F936C7FA33E4900412099B1DFDD67635F1F0F5EDA28912BF4EC1876FDDFEF75B39246E62447E0AE9BF9C0D5DA26B1C71B0A995CB31D31E2B06",
- "identity_type": "provisioned",
- "iv": "87A512B81D64F5E12678BA49BBE8827E",
- "key_seed": "56ABD8D2A0121F6B2036F5995FB901C671902708CE8F122F9FA2EEEDA76B60A4",
- "metadata_key": "E2D1095A39383B17B22D89AD524A2503",
- "section_mic_hmac_key": "3F04EABBB85B4DDDBC2EE93DB5DC9E5748E086829E0A933E5484A2828309C7A1",
- "section_salt": "75B3832C1FDAE86E2FC3F936C7FA33E4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "04822A3F914BEB02DE158387544B33B7",
- "aes_key": "9E61F07423A43898F2B2BD793AE78265",
- "data_elements": [
- {
- "contents": "573A24E1C0",
- "de_type": 73
- },
- {
- "contents": "5737FA2542C8DA3B14D5AF59E185EC",
- "de_type": 145
- },
- {
- "contents": "B3D90DD4027492BBD8F6A03869891466D2F7",
- "de_type": 517
- }
- ],
- "encoded_section": "6590132A1E9626DA0DB9A7149FC698FF5A112A911000A5516EE85A8E5F68A7A20CD1AD0F4D8E900151BCBC864AA670083AC7607F17733752559F4B7A02ADBCFCCF538935D532EA7429ED06742544428A52A88BBFBF205D7E1E16D64EF0449E9F70CB8697AC1B",
- "identity_type": "private",
- "iv": "C1B1581BE83D958184B1F20B62878655",
- "key_seed": "434D7F1E6F20E72E968B6967177C7172E89F20605C6A0CEECB940DED13C73417",
- "metadata_key": "E31B56FB8461D5D0C9CB4D65029B27F0",
- "section_mic_hmac_key": "D7B91FDAD07753CB972FCB2300055E27CF54F56F1B5C208126917ACB4B98B40E",
- "section_salt": "A5516EE85A8E5F68A7A20CD1AD0F4D8E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3BDCCBBD6FAEA4D81F0C38846EDB0007",
- "aes_key": "2009340BB233CF0120BC7B9D43FF6EA6",
- "data_elements": [
- {
- "contents": "9321C26068C444C77A4C",
- "de_type": 568
- },
- {
- "contents": "5610C34A4873EE4AEA0D64E07AF9F0805EDB22",
- "de_type": 616
- }
- ],
- "encoded_section": "5A9013BC4CF26CB67978FB671CC8C30360E7F691100000CCB08A96F8FFEE613C18F090085B059001A1F803A6ECEDA8A6D891CA8D93D521231DF5C635EBA09165E8E53EB8A5577299D4F9BE41035EA3C9E9E43A7CF32D44D4DD7BC8",
- "identity_type": "private",
- "iv": "4B3E5E0EC2C11AB77F1B5F0F282B1549",
- "key_seed": "ED165FB36D9788873B3C2AB86363A5FCE5728FDBFA33798E8242A27ABB4E314D",
- "metadata_key": "E207E837B797DCD4B7ACB5F58312805F",
- "section_mic_hmac_key": "C9EED4F111AD3783F9F497CE8EBE2591277DCADF8C96A4E4E31648C62C31154F",
- "section_salt": "00CCB08A96F8FFEE613C18F090085B05"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4E7FB1A6499207FA6E81670CEB1A517F",
- "aes_key": "ACBD147D71B379B5788ED1708E5AAB0D",
- "data_elements": [
- {
- "contents": "F33836DB6662BEA48A083FEFB086714D",
- "de_type": 544
- },
- {
- "contents": "008185A991906A5F1E2F45358097F39258",
- "de_type": 503
- },
- {
- "contents": "A887EB3A5A5DDD3E234CFD84860E570D769BEBDD",
- "de_type": 401
- },
- {
- "contents": "7FEC120653B2C2F4430F1D4E",
- "de_type": 285
- },
- {
- "contents": "6C55DC27D312CEF55DE857C7",
- "de_type": 614
- }
- ],
- "encoded_section": "9390139C09EE9AF9FD231DE8BBAB6A3006E327911000BB8C90B1631FA5349DBE93A8F8089D829004A288A109B78774698FD5CFD572F82AE470B5DB59FC33E58AA8D84517653DB8FFE57FA6DC1584B21D29FB3B744BC763DEC891B42CBBF2162E5634FD2AF6ABBB98E8A222E1F86DB6E92F9E79613D133EE7324A21F78F9F024EDF1BE8C5CC21A1330DE313169D2130088FA49904",
- "identity_type": "provisioned",
- "iv": "4D83F30109D4707667D1BAABF2BA1312",
- "key_seed": "1CD41F0D8F60C95335ECC8B03AECDA964413DFA25F51950A867F86A91E4206BB",
- "metadata_key": "CE44E301C09D5B72BA4D077648431CF7",
- "section_mic_hmac_key": "8607BFB5EA7F4CEEE160990667025D950511D4D909A1ADCBBEB8D6F87E9B2F2B",
- "section_salt": "BB8C90B1631FA5349DBE93A8F8089D82"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ED8F34826D86C32F70C23B1B7A4B931A",
- "aes_key": "489A79206A9D1A6778D00DB2A49A6BA0",
- "data_elements": [],
- "encoded_section": "379013ACB36757EB46FC893FABF338BBC613D0911000FFBC4E258FF5E9F7D2E3BB3B6B0C03C69002DA9B70F9A96DAAEA10B5DD919D09267B",
- "identity_type": "trusted",
- "iv": "0FF0CAC823EC377E5757B4DE2E57EA4A",
- "key_seed": "D38C6B417FCB3755D9EB0813204623F4D6D15CD26949DFD5639A905C4C58DBBD",
- "metadata_key": "BA5D7A52C4E2F3B7BE99BF65507ADB9B",
- "section_mic_hmac_key": "5002DC45274213683ED0C9D8364625DB71326B85DB9B7370F4462D54A94527D7",
- "section_salt": "FFBC4E258FF5E9F7D2E3BB3B6B0C03C6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7505C20263B4515F9CB242EED923D870",
- "aes_key": "665A4ED25C48BBCD326496615C99D4EF",
- "data_elements": [],
- "encoded_section": "37901355742976F9F16F16C040E5D6ECF4882E91100095564CA7F1E190FC5EE16F47CCF6C23390013538A67CCE880536A01C72FF44A360A0",
- "identity_type": "private",
- "iv": "D6BE377B90522E1975AA152F05AC1714",
- "key_seed": "D1D38E6F7A3C498D1CE230C517F2980757908842DC5156207BEBCE1090091671",
- "metadata_key": "0A2CF8E7C024A0973C504D339D272277",
- "section_mic_hmac_key": "A6E7D3BA8BE08EF7DEE3F254B9FA1BA00EAC09FDAE80FB3594A7F45BD20D03D5",
- "section_salt": "95564CA7F1E190FC5EE16F47CCF6C233"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA8E64EDDB1675A292FB90F2BA2412CC",
- "aes_key": "30F49692078E22708DC9576A3D30B872",
- "data_elements": [
- {
- "contents": "91F9F257617B60E1",
- "de_type": 29
- },
- {
- "contents": "926A971187C6A8743030B07C43C7F92AC3",
- "de_type": 144
- },
- {
- "contents": "F86E6E5010AC0B38CD920ECBA177745EB482C8C550CC55835C0C4B03",
- "de_type": 855
- },
- {
- "contents": "FAEC19832C3B80EC7D3D54893B7D8A197AE10BEA0942C77B1860E009E784",
- "de_type": 666
- }
- ],
- "encoded_section": "95901373ABB9225851815BD480DA08FA8E6D25911000229044FA21CC77C05DE710EE2B6D8903900444EA1F1D35B55D569CCBEDA5F7A130C9733885E75A3E64CB291A1FB898AA1D38ADFA7F54FC82C99CAD3FF8BFAF84E1A629EF64CC44C42A6EB46848C1C484521C3DB5424E9A1373A5B6B61E04B4E9D1CDCF8895A83BB87E3A227105E86461B6A688D9017998EF9037C71724622127",
- "identity_type": "provisioned",
- "iv": "B50D2E6EAF29D66713CFD26E4684BCBF",
- "key_seed": "DAF73BE7AE7DDB8534853BB9AFD81B9A0F84990C601800F064E785AC4E655E85",
- "metadata_key": "3F7EBA8DE8D0F68019C31AACAF5261F0",
- "section_mic_hmac_key": "6E85868E853E08E194206FFC05E20676767CC9919ED9D83EFDFF045CBDE41127",
- "section_salt": "229044FA21CC77C05DE710EE2B6D8903"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ADAB88DD84C90EC093A37DBD22747F09",
- "aes_key": "70E5FCF2EA88CD2F7E195CF371F91614",
- "data_elements": [],
- "encoded_section": "379013F3E7199AA4111F9CF619FF98EFE320779110007302B6AB9A8C6635C582F17B5C3A0C0C9004AE7E83243075B04693077AE9E27EB88E",
- "identity_type": "provisioned",
- "iv": "4406E6C3D68D6ABD808E34740D9E8D33",
- "key_seed": "9DE259395C1D23114C8FF35253E3B2FD3FF1CD43FE56C35A9A13636E5A88E4FC",
- "metadata_key": "2D61B2E8816F45A67189DC8CC7247768",
- "section_mic_hmac_key": "CE942B542959217EF710089A1AF55AD6422DE8D0E57E67CE9E3A2F71E68C3FA2",
- "section_salt": "7302B6AB9A8C6635C582F17B5C3A0C0C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "93C14952EC8743C5ABA14B9E3CD2A212",
- "aes_key": "92A48E1409E79E488DE6F3EFB23E8637",
- "data_elements": [
- {
- "contents": "9B8E20ECDFBA7BD59E1115FE",
- "de_type": 678
- },
- {
- "contents": "1A875433F13FDAECE0BC0F3DF535F1EEE4B48519A5F09094",
- "de_type": 456
- },
- {
- "contents": "DB29429B7B5EC416E915AF6199C7799B580C8AF38FDD2CA0B978061857",
- "de_type": 71
- },
- {
- "contents": "9A3C1C6FCBFA243767F11F699FBB05C45E0B",
- "de_type": 676
- }
- ],
- "encoded_section": "959013DBEDC73C45241D9A454F0C6A9FCB95FE91100060F06A98234891C9EC864EF4C451528090013CFA5840B3F51C06556DC68F28B66C20F000A26CA532D3E66410933BFE1A27F9BD731DADB297BF8D2410821546727456C472E78C2236559A6A19C98C1112955B8E2EBA08F99CCEFFFB79C84294BF3E110D48EDE4C46AEE3B68DBEF75C21B9E899F1B780153C7BCDCF063698B7BB6",
- "identity_type": "private",
- "iv": "7B5C65A46F927A75E810DC5BF783DF87",
- "key_seed": "2D88999EBC4AD1D16AFB3F6956C25843E701958CE6456DA83F2108CF03D1E055",
- "metadata_key": "844CCA7389ECBD8B35A9570B59100971",
- "section_mic_hmac_key": "632ACEA290B0CFD3A4404D9FF8C0544E2D2734358F2F12C62280DABB6A50CD5D",
- "section_salt": "60F06A98234891C9EC864EF4C4515280"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "31D8F19C7BA1B4815280B53E4C848B73",
- "aes_key": "F5A28DFA51BF40D655E31AD80FD3A00D",
- "data_elements": [
- {
- "contents": "B835",
- "de_type": 317
- },
- {
- "contents": "0E",
- "de_type": 505
- },
- {
- "contents": "87E0ECED60A5F831AD115AE163ACD38DD2334F0C2C",
- "de_type": 724
- }
- ],
- "encoded_section": "58901345C41F264D52643107E9FA58DBA9B42591100025E0D336AA3C2B471BD678673723E5CA90014031003378B065A86FB1CBEEFA7194AE280FD23FE579BE5DC32DD905686D0E706C6893BA092D4FB7960F9D296026A3EFDA",
- "identity_type": "private",
- "iv": "D61308A82CDC546B11B0B1FC341BF594",
- "key_seed": "040A634AABD48B4660C06ABFEC3FCD61ECE2D52BA2A5E434E8D9477A654CE176",
- "metadata_key": "36A1D6F085BCD1378E14173389DB0956",
- "section_mic_hmac_key": "A0862AED0DEBD64349EC492BD7E8ACA6F7D874D24DFC983AE1F287D06F147B23",
- "section_salt": "25E0D336AA3C2B471BD678673723E5CA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "09C377FC67DAC5FA8D0C7E1077618F01",
- "aes_key": "D7AC2B958F079D386B0B392BF01F537E",
- "data_elements": [
- {
- "contents": "01F59AE40EAAA786B7C46D8B5C2E1CF22A7927D79566",
- "de_type": 254
- }
- ],
- "encoded_section": "509013153E5C4EAD84B8372B09243DD7F8E90891100064F6BB71376AC822BD1EB434AFB7CD6A9001E4317B766820FEDA9F298B00E0CC0C1BA0F863130C35C146C86C683DF5D53D67E28733C55C3BCBFED5",
- "identity_type": "private",
- "iv": "CCA05AFA378ED7E3B6E33DEBCFBF204B",
- "key_seed": "E224F6BA2E99537502A84B96F633F5E8F2020772A7298A359C860212261FBC8C",
- "metadata_key": "FE01B6AEDE1A55184EB6477E1E0EC794",
- "section_mic_hmac_key": "A47DC26C0806F40C5A322E13CB35735CC128C1DEE916EB60DA5BFA0A39F2F661",
- "section_salt": "64F6BB71376AC822BD1EB434AFB7CD6A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EDD2C2498BFB7A5CC6C86DCF37816EF1",
- "aes_key": "B638E541BF8E9E4D3F8CAB0D9C43E637",
- "data_elements": [
- {
- "contents": "53BEABE818B66A0648BBC5634C",
- "de_type": 583
- },
- {
- "contents": "15B95BBF16",
- "de_type": 965
- },
- {
- "contents": "A72D1FB5F1FCA1FCDB6BD086B1AB05984A2CBAC020F65EA3DCE95ECC8E82",
- "de_type": 617
- },
- {
- "contents": "BEDBEB964295D2487E60521A0B779C41C92D001865F636E6D188",
- "de_type": 611
- },
- {
- "contents": "4698F885A5C7385C57CCB1",
- "de_type": 524
- }
- ],
- "encoded_section": "9B90133F363F1A9D391313EDCB62DC7AA6FDAE91100007942426FD3FFCE7249E32B5F9E1484D900298AA6A9DF9942745B0947DA0AA8DB7E48C35BE7A0E4A439696CBF426A0091045DDD1C04A3205A048DF546DE43851CC0686DE448A75CEA658D7D6092FAF23BF29CBD23D5F5ED23F974838B625C25D73F8E5BD6ABB82860479288BB7D7D0978779F30A9071FCF6EFE1392E1FEE30F696D95FED120D",
- "identity_type": "trusted",
- "iv": "6B4203747F8A557FCE61C1E19010B25F",
- "key_seed": "1590AE9CF009E4B80464AAFBFCAAD6BC46EBDDAA6E628A422A1B4249F4FA830F",
- "metadata_key": "1935DBB80CC48394742FB7C36B028FAC",
- "section_mic_hmac_key": "71D7A4B4FE0AF5B94EA90A46FC83E860689BA4396E20B502B0D4864EA65BCCAA",
- "section_salt": "07942426FD3FFCE7249E32B5F9E1484D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "935B3FFA8B8135594E8527503826B3D2",
- "aes_key": "93E2CBB2A2EBF1A3AEDB88002066B1A4",
- "data_elements": [
- {
- "contents": "2E4398A194FCB5AB5D16115ECCFC8DF14F",
- "de_type": 641
- },
- {
- "contents": "C1EA5737",
- "de_type": 754
- },
- {
- "contents": "B29CCCE545D2C871",
- "de_type": 110
- },
- {
- "contents": "6EA75755FC7744088E0F7B362E41237279C4FE285F5C635F07D3CF752607",
- "de_type": 973
- },
- {
- "contents": "874045A5D8A7AA4E81B9EE2882373798DD9ECB95A34E11",
- "de_type": 733
- }
- ],
- "encoded_section": "979013EA6D1A285718D881780D442828F059B99110001DCB8556D111B113078C24BA2F06257A90028982A17443826EBF908DDC14E2E9453E86613E316703C30041097712D0D411DF102061D68772BD9E8C2092DE956BA65B2E07D9B0A7B17923D252DFB126135175629DD89BF5C96D17EB260EDF8A3D5B81D553CDA272E2DE310635BC84C3954F2A0793434C18915A2C3116A46BD0B858BA",
- "identity_type": "trusted",
- "iv": "1B9858676FA1CEB84951BFC4467F1C8B",
- "key_seed": "CAF5566753E37F13983777EDAAA48A37A6571043DF2006AEF7D119B7AF42CDB0",
- "metadata_key": "F253A8C6D3DBF176DD97993A3374EE11",
- "section_mic_hmac_key": "ED5EC19C2A28BD1AF19B1AFF30EA766510474865A3F7F1A202C54F8B4F381B78",
- "section_salt": "1DCB8556D111B113078C24BA2F06257A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4E0560D260CF64013CD1C5CC2E650168",
- "aes_key": "A3BDBB9EAF2B23B5B4FF966CE7145FCC",
- "data_elements": [
- {
- "contents": "1FE258CEA28507442694EB54141E014514673A8BC93C",
- "de_type": 794
- },
- {
- "contents": "43B8336BA71888E38BCAAE61CE2A14800F8391BE83AD3084",
- "de_type": 752
- },
- {
- "contents": "E1D434ADA8FDE1F7D4DAC388C51B119ED88A3BBB15176E5C2B4D4F",
- "de_type": 681
- },
- {
- "contents": "05A7198CF43DE4",
- "de_type": 195
- }
- ],
- "encoded_section": "9390130807BD8B1CD2AEEF80505B5DD980558A911000235636B0516C0EBF29BFEA053BA6F2AA9001E8C847964A02279AB5856888A436078FBEE7524388992EDAD6505EA5910375D473D171744D84BE74C660D2E11F39587D329E1E9179FEB630C8282FDEF0943D8A1C05C27CEAB78D3F2E4840F84C0E111DE4488459DE4476D9EE8F50350B123B54057D3672B664AA442F43E812",
- "identity_type": "private",
- "iv": "8E5A00D0BE05A48A2BA357E27C2A67C0",
- "key_seed": "E90D5815F43501F8DC7DADE9C1FF1E8B42893B9CF708DF00B7C7852C5A4132DC",
- "metadata_key": "EDEB59B65043C9D70892DE01B1FAE8BB",
- "section_mic_hmac_key": "DEB63991F7F5B2C38BE71212E5F29C6EAA5030154229B40D1369EECBE2D4B44F",
- "section_salt": "235636B0516C0EBF29BFEA053BA6F2AA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5B1529C4EF462754DC819B8A7A990368",
- "aes_key": "85EFE96F8D4DE137F7742C19A794CFA3",
- "data_elements": [
- {
- "contents": "11DFFC1867A923A6F11B76237535D43A",
- "de_type": 507
- },
- {
- "contents": "24",
- "de_type": 689
- },
- {
- "contents": "987A00093A8A9BFA2BBFD82D5822586699A7B76899C3CA21B80AA95413",
- "de_type": 341
- },
- {
- "contents": "816761B857BFB83A8EB308A3",
- "de_type": 313
- }
- ],
- "encoded_section": "7D9013904699D605A53254C2CF00ECC73CB8E6911000F2EAAC8EE7A9ECAC553E0E8EA6E370369002917F7D53E0000B7D92469C691DC007DDD552F7EF633EC0ECD760CE5A2A5551F2B3EA3B9FF460BA6CB1AC699693216AE065736771BAB5DBFC447BDFD3A0486F7E891703FD14D140190E06692A5C0E4601F0A11CCE364D",
- "identity_type": "trusted",
- "iv": "5AE06EF1A9B235583770B28C6F519692",
- "key_seed": "8CB9FDA44549F1764F0FEDD6C7EC01D2D861BEB2F8314ED90C4780AF46140765",
- "metadata_key": "4099FB6F91A2857E338956FE29D1A1BA",
- "section_mic_hmac_key": "C98F2D369EB883C1758AE560E8A1E093C2978F0322E39F8F9EF2723257C7E73A",
- "section_salt": "F2EAAC8EE7A9ECAC553E0E8EA6E37036"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6AC9566CE6E59CA80D112ABFEC45D36F",
- "aes_key": "B8E9265C2F748123F5B9F751A7A2D03B",
- "data_elements": [],
- "encoded_section": "379013A8BA2217F87C377CFB1EDB0276E64980911000FDAAC5F8B202E266DF331B4D9B46FE4D90011536961048D58AC961B34A4EEB49CDF2",
- "identity_type": "private",
- "iv": "B005B7623A86312314C0C0D7FCBC3F2D",
- "key_seed": "C8A695C2B0FBD7385393A196CCBD82493358E3BE62E1CC7BF2C71186DA29F5D4",
- "metadata_key": "8E5B6E18F6AD98F4150A32FD656B0C08",
- "section_mic_hmac_key": "EFBFE5124202575DDAD381003750174824B77800E8707A9CAEE7804E3A63EF16",
- "section_salt": "FDAAC5F8B202E266DF331B4D9B46FE4D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A7AE7921CC86A87A8C75811E6A9E03A6",
- "aes_key": "250B08B04A835AAFB9E6076FE700799A",
- "data_elements": [
- {
- "contents": "C6B28E20E9790237477E",
- "de_type": 504
- },
- {
- "contents": "28606C895F0801DE3F0ABC9EE5D131CDDBEFB3A344D6",
- "de_type": 396
- },
- {
- "contents": "7127F17814E2EFB43948",
- "de_type": 537
- },
- {
- "contents": "3082C7",
- "de_type": 705
- }
- ],
- "encoded_section": "709013C4A2A5BF3547013BBA1B383831D1BCE091100036E0549437A58C8096108736E2E54F839002C5F3CFF2372998337EBB3B98F98ECD208A00A91C9C03D46423D1282994D4AE2AE73612F111C2107AB19ED220A1C50DF885BE240BFFF7BA40FC735FF5159D92C1C36BDE1A3E8DECE91D",
- "identity_type": "trusted",
- "iv": "FF91837F451EDF3D18A22D3321C100B0",
- "key_seed": "37279E81EB85F4A82ACB0A83D1E35C175878673E5991CA8CA24DBC718459BBAD",
- "metadata_key": "4D47D647A7586385837A57466C13DA37",
- "section_mic_hmac_key": "176D917352650AA00449B407739BD411141689F7D493E0FB4DE373F6EB227D09",
- "section_salt": "36E0549437A58C8096108736E2E54F83"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "31CAFA91829553CE7076258C50ABA254",
- "aes_key": "39055F82C293C2F814D14BB7082021A4",
- "data_elements": [
- {
- "contents": "138DB57FC84A2A9FF858980497BD66AD07B3D35861D398",
- "de_type": 908
- },
- {
- "contents": "F1AC596899642AB4A3224A33E3F4BEB89567D138A00897",
- "de_type": 97
- },
- {
- "contents": "F33377C511B8F1A14E",
- "de_type": 994
- }
- ],
- "encoded_section": "769013A24F473D02C870D82B5A2C492367719791100093084927BDC539B7664A642EE828FBCE900473352C75BD958A2419FE4C5177410E191C38BE4D8B0B21783969B4FBF28D572EC372B59CC8C5BA0E38D9278308403C87CFFFDABBBAEBCAB827E53AF03E87A4E5F443604A7DC6DC78DBDDF0542CE645",
- "identity_type": "provisioned",
- "iv": "DD57E44D3F0D0F3DDD0201BAD985A27C",
- "key_seed": "6E931D385053BA0B12BBD523DCC73B3B4E67551C3F5E2B4DB28D1F877CEE5266",
- "metadata_key": "74DA1C3C2C26438FA854D14D71B8E385",
- "section_mic_hmac_key": "DBC7B9EB0B1B3B982AB762BD1AB304184D1400952590DDB7D0D04E1C394ED3C3",
- "section_salt": "93084927BDC539B7664A642EE828FBCE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C49F4B14FB613C049B9F05EB9CE7879E",
- "aes_key": "CF327AB0B447A7AF29CA225D0C66BF88",
- "data_elements": [
- {
- "contents": "EA",
- "de_type": 603
- },
- {
- "contents": "4BFE2D10A8F98339DA94AC7FD972892BE0F7F94C112C2F9018D6",
- "de_type": 512
- }
- ],
- "encoded_section": "58901345F54B3BB7D5FA01A970B7F3DE3035239110005BD59D6B596E746EB47FFAB378E67610900142AF5B387E46C1D390817ADAE02E9776069475827A331978DBE74C0B598B62EFD874514FD69C4A497DF102F7E7D28E2C15",
- "identity_type": "private",
- "iv": "49CE2D4CDDD1FE4C7F55FC3188137869",
- "key_seed": "62748144FB2FB8F3D1D26B7E29407D49E03EFD9152E00668A8D4CC98B33C1C6C",
- "metadata_key": "BDA4A1BB532F0F3759B50CC5FBB7FF0D",
- "section_mic_hmac_key": "92915252B41A8BAC323ED59D919DE01B1983FEF1232D5D3A49618998A334AEC4",
- "section_salt": "5BD59D6B596E746EB47FFAB378E67610"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "50478F0C95C5ADFF1E22DBC94040F350",
- "aes_key": "5C24804ECE27E5BA68E99847F7F885AA",
- "data_elements": [
- {
- "contents": "EEBFBE7C8584ED74277C8B3E2B502ACEBF24B267DE6D894B",
- "de_type": 194
- }
- ],
- "encoded_section": "52901366A0670E47B7DC095DCF73102FDC73E69110007B56EC0A6BABDB182C71BB10F5F08D279001B9D91DAABDBFE394958F6E84E6CD12D44D75C23DF167B985A9192F31C1086D9764E1F18B9B0510E5B85C8E",
- "identity_type": "private",
- "iv": "FB5AAAE3EACB3C7010D00F3F5D2C3BDA",
- "key_seed": "ACA00C1D38AB3622FC6476156686D8C3546B5D7DE0D35CB2E577838779F26FEF",
- "metadata_key": "F13BAF19DEAB019E02548A01243255FF",
- "section_mic_hmac_key": "D5B4C8E5CBE16DEC491C3D0B361CE588EBC197E0F8C07B66E45C620DBCF0BFAB",
- "section_salt": "7B56EC0A6BABDB182C71BB10F5F08D27"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B09E7223DB55CA715A7CDBAD5996A263",
- "aes_key": "5A08C9A027433AA95DB2853BDA25B1CC",
- "data_elements": [
- {
- "contents": "4D49B84727526D565B651F",
- "de_type": 191
- },
- {
- "contents": "F5B14E3F786C1DF52258DD7B7E5240A7707EAA887484A166AC4E54",
- "de_type": 408
- },
- {
- "contents": "A3ED876A074183595073A43A689030",
- "de_type": 910
- }
- ],
- "encoded_section": "759013C7D3F5BC51A900A5862D9C97C6420421911000742D8D5C8DE82797022EA2DBA6D1D34D9004ACA1B9AF6447CE5086B439B1BAEAECDCFBC67943ED19B7FE2AEEBE927C13A54A0CFF804BD8F6B6273D3750CAD751DE373DCDFFF91B61F4F4BC31F8931DD6B89073E2C00B353709314955E535856C",
- "identity_type": "provisioned",
- "iv": "6A4EC7D7D1DF376EFD6C30D4752FD4FE",
- "key_seed": "B7FBE1F1586D2B63C20CB1153D7204A8CE46AF139AE5ABF1E2473727EF014DBB",
- "metadata_key": "FF8E365F1C10EE5D9289E6E2A3431604",
- "section_mic_hmac_key": "FFE968EAFBFAC3D8464618A92DEB901E018E5AD5DC3E4CCD2AFE7765B97E4208",
- "section_salt": "742D8D5C8DE82797022EA2DBA6D1D34D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "90D4B993DDD10894C7DE4892AA9205F3",
- "aes_key": "73BAC41B294391FD5D5288BFC9903EF5",
- "data_elements": [
- {
- "contents": "27F554F5A7C415247701F0FC053C47F0EB0F055075E60B56",
- "de_type": 291
- }
- ],
- "encoded_section": "5290135D9848ABB456C6795F5FDF8A0D2671739110008C9B682EE5FE5EB5CE1BD9870CD71A9990043229E5C5C36B418090ED95DDBF6CC97A05C02E2DEEB8080D6B4B9DADB45B6FC5A20FCBB7CC08B5ECC2909D",
- "identity_type": "provisioned",
- "iv": "7695C534D867D68F7C1932B112715819",
- "key_seed": "6975C61D58BA24A1B4EE54ADDD2C442B98EB26E46A705F388DB5E2ED510B4B28",
- "metadata_key": "D17E6640A3CA07E378F7065697EA5991",
- "section_mic_hmac_key": "F96908B8BF76281EDB7BBD7ED61C717F9696F1D86A35A08EAE230403A1107554",
- "section_salt": "8C9B682EE5FE5EB5CE1BD9870CD71A99"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "68815B831AA0916F568E55263A7A48B2",
- "aes_key": "5EBE57C4F71896FC3D6C0F1234CFE4C8",
- "data_elements": [
- {
- "contents": "2D2EF51996D21B2E51463AF39E92",
- "de_type": 266
- },
- {
- "contents": "B5B3289B121AE9D357AFE47D5E824F60",
- "de_type": 506
- },
- {
- "contents": "CD3BA06429D31778484A63DFE622C417FC91017592E7B2A9999BB95F",
- "de_type": 605
- },
- {
- "contents": "D75A6907BAA74620FA2085",
- "de_type": 41
- }
- ],
- "encoded_section": "879013A6C5D0E432008BA653FF7129A306A3EC911000EA1BB84D74CCE63FC6E8A7BAA4D0E8BE9001A66002D08581D42781E1B71D02A14371C531338D6A14F22495832CB9F5ECA5BF022B9E62D6A72168A5889635871DEC3B4BF993A31FA6D88D147BF16E48B99F9F78D7433C9FE0D8900F2B64CFDF5C5B54AD9BDC2AEA6A53CC6AF84FE9AAF59193",
- "identity_type": "private",
- "iv": "C35B01B06E5D277079BA8AD9DBC8F362",
- "key_seed": "F0C3EF794389DDA400ADC8FAA947DD95143F6607B459C306BDAAA576F465E52C",
- "metadata_key": "AF790FA02EABFB6819FFF681B9DF902B",
- "section_mic_hmac_key": "71A8D29B91A31FF5FDDAA7C80D68F46CFBBC16402B57282E74129BC4B17499D3",
- "section_salt": "EA1BB84D74CCE63FC6E8A7BAA4D0E8BE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4A9A6B72387F31CDE7DEE4E7E406DFF6",
- "aes_key": "B3591F7BBEBCFC4D19A43572B2BBBCF5",
- "data_elements": [
- {
- "contents": "287900DBF7C6EF207125FA0402",
- "de_type": 126
- },
- {
- "contents": "3DB9807390DD723B2BE6D68E83DF7C2770667A585BAAFDFC6B60F23B6DDC",
- "de_type": 914
- }
- ],
- "encoded_section": "6790137F9988226CFB15EA43A400BD295BDFCB911000642FBA603E7E92B57E9AE3A01C2A4067900198D788FD01113B8A8C929309797B3A7297B90D01EECEF4B43E92B07E402D59F4C898D6DB4567499719BB98EEF2FDF3949CE4345E58D410B47377BA3A76EF5946",
- "identity_type": "private",
- "iv": "85FCE66A5FA02412A1234692C64896BA",
- "key_seed": "2CC2199AD55B6F938E243F37DA6ACE29254ED61B0B37B0304329430A2A76E0D0",
- "metadata_key": "631559C94CC2789DE04E60E2ACA530E6",
- "section_mic_hmac_key": "9A892BFBCF0FD28F4E5A8F4C5758870EFE840BA65BBBD08F47BE62CF648FCC10",
- "section_salt": "642FBA603E7E92B57E9AE3A01C2A4067"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3B58BD1E258028DC7224E170E5D91527",
- "aes_key": "A74001E2A3666357CAAC0E33C1855E10",
- "data_elements": [
- {
- "contents": "12A3E1127075B64AE49D7BA96E1C1B",
- "de_type": 739
- },
- {
- "contents": "A234A52C0FEA5B1BCCC9BF31ABE4",
- "de_type": 956
- },
- {
- "contents": "8F",
- "de_type": 184
- },
- {
- "contents": "07D259",
- "de_type": 483
- },
- {
- "contents": "8CF495883089242BFDD53B4564044BE87A18AB4C27F3506A",
- "de_type": 646
- }
- ],
- "encoded_section": "7F90134E199204C2471A9115FF2C632668284D91100075629F4391815BD952FB3733BE9FD5ED90029DB3CCDF47466BCF742E415F1B2808173977D02F7174626840312C0AE5F9460BB6D9896D1C906C783523FE087FC586B3CDBD3837F712E2754A920C13760D62AD1407E0FDF94E5A10A0F6B6435DB107288AA0E8DE89F61C41",
- "identity_type": "trusted",
- "iv": "ED3E7F6915FBA4453344C5B6E412C564",
- "key_seed": "1846D5BA042D86730983D0AAF49EA0AB2B83BEB46A36ED91FB14A9EF471FE246",
- "metadata_key": "E0FD1F3EEBC6BBA6FE654CECD49DB39A",
- "section_mic_hmac_key": "91BC8A5166C8148062C2CEDFC69EFFFCF988181F45B5B0594999ABD9A6A1D293",
- "section_salt": "75629F4391815BD952FB3733BE9FD5ED"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6980A6133FD8A5C51F3C733F504318F2",
- "aes_key": "2114E6476D43B88B62350530B2B5E255",
- "data_elements": [
- {
- "contents": "78D82AC0B53E7EE9DB8E175A4F4C8E3FF309",
- "de_type": 238
- },
- {
- "contents": "DC40997B9DC9FCE9D3A685B4",
- "de_type": 949
- }
- ],
- "encoded_section": "5B901364A48CB28EEFCE542E48C436C6E5C9F9911000D88F6109B3C4201C37D0BBCF905E844F9004C5199C455C3382BAAE410F855270883316438EF9A3A4B9F4AA0146A64D40287EE6570800272C4DA3CBD9E8E6855AF2B117E45550",
- "identity_type": "provisioned",
- "iv": "2677516D425DE7E57AA134A908F6FA77",
- "key_seed": "2446CFBD94DE790A7817A3B309B6578724F386F8699C9E60F64E843F1E6F41BE",
- "metadata_key": "F6619D96FAB75B632E6DB605E17C804E",
- "section_mic_hmac_key": "467BC68954AA7C5F2E3BC686A88A219025CB25E054A00A51BA7A22F9A8EB85B0",
- "section_salt": "D88F6109B3C4201C37D0BBCF905E844F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5755CEF6FE6FD55A41FA44CABD97741F",
- "aes_key": "E8708156531B7A958D952DE7627847BB",
- "data_elements": [
- {
- "contents": "23C735",
- "de_type": 355
- }
- ],
- "encoded_section": "3D9013409B507183829B924D89F0CDB0114D6B9110005BB6431511D93263B7DB812C5C3169FA90010A0D93D550F4B038870E73551CCC98CACB4BFB4A37AD",
- "identity_type": "private",
- "iv": "4190244089F66CA5612739960D6B6265",
- "key_seed": "A0B97402658B7EB8A9CE7FA833B06BE4113813C5DF44BB4CDD2A1026623CE93E",
- "metadata_key": "27EA5EDBB15D6D851213D99E85394969",
- "section_mic_hmac_key": "CBA9B0CE3E1538B7599EB74522BD58E3D6B30CDE7047123EAB8E6C837D3A86C0",
- "section_salt": "5BB6431511D93263B7DB812C5C3169FA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D12CA4BC0DF622B6F2A6C38F244ECA88",
- "aes_key": "FE420A08BE520C56C373D90506399368",
- "data_elements": [
- {
- "contents": "2B284B656DFE764CCE6BD0B8A8DC69FFE06A60A0",
- "de_type": 982
- },
- {
- "contents": "36636E1715B38A596BCC68ABEE73CFAF34EA87B634386C02",
- "de_type": 537
- },
- {
- "contents": "5BF461ED52EF4F04EB97039F41300BD52529363361208E673FF097D5E9",
- "de_type": 49
- },
- {
- "contents": "22E82E947110CD667295C59CABFD9CD0340C6F950AB0",
- "de_type": 665
- }
- ],
- "encoded_section": "A19013E8415BF7F48BAAE5E2349E6AF8C46097911000AEF9DA74479EEAC0C4E65E88E8E8FFE49001A158884B1C0FDBE25B9BFF7F48E3501E1CE87D4BB0C4EDE04ECBE90ED47B150732C022C9666FDF3E7315F74B7776FC5CC9A7E16CA18E90869D563005189D665167689E5DD8BFF6C5C08A8F2EA8025E8BF9C360E5B11918C31F682542595396B18CB98C0F6F2C4B1B7304864F165D897D17CD113D95B5927CD4D2",
- "identity_type": "private",
- "iv": "36217155A9B1C113637F5B31A0D52462",
- "key_seed": "D77AB260151CD044C7B2AAB6E05FBC8E91F36BA08D99DD9DA9B6672CCFB80622",
- "metadata_key": "D98AE815017F1CCD49B73838CF47C569",
- "section_mic_hmac_key": "1C58860A31C39611669FD41F05F3DB0E5FB3841796071415958EFD3873F6134C",
- "section_salt": "AEF9DA74479EEAC0C4E65E88E8E8FFE4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2F7824830FE99F6CEFCEFF4E8DAF9306",
- "aes_key": "B8C0F18B36A2C4CDFF83C57209CA0877",
- "data_elements": [],
- "encoded_section": "3790138347AEC84C563EF86AF3A100CB5C2028911000D26AE3AED6E647BD9318ED7324A032609004420C7090DAC986AC7383E0B07C7D0218",
- "identity_type": "provisioned",
- "iv": "B20E80EACF53908799869F1431A64093",
- "key_seed": "89C8925B2181AC409D718497B652931F78526AEEF0F0D29B16A94CEC57D1C5B7",
- "metadata_key": "7D40A615D28BD9CABF573DC1990929E7",
- "section_mic_hmac_key": "8082F293C5E89429553A6F138CB27C283BDC31F342E0049F6871D614B4E0672A",
- "section_salt": "D26AE3AED6E647BD9318ED7324A03260"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "50835FC1D56A351C460893484BB405D0",
- "aes_key": "5A5B7EBD7ED56C23D8B6F82912BDAC08",
- "data_elements": [
- {
- "contents": "6CC2B418F4BCBA2E3C334BC068E5",
- "de_type": 371
- },
- {
- "contents": "7D0C99B63FC2F485D42A56",
- "de_type": 361
- },
- {
- "contents": "5DA48C5C3DCD",
- "de_type": 659
- },
- {
- "contents": "",
- "de_type": 95
- },
- {
- "contents": "3780B32198E3",
- "de_type": 965
- }
- ],
- "encoded_section": "6A9013522A8B8B0C6E757ED4C020BCE2FA2876911000C7C5CC64D2848A6F5E9B06024AF7CF7490010553DC253CA3A8379FAF58AFC20732CDA0D2D6F1D16B659C6DFA077FB83412170B8A58A249F77F5AEB8D72AA86D3C93F64631650ADDFC8C12FE570B139123F8348B1CB",
- "identity_type": "private",
- "iv": "8C1907865989C82AC1E7C94F46ADC1F2",
- "key_seed": "4108AC4D0FFDFA538E12F709EB5EE2EC58107D42CCC21743E35C4366C8A6E037",
- "metadata_key": "B569E2A8F95000A5D8616779A1EAB30B",
- "section_mic_hmac_key": "7B4E3B5C475E1C8FB665FF5942256874C076B8305992371CDA125A3CE0289D25",
- "section_salt": "C7C5CC64D2848A6F5E9B06024AF7CF74"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B63F775898D49530F53F98C8736B4AD7",
- "aes_key": "1B2DA0F7C59B3FF7DB2E82675228D075",
- "data_elements": [
- {
- "contents": "039C353B728226EABC1C9BB92C",
- "de_type": 805
- },
- {
- "contents": "BE5252DD4308972B310168F705",
- "de_type": 936
- },
- {
- "contents": "35EB21FBC97D47937000F4EC2FF4960751502BC7980B1B3D31",
- "de_type": 579
- },
- {
- "contents": "759DF16D57824FA1F519774AFE9966",
- "de_type": 906
- }
- ],
- "encoded_section": "8590138E794DDD1F90AA00C804A1D55D74199B9110000C181E2D488AC2E6382460989CCFD4A79001EB8A74FFF9481D0F8537BDA5E83313389FA2EFE7CFFD063AE79E634FFF0690390AF5D99664325FE479E22B30E672E3A1C9FA7C51C10023DA9D3934B8E2B5E7B302F7D924B5A3841CFFCB5E4173084EB27D0AF3135DC5CD7BD0CC13817AF7",
- "identity_type": "private",
- "iv": "ED7A001999A7212E0F8D0A8BBF06F0DA",
- "key_seed": "D8C605A919DBCA02E857A0E787D643B68252650909FBBC4F92B621C0825DEE63",
- "metadata_key": "C967056677B2FE105F418127AB4C9BED",
- "section_mic_hmac_key": "76DA9B9114E01E24DACA9B02E6EA5BBBDEDE38A8CF33001989B421B67D73D5F6",
- "section_salt": "0C181E2D488AC2E6382460989CCFD4A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2DEC4BAFFCF3310DBE0F3413788D397F",
- "aes_key": "E519A2D987D271CF5D3EBFB41C42302E",
- "data_elements": [
- {
- "contents": "F8F7F2291376122477777F1C028B89957234FD1B4D8FBF",
- "de_type": 294
- },
- {
- "contents": "664104580D04F0299BFA7EA1E379B5140E891DB347F49FE31F58E1",
- "de_type": 873
- },
- {
- "contents": "8798DB136C098E7EED7A1D",
- "de_type": 383
- },
- {
- "contents": "3351FB9BE8807FC9D78EE332A0",
- "de_type": 685
- },
- {
- "contents": "A6F525066B3624AD7ED50466EE08AC9EF6141EFBF0451F87AE8277DF9CF9",
- "de_type": 827
- }
- ],
- "encoded_section": "AE9013D653FD5F4549F54B1911CAF49FF594F1911000CF4D14BE750B5BA5E49644317DEBD84590015F4C834B18AAE2AA790AC546C1BD9EFBB4FBDC4054A9E5BDFA9E3DFA77C9EA9DDFC714ED34337541979D845D155D15F5EBEA4D7E577172FE9DABFC8EA60B659BF27BC9EA813FD1C6EB693D28F11B35FC1B55CAAD3FACF09A30C6AECBC39FA1F95B6359AD3E7D5135C57B2823637768F51C0608BDC8362E6057A074F6C6A74E34C5CABF14CA7CA1",
- "identity_type": "private",
- "iv": "A9FE4C8782689FC14D8BCFBD33F242AA",
- "key_seed": "E4398DC2A8F536C4250186EC57BB080E3905C0DE7136E5E6684A94DF38020DD3",
- "metadata_key": "8286CB1DD719F554E9CA70EF5BB78182",
- "section_mic_hmac_key": "52BD0E9C4C000F837DF8A80D471D145A9625B8F118641FE81B5CCF958F3F35B3",
- "section_salt": "CF4D14BE750B5BA5E49644317DEBD845"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C2308865C3D290C95E557AEB1189623C",
- "aes_key": "E8BF8FAA9C15279F3C712FDC28EA9E1F",
- "data_elements": [
- {
- "contents": "AF0F38B4A0EE47BCE5B3F0AAF54D",
- "de_type": 27
- },
- {
- "contents": "6B2E9F0DF07EB6D9877DE3E238059802D9D04315E0D6C4AFC8DA",
- "de_type": 337
- },
- {
- "contents": "FA8917EF757AC107B1DD4C",
- "de_type": 903
- }
- ],
- "encoded_section": "7290138C4539BDC8F8AE4C73FC0ED661D0030A91100007DB45B2A020CD435ACE131E78F8595F9001C20DFF6C112B8F2F9130961C3C0A1B8121F539E238D4ADE2C865A086CC93D56D69D2BF38310ADEFE69AD2FD2679A4203E67D8472A329F52C07E85EFF4684F4113CD7C304090D02494B42F6",
- "identity_type": "private",
- "iv": "DA52FF1A543C36D4DCB573EED3492B02",
- "key_seed": "2AD3751078D15056347708E40974A33C922CC41CC28FDDF988F2E2A5A2239A86",
- "metadata_key": "FD7BC17ABBE3AE00CB69C5B13AF815A6",
- "section_mic_hmac_key": "B01C2D3C9C7F049E5F6B994286E4ED7A767AD9727DB0FDE9E0604CD09C5E6EFE",
- "section_salt": "07DB45B2A020CD435ACE131E78F8595F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0E6250F5E1063FFD5625E4899B7EC23C",
- "aes_key": "82B4EFBC00345E53944B62098AC4741E",
- "data_elements": [
- {
- "contents": "84BB",
- "de_type": 108
- },
- {
- "contents": "754F4890235008945EB5DDA0C5794514",
- "de_type": 296
- },
- {
- "contents": "817310F380A4523BA475A885AC",
- "de_type": 534
- }
- ],
- "encoded_section": "5E9013257C860C9FE68D13E448BE77AC156B6A91100073EB2D1A7B9A79694383A83819BA58C19002980493534B01BE7A4C0D57A3B7C279037B65AC33424C40D9ED3D3ED5CCAAAA3387F19EF03CEDA947228D791FA10E21C394650A6DECAA80",
- "identity_type": "trusted",
- "iv": "7B7ABAED849E8CB85465909BB1008A27",
- "key_seed": "39FAF4627996D3A4E86A2609345F8CCFBE215FA4959EE8CDEFA7C7ED76F0F063",
- "metadata_key": "D5CE99E6634247D8D39A6F9FC822F098",
- "section_mic_hmac_key": "4A8284901D526E778AE208C2A347A49FB10CC2A27E1CED6CF06E1629D5D6A8ED",
- "section_salt": "73EB2D1A7B9A79694383A83819BA58C1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "73267BDA51FFF82F035394D3EF80D6CB",
- "aes_key": "3D76734B202CDAB569B4AA364BDD8C38",
- "data_elements": [
- {
- "contents": "2C4473F60CB71FDC87628B247D3DDCE92B0638",
- "de_type": 432
- },
- {
- "contents": "2D130F6710326FE796AA4A73ECB006B595BD3EE95433AD3CA014",
- "de_type": 327
- },
- {
- "contents": "88799981CADB882884B4C47884D0944B8B37045F31",
- "de_type": 884
- },
- {
- "contents": "B2BE3EAF7781B27C26D1C1DED2D503",
- "de_type": 326
- },
- {
- "contents": "8DE982C8211A0DB37462DF80908A",
- "de_type": 957
- }
- ],
- "encoded_section": "A59013DD5CB96E28C1A8F5DD5FEC82CB88BE639110007C5463B073E37C64784907BEBE5BBDEF90021514E83EE8FEF5010680B26A5530A8FDD2A2EDFCF02D32FC9F74DE8654F3816A4E9B62D75A7C768B2D247C127C2016A0F2EA412B31A9B75D74DB39BC47617A87C767C3F7E134FD14E3051635789B5C8B29EB1F4DCC60CFC947589904C336DC786AF79471140DD27C5C4808749AEDCCF2DB7848B30022B64A53FC2365DA27",
- "identity_type": "trusted",
- "iv": "CEC5679AEB9A51471B5D4681A305DD04",
- "key_seed": "6F3DB15F4DF627B06073393BAE946B216F91AE6FE5B3CDBF13FF7EC6641A464E",
- "metadata_key": "0162EF842711DBF3B94E4D471EF750AE",
- "section_mic_hmac_key": "5529B07938C0FE667CB13099BBBEDAD33B2FA644FEFE54C02B5923CF6A8AA2B7",
- "section_salt": "7C5463B073E37C64784907BEBE5BBDEF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8F6E3B41929E4835D8A92894E01D3370",
- "aes_key": "1E7D6DC597401B8495A444FC0DF6BA1E",
- "data_elements": [
- {
- "contents": "426A68378FBD50DAED7B3FB1E90B",
- "de_type": 275
- },
- {
- "contents": "A915A4A2D2DBD35A71628777FC2454B2",
- "de_type": 860
- },
- {
- "contents": "44AC7C57E6F86C622909FA47E9",
- "de_type": 956
- },
- {
- "contents": "20F924FEB103DD50F1A1387EEFAE248676929FB54D48B1E465AE45DF05",
- "de_type": 25
- }
- ],
- "encoded_section": "8A90130A637967EDD9E12ED105059ED73AFBC69110002FD7D90E8EE16536DC7C67F3E60A010D90023894E74272B0D304BCB3E9DF7FC43C807AAFBD40A77D397D77611BCBA2EAB0DDCDB669DEFD729738A57FFD70703EC2B9695A2A37BF34C0DED20B89D6BC2F8F42711A79429C95A4A0E2E190E8BC6FDC6C7A61ABC01BA824D0CEDB71884F62A33D906D9F",
- "identity_type": "trusted",
- "iv": "5DD25A67393B6865442B019CFDB5DF8C",
- "key_seed": "EF233E0B6A8EC2808EF6FE4C625A6FC21809031077F4C3AF242E4B437D8CAF32",
- "metadata_key": "6E4695C00A4D71156E1F33ED864069C7",
- "section_mic_hmac_key": "AC752138D071EEBE9D679C8FC065416E93AE38BFCC21C4F313155F29B827D906",
- "section_salt": "2FD7D90E8EE16536DC7C67F3E60A010D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "87150E19C730DBF9A86B9E12160CE5D3",
- "aes_key": "C66FD1768C38128B074B1F8EF5D796EC",
- "data_elements": [
- {
- "contents": "73",
- "de_type": 429
- },
- {
- "contents": "E6381B5087F9",
- "de_type": 492
- }
- ],
- "encoded_section": "449013E5B8AE1079C8E1B92B68F9546E149847911000EF0F6F02489A17DBEAB359CE6006C8C09002451233A8A062D0578F6040C49FE712945A45FECFE12A899C112ADEFF99",
- "identity_type": "trusted",
- "iv": "AE5502584C0BF952B7CCF3A06D79FB4B",
- "key_seed": "4C90F913AB9E4AB30DB8EC14CEDABA184990B8630D6E72E3EC55DA678F647567",
- "metadata_key": "84C0A99DDE5671E33E2916B2C6635A97",
- "section_mic_hmac_key": "2F96B9CFBB5F2DA7B16B79E2A51B49F8983319461C5E782DC80DE00A36CCB650",
- "section_salt": "EF0F6F02489A17DBEAB359CE6006C8C0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AF2F88F8670B45CC12E1F0BB195537E8",
- "aes_key": "057F34718269CBD6CEE1F96A2281FF4E",
- "data_elements": [
- {
- "contents": "788CB56081AD4BF210B3D2BF2AE24354FC967C426C0D457BF5",
- "de_type": 419
- },
- {
- "contents": "8F48AFD689E68D180BC9",
- "de_type": 231
- },
- {
- "contents": "7306BEAFEB639848A3B9006FC5049BC2C570FE64F15F56F5A0B01F47",
- "de_type": 416
- },
- {
- "contents": "042BCBD8C26AEF494B0262B0203F8C862A3B36BAC14A419BE1AD",
- "de_type": 390
- }
- ],
- "encoded_section": "9C9013BE62CCCE821A4AB67616B63F417CD90D9110009F2AD41A47D93BCD76F3269EB9ADDE3F900160304961426D9B4BFC017C3599287A4B1509319EF24436CB3E3DDC8A5392E1A8AA714B880956F63F1085F709F1483A3200848F85E8BBC7255F0F878D7FDD472D1FE7664AA5849AA65D890CC229D08AC669C863793A678E9D03B7887856953EF9876DE62D09BFC10B0970C1828D7E00CF9FF05FDE6F",
- "identity_type": "private",
- "iv": "00CAED3CFA112DE322DD39A9D46B1057",
- "key_seed": "6CF216D98ABC54B3D01EAF03E690AA8F705D853D1A409C98AAFB64AB5DB8B777",
- "metadata_key": "3AEF7BBF65BB6397D331899133978ADE",
- "section_mic_hmac_key": "4A3B921039E9959F13555CFF983C7FFEFB4C2EB3F8009280814C77E18F2C4E0E",
- "section_salt": "9F2AD41A47D93BCD76F3269EB9ADDE3F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7794B8D1AB196CA8AC2105A839BCD4A8",
- "aes_key": "0ADF3A9468C4E726C4DB2A608549EE98",
- "data_elements": [
- {
- "contents": "CB1B557B230D",
- "de_type": 585
- },
- {
- "contents": "7DBBD4ABC8B4E7589BE1D51921022C026D3D9B95",
- "de_type": 531
- },
- {
- "contents": "DA2FC203F623B7EB1D",
- "de_type": 544
- },
- {
- "contents": "2474FDC7BF11E245A27F94E7ED426428CCB3",
- "de_type": 437
- },
- {
- "contents": "3EE60DA7CBAE5B47FE578E49FEFB1A221F08B825",
- "de_type": 650
- }
- ],
- "encoded_section": "8F90137E678458819B7DC2C5F15AF080B953859110002CDE4D9F6C04C8FE5FDB6C5E32FE2CCC90025D8153CCCA9FB64C5FB097FA5E89BC09E1C5814AD60F68CCFD49AF6FB93D7D5F9A6032BE33FC6B1C250E5AAA4D26D7D73C334E84411E72B9D486E133675636E3574B0C8B5C43CBB8240F59C0CD41D90F886DDF0BA9177BE3CB9FED65F79FBD0018B8032567A6D069",
- "identity_type": "trusted",
- "iv": "1894035341D848E48F9A51C823863216",
- "key_seed": "91506AB916B8A078A6DDE8B0BE901CE7AF4696136DE8D7DE45CF849F7270AC5F",
- "metadata_key": "6EC956F9A4E19C08DFE8D4A622325516",
- "section_mic_hmac_key": "0F4C9028DF6BE7AADA4E075A6BA1DD00677087758012415836160F2057ACD8A1",
- "section_salt": "2CDE4D9F6C04C8FE5FDB6C5E32FE2CCC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "26EF54C5E545BAFE7E3FE21889954F4B",
- "aes_key": "067B439C57F9DE70894D5719B7DB2B35",
- "data_elements": [],
- "encoded_section": "379013080E311384411FF6770D2B94AC7ACE169110001FEFA67CEE0923857B10DD52D0B34E71900450893BB7FEACC5728EEDDF1D26ABC6A7",
- "identity_type": "provisioned",
- "iv": "7EED03455676377622DA473E4F16F32A",
- "key_seed": "DED047531F38D53F63678999DBE4BDEFD7B784848EBB7E002F96458E93504118",
- "metadata_key": "3BEDA0C2BC240C647A331E616CC299AB",
- "section_mic_hmac_key": "C64D36914AAE044A5615D8C61DE6EFE50B28A276550B62F2CE5085A1189616DF",
- "section_salt": "1FEFA67CEE0923857B10DD52D0B34E71"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1F519C5224D33911C941374BC65E28D4",
- "aes_key": "0BE9E36BBA46D40FFEEA09B8F0D5F5C8",
- "data_elements": [],
- "encoded_section": "3790130CA72F7349FE92C154A357B63BCA5350911000F93678548B2DA382420B7D5B5C7ABFA19001315D8C73AAB7AF4B00B43FF2E33BECC8",
- "identity_type": "private",
- "iv": "9057DD64AD863A184C580C3AC515EF1C",
- "key_seed": "6C2ADF30FFE6F8DB97F237FA6563503EBED4A6877A7A90F4453C927C5C46A965",
- "metadata_key": "2A9DCA48AF9238C08F03CBEBAADB5F36",
- "section_mic_hmac_key": "E8E29CA7B172FE28485E42B6038344EB3850A3B4FDC0526A3FFDCE2B658588C7",
- "section_salt": "F93678548B2DA382420B7D5B5C7ABFA1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C1576CC52ACA6AEE4E6D72D158321A1A",
- "aes_key": "AA5444E04F5A5D4CD410584D05BC77C0",
- "data_elements": [
- {
- "contents": "",
- "de_type": 425
- }
- ],
- "encoded_section": "3A9013E14E5F87EFDCDF15AC1D1B4DCDB691E09110004B1A66BA4FD083871ED0239BADD179979004C17822C5F498155EB82DC5852D9A67BF6E66F1",
- "identity_type": "provisioned",
- "iv": "509D22CF33947815509F6D320B155E69",
- "key_seed": "E42FC4857670BE08A3D4A3A2E7CBBBE2C720CC04CCC411247AB51CD36D87FA3B",
- "metadata_key": "BD1150EB7D9B06D0FB9688D424143BF7",
- "section_mic_hmac_key": "0E3917077E4EBF69E843FD7BB0B38765B9BEC3C55D4DDAB58A5FBD74B586622F",
- "section_salt": "4B1A66BA4FD083871ED0239BADD17997"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "377BC9095D04B301058A806B59A57F57",
- "aes_key": "5B7C325293C552B1B1286B3F5A988FDA",
- "data_elements": [
- {
- "contents": "BE2875720FDD655D",
- "de_type": 392
- },
- {
- "contents": "76E75061",
- "de_type": 901
- },
- {
- "contents": "A6DCBCB08EE974DA3C2677054843F1E3BDC74894A82BDD3ED8E8F231B3",
- "de_type": 989
- },
- {
- "contents": "F6C0F899C87F7B6F2ADA4CB6AC54F679D871",
- "de_type": 891
- }
- ],
- "encoded_section": "7E9013D5DEDED151C0BF96D220B3AAFA310EBD91100046C9B3269C4FAA4938C3BE157869EACA90015CD656AB893D2F34D12B52C9212BA6E26191D2054AD777025E72D552876D7F603193F642B9A0AAAAA8F327AEA1C88760EB9968177017593879A486601E2A9FCA7B9AD3F4E3761177516CA335BE2C0F250DB498656A4681",
- "identity_type": "private",
- "iv": "9BF1FF6714915AAFE0ACFC6AFB53B67C",
- "key_seed": "80F614A0EBB5AB849CCC3343443DBD9560983BF83E7F699E742CD736F7C86CC4",
- "metadata_key": "BF0EB0030D8626F493C9F89271E63EA1",
- "section_mic_hmac_key": "D32162D8264CD760B9C3FB677C389333D77FBD6AC51BE51FBD11354B4F04151F",
- "section_salt": "46C9B3269C4FAA4938C3BE157869EACA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BC027A216DD34B788B55394D74F2ACF6",
- "aes_key": "F4500F319B2E1A064448EFD061A1A869",
- "data_elements": [
- {
- "contents": "51CDB7E7020C96926D5B015EF6AFC86FAD",
- "de_type": 209
- },
- {
- "contents": "A8",
- "de_type": 16
- },
- {
- "contents": "6CCC0F2F8660",
- "de_type": 145
- },
- {
- "contents": "1A6A8EF8B495F771C4BFADF39CFB37",
- "de_type": 602
- },
- {
- "contents": "FA7D",
- "de_type": 393
- }
- ],
- "encoded_section": "6E90133436164C4FE9F77A9C7A4331E5670A3191100028BE87A539716E6151518CD624233C80900258DB4E150403902E214CA9BCC5B8DF6F2A79CE406C90817577C0B3ED6D873AB480CC6989346F6893AA42C6F4EB5B83044F3FB86E41B035A7DE509DD369B86297394170886D61A1",
- "identity_type": "trusted",
- "iv": "0B7F0AF24D63480085FCF7948C1825BB",
- "key_seed": "F058BC14D7150596F7251F711B065981E786691012EBC6032D16DD5EA125975F",
- "metadata_key": "CC6B26C79E16DD81D63644043D76A92F",
- "section_mic_hmac_key": "6012E0F51DC90446DCD3BDF0701CD4C3A5C9750318C2BE597AFE5EF2E0FDFCBF",
- "section_salt": "28BE87A539716E6151518CD624233C80"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1A08F7A48EA6CBEC743CF81FC6D56821",
- "aes_key": "D97C644C27E58A5A498EA72243B4A95C",
- "data_elements": [
- {
- "contents": "AEC98CDC9931D9FA7B",
- "de_type": 273
- },
- {
- "contents": "0C0C0EF256DA68",
- "de_type": 380
- },
- {
- "contents": "D3FA7A86",
- "de_type": 877
- },
- {
- "contents": "EDD68F83E5679FD3AC94D4C2429CF0315E",
- "de_type": 68
- },
- {
- "contents": "500D0CFF89F6",
- "de_type": 67
- }
- ],
- "encoded_section": "6F9013DEB0470A1F0FA8A932BFA955957CBC0691100078E0F69271423A55D3CE7B9BAB03CA979004A1F0A1F01FDCC777695FA1905956FC2C0B2E0ECCE69A1DF5B30E799BF694545A488742FCA43945D42FF4A4D85375F6A70A580DD6C262AB36D7EAD41B29960339ED26DA7BA7422477",
- "identity_type": "provisioned",
- "iv": "AE5AD7C635F64E56905AA85E0F9B3B82",
- "key_seed": "CAB76C82AB54159962AF8F8A9E0A6DD4C9B50C5F177EE962D20809A4F547A270",
- "metadata_key": "1E7A975F40C89469B15AC5375E4373BF",
- "section_mic_hmac_key": "AE063C8CFE9CE240A12A366F41D2A4B4A8A8BF6A1C423E8B70B3B47D15CD6A5D",
- "section_salt": "78E0F69271423A55D3CE7B9BAB03CA97"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D2CBD32D735A997DA15835EFBFA7373",
- "aes_key": "00FB26A966AEA71F4F3F81EFF6E5829E",
- "data_elements": [],
- "encoded_section": "379013B611C34F3E2A898D28DFF2CAF8F00DEE911000BAC5A68FFDDEF9369C1C0BC7CC3720309001B9E0939D28E54DEE710832446AA1307C",
- "identity_type": "private",
- "iv": "2A71513622E51E6F2108327F7097E087",
- "key_seed": "F3BA939307B540A9669FCF4BBA080D1ACB6CEE90C507BF68A4E6AA370D7D984D",
- "metadata_key": "DA78623C0201AE798FFC6E8F80F84884",
- "section_mic_hmac_key": "7F14654F8045636DB98447C3BBF86EE7A1956CDFB14CE500A7D8F98C15A43011",
- "section_salt": "BAC5A68FFDDEF9369C1C0BC7CC372030"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "77ADB3A8157794B68D57E93BF8859870",
- "aes_key": "4F6EF047DDC92999AD39D14F5E9E8EC0",
- "data_elements": [
- {
- "contents": "4479FC904BF6F8",
- "de_type": 306
- },
- {
- "contents": "C97FAB7582641A84D1D8FA",
- "de_type": 403
- },
- {
- "contents": "785BDB2AECFE00",
- "de_type": 132
- },
- {
- "contents": "34EB7B5DD6FF9A7C75",
- "de_type": 660
- }
- ],
- "encoded_section": "659013283C8CA35E4ABDC728046AC5E81C10BC911000479E4DBF68E781F32D60231F00FADA7B90012B74C5F9D7D1ACA3B1FDB3BE49719E5B9FB7005799CDED08ED36939500614AFE7585F03593DD5A9C6F9D58A2D508BC234C4471D86AF173D7FDFEF2023448",
- "identity_type": "private",
- "iv": "3DCB029A083103E2C7C69763285546A2",
- "key_seed": "8951296E131C87D3A0A8F8A6E3F91B507A9FC625F2209CFC470E09AB7ECBAEB4",
- "metadata_key": "E621F60D8C3E75309AC74418E87493D5",
- "section_mic_hmac_key": "7BB1F0E37007179FFF5E50DA154C0AB6DC07FB15A3A8C2B9CB80FB0B22A3A366",
- "section_salt": "479E4DBF68E781F32D60231F00FADA7B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5523CC0A3ACAB8E002C5B03E4808D625",
- "aes_key": "A93EAD18C04AF23BA0B446769ED0D4AF",
- "data_elements": [
- {
- "contents": "57CB2931FF",
- "de_type": 736
- },
- {
- "contents": "3BCC86FA67D655249461AA5516BB1059579B79",
- "de_type": 61
- },
- {
- "contents": "7ABEF8CE6D3F04A289C51F3FEEC213AEBB27F491B29F2812F9",
- "de_type": 660
- },
- {
- "contents": "857393CDE700048F7929F87E700697268B389A526F5B4B",
- "de_type": 849
- },
- {
- "contents": "DD1F9B8FC82DC694DCE9B17CE1FF",
- "de_type": 903
- }
- ],
- "encoded_section": "9B9013BFBF9B27EAFBBF9603C2ACA1B8D00B51911000A3C249C74FC22AFC978CE2AB76F99ADC900178863494C9773EF2ED49036A65ADF8B0FCB15AFE7E05523E02D4CA7347DB21D17F63773ECD2FDAD8FEE232AC5B3C3D3EBEFA8DDBD922DEB36CF1CD53C74B55B976651149CD3E192EE54750B4CC7C0108890C5B620F308407DDE2D9E61DDC47286033EC1ACCF7ACAB012F26C116AE0A1F4BA35611",
- "identity_type": "private",
- "iv": "ABF1E4825C9043D121C73EF13E7093BE",
- "key_seed": "811D8AB3E0A91917EEFFE6A65492B725DB16CEF6AC605EC55A719CF855FF4821",
- "metadata_key": "D0E00E77083797F00688A8B8432BA577",
- "section_mic_hmac_key": "B1913208DA43E67D32EBD684C9E51C730CA7EA852C57A61B7EC3B6D296327E7F",
- "section_salt": "A3C249C74FC22AFC978CE2AB76F99ADC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7B9E42554FB00BFC2CAA42EEBAF748E1",
- "aes_key": "A93E1B7DC96488FC144480BB65A01C57",
- "data_elements": [],
- "encoded_section": "3790138A7CF75B48199BCD5F84CE324A50434591100083E5B4BC98CDA2E4DB2A784724360B57900214878DA8B2CF9E53C4506769CF1E4376",
- "identity_type": "trusted",
- "iv": "9779E069B6FA6140944F01A97D4BC89C",
- "key_seed": "BE0D17E6FD478876E8B9BB74BA9EB382D38D2B98637A318D609A377CA7B83480",
- "metadata_key": "5595C8B32A8E9C4C83D565DE60F704AE",
- "section_mic_hmac_key": "7DE7B0C7C21CD1CE05291A17EB174ED90CA69598DD3085DAD647D6FE71A0E0CB",
- "section_salt": "83E5B4BC98CDA2E4DB2A784724360B57"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "660D2523BFEC72D9DFA03CFCB4094237",
- "aes_key": "EC158E6BDA8C755EDFA4E7E40E38469D",
- "data_elements": [
- {
- "contents": "CBDCAACFC2C1898E42CB7A27D4661011705D60C5F32DA720C800",
- "de_type": 965
- },
- {
- "contents": "8F661004B6A92E32BECD006F274BABC1ACC2D3A90FACB1FFA87EDB06",
- "de_type": 710
- },
- {
- "contents": "626C92A5FDA9B4E1",
- "de_type": 188
- }
- ],
- "encoded_section": "7E9013F4C1C954AF5D56967CDC2892BD9A9D019110002204CAA1D9652AF0E2DB758DDA67ED3490016FB87E2EE1E01DE9673E1EB155582A33E799954ED39A22240BFC01E566CFBF7B6D67BE1DB06FB422AA106DA95983C2D230A1BE5C31D12A15F84FA7F580532B15AC0376768035A69094E530B9050A99028721CF9BCFC70C",
- "identity_type": "private",
- "iv": "8ECF0A26DDE36F8B649DECA07753D512",
- "key_seed": "5C7C830B694068C1EE51EF76A04D99C195B8A1836095698FDED6934FE84DCED1",
- "metadata_key": "3257B5AECD39C702BB9D5DF3D8A3F617",
- "section_mic_hmac_key": "045161FB09CE9C68B8F4F79F8ED355A581305F8B9E92503C1274FAEB0F333BEA",
- "section_salt": "2204CAA1D9652AF0E2DB758DDA67ED34"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "941BAB785F65055B50D126F54845E785",
- "aes_key": "36AC7BB4C245CD5A4E082AB5820EFC91",
- "data_elements": [
- {
- "contents": "2B78D10F49303E6870D7D466267F6FE2CD3FFF2545",
- "de_type": 355
- }
- ],
- "encoded_section": "4F901362962B873249BBE0926B653C83801D70911000AB6695F933776370BBC72AC0856836489001E7C16A69C4CFD200DFB8F7B42153F8A70A967EC5E42D4D2EFD82CA7DB23BA8CDFFF0921EBD24343F",
- "identity_type": "private",
- "iv": "C08AEFE2C72088FA9684354784D5B33D",
- "key_seed": "B20D5B6D74823D69BC64FD37C1298865DE0C23FAB71DACCF4BD83CC5AA4A6F87",
- "metadata_key": "643E478373531F6F17E71D77550A819D",
- "section_mic_hmac_key": "4130AA9A3A6E3B0AB872AF92A125F5673A4CBCF6528884520AB8E8A239D93660",
- "section_salt": "AB6695F933776370BBC72AC085683648"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "455F57E0747AE27EC84FF60FBDAD21C9",
- "aes_key": "10A3829309D3BB339971100F42811992",
- "data_elements": [
- {
- "contents": "003457",
- "de_type": 798
- },
- {
- "contents": "6F479F21",
- "de_type": 728
- },
- {
- "contents": "B815202D9A4B1DFE2A29282156288A",
- "de_type": 592
- },
- {
- "contents": "F9CDED3294668BB0FD17353C62DF3B78FD85DD",
- "de_type": 311
- },
- {
- "contents": "7A8C86FBBFC0A452B1B6D1CCCD05D5B3C0D3D519",
- "de_type": 641
- }
- ],
- "encoded_section": "8390137EFDF8FBCA2BE02D60FDA5CDC52DFDEC911000F9AB6616323C5ACE5C8BBC2F57A4AB0F90012AC5B5D47CBD499393205125BBA713DD97759656839106EA68290A930C46FD260E464B447024CC6554323EE4569315B65BCF8838C238A98F5D07BD4D2545DB255A91C9B878E54B5FA09F97C265623A26B01052F91797C11F9B6B36D6",
- "identity_type": "private",
- "iv": "F32FB41CBA0C981CB22F0EF3E128EA1B",
- "key_seed": "2876E980A8F706B04EE8BC575F7F37E79118170235F478E82333F5592FB95A4F",
- "metadata_key": "B7657539A88CA716DABF9DB888FE80C4",
- "section_mic_hmac_key": "078EF4BA19AD750FF10E9234E6F176F4CCD372371D1A1D3F22CE054FA7C8369F",
- "section_salt": "F9AB6616323C5ACE5C8BBC2F57A4AB0F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D2DB2DB9A8BCF5AEF392BF7F8EDB59EB",
- "aes_key": "89A33186987B8B2D38B8DAF629F6BB21",
- "data_elements": [
- {
- "contents": "53DB5DDC34D45ADFE541BF69",
- "de_type": 875
- },
- {
- "contents": "832E",
- "de_type": 697
- },
- {
- "contents": "1E44D10B600CF4E81ED44BD76A4431B6C23805C1D3AD9DD9",
- "de_type": 666
- }
- ],
- "encoded_section": "669013E6A1661A04FF0FB79DA17C60495D887F911000426F9B2D45B1019868EA8D7A205A98C990015C3B65037A20CD24E568C61253296917152A7BBD973F3D7372E2207E3E95AA20F8B0E1BEEF741BCA197680E124C9DE12AC5015FB0094F3157A3176ECC58565",
- "identity_type": "private",
- "iv": "52FD9A08C2A4744A0ED4DF7DF5A1965B",
- "key_seed": "1E1C95D178D5D3721482E1AB313BB1CC17CD81107270466954FCBB0AFAE33245",
- "metadata_key": "8C9E4E3F1616569227DD78E8524FA000",
- "section_mic_hmac_key": "08A59583A45FF4E63BD51BB22C22049438A228AB48E59DE4180CC9B13F48EF92",
- "section_salt": "426F9B2D45B1019868EA8D7A205A98C9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D61322B59881683F4CA689625954B4BA",
- "aes_key": "C5D0F13868492D25CCD7A9ACBB0821CF",
- "data_elements": [
- {
- "contents": "F0D028E4A63FCF08590FE7AA1F78290A952D058A44E483AD",
- "de_type": 255
- }
- ],
- "encoded_section": "5290133934FA6C6ED6A147EC05881A8DBC9B9C911000D154AA47D8B433C113D44CE491BD27C99001B754FF6A6FAF35E8981928F2129E687D75C7D8A44A4BC54F0A5EAD534A0E8D814D20B27456D3B4DF49DC40",
- "identity_type": "private",
- "iv": "39D3563760AC6862EC2BE2D078617533",
- "key_seed": "9A8AC70E3C17AA4920C892C557DFF22DE933A5225517A506A4A2DA31AE8D13D1",
- "metadata_key": "E3FD32B1669F4BC7CD8A270537729FAB",
- "section_mic_hmac_key": "E66F30B485A5F04FF29CCB6FA9354EEFD9519EEC7BFDBFB867FEB3151D6F9A2F",
- "section_salt": "D154AA47D8B433C113D44CE491BD27C9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8A71F9A833292722EB3AC152EF9E3C2E",
- "aes_key": "D6C3FE4169BA5C1F7DD5E31A69DE04C7",
- "data_elements": [],
- "encoded_section": "379013091C3653AF02D4CD451FD1CC61DD194E911000D08DFCA5EADA20717FD66C7001A13AB89004F7BB3F2D2ECE19D69359C262107426D3",
- "identity_type": "provisioned",
- "iv": "D2F89CDEC85C3065FE1855983963A687",
- "key_seed": "D3A4F31DF78BB537F4319E42EAC800AB91E2A4E0A4860BFDD8F24C38CB24A82B",
- "metadata_key": "9FCAF36AF47A83C352D8D4DA69C6F3F6",
- "section_mic_hmac_key": "14F18D13ADF4C22190EF457CE51A6575BAB65698EFD94FBE18CA227D5386E358",
- "section_salt": "D08DFCA5EADA20717FD66C7001A13AB8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B56527D15C00EA6C1F64191500E82B17",
- "aes_key": "6A43BCE02D294DAB0096FBF48E31B9BE",
- "data_elements": [
- {
- "contents": "4634BF3FD479C9804459313CEA",
- "de_type": 340
- }
- ],
- "encoded_section": "4790133CBE647AE20CBC397A25F52A5B56C936911000A59F02BDE2106CF82A01787C33DF2A089004A05865B1C3F0DDB00C3434147F19F333F1796D784CFD0FA34DD93E3136BA3414",
- "identity_type": "provisioned",
- "iv": "3B1A323410690A2F02B5259796488D38",
- "key_seed": "3AF4E5F9F468FC934D60EB5B64FE42E73F995ADF8530734194AC832AC71BD742",
- "metadata_key": "8A76F8A2C4C7D2FF7B656DAFAF4D251B",
- "section_mic_hmac_key": "0635464DCB6685C1D8CD3340BB3E81A1247AFF24A980B5E6690DECDC45854B75",
- "section_salt": "A59F02BDE2106CF82A01787C33DF2A08"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BB563222EE04AC29FF7A04090A36481C",
- "aes_key": "95C44DA79C172EA55314090F38767175",
- "data_elements": [
- {
- "contents": "D75B5DDB4C68A3EA5441964A4D",
- "de_type": 322
- },
- {
- "contents": "37B4C50550C810B4C812417DEB4199026C9355",
- "de_type": 351
- }
- ],
- "encoded_section": "5D90135D599966D1D25825A58E1CABF51DEF0D911000C01337053877FEEE2433C8675EABA35D9004C3AB83900533AADA9D91C0B11245FE4C8FFEFA907B7F99C9EEA4DD312A7FDA8E24AB21207B8A383DE2F4FF33FC95873FDF96B3303D11",
- "identity_type": "provisioned",
- "iv": "17815F8BD9BFF92671528C5F612433BE",
- "key_seed": "AA1CE89203994182C1FF59E97EEE5E15337C4FC31EBCEA71B890BA95CD103B7A",
- "metadata_key": "FF7FF9290BBD363B0D43B3158D234AC4",
- "section_mic_hmac_key": "3FFC5928A11FBE71404CC8CBB4BA8BAE630CDE5421E3165598B0404E72475196",
- "section_salt": "C01337053877FEEE2433C8675EABA35D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FFB446A0CC75E485DC5F7D16E3B40C5A",
- "aes_key": "489063A42F9BCD0D45A9A2E19A414039",
- "data_elements": [
- {
- "contents": "62F1CF47D18470AEB527B7F6775296CC6EFE09",
- "de_type": 177
- },
- {
- "contents": "5ACEF1AA889FDF113138CDAE",
- "de_type": 498
- },
- {
- "contents": "34AE",
- "de_type": 271
- }
- ],
- "encoded_section": "6190136C2A97611B8AD5309E3CAB84A3CF565F9110005AD8B5A464405396CF27B92E3318855B9002C9BC281DB61BB7A2B2C669121E354A6D749B4F8891943647B28F0183FB7D0070AF55DF680EBD14987C99345BF20FC263B30FB8ADDD031444FA2D",
- "identity_type": "trusted",
- "iv": "D79BA5933791B503075CFC01E0FB7712",
- "key_seed": "730687FF006CAEE1C0A66A01E54D4A7CF50BEB7A2D7536C0C4AEAB53E00F1513",
- "metadata_key": "1401AE3D42B1A7EEE03E608B06B44F01",
- "section_mic_hmac_key": "0270565C4972225F54D2DE44ADA82F04A11FB206EE8016554CE2E34150CBD41D",
- "section_salt": "5AD8B5A464405396CF27B92E3318855B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AF42F66B6003BD6524B54DA8D2252AC4",
- "aes_key": "12383F430FBF68B10F14C36E22CE44C7",
- "data_elements": [],
- "encoded_section": "3790132E7185611C4A574D7A958EF281ECDC9F911000AB00F549C0723FF724278B0E94281421900254511D764D856B3D86F6921C0B69BA63",
- "identity_type": "trusted",
- "iv": "02BC7DD34BA8A194DEB6394D367379A3",
- "key_seed": "EAF9F8E130E1D639D765601C07BB3926936B173EAAC71351D43EDF767CCC7155",
- "metadata_key": "3CED07F3973098FEEC050DAA89D1BAB8",
- "section_mic_hmac_key": "5599A5813A1058AECC22B1B3DB8A24CE041AE2F6A287A7886C7131C67DCA6F8C",
- "section_salt": "AB00F549C0723FF724278B0E94281421"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "25670EC81D48FF31F8771189AA170F3B",
- "aes_key": "5461131B01024CAA85D6F3F04C747EA2",
- "data_elements": [
- {
- "contents": "70F812A1C77562795B634A15",
- "de_type": 752
- },
- {
- "contents": "4A7098AB14408AA7A49E737FBBB777F0",
- "de_type": 512
- },
- {
- "contents": "132D64D069C144AA18E7515196547AD6E971",
- "de_type": 313
- },
- {
- "contents": "07F0E91FA7CEF471AF7E42C74DEFE8AB692B1B5FECD68E4EDDE089",
- "de_type": 278
- }
- ],
- "encoded_section": "8C9013A42FDE96C60F5F6E2292A1ACD8538E71911000C655B6AD55A141DDDDC8CA239D12944990047F71A803B61F1EEBC3D498E2916784FFA19ABBA694831D36F6E272FF47788F91DDCDDBCE7922E6410EB61D510D257B0A5BF1A89A2C5567300C40D27FA1F76D6C6D1F9DA88844E5B390D02F9A29FAEAF08E5A0401A824D58BE5489B6F272381628C0CE5D552",
- "identity_type": "provisioned",
- "iv": "BE73A8FB567E9F85D0AB30D9EF198482",
- "key_seed": "5FBAB9B4DA6E55AB6A28DB0CFC1848B4B1A2A740176A41779A2B0CA53C85E0C8",
- "metadata_key": "5A0FC8681CCFD973AFFC3A8A343F875D",
- "section_mic_hmac_key": "01BD476EF165370B6064C3C61ADB7EB35C28E6AA661DE67AE23DEFD9BF0C62F6",
- "section_salt": "C655B6AD55A141DDDDC8CA239D129449"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1698A0A2CBC569C04A8ECE5934215D84",
- "aes_key": "67EEB4455EAB868F8530E5CC19A6D3CF",
- "data_elements": [
- {
- "contents": "3F598536EC1EE56157FAC56036CA37D2FBD91CEC62CF817655879F6C6FD7",
- "de_type": 699
- }
- ],
- "encoded_section": "58901366D5FF91CA1E85781CB65F9F44A6A915911000D09661823870EA098CD4B79528F570549002B623382EE2174931E09C30B1EF4966869EB8E162A0B91F6299A507A566090E48B276A0AA84B82A02C9388E1572A5749905",
- "identity_type": "trusted",
- "iv": "E685B253F5DBECDE5E299677701C3C52",
- "key_seed": "6F12AA77CA2C0963B48CA6117D5AA7971BD017CB4DCABA81A94027F92A478D36",
- "metadata_key": "E91B270B0C39EE00A7445A9FEA85589A",
- "section_mic_hmac_key": "A4D97829E2F5B49AA35B36C8FF77301335A033C6B4BB97987D119B0116A24E80",
- "section_salt": "D09661823870EA098CD4B79528F57054"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "81CC782D7A1DD2CDC0AB810AB984643D",
- "aes_key": "B0EB8589C9401F28FC0C26469D89A63B",
- "data_elements": [
- {
- "contents": "D90FCFF0DAD5588D662E8A7486AEC74A9422",
- "de_type": 382
- },
- {
- "contents": "707B",
- "de_type": 231
- },
- {
- "contents": "6A6AA7D74F5FD3FC85A3",
- "de_type": 733
- },
- {
- "contents": "230C99B60765E1753C29C065FD9F9B7F512CA13613F1",
- "de_type": 47
- }
- ],
- "encoded_section": "7690130FB4E3079CDF302AB7752B12365B7DEA91100088A69F0ECC5AD36DCB48C315F22D302C9002FDE9D76DCF16CDE15E6497EFA632888F9CC783729E139D9B5A54CAF585BDCD3DE00C43748F971D6E8B945DD0A63A53ECC8405AD75DD96ED285EDB30010951E7D995334F0D562E5D5A96B7B69C99180",
- "identity_type": "trusted",
- "iv": "3F139EBD60CEE2DEFABCBE5D8C03CC33",
- "key_seed": "C97A976A77C57D2A16038BF394B1ABCBCF2CB1535CAC921B837418C75FFED5A6",
- "metadata_key": "253F314C26118C9FF2156BD6B103CF12",
- "section_mic_hmac_key": "1C2FE36935B0D3B8B54F8F7ADA894CF63D60E34C4E43E3BEEE457239D9CFA090",
- "section_salt": "88A69F0ECC5AD36DCB48C315F22D302C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3F68DECEB46FC2B26A80632B9F0BC551",
- "aes_key": "AAB3D40BA404341AB33B80C75A455956",
- "data_elements": [
- {
- "contents": "06A9EDAFCD584B6E38788637216971",
- "de_type": 671
- },
- {
- "contents": "2108A76D",
- "de_type": 220
- },
- {
- "contents": "E1AFEA550370A4D8",
- "de_type": 302
- },
- {
- "contents": "B089AF93656690E7F5D458574E009638064A02ADDD",
- "de_type": 606
- }
- ],
- "encoded_section": "73901363D824CD389AB1B5405A4084503F93F591100018C01A505928C235EC10AF668DB40FB390020577FABC21B8AD30907FEEE2AA7B75F0DD28EFCBC3A42056D1AAA57CEDC6BC99DDE47E5481C4AED0104EA28B805A32D55C06605488536113061524D6E8D3E082EFCFE9EA04C60E6205DFEA60",
- "identity_type": "trusted",
- "iv": "D24223CF7DD83A7A535C1C8C475F8069",
- "key_seed": "6AB190C93E00BE55D327A52A7D6E2A6B55EA6BC42F4B4758DF942A0FEE5527C0",
- "metadata_key": "0911EE2B4CE448C904D7EA949BFE7924",
- "section_mic_hmac_key": "AB82958BB658137045E64CAB0BF661E3E93D0CD7E9E09F8C5094832C3F324770",
- "section_salt": "18C01A505928C235EC10AF668DB40FB3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "16F428987093EF4C71103F7DAAB954D7",
- "aes_key": "B654E0BC4980FBAEB1A7BFF6016EEEE4",
- "data_elements": [],
- "encoded_section": "37901338DF36C24A081C8C465579F807AE0D719110003EEF9CADA88DB5EA3CC0A49B3594282F900164F64D69E7941A231ED4B5655C92A27D",
- "identity_type": "private",
- "iv": "A08E3CAD668107A8797F8679F356AF13",
- "key_seed": "E2C7557906E3BC6E94E7CE260E8AA2C1381629F7BCDE83BF6EBD249FAC95E085",
- "metadata_key": "8C974F54F1D47E4E6076477FB073244B",
- "section_mic_hmac_key": "5C1D2E2FFB430890D90C0A9D98C3E39F8CCE5C0F7134AA5C01E83F876C1B6147",
- "section_salt": "3EEF9CADA88DB5EA3CC0A49B3594282F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A6ABE19EA26BB9FE65BBC1F644681FBF",
- "aes_key": "8DCCD08E61E8BF6B3E29907C8FC4A48A",
- "data_elements": [],
- "encoded_section": "3790132CEE5446EF5E2D00BFDAA9BB01F11E6791100081833175A7ABCE8DC548433B6ABFEAC99001C4782C58F1F77A879FDB53B0D7DA71BE",
- "identity_type": "private",
- "iv": "89DD6857CF308FF28B8F20AD6121D2FB",
- "key_seed": "BC9EBF601245D8B4FFB331D0DEEAFF5EB2F4D255B27CA6F589FFE244D7F8BA61",
- "metadata_key": "CE7B6849F29274DA2B5153DA263EB715",
- "section_mic_hmac_key": "77EABC4A9722507E888315D75AFCEADDAAE374D29D8482C32B49E4DE797AD72B",
- "section_salt": "81833175A7ABCE8DC548433B6ABFEAC9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DBC312045F0B91D01D69B4C7D64CA84E",
- "aes_key": "8AF7683D5C00432FF70F5C0F21B62ED0",
- "data_elements": [
- {
- "contents": "8C33E56E140674BC4DE6B6E6503B665690A0A5",
- "de_type": 962
- },
- {
- "contents": "52A891F8F72BD3D53F300F6DF78386EEF406",
- "de_type": 809
- },
- {
- "contents": "E4B5E9A863195AEC5A1F58940287190C21F4EED5A114F9877D",
- "de_type": 424
- }
- ],
- "encoded_section": "7E9013AFEE4868B269521650E527FD6505254091100016B2164140F3A7D4D99588A1F07BB6829001627CA78389F5EB99D9DCF985143E7064B51264680CE657B458350306830F5330349B5943199B49D65CA4FAE46097C0FE5784578C7B937D17650DB5D7F9BB64518ECA0900F6537B0A1A9D9B09D72AAD18F927E8CE44B48B",
- "identity_type": "private",
- "iv": "EFFD6E65CE5969A045DC17F469C55D21",
- "key_seed": "CF1BB3DCBDD1B4B1854312571D0D9E4CD3E51CB66886F8101DBA51454DAB3B43",
- "metadata_key": "7712D6C6361462BB68F275E64847F92B",
- "section_mic_hmac_key": "5976A38A5FC248E579FAA97C4AD81B01EDDB181D787DA79C55C6A5B2A3043320",
- "section_salt": "16B2164140F3A7D4D99588A1F07BB682"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6EE5BA8B14844183D1C587D61EA65F06",
- "aes_key": "8C770833C8746D89219288A5F1C77A29",
- "data_elements": [
- {
- "contents": "4EE9017827E633A83A1F3DF3727636D33D68F25F096F",
- "de_type": 70
- },
- {
- "contents": "8E501147C6",
- "de_type": 700
- }
- ],
- "encoded_section": "5790134F8715DC2D2DD29001712938C4AC092A911000E5BE413F286D53CEB80C4C43A77C8F429001A090B0006FBA8B3AC2B4E6D8749565A555C2823BACBD6BEA07F06CD282865CDD8DFB9AA1EA9CAC5ECB512E94EAA509FF",
- "identity_type": "private",
- "iv": "8AC60B5B6C4BF4DA33864292D1A49040",
- "key_seed": "256E590E325B44B0145FD955AA40CFE7AC01B57FBCEC373C94F17E1B9BBDFF20",
- "metadata_key": "0B9043CF8075D46F3E0FC946A79A18D9",
- "section_mic_hmac_key": "D3479310DD4C5AAB4263C51FA03D1F8593365098868C23A374211FCDE1908DC0",
- "section_salt": "E5BE413F286D53CEB80C4C43A77C8F42"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D941C60088DD645313DFADB182C82558",
- "aes_key": "E9919CDC3C08848B22D3C9AF7834E623",
- "data_elements": [
- {
- "contents": "9BB7ED5BF7DC448BB3",
- "de_type": 330
- },
- {
- "contents": "D4539A5B30220667E3A4C193",
- "de_type": 950
- },
- {
- "contents": "57CB6A30E9BE0B44E14D42C6A9DF1F40F78E5A72CCAE8DCE6ED20E8B8D87",
- "de_type": 94
- },
- {
- "contents": "21EA5370D8F897F0C836F9C0D7D8D20D9031B6AE",
- "de_type": 220
- },
- {
- "contents": "1ADF486290D5EA500318FF",
- "de_type": 121
- }
- ],
- "encoded_section": "969013A9786ABE6D8971BD5514FDFA8CF2AC559110001142426FD9F8AC8E04980A76C8873DA1900263DC49F57C111C30ADA31DC772A46B34F87451042E48206D7BCEAA5D1C5511C413D77CEFEE13355DA1535D628BD04516B2983741CBB4266ECCC6252142347B8113956A28B3094390F7799F541BAB5FE11D7C3DE41C546B090467648933DAB1D5D4939B75B75C9BFA68FD0640EC3FD0",
- "identity_type": "trusted",
- "iv": "4C74A83C4F3D310530BC20A76606169A",
- "key_seed": "6CFB25BD6F1AD54702025AA20976E8CC36E5125EFCF766339E9FF00608383FD5",
- "metadata_key": "B6623EF31E56177E5E2FA2D34EF08217",
- "section_mic_hmac_key": "1B6CE9263DCF22995C99D2E8328D6FACDC3B3729A0B2E8EEE4992C6231B5992D",
- "section_salt": "1142426FD9F8AC8E04980A76C8873DA1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AD17F621C4099C16E1364DF5EAAD46E9",
- "aes_key": "4162A567DD3D59242D948EC4388D3BA0",
- "data_elements": [
- {
- "contents": "D1AC9D",
- "de_type": 319
- },
- {
- "contents": "AF10369D76F126F65771B19AEBF8CB7063AFDDAF",
- "de_type": 568
- },
- {
- "contents": "8EEB01E953A7DBD9FAE4543BAF174901D9946C89422B007F22",
- "de_type": 659
- }
- ],
- "encoded_section": "709013BF382460F591A5AF35356E3138DE8BBE911000F008A0E0C87CEC6F7481FAEE41DE2972900492A0930FDADCC989A95DA24F2BECB1F0120086D7B4BCD531450DF307DB40F1B3B6E2A2BEFB0F2A158EDA479565E941CEF4DD226E05EA5A377DC6BAD5C4DF31346DB5887886E07D1F5A",
- "identity_type": "provisioned",
- "iv": "E2E2D8C0EAECB4E929DFDAC68E4A87CC",
- "key_seed": "6A41B3A483120C6592A27A6DA224A2CE97A3630D7380BA9B492B7670C2DCA431",
- "metadata_key": "84B633DF772A8582F240990C6505CFFC",
- "section_mic_hmac_key": "6DD9ECC46CBBD6FFEB27625580412AA19C944BB3EE91E7BDC856B7DEE375FE6A",
- "section_salt": "F008A0E0C87CEC6F7481FAEE41DE2972"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EBDFB8A3FA70511CED2FD2BAC79AEA0C",
- "aes_key": "6A02B7B1B88FCF1141E10889BD473530",
- "data_elements": [
- {
- "contents": "78071178",
- "de_type": 776
- },
- {
- "contents": "49A8B73C22BDABDBF1",
- "de_type": 36
- },
- {
- "contents": "E34B4BA2CF",
- "de_type": 205
- }
- ],
- "encoded_section": "51901367AA7D0CEB9619E38E3BC8FF5C259F59911000282ED516C9E632397B697EC6D5C023189001E888308F07AF62FEEC9F6AF1492CF04DE123DE408A607131F4454B1439A68F73D2FD5624B674550A37F3",
- "identity_type": "private",
- "iv": "FF4CC7BD41CE43FFD5B10FB55AC1C4E8",
- "key_seed": "2860FE966BB48A14B70CC4D212BA76776EE122D2A3C58A45001060CDCFBEBC25",
- "metadata_key": "A87D121E726F9D661E37F5829450D07F",
- "section_mic_hmac_key": "EED14F69A5D27D0ACDB1A1FDFF1D5FED2FE02A60F0597F60376092286816EB42",
- "section_salt": "282ED516C9E632397B697EC6D5C02318"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF919F4B960D6466F6140686D0FA9252",
- "aes_key": "E64125AAA9FDAC6241981F9DD418A55E",
- "data_elements": [
- {
- "contents": "59C49F092732737FF5AEE11EEAA22EF01B0F8E8438D0BE8D8EFF99AF",
- "de_type": 472
- },
- {
- "contents": "",
- "de_type": 38
- },
- {
- "contents": "05F2391B9C27F2F93B4F90090D588DF3B94B1E",
- "de_type": 920
- },
- {
- "contents": "E088646F209D208B75C2",
- "de_type": 573
- }
- ],
- "encoded_section": "7B90137043A1380AAFA41C6CBE5A04DE25FF85911000C42674BE68576F2D75F9993288D240939004EB40F863F87FC7F36AAF85EB09F252C69D551F07DCACC4364B7D1470BD606DB9EB51F3EBF8721B9DF168910D7287029C237EDEDE9D4C07046349A46B7BB4ED83742649EC807874B64F3F34DD6F079C749D2C527A",
- "identity_type": "provisioned",
- "iv": "CB56304CEDF311EF61555C248ED67AFB",
- "key_seed": "C7CA3CF04F910C2F618556A302B2AA4B21AD9C6D33B623B8D55D250468B92DD8",
- "metadata_key": "70A8E9692001AAA64431EABDF02BCDA8",
- "section_mic_hmac_key": "FD97007887547EE99A2BC7160E149E08A91C640BB285B5B80B3E18B3A87E7A60",
- "section_salt": "C42674BE68576F2D75F9993288D24093"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B7D3C684246A638889A81C2A50D9CA69",
- "aes_key": "3C90071725C2D7C73AF1A21FFC7DCE1D",
- "data_elements": [
- {
- "contents": "8D580692F89B5EA1E3CA4154F0CDC018E0",
- "de_type": 812
- },
- {
- "contents": "C9E79F183FA7E85C6A93B992E99A10D3B9FC39",
- "de_type": 160
- },
- {
- "contents": "DB1462A10152",
- "de_type": 248
- },
- {
- "contents": "83067D1B116DE15914D21DAEEBBA563D9B11C7263399C97C91F267A9",
- "de_type": 67
- }
- ],
- "encoded_section": "889013120757F626EFF3FA706F5F7D9258F969911000C82A55BEE9331ADFEAF004B1F8411BEA9002269BFA035A00CFF999E7A24EEA0BDA41AF2435C3000FB78786E40EA307FF724CAF0E107ECC03677F508CFF053E269BEF7C643AE9FB379142A28C8B526720D5C02C616293082B34C65ED08F6D0A9B040A4A19907709AC21CF3C887546F6D4830DBE",
- "identity_type": "trusted",
- "iv": "8D1D26E68602B0801C1BA240B64AB2AC",
- "key_seed": "0E7F40995A8CB111A533A7D3D37855140BE8A688302F897B91EE118209F89E0B",
- "metadata_key": "44724015014CA24A6AD976E039AF5254",
- "section_mic_hmac_key": "67861314F763C77B267EB38601ABC850E44635BB29A5E015A9BF97AD02B11887",
- "section_salt": "C82A55BEE9331ADFEAF004B1F8411BEA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2275164A24418E8253458C856948175A",
- "aes_key": "FCDA486D97B17E4B73B64FCB6AC2E512",
- "data_elements": [
- {
- "contents": "62A5892D",
- "de_type": 200
- }
- ],
- "encoded_section": "3E90133D01BB959195FB48361985459C950BF1911000EE19D4FD43C4A26C45CCC2F73391D2B790018D15AE13971DFDBC5C660CE316817A9AE8DBD7388C7FD3",
- "identity_type": "private",
- "iv": "5F5F397CA6FE206A01324ECB021E3229",
- "key_seed": "E62A5DFC2D220D5A60C44680C620B02EE4B967CA42C0662143C9301CE3647489",
- "metadata_key": "69F403CDA27C235769E0B517D73371B2",
- "section_mic_hmac_key": "336592D0479F0A275CE32751290E25373CCCC3DEF8A76D2E1E19EFEC29652BA6",
- "section_salt": "EE19D4FD43C4A26C45CCC2F73391D2B7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D37D8224BCB2A88E8A32373B761C5ECE",
- "aes_key": "299ECDF8023A36C8961C3847B7865F23",
- "data_elements": [
- {
- "contents": "B2C987A7B7",
- "de_type": 461
- },
- {
- "contents": "5B5275A30550D0451989E8CCB707F4BB4E1FD7E4067559",
- "de_type": 660
- }
- ],
- "encoded_section": "59901351BC1AD8D62AD25E038519C98478075591100067A626FD764561B80156B43BBE18FE2290015BFCAA16FADD4E137A681CF88C1AFFE67981CA680202D1EFEF1539610538D8B2093E92A2C90B89CDA487E480ACA010EC5696",
- "identity_type": "private",
- "iv": "84E53FE82B267ECCA4C338365D976371",
- "key_seed": "D054FA0157A869AB9D6ABB5966714E4699E3120582643226CCFD8172DFEDDBB3",
- "metadata_key": "3BEB83127D47BFFBE32C9CB76F2F95BD",
- "section_mic_hmac_key": "A41BBD631F9F0DAB81C18776F6877DEAD586AA8C2822E14910DAD1256FEF741E",
- "section_salt": "67A626FD764561B80156B43BBE18FE22"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C7053AA74A4BA2AE0F70F44E089D29D1",
- "aes_key": "65F1F9E585E540072E2DE478FE1AD76A",
- "data_elements": [
- {
- "contents": "1A6312AB5101EC2B51494185A33F7F7CA3D3AA6A52F9BCA5",
- "de_type": 27
- },
- {
- "contents": "626A45FD",
- "de_type": 163
- },
- {
- "contents": "2AC1B1D049847CFEDD3EA121A0EF",
- "de_type": 805
- }
- ],
- "encoded_section": "69901379404B1053D12C1265E80377181C80079110001D9694EAFC36DEAD331B1AF01E6FAA569004F2611593ABA4DF715ABB0A60045DE939CCFF012A67BE7120EB8622F467C40A55A438E9FAC305C7F3DD3D7F1575561AF3B80071400A1E23474E4FE5A753060054AFC7",
- "identity_type": "provisioned",
- "iv": "BBED73E1526356DC7465518B78F1789A",
- "key_seed": "4FF6F2ED889471ADE07505655C61FC55A296E2A781ED23D697FEC64C46F7BFE8",
- "metadata_key": "02EB04450E5882DAD40B9C11E74ED571",
- "section_mic_hmac_key": "BD2564C4DF163F2CFA403BB08891432ED59C1DAFAA05014FDD02DB19006E41F1",
- "section_salt": "1D9694EAFC36DEAD331B1AF01E6FAA56"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2DDB3F10CE6908DE4064A6EADAA44CB1",
- "aes_key": "D71B858543B064C2FA1C226CED9715D4",
- "data_elements": [
- {
- "contents": "3C79B5CCA08F604A35179CF79E27EE4088EAF9284082C9B9C6E5A6E3",
- "de_type": 98
- },
- {
- "contents": "6147",
- "de_type": 603
- },
- {
- "contents": "A5327E05BDBCCBF609037A6A47ABC084",
- "de_type": 684
- },
- {
- "contents": "FDD029D869BC2792F863D0A330B26BA567F312",
- "de_type": 660
- }
- ],
- "encoded_section": "83901346D8A7AD53629FBFB4554D2893B59A3E911000193EF4A81E23010C50F7AB9D66E7B1F99001D4BBBA69FE1C5DA04ABF63E88F73FE4AEDA30C5D6AEF3F2E38F53427C49EE027B70FEAFD31011161C5F054CC6D4A916EE183785B7384149E601390215DFC3815E502695076125919A5D0A396C7769222A3E1CB02D660F4FF07F695F2",
- "identity_type": "private",
- "iv": "24B30EF97AD89F61F32199637B14D984",
- "key_seed": "AFF8A5868B46113882EDCBAFFB25259BDB083CF55DDD4EE8CEA0BBF5A8E20783",
- "metadata_key": "54ACE29DAB4432CA8456C3606A3A3285",
- "section_mic_hmac_key": "F69C1B262B9E5E9E937CE8396D019326A61FA1598383147B8864197F7E1748D8",
- "section_salt": "193EF4A81E23010C50F7AB9D66E7B1F9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3B652C1DFA6EA396CD6299D7C2F1FC99",
- "aes_key": "C74B97594BAC6BCB81E06F3860424E34",
- "data_elements": [
- {
- "contents": "29ABB0E895D880",
- "de_type": 996
- },
- {
- "contents": "68E69922B69FE5381A0B6FD2B3",
- "de_type": 210
- },
- {
- "contents": "1AA391EC93E13CB834A47EBB0D3C",
- "de_type": 457
- }
- ],
- "encoded_section": "629013C84639CCD7C09FB779FF9746B0D86675911000CDEC9DF81798E081266AA31A02A495F09002AEBB7F8E231C56ECEE3CFE99FBD91140E8BD6E472F819590F8C4407D808E44117A9E6450CEC6AEA3421C3CF6C3A17D76F4BED944670B334DF6ACF8",
- "identity_type": "trusted",
- "iv": "B202A0324BDF0E7D7D79A0FABD70C00B",
- "key_seed": "8211EFA73C0465A1C10B9518F949E4A9E51D9844F8A714E96AF4020A7BDC03F3",
- "metadata_key": "90634220E3FBAE89FFA4415C6717013B",
- "section_mic_hmac_key": "AFC6C865E7CE529D7BA7137EA854E27BB97DC12411B15FC5D2CF5661705DF098",
- "section_salt": "CDEC9DF81798E081266AA31A02A495F0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A807B550B6F46E1AE79A6963B4EF980",
- "aes_key": "B267961F7035BA20C9ACC38375A8B8BA",
- "data_elements": [
- {
- "contents": "883DDF57",
- "de_type": 378
- },
- {
- "contents": "5D7C88A0669FB0",
- "de_type": 65
- },
- {
- "contents": "B735EF9C0366D2BD9A208B7DE02C2F6316739CDAE55A161AC5",
- "de_type": 883
- }
- ],
- "encoded_section": "639013EA03F4EEC56AB81C3840FE707CD0EFBB911000C7A6D417E567FF06D8580DEDB22B6AD790012869A0017974950F3D3AE671F0B17C46335580B531F54DFEFE20792D26A9CBC80E562100C19F01B6AB91652AE86A1DA3BAA1B1BAB6C6142806A518A6",
- "identity_type": "private",
- "iv": "0F1F6DEE9C4E6ABFCA411807FC543D4F",
- "key_seed": "2AE4038986ABFB4F994675F74257DBA4D1421BB7FC26EBD550902478326516C1",
- "metadata_key": "0442ABDF1AB578F04E9828DD59C89747",
- "section_mic_hmac_key": "BDFCD117EF5E7BE2DE8DD21889827C98D3F04E1DF008171A7F780F364FEE870C",
- "section_salt": "C7A6D417E567FF06D8580DEDB22B6AD7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "776476995C0D81CC3EB4BF74DA38DAE8",
- "aes_key": "F7B37CECCCB3A565FE1CA8003E320EB1",
- "data_elements": [
- {
- "contents": "BFE38787DFC2F2E3D6E3B3C87F815EEA76D65A215C71",
- "de_type": 171
- },
- {
- "contents": "FDEC8C66519082CD2A451946464B59",
- "de_type": 236
- },
- {
- "contents": "9E90",
- "de_type": 49
- },
- {
- "contents": "3572D5AC806B58595850066B1725445CB8",
- "de_type": 327
- },
- {
- "contents": "BF3ABE62A330",
- "de_type": 696
- }
- ],
- "encoded_section": "8390131C77D267901CBF78476EF0C05DDC63C591100044DD945128151D3723FEB2519B34EC1D9004652B4B46B0FE74A2B003FB8DE0B02E064E02544FBD3F094FA6D08F17BC432C0E33DC15EE29ECCEADAFA28E6D97942CEAACB9CA570F7C8E18EDF12CDAA49D314049FBEC0D3986BE84CC8D7E5D5D6F4375A5C24980753F106F6DCB2544",
- "identity_type": "provisioned",
- "iv": "15CD9E5FBF435001DF27D9AC024E5168",
- "key_seed": "3F81DB1789AE3442A9D41D4E812CB79D5956A9AC3144B0915DFCE60F0F81FFC3",
- "metadata_key": "4DBCE7E27EC36E0D440AB84EA5F8BB43",
- "section_mic_hmac_key": "30DE6D9065BC10A08AA0E19A128FEDA88875C36F07B91F83B03E4224E8A74513",
- "section_salt": "44DD945128151D3723FEB2519B34EC1D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ECA254EFD9254459DBDBE5273EA5F20F",
- "aes_key": "0BC0403DF4AF8576D78A3BB0D4FDCC07",
- "data_elements": [
- {
- "contents": "2F00BEF93EA080BEEAA53211087262B08F",
- "de_type": 387
- },
- {
- "contents": "5A90C81267154FCE624E6CEA5DEA28F2680EF8513A",
- "de_type": 446
- }
- ],
- "encoded_section": "63901363C6D2E7FE3933E6E8C471788DF819C09110008B835CBB4228316A6BB5B90E18A8129490011E6DDE87751A08BDD4CE6EFD8793A3904FC0F36CC6BB1EF5EEA2E31100FE6E7E9A46F882E749F96E2C0661E5840221A3B8A51F54FAB65E9210C9FCB2",
- "identity_type": "private",
- "iv": "DB42DEB1413B50415B6A102990A829EB",
- "key_seed": "D19CECB68227395C94499B9CC6894791C0E82E27127CD7682E7DBD8F9490F767",
- "metadata_key": "7D38C494CC9126F3A5BD9628E79753E6",
- "section_mic_hmac_key": "D3B48E774D5ACDB850D28528416D9082C05293E9D8D3D1899995BCA079813485",
- "section_salt": "8B835CBB4228316A6BB5B90E18A81294"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D40604809AE5414A69F499F9A2084923",
- "aes_key": "43DA76D20A53C5710A6C8F0F23BE369D",
- "data_elements": [
- {
- "contents": "6870D2577C383B1AF270",
- "de_type": 377
- },
- {
- "contents": "807C81B75BE63B70659AE0BF8CF98D",
- "de_type": 468
- }
- ],
- "encoded_section": "569013339274CBE7D243DB20B292B6B966C0D291100030135510DBAFDA8C02CE0B4B744849CC9004EBA03D2B32850AC067301E495DAF062BB6A8F42DD991AC4DB31CAECA481B4EE1C2C26420AE65E5C90E732CFDD1DB56",
- "identity_type": "provisioned",
- "iv": "D2ED05465CCD69AF9831D0BCEE567D33",
- "key_seed": "43F86EBB5F1440944C76F2C1EEC4EA165CD42A18E4DDEED0CA71F3B02545C5A0",
- "metadata_key": "21E1FFA752F642FD002CF75F03582A03",
- "section_mic_hmac_key": "8D6D65F4C2F58AC8158EF41A66B55AAA11748E33D0E7AA767650575CD25707A3",
- "section_salt": "30135510DBAFDA8C02CE0B4B744849CC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "926C1D3213E846D408D5CDE85933B335",
- "aes_key": "9F95537E5023A014C7F72E7CEB7D4464",
- "data_elements": [
- {
- "contents": "57CAAFB0DDACEEFAF44DBA2DED57871F9B515547",
- "de_type": 928
- }
- ],
- "encoded_section": "4E901348A78A9E475F21CCDD2623E5AE795ED6911000A053D3FD557046F3B2EFF163A286FFAD90044495EAA257D8CB317317797423C05C60FA98796BE873025FC53D7E00BBA1DEAFE8836981267613",
- "identity_type": "provisioned",
- "iv": "99D1B79A79B7F1E4847C100368EC5125",
- "key_seed": "43D16F607338CC46B1C8FF4BE147FCB700E0B2511657B6F9FF01DDBC2D3A342A",
- "metadata_key": "D68EA89AD98D6D24E8B7B82AB7536740",
- "section_mic_hmac_key": "32F44768525E151F19138193CDB98D65A034F25E801F6C8F33A82B30FA4D0E73",
- "section_salt": "A053D3FD557046F3B2EFF163A286FFAD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F864FB2EEE7E1ED4DF98C3467E48B8C3",
- "aes_key": "CC29A730AAE43BD7F30415E1A051A488",
- "data_elements": [
- {
- "contents": "C6DC7C08",
- "de_type": 253
- }
- ],
- "encoded_section": "3E90137833ACE50465F931877DB7D7AFB960D7911000D27E59EA9C470CA9F69FFAD69B551F6C90022F92AE5F85FDF07BD21B155FCB131B2E5E9CECEB47E6A4",
- "identity_type": "trusted",
- "iv": "275F908574FBD8A2275047C81C121CD7",
- "key_seed": "D2B7827360775208AF3BB8E7490C3C6D5028FFB96EE975FC5734E38222B9ADDF",
- "metadata_key": "234339063D81600FF7474FF6211ADEDD",
- "section_mic_hmac_key": "7ADB9CA113BCD62008945F73FA7994733668E83A8AB7B9CA91070BBC7815437C",
- "section_salt": "D27E59EA9C470CA9F69FFAD69B551F6C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "09CAA0D1CD15329ADC186D389540E0FB",
- "aes_key": "7FBE39B5E000B0D4D4310F86C0C77257",
- "data_elements": [
- {
- "contents": "CF5A0E6FC4323ED2962E29A32620F94D",
- "de_type": 22
- },
- {
- "contents": "5FA1",
- "de_type": 475
- },
- {
- "contents": "F925E11BAE8107FCA842E3FF3DEDA2B457492AFC00",
- "de_type": 7
- },
- {
- "contents": "2EF99B",
- "de_type": 436
- }
- ],
- "encoded_section": "6B90139ABB3280E93847008026A21A68DD8389911000410866079E5D5895F00BEF4E871EDB07900213C71635A353B960F1FFF8C887A29746EC545860C2F7A2C9E648FDCA182ED91B9898F8040A51988D57DE0072219221CD042F325A0D7F5E3729F2A57A7264137EDA44A505",
- "identity_type": "trusted",
- "iv": "068DAEEF03EA46D6FC6CD92C3380A259",
- "key_seed": "D1FBE8A8B1F0A0CCADF811DA6E544082D29F06086D81D2292B8C6E74D9D5DF1E",
- "metadata_key": "1AFE5CC550D16DE87D2B0FF7E6819703",
- "section_mic_hmac_key": "F1C2416FE95371BDE2A956F01F87E4EE9846559BD49E595E7CF12B94B12112A8",
- "section_salt": "410866079E5D5895F00BEF4E871EDB07"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B52500F5E788EC0D9F202750CAC085F2",
- "aes_key": "AFC28DEB740608CEF6933F762B5DC760",
- "data_elements": [
- {
- "contents": "CC71059E41408063",
- "de_type": 815
- }
- ],
- "encoded_section": "42901380AED3DA4C95EB79F4EE45542D6E0DE4911000E4028B093A498111783EB7DD8699C93D9001A6F9A9F7B35C4BD33BB58A778EE44DED05555AFCEF345B8D569079",
- "identity_type": "private",
- "iv": "23C6574F20E50D4F213492150AC24286",
- "key_seed": "91D3A91830E1799A07EDB05207CEBA50D0028C33A90B491BEC4FDB2125865278",
- "metadata_key": "92C66C8FE82E8DBD7E8BA7674E9C6D62",
- "section_mic_hmac_key": "7CAA4DC585DA1048AA5D8C6E651593F69CE6271C01908D4029BE1AB88225223A",
- "section_salt": "E4028B093A498111783EB7DD8699C93D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F0F4AD67EBA779F535AEDC38D65A50FA",
- "aes_key": "C4D22667103D39080515F16B399C2B1E",
- "data_elements": [
- {
- "contents": "BBCE",
- "de_type": 736
- }
- ],
- "encoded_section": "3C901312715A779B6C3D834913F48E32201929911000317B2985660C6467DEA5DF915C1B01EB9004472D6C62E2DA0443EC06282742414A522F6BB01D1E",
- "identity_type": "provisioned",
- "iv": "D603605B1B5BBC279CB53CB62864755E",
- "key_seed": "72CEC520E533E54D5A1ABE67BE9EDB9D24467FA17223625EC4F9270492D4A112",
- "metadata_key": "1CEA77C0C5AE8B84845B85C7B74019D3",
- "section_mic_hmac_key": "653ADDF62F68AED4759E0C3502FC0DE4B2090880EF84863E28B682064F67C519",
- "section_salt": "317B2985660C6467DEA5DF915C1B01EB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4B6F7D8078261461839557F775072AC7",
- "aes_key": "D33613E0E705E3BAF1AB414E7B8B371A",
- "data_elements": [
- {
- "contents": "4A570A844770D914B0535BCFEFD79151C420E51AA33CA9",
- "de_type": 449
- },
- {
- "contents": "DF",
- "de_type": 488
- },
- {
- "contents": "5AB21ECD1526FB43A2E6414C23C7",
- "de_type": 597
- }
- ],
- "encoded_section": "66901382C6BDC0EF1DBBAA998D10EBEC81B61D911000BEB184901DA4A24184AEE1C55976EF7790015B749B64DF8A580F02266F611E8C8C7D4BDC033D3CE18C4945CD0769FA01B9D6DD8FF07789C44510A075008C8C802ACF280233C71C1ABD3BE2599087F83A62",
- "identity_type": "private",
- "iv": "B9F7A23E2F58C8D71C60140FD2E3BBE7",
- "key_seed": "BA82C25F8A56CAD3684A3F58D67C7A86B4945E30D802589ADEEBD5C3D511C0C4",
- "metadata_key": "F2DCCC3A2933263D82ED2B297E474826",
- "section_mic_hmac_key": "4EE3CFB20981FC63CB453B5E132E5F2288FB721FC1AB883F4E76E6BBBB80C836",
- "section_salt": "BEB184901DA4A24184AEE1C55976EF77"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D8E5FDD20871FD58731256D0CB62C5A2",
- "aes_key": "81F7ACCB7AC20D054E182DF743F2AB1D",
- "data_elements": [
- {
- "contents": "A6E35C990A736F98F18D46BB8B45BF506CDA38175F",
- "de_type": 563
- },
- {
- "contents": "",
- "de_type": 685
- },
- {
- "contents": "874AB6FD2685235570223B8385",
- "de_type": 470
- },
- {
- "contents": "6108D0C9F1B5E5CB8FB07EB6416867AFB020BE19",
- "de_type": 655
- },
- {
- "contents": "6EA64895FF65D99FDB904123E5F27EC2F0E9A97AAEE6B538C49B26F8C473",
- "de_type": 351
- }
- ],
- "encoded_section": "9A90137ADF3C84DEBC92F97B49EA4834A4EBE4911000B1E4987063CEB1317DE77C59EB0EABD8900431D8888C02834CB45FE988BF006D1432BF8DB613C713F2F96ED4D664CFDDABEC4319489E16C0007A21759E65CB769F8C96B83998C249F827B6FD8556000D46CD64428BFB6866834ED512101F88D059230260245D767036C70C233D0AB7C08B551D85419007BDEB71A0B1E33189FACB8C9B9F65",
- "identity_type": "provisioned",
- "iv": "FAB7B8F8457C545C22003AC5688B99A6",
- "key_seed": "D9066D7E1EC8750F01AA286D6C0EDFFED57F08E546D4BCBC37F11E1884D2737F",
- "metadata_key": "2847567D7BB29F859D0A6BC885863F05",
- "section_mic_hmac_key": "A2040734F9568DB02016A4F637352BA3E9170A92EC7320BE2806396ED4827FE9",
- "section_salt": "B1E4987063CEB1317DE77C59EB0EABD8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AFDD41BE6280A05A4A182FDDBD8556BC",
- "aes_key": "1DA3396BF0DDA834C815856E590D10B1",
- "data_elements": [
- {
- "contents": "9B41A639FC2D04D26CC0D9EAEE9D214C127C481DED57FBEC2950852964",
- "de_type": 261
- },
- {
- "contents": "F3E90E9164C65F910F9AFC0D3D91107C46A0A18882A25C6B35",
- "de_type": 797
- },
- {
- "contents": "181DB352E5D07F6195FE073994C661459C171C9F109CBD715ABDEE7D",
- "de_type": 733
- },
- {
- "contents": "53161D8FB05C583C438417F60CD2C593088AE431304F3BEFF1E5B937",
- "de_type": 26
- }
- ],
- "encoded_section": "B0901306299081577F1C9415828166669B1282911000818F17425C86B46D19F4314DC23929F09004EE71DC1AA65D63AA0CD9DE7385172A9753FE6A42CB6EE3A75F4852C60B9081648278D22C0A2E6708BB2E4949086D1EFD6E4CFED85A6405F8B1CAA3C3DD14DF4160D4D590345D89AC83E27AFAB4C16238740466504647BCFEBD3B97DB4E0E94CAA14965A1C1F20C6589C7AA7E0F7B1B22678432254FEC8D79A0029DE579A4F35A1DD424468BD60E00F8",
- "identity_type": "provisioned",
- "iv": "D6C941E5267C2582F6BB2979EDB74CB3",
- "key_seed": "EA39241FCDF3BD8D9C8F1D804A9C415F255924EA22EB3259B9EA106F84CA7A04",
- "metadata_key": "1EB0839E25260819532489218DAF085D",
- "section_mic_hmac_key": "724CC97DB96191B388126C7AD9192181B6DD813C09AC9101073C4189297D7450",
- "section_salt": "818F17425C86B46D19F4314DC23929F0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "08EFA9C40E0A0036570392CD33DB1F45",
- "aes_key": "56C7B28E8595C1A33D39AB4F8B140F29",
- "data_elements": [
- {
- "contents": "C69770",
- "de_type": 273
- },
- {
- "contents": "ABE13AA30EC88530",
- "de_type": 592
- },
- {
- "contents": "D53E9C2881E7EEF2",
- "de_type": 940
- },
- {
- "contents": "A720A74DB9EDEC417C2C55A064353336D8EB0F3AA7B3",
- "de_type": 443
- }
- ],
- "encoded_section": "6C90135C7B1B79CD9BD45F21FB487249C913FE91100003081F0A5D56CC9F2C4A87EADDE0070C9004792D26E35675BF2F6FBC982F307C53936F49AF1AF5D87945942B78A15F8BBCC14021660FC4F8E4B00DAE05757A14C346EF08660F04A2F1BA65FD0E48190779C3C0689BAB3A",
- "identity_type": "provisioned",
- "iv": "61E889286F4D0CEEBBC96D05B3742610",
- "key_seed": "A4AFF6856A7095C4B9DABDB1515C4407FAB5B905D0D58D798BD812842FED8CA8",
- "metadata_key": "9FB8CC22E26477665685F51D727B2E09",
- "section_mic_hmac_key": "1A637F0C06551F322E26314D9642C2DC7ACC72C9DD953A548B0B5F4E4EDB76CC",
- "section_salt": "03081F0A5D56CC9F2C4A87EADDE0070C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "37AC5ACFB5D9A0305EA7BB5CDA443D11",
- "aes_key": "E6D6BDD49482D54AE9C5AB69142256AB",
- "data_elements": [],
- "encoded_section": "37901372E83A536FE8DCE79BBB6DF0FC4095599110008E387F351A94036BFA085A8F6864730A9004464EEE74741C2C2629FE91C5502736DF",
- "identity_type": "provisioned",
- "iv": "B137733181B7AB2C833C606028FB6B22",
- "key_seed": "F6D27F4E02DAC7253E0907998FF49D7A39391439377AB5EBE1F0137C336A85B8",
- "metadata_key": "FA450266B083FBC3EB2C8692E7F5DBA6",
- "section_mic_hmac_key": "DB503A7C3D87F83AA4C66220C24657F84518AF6140D55CCDC1EE611A3C20984C",
- "section_salt": "8E387F351A94036BFA085A8F6864730A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F7E19D646D39679C29404EE3B6A34048",
- "aes_key": "5E08BDDDBAC3331F8D8446C868788EF8",
- "data_elements": [
- {
- "contents": "01F8CE76B237517269F2CDEA51F7B8",
- "de_type": 445
- },
- {
- "contents": "DA9EB0A51417DD89A87E69E1B3116DAB",
- "de_type": 636
- },
- {
- "contents": "9B6FBF25E22A186B2F1367BA94A80D880D647179BC392A4A68B4E4DB90",
- "de_type": 635
- }
- ],
- "encoded_section": "7C901342E89E1476F32CE4BDA127349115775C91100064F1AABAFC1A089A905BC9C5B4AE2854900149E174A599134E70CDACDFF18247C44F80F02090E0AF6DDAD80132F4843EC9FF8CB591D31FAA203E9AFE269A7F76A7E08AA0035AC8359CBC7D74DB6B6612CA9BBC657D9BD9B1F6615050A3D8A690C7AFFAFA67F7EA",
- "identity_type": "private",
- "iv": "1ABCBB904C64337AAB7BED61676CDE36",
- "key_seed": "A004861A769F72CC50175CF18E439570E9ECEC2C784AF1B05B2EC10B40E05901",
- "metadata_key": "8A5B72CB0CD76DFACC878DC16F43896B",
- "section_mic_hmac_key": "6AB27792A42D0A05941D5D1431346BE6B5F245A6F137FF63E8C101CC545C9E0B",
- "section_salt": "64F1AABAFC1A089A905BC9C5B4AE2854"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "034796B51E627F2138D8A4FB86959B34",
- "aes_key": "036A24D477FEE94B8906821BFB6CF3BC",
- "data_elements": [
- {
- "contents": "28DF05F4C663510E51CE9C01EC46117A1C",
- "de_type": 524
- }
- ],
- "encoded_section": "4B9013F9761369F75CFDCC25753E3962A266679110006E553201E38251B2EDC4E36504D7D7BD900185791665A709E7D80D9B1D7C4FF9C51E0A486C6AE1B9C63B0D233D845580067782694D81",
- "identity_type": "private",
- "iv": "2C13274C3949E9003F13C503E031E9B7",
- "key_seed": "88C9ED0E90F51DCA3C12A6AD22F4639B8B8E7C276F98E94164837BD2C45C341C",
- "metadata_key": "DE936A57C9D6BCAF001EC964B6C5EA04",
- "section_mic_hmac_key": "70514EF46B1EE66FF24179E86CADE9551893991E76A99E8D10C70D2297F760E5",
- "section_salt": "6E553201E38251B2EDC4E36504D7D7BD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "46184E36FEF285DC6E4F57A9C01538C2",
- "aes_key": "A200BAF46DC86EE97B8FE5EEDB22CB4A",
- "data_elements": [
- {
- "contents": "632D326CE5387E432410DE871CC167BB760657E21D",
- "de_type": 421
- },
- {
- "contents": "F36E9E2F130BC0254E4799F473D372C3486919",
- "de_type": 130
- },
- {
- "contents": "DEC218926E9C715196096355C86AE17311DC256F49",
- "de_type": 172
- },
- {
- "contents": "06DA3BDE65C616FC1F",
- "de_type": 348
- },
- {
- "contents": "50F9FD",
- "de_type": 319
- }
- ],
- "encoded_section": "8F9013FC2BEC7FB7E301EA360D6B3C0A0FAC6A911000DEF111A18B8FA9C6C326D4054421021090013023A39CD835BB827B0477272151FE970F97748FA2B575EF993BBF6175CAE761A96E3F9FB81C92A9AA6D9B06A19A5C3A88D601D1A67CC00C5E926A7CEB87EF0BAF0FC4F3B8A0925184D187CA130D900364D10122CA3CDBC30A6639B580198D459B88773B50F2EAB0",
- "identity_type": "private",
- "iv": "45EF8ACF1EA3FA8F1E19CBDE20594893",
- "key_seed": "068098719BD63AAB986B7EA1D5881F6963A30AAA9C2E80E40059BAA15F0662FD",
- "metadata_key": "B1D87DB284A2982EAA53C596995FCE88",
- "section_mic_hmac_key": "258571568C4C153AE5597025CD6DC193B300B6A2FEB89A24682E7934414D5DFD",
- "section_salt": "DEF111A18B8FA9C6C326D40544210210"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0DE15B10175F1DFF2628C70D0AED6B46",
- "aes_key": "E90504071197BE226CD357D5E1AFBA84",
- "data_elements": [
- {
- "contents": "A2531C952A42C417BB18C97ABEBF39505DBF6730C079B7D7",
- "de_type": 497
- },
- {
- "contents": "D0F28E7F9B6967A9199BC8B7D02399E87CD4C29995",
- "de_type": 239
- },
- {
- "contents": "",
- "de_type": 210
- },
- {
- "contents": "493816D45767C5A9",
- "de_type": 684
- }
- ],
- "encoded_section": "789013F48A6170B368DC90652516A11336D98F9110001F72FEC00A10F48A24F0BDC9E209A86090016DE45596DDD682BDB0CB6D432842C6653E61E074800DB1AD134A2D06A0F9EA32A67D3A000C3CCF76E2F12D59EC4C570A1796ED6DACA5428E45C9A071BB382DC283D4E67F77D5624D4F8DF9C8192ED8967C",
- "identity_type": "private",
- "iv": "628959806C6FD40FB815F90B8E383C92",
- "key_seed": "38B809FA67BF591F2FC3ED5E89FF69196E8CEDBB2C70A5C4214FFDF0C6720A89",
- "metadata_key": "683AAC0A90779BD7E8E6102C59C33CFF",
- "section_mic_hmac_key": "9F76A1AFC8EC596D5C12E7B2703DAAB5C2147A3F152CEDD5569C004568545419",
- "section_salt": "1F72FEC00A10F48A24F0BDC9E209A860"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A66D131470862B0A800CF36CCAF21F9B",
- "aes_key": "A4E365EA6FC7E436B0803863A359E74F",
- "data_elements": [
- {
- "contents": "37F6CB293369D0AE08C0CF498F725063BC941429D4748D88C1F5A8",
- "de_type": 440
- }
- ],
- "encoded_section": "559013340F4D1F8D98CCC159758FEFFCA24CB99110001549A78B42DC99D25E0FA7D7DAB336E0900461A9ADB4F53BC3EA94A61A8C9486F83C5A94D311D481D1E1C4B98FADD358CEF1E8C9E48997577EE881358BF6C720",
- "identity_type": "provisioned",
- "iv": "2E46CC58F90B1F259763DF87D28CFB5B",
- "key_seed": "866216209CC3BA31A0CD00FE866C661906FD82FFFA1AF1FDDFE05CB3FE5D160E",
- "metadata_key": "6E43E73A2F75C729FFC5EE5FFBD37BE0",
- "section_mic_hmac_key": "386FC2463C51822E0D2E18CF7A0CBCA1A2259F0F97DBD49AF0CF76A070BDC5E1",
- "section_salt": "1549A78B42DC99D25E0FA7D7DAB336E0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DDDF41B6ADF98A34F574AD71850DE058",
- "aes_key": "B737AA1DDDF85031F002DBE5C45F3E20",
- "data_elements": [],
- "encoded_section": "3790135EA759302F33AEF062217EBF5A4B65E99110009BFAE224D28BDDB0C9CC5D46415FC3A09001084F44EB87F5634E839BEE652E071D6C",
- "identity_type": "private",
- "iv": "10C16D86C9E0BE1F6347112C21D5FB8E",
- "key_seed": "E6582A2C793283D86BE936BC765C9EB0512329DA8952DA2D43DC010F82ABDE73",
- "metadata_key": "860157134E0A0D7293D61B43F2587D9B",
- "section_mic_hmac_key": "2506BB15AF3D9F480145093EFCC12190B38AF4BF2645C2120B4BD2CDE4F40C28",
- "section_salt": "9BFAE224D28BDDB0C9CC5D46415FC3A0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "628478EA2295D16F6B27D99F0A27D544",
- "aes_key": "78D9C68A8B7E0EA68509955971559804",
- "data_elements": [
- {
- "contents": "4933BDAFCB68075E6CC5A5423F4C",
- "de_type": 795
- }
- ],
- "encoded_section": "48901379A1BB27F73791D000D5228DF7C135D991100081BA33E21FE4ABED1A04C9D95BC2D6B49001FEFD2CC7172F6DA36547950D23EFD1F9B487B44DF40F4E3EC3F0DB2C10C86272AD",
- "identity_type": "private",
- "iv": "93505D7F5898E41D69F7EA457DE34D54",
- "key_seed": "0C8434F9786244C9AC393011DF523CDCBF30DD322487316CA06424819AD2BC67",
- "metadata_key": "2129E9F8F1D9A4599073E55B273AE84F",
- "section_mic_hmac_key": "1F04FFA93D7247CD23DAD80C54D3A02C0F6805F05D593A7F1969729E2B66E149",
- "section_salt": "81BA33E21FE4ABED1A04C9D95BC2D6B4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6636A8179A7539B6C145AB036ABC61DB",
- "aes_key": "52871CCD3C531DB8ED5E0CD2B9408382",
- "data_elements": [
- {
- "contents": "4AF0AB96E0D92C99E994BFCE92BE3294658B36",
- "de_type": 653
- },
- {
- "contents": "4950FA0E9C1DD840913D09DFC7801DD66057D63E42B231E7",
- "de_type": 35
- }
- ],
- "encoded_section": "6790138403EE19A982413945659E727142CBDA91100060ADDDBBA5581E0492927FEDA1839F849001858A8DB882908AB6E59B43DD60DD864E39280BADE1F2263C2BFDB26294F6DD996C7EC2DBB9966A9E022C78D8B31C8A94D77E708F405B40AD605E35EAA7AD2B6B",
- "identity_type": "private",
- "iv": "6FCFFA1DD673BD46A33DCAD5D78A0818",
- "key_seed": "435D4CFBFD90B09EB4FCB8618F4F3126B3941B90CC7781365ACA74B7C2419339",
- "metadata_key": "720D20F73E7ED7BD2CFA70320D90CB4E",
- "section_mic_hmac_key": "22C29F385E3F714233A8934D6D44C0F3F1FF950C26AF4786B49A3EC81A71C98A",
- "section_salt": "60ADDDBBA5581E0492927FEDA1839F84"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C19D8AFBE64F931379D7EBF939CC24A1",
- "aes_key": "9EFA45E698A339160EA80DF0ECF36499",
- "data_elements": [],
- "encoded_section": "379013B9692752CF3F41AAC03CA730A6AFC85C91100061DD84CFC18E2CBBBAB60CEB86ABE6D690013AAD9F2BF775CB780D9D8E13858974E0",
- "identity_type": "private",
- "iv": "BEB8CB30E6ADB86DEA9E572D0583A578",
- "key_seed": "27A648DE4BFFF66325913B794954218B87ED3D79662BE80BC4AA978B26878ECC",
- "metadata_key": "5DBFC0AE842BFC1347055279953E9BC6",
- "section_mic_hmac_key": "9DF3EB07A1D92235053FE039F478DD9CB6A554F79CCE713C5C813019099ACE9E",
- "section_salt": "61DD84CFC18E2CBBBAB60CEB86ABE6D6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7466F38050B9EEB5A0B483CB30465DC9",
- "aes_key": "EEB41F887877D842CC4EAAA67F83610E",
- "data_elements": [
- {
- "contents": "5E96DC1DBC05740A894EDA",
- "de_type": 560
- }
- ],
- "encoded_section": "459013D0902F2AB5972B41BC0ACAD9B2261DB6911000E35AA601D5935057BFCF03242D9BBA329001F2F956F617516A1DAA125A88C54E29A596932F5579E7D6D834E3B879E6AE",
- "identity_type": "private",
- "iv": "77EEB2974146266D349B9088200A5905",
- "key_seed": "92B2AE2BE975A24FDA5C81265161B32E9C3AB9766B0DC2D0B30A4FFF8B996572",
- "metadata_key": "3A4EE38FEE87B6F7B68270402F9E3958",
- "section_mic_hmac_key": "2E0ACBD90AA030C11B3784BC17D59DE09E11094317E45FFA4169516A3DBE7C49",
- "section_salt": "E35AA601D5935057BFCF03242D9BBA32"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8122FF813F37EEFC5DDF551646A94693",
- "aes_key": "788ADD1E00191939A9782119A5E2094B",
- "data_elements": [
- {
- "contents": "710E0E6A6762C48EB92508787416BFCA6F",
- "de_type": 714
- },
- {
- "contents": "24C9CC8AA0E42CD275",
- "de_type": 396
- },
- {
- "contents": "29867AE4823526C2E11B419C62",
- "de_type": 632
- },
- {
- "contents": "6E5B1B035D83BA417C8ED1FFD0571C24F4C0E9EAB9342F852FDA",
- "de_type": 596
- },
- {
- "contents": "1A515A8766EF2E",
- "de_type": 702
- }
- ],
- "encoded_section": "8E90131E8C489B1336454D3128B130C4134236911000F46F979A1B7FD0A2A5C73E3243A8FAA6900483E4723D8227881FF2C1F5945F3C894A7772752A61B67F9B5735667C9C1B06665CDA3BAF634A498B9B5F401D0DE765E0C3C6A51755C948CC3C196A7B4C79CBC2F95A4D968B060E08FD8170F96B8C13E48FD125BB6080672950A8359D6F1CC7DDA17A3642F19C54",
- "identity_type": "provisioned",
- "iv": "D27F64127716122FCD1CAA9208F77EE9",
- "key_seed": "BDB0A9567EBF4EA0C328570726D21525495553082AA9CDA9E5D64AF80F45E64E",
- "metadata_key": "65504F6C8B7E976ACE5E952FC5FED4BD",
- "section_mic_hmac_key": "B6593C39E6D71521EBC7CF3AFD16E1E6C949CCFE6C94139B93213D443C4A7A95",
- "section_salt": "F46F979A1B7FD0A2A5C73E3243A8FAA6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "307E6BFCF6A782B991CC2A749B09636C",
- "aes_key": "6DBEAF71EE0D2A9DA8AC1029F2DC4345",
- "data_elements": [
- {
- "contents": "CEB40AC198172437DE1BB258C1FA08291A70B949500E30BF",
- "de_type": 199
- },
- {
- "contents": "7CEA871566BD69B35E3A775D9DD09AFD0B",
- "de_type": 458
- },
- {
- "contents": "FF2D5A9236A40ABEDA2FD0847FFA45532475",
- "de_type": 957
- }
- ],
- "encoded_section": "7B9013ADEE4B07E8BCBF39E2EE45BCB9936BA4911000866FF3E8F11D08BB28FC9A2164C3452490020D0C51AC4563D2DC3CB268190F86800DD0CE78B2F4F0133A4F91C1A4487E068364F8FE0F99246BCC25632D849D0FE3E736800381E2344F29D37AA35301B9F0BFD37E8C41DA3F53748103C55EBB0C4948C5EF306F",
- "identity_type": "trusted",
- "iv": "59BDFB301F008CC7E84C962512E1210A",
- "key_seed": "F37001F68E3C17DA62CB445F3BC5FBBE1B0830EC43DD07D578A4E4AB93A97BF9",
- "metadata_key": "B18E09134D29AC36E182306B8E741109",
- "section_mic_hmac_key": "EEF9ED52B0AB9B2B9B98E4BC115730A79D864479BF14ECDF01F8A22AD23C4EE3",
- "section_salt": "866FF3E8F11D08BB28FC9A2164C34524"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BFCF368DFA6337A5BA78CF4B60B08E3A",
- "aes_key": "7B27B37D2C56F0B288D61271E9F697A5",
- "data_elements": [
- {
- "contents": "AD849E",
- "de_type": 717
- },
- {
- "contents": "F58E9B4BF3EB58DC7F",
- "de_type": 556
- },
- {
- "contents": "34AB62E364A56D0517E902AF49",
- "de_type": 839
- },
- {
- "contents": "885B928824E57AD5D4FD8A70A59A78",
- "de_type": 483
- },
- {
- "contents": "03EA0136C4685295DA9A77EDE4A8C1E9EDF7871B",
- "de_type": 671
- }
- ],
- "encoded_section": "829013B346FEBBCF63B0EAB3803D13636BA71391100071DB218D918D828C92E0204CFF4B611E90019CFF0B8A1B3FE54FE239B42BC4796958C108B1C88A768B734BBE536CFC6610873D309DC76A67AC9E17767D6190361A3F6C2CF17B58FF16A9FDC2C500A183F07FBF578CE7A0308800E9B98EE9D42405320EEE6B6016B0B05C96E6C8",
- "identity_type": "private",
- "iv": "C53DB4F70A67DE7DF7307CA6171F3BD2",
- "key_seed": "5E2B18C1833B41338025453418B8B8395C11EFE691C8EA7E763AD464DA64EB76",
- "metadata_key": "B23210152FEECCD9598793E38B2CEDDB",
- "section_mic_hmac_key": "EA04B6A0DC8DF1B4703A0F3C1B2CB76FE339295CBC5C34ED626D8CA9998EE78F",
- "section_salt": "71DB218D918D828C92E0204CFF4B611E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DED5FE514596D4F6FDC651F4401A1285",
- "aes_key": "21350A13179CD8E8DE946AF344533A28",
- "data_elements": [
- {
- "contents": "7D4DBE88BB3F4D56AD861F",
- "de_type": 73
- },
- {
- "contents": "F95B18F59E",
- "de_type": 982
- },
- {
- "contents": "02D2A88797C6763C73BE592A2AA8C4B9236F9D",
- "de_type": 832
- },
- {
- "contents": "6AF8E9C04E1C42",
- "de_type": 91
- },
- {
- "contents": "111046E7",
- "de_type": 187
- }
- ],
- "encoded_section": "729013E6D0C9F2B312B4FBC87905D44CD5E75A911000B55AD57B5E62C64382DF184E318BFE5690013F8096D9AA8FE721FED8E1732C0CA8A385307A136AEC083D2C1D73EA7113137B23A3B2B001EA0724492396E0282A267BE561B1528F994AEC04DA56119BD003808B010FD2F692A3801C03B1",
- "identity_type": "private",
- "iv": "D4C3B01CA68065A08589F17A43EF28F5",
- "key_seed": "4FF752A463D1E2C0D678C24320449F18FCD0746909FCE6FDC1B516D72A7C1CC9",
- "metadata_key": "7388750D8003EE00CC5F84E1409B12F4",
- "section_mic_hmac_key": "939E08A95A08847810EE6BE0708474DCF4404FDE883B6378CAB938B76E8BD12D",
- "section_salt": "B55AD57B5E62C64382DF184E318BFE56"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CD9E10B9F020174B29E5AD90E0E7084F",
- "aes_key": "141D0AECF29D4ABE5B4D665284700976",
- "data_elements": [],
- "encoded_section": "37901351EBC383C07087BF0D7C785964C144CC911000E40E382B6E96BD40764C5F0D5415D0279002D1951D7B47B5F5853EC55EDA09251A97",
- "identity_type": "trusted",
- "iv": "6D1D36994AB7C4A0EDF441816A844237",
- "key_seed": "247D236C67F1F56D1ACD8817170F45C500530BB9D122900272CC2E8A30A89359",
- "metadata_key": "39B3703CC7908B83CF3B53A3238565EA",
- "section_mic_hmac_key": "21EB0469854E8E7DB1904AA28BDAD5869B325E8E6B116E216B327A0DF9B70DF7",
- "section_salt": "E40E382B6E96BD40764C5F0D5415D027"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "03A133AE87140BE18A3EB46B94941E52",
- "aes_key": "9589F697EB5E5F3D2C1683B41215C4FA",
- "data_elements": [
- {
- "contents": "FFA5C5",
- "de_type": 787
- },
- {
- "contents": "30EC973D18D69C314A4DB86B47B73786D996EE5BDD1EFD7056",
- "de_type": 739
- },
- {
- "contents": "97D8216B95BC62D8B6A24918CF8F0B6EF86BA3189A0D3A75CA4CE0EC8BFE",
- "de_type": 704
- }
- ],
- "encoded_section": "7A9013CA7679919FE47E62BD141812222962C9911000538B7CD44D330EDE7EB3810E2976BE3B9004B8F73A0634838BA4090A034F8AF96FF12A174C058DD82300D11D28D86109FD09F788CAB9E55D989073D594FAAFA7AE3D67456CB956D78996FEF9D0B9519D60BF25B383AA1559495B7EFD3D903BE11F816659DD",
- "identity_type": "provisioned",
- "iv": "2CF79EA2D302D0652647EE01347F48C9",
- "key_seed": "C9BC1C391B0EFCFCD4B29D9C159DF75D040C4383251F2918B5675A149A6413B9",
- "metadata_key": "74C107B8323774F37E4E2A54503915F6",
- "section_mic_hmac_key": "E52B5B1FB65F064CAA5F7602FD57755AF4E2615FB78019B51541FB7EECF535BE",
- "section_salt": "538B7CD44D330EDE7EB3810E2976BE3B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3AE4359592BF7F201084BB24660C771C",
- "aes_key": "B8773C17826A4385B9284B3589766262",
- "data_elements": [
- {
- "contents": "DC71AAC54ECB1B47647F31E69C394FC4AED39298C6",
- "de_type": 62
- },
- {
- "contents": "EC2D",
- "de_type": 37
- },
- {
- "contents": "C79A5EDAA0A03DBC18678509",
- "de_type": 107
- },
- {
- "contents": "74F8",
- "de_type": 677
- },
- {
- "contents": "1E3926BA0B",
- "de_type": 957
- }
- ],
- "encoded_section": "6D9013E5E33AAF3D46ECD6E7ACDC59462B6BD491100016C31481FBDA8F5298370904482F6B0D9002CECC579F805F85B4FDF7CD77CAAFFC9F702C00F4EAFDBDD6A7B88A6F41CC4D299135CE06E2A1F852818F6E08D69AF50CE298BE2F506FEBFBE601E97F17A324501BBBBEDEEAE8",
- "identity_type": "trusted",
- "iv": "6142669F10695320E11C7EA40B354D1F",
- "key_seed": "32A9BAE8DE4585B275D88FB2E96D02B59BF865964276A9C6C3E847953AAE090F",
- "metadata_key": "23347E850700388424B419DBDBCAC33C",
- "section_mic_hmac_key": "3F2036BBAAE4896B8DD2D61A0F698D61613B4BE0B4F19660B6BEB71294B46817",
- "section_salt": "16C31481FBDA8F5298370904482F6B0D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6D656A4E2FC03D80DC3B6513FA2F6F99",
- "aes_key": "9E24A3900D6E56EACAF9A3F141FC042D",
- "data_elements": [
- {
- "contents": "DA8064399B756E",
- "de_type": 292
- },
- {
- "contents": "ACA505B2F1",
- "de_type": 97
- },
- {
- "contents": "00E6055661B70886AD75E59AB2D35846",
- "de_type": 461
- }
- ],
- "encoded_section": "5B90137BA9E7F1BF772CEF94B3DDE2E8F230E7911000FE36015D37F6E2747DD1786609B9805790013F0F6B3758EA34EDDF61606E0A6FF7E98129DDFAC299DD07D45094A490496F3C4C479C0DDE225303DE62051B03CD6E59080B259C",
- "identity_type": "private",
- "iv": "F48F5053B7CBB0D2278CE266444D173A",
- "key_seed": "3A0DDABFB9F1B1289651514C2F2BFA4E5907BFB05A34320064EF1D3DEC357CC2",
- "metadata_key": "3A2FD2BE39A37010435F2EC8567BAA0B",
- "section_mic_hmac_key": "9EF5C5CFFE0C3EEC958D358164165AFAF42350E0A7E930A8D6052C334BF4C3F2",
- "section_salt": "FE36015D37F6E2747DD1786609B98057"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "980AFFFE379C22B79DE841EDCECEED5E",
- "aes_key": "CA4B0DE90665264505C4CD89237FC2BF",
- "data_elements": [
- {
- "contents": "C871A9B1",
- "de_type": 695
- },
- {
- "contents": "4F174A736E938697E7A4EE944DE19CD2921EFC1456CE9A5E48EDC9A058",
- "de_type": 921
- },
- {
- "contents": "8451A82242DCD1E5E990A47E2B710B",
- "de_type": 792
- },
- {
- "contents": "ED",
- "de_type": 822
- }
- ],
- "encoded_section": "749013335E6ED7B39E6DAC22789B547DE11CEB911000A11F350D23470D8D6714C4C5025E7ED690045992C6A6AB032F0743FB9C5C76DA9D27BE1B7896DA8473DA5305E1EDEBA7FF83B153DEE304349FBE73B34E47291F64350A2A8CF88250291CBEE24A62FEE68799E245C09AC54A1C01314CBE10AD",
- "identity_type": "provisioned",
- "iv": "FBF7F6587930B12B75185D427824D820",
- "key_seed": "01AFED11D971E1477C49247EFA03A233971ED579A3D54BD6EA1F735E1DACFA69",
- "metadata_key": "06878DE1EAF8F6CECDF30CFB61C4A20F",
- "section_mic_hmac_key": "57B4D6F98948B6EADF732619716977F377438B038ED51BBBE9DEA245F660A799",
- "section_salt": "A11F350D23470D8D6714C4C5025E7ED6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "142D92DF381FB02ADA5BFBBDB3194225",
- "aes_key": "EF29932C9885D543FFEC36215E5C7D8C",
- "data_elements": [],
- "encoded_section": "37901306A47A102A3519418B25A673A5F52904911000297D7D672519392F14F37525A0A77E1E9002C478C7D3D651D54D047F7D8DA3EEA47F",
- "identity_type": "trusted",
- "iv": "753CC945341DCF47B1AC1615D664131E",
- "key_seed": "C7F29427E4BDF07FFB51959101758A7034EA2A2E3441E719DFC10633AA1532E8",
- "metadata_key": "F5CB77F80D986B392A01A036D807050E",
- "section_mic_hmac_key": "39F6B1ADF27329472F39BCAEA60B1A75B68C8CF921FE68DE7A0CB5280A0A7565",
- "section_salt": "297D7D672519392F14F37525A0A77E1E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9CED41C417A0C7A7D1A660CDAD238B3C",
- "aes_key": "1B214359E8F6A0A67001E9763902678C",
- "data_elements": [
- {
- "contents": "33",
- "de_type": 916
- },
- {
- "contents": "33D198321B338170A869F5085BB5C78B0551E2A5223599B1A684",
- "de_type": 423
- },
- {
- "contents": "46C92249B50D",
- "de_type": 801
- }
- ],
- "encoded_section": "619013CD128065A30C39221D969E1F403884AD91100045A40C690EB4CE8A31994874C36EE462900281E30F108565FFA512ED054F474331ADD12B4F12F9C772B5951C86183268ABC15B171D58A35B3491EF58AB10CAAB690F816686CC6EA03EA6BF55",
- "identity_type": "trusted",
- "iv": "9D7191BB69D4CFEFA0C02406AEE9DA24",
- "key_seed": "2E54E9BEE7263BEDEF24DF26B14D0568D3122209AC5242CB266E7AC650B82FE5",
- "metadata_key": "55A4DC9840046632FCF02F5A3D8A21FD",
- "section_mic_hmac_key": "7AB0218829879A7518E725ADDC26869198DF9A790D6F59E1A813B8F0E0D83747",
- "section_salt": "45A40C690EB4CE8A31994874C36EE462"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D9EA401291CA51C522CAB05537839268",
- "aes_key": "2A29ABFD0A8B0B9DBBD433BC6FBF2694",
- "data_elements": [
- {
- "contents": "D65B4F2CD54532FF49DCF70BAE60834255889E4C0B84EA00A597",
- "de_type": 897
- },
- {
- "contents": "",
- "de_type": 672
- },
- {
- "contents": "4381B746F456521012706DABA9E514",
- "de_type": 247
- }
- ],
- "encoded_section": "6990132DF63F223549475A6E9136749C83E4AA911000384273880FCA6E5CC28BEBDE3F02D7009001D4155F568EB768FDB8983007689B9F0BDC070243F3C1397F7DB5D70A2EDB97A39DFEE8D55A8AA282A599849FEC4AF90A61A54A01D407DA6CF9AA89C8492164483C13",
- "identity_type": "private",
- "iv": "9FCE9E12716169DABB86DDC631CEBBC5",
- "key_seed": "D12E1DB0961229C72F7A1F9FD2E03A575B304EB3CBC77D6787D2A00D76348A29",
- "metadata_key": "39437BD0EDF1F0AE69E6C168EC28910B",
- "section_mic_hmac_key": "3FB5E39551A2434E164547A99C8572C213DEDAA602680E7573453FAF22C2D892",
- "section_salt": "384273880FCA6E5CC28BEBDE3F02D700"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "52E5DC1D919E92A17EC425D120EE446B",
- "aes_key": "1070D36A68639C052708BDD149C76B0D",
- "data_elements": [
- {
- "contents": "0691E0D075CE0152FAA8BC5ECE77F1FD8715A0",
- "de_type": 193
- },
- {
- "contents": "6748926F6E2859A23BC42442C9A67286DE92581E8CB6C438C934522AC6D5",
- "de_type": 452
- },
- {
- "contents": "C05DC7EAE1890C046D11C3A09F",
- "de_type": 18
- },
- {
- "contents": "750A482F94219F642DAE0BB5731CBC8D429831078788BD23C97ABE9C",
- "de_type": 410
- },
- {
- "contents": "50C92B13EFB267255543274EF78B39E26E13C4B4F41CB9FC0C5132F1",
- "de_type": 947
- }
- ],
- "encoded_section": "BB901336682108499C15E3C9A3E960E1F0BA779110002BC1ED01E66270117CAA0CD05F05809890046D989D2205B8E302C5466A2316960D9A353C986CC3CEC221D254C1CF319898253B6EFEE1C58519F6DE75054473AD0B52AA87A8B589505B46AA814B222ECCBC43B52461DEF067D9A1D5BC34AFC835B04268E040DCCD08BDF7ED3B752D5CBB69C098DD782514EA0D4B085BFCFEC4A6DE1004304986AB4CCFA7ACE721070AAB913E3A1570A80638905137012669EDA49034BC143CA2",
- "identity_type": "provisioned",
- "iv": "638C93531115E6D017707DE649B22BFD",
- "key_seed": "6114574A94E6D39027823764C6CEFFBC698CF543C7FFDD43E649CC447A84C1C4",
- "metadata_key": "B27C10EBBE24E783576D83E48C9318EF",
- "section_mic_hmac_key": "912A9018303053335B666556024E27E0DED70D189846A2FD0946DBCE9C5DF1B5",
- "section_salt": "2BC1ED01E66270117CAA0CD05F058098"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8E7A8AD9FEB5AD035C6915F3978DCD52",
- "aes_key": "4CD663AC711C40F5E58CCBBB5612D69F",
- "data_elements": [
- {
- "contents": "1733D5DE",
- "de_type": 202
- },
- {
- "contents": "6F7CDC83033D",
- "de_type": 849
- },
- {
- "contents": "5CDC08111E0B1D094075ABCF883D89DA6E193CC7781A30",
- "de_type": 291
- },
- {
- "contents": "78",
- "de_type": 295
- }
- ],
- "encoded_section": "6590133E0D7409282A63D00B1043F3FDBC8962911000B9E781A89DC0DC26E307F2DB5AE84E859002079E2F53C842642D1766655B3CD0F95B8EEF98FBFEE2B6551EEDDD58AEFF4EEE8B1184BE4DD778D241C7D19A23F45F33B182D6F2E3D4B214189BDC3E07E9",
- "identity_type": "trusted",
- "iv": "AAFB4982D1299671CBA1E5169690CDCE",
- "key_seed": "1C0AA7DE5CE402F06C25EBEBFA297A7B8CCD03AE2747C549ACD657BC10A6617B",
- "metadata_key": "4F8EE08FF29009BACF5DF132DFD9FAC7",
- "section_mic_hmac_key": "57457810563B685ED78C42BAA44DFA37C84037B6D733079E5BF408BF8DAA63F4",
- "section_salt": "B9E781A89DC0DC26E307F2DB5AE84E85"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F368D766AD577D0FA2BA4EAD2AA71F16",
- "aes_key": "1ACB9732F1E49D43B9F2F6DE5F9EA426",
- "data_elements": [
- {
- "contents": "AED88C9593D7026A7E5FBD645A6CC0",
- "de_type": 756
- },
- {
- "contents": "29366161EA3148D44306A03FD2B1B9B64C9D54BE45AD",
- "de_type": 966
- }
- ],
- "encoded_section": "6290131DDD462C802488F8FCB53337F0E295B5911000F6FCA1B3F6B059B23F66D8C4EA051C6C9002C816881A036092A98D6E2C43B56997B3418206577AE5FBD2ED140513DB563765F8BC8F24373A34598CE965F612E6973213F68D8725BF8687E7C0E0",
- "identity_type": "trusted",
- "iv": "AA80F0C2853387D57352DA38D31DE2C6",
- "key_seed": "F191675B85BE363A41115825E9F96AE944B1BB30A4F44B5BF264607F23ED1D03",
- "metadata_key": "1463A91940AA85E20E4C102FB214B062",
- "section_mic_hmac_key": "7448C6F70050A2F6807F37A50CE846D85570164633904F6988DBCDEE309BA469",
- "section_salt": "F6FCA1B3F6B059B23F66D8C4EA051C6C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A8F73F308C8040F875068751AC07146F",
- "aes_key": "4ACCA77F6443A997EC976E8DF29BF045",
- "data_elements": [
- {
- "contents": "B4206451A977B5C7229B3706C7A9ADB5F1A2",
- "de_type": 397
- },
- {
- "contents": "56357AB9D8F59AC35C31B4A33719",
- "de_type": 768
- },
- {
- "contents": "E4E7555166",
- "de_type": 650
- }
- ],
- "encoded_section": "6590139B75C6E2F93374031891CB7F183D1DA5911000ACB22E5B30D0DBBAF07D77E81CF008949002CB361E9901B9D970AAF01C9C930078BB28E92B29E27979BCC204CC7E57B37D2A092B33A50FB2F58E104AF02590F8F81AD33F181D7E85F6CCD8E6D65D4414",
- "identity_type": "trusted",
- "iv": "784701EF2AE2B9C7B1656B6F24958EC8",
- "key_seed": "A7FD06108A6EC755ACAEC565266DA3FEC76F5CF8AEC4F29279FA144BCA3FD6DA",
- "metadata_key": "E09B7C55C7B8349092D91225F448EA53",
- "section_mic_hmac_key": "6ED015FC8D0B189DC70E4BD1E8F88E688F25A796E6746035FF22D0554F821365",
- "section_salt": "ACB22E5B30D0DBBAF07D77E81CF00894"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E576698436DEB6610A845CF01D163105",
- "aes_key": "83226FF4A58EC6DD7E6662BBA5D73F52",
- "data_elements": [
- {
- "contents": "BE5023",
- "de_type": 476
- },
- {
- "contents": "7EE00AC9BEBFC7C3C7D4CCE6F44E",
- "de_type": 426
- },
- {
- "contents": "71EF3EEFC6E87B1B92",
- "de_type": 192
- }
- ],
- "encoded_section": "5A9013F92DE8DEABABF71EDBEE8EB0BCDAADFA9110001D54B5EA6F822E53B05665A0162703EA9002AB621DAC7D9F5733D7BA7EE8934A3ED4C31CD45C0D582B0A5F7CAF5E87CF7CDE253F4CAF4DF1441BB1A46B43C45D688A870AB0",
- "identity_type": "trusted",
- "iv": "C2400D4299944D6C1488DCF1E22D6C06",
- "key_seed": "79D29D153C585EA5E90C3B79529B16FFDAB71BC5A04AF937E790545AE9928DA0",
- "metadata_key": "5D7452C2BA345F191BF6AE6FDF6C563E",
- "section_mic_hmac_key": "79900D2FE4048CA7833B859F37FBDCC0B15F7171C80DBA0B1885285696975A1E",
- "section_salt": "1D54B5EA6F822E53B05665A0162703EA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4768B89F8A7E384991F18A0495BFEA04",
- "aes_key": "7547BC2888B8E5542CEE7A3F3C5222AF",
- "data_elements": [
- {
- "contents": "E3A9",
- "de_type": 870
- },
- {
- "contents": "3BE13855A3139F39614D0FDD428930B89082B2432BC9446EA11C",
- "de_type": 8
- },
- {
- "contents": "93147F162D3D03E6B280D73646F2F2DE8550F029E4A0475EBEFC1D61",
- "de_type": 47
- },
- {
- "contents": "D4C4C08E4626E9C9938060448D2DF71E5923",
- "de_type": 203
- },
- {
- "contents": "2C955691391A",
- "de_type": 984
- }
- ],
- "encoded_section": "949013BED9D332000D6028E9BE7FF8D5D9662991100026BF874FD30958064B7FDE50DC5273249002EF9D3A6DB0E2E9F377CA7ADE125F20C814A7314F4DB049E59DFCF842AC9C3A0CDE83E86BE477EC0945CD68D713C355886BF6EBFD0B4ED3E1F130059F0D536690144269E0E575CD11ACBF81624828907DCDF86CA826D7CBF3311FE1201C677DBF3ADD1ABDBAF3F6B3435A5D6EAB",
- "identity_type": "trusted",
- "iv": "8A114B142A29B0A8FBEC8D802FCC9565",
- "key_seed": "7D5D6E5B68DF9E882D754A65671ABD44CE108669284BD684CCF6CEF2C2EF0FB4",
- "metadata_key": "9D8B48CDBE1FF6BB72F17A12043F41E5",
- "section_mic_hmac_key": "8D6A740A35A73FE7F878D2921B3D960BAF0A3486AC0C9A8819E424B1F030AC3A",
- "section_salt": "26BF874FD30958064B7FDE50DC527324"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F28906CA902C635D308F902E45DD2E48",
- "aes_key": "8706D4875D9BEFE21A3804E22B9ED548",
- "data_elements": [
- {
- "contents": "A84365F157E64CB62F",
- "de_type": 509
- },
- {
- "contents": "00B4A0D8FDB5521E004F7C38139C984657",
- "de_type": 628
- },
- {
- "contents": "8030144ED75B3228FDA5437A5B278EBEB81FEE8F9BFADD2D",
- "de_type": 343
- },
- {
- "contents": "F533F70043C57E4A829DDE726DAEF9DD7D19",
- "de_type": 397
- }
- ],
- "encoded_section": "879013829B3FB9CEEFC0DF72E63F15AEF50421911000F4F886D3942FF01D3363FADE908CBA20900179CCD98A4373FE7DFDD4B86DAB02F51D3B9E496075E671296CAFBC5F734874DCC4392FE89EB640208C8190D0BA0DC376190FBC329D495D4C8AFA2F6743C88947A5F618F7F5B938D389734CEAC2D74DE84FB58B2F1DC8557F53A0191F9C0F7767",
- "identity_type": "private",
- "iv": "D91919E5DA29C49D3A27EB7004C3A3A2",
- "key_seed": "8EAF75EBA0A679B7FC0745B9A3A151467037141B8960B3CFD153873489ADE1D6",
- "metadata_key": "F8B965AEF3130CB5B1EDF79BD3B380DD",
- "section_mic_hmac_key": "CDDF228D36AB57418939E4B225AD5E940A66099B1673E9C72617C817EC65FD85",
- "section_salt": "F4F886D3942FF01D3363FADE908CBA20"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F07F58FCDFDB03D86254EF18C7ED9F5A",
- "aes_key": "212FBB8DB7A61540976A129092DDC6A3",
- "data_elements": [
- {
- "contents": "507444EB19C5A2F5AB0408A7B1C9FB6B722485864B7FED",
- "de_type": 517
- },
- {
- "contents": "340127475FEF88C37C16738A27767280A60265E9ED7C00F7",
- "de_type": 419
- },
- {
- "contents": "459F7AB3EC821FF2FC5E3271D76CD4B927C7DE9283DA3D1F58B6",
- "de_type": 907
- }
- ],
- "encoded_section": "899013359EADDA79D6D36D643040E2F246FF5691100088BDA9DB826E3AF39A28BD3DA6D11DCE900162FB285CFC9832A941DA01960F1D23CF4C3B6B16D419D9128C57D4791005DB0CEB59681013CAFB837D214C1B0254DEC08CEEA521C4B63E0691E22197BFB77A63E5B404A6C59A5C8106C03C9E64555264AF6995235AFCB618796984136391294C9908",
- "identity_type": "private",
- "iv": "5AF941CA9794322BC9567FDCEA50EE5F",
- "key_seed": "063078D957BA49F5766C90098FACE0A30FA35A51E25EDFAA85A718A10C3E7DEF",
- "metadata_key": "C92F572CCC40BBDF3908F3E0463113FE",
- "section_mic_hmac_key": "893438116FE775A831B08322B6A69563A8CCB89BF0D0E1B072F9938B2F1E53E6",
- "section_salt": "88BDA9DB826E3AF39A28BD3DA6D11DCE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A3DEF8B9B61DEC75C9D78AD7D305A942",
- "aes_key": "B88BB7EAAD96923279AD8895FDED98F3",
- "data_elements": [
- {
- "contents": "2BF8EB8F1B59A8A6BA8411C989B45CE02489926496131DD2A1",
- "de_type": 620
- }
- ],
- "encoded_section": "5390137966542D2D7E1BB1B1CC4A69D4611B2B911000E895C370737AED915CE90F8886219DC490023E6EE711BADFC9627B0C800710236B909316CA48CC9975AAAB452A50852576114CA2040B2E46607C1453837E",
- "identity_type": "trusted",
- "iv": "31951BDF7F8295133ED6F0ACC391148A",
- "key_seed": "8D101AA09D57A75F449D3E2FD7DEAE6BFE2732B8650057B906687BE5273267FE",
- "metadata_key": "E360E68E7237460157062D59F02667AE",
- "section_mic_hmac_key": "B0229F3856F27C706D246C0A9825CFB5A8A42F943213DD297DF6C9161B01537C",
- "section_salt": "E895C370737AED915CE90F8886219DC4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D9FDC10E7DD4CEE9E6DDC58E32010C56",
- "aes_key": "13BD95BDB3765C222D83F09E7709B4CC",
- "data_elements": [
- {
- "contents": "C34DABECB5407708",
- "de_type": 745
- },
- {
- "contents": "B74FFA6EC993AFF7188E480EFAE2B5716CAC6D94BA01A6E295",
- "de_type": 893
- }
- ],
- "encoded_section": "5E9013C6528C5F67233A0621D667CDA9647C8B9110004FEBAAA8799785F0596398269E32B38D9004005AE0E84461B3A20D959FE3BEA15F943AA33F119D493B02089D7D3BA9441428B675702D1E218A838A546A4ECA06621081AF4A649467EC",
- "identity_type": "provisioned",
- "iv": "74BCB96F895B5DDC9846D24C91CA1ADA",
- "key_seed": "8DB972FF69EDFE8ADA506F8F4EE6A594F5693A3702C8387D0B19FBA6285FD3E3",
- "metadata_key": "99C123B1D364F1879AEED1E415AA2A73",
- "section_mic_hmac_key": "FD1423E5F7DA04EA60CAE11C985935089218744423CC43B3097F1AAD90F197BA",
- "section_salt": "4FEBAAA8799785F0596398269E32B38D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "86EFC69A56E5757AB62A058D5554CD89",
- "aes_key": "159ACE5A180AC4E017D4451EA22FAE2B",
- "data_elements": [
- {
- "contents": "CCC0D2FDE58D59143764A6F1805538AEACE1B9B4765D8AC26D0B96",
- "de_type": 575
- }
- ],
- "encoded_section": "559013C0A81EEC39B1B937912A6CE13ED810C79110000D4B9B8A8C4EED41C8621ABC440648CF900104798C555D077454425379DDE878641DCC3C7B6BDF25F1A1E6ED6D58D0CBA6BCDFB8069B6964894A6679C2A51D3D",
- "identity_type": "private",
- "iv": "24F1D1D3D8E4FFA7AB4B424DEFBCE37D",
- "key_seed": "D637DB7EDCC17C5CE28A181364497144C75064BF385DAEC9ECBE88C4733DC522",
- "metadata_key": "C8D76EBDD7E6D70B1368BAD74E63D830",
- "section_mic_hmac_key": "A74FF6ED127426FB488F765F3D4FB28627F8430C15249C32719A4011A3C49929",
- "section_salt": "0D4B9B8A8C4EED41C8621ABC440648CF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "54B49E29E6C813A6AB600E4FC5B37E1E",
- "aes_key": "7F2AB782AEDECD14B491B2A8582AE47C",
- "data_elements": [
- {
- "contents": "E372",
- "de_type": 535
- },
- {
- "contents": "59C944D70BEA1D61D2B148C437F0BD845A6DD9",
- "de_type": 452
- },
- {
- "contents": "028BA7012BDEC80C4408BB13B6",
- "de_type": 60
- },
- {
- "contents": "F239F4",
- "de_type": 695
- },
- {
- "contents": "AE8259558B908BAEA271AF1F6E7AA9AE2C8FBBC285B601AE7B",
- "de_type": 383
- }
- ],
- "encoded_section": "8390139CB02E72EB97CACCF9A78057EE5CBB309110006A4AE76AEE22009E704B7BD28FE8B2B1900279183874B6909CA5B47A0A86DD6182DAA730343CE2371932D34189949A26ED2DD187AC7575922178E8444DB225910D31030B992DCD92AEAF97563272CAA76CD1558DB0B684B62F740E85794CEF78EACEA7058B4831760BE43B970A2E",
- "identity_type": "trusted",
- "iv": "58DD2660273A4248EE13A8C1AD2C5184",
- "key_seed": "C4634E111562A719DA2BB9EB976735028B2ECEDE1ABE15ADDA7CD3157B233D1D",
- "metadata_key": "566DDB44E374E986BA026292C0EA365F",
- "section_mic_hmac_key": "5EF675045878EFD2070A5A9798BD142A6C34978E9DF077E79BB8A68A4177FD35",
- "section_salt": "6A4AE76AEE22009E704B7BD28FE8B2B1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "501218BE1988D66E80E7EF243937E186",
- "aes_key": "6BE6B27C8417AAFBE97B75179DAFA7FB",
- "data_elements": [
- {
- "contents": "8E3197168683F9454DE6DB69F69E94EA3F5A8F61695068C520781441C0",
- "de_type": 229
- },
- {
- "contents": "25D1",
- "de_type": 764
- },
- {
- "contents": "FAE449BA2F60AE991245DB",
- "de_type": 519
- },
- {
- "contents": "08976D80D1EF3AF9E7EBFA2C5FAE",
- "de_type": 126
- },
- {
- "contents": "3410",
- "de_type": 40
- }
- ],
- "encoded_section": "7E901311389A9F657FB9CDF7216FCC6FDCB5C1911000ADF1D2506EAC7BA9C0E2E598762A41E390018EF9292BFD0E3B84847F8B3AAC77E5C20E9F9C8B5DE8B0C389E7BDFA1847AC7EBC51267223EF07CFB0DDF9F6F11B9A7C346D5C081AD766F7330072EFE978E18ED4D7E22F5E724FF86504EA9C3B2F615ED7E6A73989C029",
- "identity_type": "private",
- "iv": "4334EDBE069FE9E747E594070B35865C",
- "key_seed": "D8791426EFA31574B5323D3468CC282EBD37B522C10B0254B75900D545549C68",
- "metadata_key": "EEA46B5BE346C68C6B9D2FF155B847B9",
- "section_mic_hmac_key": "36586A0A4B1A9EFF83B9D2C27288B2EC000F5A729D845039CB4C4E2E25D050CD",
- "section_salt": "ADF1D2506EAC7BA9C0E2E598762A41E3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6F7E74F849A9CA7DC6EFEB3C4E185CD2",
- "aes_key": "3E0BD976A1EC7956BD5A218B15CA1B88",
- "data_elements": [],
- "encoded_section": "3790130111305FC43F978EFA9FA71298D70A3E911000482B018116837E1A30C802D1FDB1D5E1900434436C965FDF5AB2C0A9794A5F1E438F",
- "identity_type": "provisioned",
- "iv": "8CE2936C0F96EB822A07C82B25CA86E0",
- "key_seed": "5CE432AAE1CA1837C7ED7EFB8ED5B8202DEE8F3D33404A2BD800691E60AC84DE",
- "metadata_key": "60F06359C33E56E540F0D562F6D795E1",
- "section_mic_hmac_key": "9756EC3F8B6D24028B7578FAEDAC3E00F01EC763B58705AFCD3C406CC8E2CB9E",
- "section_salt": "482B018116837E1A30C802D1FDB1D5E1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B7D6F035E98A76528AC824E633BCF35E",
- "aes_key": "855A405A9B896759D95909C8C01D85ED",
- "data_elements": [
- {
- "contents": "A9AF7437A71199911EFBC7F467ACE00B3068C2",
- "de_type": 54
- },
- {
- "contents": "BB4F94CBBE7AE4",
- "de_type": 206
- },
- {
- "contents": "4D3A907AEA42D758A8A8F3469F106BE9",
- "de_type": 34
- },
- {
- "contents": "D65F6C8BA7CE3B27AC2B2719BA42575144",
- "de_type": 639
- }
- ],
- "encoded_section": "7C90134E69BAA34FCC557E20B36B17747D03369110003E74770F2C3BFC7824E73C395259941490022DC2535A7F643CDEA3AE4B0F0C6EF90B575E93CBBF59D9D6B71462FBA784B35C7C36060F51A0FE48AE363A6EC3CE8AB49D9C1C1313C173694407489A8B70CA26A3BD4C099C54AD65D7425835D44949728C287A2359",
- "identity_type": "trusted",
- "iv": "1A27663FC7C2377EF8D2C5186C1FC4A9",
- "key_seed": "64AC1AF89078CCC339162EBD5DED72869833D1952CA107DB18AC60A825F1B53C",
- "metadata_key": "9D5934F8E0592C5D89895210409C8A41",
- "section_mic_hmac_key": "257F10EC7FFC7A37AE8002AC855DAEDB519FF790BB018AB37C07B3C95FA43B84",
- "section_salt": "3E74770F2C3BFC7824E73C3952599414"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5F4055051684020E65946E512C943EEE",
- "aes_key": "2E4C09B79D85D06810D3098DC1851254",
- "data_elements": [],
- "encoded_section": "3790135F9E24B4FFB9D55DC0C402783C77A352911000DC13DEBE3C218E84F7B6BF1A5EE5F99790011059D0BFCCD933671F56E42FE6EFFA15",
- "identity_type": "private",
- "iv": "EE7A0DEC1B5D713DF6F6FDEBBB2BFD96",
- "key_seed": "AE002F1AE69DA6D9E55CE9698288B1A24649A79EC710AC0EA25FA2ACEEC513C7",
- "metadata_key": "8102DD3A02B8CBC1139B5CAF2E1D73EC",
- "section_mic_hmac_key": "0645A1FF34AFF1BA9649FA6289B1614F437149CD7D365604EC23650C4990BCFE",
- "section_salt": "DC13DEBE3C218E84F7B6BF1A5EE5F997"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "65274318E96A5F3C8F853A0140948CA9",
- "aes_key": "A2AB55C2875BC6E1A5C6524613D979F8",
- "data_elements": [
- {
- "contents": "E1365D118F175446B5",
- "de_type": 109
- },
- {
- "contents": "6FD06861E3",
- "de_type": 537
- },
- {
- "contents": "75B17DA591EE83",
- "de_type": 876
- }
- ],
- "encoded_section": "54901395DF3F04E4A427202405C00CEB8517909110008555384C43C1617A30BCF72E5F4BDFB49004F86629CAAB13685CF011DEE82DF4F262F18C02E125C649BB23BD45920E75158EA9070F51274096B90CE869ACC3",
- "identity_type": "provisioned",
- "iv": "21A90C0A73430152D69C286DE55FE6CA",
- "key_seed": "D544199BCE9630C3A38FA486B24337076B81862E1EF002CDCF3F47D2F4F01312",
- "metadata_key": "5890FFFB39DC0CAEC2CD1DC14D8CB75D",
- "section_mic_hmac_key": "6D897F4D0C20E588E90887DA70802A1D1AF3566423DB51B7D461A67F1C47FA59",
- "section_salt": "8555384C43C1617A30BCF72E5F4BDFB4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1F4709A197E6740270684FAD01BB82D7",
- "aes_key": "34574FCAB952B550B440E2640175B9E6",
- "data_elements": [
- {
- "contents": "9186",
- "de_type": 495
- }
- ],
- "encoded_section": "3C901331255D9705F45F7E9517B88F8F638FC291100079F10183D40E8C82C058C764B953DA829004CB302F29874367F55323ECCAF05172CA35D7FC6D6D",
- "identity_type": "provisioned",
- "iv": "947390D6150675057CCEA6FD5718F0BE",
- "key_seed": "7AF2D95F589FC38F0B6F85DF707C22EB88F763BB671E1CB970B193AC44D4BCE4",
- "metadata_key": "4CCF453BB6EBE955C870535451F6C69A",
- "section_mic_hmac_key": "4473C6534983305DE8102EA9118C4735929E70E0544A1EA512560B21FCB48F1F",
- "section_salt": "79F10183D40E8C82C058C764B953DA82"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "96C04195E083ED70F192E617E1D76783",
- "aes_key": "AEB96E57873EB15A971A619B5FE4EB80",
- "data_elements": [
- {
- "contents": "6FC6CB1C012F258C24A6A57A7926E27F5A830A34A367",
- "de_type": 382
- }
- ],
- "encoded_section": "509013410BA26E4CACF5CF673D585B58D0F3FC911000446BA66C82AFB4E9C11CB66EEA6DEE009001F4E644F392CA55B8341671E0AAC030DF17CF0EA76EDF81F2EF4C0CB1336BE6CE9D27DC8D8A4A29E735",
- "identity_type": "private",
- "iv": "891CE2EDBC65C4B0D16DF9F624DBB82A",
- "key_seed": "3D9AB03EC3F93120532D2E778D3C2BF4DA9315896076277F2873A31E4FD5F52C",
- "metadata_key": "CFF78360D994C96E284EBEED93EA4BA2",
- "section_mic_hmac_key": "21BBCAC3997CA4151E9A097276A550A0F483AB80B38134DC980C94B9A5271A6B",
- "section_salt": "446BA66C82AFB4E9C11CB66EEA6DEE00"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CC96FC6587992A00059BF3E0DA2289DB",
- "aes_key": "AF54E2E9237E76444AAAB77B58C5446C",
- "data_elements": [],
- "encoded_section": "379013D8315BBD994D5A670BA6F780F2F028BA911000C755346DFEC27ECCDA898324E69CFB4B9001A9B1E0D2CB309713FC58CB798396531B",
- "identity_type": "private",
- "iv": "B60129EA4D27D57E45CD421948D742C6",
- "key_seed": "807DD8CF77569513B6ECBC68ED9B08E5B9475FF6607732141FAEC638A8DD28BB",
- "metadata_key": "5481564D04DD0017AE4179A82AF221A9",
- "section_mic_hmac_key": "73FFAAF7157A3AE517296592E0B8D13E506DEEC834FE1206ABAA050A9FEE92FC",
- "section_salt": "C755346DFEC27ECCDA898324E69CFB4B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7963E5F18FA7E59600E6F25FA4930837",
- "aes_key": "FCBEC40F3C80A09B60135334EE7DA35F",
- "data_elements": [
- {
- "contents": "2EF5EFF372E4702B096C5B858328F410579E1E008EF2E275D6EA",
- "de_type": 692
- },
- {
- "contents": "BAFCA28BFF",
- "de_type": 398
- },
- {
- "contents": "7E468799B29D34E1914D34B97B4AFBBE",
- "de_type": 966
- }
- ],
- "encoded_section": "6F90134BF4B2FA7735A0143B1B24205E3408F8911000B1236CD7CBD12702AFECBE9635A14A48900263C48BBFAB388B046AADED238F69E1F9A7BE917E59BFBCA2CA3B2C191C787A8C3139DBAE0B72FCEE19B98E0D9C261DA6907D9561B53B735561603F687041709A1913BF7925139044",
- "identity_type": "trusted",
- "iv": "79447B6043F287557A38B57CB6D7279B",
- "key_seed": "52895D125C5472A019409B363AF56DAAF368CA65B24E76E891500A8C3A324F81",
- "metadata_key": "C3BD8D140D94E6945DC06DAAAA211DC4",
- "section_mic_hmac_key": "C35368464E906272C5B9B8C782E9F88A8AE3AB9474742AD6F770FAE52BCB88D8",
- "section_salt": "B1236CD7CBD12702AFECBE9635A14A48"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7A0C1DF60064EF2276AE5C8F6E773415",
- "aes_key": "4AD58F3983D0B6326C71F9AAF86CD10B",
- "data_elements": [
- {
- "contents": "205DD11E927B089869B334A9C59D75032B498C8B26270EE984AB",
- "de_type": 916
- }
- ],
- "encoded_section": "549013603FFB31E477AC33FCEC9446E9C1E230911000B4DDA6DCF6B60042BAF08C824B9C9F2990019D5D07E65857011663A028155D02FF6E932BB511C55C1E2730444597E2AAD904948C7BAF9CFD59D59973745C1D",
- "identity_type": "private",
- "iv": "AAEA80FB40CF47A6266A06730EC30156",
- "key_seed": "90152000F437AF07947A71307DFC0618E116E9AA2AB8988722818AF41CDB59D1",
- "metadata_key": "BDF2BDE3B7905DF7CF58590982B89E52",
- "section_mic_hmac_key": "AB7A1DD69A86B1BEBC2DE6100FBE90AB1C943D5695633CFB48AAE2FC961EE093",
- "section_salt": "B4DDA6DCF6B60042BAF08C824B9C9F29"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2F4226AAB45A2040B831D40B0EBA4407",
- "aes_key": "1222E1C06D6E81FF2AE737DC583C0737",
- "data_elements": [
- {
- "contents": "C02B48E3A60445D37BF70DF40C44CC320203B03EA1F04994",
- "de_type": 866
- },
- {
- "contents": "",
- "de_type": 984
- },
- {
- "contents": "D402CD4FD797FF62E8D7AE",
- "de_type": 37
- },
- {
- "contents": "AAA43BF1A7AA06F9B2F63D52787D1A7AC58D557F",
- "de_type": 916
- },
- {
- "contents": "77B0DE2AEDC7048163",
- "de_type": 621
- }
- ],
- "encoded_section": "85901322B04151D900C31B678DCA782E1E6323911000D57CCB532F3318CCB7BF62288C95AB1C9001D7E937561EC6F7FC16952EC2A7E0898E9976D0028A3A31B6BF858AF26AAB5A1E7A4F36A5588F8F28A4CA3CA8EA4404494575ABCE0A97E8360771F784C26226019DED4E8FB6EE3A96750B9B934A09E28668C6992E8F50D3B794DC6AF2513D",
- "identity_type": "private",
- "iv": "1ADEEB6BE822DDC74F93D2362A2B0441",
- "key_seed": "82AFE392779367A6D4B3787AE009922456277EBC7FE04447BC2D1162778FAD11",
- "metadata_key": "9BDDC51177CD3D9311F1D17661490B86",
- "section_mic_hmac_key": "16342C46DF929343DB72EA520ED728F49F3E50BDFFCE1CF291C3697620133BC0",
- "section_salt": "D57CCB532F3318CCB7BF62288C95AB1C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CAC0617E69DE77A280ABE6A5F3E624EB",
- "aes_key": "77FE9A2730A3B80F387BBD0589358B33",
- "data_elements": [
- {
- "contents": "A6A3C4AE4BDF8941",
- "de_type": 417
- }
- ],
- "encoded_section": "429013C0975C03854C80B4E07AE4CA3076AE42911000EA332A8D5BCA0D6314BDC58F1D09498290024FB2DCBD1FC2137DD2C4FAE1B9A76B2B307B72B1C97D8322DFE749",
- "identity_type": "trusted",
- "iv": "0CCD2727784E9E5B84D45D62A93E8957",
- "key_seed": "EA3D228C2BEB0E89B3C9B28A17D2BEC7F763376D8455DC991C33FB3CD9CCCE7F",
- "metadata_key": "528A7422DECDD593FD1ADC1755835C08",
- "section_mic_hmac_key": "18216F8A0F08FC18F8694B2658CC0B1F391BFC3E82B6F8B24E321BD6371971C9",
- "section_salt": "EA332A8D5BCA0D6314BDC58F1D094982"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "623AB1FBEEF5D3827676D5F2A39FED9C",
- "aes_key": "AEFD0C18567BCB6348CB3A0B0D40567D",
- "data_elements": [
- {
- "contents": "",
- "de_type": 971
- },
- {
- "contents": "DB43DA9E48BDF35056FB18CA10F46359BD1A30A20D5655482FC3976EB92A",
- "de_type": 729
- },
- {
- "contents": "97652C8CA93C33047BA67FBB",
- "de_type": 766
- },
- {
- "contents": "D6525FFF50D38FBEE9",
- "de_type": 487
- },
- {
- "contents": "1866ADC89365521D269D6FF6A1972629DCDC",
- "de_type": 421
- }
- ],
- "encoded_section": "8B9013137611183EB9AAA3F69202645FA0DCC09110000BE535680DC0F532EA22C2F75B8A066C9004BDDE3F2ACBAC8630F0A35CE5A424AF735799E14DADCA023F6200522E83069F8ADE4786A502D31EA079439238D5A9590B1227C5CAA9CE01579FEA21D1DBECDF0D95691CCA2FC601B27D5696CF25128DDFD16CCCAA5C96675488611E407310D067851CE7C6",
- "identity_type": "provisioned",
- "iv": "DA1292F56F9B309A57103588C56F0B86",
- "key_seed": "20232B2934D61F4254E1B430C941D99408046EDA864CAE9CC1F30B003DA3F15C",
- "metadata_key": "958125E98D4CCE39EB85BB7A1799EE11",
- "section_mic_hmac_key": "B2AC01EDB57C1E96D629F9DF9B299A97C7A8078AE389FD3C4CD495C17E9C04D3",
- "section_salt": "0BE535680DC0F532EA22C2F75B8A066C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "274851FCCE9C7A4AEF4AE64A5CDF1B35",
- "aes_key": "096944332E1C31DBE39227572D5E4FA3",
- "data_elements": [
- {
- "contents": "6E64A76F629EDE6983839536E6746048F9407203",
- "de_type": 828
- }
- ],
- "encoded_section": "4E9013B4E77EEA1D31017802F64F86FAEF7E31911000BED45389016B48EF6F638B053B3EAB3690021297C8C1D17FDD132207ADA56F2E1DB48EFCC6972936EC031E5A1C12EE25BC554477A6838C8273",
- "identity_type": "trusted",
- "iv": "1F4EACA3D2A66B67B8100E7FD56858A9",
- "key_seed": "4B40631EA3307B8B03B324AE583A624B14A3846AD22A98AA8A6476CE18B72519",
- "metadata_key": "856BA488B5E3073FE98F90EC7D43D9FD",
- "section_mic_hmac_key": "89252A2B55F7FC94ED83D11D1901E8354EF6A832522A61E77DF2100FA5B40E85",
- "section_salt": "BED45389016B48EF6F638B053B3EAB36"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0EC0CD8BC147F50646909D6EC4CC2134",
- "aes_key": "D4342D083B5848972862E5244EFD574C",
- "data_elements": [
- {
- "contents": "61538E97",
- "de_type": 674
- },
- {
- "contents": "142298DD27C29352869DBD73AE86918E77E0",
- "de_type": 321
- },
- {
- "contents": "B04E54",
- "de_type": 64
- },
- {
- "contents": "08BDEC39FBEB13292A5317B91CDC",
- "de_type": 546
- },
- {
- "contents": "AE3883A3D67D64CFA5B52195337D40B768695A28036AA392F25A9B302816",
- "de_type": 255
- }
- ],
- "encoded_section": "8A9013C70296B62647E222527D694A181E0B3C911000E66DDE309D386AED3A9E6F4F4E72AC2D900476583A491A2BB7D5B11ED5D5D40D40427D285AAA7C31BF39774FB2333DAD5E8428A8728BF4619A5F3E1F646C9C637412FCB7E60BD95712CDC6DBBCA7A64509C4CF24A63615566468376BCB88515DC32CBE4462ABF2A5B902AF44CCAA8034D1B98DA864",
- "identity_type": "provisioned",
- "iv": "C8A684AD4924F67F2BB34B665F767260",
- "key_seed": "0B21B7F5AFA2FD60F417160706E110DAD08D558B7F873A7145E2F5846B30EE14",
- "metadata_key": "9AFEEF6AC49A69F403F130619CA3C015",
- "section_mic_hmac_key": "EBC37528F0E1D39DDFEB12F6229FF778D381BFD32C22EDF0A22AB350036560FF",
- "section_salt": "E66DDE309D386AED3A9E6F4F4E72AC2D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "107DE67CF73BF73111A7D273F220324F",
- "aes_key": "C909F88E99316114E33AA6727A466458",
- "data_elements": [
- {
- "contents": "8EFDC86CCC6C78EB",
- "de_type": 542
- },
- {
- "contents": "AAA1E33F8F43B229EB8189E8",
- "de_type": 551
- },
- {
- "contents": "54E27639599792ED49",
- "de_type": 92
- },
- {
- "contents": "72C8",
- "de_type": 187
- }
- ],
- "encoded_section": "6190139BDEA29D9DC86B46F9D2BBCDA4366F1E91100088D8F556CD3AF2EA81FB25030F2C782B900230E146653F1669A7ACFDF87FCD45399FC47FED90B8920E5C85A2B5ED2E31FBA1EBABB429881EAAC9CDBAD9B7B529A7AE7756AF294C1F46800357",
- "identity_type": "trusted",
- "iv": "F42D4010A9B9750FA68C39E1E7293CAE",
- "key_seed": "6433B38B99F099F8291F1AC0E46556F0110E50A48F622C7ADAE2F70FDDD13A00",
- "metadata_key": "433F040898968971CD78BA25C93FAF72",
- "section_mic_hmac_key": "2D3DAD9FC1AFD294EE70B0F00D78E57ED025932D5EAED1E85F5DA314C4372F8A",
- "section_salt": "88D8F556CD3AF2EA81FB25030F2C782B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "23DB2534F86E837128D4B5867BE7B9D7",
- "aes_key": "FF021E596C3FB19F91E10975989481D7",
- "data_elements": [
- {
- "contents": "092500E2322279050831D86A9D0C412D262AF1",
- "de_type": 889
- }
- ],
- "encoded_section": "4D901361744616A9DF4D232AD6583E68EC94E491100045112DE3235917ABAE281CBB93473C8C9004A8CA160F322458CD3FFA1BE531D8FCD0009177A286DB8E8D4BDF1A77962A55FE3AE696EB057D",
- "identity_type": "provisioned",
- "iv": "EFFEF8C52517139FA621AC011CDAB4BE",
- "key_seed": "9A62A13579CCEF2E7654D15F2A1BFAABB99E94396396BA14B5D488488BBC454B",
- "metadata_key": "5CEC4B1BA12D44BB925EE396A95149B5",
- "section_mic_hmac_key": "3C093A169750EEEF1645B87A283453DB15D44FA8FE8E6D36885E5E079736E0DF",
- "section_salt": "45112DE3235917ABAE281CBB93473C8C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1FB79ABE6FB18715F8DDA68BD6B15373",
- "aes_key": "0BAF583B5891233D33BA6B74D5E422B5",
- "data_elements": [
- {
- "contents": "0D611B00EF235E26",
- "de_type": 578
- },
- {
- "contents": "6DE7D6C995",
- "de_type": 500
- },
- {
- "contents": "310C2C3FA8E0702122BA85A3427A256F065CE1EAEDC1B9F7D4F04F13F1",
- "de_type": 579
- },
- {
- "contents": "3F1A1AF9FB1A3B409C278ED4098EA6CF87E02457F525",
- "de_type": 947
- }
- ],
- "encoded_section": "8390138D06F7CEA300F4FAA9EAFF32BDDB833F911000911991BF08A3D1BBEA49C971CD66D43190049130C7E781DB24A1E2C7255DF0FF30DA65DCC1AEF1188EC72B1D6ACD5B6E42E904B513B03DEA16D250F9B146741427C0FE6E29624849A488542A956CEACBAE834CDB227CB06520F4453A08C795A729852015823C3F540167A6B9B6C6",
- "identity_type": "provisioned",
- "iv": "C0073097AE5243E3E6861876E66B6C42",
- "key_seed": "04A20B7ED383D59B567CF62F30B25564D6509736B9141C273B638EB3A111EBE2",
- "metadata_key": "E6B382E4B38BEC2DF51C9084B2A1484A",
- "section_mic_hmac_key": "2DB0DCBCB00F8B684C3876EBC116C87B388F8E4EC2E4169536E5C34E2524DF60",
- "section_salt": "911991BF08A3D1BBEA49C971CD66D431"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6E07E0694343C77F296426DD6E13D64E",
- "aes_key": "1ABAD934592B2D7736D998BAC1194ECA",
- "data_elements": [
- {
- "contents": "DB8A57783224CF9C",
- "de_type": 267
- }
- ],
- "encoded_section": "4290138A4D553E3BCB5789F1E01ACF4D8D7955911000D0E797023C8E23832AF2DE31413FECA59001B98036E2FAF383E70C58D8A5DCDCC5C7B528D95B9238054791D51C",
- "identity_type": "private",
- "iv": "57B0B15DF8CED13A80F93751E71DE9AC",
- "key_seed": "B593545C0D736C1BFAB6E76CA49AB7DD942229C6E8B781B468ABD7C60ACBCB97",
- "metadata_key": "90687B3B2AA61278792878E85A897B9A",
- "section_mic_hmac_key": "FFA3F38A2550890AFF05E718065CC2A4AFE5EFC392122B4D0B12CA96AE3ABF58",
- "section_salt": "D0E797023C8E23832AF2DE31413FECA5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "962353CB1C07FAF6686149577DCC75DB",
- "aes_key": "E9007665D3AF271921E87A78F657A08D",
- "data_elements": [
- {
- "contents": "DD845D55",
- "de_type": 566
- },
- {
- "contents": "00E752395426921A92C74AA1560976DA2AE78C9D33",
- "de_type": 290
- },
- {
- "contents": "CFE5A4F631D430593C281AF3371C862120623F7AC4",
- "de_type": 179
- }
- ],
- "encoded_section": "6E90138E7F8FE7DD8A3FBCF4B8077EF8542315911000F36F9FB7D32C243DF950E4B059E15F9190014A5AFF2BA024EEE91B2A86D089FB84084BF6D938B4B23C220B8C47E388A344199E965D14EB2524F47A4BB2ED0A2BECB01B63071D79034984E9A386C256902483D60EA4B5A1AB78",
- "identity_type": "private",
- "iv": "83B1FD00052754192029CB2F83E4297F",
- "key_seed": "CCA7390D51E680A3B3072F1C9E70064FF16DD44C9D62A37B248C73FD833AC660",
- "metadata_key": "523BB1997FAC71B83F2B60F42589EE95",
- "section_mic_hmac_key": "0EE49B03E4B64FC2B250B0D2C4612D020494181E761B23ABFE594F97040CEF24",
- "section_salt": "F36F9FB7D32C243DF950E4B059E15F91"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B67BF6F1252F5E0EF8816F15D301A39F",
- "aes_key": "43407D6D91B96435811F30A50BE54FA0",
- "data_elements": [
- {
- "contents": "0235ABB510F05341",
- "de_type": 824
- },
- {
- "contents": "CA9166B5",
- "de_type": 12
- },
- {
- "contents": "1FDEC6B16D164A545D8B64995C00",
- "de_type": 38
- }
- ],
- "encoded_section": "579013B31D8FF7387C6F88EA6FE4E1EF24DA329110004C349BCC1D0FA5EF838F76A707E05F8F9002ACFCF23B0B23FF24956B6407E513CB77D0D7B1884C904DF788AD961EC5FC1BADD31E34E027C38199C5476203E4CA0FAE",
- "identity_type": "trusted",
- "iv": "5AEBFCFFA3004CCAEE5DDFF854D820C0",
- "key_seed": "E1B8FF062302C677E36789FCE15BF3CA6C1436D6A0B78E5D3B241F946678ABD7",
- "metadata_key": "DD3F2168FAB2123B9450F54E86B66A11",
- "section_mic_hmac_key": "BE20035F0C2A7E3BBCB38D949A8CBE3F3F1929D5658501B05BA0A14177EB1982",
- "section_salt": "4C349BCC1D0FA5EF838F76A707E05F8F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "683691EE3E8A8E95F4787967AC569B94",
- "aes_key": "4B42E071DEA02B52101DB6E24B78FA20",
- "data_elements": [
- {
- "contents": "993E9EBC3173EA199AF4BDF4626FB2FF1AE7FFC46C5DEF",
- "de_type": 21
- },
- {
- "contents": "6D16",
- "de_type": 274
- }
- ],
- "encoded_section": "5590130DFDF1B79474D9F039992B840380FD319110000E05D59BD69C24AB85016E9CBF7513F39001E420DB5C31A3BDD1FE0E64CC581F32309E4F949318B591E46A84742D6E0AB75086EDFAD1D098CE4C78421F02775A",
- "identity_type": "private",
- "iv": "F35FF701EC37712BDC76295C2D1895F6",
- "key_seed": "2496DFF7490AF44C61EF3D47167BA33E22B738B68C5D24EDEA6D9087BC4F0758",
- "metadata_key": "CA1F7C7043728303F66ECE50ABA40834",
- "section_mic_hmac_key": "00DED9280F77E5541D670B81449E4EEE65A2003D6933A1EB4F2C20BCC8453899",
- "section_salt": "0E05D59BD69C24AB85016E9CBF7513F3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "196DC4CE0B019790D86640A73F7ABE96",
- "aes_key": "8338D017A81A7041C6D4FF4F533046CB",
- "data_elements": [
- {
- "contents": "445F36A981DE5A534274F1B8CBAD2954CF66016F275A3A",
- "de_type": 500
- },
- {
- "contents": "8A1215636ECAE1EFED9182A21900224066DCAFFAF0F9D42CA05D79",
- "de_type": 608
- },
- {
- "contents": "4B605D68943C67774567CB69957D827DDDCF7F2A280BE76CC6",
- "de_type": 652
- },
- {
- "contents": "EA46EDA7D7586C247F8101FEF4DDB2",
- "de_type": 523
- }
- ],
- "encoded_section": "9D90137836767DD16EB5D181B94393B7C9C4D49110005AA5A767B7C8F390E7B84598F1E6ECEA9001F907A884F970AA1379060520D3DC2C794766F852A608DED6EDA2BB11652C88B605D333829E95E4CDDA7F2EA77AEF23BD32B61F4DF8D2994458286871792C64F6D9BFB9DC6DB688719294349997D166BFC2CA7EF0C6ECB78C8E6ABE95404372904758CBEA1E5C7805E2DC10FA9FC6A28233C0569FD0A8",
- "identity_type": "private",
- "iv": "D977A2029F9F9599DD109B5F935234EE",
- "key_seed": "DAF58A433FD1C92223C83A1D458C16A6D791C35B6D233A5B0802CD73481F6730",
- "metadata_key": "A3611E071012852B91B390F2EAD716B0",
- "section_mic_hmac_key": "1B677F76106044CF24E36F00B46DE7F48FC244D3CF907DECE2B2F39216579EDD",
- "section_salt": "5AA5A767B7C8F390E7B84598F1E6ECEA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A6DF7A7591C801A5C966CA40B18C959D",
- "aes_key": "7AAEB3A3D128791FEE4FD4872BE02E6D",
- "data_elements": [],
- "encoded_section": "379013F742C6E278A2ED6465DB07BEB12CFE50911000C7F758AF24AA696D1CB7D0A9D65C582E90043FA1230A35535BE33302A53CBA4418AC",
- "identity_type": "provisioned",
- "iv": "B445034001A0F499175F3C9EB0AE92DA",
- "key_seed": "39C904DF3BEEA18AFEB7BE38D6B8E6069401DEAA759330C9DC25C4BE112CB5A3",
- "metadata_key": "0ABF633959D782380E4E947D27A805AA",
- "section_mic_hmac_key": "54AD001651F4FEE64341F38E740DBB8FF123F756D68FDEC00E8B7912B13CED89",
- "section_salt": "C7F758AF24AA696D1CB7D0A9D65C582E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "88705DD1C65299C03EA7AA7496559581",
- "aes_key": "5651F9236F827EFFC434AD9F005D28D5",
- "data_elements": [
- {
- "contents": "45040FF6A5CDA9835F818B484CB70A07B9EF939F",
- "de_type": 875
- },
- {
- "contents": "908557DCC7A672E4559E4280BFE4B0DF7CBB9033D57420F140A2B585E2DE",
- "de_type": 418
- }
- ],
- "encoded_section": "6F90135B57ABF5DF4973307BAB1DB3C4AA6C80911000D91CE3FF1521638C0EBFB1C24543DA3B9004642281555CFA95167B0E6158D7F0EF0D5BD41FBE8A2DDC73B00B17998905773562C1BE381A66298FADDCF372204D30794F124C34FF7139623F41E957E4AF81A7379BE160E3B23135",
- "identity_type": "provisioned",
- "iv": "7FB08290F4083C8C63DD2DC495C1EB45",
- "key_seed": "EC1290EF880DE14D1AE6D5B0F5A835DCB8DDEB83B7991C7FEA02F738A7C0C94C",
- "metadata_key": "52C1C131236DC4C9DBEF317D1266471F",
- "section_mic_hmac_key": "9695F74C29EA748DD4457C18285F53555A358F759EB1183889B4A15320A846F1",
- "section_salt": "D91CE3FF1521638C0EBFB1C24543DA3B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F4DC0B55884950152C6F0C5C01475956",
- "aes_key": "FAF30D19065FBD5D679D78E7C7EA0B92",
- "data_elements": [
- {
- "contents": "5EBE58BB8F41ABFE605EFB39B48A4E7861EC80EC",
- "de_type": 455
- },
- {
- "contents": "FE52251B3CE9AD42F9A3ECC5A213D742F37415",
- "de_type": 207
- },
- {
- "contents": "85C6D2468DDC1B42286E73284C03C718DD3E1FC5FD3050",
- "de_type": 556
- }
- ],
- "encoded_section": "7E901315CF56AAA74A2A4F82F00092990E8814911000743CD7DAFB42FC38076A13E7E1F4177990044F324B65EF22A2272B929464CD7DC2C2D75872E649A1D7DEFE164D58E07B41F473505815C0BC34702A02C0E4F113866170FD1B15EB58D7994E0D33A206C0C44A2F092679874A1D1674EAEAAFD99E0FC19E6F744E0A7347",
- "identity_type": "provisioned",
- "iv": "FB564977E2D99426D140FD689871A2BC",
- "key_seed": "A62634BC57E141BEFC2564C14B48325117363328C53CDA48F814D4807048B48B",
- "metadata_key": "574603EF40BA6009E312223A51E8E2E0",
- "section_mic_hmac_key": "86ABC6D41CEF55446F03A0952E90F664718C4822451D24A3FC27E2898C84EB40",
- "section_salt": "743CD7DAFB42FC38076A13E7E1F41779"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "53234126DBD29BAF6097EC8D34317852",
- "aes_key": "84425FEC4A06780FE396F9DD6040DEA0",
- "data_elements": [
- {
- "contents": "6ACFE4B438C70672D7AB",
- "de_type": 986
- }
- ],
- "encoded_section": "44901360C0D9E68524187C1C25A4716FE61009911000B5E48CB9F2C2281E5195D2D12ABD09169002C39DB32F9F0C574E62CB199AFA336A185270C735884423B5B93B0DDFC7",
- "identity_type": "trusted",
- "iv": "D9119243F3D9CADDE86862B5ACEF8CD3",
- "key_seed": "92A8C510E73A47699B0C22ABD2914EC022E9AC8B797E993DC4C6255EF66BE228",
- "metadata_key": "39EA512E22B067754A318A3CCA5964C9",
- "section_mic_hmac_key": "12BCBCEE50AD4DF7923CF35B1AB83583A1F4E502748556DF89A646200C3732FF",
- "section_salt": "B5E48CB9F2C2281E5195D2D12ABD0916"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CEE234610E9993DC98C3D370D26F3DF7",
- "aes_key": "51D4F92C953723A8BA9288131BEFFB59",
- "data_elements": [
- {
- "contents": "3B1748685E7204CD0AC2500BB88742F69E53",
- "de_type": 467
- }
- ],
- "encoded_section": "4C901383131BCC9CB08EC986EEFF6504BA974D9110008FF0CEDF1640457BEF1F5CDA7D58BAF5900483D0B4BA6B8D9B80C5C9E12480C55424936562E3C68999DF6C4FC8256C9A0B17808194DB2A",
- "identity_type": "provisioned",
- "iv": "98603F701E96147E49F0A3F8C4174589",
- "key_seed": "6532ABB7061C073E531A655B8F49D1D2311AEFF08E26F15B3CD5EF6AD3A960E2",
- "metadata_key": "20F0584320BFF42FC597A41280E5BAC9",
- "section_mic_hmac_key": "02101BA95A03412345F3552A5C163744CB1B4B1EAA3232E2CEABB4C862AF141E",
- "section_salt": "8FF0CEDF1640457BEF1F5CDA7D58BAF5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "81A1175E23E1EC7240337AFAD6BC7EB7",
- "aes_key": "FEDFAF2A6E7FC0E21A91E59BF8B332DA",
- "data_elements": [],
- "encoded_section": "379013A99129E69382B3F3FF02558A9A25CD15911000A7CF353E32FB509A39BF6698EAA646BC9001C2A2D18471E1D05CE78FB1967ED58068",
- "identity_type": "private",
- "iv": "3CB4F19740A089755A2925ABA96D2237",
- "key_seed": "3B1D9789DE417E14DE7F5FF6AE8BE7DB5CB6617453BDD7FD1A216DEE5531D68B",
- "metadata_key": "E5D8C1873FBC970ABDA794974C2FB35C",
- "section_mic_hmac_key": "687C291B4FD7331659D26806502AE31343D972AE2E6E7AB83D647AA57C22FAA6",
- "section_salt": "A7CF353E32FB509A39BF6698EAA646BC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3002A18B6213325D185827101B8FEB1D",
- "aes_key": "CA1C7AF04A4FD83E87A9E9E730289BF9",
- "data_elements": [
- {
- "contents": "8699B5A78970A2427D55BD82D4",
- "de_type": 656
- },
- {
- "contents": "DCDAE8E9DF3EBFA2C6094F42E6C87791ED",
- "de_type": 517
- },
- {
- "contents": "F0B0161E1BE7ADBE7B8B72CB09CF4ECD8B7BA0859856F8FE24",
- "de_type": 288
- },
- {
- "contents": "B30B",
- "de_type": 56
- }
- ],
- "encoded_section": "7B90132C905FBB2C863EB4079E8B7BAD34C5839110003682E85568AAE0E82863BAD2FADA6FDD9002F9EA810B398843E60BB488546F7BE02E1B50043AD29711AACF37D90F6E1DF855915265AE4B2A4F8CB2253B76F8ED0E828288F2D47F06106F01A00C8F07333054F7EB00AC58C060BAF7F3BA9BCE4C6F031F9A93A9",
- "identity_type": "trusted",
- "iv": "B2B61B37788EAA1C5A3068450C9E7C63",
- "key_seed": "EA552C43BFFF78260A603EE8B1C72EECA8297D7373D60BE107F83AB7C147D7D0",
- "metadata_key": "E748E53B8B84D6D63DB643073B39ECB5",
- "section_mic_hmac_key": "0E9B918DD78A73505AC657B398BB35861E5A69907965F1BF5D3306B59AB12A7C",
- "section_salt": "3682E85568AAE0E82863BAD2FADA6FDD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F88AC9429FFC97BD5D9191F120126A01",
- "aes_key": "1D105B146BD337AA7EFA523A71C9E1AB",
- "data_elements": [
- {
- "contents": "00C5DF062D335BD726CACBC7A0B67B0B",
- "de_type": 620
- }
- ],
- "encoded_section": "4A9013DA781FD242A7193FCE5BD9F370AC8C309110008D1CDE6542BCF8E73879AC69688FF55990049CFE71AED546CA5745D7C06F4E689A5D8319E344654EC9495226DB8024DEE4182A8F08",
- "identity_type": "provisioned",
- "iv": "68DE89B24537AA1B093F7FA14AEA7D49",
- "key_seed": "A6845D869AEDD2ED427829ADEB09807A8A5300A2675344EAECE93BEFEA0A6701",
- "metadata_key": "2B83AEA0BE02DB20AAFD114A9C33D1C9",
- "section_mic_hmac_key": "D5E0B90E46BBE6913978A5213BE51F2C9B9D9628FD986C96A5A82E1DEA8E073E",
- "section_salt": "8D1CDE6542BCF8E73879AC69688FF559"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0DF16EC423548F3D0B47CD91150015E7",
- "aes_key": "4C28452111DFF26A316FD05F3E3004A7",
- "data_elements": [],
- "encoded_section": "3790132CC5741EAB8595660B062128880D944291100091B18AAB56D0B536F1791EE8D2C9FC1C9002A188B363001A99AEF63B8F1E5E0CC9B0",
- "identity_type": "trusted",
- "iv": "5FE3E1280133A66360FEF6157D65A3E4",
- "key_seed": "E030711E2C294C058D619E45659774C93E40067CE130DB3AD1B883FBC8E3B95F",
- "metadata_key": "75FC79BC1F5F4A71F3919FD3A658B8E2",
- "section_mic_hmac_key": "86756856EA5D1111E0D45443BC003A04D28D46FA3D9D06C19CF3BDD207CE17E3",
- "section_salt": "91B18AAB56D0B536F1791EE8D2C9FC1C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D2CB7EFD8AC55A4B7782291095063735",
- "aes_key": "E53A8922160B243CEBE1723E102DF96D",
- "data_elements": [
- {
- "contents": "90E198FFA1A1771232A470B41C3618551F808B37619364450C82D0",
- "de_type": 57
- },
- {
- "contents": "AA3536B6255F1E330F33A40BFC23BF0BE08BFDE03B278FAB353B55BF",
- "de_type": 475
- },
- {
- "contents": "ABA930A2B7EA27DDAFF5",
- "de_type": 520
- },
- {
- "contents": "CB27A674F14A84E844A2DEE7CBFF32C1ED",
- "de_type": 333
- }
- ],
- "encoded_section": "9490135104FB10A397689EB08C2D4E9BBB0C1E911000979A8AFA25DB21F7EC13D146CFC1410F900460CB56ABE59BB2DC4C6C17EDB2CA9BA8D3214665237A16FE0A4124A3C5465CFCBCFAC32C1DE41A9D42B99C8D8D36EC9D3653CE7F286A0907AE9A8D270E3DEE03F7442D7DA18075C6620D6292861C1FD97902A798F643343DA5F9879B71FE88D1D6514F1B41E9A209748FD124F0",
- "identity_type": "provisioned",
- "iv": "4C1351CC073E7B86D90BF026FF0807FE",
- "key_seed": "91980B5B07EF7D557FA8F5E60411D2A0F2F449E1F9FA2631250BD86E5C8B0142",
- "metadata_key": "8104BB265F6A7B5B61C316DB48EF06E1",
- "section_mic_hmac_key": "0DF5F3A00DB4D6AFCF99FB6826F9DC765C289B7937587D1461D825FE4D6FAF41",
- "section_salt": "979A8AFA25DB21F7EC13D146CFC1410F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B184B09431BC6D20C3CBD8D108EC4E2C",
- "aes_key": "4EF35CEA87B3BE66A3C3D72A64E4CA2A",
- "data_elements": [
- {
- "contents": "F02092",
- "de_type": 129
- }
- ],
- "encoded_section": "3D9013AA922B9D3EEB866D6046657CC594A33D9110002A4E2A1E8DA81FEDF04B8250BA2383A89004B6DC8634A6410E0FD602D04433BC254A51A050D6419E",
- "identity_type": "provisioned",
- "iv": "5ECC70A88EB4E67063D4E0F57831F4F4",
- "key_seed": "098C5CF53518E9D1F2F2D8D0AC948B9B8CCDEA905F999934824429C0426E34F5",
- "metadata_key": "7D82E485F54A2C30295125C2A1984EE8",
- "section_mic_hmac_key": "E8881B4E5CF4A053EEB38D0D8B18C7853E2001926A46471B75B864B23DECE677",
- "section_salt": "2A4E2A1E8DA81FEDF04B8250BA2383A8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "47452213CC5FDC391929EEE09F724D0C",
- "aes_key": "24274A9E54725581BEA8C3AD99D6FB45",
- "data_elements": [
- {
- "contents": "55",
- "de_type": 280
- },
- {
- "contents": "C5E7F5858DE92DDC1EF5A8",
- "de_type": 403
- },
- {
- "contents": "D111",
- "de_type": 802
- }
- ],
- "encoded_section": "4E90137CD48DFFAF75C3050516CB8439CE77D0911000C7E763251945F46C637602F94E61A62590029B749B79A1E7192F10EE205ABD363E48F834C31AACD41E39E7B104C201C6D805EF464DD0C5AD59",
- "identity_type": "trusted",
- "iv": "FC666787DA6880BF68AD87F281129436",
- "key_seed": "16376750ABB42AAE45961441C9251B3006EB249781EBF712994AD8E297BFB3FB",
- "metadata_key": "BC8BA065EBBFD5F28D57B63473F648DC",
- "section_mic_hmac_key": "D050DE0A2C557BDF173F3820B540F059F4F902A963D23AB07A27E97341433925",
- "section_salt": "C7E763251945F46C637602F94E61A625"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "397E5C2A10FEFD98E9764BB2850F9F70",
- "aes_key": "B86A8C3BEBB410A7CA7937C27982E5A5",
- "data_elements": [
- {
- "contents": "4C84393779DD47BB70185D28196CE896331EAB",
- "de_type": 999
- },
- {
- "contents": "2DAE45BCA9D994FA2F8642E698B26E",
- "de_type": 224
- },
- {
- "contents": "6CC6616B25874F1670FA2664C467A442CAF6DA681FFA8B",
- "de_type": 588
- }
- ],
- "encoded_section": "7990132E1215A7A422203DE07796127DB3749791100050120AFB3D493DB82A96A0EBAEDD595B9002290C00E97BAC5F0AE286B2F1B3EB9C9F65554CA39D2F0BEA8DC26C3C3FF3877C260EAB0C966B6D187F472E076B43ED87238C272FE87723A973DE2746FC47707E4646665461E0CCEF8D72E5AC6E410B53D4D4",
- "identity_type": "trusted",
- "iv": "671819F4C129CEA59570A45E40042DE8",
- "key_seed": "42FAC575479AF4CF414FD25107A31CAEB82E876F63F2AE64F158B1193C1CE4C3",
- "metadata_key": "75A7213D0E26DF12A237EA4969C2EA7A",
- "section_mic_hmac_key": "0A42A390A90B39228144B934135AC7F799CF4FBB70BD8414F1687C8530F94931",
- "section_salt": "50120AFB3D493DB82A96A0EBAEDD595B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BDDEC437FBD471B4309CEA1E0151736B",
- "aes_key": "56B2E5280671CEBDB46B21FDEAFDA8EE",
- "data_elements": [],
- "encoded_section": "379013AF79FB24D9AEBD4EDB9BCC1B15E3A610911000AC735789ABF3C926FE9787D8124F26039004EB9FD655DDA7116ABF7A20E5D0BDA234",
- "identity_type": "provisioned",
- "iv": "BD94284A1DED0703E49EB2A616033C17",
- "key_seed": "D972FC64B93F5C9942A0ABC8646EE78A152FBB8BC0704F52FDDC48B7FF56CBB8",
- "metadata_key": "A392A526A7068B94B1E3E25A0429F56A",
- "section_mic_hmac_key": "922DBDD6A4F8865AD9824AD8FC62B30AAD2F8BDB93D3BCDEAACC3305E32A19E2",
- "section_salt": "AC735789ABF3C926FE9787D8124F2603"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A9B77465966324AC9F3290D2369987F",
- "aes_key": "7E5CBD3F2102129DB706C8EE75A333EF",
- "data_elements": [
- {
- "contents": "847502E89C450B3FCE072D156090AD6C52B2D8",
- "de_type": 645
- },
- {
- "contents": "761BBA3496528070633DE149451D9AD4E3558F7476",
- "de_type": 537
- },
- {
- "contents": "AE9C840B555C",
- "de_type": 582
- },
- {
- "contents": "F4703CA172",
- "de_type": 113
- },
- {
- "contents": "DD2959D22A5E",
- "de_type": 365
- }
- ],
- "encoded_section": "7E9013F9BDA274AABFD8D976598D24C4DF68339110009D4C783A6ED077F63A108F3558B4FE919001677C1A3E9ECD221759776116DF4219E28E1D79E7A658B09286A4A54EABD817A44B57078452B9E6957E7B49D0D73FB94970474298DA5CB0C6C2908BF42578F79E5EC1992A89A39264D9B49F1B5F559DA0F6C6D9314E8516",
- "identity_type": "private",
- "iv": "CC837603730CF2CFC59BE454DBF623BA",
- "key_seed": "282A075FC7CF3101EE966ACAC968FE4841AF6C4531A5F2655E301C611FA6F075",
- "metadata_key": "2DB58866CCCD71AB219184D30AFB8ECE",
- "section_mic_hmac_key": "1A735D24B9F9C6A3ED6D2C01C9D797EE696EFDE44D92D2E7AC9C01BE5E18C915",
- "section_salt": "9D4C783A6ED077F63A108F3558B4FE91"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "62CCD10524DAC73729C1C47D671A9B35",
- "aes_key": "6B3EA1B46FAD6834DDC93E9C98BF83DA",
- "data_elements": [
- {
- "contents": "B29B0EA86E6A724DCCAD1FAF",
- "de_type": 68
- },
- {
- "contents": "FB4B7ED6",
- "de_type": 380
- },
- {
- "contents": "87E233EA396E891F9DD432C299",
- "de_type": 36
- },
- {
- "contents": "ADFB0CEED7C144A0C6EEA37805ADD5D906F9D24009",
- "de_type": 584
- },
- {
- "contents": "75167BC12CE8255FEC4FDABECD6C",
- "de_type": 650
- }
- ],
- "encoded_section": "84901321304B13B0CE78A9C654EA01BE27EC87911000356CC7D48B00218080567F86C8C226B59002B265CCC13ED42B84041556DD88578525CE07A7AC025EACA3F2F55D0F8A26C3F2A8B63D8B00173466BF45EE5F56CE1B3BA5A388238E532DBD0CE43823A12591752022676716BBBA2696C01A2E07367068170CEA04E4D675821C3AA19184",
- "identity_type": "trusted",
- "iv": "DE1A81AF6B53D4D1D4D50534FEE5254C",
- "key_seed": "38A92224674C6F2BE57B36D8A191E576633DF9BA3D76DD32F70D72D415878DCB",
- "metadata_key": "C140E14318193C8ADFEC1D2CBFA8213A",
- "section_mic_hmac_key": "BE625934853E588137352DFC9C3574A129F96C993C4221C8990D91FB635B4F67",
- "section_salt": "356CC7D48B00218080567F86C8C226B5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3E4E649CF35F5DD9CB2AC8E02E80445D",
- "aes_key": "07A72FF7D07703E075A69D477BAF0177",
- "data_elements": [
- {
- "contents": "9A68B1D0835C59498A7B483199",
- "de_type": 698
- },
- {
- "contents": "514E4A96E7057DD993624378D31FFA9CECF7E7B08BA9B4C73F",
- "de_type": 405
- },
- {
- "contents": "36364E971DCE98A7C23B164608BD1D4A410B79CFF32CACDD",
- "de_type": 584
- },
- {
- "contents": "6D6653D73680A3DF70FC0A0B098913CA93879CAFBC1845DA745E",
- "de_type": 331
- },
- {
- "contents": "15DD526DC963112361A3",
- "de_type": 865
- }
- ],
- "encoded_section": "A89013CC1FFAF0DB58D146DFD9B332AAE9C0F29110001730E6F86D0561262F4E315CBAFF7A9790025D2C78819ECA218C6938BAF148CB6A981A2D0884BE9EF00D8E5680E2636626FCA4B60503C6C524ACAD4306DCCCF2BB36DE37EED4B651E8C4992C87E3EEDF4E8E6C1BA2298791412E1275FF53DFE8C771C880D127D47815972F804EF4CB42CB7C8B73A89CFDFADF42BE03DB2F21F1D92EC5DCDF46E58C17A6A3FC5F92BCF001819E",
- "identity_type": "trusted",
- "iv": "F869FF07F98E32C0AD55CEF91658D60D",
- "key_seed": "5D1E0AB8AF70BD4F1F5E7AC632B46F0D3976CD3409D96D6336FFC71E0D0B1A39",
- "metadata_key": "4745EB0C29D3829EA920471E4CF7FA2B",
- "section_mic_hmac_key": "A542C3B2AD831E3212C0A66B8F78C7F1D4AE757BCC53E59EB57677DCD3B2289A",
- "section_salt": "1730E6F86D0561262F4E315CBAFF7A97"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0E7BD813499926A0801C92B1929A3591",
- "aes_key": "CF5EAFF5A6CF1C2D8D38957F9E572031",
- "data_elements": [],
- "encoded_section": "37901304FF4DE46CD91B9856A4E7F1BBD4C17391100006366EBDDDB9BDC2F6571EB0EE6D56079002C75CC331866205C21DC58413AEA40526",
- "identity_type": "trusted",
- "iv": "04A19C41665D6BEB5815BFFC82D2F20F",
- "key_seed": "A2C54EBB8A466BDCC870DC0F024B654CDF6065B7982FF161DB4309726E8A9FEA",
- "metadata_key": "40D555232C844D0DB6AC3D8B67C2106C",
- "section_mic_hmac_key": "1B5B2EA645019085A538706A3639AFB2EF7F9DCE0262A9D156DE539C5887A246",
- "section_salt": "06366EBDDDB9BDC2F6571EB0EE6D5607"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A904A75B1FE8745F8A7487D6A1F266C4",
- "aes_key": "299B6E8D83C5F4C5FA5D7191776D5B74",
- "data_elements": [
- {
- "contents": "9D8ACA4EEE438F77F1ECF161C93E79C2",
- "de_type": 25
- }
- ],
- "encoded_section": "4990138B48C8DA765DA321BF9E7F74E018BCCD911000D5DCA899C05920FBA96B57FD6BC22BA29004E9045654EA86C9EFF8533142B7EF6AA31D947E6A37AA8BEAF9C4072DFDA603495A11",
- "identity_type": "provisioned",
- "iv": "F7C11436DE1634CB790BFEFAE15A83E7",
- "key_seed": "C2DE50F20E7A123F3221A92B1BDAE0BCC707FC399081324F41A2CD10D6E9DB19",
- "metadata_key": "2561C501E52AD7DDDD24E5578A2BD779",
- "section_mic_hmac_key": "510E4C8F9ED86CCDF0EB2F6E1282A8AD8087431F380602848EFAD4FA30A46662",
- "section_salt": "D5DCA899C05920FBA96B57FD6BC22BA2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A9E993AA4BC248E9A7B18624A78A94D",
- "aes_key": "0CF2C9FE3C3CD3B9A51293022090179F",
- "data_elements": [],
- "encoded_section": "37901393A3A8C7855ACB50AB3802D631C9C1F191100049DD85316190F271FC5BB2F620EEF235900225DD3667C9BD35154CD7B85A46923769",
- "identity_type": "trusted",
- "iv": "C3A5CDB16311D0A0FD03C473522159EF",
- "key_seed": "213E324AD5D67474CB40E6F49657F14EE29D80CFEDC37794DEAE1485807056AB",
- "metadata_key": "8B87195CD4A305E6383792D307FA7002",
- "section_mic_hmac_key": "4826260A12292DE75684A3CC1020AC5F7D8F469BF7B7EFC3A9351FC22BAD1CC1",
- "section_salt": "49DD85316190F271FC5BB2F620EEF235"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9B07AE29D7E24466EDAB0C5C73C14BDC",
- "aes_key": "07C40F75E92319B0204F538597F215D2",
- "data_elements": [
- {
- "contents": "F22339BFB847E90ED663BF729597FA326FA5F62AEF5F6C5A9FB3",
- "de_type": 403
- }
- ],
- "encoded_section": "549013564A1558904D7ECE81BCD9C42924A30591100005233215A686F5A39C58599759C1A43F900274A22947028C3BB7FAE0C8534773058C000D1C97B23B36A2670BDC8F618CEB1AFF283597F687C9112D84AA87A2",
- "identity_type": "trusted",
- "iv": "FA40033D2CD29E29AD8C494507B1612F",
- "key_seed": "F9D1973B9579CAA560918B5AEBFF76FA48AD3DC1E0051569330F4D44F2998A0D",
- "metadata_key": "AFB9AF8982A61787B90548314BAB69BA",
- "section_mic_hmac_key": "AE7047E264D302914C648144850D03551C69C6F92EC92263B0942F4115DDD4E4",
- "section_salt": "05233215A686F5A39C58599759C1A43F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AA66A68B0A3E886BD9F44096E51B4D5E",
- "aes_key": "316B88C5751E2FCD16B56AD488855D6F",
- "data_elements": [
- {
- "contents": "3C10A90C59A5B3AB5B927DC7AE03D4A0EFC634808E12A7AD40465EBCB5",
- "de_type": 483
- },
- {
- "contents": "F8A58360070B908E24356B895258022AADEEE54B6ACA714AFCF7C349",
- "de_type": 88
- },
- {
- "contents": "A082",
- "de_type": 230
- },
- {
- "contents": "2E",
- "de_type": 484
- },
- {
- "contents": "67B2DDE6",
- "de_type": 116
- }
- ],
- "encoded_section": "849013BCCCC132898E376863C442E9D8411187911000FB535FD638820271787F1073F7886A1790020977D491E02CBE4C40A898A2B0132274D0213C6922DC3C44998456DEAD435761A0368FBC64137FFF54A12F6620BE0F06E71D2BBAF4317948F67907E841EEDE7DBEEC5EA81AF57D7A9C69390865382019406815C5CC1A747EC60A74FCDD",
- "identity_type": "trusted",
- "iv": "3D7C449B089A03FEC65839104E037743",
- "key_seed": "6C82B15F2C059B5835E16ABFD28FEAF239E1A6E57AAD960CB852488196620D8D",
- "metadata_key": "9955C2F5670EF9CB149A40EAC4A3A3E1",
- "section_mic_hmac_key": "B19CA117C40072B06E08437F1DD8F48ED95C857460627636E99E04D3958F5E87",
- "section_salt": "FB535FD638820271787F1073F7886A17"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8C90321F97287B8A091727E2083D892D",
- "aes_key": "409C8416E73CDE13637F2E461F74A4BB",
- "data_elements": [
- {
- "contents": "BF7419DB336DB433E3",
- "de_type": 71
- },
- {
- "contents": "C7437F5427AF382361526C55B748240F486BECD95871",
- "de_type": 173
- },
- {
- "contents": "FB6A6EDF9FDB3F",
- "de_type": 778
- }
- ],
- "encoded_section": "6590135BF61E4E7A9A3C8B73569D2C23DE591C9110009759D1DB407678D65A146AFD04322D7A9002915E8088FE74A7EA709194BB7E82B3CA9D4A67118CB3CEB441029EA23771ED3FB2B5F2077913AB93D66731AD972BA9B6DFBFE8420AC29D36AD7619E8741F",
- "identity_type": "trusted",
- "iv": "48F689048B5CA464B88E0C399ED506A0",
- "key_seed": "FF7801A75633E88D16C9DA1732FDDD7662C9B1F484E904B53C1171069A0C25C5",
- "metadata_key": "C34841270E8866200C48012EA3CAD332",
- "section_mic_hmac_key": "B393831A2B040BDFC47CE74F8192998613BA5874343AEF5241B6914809AEA3AF",
- "section_salt": "9759D1DB407678D65A146AFD04322D7A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4680C0AB3A162A977F1C57FD6ADD5D6F",
- "aes_key": "ABD9FDE4027238879ACC0E31B1DC8A2F",
- "data_elements": [
- {
- "contents": "2CAB91011DE905C17B63F3ADDAC747F301C0775F1B06256F0DEF",
- "de_type": 580
- },
- {
- "contents": "98C4592D01DE564D0360A35C983D16A9200FBD625394BCB770FE927F",
- "de_type": 345
- },
- {
- "contents": "AC22AE18E6DFF87F2441616A3CCFEA17DB0262E00C5A",
- "de_type": 116
- },
- {
- "contents": "5AF4697ECF2E9560DAC164049C4C39C08E8038E8C7C5111D096737FE12",
- "de_type": 505
- }
- ],
- "encoded_section": "AB9013A9E3A860FA238886DFF136BAC79FAE34911000D56769B70F704174E61314E11917885090011AAB5050921F7F0C7EA625DF749AD07909D6B5200976E5F635FA2BFDB181F4D0FA37891826DF9F37580457EB33017A35964559778C9EC2839033159CA8426821731FE0798DAD92825ADF33234AD09F3133A6DB08F90A87FAF7ADC7D149EC4F65D29E5E8C677DA82642B290E287C48D6DD8DC76B1EDB530DAAC4F1BED596F2FAE1C5800D2",
- "identity_type": "private",
- "iv": "D88E5CD358B6FDE88C0BDA86B4C07FA9",
- "key_seed": "FBE039E8BE5927062F30F03F84D8C8F3EA8405E02AD071A5464764457B2CA67D",
- "metadata_key": "8B6C89F2D5ACB0DD38EB8969A8AFCEA7",
- "section_mic_hmac_key": "FB915D2EAC4E6D75ACA0FFF189B2B4CA9092970C105D455A9850B9D492DD8322",
- "section_salt": "D56769B70F704174E61314E119178850"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "99EA2AB3143DE296D87275E3796EA726",
- "aes_key": "B5369D466D6D66216E050B46C9626E9F",
- "data_elements": [],
- "encoded_section": "3790133258DA52075DC6CF650B3F7487D0991A9110002174376D9188577E3AD67895F40932219001E35CAFE972108A18170DCC16E8EC167A",
- "identity_type": "private",
- "iv": "620B7155C2DACCD4E172A0948B739392",
- "key_seed": "4963C0F1DC3A169ED67E6D81873F3D8AB7C56776FEE18E8E24B227951D98F67B",
- "metadata_key": "8AC856F31EDAD3C1D3B3ABFE13C69367",
- "section_mic_hmac_key": "11EF3FB260DA29B8A761F75D3D1DD5258FF416466FEDEF1498754AD7B4F8F3FC",
- "section_salt": "2174376D9188577E3AD67895F4093221"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6EFE58B2D4AFF119286E71653FFAFF55",
- "aes_key": "1827305AC9AACA2A8BB69F7C721D9AEE",
- "data_elements": [
- {
- "contents": "A51A7BFB530482EE1A59FC50F9A29741189B68A6AE939F",
- "de_type": 549
- },
- {
- "contents": "6B5F83744DDE1AA1C365C2480782B682866505D7549709",
- "de_type": 717
- }
- ],
- "encoded_section": "6B901339002EA6193FAD09FDF604C4E349E59E911000699CF720707E6FA5CE226F88AF8BAFED9001E27EA2E4CCD2461B944DCEB37E4B4B63B5F711F1A9C5DCF9A41A192CA9C5ADB735391DD0443C3C955489CF2AD75226E8EA1357595655BDB3E3601E7B33E5D8066B3F37A7",
- "identity_type": "private",
- "iv": "D364E25A638A624590BE1FA2F096594D",
- "key_seed": "B5E64F3EEAB9749EBA831D592F1E9FC5AB925C3C5E0CEA6E129C6B8B8B4C342D",
- "metadata_key": "5027B1E2C7F8CB8A2D11ED67C651EE3E",
- "section_mic_hmac_key": "92BC5538046351A15ECC14E24E3982932E910A143E5D28F9DBB38340FA03DCF1",
- "section_salt": "699CF720707E6FA5CE226F88AF8BAFED"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1BCD64B4EED1893C32BEF93DD9C971B3",
- "aes_key": "DF5A125BB90A2D17FBEDF9B7C989D191",
- "data_elements": [
- {
- "contents": "E8F6BC0AA73516D2AB139F6FB8C9E48BB6F580EB70D3AC91",
- "de_type": 87
- }
- ],
- "encoded_section": "519013835800D943EF3DC1B88575BC5477D0B5911000B7CFA8B2DB92728DA2812D9C0EDCD07590012BBEF78BFE3208F7DDF21AF44FF0DD82D580026F9F770A5E9F40C02C24C2E36456528561D0009C2B26E6",
- "identity_type": "private",
- "iv": "919E1A3794638BF621ECFA33E8A6DF57",
- "key_seed": "03678FFD5CBA3537E25A891FAA50484AC0AB58A7D035D8DBBCB351D8643BB57A",
- "metadata_key": "D2D13AC88CAB6E55984166209D685D96",
- "section_mic_hmac_key": "2E0D2D30096D2F381F6C14F8393BC8DF670B3E975FA2BC937C10976F47BA5CFA",
- "section_salt": "B7CFA8B2DB92728DA2812D9C0EDCD075"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "57CAA17E3435CEE5F8CDDD11F8C71927",
- "aes_key": "FB555F776983D6EF70245A2A74330862",
- "data_elements": [
- {
- "contents": "4D3378D9DAC41CEEB8BB45129747FCCCB813B17E1E046C319A6A",
- "de_type": 687
- }
- ],
- "encoded_section": "5490135808863DB438BC813BB23FF000567C7F91100040EB6E953C154ED8BA7B70AF72AA84D290048B21A3E3351576DD8C0DF85AA924B4F0CD3BE49C8844E49ED2F1F4852480C165BA80DEB502D0BBFDABB448FD07",
- "identity_type": "provisioned",
- "iv": "122941F68AA7A85356610AB70E8F7347",
- "key_seed": "77BAB0D78ABC0316711301212D5429493421B2F32FD219C784512871C37891E1",
- "metadata_key": "55E20264C236C78308649B3A717CDF5D",
- "section_mic_hmac_key": "9299E65289E576D14465C3782E08EDFA71F7F0C4B96DF5D9A027A20C09D44F32",
- "section_salt": "40EB6E953C154ED8BA7B70AF72AA84D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "918EC773233875D9A8F95ECBAD0F1FDC",
- "aes_key": "9C727238CA3610D54D119E718CD06BBF",
- "data_elements": [
- {
- "contents": "62F33A8DC96064763369",
- "de_type": 146
- },
- {
- "contents": "692DB5463436975E424A40014D6B7453611B22431310",
- "de_type": 87
- },
- {
- "contents": "36EC94C156296D1A90",
- "de_type": 121
- },
- {
- "contents": "9F399BC4",
- "de_type": 102
- }
- ],
- "encoded_section": "6D9013C4073FE83CA7F9FEEDE4564CA14A7D3A9110008AA71BBFDDBD5BDFE769C6AA971E20F690020F902663091D7F10A3326C4D6B7AE0CE21D0C7958477125C301C53AA265F8A0B76B38BE77C63049ACD8FABDFE029010F95D25F182016A122C041FDCFD2A36878BD53F608C7C1",
- "identity_type": "trusted",
- "iv": "8161FE7F58DD7CB51C94E893C3E77E37",
- "key_seed": "7689440ED67C78632C580EB736AD5409C5B70833835188FCFEF762CA0ABA64C7",
- "metadata_key": "CEE36091D48B6A6933349BAAEDB06D3D",
- "section_mic_hmac_key": "A6C8112D9A7DD48D4AF3531A38C820AC7FD247231F4F433E8B11238B7EA5156A",
- "section_salt": "8AA71BBFDDBD5BDFE769C6AA971E20F6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DB711D39B427852337FA71D91CF55BC5",
- "aes_key": "A81B8FC02A525DCB4C2ED8CDDF285900",
- "data_elements": [],
- "encoded_section": "379013129BADABE83AB0218BA8A7AFA43684A19110009DE7738771FABFE6960860DEB9DBC4879004259342BAC650F527B4A5A74597FC93FE",
- "identity_type": "provisioned",
- "iv": "B504D33DE1BB8832C1EE8AC54297D743",
- "key_seed": "ED24BBB04F28035C8765F7FCC5F1453E85D4781DD1640F498A9619D56ADFCA55",
- "metadata_key": "16E55700FF5D1BD29430088C8A23C42F",
- "section_mic_hmac_key": "10B0CAA2CE15EDEE6A19C905EEDBC6F8C082C77AE22A83DAE646614B1AED0493",
- "section_salt": "9DE7738771FABFE6960860DEB9DBC487"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "15ABF702A2921EC4DA6280535C861765",
- "aes_key": "22CAA40B3717F99A3FA4B2A1E7055588",
- "data_elements": [
- {
- "contents": "6064E54E",
- "de_type": 130
- },
- {
- "contents": "B513C3896B41F8954528634301C2D8",
- "de_type": 319
- },
- {
- "contents": "1337431F91509A4888A9F8853595A5546D1256650020D6BF151A0763D534",
- "de_type": 276
- }
- ],
- "encoded_section": "7190136F47402C06F69E2F7BF935775D518D1191100026443E2A7BB7B32D564103572A0CAE959002A855F03507F04308929B2E733D645113B958A3DEB579A55DEF36E35F3B62FA005BB752019A3556269FB98D95644DDDD59CE945E8E9C5B9CEA3057392DFC1C1B818EE361431C2E0C6E3C8",
- "identity_type": "trusted",
- "iv": "253F2EF0C8214125C7A3E1D209E540E7",
- "key_seed": "F82F3CE7CC922B30FE16EACE6B79D0BC9ECA63849C981B97FA704A23CF9AC8B7",
- "metadata_key": "63DA0B806E8F3FDADACCFC2312159E4D",
- "section_mic_hmac_key": "B3B26A8FD11B78B0AE02C2F6C0B7196539CB880B46059BADF89752BB504CB95A",
- "section_salt": "26443E2A7BB7B32D564103572A0CAE95"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1CABC21DB1C0C240529AC3ADB636F5D1",
- "aes_key": "2F97C4674DF327D354244B462E131D1E",
- "data_elements": [
- {
- "contents": "3A8A8E0EA56B61160E614B6125C829",
- "de_type": 828
- },
- {
- "contents": "40A3AA30E70403F1B8CFD4D830",
- "de_type": 267
- },
- {
- "contents": "5D51B6",
- "de_type": 335
- },
- {
- "contents": "81D0363DE104",
- "de_type": 110
- }
- ],
- "encoded_section": "679013332ED64969A6D47284A3DEEDAFC7DAE19110009301091AC070334AF39D4CABBE2E483C90044E44E6E6C66C28D442F35A77230D9B10B07ED47776CC060B127913850E739C8FBEB68F9296788975DA87970ABB72936522DD38FA9093C98EF5E501B3D30D1658",
- "identity_type": "provisioned",
- "iv": "18685A3BE2ECB910DD222B30E86E51E6",
- "key_seed": "DBFFECF4EF406EA2C2EBF09122890602CF3F8C1423E72694F437ABE9A82A33B6",
- "metadata_key": "7AC9AC9E384723D87516CC941478E97F",
- "section_mic_hmac_key": "C30AD5035C7291B24097C6E6E34CDE7922C49A0850A2BB51A902C9F8428DC220",
- "section_salt": "9301091AC070334AF39D4CABBE2E483C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "18E66C02947BCD1286672E1283BDB6BC",
- "aes_key": "1578A1F187076139B90136E77F5325B4",
- "data_elements": [
- {
- "contents": "2C4D33C31E849376984F5DE450BE7BB9",
- "de_type": 838
- },
- {
- "contents": "73EED2D77B81D9148ACB2086BF5CA2076E8AB12A8E415E9063E3F7",
- "de_type": 870
- },
- {
- "contents": "4C5B",
- "de_type": 222
- },
- {
- "contents": "993987B210C00D832A84D6C2",
- "de_type": 786
- },
- {
- "contents": "0B292F6A1F2C4E7DA470",
- "de_type": 158
- }
- ],
- "encoded_section": "899013A4E785DB6CFC84659689C9721A0681C59110006A298D4CFE290BC52CE0399AEA97C85290042D4C1056B7D2A834275E94A129445B1D230D19CC4DFEB321DED2C89D5565F5D2F3FBE7296E0A8B1391D0C17CB73871CA9DEEE1E1856DED3B5E4944B5473963DF10C107D0260FB71335C4C6CA0132465C56393F7E2B317ED72CEFD4FD4E4C4EF7F025",
- "identity_type": "provisioned",
- "iv": "D00CCF4974F89E0EA8E4AEA7B8B6A4E4",
- "key_seed": "3EEEC66412789D30B844E8BAB2DD02F80DA4B193058C1F094B7F00C1CAEBFE31",
- "metadata_key": "D2BD10BCC3E0A1341A1E5CB881FC46CA",
- "section_mic_hmac_key": "07783CFD28D58E0E7E7A58A427BD526F8A23CCDB6D476C893A6577BFC8ABB9D9",
- "section_salt": "6A298D4CFE290BC52CE0399AEA97C852"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EEA784B50903BB1F3867A3309D3BB38A",
- "aes_key": "F1584E98535678BA37B4B88C1A1DAD6B",
- "data_elements": [
- {
- "contents": "B065975A23",
- "de_type": 776
- },
- {
- "contents": "97D0D8C01773B81CBB85D4654D48F679E3",
- "de_type": 64
- }
- ],
- "encoded_section": "529013FAB685D2A4E8D074AF6CC499253657A09110005BCF7C32DB1AB7213B08D65BEB96C64090043C30F732BA2C311688F57CCCEEBF13239AA81DFC7AB291C3C348B1FC0188CD137DC2199FED907A60AE4E89",
- "identity_type": "provisioned",
- "iv": "2417AC781347135F7C4AC5E3FF5610D3",
- "key_seed": "A4C8D1AE27A88EE937949D1DDE2C4812AA80B3B1325E85057DBAB45B89890E92",
- "metadata_key": "98A2EF99CDCF4366703D6CA384F606B4",
- "section_mic_hmac_key": "818E8767FA4D512C0A422AAC5298D9E6C492AA82728538F3E8563D48113667D9",
- "section_salt": "5BCF7C32DB1AB7213B08D65BEB96C640"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9FFCDC2887E86DD97B1CD7CC7C926E61",
- "aes_key": "12C10DFCA2552603C1FDE479C2F70930",
- "data_elements": [
- {
- "contents": "43D56D17A8F5E03D91BCF4E8C3701AAC",
- "de_type": 233
- },
- {
- "contents": "DD441A6FD3736A718759ADCECDE1",
- "de_type": 388
- },
- {
- "contents": "FE2437CBB6710097203765E501C075A7BB84D0DE6BD7",
- "de_type": 319
- }
- ],
- "encoded_section": "749013BD1B29276423429D5C32272760B00E74911000A69871C2D73E23EF30656C35210BC89190029822466D8A6CB94523F1F44D254C56B91C690540A37F233A1AE710FC4543D795BA11ECDC085FDB87B25BAE832933A76BFED60786C41FC80AB6303E572681F54EDF82F395336E6B5BB2F525D963",
- "identity_type": "trusted",
- "iv": "B7C4C6B5D46933E315576FB563020BF5",
- "key_seed": "6F549E0C976D9C561F18C3B7E2A11E1DE9CDBB3F5D961C8D897C4D62D7237D5D",
- "metadata_key": "3CE3E026CFBC07F235AE24EA5D5488C3",
- "section_mic_hmac_key": "D669B98BC3C5408BCBDFCF32F721B5958F42F8D0121B4CF506D250F7E9193564",
- "section_salt": "A69871C2D73E23EF30656C35210BC891"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "18FB5256D82A557D54A999C1A04077D5",
- "aes_key": "BCB3BA61D328D7EFB9438222D888AF99",
- "data_elements": [
- {
- "contents": "AF5BC7C723B9708DE8AE0F997685FFC56598015F233DBF1E",
- "de_type": 978
- }
- ],
- "encoded_section": "529013AFEA8B9B0A8FF8674527A31C8D5513D191100056E5750F6C377F9375156905EB02B0FA900403BC01343DA39F80CAB2AF188CC4D9EECFABE9CDBF75E32FA15F5BEC5AC24C1BF393C1C245415B38FA5C82",
- "identity_type": "provisioned",
- "iv": "C2337185C26056CE4441225DFE7060CE",
- "key_seed": "3E54A3C0661B47A2B56B69385D57F404B59CDAF04806F5CD5E08C42AD1798316",
- "metadata_key": "57D1F6D82B6598012DC38DF4102E9D49",
- "section_mic_hmac_key": "02D21B6BAFC774F8225F653E3FA74CA072DEE643C20AF9AD115C0F656F0A8F7C",
- "section_salt": "56E5750F6C377F9375156905EB02B0FA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3534341126EEDD02268A7CF907032A29",
- "aes_key": "941672BC6294A5FC9E6AC03BAEE156A5",
- "data_elements": [
- {
- "contents": "ECE25FB7FE3EDCEEE8",
- "de_type": 642
- },
- {
- "contents": "CAB4AF",
- "de_type": 177
- },
- {
- "contents": "FB38F904FB0A925E59AB186C824D1D121A",
- "de_type": 81
- },
- {
- "contents": "32E132145BF7683C7095FD150387",
- "de_type": 990
- },
- {
- "contents": "0C6369F4074A8980786BB4",
- "de_type": 338
- }
- ],
- "encoded_section": "7B901388065746E077EC8D797B0F0FF690A0F69110008B5B67D02A2EDE80F9E163D2BBC2C82E90049D2356AD8289D2ACBD6BDFD6AD70D136CA59E15E92B5D2D9AD3D1EA16E97828F9C722C6F32937EE2CFE7E3C922E9A969BFB73BD10F1F6E83AA574DF3B638EA680838FF779235BF394F6ADE59208709F6FCA13DA6",
- "identity_type": "provisioned",
- "iv": "17F834E108A1E530E9C6DC04CE6B4658",
- "key_seed": "DC2133269CF982E3FA4D23A8A3D7ED820B8C708C44037FE6D84DDEC982B4C971",
- "metadata_key": "F785519027C49D46E817F41766D90C39",
- "section_mic_hmac_key": "DAC78E12E6374EAA18B9DAA80A771A75969D0C6C343200000C0C32281796A829",
- "section_salt": "8B5B67D02A2EDE80F9E163D2BBC2C82E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9A85F942FCF43F69C7574D1CD2A0D0F2",
- "aes_key": "0E0534CB941D842104C642B8A1F18A70",
- "data_elements": [
- {
- "contents": "DBD9D02102C6ABFEE1E045959BD444",
- "de_type": 556
- },
- {
- "contents": "CF6DFA9CC175A07C269B84B190BCA7A1",
- "de_type": 330
- },
- {
- "contents": "319BE819",
- "de_type": 775
- },
- {
- "contents": "8F6E2B78FCAF4B5CE5D246F94621ABC50DB3B19C7B98D570C85818B8",
- "de_type": 958
- }
- ],
- "encoded_section": "829013E659F7589D9F22BF2F1E35BF3E6978F59110004BC4FDBDA1E0D06770F14BF61545244B900233E4203AAB4515AC6A71CC634449CFC1DFD064491ADD2C14E9E378C9E2098D434177D5549DA4D0EB463B520545ACD12D4805CEE4B52D218CEB5667F770833B5B64EDE4EFB737ABCBE830B68090E53965ACB5242A660E83CB82F558",
- "identity_type": "trusted",
- "iv": "DA6BF37D65F973CA1A00522E49BC32C9",
- "key_seed": "54C796907B5F73DA86CF7C183276E8FB928EC324D625DD57859A986635668117",
- "metadata_key": "ECD687DD1F9FF1CD096D76E6034F6F9A",
- "section_mic_hmac_key": "6DADAB8D9E47EB85161A5159FE728B9F74842B24584FF530D98584C0F6B265B7",
- "section_salt": "4BC4FDBDA1E0D06770F14BF61545244B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9A5D74B1191EDFD5C9FFB3693DED74D9",
- "aes_key": "C86DB754655DE997EC3B092B814A9D08",
- "data_elements": [
- {
- "contents": "B24E8C398A097EB6DB8070",
- "de_type": 122
- },
- {
- "contents": "FF8934664FEA786A",
- "de_type": 959
- },
- {
- "contents": "0496A8",
- "de_type": 491
- },
- {
- "contents": "290027D82CF848264ABC51B38B9F50301A2BE901B1865A",
- "de_type": 917
- },
- {
- "contents": "BB57846504B148C0D3D06CB420F09EDC69",
- "de_type": 518
- }
- ],
- "encoded_section": "8390130089ED0335A7EFC59F0CF825677AF8629110003BC66A7E83C34665E8148E8F405DD6B19004D3446E2F9CCA273520BEE5910B42717AC24D55486EF1D4496F38B97F29F7ABB26ACB299A32164F4FBBD64DBD128650D6C4487B681812C9B810D559F1DF7A2E619A9A2486EC27B55F48A49DB4D3A5EA3BC486BD5359EA31CC1E1E101B",
- "identity_type": "provisioned",
- "iv": "9FCCBD881DDFB881671D7C7F7F1FB16A",
- "key_seed": "48C3FB983526200C3940D06E401D1E447353B058DD3C4A1F518B9CD8F045B31C",
- "metadata_key": "449A2DCCC6E26F9AFBB91071ABE75193",
- "section_mic_hmac_key": "F57B9C5889C41E7D404CA50D39992A03DDD9D7348FBF57C9A8B5867A01219571",
- "section_salt": "3BC66A7E83C34665E8148E8F405DD6B1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B9B184BAC61B4F93DFC9C3067F371D17",
- "aes_key": "CF403FA1E7BE86B53AF114A1B0D9C426",
- "data_elements": [
- {
- "contents": "B051C4367A69BF4878",
- "de_type": 528
- }
- ],
- "encoded_section": "439013E664890A3457FCFD7EEA5AB752B14D2991100097E8397B9ED7E8E71313D8D606145444900402DC632F0AFED33FC49DCC6693C993BBF5040BCE4A4D0900C1076958",
- "identity_type": "provisioned",
- "iv": "F46A38E8A66A6D683FC6B94C6C04640E",
- "key_seed": "BC6F5B315462737EC913FC8716950B18BDAC5D2D7CE7B62E987736D9C8A51D00",
- "metadata_key": "4132EBD8503194CDFFA3DB4A9CF4E9F5",
- "section_mic_hmac_key": "77646D5AFD46271C0B3E18910808CBAB5F5B196B0C7F4363A719C58FFDA9863C",
- "section_salt": "97E8397B9ED7E8E71313D8D606145444"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E5934BA045805A7421A56BA0D4CB8F9B",
- "aes_key": "888368B6CCCA3B33D5A6FA3CFDB8D12B",
- "data_elements": [
- {
- "contents": "D6CA9F03DBF64CA2B9439E2AF8672702F81E82B4",
- "de_type": 767
- },
- {
- "contents": "6937CEC064BCA1095885872E",
- "de_type": 993
- },
- {
- "contents": "746A7794E1520BF389F1",
- "de_type": 968
- },
- {
- "contents": "DEEE6D20B58534F9C1BA4D746648CE",
- "de_type": 645
- },
- {
- "contents": "",
- "de_type": 190
- }
- ],
- "encoded_section": "7F9013ADC90DB7AB8EC54F721AC09BF0A8E89E9110001FFA28EE4F6B26C093F26CD48274E4749004CBC23042E5B3B7E471C006FF749F88E3212AD450377C64170A389DE0A1D02C4F37AF61AE5374AC0B38C772117A1AC53D6C19CE24488A51C292B903548563A6F09ADE9742B311215D27EA48C7EBFD970179AF4C509A7A528B",
- "identity_type": "provisioned",
- "iv": "C666D37611C02A62008EC134E0043096",
- "key_seed": "065262498762C06838CB80F57356EF74A34649A8B256444C31D0EAB095B48038",
- "metadata_key": "424141E8B96A7A3B35DF2F27CBE572AD",
- "section_mic_hmac_key": "E4AC63DB35CBEB6526D701F511D6F93C0EAC5AAEEE8E15511F560952D60BE443",
- "section_salt": "1FFA28EE4F6B26C093F26CD48274E474"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8B09B5CC8D452AED21A27051C4212C03",
- "aes_key": "20CB5F8E502A5C231631433D3EA74C3A",
- "data_elements": [
- {
- "contents": "FDFA36FDC1E841BE8CB8CF9F786927EB3C875ACA8782A40F64CF87",
- "de_type": 994
- },
- {
- "contents": "C217151453818FA83E",
- "de_type": 302
- },
- {
- "contents": "CEC2831E815B7741DA4AE1B430191A52A9AB542623796986904825A9F29F",
- "de_type": 375
- },
- {
- "contents": "61106F238FAC929705D579362ED8F0654FFBECB7B3",
- "de_type": 882
- }
- ],
- "encoded_section": "9A9013AD9DD460657404924554D5ABA137FCE1911000FC40CDC9F0268A4359DAAD8CC738FBAE9001B4A4E4F36C74E4630E303CF82CC7389673E052C09E190A6EE06D066956B4DE265F30D6BB6A1FFB90C7B0AB0E988DBCD6890AD54EDB925700587ED26438093EC7522F59C4D96DC3A05D57BED63FC0FDDE6921918B0401ADF02DE8A5015FD893589AD840C2D9A883970D73D4E78252E108E952CC",
- "identity_type": "private",
- "iv": "3AF0046E60E52B687DA9B405B04EE4C9",
- "key_seed": "187A06076F56E434B68E0198E97AD9A3DEE2B8330921232770A7081304A5A197",
- "metadata_key": "20D24EE641F15A53359F2173BF22D6E7",
- "section_mic_hmac_key": "92281B4C5EF9136F18CE22F5B052F0782AC51DE3872A56AEA4BB5EA9BD6F02F4",
- "section_salt": "FC40CDC9F0268A4359DAAD8CC738FBAE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1980BDCD7189D278FDCABE4B5A1606F0",
- "aes_key": "E6AC160A241743BD2F26D4A0613D370B",
- "data_elements": [],
- "encoded_section": "379013EE631DD1C657D166AC8350CB989079D2911000452D2E63C89D362EE8D6B4C81675EF5D90012FE7D7BE11D828247000351610FCA587",
- "identity_type": "private",
- "iv": "F86E064E37573CE05667B8CF12753CB1",
- "key_seed": "80BFAC30C797B1AD69B178398369D8DEE740D9020AAFE9AA25A7E30E82C6150F",
- "metadata_key": "C4D4EEDFDA9C4A7F8A605B6AC7BE644E",
- "section_mic_hmac_key": "60CA863FF6016A0BB84CA68A347B1E20B94CED09D9D0FF8F8AACD72CA9D5AA06",
- "section_salt": "452D2E63C89D362EE8D6B4C81675EF5D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CE3637F7C9AD29DC4903BBCE71B3EDF7",
- "aes_key": "283D03C921033734F5FC72BDBF2CC23B",
- "data_elements": [
- {
- "contents": "B9D0AAEF",
- "de_type": 758
- },
- {
- "contents": "13E90EA2DE8A3B96E136541945E1D14A54D07038940ABB3FAD225AF3",
- "de_type": 983
- }
- ],
- "encoded_section": "5D9013F16575E13C3E78AFED9CD58FA081D9DB9110000ED633E1509B9C35BB340C85E69F20409002CE471E855E16C0CD3B96A38178D8ECDA75CF3128C160846194A450B3991578950E8CCD5021E3EF114EB46E4E412602DE3E762B0CE436",
- "identity_type": "trusted",
- "iv": "4A371511BC88F24D6FCADCE37088F34B",
- "key_seed": "FE21995688DB34483CDE840FD00F9A96CC425AB8E6775500C108430EC0E823D8",
- "metadata_key": "64C0230DC2C5593746B2B0CE14AF63E3",
- "section_mic_hmac_key": "72108A75932EE23C133B987C0E818D81822E004E67F1B47DE6F9C1DB088264DA",
- "section_salt": "0ED633E1509B9C35BB340C85E69F2040"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B162D1322B5D26249649CB969B4F8102",
- "aes_key": "E92585DAC5D7F4662EEA29655E50A4CE",
- "data_elements": [
- {
- "contents": "A9EFEEF17500ABA6053E234D49F9",
- "de_type": 176
- },
- {
- "contents": "29EF333A49CF43E20C253605AA083893D2",
- "de_type": 459
- },
- {
- "contents": "2FA4FB0EA60274A5CACFA47E4B",
- "de_type": 504
- },
- {
- "contents": "83A7CB21AA6B3A1923F7382E4FCBB313D3E7E61DAFAD3E7EEF32CB3EF93C",
- "de_type": 313
- }
- ],
- "encoded_section": "8D901309D5FE388C56BD4E5F6322943FC3A048911000F5C76DF48CEC6BD8CAE990AE8BE181C79001A92EE39ECD5870537FF134794D9F747F6DE78C4512B3F087F0637BCB1B7EE8A0539D82E806149FC2B0D7F76FE39D9C4D820F714CEA248E808605929CA89FDDFDAADFAF87CB1EB88690382E08185623C09585E5489C21B5941F607AEC56E2CC36DEF0244846A8",
- "identity_type": "private",
- "iv": "BB9EE514C99F0518104C87999D49A754",
- "key_seed": "AC4EC8D356CF255D5AE8B9FA0B792CEAFE7947F8559AF2723AC8B966579FC0DC",
- "metadata_key": "4576F651F9196F707DCE4E1F599D0783",
- "section_mic_hmac_key": "8BFCAD24C2D370096D0E954E9A3363C8C0B239729D5B0A45E9B093A6A377B2A9",
- "section_salt": "F5C76DF48CEC6BD8CAE990AE8BE181C7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5B297B4DEAA667E3D6FB370EC0BF95F3",
- "aes_key": "99F1560561D5A887142C3C55D312DD52",
- "data_elements": [
- {
- "contents": "5C2CE141B3E5A889599146",
- "de_type": 37
- },
- {
- "contents": "1848600B2D546BCFBBF6C7C8705D",
- "de_type": 192
- },
- {
- "contents": "57DC2206B48105B60FA3C8BBF187A500",
- "de_type": 487
- },
- {
- "contents": "7C3D131E2C31",
- "de_type": 195
- }
- ],
- "encoded_section": "7190131A58CC7F4415B7BF7472C0F89D5AC2E391100084075A84F9CB2D02F54F96F87F1A163E9004C6AEC8AE7B9D25088001CEC6C53AE2D4FC8FFA1615483B6AE2DE6FDA409B13F33028543707A88A02A2C462CB81AFFFC81B3655BD8D733A13F133BE4138D8DCBBFA21E7FD4B72CFB66E63",
- "identity_type": "provisioned",
- "iv": "8B28D0A8180C17783E7653EEBAC132BF",
- "key_seed": "577AD6CFCFE8E1C3ACBE1993BFAA7FA05F81EAC8AC1E83C7E0198DAEBA7FD1F4",
- "metadata_key": "73BB407DA49FC66BB9C315EA94EDF8BC",
- "section_mic_hmac_key": "995E2E8ED0F4F4C1CDC5D13DF3C903B149EBD84F41E4D088A801A8B9396EE8F3",
- "section_salt": "84075A84F9CB2D02F54F96F87F1A163E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA6DED68CF0959239D11427F74FE997B",
- "aes_key": "9FFFC08CB431531D60DBE654D099E048",
- "data_elements": [
- {
- "contents": "539C2665DD42B55FB0E9",
- "de_type": 658
- }
- ],
- "encoded_section": "449013ECAADB35F533CF451CBF0B38EC937432911000D32DB501E334CAB82F79520F3C892DB79004E7750EE5BDC44BF9BF13543DF92F315E25D7E54780C7A2623492AA0175",
- "identity_type": "provisioned",
- "iv": "023DD3C725AE97C27DC0788CC095B6E7",
- "key_seed": "9EE6A42100524DD1D112A596D5405581586D40BA87C77DD85F8A6AB92EB9E1FD",
- "metadata_key": "AA74890853C6C5BF4EAB72B38C5E2C2A",
- "section_mic_hmac_key": "3B6C00CF957CD21086DABBB8FE4042307ABFFDDECA6D3CEB512F81C1F133F6F1",
- "section_salt": "D32DB501E334CAB82F79520F3C892DB7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AAC3A533A7C2AB440C26A8183F71CE3F",
- "aes_key": "8B68336A07D6283B517488B995AABE65",
- "data_elements": [],
- "encoded_section": "379013954DFB4D6B1382D53F3D36B4521E1647911000C6ADAE90AF6B99E17D60C8613C5BA3F490044466909ED06184090A9DBCF69FDFF46F",
- "identity_type": "provisioned",
- "iv": "42DF51FB3C37AC171470D60D4E2F04CF",
- "key_seed": "7C3FB67838916AB0E4F7BF68FE8A28C509A2A15BB3240BC8AB6CC3F99F52705B",
- "metadata_key": "393F240A2C6F9EC4AFA756425A9CC2AF",
- "section_mic_hmac_key": "AFA33F6D9DACC54E13B4F5248468F614561745ED8A0F29CD0F2E430873D9CE2C",
- "section_salt": "C6ADAE90AF6B99E17D60C8613C5BA3F4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "81C6585DC0B3B9D152F79A23DB1C8882",
- "aes_key": "E97F5929B62C0A82220838B588728F26",
- "data_elements": [
- {
- "contents": "72B7",
- "de_type": 536
- },
- {
- "contents": "1DC3",
- "de_type": 937
- },
- {
- "contents": "97CA765CF7E2E2C48B42330799F54489C934EB912308FA958DD04703",
- "de_type": 387
- }
- ],
- "encoded_section": "60901338E7ADD6C6548D813C99134BA15D9A5D91100022EB17486F7CD2CBA6E39434537B2F57900207BFB512D4879502860E54B41669139A48DD0E42BDC66FDDF265ACA9CAA359F1E4CB1482A3D506646B21698F37317D0564F842CD44919FD767",
- "identity_type": "trusted",
- "iv": "BB11AC5F4D37033EC99BCF8E6779C7B7",
- "key_seed": "11F86BFFAA9B66C77616DD6B32C63A6C81C50541BE9EF6E04AF0F953895036B0",
- "metadata_key": "AC3C67CAA7794A04DD94CF515419466F",
- "section_mic_hmac_key": "60B2EB5CF45F6600ECEC676CD76A4604B744E166B5935BF4C5C750634AD081D5",
- "section_salt": "22EB17486F7CD2CBA6E39434537B2F57"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "00511EF933CA6DC0EEDCB94B38987087",
- "aes_key": "0ADAF776AF20958595ABCB87A10E984F",
- "data_elements": [
- {
- "contents": "1A464229DF04C31CCC08944B21D55EEBE9C1BE489B1790",
- "de_type": 339
- },
- {
- "contents": "BD56E1750AB74F38437A7EDD986E21",
- "de_type": 92
- },
- {
- "contents": "B0668FAA2F6BFDF67FD9033B8D0675680BC452D2FBD29D4F288B93C2",
- "de_type": 768
- },
- {
- "contents": "9E5C09A349090B3CF9B575821F0CE393462D",
- "de_type": 850
- },
- {
- "contents": "655C5910AD15C62A126D2FAF109A26",
- "de_type": 399
- }
- ],
- "encoded_section": "A890132778CBA5093DE49E4CDF829C83BBC8B0911000FED627BBA15D95068F43ACFDF42D2426900157609145B639C9C92C2A81A0717C11219DFCBCE7DD6B6A80146CA785EC92DE677C43AB269672AFF27FBFE8A4A34EA6E4DBD5C1A53E8836BC8149E27A59A449E6752025DD324A5FBEFE17DC2EB8C0CEFA651F949CA334A0E3FBF9657C5B0C8C9CC819BF2C85EE8BE5813819372E1308CEF54567F70B8F6534A008CE0D407ECDA3D9",
- "identity_type": "private",
- "iv": "EFB9C48ADED0FBA9B2F10E7799B1BC11",
- "key_seed": "05BA0D78A0AF7D0FC55A4B640C8573C74115E6BFB35CF849EC024CE0E5ABA91E",
- "metadata_key": "4D0EDEF4A062C6A83A925F727C997C68",
- "section_mic_hmac_key": "C3F3B8305FF694E5BE8EAAA0752CD8DA61D3E6BD544AE2DED8663F4B34ABF95E",
- "section_salt": "FED627BBA15D95068F43ACFDF42D2426"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95758969EAEFE0163C295B1733BEBDFD",
- "aes_key": "08B89985AB9371EE8A7C749FA10D7965",
- "data_elements": [
- {
- "contents": "42F3FAF94ED0FB40C070",
- "de_type": 906
- },
- {
- "contents": "2870FEE3B66905C1C865B578458847CAF0F8AF67",
- "de_type": 827
- },
- {
- "contents": "555387D04F9A2CCA92EE39E54408ED6F2E",
- "de_type": 767
- }
- ],
- "encoded_section": "6F901375D05E0E76CDDBB5ECC6637172CAA0FA911000A1939F4A327A3FE2596522A22DB6C5A59001E0EB6C5B53D04DC02C32041E4880E4D65D84151A34F27CA74E7005C9BB2CC12BA2B343395FE847997119EA78AB0C1AC5B3F643A538C4FDD3BDA97B1872BF596AF0B0A59832B2D648",
- "identity_type": "private",
- "iv": "2ECC3361C8C791708F4C7B8C39C15D79",
- "key_seed": "DA612AD55892DC4C53B80590D940929D72984DFF5A5F6F03DC23DF8E8533B512",
- "metadata_key": "B1CAB6C41D016206FB92AD7B4DDE8B4C",
- "section_mic_hmac_key": "3D75FC10EA014EA03A511D12A3001062354C69FD19910D31F7931635417D9350",
- "section_salt": "A1939F4A327A3FE2596522A22DB6C5A5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA6000111B7177C842D94B678C834DDF",
- "aes_key": "0FCEDA0332ACD49A195ABB867E6BAA1B",
- "data_elements": [
- {
- "contents": "CEABACE7D381A232FC75805204E7270B700D5B4FC2D8BD",
- "de_type": 672
- },
- {
- "contents": "9AD36A4438B590412E41CAD870CC8BA2CA27315D",
- "de_type": 178
- },
- {
- "contents": "CE20C944EC92910AA9878C",
- "de_type": 587
- }
- ],
- "encoded_section": "7690133D110BD2D3C885F07437DDE3630C5D7E911000A4E404D0D8DFCC6F1EADFCCFF09E925E9001F6AA807E5AB71B59EC053660E13A15739A1BEABDFAA147D3285CD42CC0AD05CC1541D234FDE1FE6F5B0387CB7421B3212218FB7135516304295DF97339562FABAAB5D3D86107F5F7E8BABF6D23DAEF",
- "identity_type": "private",
- "iv": "A9DCBFC679102BB70F88C434A62BCB58",
- "key_seed": "FB9B3394FA19B352B121F5176DC2BDE9DE6901F8A3C47AE297527EF13DF6061E",
- "metadata_key": "1B044AFCC875CC44C5305B79FFD030BD",
- "section_mic_hmac_key": "A9BEE21E360D0E27366461547D779FE698A82E16E40C2D20413DAC39E851C75A",
- "section_salt": "A4E404D0D8DFCC6F1EADFCCFF09E925E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EFB53470C08C0623EB392B698DA54733",
- "aes_key": "560C8CA057D94CF4EF794E192324F93D",
- "data_elements": [
- {
- "contents": "668992",
- "de_type": 643
- },
- {
- "contents": "13DA",
- "de_type": 684
- },
- {
- "contents": "0644943798483CDE51287D117570D6B1879BE0B677D86D7FDA9E502E",
- "de_type": 838
- },
- {
- "contents": "8DE3050FB50AEAFE8825211569FD59526395E0FE71F9464EFD0032D945F8",
- "de_type": 659
- },
- {
- "contents": "8CC01BB0BB481C4C355440B4A65D3611345B036268B913",
- "de_type": 578
- }
- ],
- "encoded_section": "9C90131E6B368314CBA81922DF93F3FB58882391100028EBFFEF24B6C89067BB31A550C043319001A26FBBE8A1AD2304583A63C804B269F163BCE88B8D89377B7CD26A0DBF6D331A12C84759AE583C7F7FEA4194BDDD77154DF89BA4B4E024E13E9AED6FA0B7FB27D467EA2A568B5C3324354AAD300CEB8C987E98E31234178DFD263E04027E4B8F0BC0EF53E5D77F45CBBA26B95E88D1036BA7BFCE96",
- "identity_type": "private",
- "iv": "F9F2984CE55D17978DA1F074305C9C96",
- "key_seed": "BF601538B31CFC67922FF6BF44150DF8DACE1485BC93284F4166B11EFAA5344F",
- "metadata_key": "5DFD83B4E657AA2BCD8A0373490573C5",
- "section_mic_hmac_key": "470CF61CF85A1249F42A5CB24EC08AAB431E1DF4EC0B0391751B313C36715ACF",
- "section_salt": "28EBFFEF24B6C89067BB31A550C04331"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AFAF84AACEF8881F848E7B85C7539880",
- "aes_key": "CBD54146C955B6C8F00BA1D38269EA98",
- "data_elements": [
- {
- "contents": "FECDB0E0EA56B7ACE68A83",
- "de_type": 120
- },
- {
- "contents": "0B733BA3",
- "de_type": 781
- }
- ],
- "encoded_section": "4B9013524EAED100DC3E32D41005234B543740911000EFBBAA34F6A5D2CCB39DFCF9C89714DF90025EDD541786FA33A58E7132F55209DBEF9242C353BB72CDD1550FF0026E18AC166956E6FF",
- "identity_type": "trusted",
- "iv": "413D670613BA8E8838386AA10F29C898",
- "key_seed": "91165D9E35460BAE2E80856F736CA95A1CB0DDBDE92E6F55B2B0592E976A8030",
- "metadata_key": "3999C8B72B85830A4F46CC24C0CEFEC0",
- "section_mic_hmac_key": "3B4E66850E50DDB2376FD26E0B6506F2144DE3E4C9FF0F0ED3A2A95AA2B2CE4D",
- "section_salt": "EFBBAA34F6A5D2CCB39DFCF9C89714DF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "437431D701ECBD564CE91F04AD002790",
- "aes_key": "B7DBA314333C96D6E7420CC20C3BDB7D",
- "data_elements": [
- {
- "contents": "08F45E72C77E4F763109",
- "de_type": 522
- },
- {
- "contents": "4BCFD9294127CEFA59C6E3B17F5F",
- "de_type": 246
- },
- {
- "contents": "A0AA932C07DC7D06E224D95EC31C4AEA2BEC4AD37A66DD",
- "de_type": 459
- }
- ],
- "encoded_section": "6F9013074F186DD7876DD0F5374206C65F523E91100050205EFE1CBB39FD3572899E4A9FAADB9004544DE8447ED37AB18AE43746E06D5331A4102428F2EE7CFF71482BC080EB01EFD1A42970BE9132663CF654846A92370CF909076D780976F02BCB93F4B739ABD92FC18DC1DBE28EDA",
- "identity_type": "provisioned",
- "iv": "F2DA6B13367A1D956592B937986DCADA",
- "key_seed": "CC5669D6AB653BA0D76496518A8BEB80C904747724CF21ABFE711EF4E66C1717",
- "metadata_key": "CD38133DCF3BE5E85AD5152614EBCC70",
- "section_mic_hmac_key": "A5696785B14A4D7352246FFAA8926DA57C2D47B5E8FD9CAD3DEA52BE766122EE",
- "section_salt": "50205EFE1CBB39FD3572899E4A9FAADB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C90A438A50E93F2464F0EE55291F2472",
- "aes_key": "783982C76051896CF3879D01AD48E82B",
- "data_elements": [
- {
- "contents": "DE3D9E2E05876097FA1D8C",
- "de_type": 129
- },
- {
- "contents": "D066B484718CB966E1F4BE4B3DD52C712077A3",
- "de_type": 145
- },
- {
- "contents": "1A8F96D8CFC568DE5FA81E2E25B21F",
- "de_type": 162
- },
- {
- "contents": "8E1B11FA0970BB66441B5D9EE43569EF92D9A93D9443F868",
- "de_type": 296
- }
- ],
- "encoded_section": "8890134276D816E4465BD410B3B16E1D9E7D5991100023F02B2A00F1E5E9A1ED089BC433715F90042013AD595A1742D2EED91B031F13E399FDF21F4B491120694D72ED8E822B87C7C13CC13019BB1672281428A2F2ABDA6FEEA9661AC3179C926B3A51A3C529040BBE048DCBAB14D4DCE8093CD66015BA0E77B61B922E20325F51799611608E694330",
- "identity_type": "provisioned",
- "iv": "213A6CA4A300251C8E06F982E3ABCE8B",
- "key_seed": "E5C922600165DE89DE7441F0312C7B5F977D674631C91D6046227C6A56B1E21E",
- "metadata_key": "3CA2053EF6F21F47E9FAFD974B23C5C6",
- "section_mic_hmac_key": "5ECE1E81AFAFCE2FA416FC9DBBEAEBEB154F1C6A956CF2B32A0795E7438C7975",
- "section_salt": "23F02B2A00F1E5E9A1ED089BC433715F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DE17942EEA2F8A64B88FA1BF6DEC9995",
- "aes_key": "17BCEBB9A4A9490F404AEF55D5729ECC",
- "data_elements": [
- {
- "contents": "A039F67CF7F3",
- "de_type": 399
- },
- {
- "contents": "E9CE7BC13F8EC91D4A7B2DD9AA389F472F5090E17DF4FB99546AD8A73E85",
- "de_type": 470
- },
- {
- "contents": "71F962A82E4C980D",
- "de_type": 494
- }
- ],
- "encoded_section": "6C901356238CA02CB62DF82AAA695B9F99C76E91100067859E665050534B84E37961D658822790025D988421412F895E343CA8EEAADEE1CF2E12DE25EB2C2DD52B2368A7C2451CDF00DBA31B44801576BD6AF8B6D689EF232C4250C363ABEF30F39E6276FC9FCC28A33A83287B",
- "identity_type": "trusted",
- "iv": "842B1A1F3A3102058F7575310293CD3E",
- "key_seed": "F5E1B94291A9CEDE059BD01045DAAE8E7BF8F9B4DCFD98C816F14D17E5AAAC3B",
- "metadata_key": "9CFF8F87781CD2434DB335C063DA7EFB",
- "section_mic_hmac_key": "96EA7A011BD46B42FED04395B7554816A3770C9627EA8140A954C834E6D95788",
- "section_salt": "67859E665050534B84E37961D6588227"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EEC4ABA003D9CAA5E225EE938E59A88A",
- "aes_key": "A3ECB264388150FF04523DE0CA4AF3FF",
- "data_elements": [
- {
- "contents": "5844574BA986DBBC3FB734C6A0E1FA9D5117CF282C06C47E6CD568CBFB",
- "de_type": 826
- }
- ],
- "encoded_section": "57901396739698F47EEA126FA41FFEAF83526B911000A1C40F8D2851B55CE81385810F82C8999002889342B7DD12A80AE6337FDE0EE82E22533592B5E902E6763AAA274863B2CE7B4621AD059338821618D09ACC1481A060",
- "identity_type": "trusted",
- "iv": "6F7CE3865CC971472C29270AE628765F",
- "key_seed": "FB21E795C55BD93DD87F63107ACC78ED61E9E17DE0EA81C9A6300BA63F1B369C",
- "metadata_key": "35D70D76E387E1BCA4D02CC6BFBA51C2",
- "section_mic_hmac_key": "3EDBCF936225088A78F30EFA4825982F6EE29398679AB1661C1F365D47538EC4",
- "section_salt": "A1C40F8D2851B55CE81385810F82C899"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "40DD0AE6AE5E4181F03C8A77CD35D51B",
- "aes_key": "016F45AB063A9098880BD35B56F93324",
- "data_elements": [
- {
- "contents": "75192B40B7328370B88E0983A13901EB57AB1522A4646850D869CD",
- "de_type": 851
- },
- {
- "contents": "6A21620BDC9E",
- "de_type": 810
- },
- {
- "contents": "6F1BCC7D79A2C824CD4417A720A7C470C2EFA8E901E643E8B4",
- "de_type": 502
- }
- ],
- "encoded_section": "7A90139875296CA1A492DC5433EC0C158390D291100016C8B52E762259821BB72DDCA26B7B4B90022BA2F6C9F36284CA3BD06F8F1C7316988CE9C1461EFD1081A9C6F88C03039DF4C3798990FD9CB1B7535582A27E091340D56BBBCC6251D716F0F64208893548ABFB4B8CEC8273B1B9E188A528783672B31188C7",
- "identity_type": "trusted",
- "iv": "E4D5AB6C234F20EFBEFDB8D47694BBA8",
- "key_seed": "604C1B551B481F1A897F85DEC2F35DDCDC7C5AF74CE2B45B8680F76EA13DC626",
- "metadata_key": "CBE00FD5F6CAEE0428F8AC2EBBB876B0",
- "section_mic_hmac_key": "DE57E2DBDD55226FA52611244EDF1FD974C633EE264AC51EC09AC1F9E192F60E",
- "section_salt": "16C8B52E762259821BB72DDCA26B7B4B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "493740337B758DD54FEDCDBBAD59FDEF",
- "aes_key": "2CC6A4D0D81ACF8B800C71D3883DB5AA",
- "data_elements": [
- {
- "contents": "E05DA93367830FBFF2A5A06D84DA99A681101A994B5AB5CD",
- "de_type": 299
- }
- ],
- "encoded_section": "5290139E7281721A0C71BFE961E2BB6EE3EE169110002DAF1ED3BCCFA03A33C8A12EDD6A774090043E221E6BE16A640381C047CA79D446940E7159C2D63E49730A006BC0B71019200340F11B7BF4B6AA8F80F1",
- "identity_type": "provisioned",
- "iv": "CD540D1F885B93C6019EBC6B1AEC866F",
- "key_seed": "DA6F8D036A011F4EF959EEEB64DD7DD7BDF1E30F0EAE672B49D8A68E6D175BED",
- "metadata_key": "EBD30CAA381AFB2446A295F1E33A205C",
- "section_mic_hmac_key": "8728D6EB04D094F213ED25E9DE0C797856C5CB6378061EA7A7E0DC5F801DCDFE",
- "section_salt": "2DAF1ED3BCCFA03A33C8A12EDD6A7740"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6B6C93C92DCEA4FDFB0EE6F40BE8DA9C",
- "aes_key": "19BAB81AAD722A2E0CB0E1FC5A14A854",
- "data_elements": [
- {
- "contents": "7580DFFCE3D30EDD2DB5AC5F18C4AA8E8D",
- "de_type": 370
- },
- {
- "contents": "EF1E4F25CD5A8888CD41F0237A75EDDB9801E706578EA0619C",
- "de_type": 207
- },
- {
- "contents": "FD9E1EA36172D0F5EF",
- "de_type": 761
- },
- {
- "contents": "3FE5D2D5B86DC22E2BBC14612748CE40507CED56B0ABE2",
- "de_type": 822
- },
- {
- "contents": "8C7B1B818C82412946EC964A4AFCEC5D77F2E49AE42F247CA419",
- "de_type": 628
- }
- ],
- "encoded_section": "AA9013CA08132660CA46BEE4E55FFBF82D98F1911000EC8314769B664C86461B6EA9E12773969001D9853FBE75F68B42B3E95C7D5B3E08DAF0585FE8292777E631F36ED2E0E0A639C821F5AE2786DBE51893D9DF92C68EF63E01F735F69790B7847ED685E3D4851F53D672EA63164B84322A49DDA9BE84427590959F035A608D964F3C49D6BED8E446AF319FBAA9BCC749199BC14CC3B0F5D74E1E6BBF6517A41FEEE61B5112A968883EDD",
- "identity_type": "private",
- "iv": "147048CD988E7F8643E32E2449ECCA07",
- "key_seed": "61D23B0B31E7D1C9A401378119A082952523D5A3ADD9D2C56EB29D695F8EDFBE",
- "metadata_key": "40ACD53A2B51E6F0C26CBED7D58B2D0D",
- "section_mic_hmac_key": "CBCD4D44B600248C33BD5BF177E470EED36A1295E9F2E7813D3BD827001A2EF8",
- "section_salt": "EC8314769B664C86461B6EA9E1277396"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "80E94BB8F2BF0314AD27A08808A81E8E",
- "aes_key": "D48A2B9E344DC5E13A29F40C4F4B0BAD",
- "data_elements": [
- {
- "contents": "32DACC08BD9CAC4BEFF141E364D6D9B408EAAF",
- "de_type": 840
- },
- {
- "contents": "F2379E76F0E1972ABE60536A9B004F93F0F6229E",
- "de_type": 693
- },
- {
- "contents": "",
- "de_type": 482
- }
- ],
- "encoded_section": "6790138854BC068046A9DC6438D9AE0A6707A09110002FA6884A260B808CCEC3C12E058DE4219001B1313868C07F461355998AA9C33D1625542C04A413FC422FDD8BECE20E4EBD8157ABA83E0FE1EEF9D471266DC5EBB50B910DB51086D3AB261A0C64EAB6E1199B",
- "identity_type": "private",
- "iv": "09E7564C426DEC118EE479ACA32437E0",
- "key_seed": "AF6DF5E99E86E3CD676BCECCA7295E1313B989E329F4540A9FAD643A0F1ABE51",
- "metadata_key": "C064817D63652D0DD19F5A6ACD6BDE17",
- "section_mic_hmac_key": "0E01561E7D972FC6EDE73397C102E4062644EEC472F6DC93FFA93AEAE66DCD6D",
- "section_salt": "2FA6884A260B808CCEC3C12E058DE421"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0873B091BF980929D63B07E49841EA92",
- "aes_key": "360F5E0D4F6F7F0D293B7C17B02629EA",
- "data_elements": [
- {
- "contents": "13E936",
- "de_type": 684
- },
- {
- "contents": "151804DFB79EF7222A24A5701D87E68208480E",
- "de_type": 606
- },
- {
- "contents": "80D6BDDCFBD6B69BC93D93D53C",
- "de_type": 492
- }
- ],
- "encoded_section": "639013DDE68E24EE100BC81DE740B78E1CCF98911000AC07A89E68FF59661FE04EF27BAA690C9004A89E30884E4411C87AFCDF22A2AE9DFD4358D0990799ECD6D36A392C3C2F382C4056A2029A15D0C6812B5854F70C369A2F942262DE9729FBA65E79FE",
- "identity_type": "provisioned",
- "iv": "136FA42D9B2B99B94F546C2C7E449F74",
- "key_seed": "F11C412BCBA4EC9352B8503D40CC8263F8910C07ABAF1BD91F7058EF6D8145EB",
- "metadata_key": "64E6F3A83672ED26CB920D57705CE772",
- "section_mic_hmac_key": "2C1630C0416F925EC56A27E00FD6824259447F4718C8100EBFCE6E2E592E1D9C",
- "section_salt": "AC07A89E68FF59661FE04EF27BAA690C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2B72A7EE969EC60FDAEC5744A282CA4C",
- "aes_key": "47A4A0C53E8BF557955DE007FBC442DD",
- "data_elements": [
- {
- "contents": "C36CB8CC680B4B33EA02671DF361BEA7BF",
- "de_type": 411
- },
- {
- "contents": "6B97B27BDDDD6494FCAB9389B244",
- "de_type": 429
- },
- {
- "contents": "3024307E3A7DB9BFB1BAE994A324960889F4FBB9B147B6C0EA45ED9CB7A9",
- "de_type": 370
- },
- {
- "contents": "F9A393167AA68988D465C5D2CF1CAD56",
- "de_type": 502
- }
- ],
- "encoded_section": "9090136B6CD3A51BF4E8F1B05CE8EEA8A990F3911000F16B5FD28A6DA1856DDB813CBAEC800C900441E630201EC8BDBE9513A703235C64F1DCF0C6D9834310A132BB3BAFA165197DF0F0F1006AA34CF11BFD0186C9C20474029FF28E3F80BD3D4E28435AC1730F4F012AE7E12E4B260C114A645E60DF99E0E29F4C6CF94FF1712176DE6C55A9CB340354954A855D178664",
- "identity_type": "provisioned",
- "iv": "46B8EBE1F9E5813B4C1B6E0C2582AB6C",
- "key_seed": "99324A5E7EAC85B893713A8A71B791F414AECEDA4718E972BAAF5C09C94B4E04",
- "metadata_key": "540C5DD8EEF491F8E2DDC5D4277D32C2",
- "section_mic_hmac_key": "8D660846F1432E8E440689560D543DD3533238ED0D71B70F5E7E61A509FC7604",
- "section_salt": "F16B5FD28A6DA1856DDB813CBAEC800C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7D48E37E2858A787F24D7ADCDEC6B4F8",
- "aes_key": "0A887E550738FEDE515876E254B32262",
- "data_elements": [
- {
- "contents": "2479050EEB",
- "de_type": 377
- },
- {
- "contents": "819CE61E221A075010D5306CC7F29BB848A7DBDE1CF044",
- "de_type": 438
- },
- {
- "contents": "73FA1B3A7FF53255786C2C206501040278A66515021557CD",
- "de_type": 906
- }
- ],
- "encoded_section": "74901383D8F28210514557CD5238BD75B0004891100055505B97347C3937A4A25E8EF11E19C29001417D67B71ABDF30298BD1958110886A41360A6C45AA9D02B9F92DB44FA632CBF1437D182C83159AC936C13CC75403A5148A34CEC6AFDD77FDF6127A57C584C9715224B26F646038A21B02647AE",
- "identity_type": "private",
- "iv": "19F9D2CDE3659048AE4151D6175039BF",
- "key_seed": "8DA828527A20965322074BA930562586E6463DEE6D45E788F18D66D42EB73AD2",
- "metadata_key": "0011F0F2FC05ACA4E1251189DA36D627",
- "section_mic_hmac_key": "B2F4D66EB2C40A21EED774F25B5E8B7C9B7A6BD4DFFDA446DBE766047D32AAFE",
- "section_salt": "55505B97347C3937A4A25E8EF11E19C2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "31FB9D5AB71199BD3D5A5108CF837244",
- "aes_key": "4A55292BFFA7C78A73FE80786C9ABEF0",
- "data_elements": [
- {
- "contents": "9A",
- "de_type": 692
- },
- {
- "contents": "ED6453FA7D5A41DFFA12CA200D301C75661C",
- "de_type": 772
- }
- ],
- "encoded_section": "50901323EDF88A11D2105770DB1A1ABF5FEC3F9110009AF3A095E594F715D19B7D83511B49219004C7E360A866771654C1D7E3A58FF19045AF2BE397E964EBDD97C959F54316D0F91B61A2E508D5D4EEED",
- "identity_type": "provisioned",
- "iv": "1E787E4FAE77DE57752F91B18558A915",
- "key_seed": "8C34BFAF25C9C03A5B69EFE1952B394E9ABE8326B25B51260094A712B34D004B",
- "metadata_key": "FE52B2D64213A21002B8C7B956010B5A",
- "section_mic_hmac_key": "D81C4340E189DD4964D0C19F4A57551233074991CD1AE1D48EFD8138B89C5BEF",
- "section_salt": "9AF3A095E594F715D19B7D83511B4921"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CB2018262182E6D33BA5AEFB0CBBE143",
- "aes_key": "10B52CC57509D02CE36E78220DD10359",
- "data_elements": [
- {
- "contents": "308DE91BDEC2875E",
- "de_type": 808
- },
- {
- "contents": "85C2A96A3D4831F7BD91A8CE97F32ECA38602F5B7AAFCA8E56932F",
- "de_type": 143
- }
- ],
- "encoded_section": "60901348D690B04EFA3BDF4C3E8DD74A70B2C491100089BFA018D4593699A057C59303FDFE159001E8683BAAA53B40C1F61575F920F120AB62C9011FA9625A8AD44FF8014C65004A6AB6EED92C54C298AED9D6C5786557B2652923E4B162EDD974",
- "identity_type": "private",
- "iv": "15094DE55EF692E976BDB1EB2E745CB1",
- "key_seed": "4D3212178C679CC76E36E4EFD849D100876E4C5C736EE0B01E151B5E35E587D0",
- "metadata_key": "17DB670A98FF3B44602C3F65108464DD",
- "section_mic_hmac_key": "447DA33BE77C14468DE40322000D3776B80F7C4C7B86FE52477BADD157B552EE",
- "section_salt": "89BFA018D4593699A057C59303FDFE15"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "47861A7A891274B6D1655A79F98921A7",
- "aes_key": "9FEB0CE8CF647F32689CFE9E28ADBCF5",
- "data_elements": [
- {
- "contents": "9479B8564C4C861081E6D40EA07313E136A03B205A37292A9F",
- "de_type": 767
- },
- {
- "contents": "20FB6D81898875FB84B96904690ED4D15C3CD5C6F17B1B5BBB08",
- "de_type": 958
- },
- {
- "contents": "23880B754346286380FD62670369A54B",
- "de_type": 970
- },
- {
- "contents": "32891E939A61CA6F8CA86CFD4BC1B3F1629927",
- "de_type": 871
- },
- {
- "contents": "335F55B4E34382BF37EBC5A21CA9624E",
- "de_type": 669
- }
- ],
- "encoded_section": "AC9013204837C358B2A875405D09FBD7B3992B9110007BECADE8EA1435CDBEDBB18E469114CD90045863BDF633745EA129538D9B3BF1263E6B09ED55748179F0FBECA95B8AA38C87CF1DC3EA24AC9955EC83759B362C2A1DF7FA8D251A5F294D9BDF349819D535EE4C752BC42C555C0DED91CA4AF570787FB68A0702BAA497BFB342030E81B8816B76B8D79F380A80EF0B4F96CBB9194D5961198F675C06279040BE4523B520B17A323E342059",
- "identity_type": "provisioned",
- "iv": "C55BA6CDFD4A092E9D94E5A89F1AE2C0",
- "key_seed": "28D860FDABC254A35234D5E56C8F072CCE1A5D1CCF76524FD9E9805DB350C23F",
- "metadata_key": "B9D69EB1576E56E08FCDABB5FB775F60",
- "section_mic_hmac_key": "949A61FE8DB02C341BC58D96B84585433522ED90E57D604684380A8A2FB46F9B",
- "section_salt": "7BECADE8EA1435CDBEDBB18E469114CD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "242B4AC6DBBC48533D80BF1FF9A4BF08",
- "aes_key": "1964275B07A2CDE782A915674B2C3B30",
- "data_elements": [
- {
- "contents": "B0593CB5472B608EE74D7AAF4483E3BFBB6EC807D36B2D7C3FF2177F",
- "de_type": 378
- }
- ],
- "encoded_section": "569013168E3FBABE4BD7F9026CB85EFA63BDE8911000CAABF68BB9EA843F3160944F444553419002B2A9BC48B3ED25A01FFA491A2AF4EF727511880B33161D0EA013F792EE3C0E468C3F265030A1B29240F37A7538D111",
- "identity_type": "trusted",
- "iv": "98B3F79C48E45D75E4FC709E41D150A7",
- "key_seed": "AB5F98D672AFA5DBEDD0E7805FC1B4ABE971B54CF02DC2E543267FAD43B35882",
- "metadata_key": "448C2CAFA3490A9746664729BB8931F2",
- "section_mic_hmac_key": "63938C028CFC2E53E88F94C2646B8CA4785423173A512051B50D02D2704751FB",
- "section_salt": "CAABF68BB9EA843F3160944F44455341"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FD0B85F4098C82550A9EC6DA9D240983",
- "aes_key": "89CF85C86296167F6F1CEFD3C5A4E4F1",
- "data_elements": [],
- "encoded_section": "379013540CC96A83E31A5086D355E221B7B4DC911000092281802DC11AD81D24A85EB69CFB689002BA7E7247677B83453C745F87E64F4474",
- "identity_type": "trusted",
- "iv": "6302C0AB71F4F52B8D7D57088A495AFB",
- "key_seed": "B5DFAA6C34894DD3C1371C2D525CD1040228261883DF3C71C446EDA72203921D",
- "metadata_key": "1B17E9776E56ECA0EF359DF062118638",
- "section_mic_hmac_key": "5C681440F84C62B8A7342600E73987E8E883A629B0B9791B26F53673D830E072",
- "section_salt": "092281802DC11AD81D24A85EB69CFB68"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4C2EBCD9668E6E1D431E059EDD16D0B7",
- "aes_key": "EC3A1D6A13083AAFD8DEDAE93F24FE23",
- "data_elements": [
- {
- "contents": "BD9F8933F20E3D83BAA4537CE0B99A8E21",
- "de_type": 898
- },
- {
- "contents": "A7F0B8AB76E1F886AF2F54B4C8EA991B",
- "de_type": 433
- },
- {
- "contents": "2C8F580D0FE48B",
- "de_type": 265
- },
- {
- "contents": "7FA7C5C31A427B669C3B923BF5E06A74586691",
- "de_type": 780
- }
- ],
- "encoded_section": "7E90137F75593A7313AEA3845F542E199694AF911000C229127841779C7A5C4295D5969988F0900400A4D8B0D35EDE45A79C0578B7F93A687E7BD4E8B16F53545FBE12C6A99CD768961DF08D544D978C5E2CF6352BD2E2332181D46C4196BC0CC9AAAAA01DC2E32DE9D7F41480769306C071113EDDED0EC4C1E56353E2DBE0",
- "identity_type": "provisioned",
- "iv": "DA2728120E5CD3EB3AB342BB30E97EB6",
- "key_seed": "C644228C08EB7994A9A2F594C73B5A6C60D7D35D6DCB5CC02BD356CEAF43B0F3",
- "metadata_key": "5DFE12C82CE8EC51C896FF3A05C99A8C",
- "section_mic_hmac_key": "92C128F03A968B4E386393F1A92FD7D5330A1354BFCEAB5CC3546913D799B338",
- "section_salt": "C229127841779C7A5C4295D5969988F0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1CAF5E2F6922816F4DFEEDD6EF50E3B0",
- "aes_key": "05BCDFA12204C89B560461D8D0FE199F",
- "data_elements": [],
- "encoded_section": "3790135F8E313E539461B0909160F59361A52B9110001DFB04A1D36A2D1246395348A3DC32B690012EBBABD8762AF1563969C0A4C0944756",
- "identity_type": "private",
- "iv": "33953147560A0CE8D874DBE2E43ACE03",
- "key_seed": "826FC403B24CD2C2C09615C7615519DF4F307F825FBFB6F9FED666C30009E00F",
- "metadata_key": "27045092CED412FED90E2830E2885062",
- "section_mic_hmac_key": "CCABF9B74F78DB6DD3D0D52AFA0A682CE02CD0A922BF6DB9C30FCF6AE0C32AA2",
- "section_salt": "1DFB04A1D36A2D1246395348A3DC32B6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1EF0DF08D58298A0E357D58C46A37EB7",
- "aes_key": "048A4B2AA3DDE111E4BA17205E03C662",
- "data_elements": [
- {
- "contents": "010756998EB5D06CD09797872B98F792BED2FF8DFDC5",
- "de_type": 314
- },
- {
- "contents": "2D49F47794A626D6136EC1B131DFBEE037DA81FF",
- "de_type": 805
- },
- {
- "contents": "3233E2AD33C84C20EE5C873647FF2C973F33C2EE2F",
- "de_type": 198
- },
- {
- "contents": "F801D66076A8D735EC95383F07DE6E61",
- "de_type": 151
- },
- {
- "contents": "61FE63986EC6C8AE1DEC1D60",
- "de_type": 74
- }
- ],
- "encoded_section": "A090135F57C94D2A4431B25F9E82466B7F7F75911000135861848398D4D2D008FB8F23BA28609001597090AD434166B89B3C1D0E8C9D519026C80588D401F0FE4C1024A011246A8C34EFCB98FE65AF5E9143ED806F38AEC55CBEC4E5331527A788F61DBFDE946500BA9CAA2363F2652B11421D386DC1CDC7491DCD16544DE410447903729849F858AB6AC3A538E2C7A08A26DD39D4FEDEB03A89000214260E53DF",
- "identity_type": "private",
- "iv": "E824A7EB69FFBDDC98410CA5AB2B2ADC",
- "key_seed": "7E5E71048A74C3408127CE6A9F9AE1E2C6BB9328824165310E7AB1F2C46268CF",
- "metadata_key": "7F11E9659E1ABCE558A04E7072106314",
- "section_mic_hmac_key": "9BD45B87E27D82FBF6C663E8D208F1C033A9751F7C6A1FA7AA9BD3DBAE9C920E",
- "section_salt": "135861848398D4D2D008FB8F23BA2860"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "56745800DD04412A18EF2923C2C1E5C5",
- "aes_key": "B9CCB0BD14721C95C4B8A82343B0DC69",
- "data_elements": [
- {
- "contents": "3210F9990AE69BCE70A95FD0",
- "de_type": 546
- },
- {
- "contents": "4311BACC1959CB4110506351FC8282D2340D",
- "de_type": 710
- },
- {
- "contents": "ECB77BF5070098A9CA3B5476FA51289575431A",
- "de_type": 699
- },
- {
- "contents": "456E941BF4E877C7C0D3AE3194184576B38648",
- "de_type": 943
- }
- ],
- "encoded_section": "8790132B1F4D078DABBB8B2F7F1AA4B2CE000C91100043713488CD976125D5C9021673B54BD49002DFCA02F508566D9987015A4B9EA57B18348BB3BD0673AF96D26EC99CBD8F3710AD07925C202D19CEA07E2A3E174737A01A87BD7BB64E07668D0F73704A3B07D3AE1658C07351FD670EA94CF4F2255C2245B6776B348613C593373C419E33BF97",
- "identity_type": "trusted",
- "iv": "E9F160D212F5F23E6E0C7395A49A8E17",
- "key_seed": "3FA2A3D35B24B6E8BD5CD626AA7B3BFA7C3B4BF09CDDE290728DCEC2F3C4D0FA",
- "metadata_key": "5926F8FA508EBAF60496AFD11B60B167",
- "section_mic_hmac_key": "936442541778732A30D1A91F94FC0F18AF5DFF9E328C37594578316656B47723",
- "section_salt": "43713488CD976125D5C9021673B54BD4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A987A4F50BFD7B25C8A49901CF43A052",
- "aes_key": "A5595C267A34F4870597DBBD4827DA38",
- "data_elements": [
- {
- "contents": "33118B478C00918923C55B1DC54A31C5BF790066C778B7",
- "de_type": 933
- },
- {
- "contents": "3882AA0EBE9E8D",
- "de_type": 402
- },
- {
- "contents": "578FCB48E206B3D6C98EAC841DE9D1AC69D43023E62AD6",
- "de_type": 610
- },
- {
- "contents": "728D9B96470AE5B5ADF38A1A9A4215C031970DB045DCE4E2BF",
- "de_type": 779
- }
- ],
- "encoded_section": "9190131C0606B17B45C8BE9367B22C9B395B76911000EF7232F8A53316C10FB9B12BDBF874C290019BDC987EE78BE56EFB2B4DA056A45DE88D0B51BB0BCEA3D5D16437415CBB54912083E236626B501B8892CDD61FC154F5FDD5B6603E0AC315345B0B66C9ECF7A1C73735771D014ABB59AC6F08E89E47D78248067B5D01EB5D86227C029BCC2BB0E6BB44FF9BE8B4C9F6D3",
- "identity_type": "private",
- "iv": "CBCBD0C1CFF1E1A93AA4A851A0A412CE",
- "key_seed": "26FEC8FD9564D289B5D8F52A5D92F3374D16F03EA56BE5F4D7598CE444605B3D",
- "metadata_key": "7A37107DFD235BC0A8A94FD05AA69EF8",
- "section_mic_hmac_key": "4AF863F5A51CA185E843E04C8ECBA614DE86D229BDE71D113E280FF688AD0A6A",
- "section_salt": "EF7232F8A53316C10FB9B12BDBF874C2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B177C937AD0440B365E3C3CED0B4ECF5",
- "aes_key": "7D40AF7575970745C5A0F7D70E3385A4",
- "data_elements": [],
- "encoded_section": "37901300CA2C36D77EEB66F56395B5F88615F1911000190E5E624C8AF7EE88442E6F45D52FDE9002379C9C52C7E36620BA82C76E9F9C833E",
- "identity_type": "trusted",
- "iv": "FA5F5B43D79163347C5CEBE72EB7D1A7",
- "key_seed": "C26723C79C5316A9AD2DA3F33FEAE4A2E88A2A1135E1DE408ACC7EBBC97DA81D",
- "metadata_key": "4917FB622BBA8489B507FEC52AB3E689",
- "section_mic_hmac_key": "E0624BAD763E837D01A7DC8475A6D4BD032BF029DA06117674E1E46B41FD59E6",
- "section_salt": "190E5E624C8AF7EE88442E6F45D52FDE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FA2D6DC34EE5F2448477514FA147A69D",
- "aes_key": "0E1EE274831F71B301A6E8DD14D07B5D",
- "data_elements": [],
- "encoded_section": "379013409E9C337F0F080FA88218EDB7D662DA911000F54BBAAC999D3077F2358E0F5D6F6E189002CAF808A29DABEE53046F9E213AF03D3A",
- "identity_type": "trusted",
- "iv": "AFAA0446DB0D21D787121C963804CECB",
- "key_seed": "26F4220C4937B3B3E8A07F53D536205F49A00890B97A10065CAFC190FC2D94B5",
- "metadata_key": "E6D25ACEFE69AE468697686404908507",
- "section_mic_hmac_key": "3772B9EE7DBFD9EAF93856E0ADAF7893EAE501B0AA4319634CC71396051E3D0B",
- "section_salt": "F54BBAAC999D3077F2358E0F5D6F6E18"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A6280B06DBAACBF7D349965D5BC89A29",
- "aes_key": "87E8362317FD13D66B3CBD2BA7945474",
- "data_elements": [
- {
- "contents": "6F38BC6C3C51A12F811B2995",
- "de_type": 995
- }
- ],
- "encoded_section": "469013DF0934F5F3F9B6112BAFE9E4247E6E469110001714054198B85EB13501CCFB5238EDE09001516776B88AA711D867D8E555AB751386189FD0EA6AB0B46AE6FBE32F00BC32",
- "identity_type": "private",
- "iv": "14CAD16E8873456B63116AD8D44A1DDD",
- "key_seed": "795C911C94D65CF52423B7FC80A1238AD2B368E9B63B84EE68B96C254BA9EBA1",
- "metadata_key": "387D38DB6B421C87D9730E68378C6A66",
- "section_mic_hmac_key": "527195983F0A34F82CC68E7CD179E0E76A715C42221BB028807E09633EBFA556",
- "section_salt": "1714054198B85EB13501CCFB5238EDE0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B93D5B221DA6B6630432D05971BD097D",
- "aes_key": "D145D00B76039023095EFCA293AE5C31",
- "data_elements": [
- {
- "contents": "B85F85569E8BA916DBD401A29DA12D246B9CC1B8A5E1443FAB343099",
- "de_type": 276
- },
- {
- "contents": "2B31FE53220530EE7237618120",
- "de_type": 912
- },
- {
- "contents": "016008F70522603B5E4F6B76344F3D52C5A57B39E4038AF8A8F42A",
- "de_type": 602
- },
- {
- "contents": "B14882D90E5C4690F09CF3E945",
- "de_type": 318
- },
- {
- "contents": "FA4E574D4E2E615A3FFD2D185AEAF145B2D71925C152A6",
- "de_type": 822
- }
- ],
- "encoded_section": "AE901319824BDD1F5E974F6DCFDB43A2CF01E9911000B7B0B621D9724F0DF78391C91EA696C390013DF4B00F304BB7398762286C53648CFFC8255329F55930F1897E2C263298D50D3742A38F2FACCA2AD4DEC504F26B0807F402526FB44C656303A5B2C2FDDC0F66E986C1A4622D795D2F69FA1D7897BFD3C51B0C73B41A0FADD795C81A929126AF23142944F6B7D4E8555A23013398C47010884C0F528304A648B5CFCF48DF789BCBB9EF14D2A894",
- "identity_type": "private",
- "iv": "EDCD3E09ECC33CC0428B84B84A306290",
- "key_seed": "F4DFBB6FEAF8AC93BAD4732CDB320B6E862122646F848E275919104C2D42A873",
- "metadata_key": "BFE267A05480880B72716BE7339D871C",
- "section_mic_hmac_key": "B8B176BDAFBE2009FAA4061560DECA5E315497E163390EF339DB071B15FB4B95",
- "section_salt": "B7B0B621D9724F0DF78391C91EA696C3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E12D7AB4AD24788123EBE401FCFE0361",
- "aes_key": "B9B30EA4622A6F9D8AD6F0E55BA4B942",
- "data_elements": [
- {
- "contents": "3051CF22ED9D25",
- "de_type": 618
- }
- ],
- "encoded_section": "4190132465A472C19E1132D6920D85859C462D9110002A68F093B202AEE3BA5C5920E1CFD169900148079856121A9BD3EE0EE241012343707145363A5036B2FD221B",
- "identity_type": "private",
- "iv": "A8B13B39231EA9901D765FAA4D903CA9",
- "key_seed": "F401092F0C5FE27E56C9A156F3758F00785479106A65D15BAE8A71EE0D74882A",
- "metadata_key": "A13B7F9FC15F2BC3CE3DA2FE7A12B8F1",
- "section_mic_hmac_key": "109B276D0832C380BEB445EE69833504C4C1C36336ED29FD5A968275539D06C4",
- "section_salt": "2A68F093B202AEE3BA5C5920E1CFD169"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4A44E437E8CB79A4D9CD8B36C741598F",
- "aes_key": "9DF76674041561AECBE242B96765159F",
- "data_elements": [
- {
- "contents": "6DA30D675509E1A51259DEDA2F11E5B3BF23A8FD",
- "de_type": 639
- },
- {
- "contents": "87DCB0D2DC1A",
- "de_type": 247
- },
- {
- "contents": "7B59DEB0A3127B05BB534C71E77E35918E83DF59",
- "de_type": 589
- },
- {
- "contents": "",
- "de_type": 101
- }
- ],
- "encoded_section": "70901391E265F35A1E0577B27E896855A176F4911000BD2435F6F73228A37BC92F68AA6A147B90019E7DD0615640A2FE79D4239B6A943831D7C153CE9563FB645E396005A037F61F5F3F9D85A9F028D370A22BE88A7DEF734208CE97931054D7D6002432993830428EABA280091229CA39",
- "identity_type": "private",
- "iv": "4C0F11065C0D0A50281895D599B113E7",
- "key_seed": "F3D388C12E7FACB9A9A10D71841128E5AA5B62203C4D9288CEF583FD0C973281",
- "metadata_key": "36BE0AAEB9570FC44C86D948C112D2C9",
- "section_mic_hmac_key": "6C082598D6635262737FDCD8CF2C84F0564A88B0619C46B1087BF10C19D3DF60",
- "section_salt": "BD2435F6F73228A37BC92F68AA6A147B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AEA8992BCF56D8C977B4F23CD035215E",
- "aes_key": "FDBDC8FC03D9D4BD00E02D7E95BC806F",
- "data_elements": [
- {
- "contents": "29FD64AA2AF020C8C1DA859D8F",
- "de_type": 274
- }
- ],
- "encoded_section": "479013F445F2D544BA05B19A3476E945DFE97D91100072C4FF46E7236884EA75F40693BFF42E90048B3C5601202F9764171E03FC75A45120BFE756EAFF35D3CE64EA5C749E93FA52",
- "identity_type": "provisioned",
- "iv": "48F82C64D3B561EC02F68C129E705F7C",
- "key_seed": "3B1B53F1A643F064C11C5FC0289D3AC60314493366D5286899B4398A579F5D64",
- "metadata_key": "B1CEED2817D2815495A72C8BBB856EA0",
- "section_mic_hmac_key": "B4155D5CEBB91D838092A22CE031FC3A18C751BD1C93277781EBD05EFBEA5449",
- "section_salt": "72C4FF46E7236884EA75F40693BFF42E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7844FD878C399C26ABC3F5898F1EEE7B",
- "aes_key": "26EFB718B9B26B32C37DDBCEF467D023",
- "data_elements": [
- {
- "contents": "F17E9BF1E3F0713D0F30F2D160",
- "de_type": 538
- },
- {
- "contents": "D18840BFB3F67A8CA354755541827C27BA67804B9379D966",
- "de_type": 121
- }
- ],
- "encoded_section": "619013AEF9942B3FCE71119B0158F3B5CEFFC19110002D3887C9CC4BF9B5678676E908D6B65390010ECA727C2BEB2D8BE03CF1AF18057D68A28F3C87E05EFB8C46FD8F70E81C44BEA67C5B744AC821302A345A2A078260A815FE69088127C8B377B8",
- "identity_type": "private",
- "iv": "849FBD20C4DEE438141A13D97554D787",
- "key_seed": "5162B090AA207D037425C2D3A1627A01009FCBE33076984181B26E948630B08F",
- "metadata_key": "792BAA366C23A2878F7D5376867E03A6",
- "section_mic_hmac_key": "1235C37B0CA4D707242A8DC6CCD79F80AA9DA1462E6AE7729F3C2680F38C3D5C",
- "section_salt": "2D3887C9CC4BF9B5678676E908D6B653"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F42DCC02D50640A2F658B83FB4E7CCC7",
- "aes_key": "616EF3104C743DEF83DDB73A4054469A",
- "data_elements": [
- {
- "contents": "03383E9297",
- "de_type": 260
- },
- {
- "contents": "9462914DA98DB75E09",
- "de_type": 412
- },
- {
- "contents": "1DE476",
- "de_type": 421
- }
- ],
- "encoded_section": "519013D4E125FE1E65626076AFFDAD82D5BF889110007F4552E79D984C742B9DADB5F74E95189004D3AC96826BB9BEFC0F1E79081B62A2FE3B1E9ADB08AB470AE6F93E8B7A809190D6312B28EC8D81AA0801",
- "identity_type": "provisioned",
- "iv": "D7A0BC0D7FE96922460BA73213646E9D",
- "key_seed": "3ED27ED5664D454F921BCCD0869CE1CC7B3BB85E7585375DCB33FB0650EF779D",
- "metadata_key": "EB3C8E526E6D9235391E827F2C6E231B",
- "section_mic_hmac_key": "BC311E65AD6DD040501783F1664655BABE513E3B907292CAFF9BE29FFFF4A448",
- "section_salt": "7F4552E79D984C742B9DADB5F74E9518"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "362715986AEF2115C1E99FB44EFA1C75",
- "aes_key": "C59A28A212B4FCDAC1E16462C5B1D165",
- "data_elements": [],
- "encoded_section": "379013A2A1BA7A82B6F9CDA55E5FCCAD4257AE911000B55714FC13B8BD3C6B8C0A7C668F1BBB900270E9E6041661BF6F78C6AB5322EBEB23",
- "identity_type": "trusted",
- "iv": "0D644B9401404857EE408775BC5A52A4",
- "key_seed": "1568B68A9D59E4C9482EB671122CACB6663B00DE1215CB0FDF68A5B32E186478",
- "metadata_key": "54A22FF50922686A95E211D724463375",
- "section_mic_hmac_key": "46281BECBD442DFB726A2AAF39230B5EFE5018E343BC551B2E48A5750E83D8F2",
- "section_salt": "B55714FC13B8BD3C6B8C0A7C668F1BBB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "505CECCB0BBF804F3680A901A0A84A21",
- "aes_key": "4CC11507027A2925184A972BDDED37ED",
- "data_elements": [
- {
- "contents": "0F4726CABAA7A44D817F00",
- "de_type": 319
- }
- ],
- "encoded_section": "4590133CEA393A75D831272811392FAF4A3545911000D776BD1C0C14FEFD55DC62B967C2318190041F745F67713849A775058D883A469627A056A7C207EED34AB4CE3B710878",
- "identity_type": "provisioned",
- "iv": "BED30BD783D7571B1564D14C3759997E",
- "key_seed": "BD9A88F8FA79FEA622C56138525FEA07EFBF53800B3AE4CDE7C6CA69B2A0D9A0",
- "metadata_key": "2BE32D599D847EEF1023E437601655D7",
- "section_mic_hmac_key": "01D5077099F1BB11915BF29E3CFA7DEB563386EC878CA136DD6F0D1813ECFC2A",
- "section_salt": "D776BD1C0C14FEFD55DC62B967C23181"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C295D404B8FC5E3737BDF1FD586EB54",
- "aes_key": "333AC5989888D159B59BEE541183F1B4",
- "data_elements": [
- {
- "contents": "",
- "de_type": 376
- },
- {
- "contents": "0EC58152447FB55294C763C5310B90C4B1BDBDBA",
- "de_type": 897
- }
- ],
- "encoded_section": "5190131DC5A94934AB3C124656E7E19C9D6D74911000D77197B01CECE72E38B7055E1B2A4E9190028EA817F765B15EFE6F9B1273E5164FAF6082E6F6CD317DC41D9C1DF860C7F17D7E205EE1D4ABBEA59EAD",
- "identity_type": "trusted",
- "iv": "380397FC7FC735D90D60C40DE97D64BE",
- "key_seed": "58FE4D29790740442D5A1BD2ABB189DFC42B41E4507A0517E061063AA1BFF5E1",
- "metadata_key": "E4FDCED3B8BA98A09E195E2521274AF2",
- "section_mic_hmac_key": "22E7FBE87FE2B9FD4D24A0F8A6EF7603DA4AAFE314655DC486D46A197F95DABD",
- "section_salt": "D77197B01CECE72E38B7055E1B2A4E91"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9B60494234512A3C9B6A5D72533BB7A2",
- "aes_key": "8924A8A345E22836490AD4494DB516BF",
- "data_elements": [
- {
- "contents": "FAB3FD79DE4BC47D2C14B8B99E",
- "de_type": 615
- },
- {
- "contents": "3479BDDCE860",
- "de_type": 667
- },
- {
- "contents": "18D959580DA781",
- "de_type": 786
- },
- {
- "contents": "615DB667E6E281BB9A3641",
- "de_type": 610
- }
- ],
- "encoded_section": "689013C05D97E98B3B8BB1E3DC27D55ED975259110008EE527EE8F974D8E0D0B5B3A665965A090027C5BF2D01D8AED7FA473E8B2DAFED89D2EED05E3D6065A114F2530D30AC5FEB37A439A32AF1D037C6C8EDD5B12505354D0FED97E72C125E079EAAEDCB44CC22355",
- "identity_type": "trusted",
- "iv": "8602AFBB2A34225261DC074174B8E670",
- "key_seed": "CBAFC7E710BE96D3F94FF216AA7F2933E66B1F7C5A57DBAD6E79564DB908CF06",
- "metadata_key": "0A8E7FD1F928402D5ECD50BD80D10A66",
- "section_mic_hmac_key": "3099BF02D5FD168EC01E036738BFB8E30BC0FB4AD407AE3A08F8D8239F64F54A",
- "section_salt": "8EE527EE8F974D8E0D0B5B3A665965A0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3FCD698F9489E37EBD7F6A4D3224C33A",
- "aes_key": "F99653068BD2A63FB36578720F9F63C4",
- "data_elements": [
- {
- "contents": "ADBD7E7559",
- "de_type": 555
- },
- {
- "contents": "48125DBEEC95494C0577757CBADE",
- "de_type": 909
- },
- {
- "contents": "E7AFB7E6690AA0FE3747EBE2F251B606A034A4D817B5",
- "de_type": 14
- }
- ],
- "encoded_section": "689013BB941D4C7CE5BC91FB3D4E6041E4AC9F911000ECBAF5C243C3B5BB209210D84B821A2A9002926509475302C3EC09089E68268572F1525C6382809682E9FF8EB06701D647A5AD7B8038E06C851B7A76FFE98403A5C7DB36893D5CF95FC349E98A177FE6C90CDD",
- "identity_type": "trusted",
- "iv": "D237427573873BBD2A6B372FB9284963",
- "key_seed": "90D41DF3F409B5A2C6895CC449ED835C3C70E509551F8524DAE13F3F4E42A429",
- "metadata_key": "86FCB812E49A140B17C7803C51121583",
- "section_mic_hmac_key": "853B7A9AF337E2EBF2805550EE36447233D006CECB4E4BF7D4085C875F1497CD",
- "section_salt": "ECBAF5C243C3B5BB209210D84B821A2A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0AD3C84FC7C58D3037142AF41852CD42",
- "aes_key": "85571EBC9483AF47E86FBAEC31C8F2C5",
- "data_elements": [
- {
- "contents": "D133239451",
- "de_type": 901
- },
- {
- "contents": "6C2762576EFDFB6F86A41D4FBFED",
- "de_type": 422
- },
- {
- "contents": "4510C7CEA7E09A03E0B7AE2EBACE9177BA7B1D46AD94256574",
- "de_type": 922
- },
- {
- "contents": "DFDAF2",
- "de_type": 207
- },
- {
- "contents": "C5335141F74C8E52E4F2230872366E83D2678B8C373D03987665C5528EAA",
- "de_type": 844
- }
- ],
- "encoded_section": "939013013988FEF35F4BCD059C3077FEB6E19791100091327AAC510808996400403A8CF444DC9002A0A7721297142DF288D8AF4E70874CBCFF74B11FA183925FE595C24F1E676AA8D158EA2605B283FC22951A389C097CF4DFEE6CAEB829CE8C387E3826C59499AA6FE04BAB5726249A4DB982986B1FDB3BAA5772D7EBDC16ACCBE061AB6914C61DA1F98B8ABFEE3360633E106A",
- "identity_type": "trusted",
- "iv": "82B513DD8F4CA0CE7C5E0E4889E860FA",
- "key_seed": "5A29295C59212A429AB6EA78F278EAF3ED825F57AB0D2A129F52CC277B1B1CC8",
- "metadata_key": "EC7EDC4ACB3143F6427A9519FDBA9416",
- "section_mic_hmac_key": "80D950334DC3B27A0260AFE2ABAAB53C5E3C1EE022289A4A81D8933620814D90",
- "section_salt": "91327AAC510808996400403A8CF444DC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C6C90D3B1F749744590F016A23507912",
- "aes_key": "5921AACC16814BC770EACE04A011DEDF",
- "data_elements": [],
- "encoded_section": "379013C51A5B8064CCC91CBF70A7BDDE6A35B1911000CB58CD4EF7644C8AAE7BCF0E9123BD119002B868633C18CF476A943747630391F0B4",
- "identity_type": "trusted",
- "iv": "7D48634F169987CC2E53CE148B93BFF1",
- "key_seed": "77691B80B2C0CA3BAD73653F05B84C0C31704FE6BCDA1551B055B1286F805F86",
- "metadata_key": "0820719A54E2A8D41FCCBE04F6A19116",
- "section_mic_hmac_key": "A9AB5A8E48AFA1C80E86E9764088305C75F440B1CCFABFA9BBAB981966EDC225",
- "section_salt": "CB58CD4EF7644C8AAE7BCF0E9123BD11"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AA5AEF76D88EB7A98704D6F786978A79",
- "aes_key": "D0B5E2F53665D4A49213F8E3CBD17238",
- "data_elements": [
- {
- "contents": "",
- "de_type": 130
- },
- {
- "contents": "008A8A351B53EB339B92051ED484AF78D7",
- "de_type": 212
- },
- {
- "contents": "EA",
- "de_type": 970
- },
- {
- "contents": "61305021F575FEC5427EE4E5F007CC548C7D3DF098",
- "de_type": 496
- },
- {
- "contents": "819984253481F9F903BF58DA2CD7E426E11C681DB803",
- "de_type": 526
- }
- ],
- "encoded_section": "839013C5B60ED430A58C53A974CBA2B932B7DF9110002ADC62BC5A15E27A5D040BD13364457A90029A1C3316152852BF28F18AD8EA58D79CD5CD5460B1F6FDBF6A6DE7982068DBEF5A3F0DDCA5DC1AE558681667C1E896DED773B85E637CFD76AB97C02B7476D058AE259383001072DA55A825E8D9AD8B52640C2C17938D087A7C2C5376",
- "identity_type": "trusted",
- "iv": "F11001063B0781ACC0C9A56FD606E2DA",
- "key_seed": "321B859773DD3BD05F2CA1B0EB5A8B2D50A2CF4800DABB6137B80E0B9E77C53B",
- "metadata_key": "9F67F3ED285AA4A2065101F5170DC3F6",
- "section_mic_hmac_key": "38CB19DA21A127986862AD06AE17603FAD6FFF450BEC8915C71765995E3C9E1A",
- "section_salt": "2ADC62BC5A15E27A5D040BD13364457A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "85033540DAB893A56198E6C61D126215",
- "aes_key": "FA3F91590A9FAE50C85DC060118F34BF",
- "data_elements": [
- {
- "contents": "C1BD30E9571DFD4A46CE538674AEC77965",
- "de_type": 302
- },
- {
- "contents": "E0F4F75A38F47A611824C3C7C36D66EF4F66F7B386ED5055586875",
- "de_type": 357
- },
- {
- "contents": "45531A11802F333B",
- "de_type": 496
- },
- {
- "contents": "4884A8F995F73A415EA5AE2554B5",
- "de_type": 935
- }
- ],
- "encoded_section": "8590139CA7E3ED77C285D887178284CD648077911000D916BE31B39EB0B2C3C8627643F4064C9002352CC9CF57BCF7235F98A537B7DB5615B5DAB258536C24D51FFF0170A18125ECFA058FB63858701B8E98F1B8757F7A95194C86776C49C517F8D30868299BA3221D66BF197D6416A1CCE5044CBBA2EF9D42EA5DABCD618FB117B75E948A18",
- "identity_type": "trusted",
- "iv": "8B5180935197933E61C2A44911D15A10",
- "key_seed": "8E6C7E27B061CB997479DE0B6369D0D06A74EA34B3CCE46E4C8E184D2F5670A9",
- "metadata_key": "42018C7AC5101C0258523EF8C7F0A568",
- "section_mic_hmac_key": "5583258D33DBCEBDD9E51458998869791B41A2F08F182F70B1E3291D42F82E25",
- "section_salt": "D916BE31B39EB0B2C3C8627643F4064C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D3AA4C688EA0AD1918F1C9D71C75562A",
- "aes_key": "580E68ACEADCF22076DFF033AE22E2C6",
- "data_elements": [
- {
- "contents": "EBE2B615",
- "de_type": 8
- },
- {
- "contents": "CD5A0B2223F0E8D0F2C927261AA127",
- "de_type": 597
- },
- {
- "contents": "254D8F45F8E5265C7CA01CB5EBE36D2F5E",
- "de_type": 980
- },
- {
- "contents": "CB749F9F2474F2E1431C822E853FAD78854FF8D2D869E13E",
- "de_type": 82
- }
- ],
- "encoded_section": "7C9013EAD8F6468C5270D4F1F91C2FF6E4D795911000DB917CEFE3F87ABD3C6FE091FE7080169002CD415457D2264207614B3AD25C4684BD245F66E24FF1D32DAB7A5CF5E08EB4E4BFCD04485F639B90758CA40BFC86FB226273E95315E6640032AD8F42F5D6EAAB52D22E3067FF073AA6721FF5075A35E9892785157D",
- "identity_type": "trusted",
- "iv": "7CB9B3466AC81FA752E73027C9E7DC1E",
- "key_seed": "F8649F5B5D4C6482A42BCA722751F19356663FCA5C79D85D635893696BF2ACA1",
- "metadata_key": "DBF7DBD16D60B0AE863E8EAFEE60A8C9",
- "section_mic_hmac_key": "A5D6A3FD29C470C7C27916035F632C5DCAD89CD7312132C6FF3941E8CDEAF515",
- "section_salt": "DB917CEFE3F87ABD3C6FE091FE708016"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EB6BF655A2E80D1AF8D36AED56B6A486",
- "aes_key": "17F445E7EA205A56027250C0346A2E71",
- "data_elements": [
- {
- "contents": "014E6E7BB0D40BC7FCBF9BD3",
- "de_type": 977
- },
- {
- "contents": "A66F701F2B9A8451EB925DD5DFFB18273FD156",
- "de_type": 400
- },
- {
- "contents": "0B730FD3630237F45E3C6EA47F8EE72A69108C94BE72",
- "de_type": 922
- },
- {
- "contents": "AF35622DF4032B16BC69AA13859D54A3CE8A8EA0A637FD7B",
- "de_type": 873
- }
- ],
- "encoded_section": "90901303C3DADA1F1918061D9922E9F5508C449110006F4653653712F88848A16560CB9D4B289004814FF4D9FFA580804263DA2EADEAA12FEC181D131B19E561E2D3811571C796B15B584E6DF5C7B5809A3C61DAAEFBA0496D897583A8A8CF84CF5727911411A9B075C3F4F2ABF2565F7991C893638FD68729C425610B61FAAB5CFF4CDF3E4E7971C8C6DAF7BB92D08D30",
- "identity_type": "provisioned",
- "iv": "189A717116D2613604B3E642AE28A02C",
- "key_seed": "706710F7D3107D9B7DE125A04EB20972E73151AB942360289B3BA4F23F7BB3A2",
- "metadata_key": "9D3E61673F1406C976DB176EBE07B535",
- "section_mic_hmac_key": "5907214C4AB21EEC7F1ADFF46C72E2F7D4141F5D7FA3D4A31B4E698530499066",
- "section_salt": "6F4653653712F88848A16560CB9D4B28"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D78B7D217B2BAD5FABACC1946ABEBB4C",
- "aes_key": "DDE0A6C66AC49FEA60647AAA0F51B3AD",
- "data_elements": [
- {
- "contents": "7DE71497790F3C87A6B1",
- "de_type": 591
- },
- {
- "contents": "73168472EB83D78006B65795611C22B92E8C99",
- "de_type": 797
- },
- {
- "contents": "6FA0E9114BBD4F65224DE85910F489C4AE20BD64AB2184C32ACCAB",
- "de_type": 266
- },
- {
- "contents": "DC41AE5DE9B12057ADFCDA797B077BEFE31DD0352B",
- "de_type": 666
- },
- {
- "contents": "45E2BF06FD93AD81D32E391A18F6ED10939FB5D598925F060413E0C9",
- "de_type": 864
- }
- ],
- "encoded_section": "AF901361D877AB393135E03356064C028A5FE0911000573A6F5FB7DE8D281C473C3ADACA77FB9001EC4FEE7B442EBE106D892C85074695F12CFC7F7D03C692EB54BD467D8473F76D6C3F62AD849A82E3D4F0E2FC9B15AF8604C435C11880EC4690DED0BA67FD4D7ABD258E281C094F695843C59174BC5C59EC82C93D72BD9E9DACD4A8DCBF4B36DCE9F849A729A832325F85C097122E08CFA360CC073F8022F10C7B76E1FA8D67E0732A33DFE0259EA4",
- "identity_type": "private",
- "iv": "0BFF6C36B9AD3D46241C48C045404441",
- "key_seed": "B595F2E119E405069858063A2D71A34C08CAEF8842CACFF2841103C33476B8BF",
- "metadata_key": "81EFCD94E99E534D60F2189BAC02854B",
- "section_mic_hmac_key": "F03A05B7EE67BF56BC9539D8102D174B556D970122EC292EA0AB6BFDB8E36A1B",
- "section_salt": "573A6F5FB7DE8D281C473C3ADACA77FB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CBD7C88BB7E820DEA7629856F507C7AB",
- "aes_key": "F7D24E7DF3FB39E4C01D50213CA4427E",
- "data_elements": [
- {
- "contents": "B5427785105E6E551E41111DB9A5",
- "de_type": 941
- },
- {
- "contents": "27B605AB2C3FA4B3F91BCE5D3968A289",
- "de_type": 241
- }
- ],
- "encoded_section": "5B9013FF3841C3001F80A54E975483DB6C5D74911000F896663B53DF517B14CBF9A3A99BEB60900264CF1670CD3161CC7A9E07274C49BC76F0F30169FDE2C493E0E572AB011E1DFC60F52CA98E495C0F21BC81A5634B35D55B3A89E2",
- "identity_type": "trusted",
- "iv": "3F18203F323E679A3F665D4D7AB780CB",
- "key_seed": "7C4425B244F0C63E398983EBACE4C33BE1DF8904348ADD1731379EDC614820F5",
- "metadata_key": "CA10051ACA62C5408E9AD33AC0B6D62E",
- "section_mic_hmac_key": "B923EC80759AA88B679B309AE389AD81B113BD3AD7ADFB1582575683E717CC35",
- "section_salt": "F896663B53DF517B14CBF9A3A99BEB60"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BE0D6935B5CBCE532B644EBAEB0CB4DC",
- "aes_key": "09F96BCC2EDE21309F12AF572473394B",
- "data_elements": [
- {
- "contents": "76",
- "de_type": 700
- },
- {
- "contents": "83BFD32351F59A0C6C0886AFC296BD48C1E442AAA8CFEFCD1AFEBE91654D",
- "de_type": 673
- }
- ],
- "encoded_section": "5C90132605C5751F7E217A7E36D2C846C5DF8891100004FF20FC90A2D3B71931FA83687E046090045D73462C825BE89AACA4AD1EF3CDC4C5A6E3C257787693C51547CD927B09438CDECDC82610E04A0ECB445512CCD10A98ED7547A975",
- "identity_type": "provisioned",
- "iv": "0914932394906428A0D76EE9D518875D",
- "key_seed": "67FDE8780AA1EEFA293EE8897234FE2C0D5DB854BF6A3215609DC44A601D448F",
- "metadata_key": "E77492D379A619F8A40D54D91A5DBED5",
- "section_mic_hmac_key": "F84CC8323ACBFA67420AB61721F4039EB2859FA694DD8C9FA15A9A5C5CE6365F",
- "section_salt": "04FF20FC90A2D3B71931FA83687E0460"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0CE7F59C7D7A29C744084A1E346B308D",
- "aes_key": "2740097F0EE9541B3FE75A1580500594",
- "data_elements": [
- {
- "contents": "B3CC25",
- "de_type": 323
- },
- {
- "contents": "39E0F88DCD564592199E1D2F582BA79D054C292C6DBDAA0343",
- "de_type": 501
- }
- ],
- "encoded_section": "5990139E6B783FB0F70C3902C8A67B9019BBDD911000E3240073A3AB269A8AA57F0122D70EC490024E4CEAC73CE78AA7C17623FEA674A0F892D0DB5FD0DB28392CBDD7FE48F675E5946FC44FEAB8CD4683CAA251AA2084098657",
- "identity_type": "trusted",
- "iv": "3CDFAE3DA464D67F574AFDBBF69161B4",
- "key_seed": "31F9C997DAE4B7C28566810532ED77A9BDA311E0357161B3933F6116C0E3AAD6",
- "metadata_key": "DB75222950D33438C7D8BFC500EFE5CF",
- "section_mic_hmac_key": "BAFA2EF3A4EC8A7EEF7B2E2EC74EB8C89D51D7589D5B316EE19388755639839B",
- "section_salt": "E3240073A3AB269A8AA57F0122D70EC4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "73EB253EB94944B28A0929DB906F3965",
- "aes_key": "B528A116686C84C53B6A71680E846ECD",
- "data_elements": [
- {
- "contents": "F561F2FC",
- "de_type": 347
- },
- {
- "contents": "729617D310A7107E6B62763A15E8",
- "de_type": 436
- },
- {
- "contents": "26F23C2652A0978220A0CD",
- "de_type": 679
- },
- {
- "contents": "BA2CA34BF2F0FCCB4FE3C4FD0D8911F3E5E01837D810ADBB63F091B96D",
- "de_type": 487
- }
- ],
- "encoded_section": "7D9013FD4ED421EBA8A62819978D7E11C4292C911000880D39B609325E05472E3C5D8C6999AE9004358528DA38735AC35115FBCE268A37BF76F6FA4A2E2FB9C39F97E92EE39799487B4137A8D7EB669ABFCC1A46970CE5ABF8D0EF13085463535C4F871184E000260ACB47D637BE03A8FE21D3A302487A51DD89AAB1BCD9",
- "identity_type": "provisioned",
- "iv": "320152979988F1BEC69DBE6A55447602",
- "key_seed": "492F19D4AEB5EA017282ADB13CF7BF4D5A271B78F75AD1BA202B5E3EADFDAAF4",
- "metadata_key": "956FB218D86E0B1022B9D9EF9557E0DB",
- "section_mic_hmac_key": "A1FE43F2B654C7609E652267C50E47E5006B9ADA95AA6FE9CE74C0A7688CE14F",
- "section_salt": "880D39B609325E05472E3C5D8C6999AE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4DE153E88AE9F55EA216E8460C5B4AB3",
- "aes_key": "437A29371741838743A218D22C151D97",
- "data_elements": [],
- "encoded_section": "379013EA44AEE04512C910A2DD265ADFA11056911000BBE190D2D9010D8B82EB6885F11888B8900494CB0BE562B2A7D547945AE25C11ACD0",
- "identity_type": "provisioned",
- "iv": "0D790B1F58DC583F71CC470CF2639578",
- "key_seed": "E6A5B4A42797FD2443733A51FE08E0E20A97142163D82E17AED64395E2E25A1D",
- "metadata_key": "EBE57E72E39DFF45F46CDC67406C79C0",
- "section_mic_hmac_key": "2E2E7B8051FA5A344F74D36B3881951D476E291DA95F619AE54FDBA38F23E7B5",
- "section_salt": "BBE190D2D9010D8B82EB6885F11888B8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F6B8A28AA97515625D1BC8744ABF581C",
- "aes_key": "F4FD755476BFB54A67D333FDE5F21D38",
- "data_elements": [
- {
- "contents": "11E6C336306364DF2C6FFE3C44296C238FBE80A7C39660",
- "de_type": 553
- },
- {
- "contents": "F895D8637D37F08C2FBD63460CC66EC79D61DC7814A8317DD9",
- "de_type": 142
- },
- {
- "contents": "023536380CB2B465115601F0549C1E225ED0DDDCC1A5757CE504348EB006",
- "de_type": 426
- },
- {
- "contents": "90163807A994663D6BA798C051E17A4FFE136343F70CEC",
- "de_type": 711
- },
- {
- "contents": "34C1D3B746DBE55C999FE970A78892E4312154893D",
- "de_type": 686
- }
- ],
- "encoded_section": "C0901358E24D5D9BCCB5631A933692B53ACC60911000041BF71ED6F92D89A7437595D5870FC490025408C683AD58FA66667A80D6B9A16201FE80656CD7F160DAE3A0E5D6C56059E87075977DFF54C593082FCD681599A8BEF62A9152700490EAC32F0A230A4EE201096056827AFF77B0E691B83E0ACA71195C60C372A7063A662D750D1EAF2B97BF3B7BEA594B7E25A2C0449AC9001C4CD601E5329D30994932854A78B8678AABC7AE2CD0A40590EDF91F91C0CD4BC5658543887CA9CB9E36EB0D",
- "identity_type": "trusted",
- "iv": "A55C04DE4370A9539D0054FEB77CBB41",
- "key_seed": "A0F4708912E13265DC407CB2E58EBA265C246741CFA5AC92C5F45003E9DC3D73",
- "metadata_key": "0755F41DE31C1DA14183BCE6ED2A793E",
- "section_mic_hmac_key": "45DD4376D86A64ACF88C521BEC32316AD023B10200514E6C1200E364FDBB1C89",
- "section_salt": "041BF71ED6F92D89A7437595D5870FC4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "80B55AAFF717D29EE2150527E786FC22",
- "aes_key": "89D2E5C6EF19C4798B18A5AC956BA8A8",
- "data_elements": [
- {
- "contents": "C925910705C708716C2A2E2FB9B7",
- "de_type": 746
- },
- {
- "contents": "7441B7",
- "de_type": 798
- },
- {
- "contents": "5616AF27BC9705EA841EE82D8A8CE2A4E4F4BE51D4",
- "de_type": 284
- }
- ],
- "encoded_section": "6690131B198CEAE84F43E5333491064B8C72D19110005A8BC686BC40CFD016A6549C3E3220A79001E09548FC1B654C438A8B9949692224C81D87813B39830B110F4B5FE0F9D58BCEB7CCEDF442B77A17839F79F00A0AD51DAC75D63B7B137949665C55C8EEFDBF",
- "identity_type": "private",
- "iv": "C87B5050A21E0BEF4DF28C8E2E86B9E2",
- "key_seed": "62127F82AA866333831B924405D6AD1B36112C39901CA63820FF8CAFD841184C",
- "metadata_key": "863325C4DECDBF4CC7BBFFF32518528C",
- "section_mic_hmac_key": "5E35357D5B711AE75EBEB698D5FD818E165687A6C941F545EA7A54486433D521",
- "section_salt": "5A8BC686BC40CFD016A6549C3E3220A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5CE67FEBA4AED76BB9C04DEA24F5121D",
- "aes_key": "CD9B63EE81CCBC1A6FED8AB873DA6F9C",
- "data_elements": [
- {
- "contents": "0E0FCD76BDCF900F512961B856A7A8177BD66FFBDB33F4F5F44459B009B9",
- "de_type": 153
- },
- {
- "contents": "C45B234AAC5688FC4196",
- "de_type": 952
- },
- {
- "contents": "CECEA9E54D144A541D",
- "de_type": 299
- },
- {
- "contents": "A5837AEB6B56F1C33168919FCCCA914D7668DA65107E",
- "de_type": 583
- }
- ],
- "encoded_section": "8A90130DF91C2EA62A4347A347AB4FFFAC68BB911000AABDF7BE435EF0A8DC2F5ECD0099C2169004FED4F8ABDB95DE277D5EA8CC2CDE85DA2089ECFD798827F8F757DEDB8EDEA4EE5A53A41316D8D3DB792007477A232506EDB88E6E15434D52978B671850915B0B4E91713CA3584FBC1E92581FEB81750D378A6E0D51835A8F3CA203DE4272FE41F2230F",
- "identity_type": "provisioned",
- "iv": "6AD1D35AF9DCFA8846CE08139586BE4D",
- "key_seed": "3EB0A1FC103DE614F09A1A555E9F83A7B80B87712014B0CAD6C4ED25F52B9B33",
- "metadata_key": "488C3EF28CAAB88A94CD82AE8EDFF615",
- "section_mic_hmac_key": "2B44CC0286E9B946662DAFCA116AE8AC7464625D20BA4972F9CD5E09A226957D",
- "section_salt": "AABDF7BE435EF0A8DC2F5ECD0099C216"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B9DEA2501303F34F7BAAF91B3FF6FDFB",
- "aes_key": "6EF9C4550455F6B122A9842E4FF9563F",
- "data_elements": [
- {
- "contents": "59E50862FE4633D3ECF91C3EDB72270FCBB5",
- "de_type": 286
- }
- ],
- "encoded_section": "4C9013D4619FC79CC7834813D1C2A27ABF790E9110000F0469848994E26F09CA0C6C440462749004F0A1A5CB662AE19B307355144B85F4EAF30056D216F9D2C0DE09D233F4C85B3A39BDB355E7",
- "identity_type": "provisioned",
- "iv": "EFBEDF6DCF3B97786CABF592BAF9F5D6",
- "key_seed": "F0EE8773F58564994D1F3BA077E7A3990228BBEA25A527ECEC620A62279F0319",
- "metadata_key": "FD3B6FF7375FFFF1CC29FFEAF9A4C2EB",
- "section_mic_hmac_key": "7123A128F2D15A893EB34A5114774DE3D49285942274ED8F5F3FE198D58F3110",
- "section_salt": "0F0469848994E26F09CA0C6C44046274"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8D8E8645D7B0FD0E9E36ECE388CC4F6B",
- "aes_key": "CE9FFE75B22C96DA0FA83BC6AE435B4A",
- "data_elements": [
- {
- "contents": "4C84EA9E7ABBE9805FDA1AE32592092F414A",
- "de_type": 446
- },
- {
- "contents": "E2013312F6",
- "de_type": 100
- },
- {
- "contents": "7647A9C883BD",
- "de_type": 427
- },
- {
- "contents": "",
- "de_type": 434
- },
- {
- "contents": "9A48A6A9C9FCACC1E8BC284FCF5A368125",
- "de_type": 953
- }
- ],
- "encoded_section": "739013765C4523E0C5459C2573E009ADD07AEE911000B52AEE3E5778873503DB2A7374157D499002C6032636BCCE82535DE0210C953C742AD0E29C1E270461E7C0D27DD7C81E402CBE795FA9F76971E0138E2533D0D47ADE1F673E73FB92A528A0BA6557AAEAB58AC529D3568B70625AEEB89E06",
- "identity_type": "trusted",
- "iv": "26E8F98BEE4A9526EA91AA37D9290E4A",
- "key_seed": "C3F16DFE3A2C64284BF2ECC6CE660B8245B60CAF9C6BB378EC85AB0D2FBE70EE",
- "metadata_key": "653436D31BEBCBB3B1A13D9118541883",
- "section_mic_hmac_key": "2B3BD1A84191B22159C5FB85BD543C3673357A0F35AE67C6850E59CBE30AA17A",
- "section_salt": "B52AEE3E5778873503DB2A7374157D49"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "034097967DC080A36D23F899968F81FC",
- "aes_key": "FC52BBC65CB4A29005CDBC12244BB6EE",
- "data_elements": [
- {
- "contents": "E911676F5B4E9F61",
- "de_type": 566
- },
- {
- "contents": "",
- "de_type": 455
- }
- ],
- "encoded_section": "459013C48F03E367BD6F91F0B051FB2D8791F3911000C713EC5C07873E7CD62C20B0DBCC23AD900203A6EDBA4B5584A004D3241D12A40A7D6249D1D9530358F146EC5843C68E",
- "identity_type": "trusted",
- "iv": "D2564B7B324F39EC38CA5B83BF40FE80",
- "key_seed": "B0F6316F4E5AF9E14F4D2E0D83FF526A2FC1C243058E6388BC5DF379438AF84A",
- "metadata_key": "2E0E3C928A480081465B77B49A94DD56",
- "section_mic_hmac_key": "556C7EC0D6D6B7039D48F792BA144CBEACFCC0DBADFA48216F164BAEC8D63590",
- "section_salt": "C713EC5C07873E7CD62C20B0DBCC23AD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0BC6ED4E4FAD31DE8B82828233A12365",
- "aes_key": "3FEF727B599B4459455003A24642403F",
- "data_elements": [],
- "encoded_section": "3790134EF72ABDD3AFCBE1EE92620E4DA93B7291100041A9598B504C6C06A001007085FA9E0190018DDABDE4D015767D58FC48D349221A74",
- "identity_type": "private",
- "iv": "ECABC8AC7BA091020DC32E9ABD83EA8D",
- "key_seed": "EC81188441C84DC2ABDB353BD825AFEE28068F397BD3E69DD9A1F51E5968CE7E",
- "metadata_key": "D22BD70DD5645FD54109C0EF7BD0230C",
- "section_mic_hmac_key": "B5B3BD02791CF9B92F1C14CCD4DEBEAC2DA75B7B1E09F9621358BAFDFA90BC66",
- "section_salt": "41A9598B504C6C06A001007085FA9E01"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BF047090110BE62932CD9AEEA0A52C48",
- "aes_key": "074D26AD25D20FB1036B4249E2E65B8F",
- "data_elements": [
- {
- "contents": "C6A2397CF77000BBD2EBE6823B067AB8DBCA0B286C5CCFE016F1C4DD",
- "de_type": 268
- }
- ],
- "encoded_section": "569013EC3001BC38635A32132EA9F28B7384A59110001C583A0044B9A78DB388334F9CC28A6990047EE274D8D6CD6FF1A0C80003FEE139C37C699B106C421F4B6A2CC6519D742A54C5858A398EF3F71D3F41EE45CD0B66",
- "identity_type": "provisioned",
- "iv": "5FE0E2D415A4FAA3BCB05F7916A8DE70",
- "key_seed": "D963624712D4A0EF3595BB91D3AD2544BDB5CEEE55BCD98BDFD6338616138018",
- "metadata_key": "8DC8B52AFCC6441510745EBD7B64088D",
- "section_mic_hmac_key": "0086E6595B16AE4D2DF1F4F0392D7454659FE056469DCC4A77F97CF03FA64580",
- "section_salt": "1C583A0044B9A78DB388334F9CC28A69"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "70F216A7594C3FF0E50939B5F220FE79",
- "aes_key": "F01E3A52411A7B1FED0BD6E66293A36D",
- "data_elements": [
- {
- "contents": "7405920409",
- "de_type": 27
- }
- ],
- "encoded_section": "3E9013725A39A695F3E9F46AD197C21A99C2D7911000470C1930342C821B79454E20E5AB565B9001CC0690B842E78B7D6B78BEBD4211D467553DC5EDDBA2AB",
- "identity_type": "private",
- "iv": "0FAF61AA59E9CBFEDF4980C75B398AA9",
- "key_seed": "179D0580612390420788D334FD020577FE02C7BD687DC505D187D79F08043268",
- "metadata_key": "50780E0D785234C8EBF3AD1DB5C75B78",
- "section_mic_hmac_key": "4B1B5D53E4470367C14FBFE4F7125B93600BB28C06C92793E1C64EA61627D5C1",
- "section_salt": "470C1930342C821B79454E20E5AB565B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B3BFD568BC29834E2E7F3464E5C51A4B",
- "aes_key": "FB487D058A744D7651D78F35E65719B7",
- "data_elements": [
- {
- "contents": "DF9EF9CB0BFB15675BBB5538BEAD105177B941FC3D686B",
- "de_type": 797
- },
- {
- "contents": "7D24B6A84E",
- "de_type": 884
- }
- ],
- "encoded_section": "5990139FC1B788D94802986DBAEDA37EDBA2AF9110006BEF387F51D62868738ADD58FDE218249002E262DBF23D1632384B901434E093C6998AB986226C99C8F7F6B3F9380322ECFD251D8B8BCBC6F9D2F197CD856C2BFCA6799B",
- "identity_type": "trusted",
- "iv": "D1646EED1BE182D8F658BBA68FF28CD0",
- "key_seed": "0DD1FE126C5BAFC3E252D7DA0594D99F343A912E0621148915369B386348172F",
- "metadata_key": "12E52DC79FFF5748E238F667C4CCCFE1",
- "section_mic_hmac_key": "B5B5BE70DA1B6E67300A257C9568D1D777263CCE944001D4571F86966237C266",
- "section_salt": "6BEF387F51D62868738ADD58FDE21824"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "043890F126BF8FD56249E2C73E59800E",
- "aes_key": "F372FC7CB4D3900FBB9C6B41921ECC89",
- "data_elements": [
- {
- "contents": "14BB8E9B7B",
- "de_type": 389
- },
- {
- "contents": "0988FF91EFBA62AE84619FE5A71978B457EC739AE265D455856CFE",
- "de_type": 392
- },
- {
- "contents": "EFB5AA412C20472C54F22CA84AFA",
- "de_type": 369
- },
- {
- "contents": "2A6E32C24C3CD0AB1CABD0010F49A94664BE81399CF39DE9C8D225DFC67E",
- "de_type": 408
- }
- ],
- "encoded_section": "8F901394A25D3684C8351BA133D7935CF78FCE911000E97B66077075042EEFEDE4ED8B42744F9004BD060A6FE04F67326A3316058E3A354F32195D06920642A21D1F38DB9DAC8BFAEC958C457F0B5DE19626033705374CF5BBF3A4E2AB1C1197A411DAC42B636511827FB43F9BB83D28E1FB5F3F359DEAC8E6D4EEDCFE8496C6A27EC348C2778E1BD004BCFC5A154FAF",
- "identity_type": "provisioned",
- "iv": "16339A85CD833FB55944A135968EA806",
- "key_seed": "E7C4E1D06521AAD6962A498287BAE9EE92361BE1FC7DF062564D0107649F6FFD",
- "metadata_key": "B23F3EF58B4E7CCBC098C105B9D50E01",
- "section_mic_hmac_key": "C37C26624B9F567661B253E21D89336D23C21ECC122FB83359DFE86203685E45",
- "section_salt": "E97B66077075042EEFEDE4ED8B42744F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C063C2D07532B482BFDEBD663EDC8265",
- "aes_key": "78886059E7F87F6478A15B1CCEB129C3",
- "data_elements": [],
- "encoded_section": "3790135199391E9E94DE46457DEFA2423C3BA6911000DD4628D624F0B29D1B9E298F42873FAA9004F3675D66D5129706C9DF1FF21F4ECBC7",
- "identity_type": "provisioned",
- "iv": "25A3BF84A38B4DC18D6DC400D33D85C9",
- "key_seed": "6465DFE7C9EA8D4F1BAC260D41067AFE04D5F1417A8A2BE49FC8498C98675331",
- "metadata_key": "D786EC2AF4CEAD98F381671FB41224B6",
- "section_mic_hmac_key": "8131F5C4D353A851B8763D5A92396040F06246EAA72F1F6DE549E2D35A35B57A",
- "section_salt": "DD4628D624F0B29D1B9E298F42873FAA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C94BA491AB602859E1F82F97DC7E31E0",
- "aes_key": "F61ABA231C3721C2BD49328F3D090AB3",
- "data_elements": [
- {
- "contents": "6C1BAB85BB39D714EE",
- "de_type": 738
- },
- {
- "contents": "28CE85B2A00672F37691D02111DFD1BFC21D",
- "de_type": 105
- },
- {
- "contents": "16A72D416A0D6851BB0CA8CDC2B07848B6A06A",
- "de_type": 225
- }
- ],
- "encoded_section": "6D9013C6D572F4EC76769832B2F2F3AC584A599110002556D8F2392B4790EA6FA9B70B18D3AC9001E64E58B31B1F9DA5DEED6593631E650F2B9C4FFF9C5105ABA3332D06A64436DD5B2DD2F3ED517E533889DE660536562FC3A0546FCEFBA559E85DEE0684134A3DC15C472539A7",
- "identity_type": "private",
- "iv": "EF82962F49EA98E5C08EB77194A2DD03",
- "key_seed": "ABCB15E7264D97216AC3352B5BE3DB9678F9DFF1C5C9F62F8C911BB7D83DCC04",
- "metadata_key": "6EC93C5286500B4D7E15754A4125AC6C",
- "section_mic_hmac_key": "55B357AF96262F52A3F2DADF540144862D66F19D734277102308554E4A803C63",
- "section_salt": "2556D8F2392B4790EA6FA9B70B18D3AC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "845E8EC3A0A25B2298E6431A91E189BD",
- "aes_key": "54D20D731E4FF2CA206D66C95313ED43",
- "data_elements": [
- {
- "contents": "C6CC76056F0FAB3CEB159B6C76EA0A",
- "de_type": 781
- }
- ],
- "encoded_section": "499013628E1C5A4B6BEEF1429B72C20D781CED9110009C067D1D8A1AABCCEACAE28F4441548B9004B8409502A72B1873614B1D9C3EF45B1610D462314B0FC36CDA1CAD8BB9EA670B76F3",
- "identity_type": "provisioned",
- "iv": "1AF8A3DB82F8E98F43EFD67273112AD3",
- "key_seed": "723EB47D34E9D5F54CD657EA4B91BEDEC4508F5423940653B13CA3F9C0E5D0F1",
- "metadata_key": "399A68C6D9EBD1C7136879DFFB4BB661",
- "section_mic_hmac_key": "E42B114BDACD69D449050F295B9F8E1989927928C3DEFFC2C4B1B712156EC7CA",
- "section_salt": "9C067D1D8A1AABCCEACAE28F4441548B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "23240D3B2662A867CAC09B37002EC151",
- "aes_key": "7A6059F6D0A60CAADE7FADADF8A6DC28",
- "data_elements": [
- {
- "contents": "",
- "de_type": 946
- },
- {
- "contents": "7C190D653583EE",
- "de_type": 324
- }
- ],
- "encoded_section": "4490131EEB5DA191A2CFBF9FE477A71C5B16AC91100023AAF945414E18B7B2DFA5CD8F56E1889004C3139ACE2449BBFBF8A129F85AB3959B7BADCD320FD0F0E5D14981B986",
- "identity_type": "provisioned",
- "iv": "AA2A519687C28CCF377AFC1E31A5CD8B",
- "key_seed": "532906986C81E3D60E295AC315B7C414C3CE4CD64654AA7940223E5B0366A38A",
- "metadata_key": "6B3994E58566DC0822C91AD7A9233DE9",
- "section_mic_hmac_key": "2621946D28448B0FE1D49F42F14DBB771D036981A8BF60D68183E48F1370CE68",
- "section_salt": "23AAF945414E18B7B2DFA5CD8F56E188"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1BF5D55B85DFE348E916009BFD94E23E",
- "aes_key": "BBDCE9CD6AC6B4D05A30F0FFD12FCA85",
- "data_elements": [],
- "encoded_section": "379013C80B6B02142DDD201B73820ADF0B2E34911000A321FFAC8CD880B256A741A077BD1C4F9004894461CD30CFCB9D823BA848BB442098",
- "identity_type": "provisioned",
- "iv": "1125CA91BCA3D2C39E84F864736D3243",
- "key_seed": "C06F738CE619A69F7C35F0853EE53BE4567F1AB96CF2DE1D42271BBD4A3FBE25",
- "metadata_key": "9BBD434403D6B68CA9D0B2ECBE1391D6",
- "section_mic_hmac_key": "072FCC113795FD057E811E3573E219B3F4F01C886808E060B2D8CBFFD05E2A39",
- "section_salt": "A321FFAC8CD880B256A741A077BD1C4F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8FFF31D9E05C67B63EFE52C70B562B2D",
- "aes_key": "69C6A32CEE99AC1D008C633D0322AFA7",
- "data_elements": [
- {
- "contents": "775E02A1DD5313C05333CA56BF884A55C3C4A9",
- "de_type": 997
- },
- {
- "contents": "EE659244BCC7E04720E5D5C3633793B3A2F1801127960F4E846C800B17",
- "de_type": 303
- }
- ],
- "encoded_section": "6D9013167EBF9EFA9F7450FC14B8B4755652999110005A21C2E9033C4D92E3D0E343265854A99002617AC1869E187111E631A2E97C28F8179C94488578C3798499A6D1FCE3CF60D4A0265F81DC3CA0F43C49B70E8E00F7AAB6BE5E28175C99E4E868BEA0239098E94DFE43C3D830",
- "identity_type": "trusted",
- "iv": "EC1631F0E9992D01661973E10CAA0598",
- "key_seed": "D304FF6EFEF40CB4745AD0C2112348A40F5BC04D3D91EBC2A55783A2F8869F82",
- "metadata_key": "9EB2E5F2B16FE3803E28A17ACB2E9A56",
- "section_mic_hmac_key": "64449AD305C717B9BC1C186F0BA4B8415CB93C34EC52608A7173EB512FD55EF0",
- "section_salt": "5A21C2E9033C4D92E3D0E343265854A9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B9D3A1A05CBF5F5E1F69C7E362BFF3D3",
- "aes_key": "7A609D1D39BAE76BA999840CD3FDA233",
- "data_elements": [
- {
- "contents": "64A1E6D6457FADD30243A34640CB96D018D8",
- "de_type": 759
- },
- {
- "contents": "8E7893F12DDF3CAE263C8231E284580D78",
- "de_type": 433
- },
- {
- "contents": "8EA89C3191D3",
- "de_type": 979
- },
- {
- "contents": "726840E37DBCC2F0D910874214C21C",
- "de_type": 516
- },
- {
- "contents": "72F6BC7F5BB01EDDFC7892",
- "de_type": 165
- }
- ],
- "encoded_section": "899013B1B9AD2D96FD2C5F6C56A2AB23C6549A911000B4CFAF758BA05C70F0086695B8654E719001E317BFEE6A2A6D5DAE263832DC0A0357E3346EAFA060BEF5A39ABA906872C947DEBCAD36F176043900199327F70F11104B1E80438127A3EFAA37B2FC3B8E800ECA8FEB295316C6D3276F428119CD6BD748E5DAAF5774D51FCA31E5193AE9BC5BE3BC",
- "identity_type": "private",
- "iv": "F786B13173BD39A7BD5DEDECB2C6F86B",
- "key_seed": "FC09B7FB045850F61BAF9F55BF5BD22944884C77EF5ABCDB29C98E9957760AD8",
- "metadata_key": "F7F75BB418B3BDE041DB96A09A16B777",
- "section_mic_hmac_key": "F08A8BF5C5B1E23F20301843ADBC149B886BCB75F017886AF29F123D686818AB",
- "section_salt": "B4CFAF758BA05C70F0086695B8654E71"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "020BC589FF43EBC8F13AE2E43BBD7658",
- "aes_key": "8F3E597366BF11B9B9AF34C266085D81",
- "data_elements": [
- {
- "contents": "A08381B564B135F3322D33E64262AF5A6FD68A085B6908B5602602084C5E",
- "de_type": 89
- },
- {
- "contents": "9A76EAC96F1758FED565E92354C68AF267536BE3522D8D932EE5",
- "de_type": 303
- },
- {
- "contents": "FE73D94D1454A2BDA8F978490437A2BF36C2E72BF6487D5733B2E29F67",
- "de_type": 907
- }
- ],
- "encoded_section": "949013E74B20DEE21DBA2ED1608245C1510777911000A0EF20B9AB805B7746172E5C1CB9A42D9002C03E4EFEB9EBA55E204FEC5F7DC17B6021EE9C652A15486FD70278DE23455D858971C649F749BD2B072A3B573F12F841087ED3516549ACC27BBA69A8C39C36A33739760829F1815F782C784294E64BBE2A3B42EF1752F177BAEB5871E6F913B958F8E11E23DC292A20BADD025E",
- "identity_type": "trusted",
- "iv": "F9282C23FE33849259D66A40165A895F",
- "key_seed": "88EAA2A88210FCD0A7C7A5B5F55583BEEA33324FCBD8F2530F7E8EF3D499A823",
- "metadata_key": "81FD9DE2086417EE30A0A49B89CED2A4",
- "section_mic_hmac_key": "E6954F5FBAFD6C29F2387CFE59C53D49B355501FF14351445F3685BDBB85C64E",
- "section_salt": "A0EF20B9AB805B7746172E5C1CB9A42D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A022D2A91854E61C50C482B8CE339FEF",
- "aes_key": "84109A4F76D0C313388D16CBE43CC8DA",
- "data_elements": [
- {
- "contents": "E4E2A0D0943301F980E26F",
- "de_type": 718
- },
- {
- "contents": "AD9C95407E",
- "de_type": 733
- },
- {
- "contents": "E8",
- "de_type": 49
- }
- ],
- "encoded_section": "509013F3745670932BBB42D2C70A6D17C94DFE911000B39AD48FE7075F779F82D4E60C333F029001D708D6C505181C687C84F36F2A3169DFBD020DF19D5BB72AC8741EF60610A7B174A2FEBDDD22C9C7F3",
- "identity_type": "private",
- "iv": "D1E556A9A5AA49009D49E19983DBA615",
- "key_seed": "7727741471C2E6CCEFE4EC70253B8788D228A3FE618117C6E76EF5E3309D2231",
- "metadata_key": "E1569AA98E6BDB4D6DC9A5BD46195ABA",
- "section_mic_hmac_key": "D461D7A01671D7F83124856867DC04B96F62EC0E4DFBF70CE9CAB556972531D9",
- "section_salt": "B39AD48FE7075F779F82D4E60C333F02"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A7C810623229157F1FAB904377B695CF",
- "aes_key": "5EB951C2968A33F2E7903255731EA4D9",
- "data_elements": [
- {
- "contents": "39973FEFF2D8D62FE6C27BE3AF9B227662461635BB",
- "de_type": 97
- }
- ],
- "encoded_section": "4E90137D2063093EB07801E876E8716FE29D95911000CCD6600A1D0FAAAE97C25B5140102A33900435DC34F63BE56B05BC152597764EF8048746085FD4D12E96EE6A3BC13BF1A4E3BA669EBC3F8EC6",
- "identity_type": "provisioned",
- "iv": "9D738D7B215640FC45EA0AD04FDA685C",
- "key_seed": "98BF712F93903FFFEC4E0EDC656D07CFC78D0ACDBE0607EF19A2A1ADBF4173A9",
- "metadata_key": "9D83C372D120920E197FE972404E1C5D",
- "section_mic_hmac_key": "A65DC4805D1B2611ED71FF80FC7D40384E3ABC352C533422DCD5299228179FB5",
- "section_salt": "CCD6600A1D0FAAAE97C25B5140102A33"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "70BC4889A9135FEF8558DC85DA869313",
- "aes_key": "2F78A0C2E0A662A6AFB80C6170329DD5",
- "data_elements": [
- {
- "contents": "4FDBB2F43A4B80C48905A081D73F0AD23407A50A96FB872ECD365C654A",
- "de_type": 5
- },
- {
- "contents": "238F48BB7F230CA3231C0B8800F7",
- "de_type": 463
- },
- {
- "contents": "7D77BB7E5EE7DF8D11DEDABAF5",
- "de_type": 493
- }
- ],
- "encoded_section": "779013CD09FA4E2906A1B0497103C8B958A4B19110003848C27BB68D7751BD109AA798A5A1FF900111FFDEB247F0705D5D6FD0CD158A38EF11B40163ACEC63E1279BABC6736F3F940CACCDB6600BCBD5652625ED21844D854F0BF2467E5EBE5DF2FC8BE2CA6D6A18A5B60337D94F0E57EAF8B2E3EF417901",
- "identity_type": "private",
- "iv": "177479EC161C64F5B9015DCB22DEDDD2",
- "key_seed": "067F5D95027B2A7BFF1C653CAC3040EA4DCA805369AA6EDEA735899CD2BCA30F",
- "metadata_key": "67E79ACFB7EF2C6FA6357C154450DEC2",
- "section_mic_hmac_key": "63F5C63B2306E218536A099BA9EBFD0EB16FDE66D04E8B917608F0CB39BFECE6",
- "section_salt": "3848C27BB68D7751BD109AA798A5A1FF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0B62C9D1874CB2A9361CD266ACFE0943",
- "aes_key": "3D59EBB776EFA1803E495CAA387DB727",
- "data_elements": [],
- "encoded_section": "3790131F6A24505B1F4420A388289F7F2BC22D9110008C40367DF7D629BC40F5D01CC680C53F900181FB9E16124D32FC426C1C4E4B2ECFE5",
- "identity_type": "private",
- "iv": "D7A366700B7C0223230E9E9677361443",
- "key_seed": "3A4856049F6612A949BCC3647B5BAF36F9D71D0FDE813B824D5BCE2182B5FDF6",
- "metadata_key": "9BAD67AA712DF9C5639C1D2398125C40",
- "section_mic_hmac_key": "9D2C92937531075FD9D09129497BEF9111C0375C6302A80BBA61F0BA5CFC81D8",
- "section_salt": "8C40367DF7D629BC40F5D01CC680C53F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7DDCD2740B158A2EDB7842390C73B169",
- "aes_key": "BE02546B3D28D0CAFFA8600033802837",
- "data_elements": [
- {
- "contents": "D095D2747F4A2EDE1623963AB0B48A2649E60C0255A11200044BBE",
- "de_type": 885
- }
- ],
- "encoded_section": "559013245407838E530FF4CA8D651DE3F4EBB79110003D4B11380D6AF601B651492FACECEA0B9002434F17846C767176E501E462F1E88F6256AE42BAA69F62FF748B1F10704C5ED834105F6CC1374C2A53C200BF8EA5",
- "identity_type": "trusted",
- "iv": "C6247D6BD8C642673B8FA1C533A9263F",
- "key_seed": "35CBFBDEFA43F8AD872C6EAF8C743076EFA7F938EC2B3D02FD034A6045536605",
- "metadata_key": "0359B617E2D475D366F7B2046DCB7383",
- "section_mic_hmac_key": "99DE9888F8AD547E181420DFE74D8412E13836BEA0DED59264102E68033BD0B3",
- "section_salt": "3D4B11380D6AF601B651492FACECEA0B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E644DE907183C18EB11F7B4A9C5D0725",
- "aes_key": "4CFECD89D5D364E176F67F127F1FB0D8",
- "data_elements": [
- {
- "contents": "A630BDB220762910",
- "de_type": 443
- },
- {
- "contents": "E10F32B0",
- "de_type": 298
- },
- {
- "contents": "6482387D8BBAD195CD",
- "de_type": 918
- },
- {
- "contents": "1BE384D2FE8053FE99",
- "de_type": 555
- }
- ],
- "encoded_section": "6190136FB3B3D8620CB4D3928F608BFBCC069D911000D48208F2E81A395B338FAB5BAE6C760A900459356113E165F119D38778927C6790DC5146415F4F254995E2EB98BD322DD85C4AE24D1F0CF4B0C26C46A06E5B72851A6ABD1D3EAA170A13F5A0",
- "identity_type": "provisioned",
- "iv": "8F553BBD4CBFF05A75898D3D39462728",
- "key_seed": "64ECEB1A3107369944DFFD3FFB9BB33D5177269BD7EDC99034888AAB415CF7B3",
- "metadata_key": "A6327CBE37966B45B0047F3B6D2387EF",
- "section_mic_hmac_key": "D3BB8A8AA1510F67E77EAFE45F79E4685F26D90E5044AF2EC02FE104CB06C0BF",
- "section_salt": "D48208F2E81A395B338FAB5BAE6C760A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F3BF8CE4146FEB417CCBEFF0575B6816",
- "aes_key": "F7298D234884DBB39C5326BE9CE58BC5",
- "data_elements": [
- {
- "contents": "1BEC46DF0FFE5BE99BBED7306A",
- "de_type": 533
- },
- {
- "contents": "",
- "de_type": 224
- },
- {
- "contents": "EEEC",
- "de_type": 899
- },
- {
- "contents": "82BB76BD6A80BF3A737E72086E8E992490971CA48C9A8B7220FF90",
- "de_type": 458
- },
- {
- "contents": "55E08CD9F499CF88B5778CD24C71C22B8933750C89",
- "de_type": 940
- }
- ],
- "encoded_section": "85901373651DA9F5520F901CB346E81A93BD0B911000536258509CB9BA353DABBFE54FA4826B9001485BDE12ABF28AEFAC16677B0520D2E545CB2237FF8822E97EDBEEE819385C1B09F12B982B0B2E2C0FB579F5294CAAD96D2DFBAA0DA210D867665F12A1F0576520BE4B11929C4FCA001D5AD95ED181FB8CF17BE130AC553C59F8E688AEF6",
- "identity_type": "private",
- "iv": "17FBACA04AE79C76C41CD2B82CD59C11",
- "key_seed": "A5BCB398B80D10B1FD2423DA6F342D113AEB13C34668E640A968A8733EFC942A",
- "metadata_key": "70E737B2D129BD7E2DF862F71B2E369E",
- "section_mic_hmac_key": "6E3223166BF4E3A185BECDDD34CEB6D8C9D3A9E698AC5B8864B83423E825F10A",
- "section_salt": "536258509CB9BA353DABBFE54FA4826B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "61013AED46837E354AA29735E8CE2453",
- "aes_key": "DE2D317CB7AA56B32B262326965F8A9D",
- "data_elements": [
- {
- "contents": "E8AB270D18C57B0ADC1CB3DC4C7449DA",
- "de_type": 335
- }
- ],
- "encoded_section": "4A9013192B45282D4FA290760B781F1613535591100075C506260F5D61EE14504C42FA5FAE13900479BCB215EE244D3C5BEA6A61E13FBFF3B3D49A9573819FD6929BECB1D8BE0DE085D6FF",
- "identity_type": "provisioned",
- "iv": "D8B19C28725DB25449B16530FBDECE2A",
- "key_seed": "A2D7FA151A0EE90ECEBA6D4F4BF7E85A2C1CDCE93D705CF59AC6A10D2C098240",
- "metadata_key": "8E9063E9449722E3852DE6C07E799974",
- "section_mic_hmac_key": "1F9DE18CC2C895DB4D880DE858CE05A5708B2FA9B8D3C69D208A966D5B066D4A",
- "section_salt": "75C506260F5D61EE14504C42FA5FAE13"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "05690CCA9ABE110947D18BB479062B32",
- "aes_key": "DA0D102B8953A994B76B1719C0041647",
- "data_elements": [
- {
- "contents": "161AE3D8B65862FE5AFC2D03CDD680F5",
- "de_type": 268
- }
- ],
- "encoded_section": "4A901385B1AC6803247FC7614C67F32266B3D591100079AECBDFB7F3F4301BFC7D23602E11329001FB8EC97CD186A2D2ED230FFE2A5288D7C82FF3C0E7317BE06C93C0453756B23A423135",
- "identity_type": "private",
- "iv": "83DDD162BE71C736E65BDE8181DF7A81",
- "key_seed": "75BCE8199AE92DC7A3DE9EA798E10186ADCE6473ECB78562F185CA6F3E8E98F1",
- "metadata_key": "A455F115BA43C061EED4320B1C4498FB",
- "section_mic_hmac_key": "BD92C0272C1D2CB10BB6506C8C721BCB0B54EA71EC83C8213698C7228CE3AD1F",
- "section_salt": "79AECBDFB7F3F4301BFC7D23602E1132"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E23B4C0D7BFB6FD8E6E0DA3261F9A3D6",
- "aes_key": "1768A8ACB8EC354B0FCD2ABAAEC64760",
- "data_elements": [
- {
- "contents": "23004D740BE1EE3B4B5A8DA3426480",
- "de_type": 756
- },
- {
- "contents": "EA0303D125",
- "de_type": 669
- },
- {
- "contents": "7541304A",
- "de_type": 83
- }
- ],
- "encoded_section": "579013390C93D780F8096F0D413AF90C632988911000814D8033C76A6E1B6B008F2E3D460D2C9001E94C0EAE1E10ED82B94C0A7ACE66BBE7BDB943A9BA6C1F2EEEB493A823DCDDEAD974FD717F8490E9B48EA52393E343CB",
- "identity_type": "private",
- "iv": "B5FB42C3108C8AE313ED69685648CAB8",
- "key_seed": "29A23FD4ED5E66BCAC1ABFBA0E9FB6FC0059A6354C42936C4599A355AE3AC76D",
- "metadata_key": "5A814D128ADA2D20663F759F0232DF46",
- "section_mic_hmac_key": "2C69B4EED4E52D3EFBBAF37E9749E2C1660B73A951A75198191F82AFCEA2191E",
- "section_salt": "814D8033C76A6E1B6B008F2E3D460D2C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1839D2C3BA13C005F5C45F0BDA96ACB2",
- "aes_key": "A030D853E042AF8055935DF441217CED",
- "data_elements": [
- {
- "contents": "2376F195FB1505C80FDE28394E2E398E2902A3CC84F9AD09FD221D10F0",
- "de_type": 53
- },
- {
- "contents": "99",
- "de_type": 181
- },
- {
- "contents": "4A4C47C2A18D15F2E4D1A89C1D4EF686C9CC40C1BC057C2CD1",
- "de_type": 45
- },
- {
- "contents": "C7BCADDBC0EAB47E6D22F5A11B59398E7354B1448FE9CCFD229A",
- "de_type": 814
- },
- {
- "contents": "FB62CE7C1BC06EB95602F99308D0393E10C833",
- "de_type": 433
- }
- ],
- "encoded_section": "A8901383E429525E34D29E92BD41227C23F2259110008265D5A57D3486212EF93FBE297FA43F90014E2A55BD81FAE9BD3FD32E7D6CA34D0840ABB8E12CF3BBD435270889D2E9B4286DB13CBCD73441D3433DDB05265FB5C691D77CFDC464121E194262F852EBF42CB2150CCAB45F4080AB5CD824BD0AED6EBB82EA5A26B26FD7B03B7F6E2459F48B6FABFFBAD719787564A505FBAAA90C5BFEE1FFCD39EF97847DB321CA2198E722B9",
- "identity_type": "private",
- "iv": "AEA7A390C40F8095ACEA1D8ACEDF3D12",
- "key_seed": "C1C16A9F6FE7E6C00A780ED9A2BC1C487F9268805B474D3A1FFDC74FAC8B4E11",
- "metadata_key": "6B2A826AF6C92F037F6FD7B91BCE34F4",
- "section_mic_hmac_key": "39FBA69424E69CC24A79B0F09FA447BD5165511FD98631380A8B261F683A3C6C",
- "section_salt": "8265D5A57D3486212EF93FBE297FA43F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BAD2528C1B7CB990D7AD3DCDCE3A23DE",
- "aes_key": "DAEB2E5F4394BE918AF351E93D7A77D1",
- "data_elements": [
- {
- "contents": "1597B826140F36A5953776AFA20014CA8CFBDE245C91A34D92C1",
- "de_type": 53
- },
- {
- "contents": "06D2005AEE6B77C800743724DF",
- "de_type": 439
- }
- ],
- "encoded_section": "639013E912574072B31B6DAECF1F281DB12A539110009BCEC0F8CE3CA49BCB70A4A232293DD99001DC051CFFD8482B3B4ADA0075EB65E1E16DF2E1136C057CD58A1045527F080A6F16497C198E95951DF5C4D854E167E80A1E5D0D2E62C1B3996095CB63",
- "identity_type": "private",
- "iv": "876E6DB1FAE9D6AC1498605E2D69D5B8",
- "key_seed": "33A85E4AB836104AA7F44CA998500558FCAFC256B2977A1F1C8511785DA10B08",
- "metadata_key": "49E5B24F9AB621DA9F7F7F2884A1C25F",
- "section_mic_hmac_key": "C3F6790A2B82BA0B17EA93FAF612E4CD3D11451A4D28765F843B73D7EF7B4293",
- "section_salt": "9BCEC0F8CE3CA49BCB70A4A232293DD9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A6447AA427EE701C9AA690F9984AEF6",
- "aes_key": "8873AABC9EA3D48F6EEA776A7E15A0EB",
- "data_elements": [
- {
- "contents": "D9B0253A3E1BE351",
- "de_type": 903
- },
- {
- "contents": "BEA6C715E6A06EC584526533",
- "de_type": 5
- }
- ],
- "encoded_section": "509013165A35A8BC76B529EEDE11257C4C929E91100040F88999F3934B36602BB79919F5EEB59001A6E1A6C4527EA8EE03C10B0E2FA65C0836BA3E179E5A8122A0C01CC4D63FB3BE89FB9E47C75EEDF481",
- "identity_type": "private",
- "iv": "0B977324602019C876020687AC0FD0F2",
- "key_seed": "EBD257397FD934222D84245BC1EA73A7D14BC02B82D2AD05E789FA92FB021796",
- "metadata_key": "4366982F4848A99069342C098FA0D5E1",
- "section_mic_hmac_key": "CE5958CD6416383EA202CA5AF15B0E810BFCD99488AB311A17A895A5AD3C105A",
- "section_salt": "40F88999F3934B36602BB79919F5EEB5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1AA084C1AF2A39928A561D1E9013CDD1",
- "aes_key": "9278ABB20D9C47298A0BB81C3BAA05C3",
- "data_elements": [
- {
- "contents": "A1042FF05E80458B9F79",
- "de_type": 926
- },
- {
- "contents": "4EB0D1BB7E711C9DB588F1ED5AFE54AE46A361B0547FA3C0",
- "de_type": 299
- },
- {
- "contents": "F382",
- "de_type": 220
- },
- {
- "contents": "DCECB4FA5BC7E7D72AA132127D27D43370480F1AB952E654ECD08ED5B28B",
- "de_type": 911
- }
- ],
- "encoded_section": "859013225389037B2722F8D27F2226F1449ACB911000AE062EE145A8CF45329EC95736762C939001BF95DC4B5B20BC1696BFF79264BF8CE88760D1BA0834E103C9C3DD35111224F93A46DDA193BCE22C3FFF0DEABD66C91933B5EA8B9D9DA8B8C8430FD8C4C9ADED4FBF843A3206D0CD4C2CF4258CC4C47FBFBB68C7A6D3E463C3D3BC2045F2",
- "identity_type": "private",
- "iv": "C789264887CAAAC20C0A84CAE6C16A6D",
- "key_seed": "9C0E8A9E88EBAABFC8620322B4DC189D17AFB01B7FDE0BEB5027AB67B36D58F8",
- "metadata_key": "602E08A242159621ECCBCF62A1BB77B2",
- "section_mic_hmac_key": "B9DA231118DFFE6E168A4561180D096196D7460CE3E39ADF400958A411E91F11",
- "section_salt": "AE062EE145A8CF45329EC95736762C93"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "618DAAB745E83D398987853966EB8D73",
- "aes_key": "60BEC13C1D8742EA4711CCE37F8AFA57",
- "data_elements": [
- {
- "contents": "A01201A2AAED58EBB95DA45C",
- "de_type": 941
- }
- ],
- "encoded_section": "469013F52ED257572229C484BEDA18270EA33A91100030A663A6FFE15F76DD3F29F84018F96A9002DBD150672794658EEE0B4D1324CAD3D9937518A48F7722287A7C4F15B16363",
- "identity_type": "trusted",
- "iv": "3D850D530781D998CFF408E7EDC5BA43",
- "key_seed": "48F03D01564000EFB7BC8EECF1328FC6489327A7C79AE7CD4C190B5C41ABB61F",
- "metadata_key": "1CED23D2582A5320DDC1C9A75F79535A",
- "section_mic_hmac_key": "4D96D070171E81DABA26D6F55BC91CB938B694AB4D6AFF7AC324BCE2A36BAD7D",
- "section_salt": "30A663A6FFE15F76DD3F29F84018F96A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F24BF18270E7EFC7882FD7300BCCC0CE",
- "aes_key": "6237B593C1E95DA0E71B42F390B79E3A",
- "data_elements": [
- {
- "contents": "5A0FB6BC7788",
- "de_type": 347
- }
- ],
- "encoded_section": "4090130BCE2E9C111E02B7CB33EAEFA76C1F189110009AE61B57A56E074D46354A6C28A6600B900291D225FD9D6DED94B1AE1A8DE03F95D14DBE075885CC06AD4B",
- "identity_type": "trusted",
- "iv": "9EEF6EB4A585A899C07623A06B6EDE18",
- "key_seed": "053E32D215D9706EB8BA952E5C2D520754349EB64BA594780F1D04883FC20B69",
- "metadata_key": "2E3EC7648FC3F6C1B64FE4BC64363DF2",
- "section_mic_hmac_key": "709572F18493C4CFA68B26676369A9A17FF660AADEAF01A6D3C9FEF62BA7B65B",
- "section_salt": "9AE61B57A56E074D46354A6C28A6600B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "141C71DBCD57779A9010CD756A76E381",
- "aes_key": "7EC0F06C9555C817D80506D742CAE986",
- "data_elements": [
- {
- "contents": "A3DA78C3A46A6465AAC28A7180F4AF3CED356195F59C354442",
- "de_type": 848
- },
- {
- "contents": "6FB0",
- "de_type": 612
- },
- {
- "contents": "5E86B240E0DA2EDD9FF1EEE13D08BF747F",
- "de_type": 593
- },
- {
- "contents": "3D5E1FFA8D17363A09EA3419E74ACAF8E530BEBFD2E5383435BA96E5E93D",
- "de_type": 602
- },
- {
- "contents": "629C",
- "de_type": 535
- }
- ],
- "encoded_section": "929013AED254BBC1126C996810D72CF962DE3F911000CC9DD44EEF9A16CCA9A5A353EB3F6C099004F512A3DF26EB3A448559BC668546BBC5E39939B408595D81DB2C9BCB22BF44105D4FC74069E211F76B1B5947632BAC38E032303C1E0BC15115DE5BFE6C5C64BBF75D7527DF0C1FDC42186D3B4E8A0B11F444E74E8455A8F32A792603FF5D06BDFBF4095FC8C3F19F2DC148",
- "identity_type": "provisioned",
- "iv": "1F3348A80250E67C0439DB33713640D3",
- "key_seed": "B8F2BB87A76D6B19C9666E5AF7DD06F0965DAC56CD5E18D500660D621B6806C0",
- "metadata_key": "791697B259A389A16454F472C26B07B9",
- "section_mic_hmac_key": "5F025042B03F8AF6FEFB3F0ED5D572D80D15189DC8ECCD27CF4EEF05F4A57F00",
- "section_salt": "CC9DD44EEF9A16CCA9A5A353EB3F6C09"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0DC36EABCD58AD31FD3414A5A79D856D",
- "aes_key": "B7FCF0EFA53B3230297545213C0524B5",
- "data_elements": [
- {
- "contents": "64BE90FC09B580EE",
- "de_type": 299
- },
- {
- "contents": "D9CE2C829CD03EA10E4EBE3ED32CF9F03848E2ECE7CAC2B5F062FAE306",
- "de_type": 637
- }
- ],
- "encoded_section": "629013586179ED9F640B114F3A74EAAFDA169E9110004F5F28DE93C71BD513CEAF1317690AC59002FD14A70AF3805F6DDA65F7309408708224077D83A630F4A6A28ED8F14F1E32072981D91CCC3AF19A091791B44927EA10A30EE18F261D3A902A5608",
- "identity_type": "trusted",
- "iv": "B841EB2BAAE284E872A3A2423601F00F",
- "key_seed": "131324FEF7EAB54FCBA0F40F92167DD7334863AB7DFFA93D1B2E05FDBF7F30B2",
- "metadata_key": "C39F84EF9D0EB94DDC0F35B032CFE945",
- "section_mic_hmac_key": "3FBB040970723C36D6DAEBCC475E95F100D5CA410C938B7C7552FAC69DDB7E13",
- "section_salt": "4F5F28DE93C71BD513CEAF1317690AC5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2F7A899B44F390B8C32AC3FFBA8536CA",
- "aes_key": "C757CD4202E253D64F6ADD70D6802F76",
- "data_elements": [
- {
- "contents": "E13B9414F8E4DC48F9E41F1ECEDE",
- "de_type": 873
- }
- ],
- "encoded_section": "489013F3E95BAC1CAFF7A986116C838955CA039110001F2D1152B9AC95ECDAD02511DC5ECC8790046AAC45B087398FC2276B1D1015032072B5AA69854873AF49A2F9D24711D6759A4F",
- "identity_type": "provisioned",
- "iv": "C697367BA74524CAB1168BFBF2922854",
- "key_seed": "2730B32C6DCBEE3DAA66CBDAE3BF9E42890B4E0B46C57D0700D58081814CA0D5",
- "metadata_key": "24AE50DE045D1238B2E0AF3EDE2E5C9F",
- "section_mic_hmac_key": "052A829770EC3DE369B2A4504D75DAAF28577A7F4638B0356EC924B23C91C5E7",
- "section_salt": "1F2D1152B9AC95ECDAD02511DC5ECC87"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A229253DEE5642D1A341465C48F81501",
- "aes_key": "954B9BC25FA0947752A02707A1D72848",
- "data_elements": [
- {
- "contents": "8F35A5BBDC9C1C",
- "de_type": 193
- },
- {
- "contents": "8894D592508CD3611F906F8AC44F706B1517F0B5980E268B99A0",
- "de_type": 124
- },
- {
- "contents": "",
- "de_type": 795
- },
- {
- "contents": "55DA51",
- "de_type": 902
- }
- ],
- "encoded_section": "669013C3BC7FE06F86785FEC6BB8D3EC2DF618911000DB52438878F9EADE488682807B3F9A009004BD9E07EDF91224F3EB734D17F3999A99C8262B2C91BBA94505C3DD67852AA19C7A748D56165A5399846D368009F6BA3131ED227A75A7D0BEDEC8FCB729FF26",
- "identity_type": "provisioned",
- "iv": "1C797DF15F0945FD31FB2CDE94CE2F44",
- "key_seed": "B965BEC0EFAB1BF93ACBEC55D5FEDD7A9E4E35D68ED782E805445792B8FC8630",
- "metadata_key": "0A51D7C3CBB8920ECE2C18C16103FF5A",
- "section_mic_hmac_key": "1B403F3B1542CCC670E677988496CAC0EC233748D4D488BE8C64D6DAD9E97DA5",
- "section_salt": "DB52438878F9EADE488682807B3F9A00"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0214D0382281CA031DCC305A1170C4A4",
- "aes_key": "3AAF3FAF8B3ADE10CBECDAD2C0F9D9DD",
- "data_elements": [],
- "encoded_section": "3790137A79252A76378480754C9935BEEAC40E911000E697F979481D94C83D143D416EF15B0B90023C2D0EA174FE7B0F748EB3A897F86CBA",
- "identity_type": "trusted",
- "iv": "08AB0C2EF3B3DCEEFE63E345EDE819B8",
- "key_seed": "236811C3C81857B831C028B6828F2E28AB948405B391377895BCC1011A82D87B",
- "metadata_key": "8F3FB1BBD7CC2596188C022C816BEEEF",
- "section_mic_hmac_key": "AAB0A17B5A667805AC94E43D775FFEBCF4832CF67F7839D8B60FC6C739C2A9AE",
- "section_salt": "E697F979481D94C83D143D416EF15B0B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F6579933CDF9D9BDA0ACE32E7EF5718D",
- "aes_key": "C939D6AA33F9BB4FE73AFABA9DB89CC7",
- "data_elements": [
- {
- "contents": "51C2163162B4A1ED861DE57103CFB2C8CB4DEC24B75710563AF3C0",
- "de_type": 969
- },
- {
- "contents": "BC465AB618F9A89C2D6DCCE131DC68B3CFD45ABFE9B3A898F5B21EC3",
- "de_type": 386
- },
- {
- "contents": "99",
- "de_type": 51
- }
- ],
- "encoded_section": "77901388ED01CF901FB3C6740072CAE51AF8BE9110003A898F8BE6FC92035BAEC946D5CA2141900175BE48A38808002A983A169C804D96B80CDDE4849FA6CFF66B6955B8F60194B29566F29DC113B5A7DAC4EDEB369BE2B93C9CC3D605AE3FFE7CA863B9F9089B4477A1E591DAEC0F1FBBB2ABB65445E71B",
- "identity_type": "private",
- "iv": "D07741F4556EDB80F156377E05D86AC7",
- "key_seed": "6EF6407596F397D8752C31399ECFD94165EEFAB886385098A7D2E62A0D322D65",
- "metadata_key": "7005FC4F95DD57D7CBBA8286480EC221",
- "section_mic_hmac_key": "D68F4EEA77F4A3A812BED734FBC151E6B564984E5BA51BE94F018B0F0E0A40A4",
- "section_salt": "3A898F8BE6FC92035BAEC946D5CA2141"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "93A2A5408CB92C828DC2706D184B93B5",
- "aes_key": "483CE8FA0C97190150C89044D0A3B562",
- "data_elements": [
- {
- "contents": "B74426C4B81CD14DDC66B5D81F5048F35645CC49D784BF1901DB",
- "de_type": 540
- },
- {
- "contents": "ECFD9C9D59E8B557A961482F3CD9CAE1EC82445E",
- "de_type": 684
- },
- {
- "contents": "16CE37BBB3AB",
- "de_type": 907
- }
- ],
- "encoded_section": "749013EB2EC9939D0B5AD346C488C81AB2B7A59110003FB7A780A3D390141179A24BA5E348749004D79AE3EAA467DCDB6924035AA6B730BA38A3BA0DBAB8FADCAEBC40EE87FB03DAAE8D04D7F09A98C5DD245BF1993145D63CE6F39A2F2A954850DB8CA9B9927F3B8B7A0FB3D7F2FDF967C4A77C1E",
- "identity_type": "provisioned",
- "iv": "1B2672F3752153E4719D4D50F75B32EF",
- "key_seed": "809959218AEE024135CF2F9D03A1BCAE95334C91241679F27D0E4BD6AE2D7A9A",
- "metadata_key": "AB90DAB8B389AAB3B96925579A583559",
- "section_mic_hmac_key": "F324525CD2C3407588B22B71BF7B879ECAF343FFA9860876D584BFF14594E621",
- "section_salt": "3FB7A780A3D390141179A24BA5E34874"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4CF830D5D5BD08C26F4BE1EA5B97A4C0",
- "aes_key": "F66E71F797BEEBFB0150F2C7F4C4ACD7",
- "data_elements": [
- {
- "contents": "F16C3CEE603F93",
- "de_type": 538
- },
- {
- "contents": "F65E08453918E6910CAFBF87155D9B7D8E020B816BE6F064A76C2FFA3BEA",
- "de_type": 728
- }
- ],
- "encoded_section": "6290139D6BDADE8B80272A9C4DFA705CC8CD38911000FE1EC77402715D1928D59BC1A69DA35D9001E45533C131CE90457E1433650E9993DF71D74E3B90D98B1B2B7AFBECB6EBFB479C58E7AEC3EE3F689AFAA7515CDA6C06546883365168066BAD9371",
- "identity_type": "private",
- "iv": "7C7BE58937B2383F8EA9C91B1D8ACD8E",
- "key_seed": "1E368F539AADA86EB50185328B05D9D859ACCB951D70AE6BCEFCDED587598484",
- "metadata_key": "9BF76E47E18DEC4135F95D65CCC5AD5D",
- "section_mic_hmac_key": "1A7880A4B012784166BB7BE7AD91425AEB6E10DA105FDE534824B10FB1F01B3F",
- "section_salt": "FE1EC77402715D1928D59BC1A69DA35D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "42BCF8C051CF5BC8D61B1C61865A3D0E",
- "aes_key": "7A7B9705EA9E3E6BD24E89A8B5EC5629",
- "data_elements": [],
- "encoded_section": "3790131EEB4FFCF3E322EC21209253D804E5F2911000EA5BCAD5F2FF77DB2C44939BEB5D1DF590045CC1115031BBEF4F64F4D7200CD7EFED",
- "identity_type": "provisioned",
- "iv": "48345860EA2F626260C6BB20B166B245",
- "key_seed": "C61CA661BE7F95C09DEDD5E5B3AD5EEB7C83D5023B95CE53F5AC471FD7A88817",
- "metadata_key": "2D8F7FD76DBFD36FC69923CB084C2ACC",
- "section_mic_hmac_key": "DAD99FBEBCD2787C70637F3163FE6D98B3F12DBC5D3D68ABCFD48D7AC7FDF563",
- "section_salt": "EA5BCAD5F2FF77DB2C44939BEB5D1DF5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A8C7424675FA2E7091A36C6E61AFDA42",
- "aes_key": "6B31245D4D06FA075F0FE3B368DE594F",
- "data_elements": [
- {
- "contents": "7527234E872383C3816F",
- "de_type": 48
- },
- {
- "contents": "31CDE714BFDB05AEACB81C2ACE",
- "de_type": 272
- },
- {
- "contents": "AD37A2754F3B9B",
- "de_type": 772
- },
- {
- "contents": "1DDCF4",
- "de_type": 461
- }
- ],
- "encoded_section": "6390136E1F6E5E79E07AAABFC71A1ADDC6855E911000B729ACD6ACEE902D62B36C16CA11B8F69001B5E54164389AD739445D291F8BB668F7D5F486336BE306D2E7537088CB34FF31793C482E1AA770D33E0EBCA3FA909F635EE801E8804D85EAB562B0A4",
- "identity_type": "private",
- "iv": "667E4FF1F49AB32EC02271C50F00BBCB",
- "key_seed": "11E0919824E99AFA212ED1EE264C0CEE2079394A139A2A4E4E0480390224AA2C",
- "metadata_key": "AE5E4C5CBF11AB13A15F2ABB45C3AA28",
- "section_mic_hmac_key": "900B1BA0E694FDBC069672601E3FB6A7E1ABF57DCA900F43D366A2D433BE694B",
- "section_salt": "B729ACD6ACEE902D62B36C16CA11B8F6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9561280F565350C87CFC48E0E922D70A",
- "aes_key": "0FBDD950CB6A77E49DE3DA873E05BB4D",
- "data_elements": [
- {
- "contents": "57EB419A6FDA6E141E64C96DA56184",
- "de_type": 157
- },
- {
- "contents": "B7F29895592845FD1F68F04F50E21FFAC6E0745B495D4D33",
- "de_type": 725
- },
- {
- "contents": "96CFCA71DD4AE920DB33",
- "de_type": 63
- },
- {
- "contents": "9A186713837F3023FDA2ADFCA7ADBA5F",
- "de_type": 802
- },
- {
- "contents": "8295CE8455A32E12E72A1A3EE445F3A7ABB33F552E28E8AF3B49",
- "de_type": 650
- }
- ],
- "encoded_section": "A0901301554DEAA33ECF529285855175B4075F911000F1B7A762DD991286560F50C190AEE84C900410A344196A44F2872D97E4A52C86D4705A0154AA77B0B6A8CBC8BE5707D232C64F3A58123494FD117DCA5F66289BAA6C1342A3C0139362180E4BC01D739BD9AA658244621615B70C03A47B547C3AD84D84AFFA59633EDC39CF23B84A40AEFAAA1F4EF584BC9F8C62E177641EAF8D2D3B5B72E70F5610EDDD66",
- "identity_type": "provisioned",
- "iv": "233ABC3B5240F3277A8A3D9B77736EB8",
- "key_seed": "B3903A0B6F65A51C04C61F33DEAF2E4E2F8D9593C0418A08B5DEAE1B4B5083CD",
- "metadata_key": "C20215BF9D23940621D1243DAF4EC38F",
- "section_mic_hmac_key": "2189BED3EEB1C7F254F0148D32B6977850DC2393C6D569DC58F32AF838DA075B",
- "section_salt": "F1B7A762DD991286560F50C190AEE84C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EBC1A6EFA2ED8CDA77BAF544E4D904A4",
- "aes_key": "65E3A98AF7B85AC0781A211CC6FC72E5",
- "data_elements": [
- {
- "contents": "3945EAF5EF2E084E1F",
- "de_type": 46
- },
- {
- "contents": "12E6F96050FACED899537AE8A6",
- "de_type": 997
- }
- ],
- "encoded_section": "529013BAD0AC44AFA4063EB49BA6CF34A8C03F911000774CFDF9430D5C16D57FEDCC76C727E29004BCB33E582FD7A3C616E6701A38DF24A61E13FC2680162A038B6419348DC7639F9DDA362DDF9A6545387A1A",
- "identity_type": "provisioned",
- "iv": "AAE212B6EAA3AA96187816E6FA3B50B2",
- "key_seed": "310998B2C7F6D69281748342083D74ED44885D73C8873E97C0A00C866332A49D",
- "metadata_key": "8897F642A09797D2D710391CE3F9A679",
- "section_mic_hmac_key": "74D664F756163C18681A9CBE553DEF5E0B17C040E3E3B265CBD3DBB3A931FA18",
- "section_salt": "774CFDF9430D5C16D57FEDCC76C727E2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "540624C3D336F7667597EEA1FD0CC48B",
- "aes_key": "CA3CC08E1C4FB3974D9DE0A9FAD09077",
- "data_elements": [
- {
- "contents": "5467F818B3EEB029B82D47A14A4E6451DD58EAA0030EF12E14",
- "de_type": 565
- }
- ],
- "encoded_section": "53901331A52875544D7A7D299A2D6BD3EB0D86911000EDC8ABEC4C7FE7D3A91094D9727CA4D690019C8DA9BEA8B990C4BC1F6F464675F74AD38BFB28C419904C514A9A1E22BFA28285D757D66DF54C47B115E01F",
- "identity_type": "private",
- "iv": "60998CDF9DD4FC9271DDC24FD00BF4E5",
- "key_seed": "563B6F117F7191C693688B2C98794AA4B1219C581D2932A7636338E4CA8D995B",
- "metadata_key": "E6ACE435015C0967BEEBC7525C84A68B",
- "section_mic_hmac_key": "568C17091F1FA841D94361047719BAF85ADDF57B13C190BF3D2801A5B229CB5A",
- "section_salt": "EDC8ABEC4C7FE7D3A91094D9727CA4D6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1BC71DB7C830793A62D4A1D64A194DC3",
- "aes_key": "F00505EF81341DD41628D319A51CB9AE",
- "data_elements": [
- {
- "contents": "72FC3313D216E421D5283686FA",
- "de_type": 166
- },
- {
- "contents": "835C0734",
- "de_type": 332
- },
- {
- "contents": "",
- "de_type": 236
- },
- {
- "contents": "6076F43AF0A453CB8D740CF39EC6",
- "de_type": 789
- },
- {
- "contents": "195A1FBE7A2D24A4C51D6796BCFEF82C298B3EE3F8B6B96FA53CF83D",
- "de_type": 102
- }
- ],
- "encoded_section": "809013BBFC5FEA8BAD0095718AD322503E917E91100061E7C6ED035A4567FFE6C83A52560A759001DA6B1C2FE7F73DAC214C4074DAD30A2099CFC96A89754C6643189C43AD82BC5999F79228BE9B2812A94F38A569194DB4AD2F0867CFE968BA6B993F8AC07E026C21B57D8AA2B4CC0CE6CF0C940191842F5D4F7E1FE9EC9194B3",
- "identity_type": "private",
- "iv": "C49795F17B8BA9676DBB69DEE5608FA6",
- "key_seed": "9E55B64D97D55AD785A2D5CFF54FC31D8C2A10423F03AA4F41CA007BF5774179",
- "metadata_key": "96332ABC07154AAD77CB7C037C364D8F",
- "section_mic_hmac_key": "32C65336074D2DA5CB55280E59DBE181987F1631936DFE783CAB584B52276517",
- "section_salt": "61E7C6ED035A4567FFE6C83A52560A75"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "173A13ABE2FF18D2F7109239F401FB21",
- "aes_key": "333CD8634CB7451F95519C052CBDF152",
- "data_elements": [],
- "encoded_section": "379013096CBC2B8A796E245980C1862ACC387091100082E5BA46988B576F8618B5B352BB5AC990028EC4EB4825905EECE11DD62509238E2C",
- "identity_type": "trusted",
- "iv": "54E19448030FCEFB036FA3A918EECD42",
- "key_seed": "F677983EE2A9987F61F7DA6B886866362469221DC726518FDDA105CEC41563BA",
- "metadata_key": "D468CD1134E0BE76ABC05A5526F18EE5",
- "section_mic_hmac_key": "42A1576B2B917F654B6230579B98D0BA1B999EBAE10F99EA920878A3C15DD211",
- "section_salt": "82E5BA46988B576F8618B5B352BB5AC9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0600099A02ECCCDA983A853EA87B40CE",
- "aes_key": "F8361A483C7259A77A4B9F7BCC18CF4E",
- "data_elements": [
- {
- "contents": "0B1D4CD6D6D51CAC90BC02A63137AA3DC785E9ACDC08297B54AB0456",
- "de_type": 152
- },
- {
- "contents": "EA8FCBA28B2CA1FFAC4B2C880398B79C7D6CD79AD24EAB3A9F0C01",
- "de_type": 789
- },
- {
- "contents": "2B18E586B9BF45BACE62A8B8EDA7",
- "de_type": 913
- }
- ],
- "encoded_section": "85901302F968F6E1833E28F19F63391E02600E91100006F9E19728E0AAF75BE4634A1F8D7C679001DD5679B2068AF5DC2837E39A3B7140DED6261AAA8A19A8FD604F9B3C50805488C86DF7FA5C7A42443B73C78696A212057B7A6B2E3CFE277B29A3A5A5CC6C441F78C4E2644F4DBB5A6214820B3D184477CDB3F54442D0045C5C81953FB6C3",
- "identity_type": "private",
- "iv": "4ED9F6DDCCA5759F3290615269114852",
- "key_seed": "A82F0B67DA493625BE38FAD39EA6116A78505439EB85294438EC967E0BB92974",
- "metadata_key": "7EBAC6AB7C2E3EFE20C185415935BA36",
- "section_mic_hmac_key": "93689F1002288DC64C2CA81A3ABCE1CF4CBA0AA1F2F1DABC39277D57E9C9199C",
- "section_salt": "06F9E19728E0AAF75BE4634A1F8D7C67"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FEE965C5BD73B49EFD8B3D0AD98D823A",
- "aes_key": "F3085A213CC43098896781968F34CF93",
- "data_elements": [
- {
- "contents": "C9E41D4978E8",
- "de_type": 328
- },
- {
- "contents": "7A984B285B2F5D5DFC1CBA0B0C23CBF62C",
- "de_type": 950
- },
- {
- "contents": "D5BD48E7EA000500FB4D",
- "de_type": 325
- }
- ],
- "encoded_section": "619013B68441665A2CD396B8174905412BAF759110006EB5F5B21043BE04D6972AFBB86D172490014D74B48E16FD27458628305F62BB5EEDBFF77533E1C8263FAD5376C7D167245435D48B7D1EBB91E89A39D7D5061EAA1150E40B73D7542B2C5109",
- "identity_type": "private",
- "iv": "B4A43F5693F7467CB19116D40367BD3C",
- "key_seed": "12FEE160551F2297D799E1571A8046AE738C4916ADF58AB6E8BC5283B9DF5A9A",
- "metadata_key": "C42AE1BD877C17986AA1A9F062866318",
- "section_mic_hmac_key": "208087A638859B6A21F491E525C97D8AF2C1C19945DC8C84227DD2330F89812F",
- "section_salt": "6EB5F5B21043BE04D6972AFBB86D1724"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E6AF288C6E7479E495EB7FD64E6A311C",
- "aes_key": "3BBB312D4C50E6220418CA88645FD3C3",
- "data_elements": [],
- "encoded_section": "3790135ADB592FC4E3261881C033CA13B722039110005CFCC4E76959DE69A46A26110CE5F5DF9004717A64A5F01E52B35C3229F3EAF20B46",
- "identity_type": "provisioned",
- "iv": "D93C814B4EB98D9D9A65D00AC707FEEB",
- "key_seed": "67C74FD2F407B1F2168B9AF4072CAE89C5CE31E5CABE1AF1C318652C16234309",
- "metadata_key": "C4AFF7489F452F80EFF17D0C1ECB7591",
- "section_mic_hmac_key": "8F5EDB51B470611B53995F6D852A38302EA98584053DF49D5283CD62FA873885",
- "section_salt": "5CFCC4E76959DE69A46A26110CE5F5DF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49BFBD2B9DA62843694633F892D4AF90",
- "aes_key": "DF226FD90BD7B42958EAE9B73D9F3107",
- "data_elements": [
- {
- "contents": "F0A7E8D6B009594814B97DFB5C3052AC0255ADE9B6AEED6BFB25A670A4F1",
- "de_type": 525
- },
- {
- "contents": "984EA937",
- "de_type": 72
- },
- {
- "contents": "537A4993C8A09B85C312",
- "de_type": 6
- },
- {
- "contents": "F2B65846498D58ED36F7",
- "de_type": 56
- }
- ],
- "encoded_section": "76901353D6074DF5E26C64A67DCEA4B54F4FE591100089522D3D4E82B879A6E227EABB6F5BF490021152819FE7C31E3AD6BFF55EA31B88B904DAC0687D0ACB304C7120D4ECE40AA347B7CC2FAEA00536233297D2976D13BDB1349CE159477020DC0541FC247FAB7E675E6746872058906C27EE206830B1",
- "identity_type": "trusted",
- "iv": "363DE09F4423704E05DA5D1A603F88EF",
- "key_seed": "F7E644C0B35E3639F0759DD3459A4E81A7B5B1467D9E27782C9D58473F7D2303",
- "metadata_key": "20B6032091C7B497C9C715B44A680055",
- "section_mic_hmac_key": "AC7F9AEAC350B2BC7835A6953CBF050FAD9B1C761CFF5BDB1E766AF51DC97E6C",
- "section_salt": "89522D3D4E82B879A6E227EABB6F5BF4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9AC61514FCC5ABD76F8B6A60FFF0CB23",
- "aes_key": "65A5B1C977CE2B71E137FBB66464E4C6",
- "data_elements": [
- {
- "contents": "AC018897D3B2098C96B4B2D04B18356AFDBE76873E902686",
- "de_type": 433
- },
- {
- "contents": "E6268BD9E23FBD9F54E89A33A9B953387C0875D16FAE",
- "de_type": 859
- },
- {
- "contents": "CAA87F4364C08B57BBD4",
- "de_type": 524
- },
- {
- "contents": "14300A4595500DEB37",
- "de_type": 734
- },
- {
- "contents": "54C2A5437292",
- "de_type": 606
- }
- ],
- "encoded_section": "8D9013578908536364B9F6141A96126731958C9110008FB91F1844A5A3601A18CA350436446F9002F172ECEAAFD2E24578444D8CA68C014E1BF6722524A2750B1A9E5F4CA3340EB3D4647E45E35F69C330C0918FE002C922F30018934D9CA78F81A41FE035CADF61D135281371ED2B022E532D29D9853BAAF17D7A66AE0EB5DFFF9E66799D98C36DA0EC17BF7971",
- "identity_type": "trusted",
- "iv": "E4F6D7F01E683F03820110FE9B9070C2",
- "key_seed": "471763E7BB628F2107F6AF8F71DD0429FF9012C7BE7EC58C72F5C6CDE1C3C880",
- "metadata_key": "949F830445560E2C7E0E156F2044EAAC",
- "section_mic_hmac_key": "03D47D91A1AF8EC0141E699BAD459E2EE7F86F9B91A5386DB8D0D2218BA13E8B",
- "section_salt": "8FB91F1844A5A3601A18CA350436446F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B796C0B874B37A965A635AACB0305B1F",
- "aes_key": "E000F49E7E5F8307D27A471E27875CE8",
- "data_elements": [
- {
- "contents": "211B11FE2C7B3F8A8907468866B92695234B9C06C56ACA1E7EF5118061",
- "de_type": 336
- },
- {
- "contents": "2CE435BB39131E9603EA734E8FEE299F26BF598EA5C2F0FFA518DB2C92E0",
- "de_type": 228
- },
- {
- "contents": "DAE3FC39546D53AD1A3A",
- "de_type": 470
- },
- {
- "contents": "9A2A563675DD8BFA71C9BE13C479DB4DE2544FB97004",
- "de_type": 266
- }
- ],
- "encoded_section": "9E9013F0451460F5EC18035FDFCC9B233FDCA29110003DD4F4235AB965B797DEE44EF0A0360B9001BEC49A84632B991E0A5501A56ED3D9709C189FAEEF2445DC131AEC2343D7071A578293B76D3F849B80C372268123838CA9FC2B0E14A41992CF2AC92DAD1299FA67225BE71F479FFA312946AE18774AF353C3C14C346A04F24747E6582F7C528AA1E49E9E03370D053B2D95178AD336A42367AB578EA993",
- "identity_type": "private",
- "iv": "0778412CA588FD3D607A36B1BBA305FA",
- "key_seed": "63212ABDE0EA4E8542FD2403A0091CF53460C2CBD7BBFE6A434D24D6B871BEEE",
- "metadata_key": "F61E19A50DE9B1E486865A0498D4ED59",
- "section_mic_hmac_key": "5E754AED53501C62B51B214B3E21E8C1A39D0B8F1EF47FADCEE9C7391A437F36",
- "section_salt": "3DD4F4235AB965B797DEE44EF0A0360B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "08F6F482433E821BF057DA969070B210",
- "aes_key": "E17992E3DDE2E17996BF2D26B284BF2B",
- "data_elements": [
- {
- "contents": "E01D05404D",
- "de_type": 656
- },
- {
- "contents": "DBB677B7AD69380E50712C",
- "de_type": 651
- },
- {
- "contents": "2983A0843D5DAB0CC087BD5572E983CE13C3F059",
- "de_type": 515
- },
- {
- "contents": "DB40E040A436133BE734C5855B",
- "de_type": 515
- }
- ],
- "encoded_section": "7490131512D60F63CD579B350AE46C619240C59110006CB2D3074DA5611D18E7200EA58D4D2A90010804A23809C9E79F68830337C1561EF95B58C35AF60D256BF58BC367C7C3CC923AE044959E8766170ECF6E24971DB1FFEAC71D76C7592C53B40B5D594BEEB51423C72512C50124951928ED0B15",
- "identity_type": "private",
- "iv": "E51C069184919CB5C41DF3A1973A12EF",
- "key_seed": "3AFF0BDBA428B3E7A75CACF64B960384ED52F6055B53DDC869411C00CE3DFB33",
- "metadata_key": "C7FF94EFD6BA7F4D49753C9C51F24C32",
- "section_mic_hmac_key": "23FFEB85772F286F363ED40589D9069BB0CFBAD80C0F4709F2D7EA4D53AFD56C",
- "section_salt": "6CB2D3074DA5611D18E7200EA58D4D2A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E01A36923644F0AD58157CDDEE3D6E57",
- "aes_key": "28A7CB11218C9DD608B4C8A3BAE62AA5",
- "data_elements": [
- {
- "contents": "4713D017ECA392781333",
- "de_type": 890
- },
- {
- "contents": "FAE2DEA46755BE0C6E0BC28C8587",
- "de_type": 406
- },
- {
- "contents": "CCDFAEAF820F69BE029967700E8D4EFA20",
- "de_type": 192
- }
- ],
- "encoded_section": "699013B733E709907E9B73EEECE403065285699110005A8F6B53799B2B96F01116C7EA43B24D9004C0CCEF4A0B0ECBE91A422DD0ED9680D23781E95311D3C78E5C154F71BC726E679AC9BB60314D4DE9B19994A6831286FA0A22B438098A7D10FDC1060F7354D0B4D6F3",
- "identity_type": "provisioned",
- "iv": "304D96C4F8C3E724140E327EB02BE4FA",
- "key_seed": "4D76E8957C3244719D51B9433DF83AAB034452817E76DE43F5428B948592F061",
- "metadata_key": "E158F1E40D3224565939655BC879DB05",
- "section_mic_hmac_key": "1CBFDF042B635283167190A9E19DBA9D5EB04492AFDC9D4AECF9FD3DEA2FE78C",
- "section_salt": "5A8F6B53799B2B96F01116C7EA43B24D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "093EA5DB990DD969FA4C4EAC9FD04300",
- "aes_key": "C42479C9A8EF89FE3A3A83C323E39075",
- "data_elements": [
- {
- "contents": "C5CEE03E05232CEB2706FCC52D8582E15D6E0309E39BEB1049",
- "de_type": 376
- }
- ],
- "encoded_section": "539013CAA95A7BBAE1DACC4C1493F1631714F39110007D6EAD457D2F7C96C246A361CE6D51F890029BFF6C5561F0D23FA684E8B3C5B67190B0E869847A48A703596DEE74C063E03C3796B437DF451F2E580E070D",
- "identity_type": "trusted",
- "iv": "3C508F99B78AB555A8FCCB86D451C384",
- "key_seed": "9CC130089BC7A521C459F6951588707D1C39464D4FC5F83DE02A388DD9B9CFF6",
- "metadata_key": "8E22B372F7843A39842E9C99A095222B",
- "section_mic_hmac_key": "BB1185F021C79BA0B12496AB407BAC3B925D6C0D3E0FFB3D2489F110436C3725",
- "section_salt": "7D6EAD457D2F7C96C246A361CE6D51F8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0D3999FA6D616562631A00DFA536DA4B",
- "aes_key": "106EDF096A5A90718645B2350FB47A8B",
- "data_elements": [
- {
- "contents": "",
- "de_type": 913
- },
- {
- "contents": "0439E4BC4E416859331F994B7A7967E242692162F0A90DC74A",
- "de_type": 572
- },
- {
- "contents": "3E46E2",
- "de_type": 133
- },
- {
- "contents": "C4D2B7F9B3404DAFC46AC58BC4F69525FC63290AB1C752B04B19349E",
- "de_type": 248
- },
- {
- "contents": "70D3E5634D",
- "de_type": 544
- }
- ],
- "encoded_section": "8390132CCE2783ADBF25B7605743CC2B5D735491100048186B398DF4CAD231B9A47C00BD02E29004AB47CF0C18763A5271A3CB987B200905499C2BB25ED2F511D33457321E221A4996DE183BD314F1EFAE36BC4AFAC00E3FE61E822D6A0C90E4964E39F50E0584ACD334757BCB7B150E9569E2F9B9E66ED9F09E1DACDC4B9300D8FD0D7B",
- "identity_type": "provisioned",
- "iv": "727C01C9645EE10F343B1F653FA8A03C",
- "key_seed": "4CDA79980B1DF514C24C2A80C54C97B1DD2ACE9146FFE02B8D02317D7DC7FD33",
- "metadata_key": "A4BBF9DDA5775F84FFC6E7A700B85F40",
- "section_mic_hmac_key": "09863C0F71491893C00F06B6A38F5605951379845B88997B4C2FD7AE03BEEE05",
- "section_salt": "48186B398DF4CAD231B9A47C00BD02E2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5F0DB8BAB212C01A15D1276C8111EB75",
- "aes_key": "FD0804A8059A889D6462E272E40736DD",
- "data_elements": [
- {
- "contents": "3AE626A64BCE",
- "de_type": 913
- },
- {
- "contents": "081BA24B63DB458284FBD02292F412DF67C22EA5",
- "de_type": 664
- },
- {
- "contents": "4EDD5AE85FBAD3B50947",
- "de_type": 414
- },
- {
- "contents": "FE5636FE49CC9B62F3F6F7F3D234D1C2814CD2",
- "de_type": 252
- }
- ],
- "encoded_section": "7A9013E2817D9D32C943EA7A07C69CB39C1F13911000CBCD80EA37EF7103BD971F1769362A6D9004B5D90F3F4B85363C35BFB1C5F2D33A6C32211C91023263539D31E4101561FA16843E7099B3ACE21CC285A818E5B121A53B8DC0C12AE39B07A1312A3E8DAB1854D32A11BF3AD661BD02FB69107D00509D5ABE30",
- "identity_type": "provisioned",
- "iv": "C85ED610C5284B60E85EE2EB65D824CA",
- "key_seed": "50CC7E8BB70A560801376BE9507637A2E0DABB2C27C57ABBD4C6655996B310FC",
- "metadata_key": "8AFB53C6D5AB8A8E040D6C43925ED79C",
- "section_mic_hmac_key": "5EDBF3A1B90AC15F795203F2B7A62B8202C365C8DDD12125CA04492C666D5029",
- "section_salt": "CBCD80EA37EF7103BD971F1769362A6D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4ABE96318E942D913EFEF38CE35EACA8",
- "aes_key": "00CF98EE0A1B419B7F940F74FF10EE6E",
- "data_elements": [],
- "encoded_section": "379013F61D7E6303A40196D23DFCD2FD4AF8B19110003BD8AA188D8F355F6611B84C94D418BA9004FFB8BBB535C1A7E1DBF8A12938BCE857",
- "identity_type": "provisioned",
- "iv": "7251E4AE74A6EB8322818F09A004A0BF",
- "key_seed": "0D13BBE27EBFE4514ACD491F0E66FC7BB7A115D79B73296EA83036EA681EE1C3",
- "metadata_key": "238B7E260087E6974BF1001BD92CE7FE",
- "section_mic_hmac_key": "4D70D13E0DB450B18F9B90584E9089EF8D8B0B21C1F28017AC0D542EE0201DEE",
- "section_salt": "3BD8AA188D8F355F6611B84C94D418BA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "72037D0250C97CC1C26E0E715934B7F4",
- "aes_key": "C96ADC6223409E5BDEB7AF3262EFB102",
- "data_elements": [],
- "encoded_section": "3790132EF73EEECCE1F32344D242781918B3D6911000D508D8EE1CB7B5B4457C34EAA1408D619002BA08D2ED7C5853A1C7D3661639BFFF3C",
- "identity_type": "trusted",
- "iv": "372B94248EC23F30A455DF27F397EE0B",
- "key_seed": "C1DE01E9F5C668EED6E11935D5306F7610CD174CB883353086456D5D9689C611",
- "metadata_key": "FCC9F9A491F6763794895FC2E8F5DA13",
- "section_mic_hmac_key": "C62A4103BDAB300378CC50CE8F28DAE28D78D3C1F07219B2E1DE73FDCF606332",
- "section_salt": "D508D8EE1CB7B5B4457C34EAA1408D61"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4F0B46BD474614611D7A9D1BA9DE0C03",
- "aes_key": "C5DDEC1F35F8B6974302D062297B6792",
- "data_elements": [
- {
- "contents": "E772DE467CD7896B78A062401310DF60A12164085D31EA7B",
- "de_type": 783
- }
- ],
- "encoded_section": "529013276DFA6BA513BEBCAB169691B61FD79191100093F60AA548031530136472E90FA8B2989001B948AFF95F6998BA8C8D95BC5B75710DE26D6A391A649AE60DBF82DA9AF2F8B01CDEF8018F226FE575B342",
- "identity_type": "private",
- "iv": "68F95B82D9FD1727831B1A18ECBC0F07",
- "key_seed": "16120AD8398950406E4A12D5133D3C8F71D961E051B0970CAA8F8FAEEC187F83",
- "metadata_key": "035A86F026FE0A595C1955FB1ACE685B",
- "section_mic_hmac_key": "842116F8CB1EE997C7FECC683959AB4CD8EE3EC9C61152DE56F2BD2446A8F5E4",
- "section_salt": "93F60AA548031530136472E90FA8B298"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CD771B262EC5CA3A5C0D0FB4B4D0A9F1",
- "aes_key": "073C363B4DFA35C507EBBE01F75D4ACD",
- "data_elements": [
- {
- "contents": "A510D052E5CDFE9B7F96A7076213D0D996D24E4D99",
- "de_type": 220
- },
- {
- "contents": "B0C476C075412AB26C51E6C0B8A01DB179F42A",
- "de_type": 651
- },
- {
- "contents": "A382A1DC37",
- "de_type": 961
- },
- {
- "contents": "BBA6CD7F93C8F950C7E3",
- "de_type": 630
- },
- {
- "contents": "EA45D2338F1A82639512EFD7A3DAF1716FD9279B32EED2",
- "de_type": 448
- }
- ],
- "encoded_section": "9490137FDA79A6A4413EF091B89DF894715D0F911000207A4ACED9DD7DF5469BA445D82C4A509004574B862AF8A5F1ABE9B7160D138C98870F4424CA9370D51712D0396D87644A2EDA5077AD5174F0FA4FA9F10B9B9E303D5CCEF3A36BA46D97F655644F44B747ADC2EC2164AB66CCE1502BDFA2FF38CF44D9B059DA0CC220246444E388020982B1267420374E3CF50BCF15FEA821",
- "identity_type": "provisioned",
- "iv": "8CE19168A15D76869969155EC24DB3F2",
- "key_seed": "2B685F1252FBFB847B415DA3AC973CCB495EE32463325C507A28319AF15FEFDE",
- "metadata_key": "7D65245E7BE0CB380D42E4D080C4B30E",
- "section_mic_hmac_key": "3B54D8A9281273639E19E939070E13E81625D2C1FD16186BA429D58CA37205F7",
- "section_salt": "207A4ACED9DD7DF5469BA445D82C4A50"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "55893FCB8F8DF622FD6A289A05C4148C",
- "aes_key": "BF693BE1C25DBBEE6008755AE5E49920",
- "data_elements": [
- {
- "contents": "33FD1BA6021EBCA4E5C7495D8E91578CC469D1E17551FF",
- "de_type": 155
- },
- {
- "contents": "0C14A55F473712E28050FD40E3CEE43A070CE813FA4C8F5C6C77CBF0",
- "de_type": 997
- }
- ],
- "encoded_section": "7090132ED1930BFB257B03FA14ADAE1B5C1D729110008C160E1D28A6D285D1DF356D50D4F79F9004769BA4CAE9955FDCF71B8BF9846D197E1959FFD62CAC6EC095FB709B140711B403EABDAFA3310E083886EBFA539F176EC7629D0A1B1EBC066CE5BE3244EB27542291E3E807F607F93B",
- "identity_type": "provisioned",
- "iv": "925B767E05ACDB3C182AF1B7052AD119",
- "key_seed": "6043699A67E42BBFE23654CCA2ABCA973462107F14A3D255C6CE66FDED3BA8E6",
- "metadata_key": "B182B23DF37C3FAB1127F1EC02EFC99F",
- "section_mic_hmac_key": "47632D7EC5E8F44736F91AA12B9C6B57D099B9F23CBC3EF022C49F17DCD31BB0",
- "section_salt": "8C160E1D28A6D285D1DF356D50D4F79F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B9A1E1F915254078F13383BEDA83CE1B",
- "aes_key": "B2A38645ED7EB5C3CE73102FF9D2CF97",
- "data_elements": [
- {
- "contents": "87818B3613A5D1AC040D",
- "de_type": 304
- },
- {
- "contents": "0CBF84397369C1",
- "de_type": 98
- },
- {
- "contents": "FE3972",
- "de_type": 286
- },
- {
- "contents": "4B",
- "de_type": 269
- }
- ],
- "encoded_section": "57901317514DDE22C7FA254E649536313E839B911000511A20E6594D496C588FEBBB9AAD242190017E66D43A84690796346F8436D0D8E8DE6F146D44C4AA622E9D739903FE39010B1BB3D07923199CFE45AF3E75ABD549B6",
- "identity_type": "private",
- "iv": "8FC1F2CC1AA763E1A5AE5B1A46BE72D2",
- "key_seed": "8952E7BC0784A56739DFDFED452B9AEA99AF09D12A28E38DC923AB85A02F7AB6",
- "metadata_key": "D9AF7A2E6CD1AA70B9689C5FBCD4D7B1",
- "section_mic_hmac_key": "8A6D496379762DAFBF4409AA7526B7970A137210934D1F1419AF9B05283535E8",
- "section_salt": "511A20E6594D496C588FEBBB9AAD2421"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "64B1CC633B622BA54618467268F0BCF5",
- "aes_key": "57BC65DF5020C32CFF6B29055E11CC62",
- "data_elements": [
- {
- "contents": "",
- "de_type": 492
- },
- {
- "contents": "370234107E41CF0DB00FC2DB6F95D5FE6F2669B8",
- "de_type": 979
- },
- {
- "contents": "0E7AA3067932410963858A7A0C03095826A2C1CFF616DD0A30",
- "de_type": 484
- },
- {
- "contents": "EDE7BB01C66E6AC77A372C5E0E99402D55BD",
- "de_type": 909
- }
- ],
- "encoded_section": "8290130FAB943DD3C3FFEBDF9EDBB19642A59E9110002FEE3F3C4DD0B38D2E90140654CF7555900497853980DAD64238E6974BB2DAE98D4DCFBCA0E2AFC6AD543A33EF8EE42F6DE0506A9B186A1FE02C409568362512C59DC04280B396E9FF8D4C4C2A3897412B290DB2076E1AA52580A11CB7463BE3FF3F0419A9D8E36079EE2CC38A",
- "identity_type": "provisioned",
- "iv": "8F5ABC9AA8000BE5F0185BBD0CB40B2E",
- "key_seed": "FADBB185CBB88DE7D922282131A346D72869243A50911622E2EF1D5BD9F1015B",
- "metadata_key": "5A7E3BABCFE50EF8B3CCBE8BB9741768",
- "section_mic_hmac_key": "1D5E78BBAC91A6AA8738425112A23966439DCAE1D69161476501A605F4AFBC94",
- "section_salt": "2FEE3F3C4DD0B38D2E90140654CF7555"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E5E46A2DA8C6DC22A69B3779CB44B1B6",
- "aes_key": "D93ECA4F58BE626EE2B2584024D567ED",
- "data_elements": [
- {
- "contents": "57186FD96B3B2A1B5099984E316AF34AD8F827A941AB",
- "de_type": 289
- },
- {
- "contents": "4F8EE606B8EE6567D40A3591485AB09B",
- "de_type": 761
- }
- ],
- "encoded_section": "639013F8605F4B7039EC7A0A92AE8839FEB15C91100073134AE922D5968E2AF8A54EEEE2E96E90019135A873371D039ED8BCF8D0E559F20B5A023516DB58A0FDA54F3B0AF0C3CB066277978EFBD3053F406ED380348DA8E0F365349D03349178A4CA5902",
- "identity_type": "private",
- "iv": "3ED5CCF399311A8CE0A94E9498F32454",
- "key_seed": "C141FD581082AE08005BE0FE63B430D320CB1E6816E508CCE92D9E4487D97A88",
- "metadata_key": "11EA53BA87F3632C176F7B6B7AFA42FC",
- "section_mic_hmac_key": "3B60B3FCD92A91A83030C1F33B54242AD1A55699E6721016C8B3E9B95CBA7158",
- "section_salt": "73134AE922D5968E2AF8A54EEEE2E96E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1AC4700BBC34FFCF56FE27722FDDAF8C",
- "aes_key": "06FEC5659E272340991B55911FC8CEB8",
- "data_elements": [
- {
- "contents": "8013EED9499B4FB30FE42FA2D25F73C62E30E0C13E4C1756629C87",
- "de_type": 276
- },
- {
- "contents": "D5F7EA0C7C5C2D3EFEAD2DA54C8854019E8508188CBAC37A1255",
- "de_type": 254
- },
- {
- "contents": "319793E7DCFBE4",
- "de_type": 95
- }
- ],
- "encoded_section": "7B90139E98AEFF088AAF2045661ED346D04613911000822C36C3F54743E8CCBB518C3E8A392D9002AEA2EEE26E1B161066AD737160B1815C36AF220A2BA8D8286A710BBAA1851A390F83083CDD47F4485A0D27D1ECCE811C16B614DE6AAE0854FC3C3F1DF2C1918D810CA3C926BED1062B00942B19759C4825C14085",
- "identity_type": "trusted",
- "iv": "B0238742AD552F78DC3F34B588EB1DAB",
- "key_seed": "EE1B60A84CAAAC77DD6FD1B0A5770D58F2D65EF0D7284B0077E6AE18EEDDC910",
- "metadata_key": "384A5B50211EF272A2A5C2DD917D9E4A",
- "section_mic_hmac_key": "EB2659D6BC3B0E72645864BE08C039AD8E9BA70B6D26C5C49939BE6D4D007D86",
- "section_salt": "822C36C3F54743E8CCBB518C3E8A392D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "688AB25983A9C40466E16ADC513ABAE3",
- "aes_key": "709696F50854B468C9BBE0D3DDA9E26E",
- "data_elements": [],
- "encoded_section": "3790130D25512946BAE13F6E96DC89DFF0BB789110000322EC17288B60620CD9539AA9CD6B99900209B744C0B195BEDFB06D3DED5103CF0D",
- "identity_type": "trusted",
- "iv": "5C3D8F194A93E04EB34E7E59B3767F2E",
- "key_seed": "8033F31A3FB892D45877E3398B8DD3444CB2E251EBC6B0D50C9C218384BCB792",
- "metadata_key": "E0DB32B9221DD82283C29EEC5F782E0F",
- "section_mic_hmac_key": "DC156CF79131E25E00AAAEA3BCFCB044C4E1066F84D7E07CCCA5E846E2E44156",
- "section_salt": "0322EC17288B60620CD9539AA9CD6B99"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ECCEBEA1B1C11B3D5888C3E163EABDE1",
- "aes_key": "1CCECFEEDCA3385145ED977B3AE8AEA7",
- "data_elements": [],
- "encoded_section": "379013FFB104D3791419F3C3E265B1C0A0FC56911000804E5C3901A32B9C8EEF076790D48E329004BA0FE90EBFB6C81ECA3D0551E6CE469B",
- "identity_type": "provisioned",
- "iv": "95D7DAB8C760196851972252AAC93D75",
- "key_seed": "FA8D1357B505B8CD83B94B9D11A1D1EC33A1964F2D95D4F6BEF9D958921D58F7",
- "metadata_key": "4018D81F725B848799F4B2682A494819",
- "section_mic_hmac_key": "AFB505B132A0B25DEE858DA00379D267045E19BA3739311A01569BFB24662A1A",
- "section_salt": "804E5C3901A32B9C8EEF076790D48E32"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "61CDB5B59D3DAF922471F816010577B5",
- "aes_key": "05F8C6D879D6F0CD30C79C10892E5509",
- "data_elements": [
- {
- "contents": "0B36121960993A4FF30D3F84CD32B8CABF",
- "de_type": 765
- },
- {
- "contents": "4FC94B",
- "de_type": 122
- },
- {
- "contents": "0345E7",
- "de_type": 331
- },
- {
- "contents": "BD882C86",
- "de_type": 64
- }
- ],
- "encoded_section": "5C901310D1179AE506FFBD55FB2F356E2F8B7B9110001437F875D102645621739E078680E1B390020CA5C46CEA1767F34848E4E702E94FC9607CAFF41AEE7253BA7976724E461327BF2CC028BA1709C0DF368CD08D8DA6B4BB9F48D0AC",
- "identity_type": "trusted",
- "iv": "97681895B3DBB45117F05275011522EA",
- "key_seed": "8AC64ED6DE2150104B510FE6DD2A49C744CBC4733D5DEA36BEE78170375701FA",
- "metadata_key": "D7A9DFF5ECB1F4F785F929BBB097CE42",
- "section_mic_hmac_key": "D05EF6C19FBEC3DAC6AA35992FDDAF2D69DBF56CD43D6E406597F01CFA212C23",
- "section_salt": "1437F875D102645621739E078680E1B3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6B659D0B21836653EFDDD806AF70C39B",
- "aes_key": "1399E5BD319D9D09DE5CDEB4C62E52C7",
- "data_elements": [],
- "encoded_section": "3790133A73A266945AB5E75E37AA0E4712B7F0911000AE4C670CDA23AF45ED828FAE7E41843F900281FE9EEE78132A0A54E5434BDBAE9062",
- "identity_type": "trusted",
- "iv": "F46E135C5AAE51FD7DAF53E6CCCB1113",
- "key_seed": "36CCC67956A6F1364CAA0B7DDE0CE6CFCB53118C140A74A05A76B2A4C13369DD",
- "metadata_key": "1A4D878971F8F57335B5A002C861F202",
- "section_mic_hmac_key": "A0DD0937541A8ED002593C07BDA8351A9450073F748DB427FD57517FF1AFDA05",
- "section_salt": "AE4C670CDA23AF45ED828FAE7E41843F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FADB2D052C1C1C27CB44E1A944104714",
- "aes_key": "6B0C0385579C8A4EA0D91C928907B6F2",
- "data_elements": [
- {
- "contents": "2F556D2609FB6A2053A998A91A",
- "de_type": 577
- }
- ],
- "encoded_section": "479013AC0A1D0434D93670BA9C9E2CA4B5091D9110001CAF1A47003F980443B9E56B4980731D9004AB942B3607465541F191028EDEEC77069FF9D15D5F2DCE9FB8CB930F2BE41723",
- "identity_type": "provisioned",
- "iv": "70ADD8C102E04C438C17F623252033F5",
- "key_seed": "5CA287810D59C030C8CC8E9AE4FA3B446FC363D0E09E229194FAD91781A7F196",
- "metadata_key": "9716BAD8F56242A3925CED10C4583901",
- "section_mic_hmac_key": "F82A3B7F6B516694C1AC37DE73BFA8E170C6C23B759C1BEA0616710350AE641D",
- "section_salt": "1CAF1A47003F980443B9E56B4980731D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6DB6728F2572B9138DF53B200CD8E30B",
- "aes_key": "9986ED53BA3786C54562944C5633D59A",
- "data_elements": [
- {
- "contents": "A094756B831AC0F2309FE373E4952C5899ED54DFEFB5",
- "de_type": 295
- },
- {
- "contents": "A3AFF2F5E05A0DB339CD73AD20AF8E3F34E0D4E9D5",
- "de_type": 457
- }
- ],
- "encoded_section": "68901398BF6715F57B6BE9A1449634DDFBD298911000D70B75C90790F143E006F97C963933769004FBC0E23ECF8951689315A48912CF86B7D85E7919A42C8AF123F862374840F2A94A89054731060F3336C723FFE54CE1366BED63741EFF3209FB1C8CC66A5F45EAAE",
- "identity_type": "provisioned",
- "iv": "6F05B19E3297E8DE48A6B8ED9597469E",
- "key_seed": "21D64EA0D529E3C695348D2130CE0D970FF226D913AD85D544BD8BEA7BF7C3A0",
- "metadata_key": "24F2B33454E620FEA4DC86EE10C90693",
- "section_mic_hmac_key": "1EA011BF9B8063BDE3E95256E1A30994F9959AD3A80815E54801FE1A278AF1DD",
- "section_salt": "D70B75C90790F143E006F97C96393376"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E7ACA2839BC4C6A7ECA4351B5B4F4D83",
- "aes_key": "6E674BDEE405F4DE0EF583E2F7649A37",
- "data_elements": [
- {
- "contents": "08AC57735F3F1316",
- "de_type": 580
- },
- {
- "contents": "185169B0BD105E2CE86FA692CA800858C23770F6A16CD57851FC361DFA",
- "de_type": 351
- },
- {
- "contents": "20E1D14615FDCFB630EB3293D3",
- "de_type": 692
- },
- {
- "contents": "09290387F31B81C684B8D92C5B",
- "de_type": 209
- }
- ],
- "encoded_section": "82901317F1B6491210D57AC3ABF4A33C2E4E43911000327D3D22CEE3A22CA4EEE65584907D619001BE43CD470A29DB32BFFACF5DBE8F63E501FA2FB82107C7D69B26348FF76A96644DB1E9A41592348404289395A150FDE6E76E7EF186E35EAF0E4572E07F1A4A093EDC149AB0C7022CBFCD84625A56EEFE9F3091E5263B23D051A28E",
- "identity_type": "private",
- "iv": "F2E05B8E1B5D670B361A240EA8CE4C17",
- "key_seed": "5BCD7AF92667A3FE3B5C1F6F60372ECB5D1DF8E564E880FE523E3EA878C34ECB",
- "metadata_key": "DF80721C303A49EFF2EA2AAC271F7CDE",
- "section_mic_hmac_key": "2AEFC8097B0182AECE54F5CCA2FA741652BCDA820D0465CE573017E950CBD89F",
- "section_salt": "327D3D22CEE3A22CA4EEE65584907D61"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "99A12E831E51DDCEF24924B1975C0589",
- "aes_key": "594BCE537928BBC2259C658BA8294F79",
- "data_elements": [
- {
- "contents": "6D1735B3D6221CEF5727CCD86EB799FE9EF05A",
- "de_type": 6
- },
- {
- "contents": "",
- "de_type": 289
- },
- {
- "contents": "10B7B4667BA4EF81315DB3D16127A4F0D9A63457",
- "de_type": 99
- }
- ],
- "encoded_section": "659013FEDFB8B589D781F1EBA87BAF95B8FCB79110004EABCD4E5E6C9A575FC314EA1F9165AE9004C06AEB6AC5B16BD435D7E69748BA6977DBAAB9A6E1A7B0CDBF4975CF2DC4A48C154726F5214A4D3A78D750BD49C97C0493042074ADE2BE34E86EBE25C1ED",
- "identity_type": "provisioned",
- "iv": "C9339EF9AE4B3F518B1BD4313FA73C79",
- "key_seed": "2456DB0645CFFB37C50F85C1A0E4B3B3D62592B305DA2409D29222993FBD8DD6",
- "metadata_key": "6C65E9861EA62C009260583C667568F7",
- "section_mic_hmac_key": "52400F51B5CF34C2FBD9281AFDB2964EE49ABFFF2AAC1AD9FFBF931DA7B2D362",
- "section_salt": "4EABCD4E5E6C9A575FC314EA1F9165AE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "878AACD95530B43C7913E501C8C4ACEE",
- "aes_key": "341A08C911C28E10C9938C1CB0DF998F",
- "data_elements": [
- {
- "contents": "79AD383E5AC871E91A471ACC",
- "de_type": 343
- },
- {
- "contents": "C77A72121DB14B812CF89D5D",
- "de_type": 218
- }
- ],
- "encoded_section": "559013C3FA6A34319D21F0113A710161E774CB911000132290FAEFE4EB99C181B96B5076979990010E92F2BF8F3565A81C24082EB66420FD2D32F18669221F3EE9C5B23722845ECE0C11FC261180613DCE38D704EB91",
- "identity_type": "private",
- "iv": "92AEEEF801E75B6C451EBA001AFEF5FF",
- "key_seed": "DB24DC46E2C2864BA42A405F8C19F782A9B4A8AFC8F69F7F7025A1CBE2BB968E",
- "metadata_key": "18BF8290AB02AAD2100F28455E585FB3",
- "section_mic_hmac_key": "7707AF050E3902074823EBF13FD3D36B64E2435BF116C00ACE0BB85A7CE59AE9",
- "section_salt": "132290FAEFE4EB99C181B96B50769799"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DF0A3C777D4847C4EE6956A868840BC4",
- "aes_key": "B09A907BD200E651C42C517BB92A38F2",
- "data_elements": [
- {
- "contents": "7C30A6D0913132E43E6303A90005DB",
- "de_type": 346
- }
- ],
- "encoded_section": "4990136D86B8E26F22B175A2AEBDF6A520BF00911000C3CFBE28CE663F1BAACBAE369DCA6F7D9004B31F7A82993A384A7246B91E008B10DF5AE74B2E10809F089F3B0894C5B958D6ECA6",
- "identity_type": "provisioned",
- "iv": "00140D6DC0C9AE914E6EE880792BE76F",
- "key_seed": "28C7233E1CABC3F5473F5B0F839133288FD4ACFB12C57CAFA92A6E56E9019822",
- "metadata_key": "4A3A0B294F19898858F13AAFEFDDEE15",
- "section_mic_hmac_key": "565E24A4C9C335FF6A36E420C84A2F4EA1E85610D246DAC5D0A0F2C8D40DCF98",
- "section_salt": "C3CFBE28CE663F1BAACBAE369DCA6F7D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "48FB067349EA60A5548283F90D3FC74E",
- "aes_key": "2D0054A2730B07075A868BA34305C0CA",
- "data_elements": [
- {
- "contents": "4FB6BDA26FA11EB8EDFE6C6A",
- "de_type": 155
- },
- {
- "contents": "7870B1EE4FBD",
- "de_type": 79
- },
- {
- "contents": "F398B6D9B6328776C81B4FBD",
- "de_type": 914
- }
- ],
- "encoded_section": "5D90136AF14091CA00746306320474998A13DA9110003A9ABD9A4070DDAB398E95FB7F0E109A9004A8C4C17761B322D5EA37EF8E74F5497FD847156677DA00782677C144630049AFCB9CCBCC4C080548925A4926EBC9D13AD07F5E49962C",
- "identity_type": "provisioned",
- "iv": "8FF9284343646DA8172A83EFCCD1C15F",
- "key_seed": "970E15EBA91441149A67E61DCE78BE67F995B606D2E76B02E9158E47E5142D72",
- "metadata_key": "63862AAA507FF1AC7AB3E2F1B7597AFD",
- "section_mic_hmac_key": "6BFEF95375643FFF9AAAA64B2FFB240E69A282B489FA6F23A0EAF8EE6C85747B",
- "section_salt": "3A9ABD9A4070DDAB398E95FB7F0E109A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "833CB4935E9649B7AED0AF5AD62D9B6A",
- "aes_key": "34867395BC36729AFA0E9651E17C16A9",
- "data_elements": [],
- "encoded_section": "3790131F3EAC01B28C1C974B040BCFEF38D838911000FE231478D02A9EC3AEAFB5EEAFD225459004252827D70ADAAC287267DD67A23ED9A6",
- "identity_type": "provisioned",
- "iv": "35902BD9F63C59083E5F15E541D6C89B",
- "key_seed": "DE13251FC20C24143C5D1A3C1616030CBA3517EE9CB63416E169F86E5623C028",
- "metadata_key": "A160EC6E23F3FA1C5155A3A8E982C28E",
- "section_mic_hmac_key": "DA0632A39F94B40803FE3F706E0B7B5DBAED011230ACE7C4A00B90117B90F2F6",
- "section_salt": "FE231478D02A9EC3AEAFB5EEAFD22545"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "271CBA3E2DE6311E84785053F08F6A34",
- "aes_key": "48CFF76E51AC2C0956D41E9AD2D6B013",
- "data_elements": [
- {
- "contents": "193684EB59862957D04183996B",
- "de_type": 157
- },
- {
- "contents": "3AB0E211CEE972C99EFE4022E1074C41663269",
- "de_type": 56
- },
- {
- "contents": "",
- "de_type": 411
- }
- ],
- "encoded_section": "5F9013B3D962B848554F750E23CE1DC503E29491100091AE51980C7684B16CA8C6D9F720C04790012581715CE9199E34170E21325A55D058820D62926B2671BA7CC37F6F90CD346310ED13CDA9003482DCC640C6516B93809FA6FE07218C6328",
- "identity_type": "private",
- "iv": "680126038E0D0C959C6F92CADF2B4DB7",
- "key_seed": "70B633AFC7B05E5B54E499BD8F4556AAF5DECCD7A86DE04C45B4C3001EB24F80",
- "metadata_key": "F8DF70B871DE7BB917ECFB0704A62685",
- "section_mic_hmac_key": "D183ACB6D00F733F06179CAEFBECE5F4E0E5D690BBEF15A69904C143E4AB610B",
- "section_salt": "91AE51980C7684B16CA8C6D9F720C047"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "52748CCA266DA944279BC16D0482E73C",
- "aes_key": "44FF93170DA4A5EF9E35B21C2AC6E228",
- "data_elements": [
- {
- "contents": "C3C03A02A3035C52D2BD8DB044",
- "de_type": 952
- },
- {
- "contents": "A8B3082EAD2495",
- "de_type": 459
- },
- {
- "contents": "D8F8770CD2FD961BE8F25B9B289B624E0D5EB550C558947A",
- "de_type": 200
- },
- {
- "contents": "BEE10F2031F41820F1B544709A29ED49E54809B3",
- "de_type": 831
- }
- ],
- "encoded_section": "839013100E58C7B0532D0ADFB41365B1A17827911000C755590B2F4894B1A5E48B0EBBF85A609004F74B503EF23735022525F4B920D6062FD791FB022FD24E687230D9864BEA2BB77119A3E96A5300B6A0703DC38A9F994E33ECDA1AFBDD0661930046C2F71D4CDECB25AE9D0FDBDA76D940119A557F4D1F552749690B30FDEB83F47108",
- "identity_type": "provisioned",
- "iv": "B386766CF3AECCE511F55D365BA53040",
- "key_seed": "A4C01D2CEC164CD21C90FE0F05A6416F08A336DFFA5915EBBE3399F375E4E726",
- "metadata_key": "A94A8413AF4BBB6A7F208BA3728CF664",
- "section_mic_hmac_key": "A8AA56603BAF8162878DAF90AAAE3F2284AF34411328502FBF9BD05942239EBE",
- "section_salt": "C755590B2F4894B1A5E48B0EBBF85A60"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5E4896E304E68E96A3B6EDD820E5F206",
- "aes_key": "0573815A1D7E41DD84EFFE7BBB0A414B",
- "data_elements": [
- {
- "contents": "CD459496304C08D118AD",
- "de_type": 758
- }
- ],
- "encoded_section": "449013FFD6666622A2DA34A2C275880506157F9110009874A69F2464B9DE4FF74F919CAC9D3890020A50F225CD2764D259A371F025387AECD2E84F2064417D98B96411449A",
- "identity_type": "trusted",
- "iv": "4F7C4F082F3718D52BA2A3222293DD19",
- "key_seed": "4F2E1F3AD51A20DC3918600AD08D4D0BAF6B64E429F68D125AAF667BC17A725A",
- "metadata_key": "CD1CB9AAD1597C77759AAD87938A9C36",
- "section_mic_hmac_key": "DFCF245574F4751BB2A5DF4A84EE02D3E3D70ABD8FE987092B0F59ACCF2552AF",
- "section_salt": "9874A69F2464B9DE4FF74F919CAC9D38"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F270C1808AE8861C06BE51C246839671",
- "aes_key": "6711054A1EC414B5715B8AD33EC563BB",
- "data_elements": [
- {
- "contents": "BB1EE72B358621",
- "de_type": 690
- },
- {
- "contents": "6CE1D344EB4F1641AE8AC5F9E2EAACC01E7C8FDC3D81AD77B2CCA371",
- "de_type": 983
- }
- ],
- "encoded_section": "609013E5F1F076FA559ED8A4CB17EC6D61EC6A911000EB93F9F5A15960A048CD6F8B8B6B58649001AD39CBA67C832FF3B377139EAD4E352D5BCF8E71974E4951DED2DB9918398D6AABF0DECCBE8E37224FE601F5CFFC705C5F227BCD511411796B",
- "identity_type": "private",
- "iv": "6723B26C84532019D6265FB1D9219387",
- "key_seed": "5827EDF50C9C538E05C59270334EA25A707BAA6AECF563A6228C9A645DB95259",
- "metadata_key": "E5034530CD6FE12AE1B8D9FA2BD772D4",
- "section_mic_hmac_key": "D6EF9EE9456896020F182EE408581EF01B10CAF8A534693586E7F6A9A23A28BB",
- "section_salt": "EB93F9F5A15960A048CD6F8B8B6B5864"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8389121A80436B19156632AC51695A13",
- "aes_key": "6A5E04C19CC54841180722029D13F7C5",
- "data_elements": [],
- "encoded_section": "3790139684BDB26A1EB70A15B98EFB09D5111B911000FB98AABA968E22288FA299ACB4E405749002AAD65BA2AA0A63AB971C5722229B9C47",
- "identity_type": "trusted",
- "iv": "BEC2A53243D6F2707722FA034A317A68",
- "key_seed": "1E700C710D7280FA6AC7439E403EDD5DE0257782DFD687BD323B57111DB15EEA",
- "metadata_key": "8EF84C05AD7E87AA76F2D3F57FD231B5",
- "section_mic_hmac_key": "AE770F2EBE85476AB97BAC70CAAF7F0B2D411DD01211E4F13855583E16EF211D",
- "section_salt": "FB98AABA968E22288FA299ACB4E40574"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EAAEF0F0BD203FF07EE43BE082FFE487",
- "aes_key": "5A8F6E1A06CF11AD9966D7DE70680E78",
- "data_elements": [
- {
- "contents": "8D985C3C5BD7",
- "de_type": 335
- },
- {
- "contents": "ED8D6C68F03FA51B2F79759A78E8",
- "de_type": 158
- },
- {
- "contents": "15010A88EF1368AF73",
- "de_type": 634
- },
- {
- "contents": "04BBDC82881BC0AE",
- "de_type": 964
- },
- {
- "contents": "8FD5",
- "de_type": 526
- }
- ],
- "encoded_section": "6D90131F37122E6A01D9C8138CE142E9DE94FC9110006828E400EA55AC14C4AE3747AA7050FA900149BAB83CE2166727ABACAFBA637FAC4DE8F17FAB063D51BE286E68116796A8DECA3BFEBC98014CDEC2FB60D7E712C84057360216D6B9C222EBB6A6F1602D6AD41557BF75B28D",
- "identity_type": "private",
- "iv": "8A4C13A101DE46A8E1A4B39A7D458400",
- "key_seed": "F4CA2D5D0F233F02D75BF99566E87F46887F3B57BC224D44B5C6CE2CA0B8F1F7",
- "metadata_key": "673471840A043D3029819713668DFAE9",
- "section_mic_hmac_key": "B1FB222C74B0ABDD529D06926D60C8685B5304B8FBE8491C38FB8A3DABAC9B2F",
- "section_salt": "6828E400EA55AC14C4AE3747AA7050FA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9BC7CFB71D191BECC444808364D813C4",
- "aes_key": "51518AE5E163D9D8D5416A193537ED76",
- "data_elements": [
- {
- "contents": "4E18846D",
- "de_type": 712
- },
- {
- "contents": "4820CB3C92CAD5B8542AAE9A36",
- "de_type": 832
- },
- {
- "contents": "B5D2F1B6CD8A17DE1B03FC670CC9808FBCB4020B7BAE8FDCCD922961",
- "de_type": 739
- }
- ],
- "encoded_section": "6D90137D76CF1A4074CDE63F8C6C0329155D58911000F27909C892E859590581882380B7F73B9002FA6E25428FF322E54F5CBF0BA057B844E3391F0F719F4ABD296FCF239D824E940EF2B31760698498E6579D200686A63E33C766C109BAE6C2C7171305EF8D7D05B56A4E628771",
- "identity_type": "trusted",
- "iv": "CFED21D898A59168C5FB57F3A86AB6FC",
- "key_seed": "5189E43E665A66541461FCB1DD460196AE5F64EFB70F344E5B00E6533566AB35",
- "metadata_key": "C3C0CFA6645E1AF45DDEF7B3D1F74751",
- "section_mic_hmac_key": "7F4EFFC52343AB47D1EC9C234841BED7BA67A772CC238A9AC005847361718BEB",
- "section_salt": "F27909C892E859590581882380B7F73B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EFC325741A620CDF60ACE605C3356BE1",
- "aes_key": "BB076A02A36F6D81B206B1C9C8236EE9",
- "data_elements": [
- {
- "contents": "EE2C53A7B84776BCBE",
- "de_type": 322
- },
- {
- "contents": "3D831323FF7DD1D925C629564D92C87D7ACC5FF526BB2A0B5FAC9132",
- "de_type": 610
- },
- {
- "contents": "B38D897E0829B179A5FD66CDE9D5B5B0D574E04008",
- "de_type": 240
- }
- ],
- "encoded_section": "7A9013444AA5DE765AF1E12CF47CE2C37B6227911000249EB7CE39639EDB7AA5680B7445ACCD9004D0230E8B8D679112F9F650A8E4779C93FDF8F26AD5B381729C15F83A07808F094528BD326047036689E5DD4A92DE1B57DB883720D93E4CCA65058635AE9612A8E48DF6A8BD372262E06328D5FC5456FA168186",
- "identity_type": "provisioned",
- "iv": "BDC3752E0380EF0CCC465A207B36AC33",
- "key_seed": "C855E8921027426AAFE3C38593C328834BC1DEB79007F68455F336A0AA2E6979",
- "metadata_key": "249DAC8BD2E0A6D705BF4D5729A6B9E0",
- "section_mic_hmac_key": "848CCE3F38671B20F910FB919492E1E80051AA4C9AE7FED49B71D4E60C8EDBD7",
- "section_salt": "249EB7CE39639EDB7AA5680B7445ACCD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C45308E14C984650D43BCF505BC65F5",
- "aes_key": "D1A76910387CF7AAB6CE4A0EF807FE49",
- "data_elements": [
- {
- "contents": "AEADF60EEF2311B4FE8111065D40435AB79809469B08FC5FEE",
- "de_type": 674
- }
- ],
- "encoded_section": "53901393F3F5E4C94F10F460E9B79E4A8488F191100020F961FC32DAAFA88DBDD328319AEB7F90019FB4153E082B763922CEF5EFE91F357D2E83421DB3CD2AB47308C127A33A7079611224B3763E863656848939",
- "identity_type": "private",
- "iv": "C0E2E91FB0D154BF04CE881789D11166",
- "key_seed": "7D4DAB11FB6FC7BE19BC0D9A56936874E83966C5F58686C9AB533FB3A6F3F2B3",
- "metadata_key": "7682862834A4910F038FC5CDE1A7BB7A",
- "section_mic_hmac_key": "244E6405668A612CC41EF88DB5D046256AD61698DB7E5D9CC632BDAEC18351C0",
- "section_salt": "20F961FC32DAAFA88DBDD328319AEB7F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49716F792B5B2446878F04B9B080DF27",
- "aes_key": "3FF2428CC19EB164069991144389B867",
- "data_elements": [
- {
- "contents": "953F0048B02C14E8BA62C721240D68D90001B4DD0E897705",
- "de_type": 401
- },
- {
- "contents": "0775542388275325E3FA4DD2FFBBCFB429BA51CA4775F8A342B67030A3",
- "de_type": 395
- },
- {
- "contents": "E0246D98751CEEC87A2A86866D06EF",
- "de_type": 165
- }
- ],
- "encoded_section": "84901324809B6938CB9ABF43A1A28BE74FF373911000C05F2D1681AE6F6689FF8989B0CFBAEF900160F98F0EDFCB8E41846F503B92280E0BE2FC3E1D261CD9A2204AFBC3276A639296B87C27C143969FD3FFE020918D8FB9CA5846E095566F27EF8F45442B3BD2ACB637C8360D82172A970BE0574ABABD5D34F0EF773D4FA68982B24F8A8D",
- "identity_type": "private",
- "iv": "CA0256A71F1F8248F4E5804C5C80C42B",
- "key_seed": "32F7B3C74E59251702FAE6CA0DDBC4D4DCCE002F82F064A92093EF0E0DFD96CA",
- "metadata_key": "5AAA3B579A426D773E975C442A0D24DD",
- "section_mic_hmac_key": "B3F114BA4764A3CDA2A0DE54E53F0747324DB0DAC3EE19C338FD5898948E7121",
- "section_salt": "C05F2D1681AE6F6689FF8989B0CFBAEF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8F3ACF2B400ED33574CCB9AC82B7FF80",
- "aes_key": "CCC54BB5C42A61F4F50820F1D64C601A",
- "data_elements": [
- {
- "contents": "C4878BE538",
- "de_type": 696
- },
- {
- "contents": "5081C9BA7B0F06",
- "de_type": 10
- },
- {
- "contents": "E009C8169E51A37B7544A8EC8A1E6085C345D3350D7ADF",
- "de_type": 400
- }
- ],
- "encoded_section": "61901380D74E5F857F77C6324B0DEB8271F2F5911000535996FE591823883E8F94C9528142FB90029EFAF31276DE796DF3843E4C08FE5DA982EB047A4E932F1C689DB334E0DF51EC92622CFFE9AC50711E45207EA4493A88A6A2EA36741D6BE76801",
- "identity_type": "trusted",
- "iv": "6BA59F3930B610C64F9A97F9254130CA",
- "key_seed": "A9F58DCCA97743D648C98BF39AEEC09D1042794054924AA10B601CDBAAFDA1F7",
- "metadata_key": "E18C1EB3D52ADD20D13E6F5CD7253F36",
- "section_mic_hmac_key": "B9336123B29683DCAF5421E6A934369E3D587749147C3D3A9C65DAA2FCA4FD5F",
- "section_salt": "535996FE591823883E8F94C9528142FB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D906139BD4F5F0D43588F1E463870ED7",
- "aes_key": "659E7E26B7350532979241C71A794A47",
- "data_elements": [],
- "encoded_section": "3790133051C1E0D286C009937A41FBEF966F4A911000E9B18B58534EBE29990D03A38305EEED9001A3F393753D761A490BD4204C22B88D18",
- "identity_type": "private",
- "iv": "652B4283066AAFDED606DF9F74BD40A2",
- "key_seed": "92F464D53AC339F4CCABEDEA6C123D36319ADD612EDBE6674D1CD8673AB4B591",
- "metadata_key": "6AF8037879F253615782CD0A041EB12C",
- "section_mic_hmac_key": "AA4229BA575F5800F32326FE1981C126F79755D1F6B07BA91670B3E2C4178B55",
- "section_salt": "E9B18B58534EBE29990D03A38305EEED"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D1DDA0E7AA3E69AE2F3370D6E15F4062",
- "aes_key": "600F6D5E91AF5302CE554A57A7EBCA42",
- "data_elements": [
- {
- "contents": "769BC18B3624C9C3F9538B96F668E73E7E53D36B16",
- "de_type": 199
- }
- ],
- "encoded_section": "4F90139FEEE459BE5B388C727B8A576E4C93619110004892C57DF0FF7BAEABC88477F349C4A79004AE6E76B72576ABD71FD6EFCA914797AC69C80AAC2283EFFEE9DB9A784D7518FD45A71BE14AEFCFD9",
- "identity_type": "provisioned",
- "iv": "1E805BEA0FDA0095E961BE043176F24B",
- "key_seed": "1B19E9B42F8262E9ECB505D43A949363ED484EAD3D8B802C19B826C40C293778",
- "metadata_key": "E6BC1FF04AAC597D5116A868BF0107A2",
- "section_mic_hmac_key": "3B15004ADC3A4F59DFFC423D292165746C76969A40F763043F5F009EB38E5B6F",
- "section_salt": "4892C57DF0FF7BAEABC88477F349C4A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F02914E89D274DECC66DF2B3C188328A",
- "aes_key": "8E89A5C199B8E077FF0C020C9E5FD1D8",
- "data_elements": [
- {
- "contents": "087FFF3F2F",
- "de_type": 934
- },
- {
- "contents": "447FF6BE8D5D86F7C59001FBFC19E00E",
- "de_type": 163
- },
- {
- "contents": "AD33",
- "de_type": 695
- },
- {
- "contents": "",
- "de_type": 114
- }
- ],
- "encoded_section": "59901386E81CDE1667FBFDD7799D04920C706F911000279EE983242C291A41DA61962A3C6E229004E3973DC6CC11CB4B4853FE0A72D9DFA304E37D1D01517B31771AEE26680F9AB271BE747FB639A5F5BFDB4C701534F7C7E083",
- "identity_type": "provisioned",
- "iv": "B1B0129B8F410981FF08A1E07765FE25",
- "key_seed": "37C6B00660E3E82EF5176F7164828F5501D19B08EE50FA8B5426BC87EFC6BEA7",
- "metadata_key": "60C8892135BE25252CB238940AC460A4",
- "section_mic_hmac_key": "8491D901EBD1B5E3C23828A7B8C830FE557F6D238CE41296A14A97C0A26BE21E",
- "section_salt": "279EE983242C291A41DA61962A3C6E22"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4F655495958DA3AC2438FADC76CAA469",
- "aes_key": "48017698AA818DF52A218956255D1184",
- "data_elements": [
- {
- "contents": "D21415A59D61C37A431C94CA3D1B12",
- "de_type": 223
- }
- ],
- "encoded_section": "499013BD809616651CB4C0FA14C3FED9EEA8199110008F1695AE141F457D323BFE9FBDB4A646900164E3DB751CD22313B6EFC2BB28D064CE99C04F4377CFBB39666CE7F6B35822CEAF23",
- "identity_type": "private",
- "iv": "2279F7D60A8ACFC3400EAB7D479DB51A",
- "key_seed": "971782B7DFE1FA2F6D6F2C76AC4C6CBCC2BF05AC1CFBD19882E484D07D90A467",
- "metadata_key": "658C560090654FE1648E9939A51BA9A6",
- "section_mic_hmac_key": "AB9431C41C87442A332416CCE3074BAC1C330F923AA07E57CEED68592C0208E4",
- "section_salt": "8F1695AE141F457D323BFE9FBDB4A646"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ED33675F04F139BE2E7BE9417679089B",
- "aes_key": "D169E3E3EF2ACCAE3CEEB84523649232",
- "data_elements": [
- {
- "contents": "138081B628B974A24C1CA904B706ECFC64ED8B256833B9F3",
- "de_type": 487
- },
- {
- "contents": "2BA4C7",
- "de_type": 311
- }
- ],
- "encoded_section": "58901346E74CA333752A4F091A53F7BB6A1E6391100017C25D290070B12CA99F7B188DBA2C009004462896554342784C49B6A736DBB42FA93EA55CA27E9BECF238D8D76E39AFEF0EF3809225ACD1338A7C3802DEADBBC38303",
- "identity_type": "provisioned",
- "iv": "5CA7E4BB4CB64ACC75FE3D7ECA59B5F1",
- "key_seed": "BC53A14CA7C5A41C1459A17DE84DA7EA69C9B4B3BF412CD1B7F735C86FD026FB",
- "metadata_key": "6B2D533F3E784395DA8EA4D104A9A5A6",
- "section_mic_hmac_key": "D6831E0EB880B6EBB5EC3B5A6178589CCD4CFE42C1D2C0982039674966809A1E",
- "section_salt": "17C25D290070B12CA99F7B188DBA2C00"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EEE3952D89F58C16D86CF2A0D676264F",
- "aes_key": "EE4D226F72FAD340CB5969026B5009F1",
- "data_elements": [],
- "encoded_section": "3790135CBA17D59F867DD8152D6A15D42C059E9110005F9D9CF54AF1C87EA73CF0539B878E559001DDF4CB6AD10039706AC555E84E731BB6",
- "identity_type": "private",
- "iv": "960DD7B569F6084D311B14EA5EABA4AF",
- "key_seed": "CA471364CBACA719FD0FFBBB46AF040A9B77BADC1C5DD45671DAD16658908CCA",
- "metadata_key": "BC7545E167CE62D60E04709FE54A0EFE",
- "section_mic_hmac_key": "AD60A30FD4927631B4BE521BB0BF8EF4805993AE122CB68B749D39A6051D2156",
- "section_salt": "5F9D9CF54AF1C87EA73CF0539B878E55"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DF5649D8C88520FA5B4C48C0D156FC6F",
- "aes_key": "83B0F91866C953759BA6C220B17BBF79",
- "data_elements": [
- {
- "contents": "E712F3058923F793652BD04D42D44A38371F7A29027D4E6AF3F2",
- "de_type": 184
- },
- {
- "contents": "8EEEC3B2BCFAC213A2A95EA3EC5596DC8BB30D52B3D095CA",
- "de_type": 546
- },
- {
- "contents": "2C4B5138B3D520FD9D3799CEE77A57CE28",
- "de_type": 125
- },
- {
- "contents": "4F039D61E7908BC515E127542C4F69393593BF9015E8821E52FF",
- "de_type": 550
- },
- {
- "contents": "12159E47",
- "de_type": 107
- }
- ],
- "encoded_section": "A59013C0DA8CF829FDFEC39AF1136EB83F1930911000F16D6B2A76966AE53ACF6792DFBC41C5900139D1D9C42A158ABA72D040B5B379308734C4AA5345EC3FBE04EBD2543A38E50551C82BADC8BC9A8150450F68E3DC4DDC1F7EDFC9A48BFA00985F334AC8B072423E38BEA3C91A1C7E59DDFF1D74948A17DF9FC3B25DD3E61B3882CFB3734646FEE24D60A03D329BCA50BF5E6EB8AC4C377DE637D0971CEE502419683DADBD",
- "identity_type": "private",
- "iv": "C56E5DC162716C9EF3CEAC49C0F115B8",
- "key_seed": "CA4F0FCDE67D6A691236FE32B43802AAA785519E4108415A4B9384FAE6220F25",
- "metadata_key": "5DCE8108DB324CDEAF9C4DA6C5652CE5",
- "section_mic_hmac_key": "435152983E08E498549369CBB3845599399E0C3BAE7A6AEB530CF9BF74F94F43",
- "section_salt": "F16D6B2A76966AE53ACF6792DFBC41C5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F6C8A813A71E37E62E7B4A383DE9CE03",
- "aes_key": "28F700FF1E657FA5B93060B77CF3F673",
- "data_elements": [
- {
- "contents": "7B25F39E00B7B165",
- "de_type": 588
- },
- {
- "contents": "4407E542845E25D8C5F651C54A6325DB08D31CD01C0A39CE68F6A63521",
- "de_type": 397
- }
- ],
- "encoded_section": "62901319919D6F5709324CD2F3E6C38393AE8C9110001A35A3E9A1EF41933CE4934C5576B4AA90028C72D7952DBA1254D1A6F28B061A89EB461FBB771E1291C35270DBDB7F4F344E527F4F419D80D9D8F37ADDBCB0300061DCEE9DC4A49295C9CAEBC9",
- "identity_type": "trusted",
- "iv": "E9C4F94C776EA7100BF8FCF029EAC9A5",
- "key_seed": "691BB699B3A533E919AC8F2592FBF465ADFA3232A7102CDAB4A2BFAF18D39216",
- "metadata_key": "D19E7F2C3EDD021E38F7EB3668A30D21",
- "section_mic_hmac_key": "9166DE19913527B22E2D285A5623FBE27843DEDA9BF75CA21AAC1D7A925BAE71",
- "section_salt": "1A35A3E9A1EF41933CE4934C5576B4AA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E03BD15C47BE63457ADA2CAA38F8C01D",
- "aes_key": "E57DD2A12514B1A31EE3031299B69BAC",
- "data_elements": [
- {
- "contents": "E1DACD22961D862FE8B7A8DBF8DF3014ABDBB06525C3",
- "de_type": 408
- },
- {
- "contents": "00982ADF65DCAC4218EAF676347CA52607D55CA9334F",
- "de_type": 600
- }
- ],
- "encoded_section": "699013EBFB56D27710D376E2F78AE5314B6EE99110002E9A05B98DC81FA726BBE0B25ED6616E9004943E813F9E1C01E8C8987A3C7C2A612A27C011AB3BD5134E60593FE73B0950C777D4FD02A1220ECA13213A10769B4456DB92139D8A06AE5A33CD1EB07D629BAD3581",
- "identity_type": "provisioned",
- "iv": "18A7EE60B7F063FC35EC9A051432A276",
- "key_seed": "854812FA5DD5336B82417C854DE3C21D55EB81CC503D395D36160429743EFA17",
- "metadata_key": "FBBA049407A1FB50BD32B42FD1FC5227",
- "section_mic_hmac_key": "2B1B6926BC2FE1A4789F6FF28C1B1E208BBB7B9A831B7665FDF07FE5CC932974",
- "section_salt": "2E9A05B98DC81FA726BBE0B25ED6616E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C565D587CAB49EFA12AC6F0A2DD13227",
- "aes_key": "432B9F04E0F4F71190D9CCB3DA261AE1",
- "data_elements": [],
- "encoded_section": "379013DEC89828681CFEB999004464A2DAEA7A911000533B00CF247DD1C3271AC6EBBA2DEFBD9004309005A18C6BB3D59BB078853CC5A98C",
- "identity_type": "provisioned",
- "iv": "46696325A36A170F95E6D3258A08B04F",
- "key_seed": "15740DD5FCD0FF3547B15163C6041E1D8DD9DE508BDFF02042B0BA37F11C10B7",
- "metadata_key": "C6D054B984ECCE9241E8F5C7F95A788B",
- "section_mic_hmac_key": "52EFEE44663018C3D495F0726D8AFF9BF451607C491D8982E709AC57C9253A8C",
- "section_salt": "533B00CF247DD1C3271AC6EBBA2DEFBD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A2F7DFEEE2E3E735EF73F8E75D9CE4F6",
- "aes_key": "14A2DC3915F43E95AE53A541DB6A20A5",
- "data_elements": [
- {
- "contents": "1F819F1441E9818AD0AAC4B083840D81AC",
- "de_type": 743
- },
- {
- "contents": "FF547347B5FC33DEE1BC21109492E5B254231ED5CEA88445ED5F7892A2",
- "de_type": 822
- }
- ],
- "encoded_section": "6B9013659512ED18290B6C5F4DE46EAB3E54AA91100043B1749F94745222204B1E9AFF8C086890017EA654267AA0447CFE19880DEC1916CAA03546DAF407913D33465D78F90FE9C982F101EDB98C030024372AC65278A26D644A99BBC06860B81E8E46F97280A7A9496919AF",
- "identity_type": "private",
- "iv": "0B79362274A4ED6B0A2DDC9B3A3D0C4B",
- "key_seed": "EE2EF449A38CE4C5AC6F70F3592DAF53E0EFFDC3FAD5A8D35914A301123C65C7",
- "metadata_key": "18D9E6C0B7CC34DAA3FBF27255ED25CA",
- "section_mic_hmac_key": "99F5025A9BEF0E77912BE3A814A87DB26C75A86092AE4DFC0409F2E7CE1A61BC",
- "section_salt": "43B1749F94745222204B1E9AFF8C0868"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9250734FC0AC255D11341B94703240A6",
- "aes_key": "14E0C14BFE51E3E2D9C17E46617A7254",
- "data_elements": [
- {
- "contents": "7AD8D89A3BAFE604CE90BA870FBAE5061E596406D3492A",
- "de_type": 773
- }
- ],
- "encoded_section": "519013F3F99B6429EF43A25C3096E54A7A6AE191100097B2C056D43F50DBD56CE2F57636E93F9002025D4212219F661181F68D105E0567675318418C08858F7F9ADBFDC9EC2525CA987B754CA7B7E20541AE",
- "identity_type": "trusted",
- "iv": "CF58402F5FE4255D36AC71B32A7E53DD",
- "key_seed": "0737014DACB915DA41FCDABFAE3A1612CEA784C26E728B92A515D17AC9880BBA",
- "metadata_key": "488DFBB55E10A9C4115ABE9EA510E685",
- "section_mic_hmac_key": "2A83F033AD0948FA29DD234D02124C1BF07BB0A914E008CD5A32A794FAFD594E",
- "section_salt": "97B2C056D43F50DBD56CE2F57636E93F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "742306D9A50A5F57414C636DAD6758AE",
- "aes_key": "843800EB6901EC65E32BCDD8C42DDBB0",
- "data_elements": [],
- "encoded_section": "379013A910AB5E2636F86BC67DE65AA6BF508691100046DD825A5E29527818B48BB6B12D52D1900141FC36E88D10ACBEF867C69D0F07DAE2",
- "identity_type": "private",
- "iv": "C622A5E21BB8C2A60B610C1523013FD9",
- "key_seed": "6A455B03C96F4CE85832223DDB4B84AB1A2C98356B00F09F5855F5D1DF296400",
- "metadata_key": "B7BBC5E06529761651EA6817D5434679",
- "section_mic_hmac_key": "7BFCEE3D3465311604F1BFEF4746CF63D2433806F5720F4B8DC4876CD398E276",
- "section_salt": "46DD825A5E29527818B48BB6B12D52D1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "970ABD5B5C3196B424CF4D3BB360A3A2",
- "aes_key": "505ED35ABFD6327336834E0A3B8A1168",
- "data_elements": [
- {
- "contents": "3BAED92467687DDCCB55D80114188395B55B82",
- "de_type": 249
- },
- {
- "contents": "7D8988A293E7FD36AC2C6A9DF2",
- "de_type": 103
- },
- {
- "contents": "0186E7C12684315D411D523F67C43FFA8A1CD75A",
- "de_type": 1000
- },
- {
- "contents": "390049E7B31C2689FD0E6A78AB8165E724F1F70DE1A2C93C615B19",
- "de_type": 234
- }
- ],
- "encoded_section": "9190136E43BD77DD71A1178B3A9D6E81F6218D9110006F5E89B4DD9C9E840C769C2D9CCE5889900294BF8F6B35C8A0A1ADEA4EAD45B4969D29EB245D277B98EA35316E32FD2CDCF61464007AF3EC71697AB7C81845C03493206C236D076D094471DC5E7DAA4D822EF947A2E6446B6630F8605DEF9C467CEABC0AEFDB73BC7ACE0EB4352B06881F71FC480F14E153FA4DBF52",
- "identity_type": "trusted",
- "iv": "4C9ED54A1DF5B2930A75F6117A853CC5",
- "key_seed": "7F47276F24CE6BB646B1CEFEF060FBFE235AEC3DCDCCF4CC2385EA943EE690DA",
- "metadata_key": "346F80C5C67A4EDAE1818D56393D3B82",
- "section_mic_hmac_key": "AB43E9A5ED9D2DD9535153F4338CDBBE77046191ADF5940A2769B2F919A911E3",
- "section_salt": "6F5E89B4DD9C9E840C769C2D9CCE5889"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "228D8BFE431F88F73A132DD2E756DE94",
- "aes_key": "AB278D4D71D4DFA69690315EAC610D6F",
- "data_elements": [
- {
- "contents": "170117845E",
- "de_type": 913
- },
- {
- "contents": "FCFAEB51A97F49110B14325B51364275",
- "de_type": 100
- },
- {
- "contents": "82",
- "de_type": 510
- },
- {
- "contents": "D62D60EFF7C12231328DE62E",
- "de_type": 779
- }
- ],
- "encoded_section": "6490135A2E477C18D8A5D04E1138CDBBBD2BEF911000B39BE49E8FCC53C0C821C9BBBC0C024D90027F72C6072B8172256C2194121844B4EDB6C2154044FE30EF19BA68E2C1A7F7FBE0387F5764D69AAE52B0E2FC46B0A52CD08728E375B042B0F3E8CBDE3F",
- "identity_type": "trusted",
- "iv": "31A4BF684280A37A8030426577EB7B9C",
- "key_seed": "912586C615BE6DD6F4F6ED12C85D9189B85E1D2FFA06AE1763BB32713ACA1F95",
- "metadata_key": "C16D146B28A8C32B7DCB66EAB90C30EA",
- "section_mic_hmac_key": "ADA2821A572B4B3ED9298257C200A5B73A39634117024404EC3011E7DA17D24D",
- "section_salt": "B39BE49E8FCC53C0C821C9BBBC0C024D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BA26ABDD5164F306449CFF633AFA7806",
- "aes_key": "328428A223099585C9ABC9ACD7911FD8",
- "data_elements": [
- {
- "contents": "33222D5C84507A2B0130501E",
- "de_type": 413
- },
- {
- "contents": "1ED1B4E58C",
- "de_type": 41
- },
- {
- "contents": "E2079D383308B60A86988F3B36F491127E",
- "de_type": 812
- },
- {
- "contents": "D5DE2EFCEAD465719916DA22BF3FE9",
- "de_type": 855
- },
- {
- "contents": "84D04B14ACEC49162E4705C4DFBADC5EE6161B8D323A",
- "de_type": 185
- }
- ],
- "encoded_section": "8C90131AFAB491598665D824C89C5398CC85B9911000633957E0C51915A10852DC7A8F09400890019069C7C9CFBEA948E3DB9A4DBD040F8E776D4F3721EACE87669A8CA6FF04E51B02D67207B82BC9E6E33D65B0F33DF6D878F0E06560FA8EB638C80117FD6DFAA2B902732BAE4E8CED79420FE93D9B57C724CBB06369FE960269B80BAA1FB8020BDB2D00D72C",
- "identity_type": "private",
- "iv": "E0B0D025435FF6F9FAAF4B42044DE4C9",
- "key_seed": "E75FCCB24B1405672AE7A48F64DBDFF890783DDCC42B9928E74B591D387ADF86",
- "metadata_key": "26B8D6CA92011D8C16EA62D6C62781E1",
- "section_mic_hmac_key": "5665CD729F01A5933E5AEEB2B38EF153D71A19E3A7A603723E2AD564CEB83D99",
- "section_salt": "633957E0C51915A10852DC7A8F094008"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DC49AEC367EA0121D5FB188143092866",
- "aes_key": "B42D7A6A8D1776BADA8E21C226605833",
- "data_elements": [
- {
- "contents": "B3BE9AB518C82B73A3C0FB57D56C6F2A335F",
- "de_type": 423
- },
- {
- "contents": "4D96F55DA0342CE760A1832CB0A53B2A74CB529FF65EB532",
- "de_type": 945
- },
- {
- "contents": "20ACF6ACC51DAA65AEFDEBDA0D8697476D0E",
- "de_type": 423
- },
- {
- "contents": "2C3F7B88FE5F07C99978BCF68B3F5E7198724FEDDE",
- "de_type": 465
- },
- {
- "contents": "06BF37158C17DDD27C8F8DFB3EAD50096EFC8CC085D65AB195A7D0",
- "de_type": 368
- }
- ],
- "encoded_section": "B29013658EAAAEDD464C9AE3EAD5F4D5EC48FB911000739370CE2574699DE19C1289E6F976A390040B3321DA88445526B10812DB7DCB8E5FA5C3FE2602991884CF5444623FE87FC4E63086F9039CFC7B871E08F88FEE69B1BAD6730C2C4C959FBD0AD2DE89020F46CDA552DB50C50939DD58C4D7AEAC8DE212D03F3D47A13990CDA58D276DBD6BA9A8F90A623CEEB931FFA530DF6DD7F57BC1CAD71D242778783C92F855D6E90D509976F8563C9B9370849CA7",
- "identity_type": "provisioned",
- "iv": "FF2AC24716EF0EEBFF2CF92A02049CD2",
- "key_seed": "DD843B0B46AD2B8D137CF22A2517E961A79EB1AEB2882986DE825056D2FC52BD",
- "metadata_key": "F64D69CD52EE04FF9E8324E751FAF1FB",
- "section_mic_hmac_key": "78F4F673BB14B5F7F6C4563F4D9636355C91CCB01BC021C2FC1567446A944A52",
- "section_salt": "739370CE2574699DE19C1289E6F976A3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF7D481AA8590423266AE9663FF6F7BF",
- "aes_key": "E47403E811D992FF13BDD5156EF15C03",
- "data_elements": [
- {
- "contents": "CE99E4F9ACD8CBF8D99295AF",
- "de_type": 110
- },
- {
- "contents": "BDF065E66145184B54FE0C0CEED6CD6741404BDA57CFFB2B73102F542EBE",
- "de_type": 369
- },
- {
- "contents": "EAC4BC7CE2",
- "de_type": 971
- }
- ],
- "encoded_section": "6E90131C80766FCE663175DF597C00BD95B39B9110001568D698479F825D5637D908F813F4DF900154739ED1447C96CEB428C6C2E98F9F6C544970AA9EBE7DB216197F20B6F4B3A573F461E2025808BDDED29278410B1AE18942699647D71252759992BFFBC9F5B7A923965972E820",
- "identity_type": "private",
- "iv": "11B6F13C8903EE0D12233F0FB5DA1C6D",
- "key_seed": "BFDCC2ACAA9E80AE659F652CB2FBFDA4990B805A9D4AA898D350CCCBA3CC9CA8",
- "metadata_key": "9AB08AE1CB6AF2A4745439770718B2CE",
- "section_mic_hmac_key": "0580E1B433054DF31F38E72764FE5849FDC54D54416CD139F34D4D444402263D",
- "section_salt": "1568D698479F825D5637D908F813F4DF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "85B1D40513E6CAE086C28552C12FB350",
- "aes_key": "CC37B97B5B92FB9F9D6E00EDCA6AF45A",
- "data_elements": [
- {
- "contents": "14EA6D3FEAC9844D84E540D0AE1033C435F130AB1BEF75B7760E6AB9AD",
- "de_type": 341
- },
- {
- "contents": "",
- "de_type": 550
- }
- ],
- "encoded_section": "5A901328BA159A1D698C86962BBE2358C362709110008D6FDFC90CA3D1A3AAA1C766B72B5EA490022F5AAFBD03AC4ED441B9EEFFEFFEA020A82B9EBFBD20648A4CE8BF57BF728D9FAD388AD1EEFBD957EF312CB9FDFB7ECF68AA06",
- "identity_type": "trusted",
- "iv": "25ADEFF36CE0A5B0A09953648F7EF334",
- "key_seed": "0454B57060C890C86592212E9A3EC7926D43BA17D4CECE8BCFE7637484D83802",
- "metadata_key": "21D66A2461F62F2D1C0B9F66D9739287",
- "section_mic_hmac_key": "A61711DB75D7A424E6E806F1F43CFEAE962A7F6C499622A0793A170F4EB9CBBC",
- "section_salt": "8D6FDFC90CA3D1A3AAA1C766B72B5EA4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "02D5D750D664E288EFE7A964A02A927D",
- "aes_key": "A3A5A8A7E672AC04CC383C0F95DCE6A0",
- "data_elements": [],
- "encoded_section": "37901361A89D3B7C790776967C6501726806BE9110000EB05C6B0F96C24634A63A667709215D9001255CCF12AC41FEAC1EB155D864DCA570",
- "identity_type": "private",
- "iv": "27A2765AE71E5B83F0480E32BE173DFD",
- "key_seed": "2EAFB7F93967A4C45F5DDFF41E13410591E3419E65A7DB92762697DE216FC967",
- "metadata_key": "283DD374AA19C66FDB250A312166E6EA",
- "section_mic_hmac_key": "D4BD0787505004AC108AC3DA06C1A450057D551AE7DA43BCEBE14C2D975A8E78",
- "section_salt": "0EB05C6B0F96C24634A63A667709215D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "125D63CB7190B478236C3747A149366D",
- "aes_key": "0BE97B73FF512505354DAB5D6B29FCBA",
- "data_elements": [
- {
- "contents": "14EF62BF82F80FB085A310A1435223ACDB920B97DDCED1",
- "de_type": 871
- },
- {
- "contents": "2CAF9EF90EAD8F6298060839624769DE",
- "de_type": 964
- },
- {
- "contents": "768E7C5B73E36F162BF105E085899DA027D9",
- "de_type": 721
- },
- {
- "contents": "A178D1480EB66B5551EC948ABD91F0C049D33B8D29360DB2EF",
- "de_type": 198
- }
- ],
- "encoded_section": "959013997F971BF31BE7F59A55046ECDE81BCB9110001F657CA6FA909CCA6C1681FC6DD0928B90043DBF611BE7A90F0905DA13400AA1A1866644AC3671290548F39EEBC9B5BD3CC18AB804DA5C77D714181A605BE5C884A5EE6081FF4591D2AF96BDFAB2546D12602EB44A3FEBAAA3E4C66F444F55A6FBFAC75DDD71D57E6A719C739492CBA1C0E73711D2A105A3B3FB2AD3237E9ECC",
- "identity_type": "provisioned",
- "iv": "5404FADA1301DDEEE830D6119A3846BA",
- "key_seed": "246A732C0A2F892B057A253141C26E21F7B0ECEBEF3AEA051118FC0E1BD8D36C",
- "metadata_key": "4B47D6D3B10A385845DF425AA1C38431",
- "section_mic_hmac_key": "CBE07A55700BC8C0BF94EB36BB907882CB50CB667FC240FBA6AC1830DC14F3FD",
- "section_salt": "1F657CA6FA909CCA6C1681FC6DD0928B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C5994B3FDEFF488147D2225A5AD3289",
- "aes_key": "EEEB9A1765F85001AAB7C718544D5853",
- "data_elements": [
- {
- "contents": "CF41A589C639780D91A23D762B7871",
- "de_type": 400
- }
- ],
- "encoded_section": "499013089985A0087D6F5ACE5AB3B11DC8EE0D911000DD64F5C39C94FF038BFAA44A1B009C139002D5EB61BABCC1E0AF9080528B6261FD81C25644B912DBEA20EC659DDE6F0778CDDC85",
- "identity_type": "trusted",
- "iv": "43C6A352609BF3D07C23F7457F7BFBED",
- "key_seed": "FE781376ED435B876E0E7FA261BE9A2E4D7362EBE61D5C015F6694019D4246BF",
- "metadata_key": "670F87F10099A52B7714DC7B088A9AB7",
- "section_mic_hmac_key": "94912114FD584C0BA0F6C1C462117D516F0619F216BDB8099BEF422FA50EA315",
- "section_salt": "DD64F5C39C94FF038BFAA44A1B009C13"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "86890C122BA74C502FAAA2B246EBFFB1",
- "aes_key": "1A42B8762AA6E9320C32FDDC669DC405",
- "data_elements": [],
- "encoded_section": "37901367745F1F321A28509A1FD382E5576965911000D788AFA3591BF1E13252441A7D280B2B9001C13C4CD9EB22629AE6ACB4648000FA2F",
- "identity_type": "private",
- "iv": "8A763DF0DC6548AFBF6EC1526711F13C",
- "key_seed": "660D035C9A48405AB89BF25E4F71494AC76286D993B2E8CA213BEBB6C00BB604",
- "metadata_key": "A0E42B6646670B54D13D012B2AC9D610",
- "section_mic_hmac_key": "3419FAD3032B38259FB4447FEAAC776F5E64DAF919AB24EAC7904709BF60BD61",
- "section_salt": "D788AFA3591BF1E13252441A7D280B2B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A507D673235683A679F00AFF69858E78",
- "aes_key": "74F54D0AC51AF56BE4CC75ABD624AF34",
- "data_elements": [
- {
- "contents": "9E4AFE615138D74E",
- "de_type": 758
- },
- {
- "contents": "2E7BD8416782398BF01F53CD4611DC26DDD158965C2C6D55D3",
- "de_type": 583
- }
- ],
- "encoded_section": "5E9013FE192C6106C46626A96469BBC51CF37B91100060EA0FE905728A9E01B9891E5731F91590010026C008E139C9EF930ADE42C20B09FB19D70EBDA109AC5CE58F35A7F05F329D2A7F8823281DCCE0C246DF43A752DF1B571ADE24671464",
- "identity_type": "private",
- "iv": "371E3734A83E864FE7434D06799565A8",
- "key_seed": "5FADFF2AFE58072B5C59C59B5114C5FE544638917F0EAA8B73B2FFBCB93C5ABA",
- "metadata_key": "138F084E2B8D250604A01F2AE51AE287",
- "section_mic_hmac_key": "F10F17E2EF9E66F261398CAACC64F069301D59F4C674C583941F959716435E1C",
- "section_salt": "60EA0FE905728A9E01B9891E5731F915"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BC4A32514B46C03C366AB566227DCABB",
- "aes_key": "319D7CB155D521DC9F2017535BE3809F",
- "data_elements": [
- {
- "contents": "663DFF01222160CB8B4AF0",
- "de_type": 611
- },
- {
- "contents": "74A119294F8C71D64DEC46282D88B43F3B896420A0A2",
- "de_type": 410
- },
- {
- "contents": "89A9338136",
- "de_type": 756
- },
- {
- "contents": "671D",
- "de_type": 830
- },
- {
- "contents": "745FEA8DAADEA15F08",
- "de_type": 294
- }
- ],
- "encoded_section": "779013FC8A3C4941128517FBF0C9DD73CDD5D1911000E70075B4DB3AE7073A33D45EB9A683D29004A2BF89757731C8381C0555234E298E9786845CD199883ED9444B434A4A0C9033DA1DB45E377719B2A7A9B5DBC9A999A43DFA606028DCB57E6FC55D6F1371AC9F0E45DCF3CF2477D87B39902B34758F7F",
- "identity_type": "provisioned",
- "iv": "C757A65A68F3EBD6A716AF192FF956EB",
- "key_seed": "B19A2C4A8869522DA56A328B502C3C5B54C7E272A6E77861225624038C9D9B2E",
- "metadata_key": "86AECBDC0B76BA224B501EC73B8E6BA9",
- "section_mic_hmac_key": "421CC07318D2A08C383681AE93B61845FA8E952FFB670340E6860D2BC29B3979",
- "section_salt": "E70075B4DB3AE7073A33D45EB9A683D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C54051A886B449242FE691EFBFB9B8CE",
- "aes_key": "B913FEC648BB9E3D942E6A8683F07BAC",
- "data_elements": [
- {
- "contents": "1F6DE79DD0F5CEE21D5D485A",
- "de_type": 980
- },
- {
- "contents": "9B",
- "de_type": 756
- },
- {
- "contents": "560487517D8A50F671F4ADDD8827D2ADE2",
- "de_type": 697
- }
- ],
- "encoded_section": "5E901348E76A5E52F4D62ECAE0CCE82DED2876911000BFA9F58BF2E56725C08161B4F81BB459900161AF730F1FC29BFA27F62252D430C72BEC351333D47129987FB00291F43B8343585C8B48863E042F6EC34D500743C95362EA6C97213BDE",
- "identity_type": "private",
- "iv": "F09F6C29C92034AB81F55EE06D133577",
- "key_seed": "9EA688C752FFAEE37FCB91894708CA03FBCFD9AB3798F0D3B1E1578972861CEB",
- "metadata_key": "00106D80565F791BDF1612CD3E290EFC",
- "section_mic_hmac_key": "72B11A271AAD73820E785D6C56578AB0847DD744A8E6ABD72790BDDA339F1223",
- "section_salt": "BFA9F58BF2E56725C08161B4F81BB459"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1E40D6365164CA659D4B50F39E3F85A6",
- "aes_key": "9B3859BC7836621D944C23864F6F3550",
- "data_elements": [
- {
- "contents": "8E3058E4062EAAC88D165AA151D44DF6AF58D634245F10FD71FE3F613275",
- "de_type": 90
- },
- {
- "contents": "B2FEBB35A264B7537903B8",
- "de_type": 712
- },
- {
- "contents": "29A0D1104C283E273DD5A3895D0A3D4FB996D96F4C482487E02F09C0",
- "de_type": 712
- },
- {
- "contents": "25BA53B6E20672A6C53F19FC35388A45EEE09CFD",
- "de_type": 819
- }
- ],
- "encoded_section": "9B90130505D9ECE86F5E3EDC6FC0229F02EC68911000964CF0FBD200823DA6AE76EDC4F2C1449001298E94F4601B7165AA782D1DA74A9E274AF98F92CEFC7AAF15075BBDF016D2FA06F09167A305BADA6B4FA6B2B17AA2A3F73B85C67DBCFA1F565C07C85281C3182C301FC3B810EDD4FF195EBF4D50C1ECCF51705ACB38966B2D61E496425E6B33D2017A5692589D573F1226C182862F31C1B06BF4",
- "identity_type": "private",
- "iv": "64FE3459449A905E996A5730ADAC500B",
- "key_seed": "791CBF19EAE82635964320BF77F90CDC6A40B25A714A47E2E696A03FE466C75F",
- "metadata_key": "35402883705B38294EB2D93FF46112E3",
- "section_mic_hmac_key": "EF49867605FEC8C35D229722B9DD3AEBEB0B434C4F4925AA3D34F706EFD87D21",
- "section_salt": "964CF0FBD200823DA6AE76EDC4F2C144"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B8071EC0685F84D18F37D305200EE4FA",
- "aes_key": "964869E0D50271B6944FE957380DBF8C",
- "data_elements": [
- {
- "contents": "24945148BCB09A73",
- "de_type": 483
- },
- {
- "contents": "79DD087059250E029F",
- "de_type": 440
- },
- {
- "contents": "9D82CC",
- "de_type": 812
- },
- {
- "contents": "775F99E59CCE70FCA9D050DD11",
- "de_type": 305
- }
- ],
- "encoded_section": "6490130CE57E93E2E8A432D77023CB6590E0B6911000F746162C91A850D8DCE3BD3A9090C0429002AFE864CCB7884BB9D8AF1C927C847FF0DFF33898E5AC6DDBA9A741956A4B488D5BB52C343B6FF4D9BB888D1D4366E357CDC20BCCBE05392091D18F8961",
- "identity_type": "trusted",
- "iv": "1CE7729EB320E531F4C3C60EE4C59AA8",
- "key_seed": "0D0FF621E557488CE9920E1DE78CEAC7B0D9666B21443FDC57EBB108FC1DDA86",
- "metadata_key": "9E53DDBB1F1FDF5E5899E62210663BE9",
- "section_mic_hmac_key": "E656B56AA9B2A4A91571D7C6F593AC20AFE90E83E0C13EFA883E20488E37B487",
- "section_salt": "F746162C91A850D8DCE3BD3A9090C042"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9C13345061898B01207C68614DDA532B",
- "aes_key": "AA5B840D4BFDC99B8AF79B584CE12E84",
- "data_elements": [
- {
- "contents": "A1F81F14E46B",
- "de_type": 390
- },
- {
- "contents": "A42D01AA6C08",
- "de_type": 160
- },
- {
- "contents": "9AE6B3E298",
- "de_type": 937
- }
- ],
- "encoded_section": "51901310EAEAFA6AC17122CDCA2573D355D0CD911000CCF8CC3D63587712B4E731FD35EAA3669004B915C781CC1ED7331474C7BC423AFEAD113D1B25C0E94E69E3EB59894678D87BEEBE96355C09DDD32C4E",
- "identity_type": "provisioned",
- "iv": "95A37DC09AB387CE11030FEB6B1C9DFA",
- "key_seed": "B570342527343884EF1CB5BAE4228CC72A19C439402FC11E449A4CBCF50F7E3B",
- "metadata_key": "46EC49AFA765AE05F70C74DCA5715DBC",
- "section_mic_hmac_key": "0388A70B3DB58C158BEB9A21198BD81FDA14300D6FD4527C80B33E7929C21021",
- "section_salt": "CCF8CC3D63587712B4E731FD35EAA366"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DCF9E3CE0572EA0DF42D4A555A23592E",
- "aes_key": "ECB0F2C8BC9E75FA10F8EA4B4D8629D5",
- "data_elements": [
- {
- "contents": "8920EC9E22CEE0DD1C8ED84CD007DABD37160FC8AF0AE95923",
- "de_type": 728
- }
- ],
- "encoded_section": "53901313FB99AE0E6BABC8B4849186D87DB4A89110002EBCF33E80A1C8FEF0FEA18D38F4B6FF90028EFBD0ACAE3981D4191B91BD4A7931FBB7AB9587A17D735034B8B94B2E0B5E4B99E1074CA04F4D136AE760D6",
- "identity_type": "trusted",
- "iv": "4EA1AB449CE1ECCF1D975F94E111F508",
- "key_seed": "8817390FE2DDA73E10454028375DF6167C737A41591E2F8BAF9E6EFE8185669B",
- "metadata_key": "EA92B90A39ED2CEC3D5D61B74B07A356",
- "section_mic_hmac_key": "ECE846A0D0C013B82CFB53C18F7D044FCD7E53B027F2B562CD43EA2AA881C343",
- "section_salt": "2EBCF33E80A1C8FEF0FEA18D38F4B6FF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "295C4F693C6ED0E9B8E92727C5F4A7B4",
- "aes_key": "A45CD64E2DC93AB7FC688850CD3B3FB5",
- "data_elements": [
- {
- "contents": "65CF460752C1B9676A2049D19BDA1CD3F2",
- "de_type": 43
- },
- {
- "contents": "7BDB1C4245F476F0E1CFB5F1491C5C0318416011AA69",
- "de_type": 45
- },
- {
- "contents": "22756DE6303A1311BABFA22E170E9D1F",
- "de_type": 762
- },
- {
- "contents": "6F23",
- "de_type": 329
- },
- {
- "contents": "480AEB8EE08170C1D5FE904B5BE9DA2AD094376598DE0F70548B705A25",
- "de_type": 828
- }
- ],
- "encoded_section": "9A9013BC95851D486FAA4EF13F6D7A5AD6E6CE911000749C9EEA6B4A6792229D9E531152124890015B7124853389DBD3B5CC2524AD1C434B2C10214716D89D585E8FA0F55E1CA11B4BC8C262D1BAED2019E61C815CAB00036B15424E1DEA61A93DEE90FE4663F3EC04B1010BB7A178F47B6BDB61847DD9B9A88D35CE2D9A247968F93549D09CF01A98F33B87F038EF995137DADC3D9E2C908D61E7",
- "identity_type": "private",
- "iv": "CCA81A30F3887FAC55CC619C978C0B45",
- "key_seed": "BC9DF6FAE9C35B873DE0FE4AD8CF11245105B7AC518D80498A5205BFB35074E9",
- "metadata_key": "32A45452147E1B0A64313C39EFA855AD",
- "section_mic_hmac_key": "B25364C8CBF115BF9A46287B759768B611CACEC692152D0DBE125FDBB3A8829F",
- "section_salt": "749C9EEA6B4A6792229D9E5311521248"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "12571F71243CD373229D0C7BB8D30710",
- "aes_key": "49B6E023B58BB34C272F807D5DA0A938",
- "data_elements": [],
- "encoded_section": "379013715C03AC7E1419D8D44694F5A4CB6266911000D55A403C5DEAB9883326E5B111C522049002CED99F5612149B9FDB72B03FADF057D9",
- "identity_type": "trusted",
- "iv": "B0B763E4D08FC218A318A378EBF75E8C",
- "key_seed": "16003DE1916A0820BE43D32BFA1629E67FA83CA01723D4FDFD95746BC16BC7A2",
- "metadata_key": "A3605E523D0C4E8CA3787B141CABDF32",
- "section_mic_hmac_key": "13E544ABD5FD671F496322D77A4446C3B77ACB007F746A4B948129500045FAA7",
- "section_salt": "D55A403C5DEAB9883326E5B111C52204"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7856ACD18EF6930C9EE065073F685E8A",
- "aes_key": "F6A6945E6C274AF90CF773F8D4FC6FF0",
- "data_elements": [
- {
- "contents": "DBDF1692FB5E018F0C49A7",
- "de_type": 908
- },
- {
- "contents": "028A7815CFF85F0AC6D5",
- "de_type": 291
- }
- ],
- "encoded_section": "529013CA6D31C6A12CAE2D2636712A77C22F51911000884B1C54E519FC35F64802BFE939E6929004B056A9831532176B1AB6F17B7577C994EAE50667C44842ACB793918F39962150F1EB4AA0E520277691063A",
- "identity_type": "provisioned",
- "iv": "6F79E25D027B6E4186761C47E6E1EE0A",
- "key_seed": "A891081463E0C9FE931B23F137879FF4B344F2BCB31D5FAEA2A8BFDDF5F13781",
- "metadata_key": "07210356E3A7C4AF1B88209799127A55",
- "section_mic_hmac_key": "9DCD53D49928551A914A807FFB85660F307480AF464ED3691142DA591D79C951",
- "section_salt": "884B1C54E519FC35F64802BFE939E692"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A45B0515F2A249BF7B1387CB70901AE",
- "aes_key": "021CF92CE743805B8DF93B88E6AEF0D0",
- "data_elements": [
- {
- "contents": "08D11FED65701B3A3F5402894F1165",
- "de_type": 677
- },
- {
- "contents": "F49808BB6625467F86",
- "de_type": 810
- },
- {
- "contents": "CC13627179B6B8AD3F84",
- "de_type": 889
- },
- {
- "contents": "2C2EBC4E0F92D24D03A867AD8B07300E1F81BFEF9AE4C2B3F980",
- "de_type": 950
- },
- {
- "contents": "E55E101A8EF67E80A3AE5F8A0D1A5C1F37B627870B9D586FACB5A718EAE7",
- "de_type": 760
- }
- ],
- "encoded_section": "A090132E71DE6700AA3E0C1C842F31A135B2D5911000562D7ED3A3EA4D2620E92FA7DD128BDD9004035EE5E4CC870B7B1B812CF79D4719E2676E5E2AF7CED20BB42F45CD7F9B8ADC660E976D664DB7B10D049EDBEE2B60E69700410951E62CEBEB4EE089730CF9B259A2B651223902FF17B6FF7C025109F7AF444DB9C2DF564E676B720C0B99C0A9B84DE4D6FF084AEB943B95728F94BB1C65E44CE6C5A97A8847",
- "identity_type": "provisioned",
- "iv": "6AE6067877803C9B82D5B30A6792FFC7",
- "key_seed": "1FF1D25A12210940D973C467FD115BB4B7C906C3FB38D21F16BE63744E016B5A",
- "metadata_key": "CFF931305B876F2DBF5BA261EE9E8D17",
- "section_mic_hmac_key": "467241B19A991B7AE839D5AA1DA92038F7389ECB55796C6C6B5B181070E23EC8",
- "section_salt": "562D7ED3A3EA4D2620E92FA7DD128BDD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "485599A65B35D21A40658A9E2766B597",
- "aes_key": "8663ED345FECBB713029DC829D74543B",
- "data_elements": [
- {
- "contents": "E9",
- "de_type": 810
- },
- {
- "contents": "6E6E09DB0F2355AC2B3C",
- "de_type": 404
- }
- ],
- "encoded_section": "4890138E055A46A940DFF96DF637A5EFD7B93C911000E0A1D051D8D533CF3E77E10A5F8B6C0E9004E4E7C9C6EC8AFC814102DF0DBCEB09A00938F75F24DE48ACA96EB524B708D6D545",
- "identity_type": "provisioned",
- "iv": "8561B433E308C0D1CA6C9C91BCF0FF81",
- "key_seed": "F3F4C98BCEED47C4E562B406D4BD793926B20945745F48D0EB78D5F31F9F2BCD",
- "metadata_key": "308BB628E7DECE141A7C5309ADBD6A62",
- "section_mic_hmac_key": "0CB4466330332C9FCD21DF8388B1A82C1384D041924657423091BF61A5199BF4",
- "section_salt": "E0A1D051D8D533CF3E77E10A5F8B6C0E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0483C23ED6D77A8D0C278940BBD177ED",
- "aes_key": "0621EC75B3278510C3093EC0603EDCF4",
- "data_elements": [
- {
- "contents": "417A9B78",
- "de_type": 640
- }
- ],
- "encoded_section": "3E9013B8E0A03E4AE2E7C1B9F25ED66EA06746911000B48692BE5AFEED1AFBD1184172C7C7969004C1B7DBD5F3B1FD26360B730588E7A5D9AF6677656E2307",
- "identity_type": "provisioned",
- "iv": "14AE44FB4E180AF23246ED81C4286150",
- "key_seed": "A0C7A5E03E6FEA711AAAEEA331CF2B1FC7FF1E9B11D45910ECD2C5B9DB4393AD",
- "metadata_key": "F190DAF1401184759B968F030ADC4C41",
- "section_mic_hmac_key": "969F571D76ABDBECCFAD193C906C94295C28257C8B6595A08FA511ED4107B32E",
- "section_salt": "B48692BE5AFEED1AFBD1184172C7C796"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "22663881121C84CC788A4F6922C843DE",
- "aes_key": "0F81827BB3D0C01DCF64D7E758984BF3",
- "data_elements": [
- {
- "contents": "68C7FA8F642F7EA1691EA458690F29479E21B04CBB109FEF",
- "de_type": 811
- },
- {
- "contents": "8A0F88051FD567DE679BFB29095332F265EB034173FB9CCFA5",
- "de_type": 435
- },
- {
- "contents": "7248F229F7C3561570",
- "de_type": 431
- }
- ],
- "encoded_section": "7A901340369C7D4FCB569C613A49C8DBD0329B91100018EA0774B5EAACC943949E550BE9BB3F90027ECAEE8A6F71B9D7FB08EFE2E3703DAFAB895EAAEB766E0553D865D90BE25DFEFA27648AB16D8B9C9A6D9D516DA6C8D98A3B0347742CA933963AD32B77090A10B631362604FCD808CE3CFDCD1F55501CF6F591",
- "identity_type": "trusted",
- "iv": "619245F3980B3B070388B0E858E58611",
- "key_seed": "3F58BFCB2F818DFCCF2B1A1DC6EF4CC4C30B798F65DBFD6CEF0FBEB2DD78D6D6",
- "metadata_key": "19C7DFBC68C5918D20EEC53476B394CC",
- "section_mic_hmac_key": "C7434DB05FC2B8286FB317867A78B34C7344CFF20EC1C4C7AF58D2DF66FDFE67",
- "section_salt": "18EA0774B5EAACC943949E550BE9BB3F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7F398DEAADE4F63E3321618AC28B0A8E",
- "aes_key": "0218AA8671D3E2E3B9EFE1B5C4C11581",
- "data_elements": [
- {
- "contents": "9323424FE556B495790619DF9DACC116",
- "de_type": 37
- },
- {
- "contents": "128970C823632AEF313503B1",
- "de_type": 782
- }
- ],
- "encoded_section": "589013F189A6CB59AA3A5558AF3E6A708542E29110008454882DDD820F52035C40B1D5312A4C900428991BD1031F9679D03ED9FC6B252EB552937EEEB002F5948495D55B8C19BDA0EF0975100A8CCE558ED14FB7CA41783BA6",
- "identity_type": "provisioned",
- "iv": "548A8956100DE08A0305C789B52833CD",
- "key_seed": "5B76B5CB1E81CC93E525AF117B8251E0F61C5DA57E4FA328E61A5BFAB48718C4",
- "metadata_key": "CE0A85F582B746AF57AF0349E3258079",
- "section_mic_hmac_key": "67A13CACBAB11819E8EB4E22F9F81693557DE288C42AB3731983D0C1B3C4FF76",
- "section_salt": "8454882DDD820F52035C40B1D5312A4C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E86E43C49AD176E39A0AA9821C78602D",
- "aes_key": "BCD5E866510A0A5B815385B383B22AE7",
- "data_elements": [
- {
- "contents": "EC",
- "de_type": 581
- },
- {
- "contents": "59789A920867697109C3740D0B8029F1CC7000FF04EC0940",
- "de_type": 978
- },
- {
- "contents": "940D7B076B6CBA0B73872A012345F3BA97410D8709501262839D3DE137",
- "de_type": 135
- },
- {
- "contents": "E261435EBE",
- "de_type": 88
- }
- ],
- "encoded_section": "7D9013EFC8FC9DAE00AF80415337DE30A6E31A9110006E869407F2E81551F812020C3433D0E1900254214E6EE97EEF7619C5FB9880E26357ADA5681E80DA9C8E367034D066375C0E8B834CE14A1AB864C7EC310AB35FDCC21167922D8192D0C782DB32A745BFC329176791D090CEE07B7C2E292EDD1DFEE41623C9555EF7",
- "identity_type": "trusted",
- "iv": "65C99C5FA0A0746E69C46E0C4A857592",
- "key_seed": "BEA6260AB3A2F619ADB859391F6A6CA28177B84CD449C728F6189F0467F525E1",
- "metadata_key": "7DD064AA32B3E04C57BF54B824641E1E",
- "section_mic_hmac_key": "6660174157DC50F6D1C82D1C8D416C0E6EDCA0874333C3D94B46926CFCB12495",
- "section_salt": "6E869407F2E81551F812020C3433D0E1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B040969C351F81AE34697DC725DEAC92",
- "aes_key": "3AF9FD8F0D0707DA73D7688D0CA0D2A4",
- "data_elements": [
- {
- "contents": "131A8175D19006DB8D9021",
- "de_type": 125
- }
- ],
- "encoded_section": "449013A902FC6AA6817E9CA34B810932FCB9FD9110008681C5D8FBCC1970B3C6D9F7083FF9E9900475EF1E2E01C84DD0353766ACDE314778BA6ECAEAB9D9A63A60B5578C96",
- "identity_type": "provisioned",
- "iv": "8C96BB516E8363C0CD2BEFF0AC4CC486",
- "key_seed": "637D181D26E0CF8BC0CE45DFE20610F6EAA306196A0C22BF51DEEC49E1A33DAE",
- "metadata_key": "FAA1CBAF42E95200D71F3BEC89C79671",
- "section_mic_hmac_key": "CC1FBEF9A592EB51101E67FCBA18B5FC3DC62CA157CC01ECC68B9BCD643FBF0F",
- "section_salt": "8681C5D8FBCC1970B3C6D9F7083FF9E9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "259B5127DF0CD589480E4C1AC87A2186",
- "aes_key": "4188F8C94E54114D83CCDBA4A51A1BDB",
- "data_elements": [
- {
- "contents": "A0382BA41C0E9E669742CCC8830D5573AD19",
- "de_type": 851
- },
- {
- "contents": "624153",
- "de_type": 573
- }
- ],
- "encoded_section": "5290138B66DB3AD592825ABCAA7F300DBAD488911000D13AB39D6F0C08DE53F3B616CD929F529004A5838FA715D57CE71AF1A64E317091B45E3310331738129691565D4839D38D4D6127F0235BA458A90A2766",
- "identity_type": "provisioned",
- "iv": "0235DBFEC90AFAEB878738BB174A8EC4",
- "key_seed": "E8E501A2579003EDB979B9C5B4C806B4A428D23DA93761D2C8031169BFF83A49",
- "metadata_key": "236C4FDA97FD30586D9FC950F334367F",
- "section_mic_hmac_key": "D28C28C41D9CD5B0481A62C0CEA0BF13E4910DD423C1D93C37B507D32D33DB8D",
- "section_salt": "D13AB39D6F0C08DE53F3B616CD929F52"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4C5AB029E86C38CBFC138696992D680",
- "aes_key": "82DDE2E32703369FFF54C2119F64CAE8",
- "data_elements": [
- {
- "contents": "",
- "de_type": 580
- },
- {
- "contents": "FB89815745BC95",
- "de_type": 244
- },
- {
- "contents": "2C17D2FC866D81525A7E8595D271C871B96942BE",
- "de_type": 376
- },
- {
- "contents": "4F42923EFBCF460A8D860BD405DDCA46F7C9DA0F9232E0EE23BE8B97",
- "de_type": 778
- },
- {
- "contents": "75924E160C",
- "de_type": 857
- }
- ],
- "encoded_section": "829013DC35D4DE7558FE79F6AA7C452F808B9E9110008F239DDC995DF4C680B358A8799066669001C201BDE177845AA6604EB7B7AF789F5B7502B5F6B6E546EA0ACDC9715CAC6D0250188744CDC08F61E13BF0C177E9052B3866BBEE1939A20D19BCCAEC81F6B365164759EB3016EDFDB09B0064C21C15EFAF9A9E51EE666D2B8D5174",
- "identity_type": "private",
- "iv": "090B960514A2ED05926303EBB8DFE844",
- "key_seed": "117205E1E7B6CBE3FA0DCD6A5654D6D4441C86E3F1D2CD8D14E9A00A50F44A79",
- "metadata_key": "E29007F32F7ABC691ADB2154678D5033",
- "section_mic_hmac_key": "06B6CFE233713E34981D8C0B59B6BE1471986D027521B7DD6A9690E3E74C735B",
- "section_salt": "8F239DDC995DF4C680B358A879906666"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BE9ED7A60A893A866CDD037770626A2F",
- "aes_key": "7DCBF0B035A5999D3B459BDDB37B9396",
- "data_elements": [
- {
- "contents": "2EBE52B4DC1044C8",
- "de_type": 760
- },
- {
- "contents": "C061BDBA02F6C0E30E0DCBC8299DABEC493B",
- "de_type": 472
- },
- {
- "contents": "21",
- "de_type": 20
- }
- ],
- "encoded_section": "5A9013411A3B5ACD35928ACAD6914239129E329110003099AE6FC3D8669851B51D620A42D12490021B9AE05BD61343867C3C240280327F3246B377D7395B554EB49E6A77370AA68674ABB2B6A256306A1F6719625FB54CC895CD4D",
- "identity_type": "trusted",
- "iv": "9D72BBFEA0497D1DA4ACC45BB2A90377",
- "key_seed": "94F97F6C1E46E30EDC42E6CF6D4B8A1BAC6ECC27853F85B2C8812020CEE49433",
- "metadata_key": "4796CE9A597223DD3B0FA429601A6835",
- "section_mic_hmac_key": "E480E1D001AF6DEAB85E05569F89C554C91B4C10782D524BB531C0923E5250A8",
- "section_salt": "3099AE6FC3D8669851B51D620A42D124"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A9CB9CBD617009C6886517BDCE283660",
- "aes_key": "33CAB010C3BE276797895D0CBB60AF4A",
- "data_elements": [
- {
- "contents": "D5D03D064D9C1B5E9A5C4843B275C3CD",
- "de_type": 202
- }
- ],
- "encoded_section": "4A9013A93E5B9A890CC11B51885D93E342F9389110005A3E86C86385ACDEC0F67A0F951409459001AC946618BCDE275AB4E5C0B22C054AF7D38CA4BDD5EFACC2BF163FF305CC85E79B26FF",
- "identity_type": "private",
- "iv": "4C11908D956A1BE7E5F376D7A95379DF",
- "key_seed": "26EA70FB5958B3D30BE5A4B674BF26C35B1165F1167D4D26C2D4FE89A95C444E",
- "metadata_key": "450130FDC1E9E917412A844B0B6965F4",
- "section_mic_hmac_key": "17D847BC251573C504C4A10D3C9D76CBCC4D8D59C70AF2FDEB8BBAB809195D5A",
- "section_salt": "5A3E86C86385ACDEC0F67A0F95140945"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8DA30D413D04342787231D2F4703060E",
- "aes_key": "73D393348C0CE43988E36C73C2801695",
- "data_elements": [
- {
- "contents": "5AAE629F32372A1DAD4D4214BE001D6004297951F2BF14A958",
- "de_type": 250
- },
- {
- "contents": "71EED7E50F377AE422EE9A62664C63B6E8FE7414A9972E",
- "de_type": 997
- }
- ],
- "encoded_section": "6D90138CE8BA256E0D3CE40503F1380555F4F7911000BB2EB1934C4103EE116FCD3227F2E7069001753ED1826BB108753950EE7BA87DAFBC1B893DA6A95349D954690CD30E420AA407E8E7C19B7EEF39A868DA4EDD7F4D94E30A775DE0C1853EFD8376B7E913D57B9B22BD228340",
- "identity_type": "private",
- "iv": "B1A2C2E8EACB2DAE589BFBCBE73936CD",
- "key_seed": "444A7A142BCEC48DECD9BD96B469078C247A46A276589BC49278B46DA1E66898",
- "metadata_key": "CDF23D34FD5AE8DCFA43439FA8C1DC83",
- "section_mic_hmac_key": "EEACF4F747FAF85850228F313592C4A866FF0203423AFE73AD8A784C68194679",
- "section_salt": "BB2EB1934C4103EE116FCD3227F2E706"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4E79E2C2CE7D1E7F2B4C0E1B4C6FFC4E",
- "aes_key": "686366F14F36F2790F49961D570E31DE",
- "data_elements": [
- {
- "contents": "79A5FCD4C4",
- "de_type": 275
- }
- ],
- "encoded_section": "3F90137BCB86F08C9E2472B4D7865E8BD67102911000979F2DF1B430F042258DB96F09AAD2DF9001DE6026894781DF90B574283521D90A8717B44B9B83E93441",
- "identity_type": "private",
- "iv": "CE4D3E400223D202DF6364CA96D7E81E",
- "key_seed": "2228A838E4A0FFEAC5045A52ECD38BEA130DEAE56F87E848D347EB39DE7A04D9",
- "metadata_key": "28D3DD52B97F54DE9D11725E5BF0DC77",
- "section_mic_hmac_key": "A08E5F1CADE33CEAF811625E4F2431704021BD148A11C14E628A98F81F266BAB",
- "section_salt": "979F2DF1B430F042258DB96F09AAD2DF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5E29E2EB2092471CED1528AFADDC750D",
- "aes_key": "737BBD18F03E6F059B322E4984AC52AD",
- "data_elements": [
- {
- "contents": "7EB2",
- "de_type": 976
- },
- {
- "contents": "BDBC400C6F43C492E5BC65B89C6A4F7F",
- "de_type": 716
- },
- {
- "contents": "4C",
- "de_type": 151
- }
- ],
- "encoded_section": "5390132D49C0DF41955CA5679606D637200C9A9110001AE616ACFE4F0F208FAB57B1798342BB90020334CFDDB0B6CE4BC468F665A6D3E9848C4EDBF35A9F75066415684A86653A4C961ADD30DA100FA9D45AB391",
- "identity_type": "trusted",
- "iv": "5D03AFC4DBB2F4EE8754B67BFC78BFA9",
- "key_seed": "9DB1FF1FB929DAB1AE43C57DA23E8F85253E8FEE48A2BB00C3F6034DEF843692",
- "metadata_key": "242B7758F74E2B36DF8E7D81150606AD",
- "section_mic_hmac_key": "4C0D23B47C5E9382FA9885B053CB40936954A90B59F2401BA4C0EDBE229A513A",
- "section_salt": "1AE616ACFE4F0F208FAB57B1798342BB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "242CC33270FB75C2FF4AD84277688FF7",
- "aes_key": "EFDE819D904C83619D2D30E4D70B8CC8",
- "data_elements": [
- {
- "contents": "12529277C5D50C8A4F095B89345B",
- "de_type": 507
- },
- {
- "contents": "63BA0A52CF5AD99CB9195FEC1DAE109ACF988B7BB17282BD",
- "de_type": 1
- }
- ],
- "encoded_section": "62901383DE207E70B383FC58B678E7BF4C5F419110008C5E1F088294820FA32847D46AD64CD99001E9A0818C660D4C99844859DCF57F3D97D58E724BB646F119976FABA1133442628E2C0B2F46D86BBFA1853D6C5ACCCE677175CC9426CFE14B8AE6A3",
- "identity_type": "private",
- "iv": "496EC166AF60125F0446D500C3C3819C",
- "key_seed": "4D7CCAB2C94F07DB0EBAB82519938066F522CECB330EBC69EAD51162FA850B5F",
- "metadata_key": "C2F07402322F9CE5371684278F3E2135",
- "section_mic_hmac_key": "C706AB65E845183DBDB246542F2DC17AD0B9F185BD72631BFD48648E84B2C19E",
- "section_salt": "8C5E1F088294820FA32847D46AD64CD9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "838C29BC8D62B7D297AA86FD6243397B",
- "aes_key": "A72506C80E6101E8215D5ECD7CC6676F",
- "data_elements": [
- {
- "contents": "",
- "de_type": 831
- },
- {
- "contents": "11ABEE",
- "de_type": 750
- },
- {
- "contents": "A99BBE1C3491A3F8E9FF3275512D74FBA0E11A098F279BF2AAD24A8E",
- "de_type": 180
- }
- ],
- "encoded_section": "5F9013B302168E039F6DF5F2FF279877BC1B6D9110005825ACEEA13D43300CEC795C9B920143900121D5C02870290006416E2234FBF50EB66BE0FB78C922B7C5066877C09952128FAB2AA8C264716E1FFAAAC4BC1428DC23A61546EFA39DE256",
- "identity_type": "private",
- "iv": "F1B9213795CF50E84E407BD7183C35AE",
- "key_seed": "0900BCFAC049F0F0D650C4FCDC0D6F2E1D92A5F60B1E8BB145ABB628AE5E58ED",
- "metadata_key": "FD4E55647EC444ABF650341BE49BD761",
- "section_mic_hmac_key": "940BDD8441E16C1D3664C7A47FD3453C7DD9090535D53E84609CF8CE3410CE71",
- "section_salt": "5825ACEEA13D43300CEC795C9B920143"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "608E20905F4D098AD75DE34EBA3CDB0F",
- "aes_key": "12C7CDA60ACECF2B3D80CA63FB0CE287",
- "data_elements": [
- {
- "contents": "15F7D3848623835A",
- "de_type": 717
- },
- {
- "contents": "5A745E",
- "de_type": 3
- }
- ],
- "encoded_section": "46901316E172E08886A7FBEBCC5B3AA0B17832911000F09EAABD05333528D512C8754644B8AD900467F1A59A78636BADDCEA44E2893670AF125640CBE4AD92E0C2660E6B8FEA55",
- "identity_type": "provisioned",
- "iv": "B23BF0D8170F7217B2D653298DDD2F85",
- "key_seed": "EF6FA69F6234C814FE90CEACF8312CD80CFFE80D89B2F4D95E7B8D3E2CEE31C7",
- "metadata_key": "1F0CFD60026CF03DE3CA79B50FFFB3CD",
- "section_mic_hmac_key": "3C3E1B060458BACA20D16BDCB96BD91B5FAE8216ED5EBC29943EF8C6B02C3C86",
- "section_salt": "F09EAABD05333528D512C8754644B8AD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C10B4E56E4683A24D3909A366D30B66",
- "aes_key": "1F64C99EEDE773095F8E5189F3F9A7DB",
- "data_elements": [],
- "encoded_section": "379013AD9EE886E64FB47387AFA86F92431ACC911000F0A95F8B37A126FAA7403D8A3AEC350D9004F4D183272101D5C8C109012B210A5C67",
- "identity_type": "provisioned",
- "iv": "342C3BAD447104821279EC85291B0475",
- "key_seed": "B2101BE6844AE38B5AC0D33C747729B1F09E4C8900EAA870412268A94852B40D",
- "metadata_key": "91F63DC00A30570F6205FDB025AA95A4",
- "section_mic_hmac_key": "3065A710A4107F326F25360F6E498B7375AFFE566A86DEFB62D254C67EF089BF",
- "section_salt": "F0A95F8B37A126FAA7403D8A3AEC350D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D94830ED029B92E5B29E222F722B9B6F",
- "aes_key": "C57D61016B89F28132CA0B4CAA8A1CA0",
- "data_elements": [
- {
- "contents": "402E4416B0C352C40F1163D869B8B760C17457D6C3",
- "de_type": 188
- },
- {
- "contents": "51248E19812A467000",
- "de_type": 62
- }
- ],
- "encoded_section": "5A9013EE7189D36F22441A68DC1425B2B4A411911000CFF8A395F22500E8EBCAD614762CF95890018C3EE3D4AEE5CFCC9E2D3FA21E1B79F7D2D3C7364CAA0F33952C56709120A420E36A8443D4870413BA5BD27BE985B58F824AC0",
- "identity_type": "private",
- "iv": "DF4774BDDAC6C269773CD0978A6165C3",
- "key_seed": "346411BF7C90DD0794DE3F6C9DA0D22F6B0A59811E164CA362548BEC7B452A9D",
- "metadata_key": "D440B77462CB03579C051678FA0C9E06",
- "section_mic_hmac_key": "70A01DA6C369A6B9ADE05B5C57EB0D5086D2A4EF2BE3745CEA1EC3AADB0EE1FC",
- "section_salt": "CFF8A395F22500E8EBCAD614762CF958"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "655526F2B3BD4707D603BACC74ABB7D8",
- "aes_key": "FCE4B6C8FD25716486D3713F4331B438",
- "data_elements": [],
- "encoded_section": "379013D596630672DF75A4EA5478E59232E39D91100095894B2B79D0B4A3FAD605E277AA33A29004DC96C8EDCD236F241AF6E6AA6DC69752",
- "identity_type": "provisioned",
- "iv": "E890D5EE6189B3BAB5FFDBC0AE63CBFF",
- "key_seed": "79B865DE8DA7B8930812A3D4E627A1CE74476AA1BB51116CC6B43A0E0C3ECAF5",
- "metadata_key": "0FAFAA9D6FC46F82384F0D12FB7CD252",
- "section_mic_hmac_key": "927666232383A3029385567EC2BEE80951FA4ECF87193393D76E545F3EDF131A",
- "section_salt": "95894B2B79D0B4A3FAD605E277AA33A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A03E7E784F3434A59007980D905D9B94",
- "aes_key": "4C68AC909B3117588857C08E1372E532",
- "data_elements": [
- {
- "contents": "184F372DEE00B3F9ED09A7BF86363D488330FFF7C2A0BF099257B3236C",
- "de_type": 301
- },
- {
- "contents": "9A6408F59389014B219E5B5AD8160848ACA710DE893162BCC2",
- "de_type": 713
- },
- {
- "contents": "5D3D783CEA628D3E482D801AB6B1E2",
- "de_type": 799
- }
- ],
- "encoded_section": "8590139CF16293B97917755ADBEF1A013CB4DC91100011705C1239A7475C4A716F4C78B1C8A29002D00DA5542C9AE536C8295452971C87A93A5A15D6C531300972C9451FC7F2644E5803E6E2ADACB793DC59AE0BEF3ACE6E06F03991C717782A35D5DB04914ACA3DBA25CFB011C3A55933FCB48DC19D1938DEC79B8019285B5394C67E60E4D2",
- "identity_type": "trusted",
- "iv": "6A675C10F654A737352FA395761C8645",
- "key_seed": "A5A12D4A886399DE973FDD1D713335DCED621F1A9912397CF17589F2921C3B37",
- "metadata_key": "F0354D2E5C76AA746DEC6F428377CFFA",
- "section_mic_hmac_key": "B5FE7969BAFFDB41E39B07E4272ACDD8F2959147C8A3524FD34895B1B4AF1215",
- "section_salt": "11705C1239A7475C4A716F4C78B1C8A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6FCE962D651CFA1D1FC26D80D2766F41",
- "aes_key": "B4B66DA5F5812D38A75BDDD3D39DD03B",
- "data_elements": [],
- "encoded_section": "3790132AB715C6AD8256E26D58639B9D263A4D91100078185D32370D3883575CD08D246320B69001F7D0D2D1DDD55101513DB171CA62205A",
- "identity_type": "private",
- "iv": "C1E034C75C6B7F6FA8FD225ACE7198F9",
- "key_seed": "B1CCC7A6A5647E35926BC885BC1462888401B75E7E873A160D9078009E176224",
- "metadata_key": "8D008DB1E71FF2FA4BB7846A6EB5957B",
- "section_mic_hmac_key": "B60AFA9229E0A951BE1EF9C112E0DC7E5BAEFB8EFD6C4D87C49B12AA9FDFC246",
- "section_salt": "78185D32370D3883575CD08D246320B6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BF2838A458097277ADCBE68878A11EDF",
- "aes_key": "A42FB4383593544F9CD02358F7450E3C",
- "data_elements": [
- {
- "contents": "9AABF3A4911F54903A7A585C5935598A17AC1BA1730F11BCE2",
- "de_type": 220
- },
- {
- "contents": "DBE8AB3119CFACBA0616EBEF11805BA7DB4C6D8EE936A0C75A585C3731",
- "de_type": 109
- }
- ],
- "encoded_section": "72901311DD08CE860EC740F5AF704F4ADC6197911000A5915C75281308C25817A519495433AE9002ED9804291B041DF22F1132D88C7AA514CB99C25507964F71B3E681BEC95DB43D36ECCA071FB2EAB77EC221F2814F09A6407F6D6DDF2EE971EEB161A2E4723C08C3D8907207D24940AAF9E5",
- "identity_type": "trusted",
- "iv": "B1C915A96024FB361DA2E9E17D7C8666",
- "key_seed": "D679DE42650FA520DC444F00DC53331B27A4204BE69BEB44794C7566C616CBF8",
- "metadata_key": "76A213E2A9FC5F503DD5C6E48151E973",
- "section_mic_hmac_key": "F5A02393A6338BC5D6F1099318530780F0A4AF604FEFE53E948D55487CD6C14B",
- "section_salt": "A5915C75281308C25817A519495433AE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7DBCB27A82A7D1338F3F078D12EF928C",
- "aes_key": "EA6B8BC0D8703795277414578517CE68",
- "data_elements": [],
- "encoded_section": "3790130BA98A4D2047B41A35E80D49E0D91691911000670F2BAEA4F3B15AE1D3E0A72C72C9209002DB5533D4335FD2C3B6461A9967D344A2",
- "identity_type": "trusted",
- "iv": "758D967581262F3882B691B017798245",
- "key_seed": "8B3FE8D446D0293D99FF268E762B47E33A0B530993E7177F7FED43D4F8C31CE3",
- "metadata_key": "36C1E1FC2CC7E80D4FC938FCB14F4A1B",
- "section_mic_hmac_key": "5DA2A4D4B98205C3C9FFCCB93F070B4899739631327C7A86246E0D5111EADB48",
- "section_salt": "670F2BAEA4F3B15AE1D3E0A72C72C920"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "956D51B44D835809B4DCB5C1D6EA607C",
- "aes_key": "2AE3CDCA25A22C8A800EDC754D23E416",
- "data_elements": [],
- "encoded_section": "37901310086B129A7A396A6DF01FA7F82D5CA7911000ACB37E7A8113B240AE185B5E6AFE9242900251C8DEEC88E53A72C6DE2D61D82C1E04",
- "identity_type": "trusted",
- "iv": "FB4F3041A58B740895B607D12438A62F",
- "key_seed": "75726D6692B7BA73365ED6114AD116A882A771857698CD296A1766803F0C748B",
- "metadata_key": "090CE8211B3E5418AFFACC353FAE8E45",
- "section_mic_hmac_key": "EBCE5FBC0923360145A72E27B3FCD677A9B16527631A374EFA5BB4766BF3567A",
- "section_salt": "ACB37E7A8113B240AE185B5E6AFE9242"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "875B4DC0A9FD6582A298160D8B07241B",
- "aes_key": "DD8E7898DB01F3022171929DBE859B05",
- "data_elements": [
- {
- "contents": "820995BAB825E0BFCDDD7710B139746B8E330E859FFE",
- "de_type": 177
- },
- {
- "contents": "6B1EFB732380455FCE778DB6DF50D9C474BBB3353845AF1B",
- "de_type": 883
- }
- ],
- "encoded_section": "6B9013113600EB6A517F05193F05274022755F9110001CE97084F1258375F2CBE48D88EDE4EC90011A1C1B2B6E68CAD942903FCACCE5E428FB1BE044C55685B3EF94097A3B1FE658703C24BB548E88ACCE80FFBFE5DD8A5A4724CE2254F077234A7282984038E5A062822549",
- "identity_type": "private",
- "iv": "CF9EBDF3F06EE6C72089D0F4290F202C",
- "key_seed": "F6EAA293204F1BA807120918B47F7F1C2DDF8085F7A1138452F72022B16A2D02",
- "metadata_key": "AA009F2D3D1F97B63CCA3AEF490576A1",
- "section_mic_hmac_key": "396722ADB64CCA9695A219385A71EECA3E9DD57A1CCFE93009795EA3D5EBE1C5",
- "section_salt": "1CE97084F1258375F2CBE48D88EDE4EC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A72824AEC67082FD52F521DA153BC437",
- "aes_key": "4A68482B406375EA353B8D3DCC41DA3B",
- "data_elements": [
- {
- "contents": "7F8DA439C60E",
- "de_type": 262
- },
- {
- "contents": "4DA31B9C1BE28FE4B906597598",
- "de_type": 131
- }
- ],
- "encoded_section": "5090134CE0387DF697DBFF2B6967B922DA1B96911000AFA838CF8AF1E94C6D3ADC3DEAF9193A90014B4B0C5F47F4F72BC0E54FD3A225353D9C2DB6C6C6582B24F2F4EC601F0AD29D305029F326E4E13E42",
- "identity_type": "private",
- "iv": "39DE563E758D36C340A8F1161F88A725",
- "key_seed": "DA07B9585C6328F8FDA0561EDC40F00B21EEA83C666B73A85F099FA6F4B77F4C",
- "metadata_key": "71675EB7D69EC84B1E4C058B6642D812",
- "section_mic_hmac_key": "64B80C39B9AE9DD8A7DA97E73E8CFB415AED92B75A815CF1C66AE29FBB9C3D78",
- "section_salt": "AFA838CF8AF1E94C6D3ADC3DEAF9193A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2D6A4B8DBA9D00228B9C0CFFB24B916F",
- "aes_key": "C0E2C9F0CD3574911480D28E4083263F",
- "data_elements": [
- {
- "contents": "6F512C943F83EAC9E6E961039D2B8EE806C0",
- "de_type": 296
- },
- {
- "contents": "3F16FD30D2B0ED2EBDE2EF4C85FAAB16BB428A1E0C2BDAD76E",
- "de_type": 243
- },
- {
- "contents": "528F528CAD4F647536823261A121CE0875A0E5E41735BC7ACB",
- "de_type": 950
- }
- ],
- "encoded_section": "84901365F658F25AACABB8AE42B7ECD7FDDD1C9110001C67EF90C57AE9B73871ACEEC9F02F349001EF235FC538D616127E38A22C5C64B5CC82F64248EE2CF44866B2A653BDA861AD1A61493F0DB877C8C4F2DE6F602B859659363701A8C57EB57B60D69C1A556FA11E068F407BD6C9355BB53CCD48FEC132F531519C6A6BE20F6B68B4BBFB",
- "identity_type": "private",
- "iv": "7C742AEB01EA936BE74C4B5F177C6761",
- "key_seed": "A6CC5A90AEE26189984C71CF6FE0DD2C0AEAB767E80B709FC27F16A69EA1504E",
- "metadata_key": "AEDFA8ECED1B2D6572BF4B181AC7FAAA",
- "section_mic_hmac_key": "4B1E36074BC7AD29290AF198E332090BF9910FC0D0487C5F46B0EFB009C5B916",
- "section_salt": "1C67EF90C57AE9B73871ACEEC9F02F34"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "361583139DED2B1E673CD68C16029294",
- "aes_key": "44C55EF72E97F5BFF1D8564CD731B946",
- "data_elements": [],
- "encoded_section": "3790138230C234237A46210D3A04195EE568B0911000292825357BE80336C2218747E9656A299001C92A44671591C7ABF14466844D19A0B6",
- "identity_type": "private",
- "iv": "35847BF297CA4F0F3EDEB1EF206DD353",
- "key_seed": "7FBA013FD2C6A89A6FC72F072A21DA549ED8BDFD1BE50818819EE20C7CB66572",
- "metadata_key": "0361C0EDBEE48B8DE9C163F5B8241E8B",
- "section_mic_hmac_key": "27E83E253B784927867786E495B1E54B1B2924DDC766239A45D9D501DE33DFF8",
- "section_salt": "292825357BE80336C2218747E9656A29"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "01AF8D1493DA0EA7129FEA26F691537A",
- "aes_key": "B3E74FD64DCFB8D61B4BBF6060921947",
- "data_elements": [],
- "encoded_section": "3790133A7FC10C9D1239CD46C3C6B4FC5B9ED49110002478216082A06CBE5C03A3385785D1719002A06C5AC8E3510C373EF27BF7B5B78B7B",
- "identity_type": "trusted",
- "iv": "5EDA40827CAB924516B3193A4447F831",
- "key_seed": "F427B6C08CD9D9EB69955C96D8B523840C8B9BA38572A5AA5BB2263EDA599A6C",
- "metadata_key": "E754D8C6D2D5428A722E130924D9781A",
- "section_mic_hmac_key": "90CCD137B4CB590B4D8D37A0EB14FE350FA1E771608DCCAB07469946BB771F76",
- "section_salt": "2478216082A06CBE5C03A3385785D171"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A95465E03BCFC8E5BFEF31C055C9A024",
- "aes_key": "0FB48B0B5519ECB357D58721E1A24445",
- "data_elements": [
- {
- "contents": "90B0D5AAF302AF084AECF24D32939E",
- "de_type": 404
- },
- {
- "contents": "AECA1B6B0D10D843E73AE0165A3E7D5B2C8B8310B7FD00B8810684",
- "de_type": 59
- }
- ],
- "encoded_section": "669013C6E721C70C2B3944B5FD253FC61566E491100053615ACCE2909F94FA4B998B569163359002040954BBC4C277CA47D211B5FBFDD97499FD51F6C8E8DF808C51649BEED660998226AFAA10BEC9769D1482673B7A0403F5AA343370C040F9F7B82DEA9D8C1B",
- "identity_type": "trusted",
- "iv": "B4A532C12A214BC4D727284823EAC0E0",
- "key_seed": "0F74A62FBF6CF9220166B846A0F76E669E42D1487EB5FD359B0CBC65FCBA7EF1",
- "metadata_key": "8EDD19022D2A88C0441386C74AAD046C",
- "section_mic_hmac_key": "2EA06B4B794A2F454E5B070979EDAD76D4983DFB48A098B472710D7917D3E5B6",
- "section_salt": "53615ACCE2909F94FA4B998B56916335"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FB45A0BAA38D0F35A1F64D9C72B923C8",
- "aes_key": "9ED5B7BB2B1C3413E6AAC6DFB3754FEA",
- "data_elements": [
- {
- "contents": "2CC3BC6746DD1AE5",
- "de_type": 152
- },
- {
- "contents": "DCEA4835787A94F495C7DE8F2AAE080A39FFC9",
- "de_type": 876
- },
- {
- "contents": "DC2F08CEEC54",
- "de_type": 70
- }
- ],
- "encoded_section": "609013D8F958F5ED45F8F3727CE84B31A06C0891100025A2312ACCB5535F0EF3A099EA10E7A29004D31578964C0136C455E1985055CCCBD7B56A8FD9315960FFBD889907F17865933AD86C73BE09C9E85B1CB8598B4B2E259AD4DF9AEC0871D2D6",
- "identity_type": "provisioned",
- "iv": "F332E711DEC606885B92138FD805E405",
- "key_seed": "44DF410E636A1EBF23DBC113B90F004B58E95049C1826B8F9EBFA59A6F02F39A",
- "metadata_key": "7FD6C62197D5111EAF0F95084607D88D",
- "section_mic_hmac_key": "47CF9B8136955D1DE13DFC33ED6896E7A0F27264C5D71FED5148AFA99B3A972C",
- "section_salt": "25A2312ACCB5535F0EF3A099EA10E7A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C74D81C8ABBAE1C6A90F9285801F2336",
- "aes_key": "7892DB13943D1F5167398B4A23835088",
- "data_elements": [
- {
- "contents": "0BEA3CC25F2B23B1A69CB239E9FB07BEF76623E4AF2F5A0C3679AF79",
- "de_type": 746
- },
- {
- "contents": "8AF23F8EF77D8403BE6D6C9244",
- "de_type": 465
- },
- {
- "contents": "82",
- "de_type": 545
- },
- {
- "contents": "9DB8C637C4781544D09EDEA5764F8FD47516ACDF62D8AD98F5586504",
- "de_type": 9
- },
- {
- "contents": "DFA09FD8BB33F71593",
- "de_type": 590
- }
- ],
- "encoded_section": "949013B2EE5F6DD997B4B4F8BBEECD33984B23911000757F746B62CB45D006E374E2B107DA549004285D582E49B413EE38A1FF386B7AC0BEEC63BD9ED74984319CD8FB0F39ED9104B6FFC3474EDB24465C3FB6D02CE61FCCFAD1EFE9BF6E06E2394CE62584FB7E76BE01E18C3C9CF2E4932F35F7C6DB988DFD97DCD08B983AE89AB6AB1B6ADA891354C1BD42E38BAE9EC4BE692CEC",
- "identity_type": "provisioned",
- "iv": "C1144E36B46120A9BB81FAF638354A7A",
- "key_seed": "A06644701F516480CF3EED2B66DE14FC48749E39C24CE4262F416EE47407C482",
- "metadata_key": "A8F0E7D1D083B1EB0E6BB743D2C6B5B5",
- "section_mic_hmac_key": "96BB03131488C6D55F42293579231EC82F49E057D9D1D91AD4022380BC2B32D7",
- "section_salt": "757F746B62CB45D006E374E2B107DA54"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8DC60BD4378BA88DAEF0708052F570FC",
- "aes_key": "AD070254CBD31CFF78F5413B43E1272B",
- "data_elements": [
- {
- "contents": "11FF19A9F2D6881B904B6A020B0658C3C724",
- "de_type": 127
- },
- {
- "contents": "0914FD60DB1B",
- "de_type": 98
- },
- {
- "contents": "6DB43F08EE556EF61E1F845D09178098CBE43908E0FE46F8",
- "de_type": 256
- }
- ],
- "encoded_section": "6E9013EEAB611CFFAD8C7D963355A833C9DA149110006F93D279192BDE0E527BD7E8B3168A12900445AE2642753C4D802B090C99C6EEC222388F26C0C119EB029487297606DD5772A0B043DAF23A826A3C113B6EF49C5D4F01202683137DD3FD800A4DA9E8DA510EA7F8C658101225",
- "identity_type": "provisioned",
- "iv": "C69FBF9DCC40FDEAABC5656F054A0B64",
- "key_seed": "221AE078D6806D3A41EDE4DF8CAA587F4ECFBE17210DCB7F168FD6C2DE4C3C2D",
- "metadata_key": "77E1A4867CBF4DE00E5C9FEF4DE9D68A",
- "section_mic_hmac_key": "D60017BB5E5C89DBFA59FCEF5BEF61E3DF6DAC38163D4964FBE4212652058574",
- "section_salt": "6F93D279192BDE0E527BD7E8B3168A12"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3E93896B318C8A8A2B86F8BEDC4978D0",
- "aes_key": "DAC516C10DF00826FD6F624BF8B98920",
- "data_elements": [
- {
- "contents": "83674116AC5D2915591B2C50E71E0C2402CF047D4E",
- "de_type": 602
- },
- {
- "contents": "E199053B60",
- "de_type": 165
- },
- {
- "contents": "9675FE47BD8D10B11EAD1E1377D3772D5951BDA26D8DBE8521CC",
- "de_type": 755
- }
- ],
- "encoded_section": "749013EF13622E04C646DA50382C936028A2DA911000A60DAE9062B7E80920115AA20A3DF6709004B9CD323F7489632E56DC010ED403CD83E2E22426733185AE3ED210CE702CE2959513B35B894216D0CBAD236E501B715E3801031478988BB7334EB6EDA2D80C4CD7B78E7A64916749728DD6305F",
- "identity_type": "provisioned",
- "iv": "D952D1CC42037B34686C0B0BD9E697F3",
- "key_seed": "B5663E9F549316F4156FE1E1F3A88CEDFD45EEF1413692310A745E7C711BC323",
- "metadata_key": "965D9973134E4C5AA5B527EE370875D4",
- "section_mic_hmac_key": "3AE74AAF3A515AE1EEAB3BDEBEB1233C300AE27BA3A5668BDF059BD400E07F7D",
- "section_salt": "A60DAE9062B7E80920115AA20A3DF670"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5A049145452ACBD46CEF34B3D44ACA7F",
- "aes_key": "DB91A343B3C4295B3B5A7578BAD0957E",
- "data_elements": [
- {
- "contents": "4044A5D3A69B",
- "de_type": 200
- },
- {
- "contents": "B5B5C084C05D28F6A5776A73",
- "de_type": 53
- },
- {
- "contents": "3F53E321EAAAD37321575F95",
- "de_type": 264
- },
- {
- "contents": "4969E7296C9756825F11908CF6C44C728579407005DA58",
- "de_type": 121
- },
- {
- "contents": "EA6EAE6782CADFA1BC03C22398EFCA35A25D1C455A61E86073C05F710C77",
- "de_type": 42
- }
- ],
- "encoded_section": "969013C9C75F20004942324E23C744440463CA911000E7C40EA2C2E65E5C5946447A6823338C9001E0B8C42F8B334E52A77E63C8BEFD9A717536AF9A21AE15918D84B0688C9B9A83C641B2DA40581639C617053E79AABD4FAF5DB9084512306D84091D2369C5507CED38EBD71CBCA5938CD168EC418BE57C2DA2C3C69224A3AD379C95083FCAB626627D96FD55A216B64C9718C082394E",
- "identity_type": "private",
- "iv": "B0E066C1CB9E81FEC072658AB024D029",
- "key_seed": "6AC9251B57E1AAADB0A82C14052229F0828511E8DFB62A7B01408C4C6CF942E1",
- "metadata_key": "81B7DFC2288EBA39967BCE164DAFD504",
- "section_mic_hmac_key": "305ED3775E3CBE503C3F9DE72AD075BD578D6D16A171536CF6FCA86032859FFF",
- "section_salt": "E7C40EA2C2E65E5C5946447A6823338C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E87CD39D43C0C4C98913104FFFB1B6BE",
- "aes_key": "EE96CEB9FC198FA238C718D8C664C2BF",
- "data_elements": [
- {
- "contents": "306E2C5F8259838DB0D07BBA4805E7480BEA4A6C165E31DE8BBA763D3078",
- "de_type": 845
- },
- {
- "contents": "D88025A8047D6AE0F6875BF82717FA782F",
- "de_type": 521
- },
- {
- "contents": "8565",
- "de_type": 661
- },
- {
- "contents": "4D1182D9D22A5B584276EB34F00AD16D6FA3",
- "de_type": 140
- }
- ],
- "encoded_section": "869013F1858C90C012EE372661972315171546911000CE2651E744A99AFAA849A54E1732826C90028BA480AC17C5D584F5BDEF8B4F2E078FF5A0681F77C391C2CB04324E4B5E9EC6EEC870D4F9501CABF785E02FF77D7875286E4505A9B76E28BA5CD940C9B255C609E4A4A4CEEFBB53433E707B56E9E28E202740B6A63C6891A35512A330BB65",
- "identity_type": "trusted",
- "iv": "E84094156E309C9E78E0F6B2983B3B79",
- "key_seed": "83020A9A0A506DE2A82978C1DAE9F961DED0868FABDB237B621F79CFE37E7C16",
- "metadata_key": "CF32E44F9BDB4C2AD80AEE60E78D3FA9",
- "section_mic_hmac_key": "21F6F2CDE9AD607DC36EA9F9C55A6FF654B00665379CF80DEE1C8E493DC5E35B",
- "section_salt": "CE2651E744A99AFAA849A54E1732826C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B57C92EB613E7A217DA71D86490784C7",
- "aes_key": "D9DB4C7400D56812F5D3F7DD244E513C",
- "data_elements": [],
- "encoded_section": "379013303598F236568149434CA461E3F9A4B091100081BBA4092F14CE810ECD0D7109A582B690041B06DC29BC82225D3F91DB0D996619DB",
- "identity_type": "provisioned",
- "iv": "D586725A11804C6FE31DEB705CC8D294",
- "key_seed": "149F80E11AFCACF6E13DF3D36C01C6D5DC688F8DB9F10537494FFF926052CE8C",
- "metadata_key": "D6319F5160167840627CA7013B292282",
- "section_mic_hmac_key": "51E43F329487E193A6FB0A179BB609F45AD5C4725653DC59EF075A75B52B36D1",
- "section_salt": "81BBA4092F14CE810ECD0D7109A582B6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D082000833AE11B48B49AA306FE002A2",
- "aes_key": "95D0A624DEA476B1BA80444787463999",
- "data_elements": [
- {
- "contents": "EF3C4BAF4B77424745",
- "de_type": 409
- }
- ],
- "encoded_section": "439013B0798E09DC56FD5C009B7BD24CF2D4F0911000BE2EF537A56A6022953F032D04ABC35390025EEFDD2CC06B518DDC1F1B383C59D1D9EAC33D6548B648CE39399621",
- "identity_type": "trusted",
- "iv": "0C8D19316018D63558BF62735E8AC988",
- "key_seed": "FAAE2DBB5B2652D6AD95B92F59105DD76AD1B41C51C8B4E358CA0B60A0450DCE",
- "metadata_key": "8D027CF95D5A790683C0B669D689CD89",
- "section_mic_hmac_key": "98F3525163633F6511A7BFF1598DD040181D2C3CFE3D1AC5D76FE2A23DD09552",
- "section_salt": "BE2EF537A56A6022953F032D04ABC353"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5D2264D51719AC98B1DC3E0117358071",
- "aes_key": "2F98AEE5A3841F10E02133F379B7C39A",
- "data_elements": [
- {
- "contents": "4FB4",
- "de_type": 701
- },
- {
- "contents": "48C3D5622F824DC1C7B0414387C8B4AC866B0EB9A7D888AEB6",
- "de_type": 995
- },
- {
- "contents": "41",
- "de_type": 139
- },
- {
- "contents": "EA9186B4375DD1BA3491ED53",
- "de_type": 934
- },
- {
- "contents": "9AF9C3B2BD374FBAA4F3D2F1DB2A186F8C3A",
- "de_type": 633
- }
- ],
- "encoded_section": "809013847031FDA820036FD425568B5611C5EC9110002CA0587BDDDBCB78153207C9158A10169002D74E311DD11F58BFCCC0A19F94F67B0AE4BE81741AC8DC4FAE0B17B772BE126CBBBCE66CFB50F091A70D06F3B34E16ACB9C64532990A6417B30A2CDDE1C001151EC32E7018828124E75A0B74CA5AEE9B4C840D19C255BF72AB",
- "identity_type": "trusted",
- "iv": "E288D7A1DA92318930084F3ED9ABB505",
- "key_seed": "C749179E61D827D1E2AD13B82A48420AB3E80D31F3749E950D292B64FFC08104",
- "metadata_key": "3458741999A1025974EF63298E559796",
- "section_mic_hmac_key": "A0AD19D8280DFB3DC84E5E68D7D21D5BCBFA9861B1F938660516045D6EB0C137",
- "section_salt": "2CA0587BDDDBCB78153207C9158A1016"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F68BFAB3213C9FEA8A29A96007FEF64B",
- "aes_key": "AC939B24BC933934398A7DC7E7C46CDF",
- "data_elements": [],
- "encoded_section": "3790139505676F85CA392334B19BBFD5FEC47591100074979416628A37D9CAFB2C4C6F969B569001DB08F385C30A762FA0C410A5184226CC",
- "identity_type": "private",
- "iv": "465C6117431966DBEDCD888B5221ED21",
- "key_seed": "41FFE0FAC77C1DCC8BECCFD8A7CFD4A7343D376B76CABE05961CD44B76BC4B71",
- "metadata_key": "4F3BC40A440822F086DEF13754AF74A0",
- "section_mic_hmac_key": "CB956645E987944BEB37C2416D24D7A10C0632E588677CCEF862E86B222C5704",
- "section_salt": "74979416628A37D9CAFB2C4C6F969B56"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "32AA8FD5DF4F49A764E9AA3BF5563C89",
- "aes_key": "2B4B17EFB895251408BA5B6BE94B4EF1",
- "data_elements": [
- {
- "contents": "11E38C244B9E12BE76C03E",
- "de_type": 935
- },
- {
- "contents": "C8D68DB392FBA453357837",
- "de_type": 335
- }
- ],
- "encoded_section": "539013851104503F1D2FA8E851450F39F7106F9110006634BDCFDE3CACB5C787430316E3B0F89001E28FEC491436FA0518D6DC6039167E200AF6348DBFD0FEDFB8FEE6D1783B34159A46C1CC91AB4AB161C3815C",
- "identity_type": "private",
- "iv": "1797CE15779604FE914F93871B2A0773",
- "key_seed": "FCD60D691DC27E7FDD0206B28BF9466003A96D1DABEB7F0C59BDDA3BC5064BFB",
- "metadata_key": "0F0F2E2D2C043688CADA7DB16B3890D1",
- "section_mic_hmac_key": "28862BC1B9E7774DC66B319EDB52978182AF3EA42F4C71C8E0EAF65952C1DFC9",
- "section_salt": "6634BDCFDE3CACB5C787430316E3B0F8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "31EE1C30D48B792D61C8792361D3E827",
- "aes_key": "1B618DD81493DEDC935CA68511197158",
- "data_elements": [],
- "encoded_section": "379013A8533FB16D70484318D287A8CA1324889110001DF600D41D8D806C43B138C0F76AF20590024756A94BDABC6824F118571511BBB69F",
- "identity_type": "trusted",
- "iv": "73CFA325E5CE5D6698F14615EE65D970",
- "key_seed": "41DED01B5C779ACF0BFF0641263BAC3406CF6D9F940124F033991297E0B77051",
- "metadata_key": "CCCC858E3FBAA8E5BEAF59B3A3D530A1",
- "section_mic_hmac_key": "C65B247379C1C47F50F977EE35EFD36AA14E52BC21567F3194977703D85B946C",
- "section_salt": "1DF600D41D8D806C43B138C0F76AF205"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A282D0AC1842D0A4DEC37AB35AAF4CA3",
- "aes_key": "EB7AC26A007B152D033F713CF425D8CE",
- "data_elements": [
- {
- "contents": "BB5234C9FFD150ADF4",
- "de_type": 109
- },
- {
- "contents": "185CDC775AE199F0D4DCBEBB8BDA97EFF10C482C52",
- "de_type": 390
- },
- {
- "contents": "B8D8C33864D21722A1F339216199",
- "de_type": 488
- },
- {
- "contents": "7942EA3BFACE24FF26C6262F",
- "de_type": 3
- }
- ],
- "encoded_section": "7990138E46F32DFCF3DDB81D6678EE5B9C63C5911000CD7C017292A595A9B91C2A2B0401869290028E1A072B7F5D1AE4EEBD4D3D86C6DE12AF19C45A34F2EE9C79FBBF8E559BE622359C2B632F0714D0303BC8F400263F191FDC55E7098617242A7DF0D5F06B3C3640967F57123DFCBF7263650532D6344C45C3",
- "identity_type": "trusted",
- "iv": "39B8DF03463FE9A4F1B74EFF99C79633",
- "key_seed": "C71AB1872D5CCA2A8AEDE667988CFBCE2EC9AE649062896938D414E9D0E94C4B",
- "metadata_key": "B8F3CE213E6E058AF15E956A1DC2036F",
- "section_mic_hmac_key": "7C4B63E31AD2FC40AE1D4F8FBF141E0ED08B79FCA7461892C1C8499B73746887",
- "section_salt": "CD7C017292A595A9B91C2A2B04018692"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B32A72E57DD180C1CD78E0D8FF198BA8",
- "aes_key": "0D3B48E8EC2B06C29C96BFC6C538B656",
- "data_elements": [
- {
- "contents": "5364835176EB07D1F5FC",
- "de_type": 584
- },
- {
- "contents": "C3492A918E552550E781328B57B40732977328B1325260",
- "de_type": 927
- },
- {
- "contents": "7E7B5AC1F3EAB30D71429C27667ED35C200476965C78F1CD5FB3B9",
- "de_type": 578
- }
- ],
- "encoded_section": "7C90136A1B890259C14A52A71914369DD5D7C99110001589F7FFF55BB13258B8CE9E93D31AAD900422D15C630478F6F2CB142D46ABE22A98C9C015432E7F6FEB0A922F53F45B513474F47C5068F32ED60CF9AE88147CC957851A4329A9F7116C346481BCE5AAD0786AFDD6D64E9131C36B262750FD4892F5774653BC94",
- "identity_type": "provisioned",
- "iv": "AC90BA5B1A5D39BD2241EC7DDEA4DC18",
- "key_seed": "06405596E394DE2A69B5B205F00E6119A4E9298EB253DD391B582C1899418AD6",
- "metadata_key": "68A1C5DA1051C2B604AA05DF6AB59EFF",
- "section_mic_hmac_key": "20FA4EFF48BD8E8FF5767A4C79CB2514AF91DA13218FCB63B280F6E41B2A5A26",
- "section_salt": "1589F7FFF55BB13258B8CE9E93D31AAD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A9B066473BAFB379F0937FB47F15A38B",
- "aes_key": "1F660B42014F118AD25C2CC166226920",
- "data_elements": [
- {
- "contents": "BF96B6727B448D012D6E42D0",
- "de_type": 521
- }
- ],
- "encoded_section": "469013E4A9322645BED3696A4B6924B4F0A52991100086EC145F4758FDC6D5940C864029656B90042D74437259737DDF7606D3750D4169A0F8A316FA278CAAE53B69BA3726EBA8",
- "identity_type": "provisioned",
- "iv": "413F7FCDB4FAB753817C2ED9AC9947A1",
- "key_seed": "7716AE85F2CD4F520438500DE48432F698519CA01622EE802DCE849E2C162DE0",
- "metadata_key": "0B16502A04A879A8EF6936331C7495B1",
- "section_mic_hmac_key": "33E577635DDF21CE36E3FC71944393BB3A65B2F1BB67E2015AD4903B47AC5A7B",
- "section_salt": "86EC145F4758FDC6D5940C864029656B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "97A3EA2B2D4B897973EB658FF34F4FFB",
- "aes_key": "67C524B281D8BCD2C51C74F057CB2D15",
- "data_elements": [
- {
- "contents": "0A2B142E42BF87F21293",
- "de_type": 11
- },
- {
- "contents": "733CBBDA78C13C5C598CE34EE9A25453EEA0",
- "de_type": 847
- },
- {
- "contents": "D53872CC070BBFED0E5262FBEAD45A6ACD9E1AE50D",
- "de_type": 171
- },
- {
- "contents": "A13ADB931426EAD3B2657C23CE0B4F7E4FCBE44C1E047F28548E05C8",
- "de_type": 672
- },
- {
- "contents": "69AF37BF3DC6FE2745",
- "de_type": 258
- }
- ],
- "encoded_section": "9B9013307A5B1D45053F33A0B2BAFDA032BD36911000F7D66FB12A2DCC5B9F5721066CF56BD39002E94F726AB64C08ABFF473FC3305DCC04B7258913115974B4B93FCBE7A65FD568021B184E299F44C4EA92B3FAE0ACC6D93051DF07F74402A0578D82079AB9D2E945C10D679D0EEA5E0A18D390EF17347E559C75216632ECAE4186375EC728ADAB7E1D02DA5D9E8DEB3C1796BCC23BDEFFFF075C8B",
- "identity_type": "trusted",
- "iv": "EE833340C3ECE7ED2E42BE6300591A2B",
- "key_seed": "5D1FEEA2E15BE812D6E7AED24744EAF066D2044226E1E5DBC215554C4BB21565",
- "metadata_key": "5C81700C6F3E2DB99FD9552A1BF8DB62",
- "section_mic_hmac_key": "C971E149AF0700BE9FB8A4042F0F02EFC26EBC99141EF025E270E9C6163291C1",
- "section_salt": "F7D66FB12A2DCC5B9F5721066CF56BD3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CCB6F827B0A39B6DA8437483DBBF4D21",
- "aes_key": "B86C31C7DF4004CEC6B64D8268246F4F",
- "data_elements": [
- {
- "contents": "1B0FAC5F09165840F1A1FE0A",
- "de_type": 108
- },
- {
- "contents": "F9FE53B7E86EFB5778E5DC56F8943696",
- "de_type": 140
- },
- {
- "contents": "",
- "de_type": 286
- },
- {
- "contents": "C37C58E8968BC63240",
- "de_type": 927
- }
- ],
- "encoded_section": "67901318528A80BAB7CEF27243F8F7A4543D879110008548036C89FF90B1763514205225BB619001FF05FB9C4AEEA7AF5787D23CB730BF83763C2D88740CEFB3E59A6EAC8AD289FF580611CE23391A41C7F3DAF763834D19D9FE31CCA279E335BE82B315BD028572",
- "identity_type": "private",
- "iv": "7D75415A0D1DB4D65196285773255E16",
- "key_seed": "CB2A52478DCE6738675A0501FB4A696A3B8B00318F9BB4C371B67787BDE29E89",
- "metadata_key": "76683C45B626D1230AFF1F9E0BC84030",
- "section_mic_hmac_key": "D8D2FD272E460779C37FE7AD1EE58C11D9AD119BB803C8475E10CF79AA7768AE",
- "section_salt": "8548036C89FF90B1763514205225BB61"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7664168CD02E2069535A4E243B03CD58",
- "aes_key": "0761688645B584019E0611E1C100DF33",
- "data_elements": [
- {
- "contents": "055E128D435B74BF4919E3FB6DFF9D061E767FC50A6297674C028B",
- "de_type": 817
- },
- {
- "contents": "7EABC7A23844D21D3F31940E823FD60578626B7433E1C78898228ECEFE",
- "de_type": 343
- },
- {
- "contents": "90817D2A59F7ADDF55B1F55B63E85EEE95BAA62408CEB897",
- "de_type": 245
- },
- {
- "contents": "4787FEC44DF779FAA45E2CF681ED86C1140EEBC15F2D5CA2DB4C",
- "de_type": 28
- },
- {
- "contents": "053A76",
- "de_type": 807
- }
- ],
- "encoded_section": "B290132E644D92825A53658AA88F3973AC5CB7911000293CE3D52ACE5D4C36736E0E05C8D3D69001CA7AAA50EB4888A43CDF55FE4B94013356209D4986FD7A74DB8A22B93C63CC29BF4CA30AA7D7976F33EF594EACCAA5A474C83D32F1FF7CAF7E9D0910961FA375084AA6C5A2F6E84D127C042BAFD09A63C6B0D4C4EC8CD84B8DE1711059E3C7888997D354606256ACB6FFC3A3E0F754C29D0E4D6553763C1E6DB476C138AD90AD24A46CAA585F509F2FDA59",
- "identity_type": "private",
- "iv": "A583849D6D43B5E8D8F1ABA5EDB4C673",
- "key_seed": "62F1D6EE9DBD290B2AF80AEDF635E14061025F9F279BA55CF7DBAA16DAB16B2A",
- "metadata_key": "728F086A73B981B52399C3EA8383A77A",
- "section_mic_hmac_key": "10B4AF87157247C3D06140005B0B1CB9FD71C023186C277554E16664928A2168",
- "section_salt": "293CE3D52ACE5D4C36736E0E05C8D3D6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5D2A3F63294D83FBE4110C3572F502E6",
- "aes_key": "DEC1B7CE58A15E488E53A99B0F6BFFC3",
- "data_elements": [
- {
- "contents": "F08F328184F706111296A6858F64B43E004B476D86",
- "de_type": 675
- },
- {
- "contents": "71AB692063473C3F09B6CC52884D2ABC5AA5FEE1435B132501",
- "de_type": 762
- }
- ],
- "encoded_section": "6B90133B241ED22261B210B755B93C3A46339091100024260E21CF1C1B804AF8610EFD1D40A09002BC1E6FE55D438C0A979D8E1724DE2BE88EF49E4DDD021A7BC6D62683FC44DF4B206A475FB56B25CBE20A145DB816E7978E6D0FDA3A29DB4343D410304FBB85C4911BB4E2",
- "identity_type": "trusted",
- "iv": "D109C7AA8A9C2F502F7FF2795CF0536B",
- "key_seed": "DE5BFF67545C1EA0965F927F752EA57236A0A8C07CF1E50C7B05FFE90CA3C080",
- "metadata_key": "801F239BCD59F71BFF3DC29C1873141B",
- "section_mic_hmac_key": "4DDC01519083DEE233FCD693B2DB1D50D74FF605ECA73C87D6656C2D9E555AC8",
- "section_salt": "24260E21CF1C1B804AF8610EFD1D40A0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "50AC8F669991D4D35BC8579D03EA514F",
- "aes_key": "014FC57AFD464A8788B996F85C208765",
- "data_elements": [],
- "encoded_section": "3790134B293E541BBF4E5F17F0D3980C9BC00F911000A8451CCF678102437062C19C5E4A11D990019E221A17FAE3A828DEBA689D8C1F3949",
- "identity_type": "private",
- "iv": "41BAA5F8DD05B8E6A504D599EB74012F",
- "key_seed": "DF5BBCE38A8C3E868522252DB57AF57F57DE993F9B34778A84C153BE8A2C36AD",
- "metadata_key": "577EF6FD43FBBE8F66D434794686DE81",
- "section_mic_hmac_key": "086C0B7B64863355C999983AAFBCF74E98F9EFD238F1A1502C7737E2883300CE",
- "section_salt": "A8451CCF678102437062C19C5E4A11D9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FFA2C3BE27EA9EFF4A305F6BF276932E",
- "aes_key": "A46E740733F543ABD962D2EB312D93C1",
- "data_elements": [],
- "encoded_section": "379013C51DBD3329CE6072C8A2A027F942CAA09110003F972D62A949212CEE442B4835C560EE9001E0725CD65D4CBD335842C42F4C4A0113",
- "identity_type": "private",
- "iv": "C93D934B0765A1D6353BCA51589B87B8",
- "key_seed": "3AC5766B4F5C28643B827A841A590AE959AB3558C3A148CFF3F7B833F00D2556",
- "metadata_key": "0F7080BB5FA2AA4912BDCC9AF3DE46B7",
- "section_mic_hmac_key": "9A78FCB3A75CD2B502005A4184563EB25D146A0CC58FF84C15054DBF869D6BC1",
- "section_salt": "3F972D62A949212CEE442B4835C560EE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2081A4F3811AEA051894C1C7C1B92618",
- "aes_key": "BB7480392B142CFD23F98A73EAE37E87",
- "data_elements": [
- {
- "contents": "710A0DA64D8668024AE7",
- "de_type": 532
- },
- {
- "contents": "E3471D8E60F5875C808ADA60850B01BC1F5EAD6FA43426707D",
- "de_type": 847
- },
- {
- "contents": "32321B333D25E24FEABBBC8E30A5EF11",
- "de_type": 314
- },
- {
- "contents": "8EE0E55F33EECFEEEA4485872C96CE",
- "de_type": 110
- },
- {
- "contents": "2BE0F48387594DB1",
- "de_type": 585
- }
- ],
- "encoded_section": "8F901397FE42D3756E948C098672DBDE9977E691100034F3CD62875F1A61868DD445BDEBA97F900442F07EF844969ABE5029FDEE70E060604FC171F2C6B17AB9E9A6F9B6BB0470A8F72123B30060E88060F3BBE92479CC0E107F330460156C3B6E5626FBFED138195704ED5A79745A2864ED052A5DD4C5AACC511CEE38BD48FDB904CE5904FF96D2F8B224C8C91F76EF",
- "identity_type": "provisioned",
- "iv": "731E0DB31EB1F2EBCE317A8AC207AD78",
- "key_seed": "C648836E062FE1B177659BCF66CE52DA92992A7F57A8C519EFE83B5498B83529",
- "metadata_key": "6528CBC1D9D05B685EA0B5109357CC73",
- "section_mic_hmac_key": "0E97851D27E9444ED828E6501A033E5F870F46D9D959BE6D0457EC79479A15B8",
- "section_salt": "34F3CD62875F1A61868DD445BDEBA97F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3B793A50ECB5E7F622EF1CB281DBFF10",
- "aes_key": "785E875C44A1BF02579790F4C07B08F4",
- "data_elements": [
- {
- "contents": "06B033003DBD6E5EBA861C20D7A37D61",
- "de_type": 919
- },
- {
- "contents": "2A729E0AF9286BBF90B0A3A6B7591BFDEB2180100541CE38E5",
- "de_type": 981
- },
- {
- "contents": "E05FE95894D29247E78451A5FE0635C431E0",
- "de_type": 555
- },
- {
- "contents": "DCEC979BD3722E22464D4FDBBE6C0C36B9",
- "de_type": 688
- },
- {
- "contents": "E55C2F",
- "de_type": 920
- }
- ],
- "encoded_section": "959013A64D93D01432AB2C93EE598ED825E09D91100096FD510E1761C11DEE130801210BE8B1900431467AF0C894A0E722ADE9F6CCB4A3717F37BC36E26D353D47AE9B2109D0FB52BF23597CA6A8542EEBA33FCD05B128629A04D68A50EBAE917CE307E285D79AC17CC088C8A05E4373896500AE0E3F6F602CAAFDD6FE64A4677E2090AACF1E2DE482EA152A11993C82B70415ADDE4E",
- "identity_type": "provisioned",
- "iv": "947D28352A1B86C1E2236B6E7531F60F",
- "key_seed": "6D6A7D942D7660F709710E81D2ADF1EB82B049264E83608CB61918C555C932B8",
- "metadata_key": "CEF10E891EBA5BD00B6152A2FB251BF4",
- "section_mic_hmac_key": "9817BF8D1B65414C53FB1C3D264F36D36B48E777DEB910CD87496157C57C60B2",
- "section_salt": "96FD510E1761C11DEE130801210BE8B1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F7978C49733680326C8CD0D6550F334C",
- "aes_key": "17FA0908863D1B4EBDF05DD2F30A2208",
- "data_elements": [
- {
- "contents": "246638469C9EFAB7FA881C39",
- "de_type": 219
- },
- {
- "contents": "9C1A259E1FDEA4E0B5",
- "de_type": 303
- },
- {
- "contents": "55B6AB32D64D0080BE176569732A38EAFB03450CC7D2E1C21AD3",
- "de_type": 892
- }
- ],
- "encoded_section": "6F9013C5B6C430D3A84D6611604E90B92AC9639110007CA3BE5D4F1E9798DC39FADA6E870C2C9001F8FC611C2B9508DF8AC88764822333DB1229A05449D35E67ABD092235B01D8037A3549EE3AA70482A187E8C872952FFA4A711288BFF30F493A2EE365E52C416E71D3980342F48B75",
- "identity_type": "private",
- "iv": "8BFCD2132085B890AD2C3E3A9948F316",
- "key_seed": "21AC3F8D521DC1FF26D984A4B9BEDCCB8C311FA31B3E5575A4E3AE671DE012A3",
- "metadata_key": "03F6987DA25955329DB9A2C50A879C02",
- "section_mic_hmac_key": "5D51E2CC831C4B7548CE48A6643AFC127764F31FB9E865969AE10050894FC50F",
- "section_salt": "7CA3BE5D4F1E9798DC39FADA6E870C2C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "88D9897749A087BA692088105D83C8DF",
- "aes_key": "F7DD8EF76EC305BF6B46B1F99D00721C",
- "data_elements": [
- {
- "contents": "ECB141D6A91EB9DFD5A7943311B7910F15AA07",
- "de_type": 369
- }
- ],
- "encoded_section": "4D901326351027E10EDFD7051D932A46A0BA25911000ADF3819989057AE9A61819927B7F8D1990047D54033ECFED457BB85532481D583A60A69316ABCEB31F91046C27D8FF7C844A9F662094F2A2",
- "identity_type": "provisioned",
- "iv": "4D9513DAC6E2B616C8E13E153897CEF1",
- "key_seed": "BF5C7631979835CF4B4FF4EBFF456C8CD403C68EA87960B0E6851ED4EEA51CF9",
- "metadata_key": "DE99D80A3652FE7BC2E467653CB29851",
- "section_mic_hmac_key": "A270F8B7F2C41B15DFA09CCA748427572E1089E90F42CA3B98AA1FAC5489E166",
- "section_salt": "ADF3819989057AE9A61819927B7F8D19"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FFAAF9CF08F2C0E4EABE4EDA5849880E",
- "aes_key": "5579888FDEB07F4AE593D558E3FDDAD7",
- "data_elements": [
- {
- "contents": "04B31B6181ACE137",
- "de_type": 362
- },
- {
- "contents": "EBE943E23DC7ECD4C7425BA338B5BD3CEDB01706",
- "de_type": 430
- }
- ],
- "encoded_section": "599013593827607D0CB872B3F9F9E7DD8A7E93911000C6121F8EFBA5B2885B32EC0AB3AC09C390013E91B3B7276D0F86C0C7FE864B96232017B450CDE11DB1322E7C8CCCE8F3F60BC173DCF5F6D4210A2F0FC39EDD71D0A4994B",
- "identity_type": "private",
- "iv": "067851344E70F915139C60128CFEF3B6",
- "key_seed": "685763208F4D5F465E32B59BBBB624720807102E810D13E1B7ABFB08540E93D9",
- "metadata_key": "0E8CFF3D0A9D7B2998DADD0D9FA14ADD",
- "section_mic_hmac_key": "D56C9E377820AA656DD234E62C72AB224953C36A65126252BB66773F175A9AE5",
- "section_salt": "C6121F8EFBA5B2885B32EC0AB3AC09C3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "445F8262587A527A2A50920D59873975",
- "aes_key": "A0F36838DF419D50BC5C556466E1FC97",
- "data_elements": [
- {
- "contents": "16550C16A40A2C8A362A94BE50C6",
- "de_type": 135
- },
- {
- "contents": "",
- "de_type": 800
- }
- ],
- "encoded_section": "4B90131D351EFBD9BAE953304D7A8FE0697DAC91100073AFBD6543076B300486F3EAB58E055B900104F18882A1DED7DED581EA73100AA9EC2F3F9173A401D05AF6BE5B4E1CCC8DF696E42C66",
- "identity_type": "private",
- "iv": "39A88826E22EB99F2CBEDB51171E3EEE",
- "key_seed": "F226B3049DD530E4F60C4887D0A2FBFA987A8E1FEB72EA2303EC30A7147DD8E8",
- "metadata_key": "AE2B15A2A9B54697E7CC405BDA81790B",
- "section_mic_hmac_key": "6D21434215A1F6DF62E827E0268FECA28C37693611557B1C9342EC8E0C1D81EE",
- "section_salt": "73AFBD6543076B300486F3EAB58E055B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0557BC1D38283635FBAE13D02728AB5B",
- "aes_key": "A9BC8BA7EAF519C7B85E5A01188EF50D",
- "data_elements": [
- {
- "contents": "",
- "de_type": 63
- },
- {
- "contents": "A3E5",
- "de_type": 422
- },
- {
- "contents": "D54CC7D06905667D7360AD193F3130425832776FCEBA2679E267B7970218",
- "de_type": 285
- },
- {
- "contents": "441597784AE289C3622CB239D2C4E8342231F4",
- "de_type": 247
- },
- {
- "contents": "C0336CD68C4AE63EAC656E3202C84B545813337C2A",
- "de_type": 939
- }
- ],
- "encoded_section": "8D9013C536B4E39D9201EF3025185148B9453C9110002E9AA3A07F8D9A60B7E03ECF29BB23CD9001509E02E030DC3E8FB95C6BB25A5490B29B435418731DDC6F2FE41F742397A96D8A326826BA73E9839E1BFE0B9DFCF78A063AC0B5135173F31E0DB480B06A4617BF068C88B9CC04BD37BA5CAE862D0601BD1864DBADE74F3506CE064DBBFDA34DEB49C330D7A9",
- "identity_type": "private",
- "iv": "D8028895E10766DF8BA06D75C6A112A8",
- "key_seed": "5493AE88E27447BF331AF54D9F82018ECCD1AADA9013D8FAB3E26434BB65B965",
- "metadata_key": "14D05DBAB3A9EEE82E952390E0AEDDF1",
- "section_mic_hmac_key": "10002B26833E9FB12D751AA88A90E30B7F8418BE8BDF2EDEDE47A8906C25C49C",
- "section_salt": "2E9AA3A07F8D9A60B7E03ECF29BB23CD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "30C56C83215C76E99FEB30822EBC10A7",
- "aes_key": "5BD799E5168D831A50AE88908D7C819A",
- "data_elements": [
- {
- "contents": "A52634A06EC8E3",
- "de_type": 239
- }
- ],
- "encoded_section": "4190138560C2A340ADC9FB31AD47095F34482091100068B0F681E3A5DF3C78A44BA62217395E900165E94E9C7C34CED0FEE48824E2BD691A4C924F8FBA59DC0D5697",
- "identity_type": "private",
- "iv": "2180C4533853767495A5C245C4E6B7DA",
- "key_seed": "EA428BE58334D369CB5803FF519C408C44B9C2046DA706B0FC64B3AC7855CF4C",
- "metadata_key": "794F11DDC402D478236E4FE863A7C014",
- "section_mic_hmac_key": "BA65D2678CC2A9F28B1FC79BD735A0AD94C978A183D80BABF4F7AEEADAC57CFD",
- "section_salt": "68B0F681E3A5DF3C78A44BA62217395E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "45450AD30A7FF2646B7FC9A7498B48C9",
- "aes_key": "C597783A6BEA9B14F749AEFD0554A10E",
- "data_elements": [
- {
- "contents": "A1BCA904A65BB84506FD4FA7B8F82D4E3E27F1FE06FF98C5F5E9DB841D42",
- "de_type": 255
- },
- {
- "contents": "9E22935748180AE8A2CB2552330AE84E0753C065271E",
- "de_type": 398
- }
- ],
- "encoded_section": "71901354622DA8EA9F9CC2350BC32E57DE761B911000A833A0E92CA1E0347245C35E678EE14E9004CBDC2F1ECDC2364CEC12BB5C36EBEE053F2D6E806D60BF129AC37E800F49559211A0A8DA47C4F85BD5F5B500201022790C232525FD06CB7161A123892D9D15EA32303BE5439AD3EE6E18",
- "identity_type": "provisioned",
- "iv": "80E557930065CB90C62020A24F0A88B2",
- "key_seed": "BB4AA3FBE34B70ACBBA908FA5F1BA74D9B2C8F521157C183AB94184F85BE6610",
- "metadata_key": "CAF8352A2D518815C4687370ECA9B717",
- "section_mic_hmac_key": "4A8327360B9E78473FE9E8CC2F68F19A6C2E7F3CDE21ABC007296E6F37103402",
- "section_salt": "A833A0E92CA1E0347245C35E678EE14E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2149BA09FAAB9ABCEEFC3F1ABCF9835C",
- "aes_key": "320ED87DE4141376542574C62FB7F871",
- "data_elements": [
- {
- "contents": "58D1F10B05288C8BEE4CA01E515CAE",
- "de_type": 472
- },
- {
- "contents": "341278EAF7023A",
- "de_type": 418
- },
- {
- "contents": "7F6DE46EAB91ED",
- "de_type": 443
- },
- {
- "contents": "ED3F2FB7",
- "de_type": 861
- },
- {
- "contents": "89BD3EB3",
- "de_type": 886
- }
- ],
- "encoded_section": "6B9013899F627C6E1410138BFFCE742BE143E69110003A40A350CE9225C732AC27C9BCD65F1F90020A96A446120DA7C8C20715B87789DA1EE5EB068690DDB044F346E8E5ED1BB493BF7AEA8873E8A3A02ADE54C073CFE9B2E4432079C89D84C6B302BFD02177EC6ADCEAB360",
- "identity_type": "trusted",
- "iv": "5F97B82B7494DB44B27135C54CAEC7D4",
- "key_seed": "B6E611FD268D0E0B4C5F677B942115CF92D2E4C43B5A69E867A36EA2C68C1193",
- "metadata_key": "F0917DDB2BE2193FC96B46B81675209D",
- "section_mic_hmac_key": "B11E903ABDB58F30052E0A5046B2E2D5A987589D3365224F4EC6AC25BB5755DD",
- "section_salt": "3A40A350CE9225C732AC27C9BCD65F1F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "24036FD2BE3DCF97D9DF963B68D92DCC",
- "aes_key": "602B4616715273B107370D173ED8666B",
- "data_elements": [
- {
- "contents": "2734F55CC2D6B46C5C3B37",
- "de_type": 963
- },
- {
- "contents": "3ECD6542A74D7BE449DA6B40CFAD8D3809",
- "de_type": 517
- },
- {
- "contents": "49A3375EABF0AF0B26674D2879BB79F81C",
- "de_type": 884
- }
- ],
- "encoded_section": "6D9013D63C809F3652DD6AEF44F7FB35794E82911000D146378477019DF7ACFE29254CA21A7490042BF103C5A38BFF08D3CCF725A0811B6427D6C9D8A87A967DCA5C484C6A45DA78801408E91C5E2E377FCA9E5686E3BA2C901532814770E0EED571C0D03BE53841A5A14EF7D7F8",
- "identity_type": "provisioned",
- "iv": "080A6136094FC17B1A16AD0BB82693C5",
- "key_seed": "520DAB213766293AA52073574939FBDF3FF7FD6E440FE41FDA38840112D7D531",
- "metadata_key": "22E70A8A5CE17D98948AA5ACE440250F",
- "section_mic_hmac_key": "00DFB12A3DBD705121093901BC2D50BCFDD3173593307F9D4C37C9A0849F5446",
- "section_salt": "D146378477019DF7ACFE29254CA21A74"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "63C51801F768165BFC326E7C82FC1227",
- "aes_key": "57B39C2DFF8CAE78838966761E9AD467",
- "data_elements": [
- {
- "contents": "049E77BF20D8B744640EF2F3C776CDDBA3BAFA2A88",
- "de_type": 555
- },
- {
- "contents": "15BCAE3F4B78785C16E4590DA228CC3B",
- "de_type": 896
- },
- {
- "contents": "78C11D80D8BBF31D3482C1F4162BA2FB5FD29B",
- "de_type": 132
- }
- ],
- "encoded_section": "789013E816D1BEAA6F0661CF5A37AFF036BCA9911000B834A100C92A6653F03120CEC5F5592E90025CDCC0847E46F2131D454A6C3774B5EEB4EC5D6AE886A374CFBA015D8FD3336291586D08C141E3637002176BD3F4DA468C61752284262045D3F00A0F9140FC79FC7B3B380A311BEAA0C46C2BBC9790CB8A",
- "identity_type": "trusted",
- "iv": "6EB51E1B378E7EC195ED6131D5B917A1",
- "key_seed": "D0FC05ABA9677770D9560F5CC298BB1CDCECE2776762070E9DB7729C4E6B1998",
- "metadata_key": "C3DC3239104F41A29A6CA839846892BD",
- "section_mic_hmac_key": "042BE96EE344DE41F99A6F9A99D74DE39B7FDB8FBDEA76CA4819BBBE76D1020F",
- "section_salt": "B834A100C92A6653F03120CEC5F5592E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5D2A54C35196DB6687A495E4C266042D",
- "aes_key": "B94AF3DE4F31E07283C694BE118A2D39",
- "data_elements": [
- {
- "contents": "7F221D4C1A",
- "de_type": 175
- },
- {
- "contents": "DA7BF9A3C1F1A0F7D394FA",
- "de_type": 51
- },
- {
- "contents": "A3F5054FAD0E0B0F32",
- "de_type": 693
- },
- {
- "contents": "A0F34BBEA40E64",
- "de_type": 514
- },
- {
- "contents": "A02552",
- "de_type": 259
- }
- ],
- "encoded_section": "68901328AFDD847D58B8E42C91D72766806C5A911000CEA2BF3A4917856CB02C3E535657238A9002BCA81209838C61B7DC924CB7F75B0954E37749E736DBBE2C06A20809D8DD342D1938A290C35AF882C1B7B937E58703E984E4CF794E70265512407A8E10FA031CAE",
- "identity_type": "trusted",
- "iv": "8828C505B304C04F4872D41049F59825",
- "key_seed": "EE9FC69BD400B68041022770DC312DE8C66C492E23BE76579D714E142489B440",
- "metadata_key": "66FEDAAD7F184A6C27481BD86869213D",
- "section_mic_hmac_key": "FC34E258074AE77E103008524518165B04278B97935C89ED9DC45F9F1EC090C9",
- "section_salt": "CEA2BF3A4917856CB02C3E535657238A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4DE3C97760C9B8DE4C61503AB880C1AC",
- "aes_key": "F92EDC38BB8DEF8AFE9BCA414079A5C1",
- "data_elements": [
- {
- "contents": "3D713A3004C3540EAC1EC4AA1DCAFE0989B228",
- "de_type": 322
- },
- {
- "contents": "1699702E3F9F64F6A2503415D312429EA274E049BC0B6B7F15756CD8B33A",
- "de_type": 25
- },
- {
- "contents": "37",
- "de_type": 200
- },
- {
- "contents": "04F9",
- "de_type": 375
- },
- {
- "contents": "D363E2343CAB2298956475C4F658C4609E77514ACBC58A40D75A0EA6",
- "de_type": 62
- }
- ],
- "encoded_section": "949013A75CD13AE9FCA132E0B0BCE584544EBC9110002EB54EBE8F6BDDE1109D60F57C29DFB39001AB7FA220B3D56C65AF369EB529702C9C7D039249F3D56387AE4714EEA61FFC310A96DFE05402F7CE7E354D716A3453B583B9CF812A98E85F4EBB3C2CAF09E3EDD2916A57F6AC6E68EF5180301378077EE13E410C594525D5C0A37AD77495EC42117164B749E16FD6762651110A",
- "identity_type": "private",
- "iv": "C266A550D575D8E8A76B32E4EB60566D",
- "key_seed": "DE0CA86B9DE2F53BC684E1E0546BAE9C1168EA4041E70FEA570B63D153B6E0DF",
- "metadata_key": "772C23286C809572A8A7A4CFF6562106",
- "section_mic_hmac_key": "DE9DD28EAD5F258311F9143A61CF1729938E1973DFC71EFA64BC3496B1DC2FA8",
- "section_salt": "2EB54EBE8F6BDDE1109D60F57C29DFB3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "08591DE70D9203A4BD5BBFF0EB0923E7",
- "aes_key": "84B87FAF5569BE3145FDF5BC95B8228F",
- "data_elements": [
- {
- "contents": "4B2619",
- "de_type": 910
- },
- {
- "contents": "737EA4568AD23835B9",
- "de_type": 193
- },
- {
- "contents": "7F16EDF05CE5CEF44F4669",
- "de_type": 908
- },
- {
- "contents": "997C7BAD1FA37D3725D2E58BDC87BD892D0A",
- "de_type": 789
- },
- {
- "contents": "38368E23CA2E20C2D25E0C36E8953D",
- "de_type": 683
- }
- ],
- "encoded_section": "7E901392A0322C56CCB3EDBDA02426B5F20C169110007FC169892BDFE3C58AE3A9145B1945AD9002B0904135D3B0B28995FD2D3BB2AC63CCFA0EA80B4C2FE257692A1C3D46C2ED102D06679A64D95BBA7C65E41EAD48417AA853ADAF290012327085B183EFA9016EA3AF6365776548E4EE9509651AE6BAE0A1AB23DDAD8140",
- "identity_type": "trusted",
- "iv": "1EFC0B89733153C45C3F0B9952E7CA2C",
- "key_seed": "E069DF1441FF9660D686BA2ED4B324F9EE827A41666AD3D72CECCACA3EDC1195",
- "metadata_key": "837D4BDE2339F7E0760F507FD65EF0F5",
- "section_mic_hmac_key": "332B87B53F48DE7951414290B387018BF70E2DD12A550AE288DEB8F082D5E3AD",
- "section_salt": "7FC169892BDFE3C58AE3A9145B1945AD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D3CD0C0B45D18C67D9FF4ABD9C00F638",
- "aes_key": "EA252AE1D2F51097B0B3C59CD5394CCB",
- "data_elements": [
- {
- "contents": "9DA05D735D904142FC9820E859D3D2DAA3FD9BF99077EE289848BD",
- "de_type": 729
- },
- {
- "contents": "AAA29A80423195",
- "de_type": 501
- },
- {
- "contents": "",
- "de_type": 729
- }
- ],
- "encoded_section": "6290139551860389CAB63CF19976C38F9F83829110004EAA5E6CB7B52006113B8227B50B6FAA9004F55AF889B0D3A843343569BBB9FBCCFF954C7B2085DDC35493039663D1859721DEC51AFCED18340265399F3D29A634266BD6F7B72B13904BEFFBFA",
- "identity_type": "provisioned",
- "iv": "33261AE9D64163AEEA6CA4780557B537",
- "key_seed": "D276F97EC832428E7341153402EC817EDA087F3722092DFDCD33E3DAC87FCF9C",
- "metadata_key": "B784A92864FE81EE00484C3407B19E18",
- "section_mic_hmac_key": "BFF73B8A8684137A38AA0CE919F921F5E46BEB78CAABF9001A9829A91BB2DDDB",
- "section_salt": "4EAA5E6CB7B52006113B8227B50B6FAA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8F53DA57958205F65AF175946F0E7C9D",
- "aes_key": "1AB05E4A3B94AED84AF5AC5AA0C34532",
- "data_elements": [
- {
- "contents": "70730B2189EDD115FF4146EB6736958B2131B4E758871206A7BD",
- "de_type": 857
- },
- {
- "contents": "0C",
- "de_type": 50
- },
- {
- "contents": "85363F2F6E5B68549DC14698",
- "de_type": 781
- },
- {
- "contents": "24B2893FBC",
- "de_type": 493
- }
- ],
- "encoded_section": "6E901344842419D528E3354B2B62AEB7DCA816911000F7F26313B7593F64E2609508E29C568F9002ADA0099489D0829C5C03B5E34C36A22F4DBD656538D7A34FF22307009C917241BC3C03E863B498F7E744B781E4C97EE731D6C27BBCBB9B0BCD5049BE32A34F127AF7F262555E01",
- "identity_type": "trusted",
- "iv": "94EEED11E11DD155988B855D19007FAE",
- "key_seed": "88182E258A729A4E43B5374B97A2C3B62F694B30FE8716172BC346A27E074B29",
- "metadata_key": "5FAF4F9CDDA36DE98B4BE1111E7BBA39",
- "section_mic_hmac_key": "EE0A1B46369F96415076C2C5C59FA7FBBE38620043D78E935340767C3094600B",
- "section_salt": "F7F26313B7593F64E2609508E29C568F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FD84FB907560ECF5CB2A9771A4BA8CD1",
- "aes_key": "E3FD2A72A74A7EFFC6F4585CDC240D3F",
- "data_elements": [
- {
- "contents": "5BFF",
- "de_type": 353
- },
- {
- "contents": "56E6B22A147A51A7ADE3A51B1A4ABF",
- "de_type": 703
- },
- {
- "contents": "FA366A",
- "de_type": 922
- }
- ],
- "encoded_section": "549013A550EB4A596D0709CC4831941ECD4B97911000BC96DC7FE5F9AB0C79FCB5C3427416309004EE787CB1DA498BB4C72EDB79F03197668CA9719227CA6D084FF44145EDE83ACE127060F8AF7A47BFA9AF03D7F5",
- "identity_type": "provisioned",
- "iv": "0A95F9333CCB2B0BFC001BAE3C585430",
- "key_seed": "32F7B9337E17ABEA1D32339620554D78574F2311A7DF33FDC2040ECCEA22F16A",
- "metadata_key": "0D7BC86218E42A4DE2ADCE4BFCE1CBEA",
- "section_mic_hmac_key": "391BCA81E1EB5B64A6A5B48226FBC88361F80157D68FDEF21D159D765E89B1D9",
- "section_salt": "BC96DC7FE5F9AB0C79FCB5C342741630"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A020F8E4858919DA9912CD877E5D7E1",
- "aes_key": "AB7BC14F98F82FC2F63DA94527EE1E25",
- "data_elements": [
- {
- "contents": "F206FA29E92D1E2CE7F8F97335171D49D7634167F9D24DA45945D7C5D1",
- "de_type": 558
- },
- {
- "contents": "BA45C18251ABB34EBB8A427E55B997260F451D",
- "de_type": 686
- },
- {
- "contents": "01F97FCD198286623C44DBB47FCC467BEF",
- "de_type": 596
- }
- ],
- "encoded_section": "819013BB56AD1C58BC3238CF683D9C6A2539C4911000C5480A0E75D4E0A677CA57FB7141919D900153375B41C2A3EB1A8AE9D4F3123AF5908A597DD8279AB6D68BBBA1BC107EC58B6D083F21201D44FB5EB0C254DA392099B8F47BFB9875B67C498B3CFCF4069F9A2CAE853F967F1953305E8943E9B97ED439F16FC82AAB2AEE3CFE",
- "identity_type": "private",
- "iv": "496F077A2B7916761DD8AC728D556F06",
- "key_seed": "F8E22E64BC77461311AB36F96475EAA5398D0080F0FBAE13F1C4492DF46179F1",
- "metadata_key": "4E7A8A31769B49F87CFE1FD8BCFB052A",
- "section_mic_hmac_key": "E5F81D3C2D13A10FF5CD9B863C512FA9E0D1AFCF813474F7666251BD055FBB05",
- "section_salt": "C5480A0E75D4E0A677CA57FB7141919D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2B2937852F695F8D56C725B0A6DED2B3",
- "aes_key": "C7A0EC3BA5987EA8BCBECC13ADCB9CAD",
- "data_elements": [
- {
- "contents": "3686E921B3",
- "de_type": 624
- },
- {
- "contents": "13A0B207EA7A",
- "de_type": 693
- },
- {
- "contents": "5ECF29F01D38",
- "de_type": 348
- },
- {
- "contents": "E22EA254A7EFB27938D2E75677F7CE8741463254DE17C1EF",
- "de_type": 413
- }
- ],
- "encoded_section": "6C9013B4F7525345C4D799DCC73BBD7D34A2A891100039E36002FD6A898C7113D8E29BBC18C9900288F3BFFF20D692ED112C8A264C6479AEE31F98BD1410ADB1E8B15E797F18DB33ACEA80FB761CCED0BE25F19B74AC2B7E7874E832E57995638165C3FB0222984E880845556C",
- "identity_type": "trusted",
- "iv": "6E6427719A16CE39BB3AD9ADED72A83A",
- "key_seed": "948B5BB10F06A5C607E6FDD6631F173B7D938E80FFF8F4EFDFA1DF315933648B",
- "metadata_key": "7419265431EE04AC211B9BE2072065E9",
- "section_mic_hmac_key": "CEB322C685911AF93A57E15C80E40B410600BCBCDB1091D49F1DD58F55DEEE96",
- "section_salt": "39E36002FD6A898C7113D8E29BBC18C9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "47F54618F90BA0470CAA122D068090DA",
- "aes_key": "7D286DE8F9BA981B7AC6EEF116A30B8B",
- "data_elements": [
- {
- "contents": "8E6ADCC3529CB914BA44071D1039476F503534E24E9FAD",
- "de_type": 866
- },
- {
- "contents": "FF59C0311B6365D7B2",
- "de_type": 482
- },
- {
- "contents": "86E592766FBA32BAA8CB5926C68B9CF1757B30ECFC8B01",
- "de_type": 865
- },
- {
- "contents": "BDEC4494677D60C91BEDBC5613AA622C607D623763F1169835649EAE177D",
- "de_type": 912
- }
- ],
- "encoded_section": "9890133504BB533122BC321979FD233507F92D911000D087206EE8701FADF74E29E64DC42B299001FEE75CADBFA905B7121329EEC77ED201DC81644197BF8BCEE765353ACA4C2D3E6E90F6331506C5A5180DC54AE4FB34B294F70F448EDB3EC9366DEADE0A63EFCCF7B495AF25DFD1E375F109ECF0D66BDC5C1706DA8DDACDDA0D76E109A3998263959F650F34D07BA4908FCCEAA47C3BD1BD",
- "identity_type": "private",
- "iv": "06092E39EEFF3F94DDF84FB4E82096F0",
- "key_seed": "1CEB5B27728B3C394FA53039B1A2BB3963FDB1ABB971C694FF9B583DB4D6F4C5",
- "metadata_key": "4BFF4D6A274981EEE3A41CFC71104933",
- "section_mic_hmac_key": "71D0D24E9DF1CC8CA5705A5B97564B392020BC1E31103B902AC6109A20736FEC",
- "section_salt": "D087206EE8701FADF74E29E64DC42B29"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A5CB335E0E651AEC76610103314BE5E8",
- "aes_key": "2073B2C6E4A891FA1F4A94E6E0ED2D7B",
- "data_elements": [
- {
- "contents": "39992BB369E5",
- "de_type": 403
- },
- {
- "contents": "91A4A04160751875",
- "de_type": 341
- }
- ],
- "encoded_section": "4B9013D868F86C9DABB0C962C104961D2199819110005F70263B58C94A534BA0732A362CFE759004F0376CB6B7C35E6A97774046EB8E11BE29D06EEC71C5300B63E76D1F743ACE32AB77D7C2",
- "identity_type": "provisioned",
- "iv": "8E45ADAD9A235A3A0131D1DD9B5F9279",
- "key_seed": "CF2BF8EA55BEC2D2A5C15C46C09B9291934EBEAC7792D75702B1C1F56DD52AE0",
- "metadata_key": "E227B26B4D3E35C8778FA1D40D326AF9",
- "section_mic_hmac_key": "8FAC7D8677AF486D3DFCD671F2830A5CD938A6CA7E2DB273FB9AD603617425CB",
- "section_salt": "5F70263B58C94A534BA0732A362CFE75"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F1C24DC0B003B6D25BD4C3F1BCB66285",
- "aes_key": "DB76A3E8C87A935422EDDF2E573D2EAA",
- "data_elements": [
- {
- "contents": "87",
- "de_type": 196
- },
- {
- "contents": "24",
- "de_type": 342
- },
- {
- "contents": "C72C39FF57E7FD4DA1C96A5F6C71DBB7912D5E59351BA03CEC4C31",
- "de_type": 295
- },
- {
- "contents": "8418AD4C9FED5B9908",
- "de_type": 993
- }
- ],
- "encoded_section": "699013C828BE6B34B2F3061396313E501C35C5911000FD1A8AA4AEE8DF00D003270485B8F7E79001E4A3421E4634FFB67FED3BD908779E411870A14E90F14AD32D3C9F8E34F0DF2F1E956F4586EBA22CCACCA8CDBF530867C4BA55BDE2D461D3BD331F384361963326F8",
- "identity_type": "private",
- "iv": "C3A642B990DD53C2652267D0D74140F9",
- "key_seed": "103EEB5230E3A94CDE86DE361742D42DA89715178B2EEB054192580C46FFEA86",
- "metadata_key": "AACE9616D0BE1375E9501E23B9AD5A27",
- "section_mic_hmac_key": "EDA3F8BD268CA694571B96BA31002C4C1F0780914645F09C3F41CD2D89E1ED87",
- "section_salt": "FD1A8AA4AEE8DF00D003270485B8F7E7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D1C4D57D1022E2E34A436AB3BA2925E",
- "aes_key": "95B5084E465C6C37973DEF1CA3DB47AD",
- "data_elements": [
- {
- "contents": "C1A19CFE869417D14BA0812EDB723157572FFE02431EB51B",
- "de_type": 536
- },
- {
- "contents": "",
- "de_type": 606
- }
- ],
- "encoded_section": "559013E83D70079ADAB5FC3E1F844299D6B9319110008ED6921AF82E82864706EDE25EB3796E90042DF36874DAEAF11DBF9CF1F0CE2510156BC023B8D936F09D7BF3005B068697F171958A92CFAC237954E57BAE73C1",
- "identity_type": "provisioned",
- "iv": "D77A9FE328C32C11C38DC06F43475909",
- "key_seed": "5BFA074B8A029B3617D2CA1EB0C5CCCC9AE733C23AFAD5EE72D0AFEA1B43E96E",
- "metadata_key": "0D076B70D9757FA46D1DF675985EBCC2",
- "section_mic_hmac_key": "13ADE797F4AC758CDAF7B19222516722967586D6742B514E8AC64DA36EB958C5",
- "section_salt": "8ED6921AF82E82864706EDE25EB3796E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "65E6464F45B5C34BC2B3ACAB85653A62",
- "aes_key": "4202E0AD401A9919BE9499177FBFE027",
- "data_elements": [
- {
- "contents": "87DE98B78C4998378DBD3D8513F1F4252089430D3ACA43E8A9C52F",
- "de_type": 613
- },
- {
- "contents": "30DF522A56BC545C1B8371AC0DA6583C415464F29CE827339312A5144F0F",
- "de_type": 275
- },
- {
- "contents": "080BA02D47A3D4AF7BA94C1FCBCB70A71397E14206B6",
- "de_type": 264
- },
- {
- "contents": "AA6BF69B8ECD8613C95DA243320D4A2581",
- "de_type": 349
- },
- {
- "contents": "9007448B4D1A1C6824EF74406318C43421622D8177933E1B469088FB6B0C",
- "de_type": 763
- }
- ],
- "encoded_section": "C490133190D16D406DE4CDB486C62178AA7FBE911000C0CF7E29552F1C72FE58F39607FED92B900121CD625287C4ABCC300868F871B3F9FC36B8E82A243F4B7C1DBC00236FE4F0F2FB2B215B8016040357A368672BF3670175DE4E57ACE0E68FC1932303528CBEDDA764DA369F6164070F860C86AC90D6C4EE900AA58F37AAC2CA3C92BBACF0556A28BB264CAACB5DD6515F19CC3F31808CC7341D23593B63166186809F4492CD86A1AB181FFC1F48D7AE759BEF015427EFF04FDC794559B7DB7D33939531",
- "identity_type": "private",
- "iv": "33A37770A90581B66BF440E910ABED3A",
- "key_seed": "FDA2E31760FC708DA464AB0C68FE2466846222FF391F483BBDF194DE7ED3507B",
- "metadata_key": "55850C28AB36C0478C59455F908449DC",
- "section_mic_hmac_key": "A5F0E47EC740727D97426B01CB0A1D498373E14B2A42964940274954B9CAE4D6",
- "section_salt": "C0CF7E29552F1C72FE58F39607FED92B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9FAA7146038C8FBF5223B3F4EF402B4B",
- "aes_key": "FDADB3FC15C2748A41A7BD272244731F",
- "data_elements": [
- {
- "contents": "C888F3DA553255168D1C6C687CC86D8A",
- "de_type": 401
- }
- ],
- "encoded_section": "4A90138C466CF8E025CD72F5C052580230B0A2911000D14BDC42045F83B2B03EBFEC15C42AFA9001E0A30A11CEE658DCDEE4B62B6134BE16B6F2C5C92F4571BF6A2CE1AF1A360FB9C19792",
- "identity_type": "private",
- "iv": "58E287FC21B6D4FBCFF5C9FDECA731C7",
- "key_seed": "79E63CB8F2025BE59AAAA0BCB7AF1C9876DF9E2C8774637887557F11C87913AD",
- "metadata_key": "B6F890E2A81B7C0173C0AD1725402695",
- "section_mic_hmac_key": "C0B180C437E5BC877605ABC2A30E6E008A6365DF291026AF19F181AD62BB5F3B",
- "section_salt": "D14BDC42045F83B2B03EBFEC15C42AFA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5844853779D722DCE751CE513B2A0B37",
- "aes_key": "6062FFDA23EB1FD510C3672BA5B92CD4",
- "data_elements": [],
- "encoded_section": "37901343D08516A6126826C2F77055E624363E9110005BA67B0DD13A87E2209A8796B4455C2690014158D669F5C62F236538C822C5994228",
- "identity_type": "private",
- "iv": "5FB73671DC2F2B6A48245CA4E3FF1D1E",
- "key_seed": "819ADBF5BF607833105976ECAA2E3BC5A8BE1B5E73BB11A7967B93ED72128AC0",
- "metadata_key": "4467ADE4F732BB4F0AABFA43606DDB89",
- "section_mic_hmac_key": "5462BB3C170727E8601FE06BA4B954764D246394D912E56A085567F7148F0144",
- "section_salt": "5BA67B0DD13A87E2209A8796B4455C26"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A49403C60AC65B85C47FF2D1DA45B21",
- "aes_key": "F94C9EBAD0A9A3608BAA2D0DC0493BD2",
- "data_elements": [
- {
- "contents": "9FFF46ED",
- "de_type": 411
- },
- {
- "contents": "03765D84D65C1DF5BA926D5FBB496AC914",
- "de_type": 959
- },
- {
- "contents": "2D34BC69CF",
- "de_type": 64
- },
- {
- "contents": "2456607795672BD7C8E7EB4A79BC6F71970608BB0D6F2E",
- "de_type": 350
- }
- ],
- "encoded_section": "739013D459BEAE4BCCF848831FCFD6DF0EFC259110000DBB0E6CA11CFF6F16ECCE6188E4A1E6900164CF5B4306C90D677539B05AC8FC468C7048FEF75FA4C486D0BC50038AF5620F863D111F441579478FC7474B593EFF0D59E95AA2AE84A2E2D95EDE9FCB7E6A4F669A645B7BAE8A41309ADD91",
- "identity_type": "private",
- "iv": "6BA0BC2764992CFFC2BC748EA0A61698",
- "key_seed": "2E4F8F58A9D66315331FF83B8BC341494998670500C65260040444A67847649F",
- "metadata_key": "B8653FCEF2F9771634F76E509234296D",
- "section_mic_hmac_key": "35AE4A49D73CF2763F80202B81F55F4D2EC375FAAFF14AE60F00F7F706D36891",
- "section_salt": "0DBB0E6CA11CFF6F16ECCE6188E4A1E6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7B2876D1294D35C9A633642CDB531043",
- "aes_key": "11BD09E553C69F31A441EB71286BF702",
- "data_elements": [
- {
- "contents": "1CD68F",
- "de_type": 821
- },
- {
- "contents": "D6758EB514",
- "de_type": 58
- },
- {
- "contents": "A2AB3B5B6DC7B404F1EE0B3AC1BF3D67BE64619453F5CBDAEDF225",
- "de_type": 19
- },
- {
- "contents": "A1A3542F7C661B7FECF56442923CC27152C365D245BC303D",
- "de_type": 108
- },
- {
- "contents": "9E18754BFB",
- "de_type": 629
- }
- ],
- "encoded_section": "83901388E29374A47FF296171738B1F21D9DF491100032A08CD56B7AF49208B0A3A16326B62B90024A5CADC6674D9B1CD6D74390D279F841B4DF78C1F7D6A08A6A747C6D706FB7070AF8C54BADE0743A9A1DF40953ECAB8DE3D7EB5740B3633E669A3BB14CA04B83453B23E532BE99A7F576D1F3DC5261238A734521217EDE09D908B365",
- "identity_type": "trusted",
- "iv": "478031F97CE799ECA7A88B9B742BACF3",
- "key_seed": "124837A26828865520BB821F0833993EB6459AD3F6C4A3A9E9E3743363CA0FC1",
- "metadata_key": "0F6C4FA4BA7A110CCAC6F1E253D86578",
- "section_mic_hmac_key": "3366BD2EC451B292C053D75DF63AE820D999EBB1E4D608ABD71D9EE7F17CD6D0",
- "section_salt": "32A08CD56B7AF49208B0A3A16326B62B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BF1F3EDE71CC0BA23F3E9B5188DCD74D",
- "aes_key": "0D34EA39D00C9491832F0C0893FD98E3",
- "data_elements": [
- {
- "contents": "C8D6F76BFBB24D",
- "de_type": 615
- }
- ],
- "encoded_section": "419013A6981580761522A9EC4FD894D95FABFE9110000903815A6E8B791AD5B98D3F84DC737F9002828E33F525A8188B2C7FB787101D4E1B2D25346336913916CEEF",
- "identity_type": "trusted",
- "iv": "B462E5AB2AF8A646A3EE86F73E576561",
- "key_seed": "317A34230522CA4E9A39A827F78E044E63D1882E174AF27CFC3158E85FA7BCDE",
- "metadata_key": "A16F43B5C24F051BE891FCB6429D5625",
- "section_mic_hmac_key": "83683A330870E963D7B405376CAD9952CD313DEF8469F90D6951A0AF7DEF9F63",
- "section_salt": "0903815A6E8B791AD5B98D3F84DC737F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B96DEA316DEF89973732DB62BC4432A7",
- "aes_key": "C91E00B32F96ABED4FF0122583AB10B2",
- "data_elements": [],
- "encoded_section": "37901325B6BDC8A60672158F093819CF704ECE911000BDF2DD53B2723CF84674A938606393CD9002AF993A3939824B86FAA22B5B45F758C3",
- "identity_type": "trusted",
- "iv": "BE5C727FC20CAC7FD9F537FA14DA7E18",
- "key_seed": "489D396A25321A6241DE317FD48F88BAB3D8626C6C642C33E4D71ED80C33FCFC",
- "metadata_key": "B16BE5F80A589EAAC9F6CE6E40927214",
- "section_mic_hmac_key": "DD060E89B2C731BAD9F3B541F17841047A27DFD12DCCE92E2DEDD6D72CF17ABE",
- "section_salt": "BDF2DD53B2723CF84674A938606393CD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B15D76E91DFA20E5D94AB77C272AEA36",
- "aes_key": "08F89BDE3E8CF20DAA15650BE114AF90",
- "data_elements": [],
- "encoded_section": "3790132C20330BF7AD2A9D6356023F542CE510911000C28E44A518BCC0A1AD058B4EDF7778849002A89640F16E3ED67F7EC86AC01434665D",
- "identity_type": "trusted",
- "iv": "4ED00D1E66EABEA0AB30F9ACA64C3AB4",
- "key_seed": "F4052897D21C7FDFB463D86A3F70F43315969DD6C35D4E2F28E5C5FDC094499B",
- "metadata_key": "A9CC5F1CC6D129AF1BDE07EC54685F86",
- "section_mic_hmac_key": "1B1A2DB91F5F90BCE7D03F7F283476DB0E6F856A317A3B29747114D6F7543214",
- "section_salt": "C28E44A518BCC0A1AD058B4EDF777884"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B23518E75C4291C3FF45E230AE8E1144",
- "aes_key": "0EE48AA7E17EB7AC213E0251F5863A43",
- "data_elements": [
- {
- "contents": "E8397D814788CE2F20C774EDD9A8",
- "de_type": 38
- }
- ],
- "encoded_section": "479013B7680C78524B27EF19239EE7409C867A911000937FD9077FE6FE41C87FF58C9760628390045396E7CEC68FA85BA56F754D53A236C80B709D69201120CE8DC52D023F63EA2B",
- "identity_type": "provisioned",
- "iv": "70E0CF8376E6263D6D39221A279FFB74",
- "key_seed": "C1CD56FC8895CFAF52047C5EC6E4B555A2A3FBEA8078EE18B88DF10D073D3D20",
- "metadata_key": "C409D3270AC018858924F1620EC07CB8",
- "section_mic_hmac_key": "FC9B097CE0223CF1D7719C00676607E1D99B792D993450C7E333EFB2342D5AC7",
- "section_salt": "937FD9077FE6FE41C87FF58C97606283"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FE111934B0B07379A319C62F558B8EF1",
- "aes_key": "BAF0EADC4EAC7805FF4CB8B5BBE3E33B",
- "data_elements": [],
- "encoded_section": "3790139B8CC25B1E6EE84846046B6606A9FAEB9110004EEDBAD6580D5B7A26ADC604E4AE5ADB90023E2A49EFB0DAD66407994E861FC7931C",
- "identity_type": "trusted",
- "iv": "B9F42C9FC19969B3C708F54B1B2D2561",
- "key_seed": "CA99DFBEE06974AD30031B9482C62411610D1DE2B05E1977F969FAFD860260B5",
- "metadata_key": "7EBA70428E31280F089029EBCCC28E53",
- "section_mic_hmac_key": "B7A04163665233F6DB80BFA0E9DF284676010DCC138FBBA97019550EE0505C71",
- "section_salt": "4EEDBAD6580D5B7A26ADC604E4AE5ADB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "06340305FD9EDD7CA6E97F5F03028D41",
- "aes_key": "4A3AE192FE98DF88EFB792D9244CB3C2",
- "data_elements": [
- {
- "contents": "17A7D78EB34F",
- "de_type": 40
- },
- {
- "contents": "6CDD9B23F45E60C6",
- "de_type": 13
- },
- {
- "contents": "5EB80DA49615A9313378E994B31F96F8B3C2C926",
- "de_type": 132
- },
- {
- "contents": "38130E3285",
- "de_type": 514
- },
- {
- "contents": "B43389EB33CA74907A7A4F86FE1AD1",
- "de_type": 916
- }
- ],
- "encoded_section": "7A901396619F2B2B94F7F19628FA1F51785B4F9110002340B336B5C2E124737BEF2F43F197BA9001ED28FD63D309949B6BED96D0203D4FDD41B32F847342D156B990DE7DFF2408A202690C74A8F5CE1C8D7A709CE7D85507215D173F3850F3C1B2CB91993E340431B97110F563A286331D4B7103DCBA697904EB30",
- "identity_type": "private",
- "iv": "11DD03FA6DB092780B048EBD3113CEE0",
- "key_seed": "7945F877F9D98C7610CE29F45369C662E303A8F5A326BEAFF9F0FB55611C89AD",
- "metadata_key": "3FB05DBFC8E615E495E1BAD8431FCA80",
- "section_mic_hmac_key": "FC6524ACBEEA7CBEC81E530F33889F7C852A85E4108B48F1BB2CE77B7AFFDE3E",
- "section_salt": "2340B336B5C2E124737BEF2F43F197BA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "62114838135ABD22F7D172D64A9F009C",
- "aes_key": "3757133FEB278857689A7FA8C48C2A3E",
- "data_elements": [],
- "encoded_section": "379013CE7AA72E7E878D42F249B992DB2F7173911000F0DE28B972676F2AB092E80CDF67018E90046FA72EA86F5EDAAA0F8CDCA981D5B00C",
- "identity_type": "provisioned",
- "iv": "28D18F45C5B8ED0408635743FD12CF47",
- "key_seed": "EAB98A97C8016D997690C36C1AFB9B27C179D64C4A95BABCD5B30D160EFCE103",
- "metadata_key": "1C58B34BEC2709A3E7F68157AFE44195",
- "section_mic_hmac_key": "A071066F9D28C8A5318A2E186015463596B26CE67FA85080E2E0C1BA3FA7BF02",
- "section_salt": "F0DE28B972676F2AB092E80CDF67018E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1C180AC933FBF1E4BCBCDB69BE0360C6",
- "aes_key": "705839E944B1F2E9CD381E4E53EE5B8A",
- "data_elements": [
- {
- "contents": "AF617170EC2294888C20C8A3B43BB3AC96",
- "de_type": 12
- },
- {
- "contents": "E8DC15F1D350190F674791CB",
- "de_type": 745
- },
- {
- "contents": "142A94EC2E864E33",
- "de_type": 311
- },
- {
- "contents": "A0DFF75C7969634EB2",
- "de_type": 940
- }
- ],
- "encoded_section": "7090137A7BBAF6598BF52772377F42EBBFC25D911000BF57CBF05D69C86F976C9A93BB7DD05990044ED30E5FF146DB04653AB49241949BA2233DEF5D16BDCFA8E61DEE02A211BE46C56D05AD868F1FD3229443986B6BD054D49C895EE0730BF53CAD53C8E84AA47FDE268B61F2343BC294",
- "identity_type": "provisioned",
- "iv": "566F3A2DE9C6FEC6D2FBEE1645AACAC5",
- "key_seed": "CE740FB16B092B7AE502759E36C49BDC5B7A2FA2E97AE29FC9E0B9D2CDA72AA3",
- "metadata_key": "C74FB2EB350DBBF1969E3A9691508933",
- "section_mic_hmac_key": "1B8D81AB3F79239B973E2C8E73954ED1B5127289547C38CC71BFD0ED9552AE9E",
- "section_salt": "BF57CBF05D69C86F976C9A93BB7DD059"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "26C852943966AC80964F71AADDBF07AD",
- "aes_key": "B4D2FBE9AEF3417552263603D22318B2",
- "data_elements": [
- {
- "contents": "4453D6586D1F59DFCBC6",
- "de_type": 203
- },
- {
- "contents": "8A3CD10D1097BF",
- "de_type": 383
- },
- {
- "contents": "05AC77461449443D444D10",
- "de_type": 209
- },
- {
- "contents": "24",
- "de_type": 176
- }
- ],
- "encoded_section": "609013CBADC624AD2C1F25563EB4BBA865B8F0911000083E4B25DF44E64CB1F9987202D5EE2990016AACE26DEB07CC0FF6D7CB2EDB3B7049A2E9481144AB66F3998841BF6B369CCF56E5878E5C1D2C17A031CE097D4F9B7E4B71CC190F7B637F6E",
- "identity_type": "private",
- "iv": "71A9F7A9ED012D7D0A3B5E1665C533EF",
- "key_seed": "5A0B49C13A755D3C39FB51201D79662CA2DE0CC5DF1853631D2495F78A55490D",
- "metadata_key": "441FC2E790A83563ACCEB1D121B02A5A",
- "section_mic_hmac_key": "DD41E3D2F17A81A9B4891E0B07B500140C19E3BE96876B7E38CF1B4DEAB3078B",
- "section_salt": "083E4B25DF44E64CB1F9987202D5EE29"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A05BB37EFDDB01C28868C9CABDE45755",
- "aes_key": "11824EA2413643EF46FD5BCFDB388E43",
- "data_elements": [],
- "encoded_section": "379013C86D4AEE77BBDBB8844E2926505C097691100028E0AF5531DA2DE3C0DED5BC781B7F049001582A39819023E35A620C88CE345798F6",
- "identity_type": "private",
- "iv": "BF0445BA6682A2B47F7ABF0E20E32035",
- "key_seed": "B688A40DA68CD7661B7D6089CCFE418B5B408BD375E9077C8DB33B620731526C",
- "metadata_key": "935583808C7CB2FBC7C0714A8C36CA1E",
- "section_mic_hmac_key": "F086EBEB816B05AE588F30216FC53E298A827819E14CF791CAA5B43B668A6614",
- "section_salt": "28E0AF5531DA2DE3C0DED5BC781B7F04"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6E0D833A506E4DB1F3A53EF1F43E4632",
- "aes_key": "2679F4BAA410BBC4E9854FEF3B8126DF",
- "data_elements": [
- {
- "contents": "5B6A4C0B",
- "de_type": 32
- },
- {
- "contents": "DCE0D04F8F070A447B924F6C8E16EABC8579F140",
- "de_type": 672
- },
- {
- "contents": "4AD51AD3",
- "de_type": 801
- },
- {
- "contents": "A2A4B310EEDB978A748833C1F03354157907B8F4952A82D1C60B6F",
- "de_type": 988
- }
- ],
- "encoded_section": "799013D95AC86388C09B4142211B1890B433C7911000E94F2773795ABC33E1D514921EE2BA949004E570F5BDF232B20034955E0752F5D6A5CECC93236A9D55EA1B0E47A3E000126D73140A93AE42360BED1C2DB98ECD79A07B5C38AFADFB8DEC81C8AD48B88EBEA6AC5240B479040953B63A5C6A83786CDE7E6A",
- "identity_type": "provisioned",
- "iv": "F3D857A44878F37AE15E0E4272AA946B",
- "key_seed": "6412DBC3C88BE6FE2C83658F87EFC2B68E27DC6E2A5F7818CE07E278DB4258F5",
- "metadata_key": "2093FAC2282FAB9E32873A9249CC23CB",
- "section_mic_hmac_key": "59E443F1954D91B37423505D8241E6F35BC213F3059455007F588BABAE936B5D",
- "section_salt": "E94F2773795ABC33E1D514921EE2BA94"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0366F4962B2FAF43595714EA372D803D",
- "aes_key": "2381BB44E4A84BC892495AFD32648DFB",
- "data_elements": [
- {
- "contents": "EF42CB7BDCFF5FDA2486584DC7C69755B49AEA22",
- "de_type": 48
- },
- {
- "contents": "07B646472EC5353965E24350EE4F4B41E1D3B04A5FA3AB743D19",
- "de_type": 950
- },
- {
- "contents": "4CE19C060C1E3AAF573C8BE7046339C6A72F11",
- "de_type": 772
- },
- {
- "contents": "A9DF36B2600420CA81D5AC14199AAF13B9E4056F43C0C7A9A1B458F9BD",
- "de_type": 283
- },
- {
- "contents": "B7A2",
- "de_type": 578
- }
- ],
- "encoded_section": "A5901395C08630D83223DA1529C5BDDF862429911000F33DF7DF517C94019086C3C55258270190028EE860429E7BF8FA0A3E8D5138E3CFAADB41414889DE9CCF0C46FC07FC618E4B0EDE78A19EF63C6FC7C4127D749C7ECD19EEC9D7F0C1D4BC6F1074785CF7CC06DF2CA35F43B17D8C23F389F82BB16E21C1C80328B60B0BF7EF031D3C885393CB7F86C0E48848DE744E73F7DE8AA69F5E875AF692EE5CA62B6958F450DDF7",
- "identity_type": "trusted",
- "iv": "596ADE25EB467684CEF42648156B0626",
- "key_seed": "9E23BE85340F7F6E4EF0B499865BC6771EAE8777F5CD62655BBCE72E53ACC83F",
- "metadata_key": "2EB7B8F54852A9FA534E0355A51CADDA",
- "section_mic_hmac_key": "4A08AF41A015449CDBF11C5A919FE3F09B3D002BA5FE5C0C0910061C291FB569",
- "section_salt": "F33DF7DF517C94019086C3C552582701"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0AEE1E2CF439B601CEB6912B95375040",
- "aes_key": "5089E7D176FF1A7223D80B0409C6FA26",
- "data_elements": [
- {
- "contents": "D5276E1226F20AB687",
- "de_type": 607
- }
- ],
- "encoded_section": "43901358F31DEAC2408D32879334657F553B3C911000D17FCA0932AF190778C24B96E5FD773490023BFABD0169B35850D2228C8AFB2F91608D59B80F95BFFE0B86F85870",
- "identity_type": "trusted",
- "iv": "D41B625DDAAC29E9C2C452E9F16A29C0",
- "key_seed": "44C670ED0F58A7F2BC90EF1F04EDF83C9348139557B451EB6D8275D7B0185398",
- "metadata_key": "D8BFA1BDA44332D65D99EF0080E01D3F",
- "section_mic_hmac_key": "C2B8FE9FA062BE161FF8BD14F31BBFCE43378DDD9D82EAE811BF8D61BE0E889E",
- "section_salt": "D17FCA0932AF190778C24B96E5FD7734"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "14EFDEC1CD63DDC48B8B8E8C8CDC8304",
- "aes_key": "5E279D274E2D7323A335FB4BB590EB6E",
- "data_elements": [
- {
- "contents": "A16A8E4A6AF9ECA8C6F59A0C810DF0887016754EDF4E",
- "de_type": 933
- },
- {
- "contents": "91E18A74954C81ED",
- "de_type": 768
- },
- {
- "contents": "D284DA8A828C589785EAAF87EACD9B6B629C93A72A",
- "de_type": 250
- },
- {
- "contents": "10F674B0727729EAA5906B2E2055A074EFD5",
- "de_type": 386
- }
- ],
- "encoded_section": "8890137E2AE6C6195C792C17C7A7D5D85D62C39110000FD914F6DEED1D8B294D54AC1AF731E59001801DE846E75659321A50A88FE67B0F6D15999A664BB34EAD74AF0F15CE500635DCC5662F84ED09B1DD8BE084A71FCC5952EC8D21D42E2C73862E6C7624C1E23EF238E3454F3001E1A1F628F7DDCE9E1603C29A09EAFCE0AC398C535C7E6A3F8B6E",
- "identity_type": "private",
- "iv": "2769CEA47FC25DCCB02764766D926045",
- "key_seed": "94F0C89FCD16F86CE07F9E525E6DAEF427E0E34155511E533DE9E9A3459588E6",
- "metadata_key": "F8A0DC8DA1A04B3E48500497F9AD016F",
- "section_mic_hmac_key": "BA370144A94F5A2D914A271DA273C7398BA54051561DF993717920C6402766F9",
- "section_salt": "0FD914F6DEED1D8B294D54AC1AF731E5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8DFC829806B833E4CC7A5915DBF6976",
- "aes_key": "178A9B604EEB014BFBD4E225DCD5F848",
- "data_elements": [
- {
- "contents": "E8C937C8367D2CE21D17EB8473B0C2115CFCF8F17AD95664ABC342ABA8",
- "de_type": 501
- }
- ],
- "encoded_section": "579013A26BA7738CE48F0A7785573722492B6F91100052FFAE3A4F772BE69EE13ED700E5C0019002C8986203C903B3446CAE025DF6E718BF73EFF77A892F5867B55BFF67E278D59AFEE383E4115BBC6F3052AFA8F85D5B0B",
- "identity_type": "trusted",
- "iv": "D2EEBE3242653569FCDA783795429968",
- "key_seed": "93A836F66F3808515B936588D6A270FEA403392AF0CB25E16CE672AFAF26BD09",
- "metadata_key": "1DFAA8BD5B70B5BCED114183CA5CD29F",
- "section_mic_hmac_key": "3DB4DF42F47597DD85B09EC00F7CB6828C0AE0C4AD770964BBB83C18F44A5D4E",
- "section_salt": "52FFAE3A4F772BE69EE13ED700E5C001"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8EB77BBF9B403FF005C47CD0E16171E6",
- "aes_key": "F609CCDD1AED844DB12101C1455043AD",
- "data_elements": [
- {
- "contents": "6F7BDD9D79C975F5499A0445A0A45B65093FE6BF6B87",
- "de_type": 253
- }
- ],
- "encoded_section": "509013F28F4ECA39FA96461F8A0699BFB576AC911000A9E37AD77F5AF0CDD4310C3400E843999004BBC3E4FB4CD4FF5E74A6FD5D24F758D3A225C841350134B8EAAC663A8425EB10B70D3D5AD7F5D89454",
- "identity_type": "provisioned",
- "iv": "3FBF642845DA78CA89C9F1C1773C1CAF",
- "key_seed": "81004ACD295BD7E1F3B141E4F32DB07B38D89628FEE7E832C5250130F7B76DD6",
- "metadata_key": "12D275A01046BCA9813B58EBA1A111A6",
- "section_mic_hmac_key": "9DBA40A86FFC3D909D4973DD42F5A1590AEA88CA64FDD1AACEDE1873FABA922F",
- "section_salt": "A9E37AD77F5AF0CDD4310C3400E84399"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "72F229F976778B8F81E6E11237BE69D2",
- "aes_key": "965455CE77299A33B4677C22F8934450",
- "data_elements": [
- {
- "contents": "2BF3E31146E2852F0C71FD8D00185974D4945EC0388D52FDD11F6C78",
- "de_type": 474
- }
- ],
- "encoded_section": "569013F1133A1C5D39C0EB102D559967F81832911000BA431CBF78832E8B284D34DDC999B6589004C08F255B79F62CF6CE040EDC3A23728625BC0399E1EC4D686FE88AE38EA18CD1D3A961F303FE34DCCCA5613EF5B19B",
- "identity_type": "provisioned",
- "iv": "39CA34319C4E57CFA76C0CC39D250FEB",
- "key_seed": "2EE377ED490D438BA5E5856EA6CB0206766DEC800FE300A20C5AA30FD9F985BA",
- "metadata_key": "A0B481795EE988419063BED63094A408",
- "section_mic_hmac_key": "E63EBAA47708FA1F7DC4BB439938D4434A0083BE3DB361669A090ACB41D45DF1",
- "section_salt": "BA431CBF78832E8B284D34DDC999B658"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E2438E9BF16B31C95FD6885C00E11B08",
- "aes_key": "D4CF5202400F9C1932BE142FFD4CC65A",
- "data_elements": [
- {
- "contents": "6D",
- "de_type": 693
- },
- {
- "contents": "40F83E490CA9CA93",
- "de_type": 591
- },
- {
- "contents": "E66886C93E6592BEFD3F",
- "de_type": 241
- },
- {
- "contents": "8C0010C44724714E61E68F30533460A53E6B0D",
- "de_type": 277
- },
- {
- "contents": "B277F8E0CBA5AD4FC3545F8F62834693",
- "de_type": 958
- }
- ],
- "encoded_section": "7C9013FF26D8333BFACFE99C000A04F9446EAE9110003398D1FA6CA164B2F2A9DF651AB8A08B90028DB85D0B6CE0D6780A715759F75B820D7A997FF914C10EA81F49984D37145D11414ED694AE60301AE1181A025E347F78BE15A882905044070CB461D3D04F7BE7466B9768736B89D1E1EDA8227D37E080378D6BA9F9",
- "identity_type": "trusted",
- "iv": "FDB266B94952A2C53A36FC76B6B10D70",
- "key_seed": "2C450CB362CA288FC9F268B3654DE6BBFB2C42A0A3473D1DD752CD670C45E550",
- "metadata_key": "437B5470A0C2E0EE8257D7A255D776D5",
- "section_mic_hmac_key": "57AB37FA929E2622240214CDFA222E72B87D00F68B01F28629BA162F61B24856",
- "section_salt": "3398D1FA6CA164B2F2A9DF651AB8A08B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "16A07829874761800D9FB4C3E21A2A30",
- "aes_key": "24152963469643ED0534D23908210079",
- "data_elements": [
- {
- "contents": "582A88E9ED0B",
- "de_type": 226
- }
- ],
- "encoded_section": "409013D7F48916F267119188FE49673E4322F5911000AEA39558B6060468B31BBE90D84E48569004128F5F484DC44595CD6EA02E9616DDEAD65E71B1F3C0ADA8C7",
- "identity_type": "provisioned",
- "iv": "B77132A303625EC533C2AB64430BE8EC",
- "key_seed": "9AB4FD9204A072396ACB99BF24E36F99D6DC23A9C6433CDD793163D716AAB367",
- "metadata_key": "6B6FEEDF5FECF44F4598D9F9336EA39F",
- "section_mic_hmac_key": "CA281C0ACDB75B8FCCBE489135F1F60CBCE613EDABCE4F6599DB6A32FFE8A98F",
- "section_salt": "AEA39558B6060468B31BBE90D84E4856"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9159107E1D54578B844265C291E6F456",
- "aes_key": "A142FCD93225283E9C860862F8719CE2",
- "data_elements": [
- {
- "contents": "BBD5",
- "de_type": 347
- },
- {
- "contents": "A61AEB",
- "de_type": 165
- }
- ],
- "encoded_section": "429013CF49B28303C8F063E5A9C8A2E5E5A582911000C3D02F4B3F14A8C76A0E3840C522BD199002C48D6D20B4B27E0AF7E8AA6319A62AA7AA534F867DED4748522E0B",
- "identity_type": "trusted",
- "iv": "E45AE7CB222CCB06E574519786304AFF",
- "key_seed": "7EFDFFA488A94BF2C11A3EE5B309FAB935BF41D510D587A7115D5BAD030C853D",
- "metadata_key": "C6EA1FEBD15B10E7D19D13317D39F365",
- "section_mic_hmac_key": "9F5F37B864A003287CDF62806A6D5CC4422816474DAD127DAAA0303B842DBB01",
- "section_salt": "C3D02F4B3F14A8C76A0E3840C522BD19"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "01D0C987D88C843A8DA02F96AEEAB362",
- "aes_key": "4D8530AB04B3B18073DD758C44CDB12D",
- "data_elements": [
- {
- "contents": "C635CC117668AFE7949917A7",
- "de_type": 593
- }
- ],
- "encoded_section": "4690132F78152F11A6D5F60810B49DE0E34D739110003C013D2EE71384CB77B9FFACF9A47F4E9001A32EEA69EB210803D358A56381F4A39B5F6DD7C26B7E13BAC60AD879791059",
- "identity_type": "private",
- "iv": "47787F6AF0CBFF3224FD5B90B7C62C19",
- "key_seed": "00CC8EC56019B472D3ACBE5BE0A264A6678E2DF7CEF0BC67BD79E6828C8DEFA7",
- "metadata_key": "726B29FC8323127C8BF3CA61DB54DA54",
- "section_mic_hmac_key": "6282DF040346562FEC646797AC206013549F226E4BAAA53F89F7EA8D7704CA35",
- "section_salt": "3C013D2EE71384CB77B9FFACF9A47F4E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FAC14F23FCA63EE1AC8C2F59083B88B7",
- "aes_key": "6FC985D771EFA0BEA304EBA07A4D4381",
- "data_elements": [],
- "encoded_section": "379013210B1AE359DE0CBBEF346FF559B51B64911000588A0BD17ED117BB4AF055C77AE2DC439004E313D80409FCA3D2E2979544708A39B2",
- "identity_type": "provisioned",
- "iv": "86C71197DCC66D69EAC756CF2C03457C",
- "key_seed": "C2AE57F5782C3D478DE8AB1D2E1687BF00B9E0610F7D6E16623496E61C6B1230",
- "metadata_key": "53695A2CF6468D1F2453CE5EDC1F5D34",
- "section_mic_hmac_key": "6AEED53AA44B52EAB200C7F46C01829AF89B54BCF92A9976DB76868D6F135627",
- "section_salt": "588A0BD17ED117BB4AF055C77AE2DC43"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D472CE5EA02A6BA693D3D3C2FDAD3CB9",
- "aes_key": "F3D466548CF059E4BFD26C5886022F5B",
- "data_elements": [
- {
- "contents": "D8D56CACAF01745BD359143859C0D997FFAF99426DEE4F0526C6B7",
- "de_type": 92
- },
- {
- "contents": "A24E8CF59B4C05",
- "de_type": 365
- },
- {
- "contents": "81",
- "de_type": 632
- }
- ],
- "encoded_section": "629013BE8CCC4DF63F42BA4F95A6E67E961F27911000FE4F65E41C205A3E4AECA5C3793C5BF69001EDBDC998D2BB9F46E2820FFA264F9BE3D3915E34044744679A1B1F264AD4E0308DCB0BF6480F7BA07BEF3F97BE391D659BD97C4CE4105F2D3FA56B",
- "identity_type": "private",
- "iv": "991E163873F0FD3CDFEDF8139642A8F3",
- "key_seed": "568C44F2441F53CD271E0542E28C0FDC6695D248A63610880C0453C64F0377E1",
- "metadata_key": "2852757C8F7EB2EDEE35A83C67DAA69C",
- "section_mic_hmac_key": "FA797B50ED1D17BF334DCF82CC974B740018A9C8003954FE8C86266B17D3F3FC",
- "section_salt": "FE4F65E41C205A3E4AECA5C3793C5BF6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "37CA9E5FD83C77A93EABAEDC05387FA5",
- "aes_key": "2A6AF75B9E41431A70C784C8CC4F67BC",
- "data_elements": [
- {
- "contents": "537D9BC55AE1DA87236C576CC5F26C2D602732D596",
- "de_type": 824
- },
- {
- "contents": "86804C087B781C582B55",
- "de_type": 646
- }
- ],
- "encoded_section": "5C9013115FC54D3F5BE989D8D73E6CD5FA8933911000A85F1F25192415C492401A2F8E01E92890045AEFA99C8FC1CA0EF427BB15090A7DD66CBEDB6F851224E43966EDBB49403FAE54A4EB5F2EC7DC91D3303A587F631C60FD37F77187",
- "identity_type": "provisioned",
- "iv": "EF1CAA1432DC4C9DA79FD2F1B6085F22",
- "key_seed": "83B25874FDA42842607D32442AA882CF07302E77F3ED45483B084173C78CE088",
- "metadata_key": "D5476BCD37EA529CFE0398E04BFC8DFB",
- "section_mic_hmac_key": "9A3EA2A97F65070F53F1D0565BF79C2884EA8F83777C386F788878D0405F8F71",
- "section_salt": "A85F1F25192415C492401A2F8E01E928"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "23A40362AB2ADA10E507ADF73A53B738",
- "aes_key": "2A3CDE8E1F16994BEAC62D6303BB37F4",
- "data_elements": [
- {
- "contents": "0843EC4474384A6564190967861E63F79CE2C093CBE9",
- "de_type": 549
- },
- {
- "contents": "528EE47BB4B74DC8BB9E1DF094",
- "de_type": 970
- }
- ],
- "encoded_section": "60901318D390C46D78B50D713B7F1D3E4ACCAE9110006797144436216197C900B8B9AAC56F789001CD6DE510AECDD868575107FE8366F7D00DEC23322446DEC1C1544F04F07114E1ECB49ACC9CC160A0AD858347DB70785C8A1FE1865C1B8EF1A1",
- "identity_type": "private",
- "iv": "D5757A781F250DEA9B32A2187D1DCE66",
- "key_seed": "D0B4C8F4097FCB6FA04E537590BF5D93980F62C3CEACD9539F4B805FCEB19BF7",
- "metadata_key": "F59AF47E80215C5D7080A9F17789A0A4",
- "section_mic_hmac_key": "75CBA9C19FB676E9DAA28A513B222848CF282079CB8D535638316B230DF07FF6",
- "section_salt": "6797144436216197C900B8B9AAC56F78"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "669368F2B1CA51C64A75E82A26AF1C11",
- "aes_key": "A4EB2632A392009042825BF578EDE10A",
- "data_elements": [
- {
- "contents": "F2D8D28C9069643C0348AB1945160AF061335DF9EAF41B221DBE03",
- "de_type": 436
- },
- {
- "contents": "60197A23C9",
- "de_type": 331
- },
- {
- "contents": "8A9DF20FBD2E506F3A1A9C0A2BFB4DA265569A10ACDE979A7E788D21F2",
- "de_type": 679
- },
- {
- "contents": "2CAA8CA35DEC7A9CC23AE80F2AD4D04BA3E183FE80DA7CEF25401F",
- "de_type": 414
- },
- {
- "contents": "1A1B4F43E756C631B06104F7",
- "de_type": 20
- }
- ],
- "encoded_section": "A990134A4C65C83E53EAC713E40B3AD06319C3911000436276C9196C9DA1609DC9C37F62FCCD90017D953EC227BCF3F8D3C9D12F703836BFEF24DA8CB8DFFD6E8ECFBCEEBD7C7A96FD46C6DD33481F61896CAA97B3080075A5EB1F94CA4723CDE6DEB7A248B1539F7A6F727258DA870911DF1D648D43006DD5E59E84C30F72CD61095DE966561D2CF65E1AD4D23E35CA259C6D24D31B7FC9DA8FC1F6013CF1D45C5024A5586264342E8C",
- "identity_type": "private",
- "iv": "B16EB79EEF99FC59C0668A1D7BC49AFA",
- "key_seed": "5F02964CF3FD078549F6F8A12FBDC0954E721E45D6E846889E7524D2B8434B8B",
- "metadata_key": "A708F60A0D600AA8A68217B333B97CD8",
- "section_mic_hmac_key": "E13B13E5A85167161D8B99887734E38F16B76B87A517A8C4FF136F89A5DDF17D",
- "section_salt": "436276C9196C9DA1609DC9C37F62FCCD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0A2481314ED5461D784F31EAF236F1E5",
- "aes_key": "16E09656726BD0DC340707E9A8044E65",
- "data_elements": [
- {
- "contents": "92A1BAC82C6C9E906E78A8DB18D26644E7A2EAEEED",
- "de_type": 647
- },
- {
- "contents": "98233973D9B3EBB10DD17CE8B446D32C9401AFD1B5EC9C57FE18",
- "de_type": 657
- },
- {
- "contents": "39F2C871399BCE2B2A4B30B8B2310104C5B7056E11F51AD03F",
- "de_type": 824
- },
- {
- "contents": "92A59F3F222B370631B5",
- "de_type": 29
- }
- ],
- "encoded_section": "9490133A361322C6CFD8F123B652392B2C33F0911000C1A4FD2EF8C9F2A6D6974F8499A86C659004B9B926F64A99404F409179FAE1A76A99533E523AB5C23493DC15F5F3F120CADCA02CFCAE5A3082F5FF9C2FB21D81E521728C42982A2328CC308F514795CA4EB96B8345F6BAE498307143DD189D826F4724CC8EA3FAF712901F36E30FC459E53DABAF178E7BD5C84E132A30DAB1",
- "identity_type": "provisioned",
- "iv": "E767A2363EF745A39E8787B42FD8DE81",
- "key_seed": "61F9D03A55557256DF3DB5D601914145C9775AEE985415278B8032FA275C5329",
- "metadata_key": "BB767635FA036098ECA2BC4802D976EB",
- "section_mic_hmac_key": "31D39D034312D41DC5F9345FB580C37BB38395B84C53E60162A28720C1E63FB7",
- "section_salt": "C1A4FD2EF8C9F2A6D6974F8499A86C65"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2F5E446BB35D880DD4832A0320D23837",
- "aes_key": "0561AF2D0D1CA6D8E039AF77CD3EA3F4",
- "data_elements": [
- {
- "contents": "AC27B62265094108D47755E4CCDB67D80B83C7074CECC0D32722",
- "de_type": 769
- },
- {
- "contents": "B4AAFCE877574BE04E95",
- "de_type": 926
- }
- ],
- "encoded_section": "619013DDD6BA07092F273FE5A3B387A7DC9075911000CC0F046848B5C94CFAF3C1D28E8683E59001430FC81EB61D0491A40AA0EE069E9B722C2B89CB62B4F352CB8FE93F0E9D15D6312B6DF7F955A3A8A04C4D6A4986F86D536A3E4CBDBF4FD6DE71",
- "identity_type": "private",
- "iv": "EABCB9DA7F07B140664428DCC9047C9C",
- "key_seed": "F82944B1BE8D9544BDC997CA1D03476C40D7D7FFAF30984C6FB2134B5AC19139",
- "metadata_key": "19D5EDE29D0669273A6E1EAB85910537",
- "section_mic_hmac_key": "E69B4CE7F49A47FB968E2C884248B3945F308B713AE44E3E4647DED0393E64A4",
- "section_salt": "CC0F046848B5C94CFAF3C1D28E8683E5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "745EF38C147400E52E78EF73D799E530",
- "aes_key": "397F15C3D3507F7558ED7FAA6FCFA2E6",
- "data_elements": [
- {
- "contents": "744A64EA84D1A11640AA6EC3E1A7",
- "de_type": 906
- },
- {
- "contents": "AE5862393CAE8A6A8081",
- "de_type": 472
- },
- {
- "contents": "FA53D0AC965BCC16F47544049731DA0A5A15BE0404705E",
- "de_type": 331
- }
- ],
- "encoded_section": "6F901373AFF0834BE5A8A75E5746CB02F7A71D91100061D605F31762567236505062910B3D87900118280B003A65469819DF38D09A494CF6525442F1CEF475B8314478A8F1A57BAF3C7FB86AB20E0190C6FE6850335A7E386D600128E705B2179D425FEB351F9E4EB59CC5E7A9C83430",
- "identity_type": "private",
- "iv": "94077956863ACD5EA404F69F49C6DC77",
- "key_seed": "CEBFDAAFF86989FC83B21C9AF025C8C9179994F61AD5E743A802B5ED773A3EB0",
- "metadata_key": "538ABCEE91E1133075655C92E743045E",
- "section_mic_hmac_key": "E73A504BC9BD9D96710628DC0B818E1AFE30AC345BDA21A8D433B5848C46CD2D",
- "section_salt": "61D605F31762567236505062910B3D87"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0A6BBAF5021A1D2FE1682B7F1075264B",
- "aes_key": "F9D5C665842BC9A21E7118A5140C5980",
- "data_elements": [
- {
- "contents": "04FCE6BB03DCEF4AFFB691BDC55131FB1362F6DC9716322F4D66C7",
- "de_type": 586
- },
- {
- "contents": "070F8092B39E3A464748E7AB9F0A6D3BB8",
- "de_type": 48
- },
- {
- "contents": "1B8AB668E06DCCA0A0D10CFF6319600E8C",
- "de_type": 363
- },
- {
- "contents": "0505E12CB0611C4DCDE6D2501FAF96B1375497EEC1C3D349017C4DB382",
- "de_type": 825
- }
- ],
- "encoded_section": "9C9013F127B1FD8A6754A1D23FC5ADF1AA4888911000D2EE2D16407010B143CC91248DF3EDF39001C723843332E652018213683FE8E97832066841091B04D79B031EE9C28AB3EFEBD8DC90AA76D499E8625B8D7DC05E47FC8725C9F52EC835086F1A12BE17FAE08E5648CA25CAC0C975F9D6CEAC578FA100D26031FF7D24B6A39531F184553B64DDA8B42C63400D9D938719D92EFF98743E9E06D83085",
- "identity_type": "private",
- "iv": "E54BAF233C2873FDEC34ECDBD2A75BBC",
- "key_seed": "5E571CC03CF6060B889A4AFE1525C75D7010747E1F49304996A04F6541A15BD4",
- "metadata_key": "7E9B72FC7CFC6D01C32FF8525C73A26F",
- "section_mic_hmac_key": "D4FF75AEC965C82A4A2EBCD6D793ED7901083D68C26FA7863DDB45B242B412B0",
- "section_salt": "D2EE2D16407010B143CC91248DF3EDF3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DF5BE769CC5F0353186732BE147A63D9",
- "aes_key": "22CCD7B2403BD3865C7B2A465F6C30BB",
- "data_elements": [
- {
- "contents": "A14BBA160E760CF44F",
- "de_type": 952
- }
- ],
- "encoded_section": "439013BAC4DBE0F31AC812333CE4E759DB04059110004209A410502B246C097B277FDB07C4D990013BF9818DB28F7BCEB9BB5E009163691F51BC8DE49B58C0D49F0E18D3",
- "identity_type": "private",
- "iv": "1355F2F66052B17658A63F135FDA11D7",
- "key_seed": "7361CCF3A6692EBC56C0CA940F35FC4AF1AEB3D0A61C09D9E514C39787069B58",
- "metadata_key": "4FA17703926007A4761033EDE0235613",
- "section_mic_hmac_key": "A13C30E9F3243CF7061EB9B9BEB91A45DAB682A15588C894BC803B751B4579E8",
- "section_salt": "4209A410502B246C097B277FDB07C4D9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E5F3B694C8D64BE7698617904C135CAC",
- "aes_key": "42CEDB34BEB620F53150B505DBF0017E",
- "data_elements": [
- {
- "contents": "1B9289BAFE209EB83B1317DAF000E1364AE9B42EA5D3",
- "de_type": 329
- },
- {
- "contents": "62612B87E30046057587",
- "de_type": 311
- },
- {
- "contents": "F6E858C9FC1193050685904D19E7AB2BBE",
- "de_type": 261
- }
- ],
- "encoded_section": "719013159144D7E2194B056A0C7E8584BF6CE8911000218C59E9A77F6C177DCD2A9773BA48AF900241DA1F7786470F9D4A621561E8AF20F7C08EE15C0BD534A675FF6463E81F6CA71A45ECD5406B91DDB3E4735DBADFF00978F8362A398E5F456CDAB11EEC901F03D1648EF8B150DC3E67DA",
- "identity_type": "trusted",
- "iv": "EA32DE5C1E430A835C12B1A91CC89CFB",
- "key_seed": "8BD9229CA4491845B4083623E5FEA2069BD41B56809D886324CDB1A586BE0CB6",
- "metadata_key": "951A2E71EE9898BDC0296DFF0213DF30",
- "section_mic_hmac_key": "3FCF9C69A11FF8EEC29F52F44C472C0C57E91D443C1D2B26A83221567F02151B",
- "section_salt": "218C59E9A77F6C177DCD2A9773BA48AF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C6584EC834FED2E94B8091A8747BCD9C",
- "aes_key": "15ABEEF92C750250A1A76C68241634D5",
- "data_elements": [
- {
- "contents": "578A958480E03A34F8978B8260C9A13F9B9ACF373C",
- "de_type": 198
- }
- ],
- "encoded_section": "4F9013A3CDB9B681A52DEE1310B22F1931F9EB9110003F399980C680152865FD9279D977CC139002685C63C0C0E709FEC8E9EFDB7269397FDE1E43D2729F41D9C7A66DEAF2185B5765B530A92CE78B97",
- "identity_type": "trusted",
- "iv": "1EA030B4EDB3E3830E853133F5DF8E73",
- "key_seed": "4121F59F7C8155C2C22DCD541C2EEF8FA89E1A1D92FA6C92767E70EC828E581A",
- "metadata_key": "87C695F0A704AFB08ADF552F2D70D36B",
- "section_mic_hmac_key": "8BD01A8873BC672624A111614E646520593EBCDFAC76A81D40E3C1C268F89A0C",
- "section_salt": "3F399980C680152865FD9279D977CC13"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3F2141BAD98E79288895A150E295742F",
- "aes_key": "0A35AEB6BA80958F4FBA6475AEDC9C42",
- "data_elements": [
- {
- "contents": "2EECF608AAAAF0FE733CC5E2DBF178C7E39152E12CDDD772D65C417DFB",
- "de_type": 803
- },
- {
- "contents": "22A2C92D792B",
- "de_type": 103
- }
- ],
- "encoded_section": "5F90130F0868FBF386021653BA3FE7BCD17E87911000FE75240065FDF8EFC99C0C3AF69156E59002E707FDA0FF2BD0ECDB6FD388E6AD5FB47E69D6B787971FEC414F711F7360869018634A4857329A9B0AD295C4C755CB905EBFAC9A4C0B7BD4",
- "identity_type": "trusted",
- "iv": "049F4151D3FE5B124170EAAD35C45788",
- "key_seed": "2E09F6C972F988C3AEBE406A814ADCE1323861A409071CFAC1EEE755DF201202",
- "metadata_key": "D6AFFF9038CD3B4C77CE91F438BFA3B9",
- "section_mic_hmac_key": "B1F883D3A3806235308427AC61D723CE12A761C61069ECB1F10CF61558672621",
- "section_salt": "FE75240065FDF8EFC99C0C3AF69156E5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49B2915EC7A33D0286B5D856BC1C5284",
- "aes_key": "A417B26D49ECA18BAC18ADA35F74D45E",
- "data_elements": [
- {
- "contents": "9B0E237C78F6CB50",
- "de_type": 9
- },
- {
- "contents": "C94477AAA110FE809B62604500ACD0F7D414FFA49DA215",
- "de_type": 519
- },
- {
- "contents": "992B20C63A1A22",
- "de_type": 25
- }
- ],
- "encoded_section": "6490134B524B7F1DCCA091F7824EA36A2617A1911000D340ECFA488E4B8D5097BF106F8B829D9002D655120231B293EF93F1951FA10BE3255011D75CC2409DC37406396FB62A190F4EE6438A650B01A3EE155F192FF7AE7041676C38CB0DE0470D35B881B9",
- "identity_type": "trusted",
- "iv": "869A1EF9278163ED199CF9F9F137D4E6",
- "key_seed": "9EE4BAC6148531F711836FF331C1FB7E3B02B9ACDD78F2F88E8B0E40BE39DE24",
- "metadata_key": "C81343B9BED7BD4F0758950833314D87",
- "section_mic_hmac_key": "BA6A098387BFB88E2E4FEB012F726011F577FCA9E1349D7627A46B1B5EB2DCF7",
- "section_salt": "D340ECFA488E4B8D5097BF106F8B829D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8D17E72A1C35431FE9167E9BD17E0CCA",
- "aes_key": "8B6E188A464D1E549D5988EF874A9714",
- "data_elements": [
- {
- "contents": "65F9D53284B61B216C2FB7905A7E628A36D346F27E63DF03AD5591CC3806",
- "de_type": 122
- },
- {
- "contents": "1297A56F07B1E17644212F4E57043C1424A6FCA16610A252",
- "de_type": 427
- },
- {
- "contents": "0373709C74E1682A1293A7C96B026CD7667BDBC8",
- "de_type": 321
- },
- {
- "contents": "B7A7F0CBAC26EB1A7F10",
- "de_type": 240
- }
- ],
- "encoded_section": "969013135DE684210624C70AB737EA21E2BB2791100071D1EC0652294A473D35ECD597CC09C4900451B8461BB4330D89B49CF05D5D0B305361E41C5D0DA38B58335699AA3E806BC4CFADA43F344F49FF0BB77196236F8CDA9054F508DFB5144AA7E11AB860A0F4CE6F9D47237982D8DD5B3232F3627C4C4A55AD1201A865CE24D5C73E50BB704617AA4D887B7A75048D63F29AE2C31CEF",
- "identity_type": "provisioned",
- "iv": "3365A1592043B55C5C4144AB1D115066",
- "key_seed": "80F58265457937034CE0954435632A123D95EDA52237638197E60E3C3941CE75",
- "metadata_key": "95D1A7C78A1E4BACA51EA2476EEB81D3",
- "section_mic_hmac_key": "DAF584298F254B48279150416077F45F02EA517C3473AB034D7ADFFE3A670FA3",
- "section_salt": "71D1EC0652294A473D35ECD597CC09C4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "567BB8BE3AEB3C21E81331145E2A92AB",
- "aes_key": "A617DFDBC645514858FA32E01DB12BDC",
- "data_elements": [
- {
- "contents": "",
- "de_type": 487
- },
- {
- "contents": "6AA41CA7DCFD6CB1AC6A4318DC40FB83A14443F387C8A2466EC1CFD3",
- "de_type": 640
- },
- {
- "contents": "7B8F001428B90D600D00",
- "de_type": 965
- }
- ],
- "encoded_section": "669013885D0434ACCA45B4F679F4876DC80314911000691D3A0B07D7528440C9FE2FFAE11C0A9004C856B862CB0B81B4CE4355DC8D1D1938938C313D3481DC74949373CAC221012D4B0B4CA04035F045ECD631596E29947BBC2A20A796889E1C37CD64982CF41F",
- "identity_type": "provisioned",
- "iv": "895EE2C2AE3779BC94DD8312A6999D85",
- "key_seed": "F47E65BC805D3E68FEA05C8CCCE3D494649145434287E31E952646F2576DCDCF",
- "metadata_key": "F952060A084F9CBAA1567CAF63228883",
- "section_mic_hmac_key": "EEE4F8B3DAE3B3FCB134AD655DF92456239F559B52FA195085850A03481492E7",
- "section_salt": "691D3A0B07D7528440C9FE2FFAE11C0A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D5E77232628E33E4FFD9381E791689F",
- "aes_key": "0DAC17E78298ABF6982AD8FDC35407A4",
- "data_elements": [
- {
- "contents": "97DEABC3A327B8C4354C65700EFE47ADC6617EAE56B7D9",
- "de_type": 115
- },
- {
- "contents": "2E3A60DF71E005D1E519B5F1443D0D918845C0C621F0D877DF7C33A4FB44",
- "de_type": 579
- }
- ],
- "encoded_section": "7190134EBC1FB02A556EB545C3DB69A142E9B89110009FFAE095EE40CF7BAE117E7431FFA8B39002E91322121BEDB880976E910A1EA6003BDDC0B45400C07A141DD1E14271CC2912438B0B68EB80ED610E8C1DC4723EADBEF7482C8AAC2E723404EE3D4C88238FB9418A968AF469BD65A6AC",
- "identity_type": "trusted",
- "iv": "34DB2B5538C1F25E926D8191C5EB4382",
- "key_seed": "4DA9A6F59DCF615E03AD56258554641692E02CFEE284A5D0F0D90296490475F9",
- "metadata_key": "5B8F323279D4CC8CBE66DE149B267214",
- "section_mic_hmac_key": "D23649C4CBA96BD6413B049C07B87D7CE18AD6E60D68F56AF270E2B1E2DB97E1",
- "section_salt": "9FFAE095EE40CF7BAE117E7431FFA8B3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C167B8ECC498094A6DB33906F974F4A",
- "aes_key": "81353FC4DB19F1128CD2049615C0FA92",
- "data_elements": [
- {
- "contents": "EFAA10A500DA87",
- "de_type": 436
- },
- {
- "contents": "E3144711F717FD0853",
- "de_type": 956
- },
- {
- "contents": "522B257ED92E1AE819C77DF0EA",
- "de_type": 547
- },
- {
- "contents": "A78410D4E03BAC31469139B84654CBC6BA",
- "de_type": 483
- },
- {
- "contents": "4A1F996AD64441C85400AF32BE",
- "de_type": 549
- }
- ],
- "encoded_section": "8190132204DF3E53BEDCD51A7AE8F492F566D7911000856E7A66F236E9D930C684BD59B02AD79004641A35B7962DDADF14B7669FCA7CC36C1445925D48C45771B14DDD89DC594BBAD36C95A2A042D28D19979D698BB49CBFC43FEF03C89A80F392A9143C4C5D313A999EEB63C5C53E4DB0568E33770E9D2A9EA92C6EB2EB48224CF5",
- "identity_type": "provisioned",
- "iv": "5D8C4A61716F2AB552C717A3EFD049F8",
- "key_seed": "B92F88C4CF23C1798C1FCEBEB328D300930CABC7DD84B347EF1F0A57F8E44EE1",
- "metadata_key": "46530816FD06FF7D41FF0BE5A853A6D1",
- "section_mic_hmac_key": "ED64C3F6E9D7E11E0B9299EB0C33A6510B9AB292B01A3BE53C2D13F8D2D8F9A2",
- "section_salt": "856E7A66F236E9D930C684BD59B02AD7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C51E8816D92BC1E03CA638712EA09A95",
- "aes_key": "08C67FCA2B413C3C583437251B130182",
- "data_elements": [
- {
- "contents": "0713D3BB05B5FBA4B840171A21AF080166CBC082",
- "de_type": 193
- },
- {
- "contents": "E2736CB03ADB4DCECB1A316AED5F331044EBE44130138CB85970",
- "de_type": 766
- },
- {
- "contents": "2EC922EA4A01CA",
- "de_type": 582
- },
- {
- "contents": "9710558A43",
- "de_type": 480
- },
- {
- "contents": "",
- "de_type": 319
- }
- ],
- "encoded_section": "8090130D8F386275A65EDFE296E7D02E4D8A80911000AC100EAD10CF49B4BFA4BFD03D22DC619002F9B057A5DFB8A47B3DC1E369CFEDF5A03E58B49395A2E8BE6952AE63CA45680309ABBBCD65D77055FCCB901A657631B0B699886718542E5FBD2ADBC7413A956D85F3BCB6921A97641C74FAEB45E7F2483A6500034788190DDC",
- "identity_type": "trusted",
- "iv": "A7702DC73BAD3498B5AEE515BA94D38D",
- "key_seed": "B045094272F3A0C7248F9C2E7CD8A78491F06C05F08865B7B48418842EE56452",
- "metadata_key": "06DA134E75557D145D8869E8858407F7",
- "section_mic_hmac_key": "FD2E35B135B6EE46727142BCC2577ED5C53E5D0BF2E8817A05FBC8233B741EA7",
- "section_salt": "AC100EAD10CF49B4BFA4BFD03D22DC61"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "115CE5999BD1A1729822C11BBFFA3197",
- "aes_key": "606CD07F4B3B228E11BDD67304CFF94C",
- "data_elements": [
- {
- "contents": "F51C44D19CF610828FE35CA6D313255BED137D1CA02BECC8F1",
- "de_type": 32
- },
- {
- "contents": "085D8A1FBD42DEEA5DA9960B20CED595A8A220068AEE29DF",
- "de_type": 692
- },
- {
- "contents": "30322E279AF190D06F",
- "de_type": 329
- },
- {
- "contents": "FFCBA9466A7731EF8CC5DA9642FCFA6E",
- "de_type": 383
- }
- ],
- "encoded_section": "8C90131F34C598BA9CC85C706357897958835691100078884C8469817D638BB7387AF840716E90014A5B9F3CA8FD31B906F39867912E9E4472845E72DC24EBCC0AE3BC469DE9E82F365B8C69AF4499902EB14C4F4FD2FA87C7BB5444B524C96D546A69C6374B9EEFE8EABD54FEDA65F3F0A8EE73BC2B253535B32D25675B38FCCD9EBB88D4721D36B0723A21C6",
- "identity_type": "private",
- "iv": "879EE00C17EE3C3B44268DA9ED727759",
- "key_seed": "D8F2A8604FB68290CB810109695B7057A80A161AF8E2685FD099490654A82C03",
- "metadata_key": "16D27C779AE2F1C4F21AC121F734D4CE",
- "section_mic_hmac_key": "1B93D2DCA5350A33466639D852947667E54E09AEF3FAA193AE3677EAEBAD0635",
- "section_salt": "78884C8469817D638BB7387AF840716E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7A2FEC84BCC7D36821CBFDA1B8AF6BDE",
- "aes_key": "D94316EC0C1F3F5556B0A6E3EA44BAA1",
- "data_elements": [
- {
- "contents": "A18233E6470943CEDD28B316DD43F92E8B658D42BD4322F7E8116B",
- "de_type": 320
- }
- ],
- "encoded_section": "559013CF23E8E383098669E7F3B37FF2FAF607911000F1ABBD27DF8BA7CC017FA7E81AA40DD3900248488C1E48B090E1679DD3AE096446392E61E2E044F2464CC4FDB5EF6EEA1F72A5607A8F90CBDDA3E320BED67D6C",
- "identity_type": "trusted",
- "iv": "E27184AD7419FCA23E773896AD12FDCF",
- "key_seed": "B4C4197B892B450AE1AC96CDD612B7DAA67CF43DEA931691FCA75E067BEF9A9F",
- "metadata_key": "0DF12C45B639A4C469417723D0599C42",
- "section_mic_hmac_key": "87CD066A0003D6487925B00E6D3BB50ADA175AAF8FF4806A0E4A77A62D262D9C",
- "section_salt": "F1ABBD27DF8BA7CC017FA7E81AA40DD3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6EE25ECBB7A186290EB3DE0E054CA1C9",
- "aes_key": "5477F3FB31FF5E2ABC4EBEDFC20C837A",
- "data_elements": [],
- "encoded_section": "3790135229E15175751ACE1FC3D9E27815847791100012517EF20157AF7D7686300FFD93CA76900429A2EF5644E24A3812DDC9261EC4C8B0",
- "identity_type": "provisioned",
- "iv": "551FCE3922ECEA01BF57BF7855905D9F",
- "key_seed": "1BA73E4554F36779EE44DE6B9105F69DFF5D0EB3A148F671A1494E9070FF0C94",
- "metadata_key": "951796A7C33819FEB9A73F6C7AC70683",
- "section_mic_hmac_key": "F5858FC13AB364F8F7DBA608AB127EFF8C96B885D3A4750F4E77A6E6EC206E3F",
- "section_salt": "12517EF20157AF7D7686300FFD93CA76"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5AAD4B0F2A5F00FFB25C6289A53ADA69",
- "aes_key": "2B69E18B00F7C55BD2A0ED3BE199F17C",
- "data_elements": [],
- "encoded_section": "379013B003774586CD42E7AC66F5E4E31E355F911000ECA4F513378109DFBC32212674423D2F9004AF07EFDCAA038B74D585648EE9827064",
- "identity_type": "provisioned",
- "iv": "B39D516DDC2723FBA1B60D0FF63DB836",
- "key_seed": "8B69FF71E1BF629344A119B02EB326CDB7B7D3145657CECC390E2F81C1890907",
- "metadata_key": "C74ABEDA2BE5770EBEB1DAECF4C5E7BC",
- "section_mic_hmac_key": "0C5265739DE3730885F7C6A628C96C57851387ABEB914B75C16F8B6099CBFEEB",
- "section_salt": "ECA4F513378109DFBC32212674423D2F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "532E9FED397C96814EEAB6E1B27D4C86",
- "aes_key": "C45208E0024404A60F492DDB2C914191",
- "data_elements": [],
- "encoded_section": "3790135CB193ABAE4F297BDD49862D1F937ED49110001E90A2A86D1CA79E2F64AD39A5CA77869001526D432A5829C0283F24F39A9CA1F2D3",
- "identity_type": "private",
- "iv": "9CA827CC416005F5F30C3E170D482CE1",
- "key_seed": "1F991BF25881125FE75847D4C6F85BFA6392C2F8B53F1E7FE5FA893B023224BB",
- "metadata_key": "39CF4CD3AFD063272F5E540476861918",
- "section_mic_hmac_key": "EF468FFCB94D5466593B9B25909D4ED49BB1F5590A66FEE2A6956EA5FB2B8426",
- "section_salt": "1E90A2A86D1CA79E2F64AD39A5CA7786"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "20F33C7ABCB97FD1B01811347ACDDC19",
- "aes_key": "9C75B6FE554C7B132A95FE610239A5CE",
- "data_elements": [
- {
- "contents": "D9ECD7FDC3",
- "de_type": 927
- },
- {
- "contents": "C1CFCACCFA30BB3D0F84",
- "de_type": 486
- },
- {
- "contents": "CFE52999406CBAEAF0BC138DE8233B9664C10997E6F8902C1D",
- "de_type": 282
- },
- {
- "contents": "019E37A059275E31906C582B37C190F7926DD006EB4390CC",
- "de_type": 53
- },
- {
- "contents": "DB192BBBEC104BC6FD5884AF1FA1E86C4DECE0D945DF93E130",
- "de_type": 342
- }
- ],
- "encoded_section": "9E901377069C7408696D7960EA0BF71DEC6B1F911000674927D66F2947C6E6CFA19007F33A7A900263FB8DE4E5D01AD9B90E3C430689362C1FA797775FE1A5F6AA66B563AF190D6BC65F85F22AF2E337FC4B3AEB313E09E2A5F2B7583C504B37513170BC93F35C43D4CD9D02C7C5A9FCF66F83880160A769D1825AB2A1BE3BBBE69709D6649009DB70314C37D4704C7325A7C3E0D042BF8C0F6858A86F2769",
- "identity_type": "trusted",
- "iv": "75B00C025C3B6E74D1685D850286425A",
- "key_seed": "D483C3C44C959801D49A5D40EA8ED53C623A1C2E4366AA22DD2CE4D2BB2AEB65",
- "metadata_key": "B636C1D5060722295EA4D9D29D83144A",
- "section_mic_hmac_key": "409242248BD9F7B475BC0F055BAA93A676948BE6F57989769DF739717B56313C",
- "section_salt": "674927D66F2947C6E6CFA19007F33A7A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5FFFBB726259844316370AFED28E66D2",
- "aes_key": "E8B7530E124B7900B5281191D89BD73F",
- "data_elements": [
- {
- "contents": "5ADC8EA7781A428860082FF8D90439A6D195C7",
- "de_type": 452
- },
- {
- "contents": "0743",
- "de_type": 582
- },
- {
- "contents": "DA22170A8C",
- "de_type": 645
- },
- {
- "contents": "5D1B5ECDFE491D5171232041",
- "de_type": 267
- }
- ],
- "encoded_section": "6990138D6BAB5B944BE0BE770B03757B61DBF191100094F0DD055481AC91B3856C44C113C5229002AB5EE385FF4D8533458D5D1018B219406C7C016D3CEFD2F2D89FE06C32CA1EB5AE7E8A5954D0911C4A4293AAA0E3F88E9DF83F3EFD19EC8764E16A51B60EA20C822F",
- "identity_type": "trusted",
- "iv": "B673F39CCED213EB6880FEF952DA8F56",
- "key_seed": "F78D9E077004872A3050A6A3EA50B1E70FC3C6DE9E7F49F134B0AE9BE1738A2B",
- "metadata_key": "24085049DAFEDDDFD928D0E87A95F58B",
- "section_mic_hmac_key": "639957A7793CF45CF598A1BAED976AB2C127212C3C2925CBC11E1570AD73B549",
- "section_salt": "94F0DD055481AC91B3856C44C113C522"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6325640BF11B968B7C13063AB59A6F22",
- "aes_key": "5D2197FFDEFF298C4FF9FA541DAB065C",
- "data_elements": [
- {
- "contents": "F4F7C14E800989F15DEF6ADBEACFF1A1035B658234C91152C6C51C5F",
- "de_type": 157
- },
- {
- "contents": "86F2F7FE27446E08",
- "de_type": 555
- }
- ],
- "encoded_section": "6190139595DB3FD2DD731ABDD1BECA616687F7911000378134A082F77DA2BD4DBC13CD4A1C1B9001A8A5CFF56B235053651822983E68C5BD46F3B4020623A8AE59169CAEDA758AE87865319B3A8D3228CC4D04418D44F394B949B37815980338A7C1",
- "identity_type": "private",
- "iv": "AE588E4ED351B78564904D2E45354BF9",
- "key_seed": "A4DED14526CF6F5F984E8900D671B9BBAD83515521A53B9D420D2A388CCAB2F3",
- "metadata_key": "94583C4E13E8C9C9944ED50786D19345",
- "section_mic_hmac_key": "6F320F7C56B7436AF72F9DDCF837FACABF9D4AB713268225A72BF6E4ED4D56F8",
- "section_salt": "378134A082F77DA2BD4DBC13CD4A1C1B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5B662E491149B1B15260B320F4E01E89",
- "aes_key": "D4D334E6C506B1E46ACAADCB94AAB75E",
- "data_elements": [
- {
- "contents": "E45B42DBEA4552BDD8987DA3A9F7C474DD0B5D594704D34C",
- "de_type": 927
- },
- {
- "contents": "80",
- "de_type": 144
- },
- {
- "contents": "8C19",
- "de_type": 612
- },
- {
- "contents": "2AE92C14EC",
- "de_type": 278
- },
- {
- "contents": "5A3FB2F54F4399259685DE522D31C9E1E2A150A97F597B9DB51F",
- "de_type": 449
- }
- ],
- "encoded_section": "8090132B814D8B0438AE06E18CC62B190F0AFF9110000E7D5791602F29BE17656BADCED2A7269002C35227A826484C307A5FEAE5F5946DEA16A6512CF0C7E661C994CB23E31F0EA5A393FE3B7EE99BEEC02420C3DA7BC94C7E80CF5AA0FE0BB75BEE24632756ED3EC92CF64F9A2E7F9777403306D6995C1F32B1F7ECDC6037CB47",
- "identity_type": "trusted",
- "iv": "A31ECB0D9891D74FF9DDF376007CB629",
- "key_seed": "E50CD35171C69F53BB3631558F6A92B8D202FCB93ACD6C864DE9B1FB0D8A3C1C",
- "metadata_key": "E83B8B0FC3FCBC486C852EBEC880A253",
- "section_mic_hmac_key": "0CBFE4AAD62203251AABE57D06C7F8785CE7A8AB924584888E4B2E91D0BEA44A",
- "section_salt": "0E7D5791602F29BE17656BADCED2A726"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D4D3BEA3B13E0E8F2614716FB48F0D6A",
- "aes_key": "E05199F2CB435DEF145BB7E73344E9AF",
- "data_elements": [],
- "encoded_section": "3790130A196A0477DCA5712C2882BF02E4D442911000508CEDD68F1A6A9D7611F0A8BD14343590044945F0B86E7D957AE20C1B6BC7E86735",
- "identity_type": "provisioned",
- "iv": "6C41743B8B7DB7062EC670DAF6A61798",
- "key_seed": "C3C39B75D1D6402D67B7646996D02C1B3A74FE334497C43048D2433668AABF2A",
- "metadata_key": "62CBAFD9D46C32E325D99A83EB7C353B",
- "section_mic_hmac_key": "64D6C934EE6EAFE81A9AB9BD79C8374461550ECA553909391E1F60E8368E64E4",
- "section_salt": "508CEDD68F1A6A9D7611F0A8BD143435"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "57ED0FF15D76C4099AB899F4E418420A",
- "aes_key": "4E9CDD52C9055A07A3BC128358EFEE80",
- "data_elements": [
- {
- "contents": "779B8A371B9E8BB9D0CAD88505AA1D9A1ED23036A0C6CF572A66E139A687",
- "de_type": 215
- },
- {
- "contents": "BD5F721280FC99C1B08886",
- "de_type": 828
- },
- {
- "contents": "D6",
- "de_type": 810
- },
- {
- "contents": "347A48731BFA69103A4D0F",
- "de_type": 678
- },
- {
- "contents": "FE74379D142F",
- "de_type": 975
- }
- ],
- "encoded_section": "819013DC7D6CAD65E2DA625647E9D79B415C7C9110000500D0334277EB0134622CD78688B3DA9004BF86CC7D343077E7E560156DB988B4D44DD10AE2D2A9024C20BF5DB58999156BC086F7CD85517B70C08511AEAA9172C56150F5FE5EAE80DD4629EAE66D3B02042A5E0821FF37290FBA5216EFB2C2C01B812F339EB4D240DE59D3",
- "identity_type": "provisioned",
- "iv": "01576839BF9354E4AC4C715763D32CAB",
- "key_seed": "9713BD491A7DDA28161429EC8DD6A456D3A135A1E808DA30B4A55D8528776495",
- "metadata_key": "35B0152C9416B9C96E369110D8C6CF9B",
- "section_mic_hmac_key": "D12B6016B127A4CC62D2B1BCDE84CAF328626B19F24F3B770A07BA7E6AD9E9EB",
- "section_salt": "0500D0334277EB0134622CD78688B3DA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B4573C31F4F975EFFC728BDAC5734826",
- "aes_key": "71EFBBAEB4A0E65A8B25AD5D630CCF60",
- "data_elements": [
- {
- "contents": "",
- "de_type": 389
- },
- {
- "contents": "3CB055F06072",
- "de_type": 910
- },
- {
- "contents": "B7518C446B1576FD37BF85481B",
- "de_type": 953
- },
- {
- "contents": "B6059A5CDC56",
- "de_type": 792
- }
- ],
- "encoded_section": "5C9013FB6CB6FB8FCF17D8F4B5547D9D9FBCA2911000B55F88A79A4D2308C6C58ADAF22BF1CE9001FC6689DACF7BBD836A7384B5E25B4CA444990364955921DAFAE62CBA2953A472F8D06A177D1FC116BABCC99F564BF1773D65E8D964",
- "identity_type": "private",
- "iv": "54C25EC2FA8AB87ED1EC10ED342FFB3C",
- "key_seed": "47495F708FEBAF178EC2565BBCF981AE6AC35E1F8B721102A7337E061BC91935",
- "metadata_key": "C8013164B860618F36848811670EF929",
- "section_mic_hmac_key": "C5D4B92FA23796773094C596DAEA1B33219F2A3D7A64316765E41FD8D3E16BAA",
- "section_salt": "B55F88A79A4D2308C6C58ADAF22BF1CE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E4B5A27A27BE52545A47985B9E7672C8",
- "aes_key": "1CBEF7B3F2D0B8B543A8064D081887A4",
- "data_elements": [
- {
- "contents": "66",
- "de_type": 56
- },
- {
- "contents": "BBD48390F886FE3524BB7CBEEEC484C3E5F8AE56D6397507C986C64B3334",
- "de_type": 797
- }
- ],
- "encoded_section": "5B90138D632E4E4CF4342FF32A48179E3F363591100066577FA1CF451210A7F51FCB91E8090F900225745619E27544AC812B4E8A914870EE4DB218008E498D777469B12F683439BEEBB15F1D438CF9A2D065D13F7464BEFE7FC78487",
- "identity_type": "trusted",
- "iv": "B4636AC8670D445B40129E5AC546748B",
- "key_seed": "1119F85B101A1C2E50916D1D4EFBE165115CFA1D516BF6FF38E26AFD989AFF1C",
- "metadata_key": "07261A673092A6796C05396F34FB979D",
- "section_mic_hmac_key": "64CDA74FAE14EA9A68520991817CEB209D3842D1507C55E2398618E02F778686",
- "section_salt": "66577FA1CF451210A7F51FCB91E8090F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9B384D5C760F4D838C96CB5C1E9BB241",
- "aes_key": "1836C7B82C2B6EA947D8E012F116C09F",
- "data_elements": [
- {
- "contents": "D9976568115CB8BF83FCC86839E7FA5E6CC215BE1BB1",
- "de_type": 358
- },
- {
- "contents": "AD587B8B83B854A5F43E3A876649E31E",
- "de_type": 27
- }
- ],
- "encoded_section": "629013D20E8E8CB6A740C268055645992CD564911000237B1902E39CD0E962BFDC3C0CB8F2EE900260224FA07FFC1C8496F1B76A4206C6909D5F802F2B79F688223D656DEC755A01F5E27362E186B5CAE06E37E3AB1D0B3B1293BE67650D0F4377D7DB",
- "identity_type": "trusted",
- "iv": "2FA2BA9E498FD9F7357D16A77DAE370B",
- "key_seed": "602DE291FD9C7C12925034FABFECD98118C38F348372FD534786FFCAFF706400",
- "metadata_key": "346B99848B2B463F6693F235D874805B",
- "section_mic_hmac_key": "52D562B21447516C31566EB4C0C68A98C71630B24304B428EAC3BABE398A7AAA",
- "section_salt": "237B1902E39CD0E962BFDC3C0CB8F2EE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7E91FF05B49BE21AFC9F91A460ABA336",
- "aes_key": "B67FC30117CCE626887A7EE662652CD2",
- "data_elements": [
- {
- "contents": "D69E2C5653B9BAAFBC9D5C3EBC58D3",
- "de_type": 627
- },
- {
- "contents": "EA28DC05603AD928B2826DCA",
- "de_type": 452
- },
- {
- "contents": "9501D6E4E075570F383542CF6E8AF8FC",
- "de_type": 126
- },
- {
- "contents": "930EECF1",
- "de_type": 833
- }
- ],
- "encoded_section": "719013234A6B8D05D901CAA3BB8EC5EAAAB230911000DB399806753D8B6045C73A755B71774B9001DCA87E9CA2A023437557F2F0D4B9A5B58AB3D608D4498CC71DB3547425858CA2D7E5F1BB29387BE5FE9D3272768A65E1765AF706FA43BE09CA8B311B2B7C8B2125E7C8A4B52D1025AD5C",
- "identity_type": "private",
- "iv": "9AC108D06B463F055D49A91E14F2C8A3",
- "key_seed": "A3A8F349F07BB0F7447F51F661AF542D6904BFC6087AF67511A645FE8FCE675C",
- "metadata_key": "79B2212A99BB2CD43B34E2E1CA322B62",
- "section_mic_hmac_key": "9E7F2E3CDC198279843A86A60FF128B9F349C11E48B67EDC3158A9008C9C36F1",
- "section_salt": "DB399806753D8B6045C73A755B71774B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "26582E4CE5C251427F923630006AFCEE",
- "aes_key": "AEDEBC8CF8F3BC8DE853731DCA9E4DC9",
- "data_elements": [
- {
- "contents": "DD433F55AF726FD4794FA327246F6F2132E92E62D21D67A321B864",
- "de_type": 846
- },
- {
- "contents": "D122B1144A43EFF0EB",
- "de_type": 759
- },
- {
- "contents": "7E078FD3",
- "de_type": 404
- },
- {
- "contents": "61",
- "de_type": 461
- }
- ],
- "encoded_section": "6C9013D15EEB0F499029BD0116FEA1D3408043911000BF71BA034AAB72D7B4D362AAB499C78790029776023BBD26F7EAFC7B7928DD679D540975CEC90BD83475280C3DA16D23ECB642CB67456C25FA0F51560628DDED9F2D6662FFBDB54D11E57405825F77E5A34396BB7DF1A0",
- "identity_type": "trusted",
- "iv": "8040F7832AEB66320A2D61CB079320D8",
- "key_seed": "118711EA1D5E88DECC48D0139846D57F64A7C1B61315B1A287310948F8A7227A",
- "metadata_key": "51759DA981D7A83ABD931FBECED991C5",
- "section_mic_hmac_key": "1F08673E88B1D86CD3E152BF6C9E31A06D2CC05F57F9C877D03809FDA407518D",
- "section_salt": "BF71BA034AAB72D7B4D362AAB499C787"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6E2C7B1C5E818B1CEB5F7DE8FC9E5755",
- "aes_key": "DFEAFCEE8B8EE1F96CA60E271B6725F8",
- "data_elements": [
- {
- "contents": "113C3E2039C4E1C7418BA6BB55FA8BFA",
- "de_type": 366
- },
- {
- "contents": "3AD067F40A",
- "de_type": 823
- },
- {
- "contents": "811535BFE2A541B0961314CECD50D59374E1B30D08DC",
- "de_type": 763
- },
- {
- "contents": "16FB893BF2AFEA6DFC5146AD63BE92F84C5D2D88607E46A228BB",
- "de_type": 391
- },
- {
- "contents": "FBBC7E70BCE1D5B1EB183D3B9E62FF8E14065D94930390FF",
- "de_type": 382
- }
- ],
- "encoded_section": "A3901332173E24B194596D0A48EED7B9F048BF911000EABEA0196320B7B9C0A57A2E416746029001F85327E3300056CC3C0C0D434A64ADFEB159198EF001E2C778F56DBC1EAF9DB00C725E6688EE8812EB5DAAA339F4A9FEC3927310EC508FCA85C5D611C42DFBE9323EAA48FF38702EC1073C9C13B33BC2EB1BA89E3F233C1A326155F7B5745D05AD16976725672873F40CB030AD916DFF0A42EC4B84F5394FBEA97808",
- "identity_type": "private",
- "iv": "A9717CD38A876CE4107BD424D8FBA366",
- "key_seed": "1148504329B3B33FA44E2A221DFF6CBBE1CD4A52248B6A09A8ADCD3012750977",
- "metadata_key": "27856505C84E581AA1A6C46C6FA516F0",
- "section_mic_hmac_key": "DDE977E035CC76BBFA8A642C1F143CAACE972E3216BA65A7D75E984A14E5ED13",
- "section_salt": "EABEA0196320B7B9C0A57A2E41674602"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9FBFBFBF8BB497AB6444B41A2B58A6AB",
- "aes_key": "862A0A31E0D23BF6CC4E9DD3D885718B",
- "data_elements": [
- {
- "contents": "3477BE93CA3B096D960FBE16F63BA456089D872D76F3CD00",
- "de_type": 767
- },
- {
- "contents": "3D9B50F6ECB3F59931BB2C31A67CB18D",
- "de_type": 681
- }
- ],
- "encoded_section": "65901361778F70E6B5332529106BC5D0D796CF911000CAD36D8BE2990F1DD1BE5A8CA36725939002AE6B6909552DF36AFCC86E4D91C1FAF7ED62212D53C2B7F84E640B3E5760A41BD98F8A544F830A97595B8386EB3A27AE2CC178A5EE103CC275D404DA6417",
- "identity_type": "trusted",
- "iv": "783403F6FE6BA30DA746FA2708C4D692",
- "key_seed": "3942CF4816E8B430A03E14D2F94108C0A770891FB4E99ACD3D277501465BA68D",
- "metadata_key": "C78FBDDCEBF1A5384BF7ABC8064377D3",
- "section_mic_hmac_key": "94053E6382CEC871376151CBB9694C564ED767E1EEE3239C941D914ABCE92CE3",
- "section_salt": "CAD36D8BE2990F1DD1BE5A8CA3672593"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "55FF1F0BE15C17461B43BAB93500700A",
- "aes_key": "966B7CD205F081281E6E93C54EEDF15D",
- "data_elements": [
- {
- "contents": "D13D37512C791FB5ED13EA221EBA6950B0",
- "de_type": 301
- },
- {
- "contents": "6244AF57E139117455782A325E7E3D1C910FF0EFDFF03A",
- "de_type": 12
- },
- {
- "contents": "0E2D671308A90AD27AE72BD2C375CD2E1E54926A6DCB",
- "de_type": 571
- }
- ],
- "encoded_section": "7D9013EF0E9E3112F9F8052BFCD5095F6DA7739110008EF37B9F957E72577A88E3E6616B1F0B90025B8420F2A9242BCAFC847C0C4D389501339DF6BFA0C91B4BD11343632BB679D50A288118A92B0FD09C57E75E13FA0DAA5C2F77D107185487F1F22CFC2F9B664D30F6D386975C72B046FA237531D0D5AAADF79593B9AE",
- "identity_type": "trusted",
- "iv": "1A624B59ECF332000562C8474140249C",
- "key_seed": "5289A92DAA075E761F56E835F2DDC562DB148FE624E5C6FE08FA89CF5FCC9425",
- "metadata_key": "F86972B236221A5B1DB9EDA61606B299",
- "section_mic_hmac_key": "0F75B7C9F4CEBCB3D3CA5114EA5BBEF6A1065CD11CF1A401A7E3D6C2CEE85961",
- "section_salt": "8EF37B9F957E72577A88E3E6616B1F0B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "257A8180A470B26312484B49DB427FBF",
- "aes_key": "1A6FCC5E29E7D4BAF2ADE0428242C2EF",
- "data_elements": [
- {
- "contents": "FA0C8C637E390F8123345F41392EF8CE",
- "de_type": 556
- }
- ],
- "encoded_section": "4A9013E976A9B1B377C5AE53AB1396521D337D911000CD1525ED218139EAFF89E47A20B34D4790044DE380677DEA81DAEABD099BF7E04531DF12F3E9C7A9C1B5CEB919C9EF3567915FB74F",
- "identity_type": "provisioned",
- "iv": "2AEF9979665B18EA76574CF455B20335",
- "key_seed": "27AB5D93445CB4CEE55B3405325558636F198AED90C8E51836080F087A2E842A",
- "metadata_key": "7C1A8511E3B9200C13C78F9EA4E57939",
- "section_mic_hmac_key": "B1C4A104A63A1BA805D20818384EB39B6A440171D8C354424EAB9B6B7502DE77",
- "section_salt": "CD1525ED218139EAFF89E47A20B34D47"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8D49077EA04B6722167FF9DC3E5A5C6F",
- "aes_key": "1D3642C5B0338782485683BC113AD3C7",
- "data_elements": [
- {
- "contents": "0761DB68EB536A1ED11FF6EE1A2BA0B9859AC5DC206C",
- "de_type": 490
- },
- {
- "contents": "64DACC73432881300198",
- "de_type": 69
- },
- {
- "contents": "A2074C1932DACCD81D3DBA",
- "de_type": 213
- },
- {
- "contents": "E26C55BE99DFAE8088BE1A01890F801D9E382C5419E6EE",
- "de_type": 118
- },
- {
- "contents": "3D9D9009F5F0B28BAED466EF285DC30B93",
- "de_type": 969
- }
- ],
- "encoded_section": "9790133210E2BD4D3A353337D7ADF84E63FD129110003B8C8A598DE9C86BDF539187043684DA900206D1B6437D8BDF3B6EA83CFF14D82D1241F0019EDF8FD5F1710CA0A9AE469B7F2EEDF319626F11376E797E91FA97E46F82B54406D5C1BB3032165223FBBE1DEB996FCC3C9036B8CA441FFAFE8846277F3FF098FFACB231D8DA52C7997AC3B2CCF65A875747EB0CDD02599308A56C5B5B",
- "identity_type": "trusted",
- "iv": "8D7F69E96E0B0FDF5711FC3B55A01715",
- "key_seed": "AEF224AF0FB93E5306BE251CA4A2F387E5A5CC6630605B0A3E0C56D7078B679A",
- "metadata_key": "7DCC60F2F58A401AAA957CF76649C84D",
- "section_mic_hmac_key": "32E6F4E7934A34A459D136652114A9C0BD0A23AA4DDE36B51FDBF59C9A9AD9FB",
- "section_salt": "3B8C8A598DE9C86BDF539187043684DA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4E4ADE9BB0F5C4629AEA9E3F16EF9601",
- "aes_key": "95CB67B31D524CCC83FE954FE9D4E2BB",
- "data_elements": [
- {
- "contents": "A1BA",
- "de_type": 870
- }
- ],
- "encoded_section": "3C9013A8A3FE675DFAFB72CFC76C7833A5F9DE911000173AC3E1BA7DD39FA785C6E60BAED8C69002F3C038ED49854C212866A5AA075B6ABEAD7DFE458A",
- "identity_type": "trusted",
- "iv": "9C68198A56ECFD51E7F8B770EBC315D0",
- "key_seed": "5F5ACCD7667D18B16F2F816046CACEA387775372D3C2CA44290C17F083B0D8AD",
- "metadata_key": "D6F99ABC33D92064B46A910FCA2C4036",
- "section_mic_hmac_key": "3E1FF3C4491442BC4C092D3DDCEDF840451EBE6C3D3A438C79B079AE4241BD84",
- "section_salt": "173AC3E1BA7DD39FA785C6E60BAED8C6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "824423E2D4F67BECC3EF225445DB8976",
- "aes_key": "CF185400D6689B037B238F61B0F8159B",
- "data_elements": [
- {
- "contents": "3C304F6A2D4E030A1EE524588D6B890A278EA715D7E72DA1F6AC41",
- "de_type": 939
- },
- {
- "contents": "EC9DC0C94D",
- "de_type": 294
- },
- {
- "contents": "291621E7F7496B",
- "de_type": 704
- }
- ],
- "encoded_section": "679013E3EBF925B22D0BD4B57CA802DE30BD10911000433A9544240B8BEFDA531A895B5FC46D900266034C3D13145C66E02477FE8F718D1C475176016D59CED1DEDEEE6415C87933D3A6D137BD15079779E7CB0B172C0563C90C9A95ED56E0B171AA08E2AEF81C58",
- "identity_type": "trusted",
- "iv": "2569CB0445A6BF7291D567B280EC7903",
- "key_seed": "81E738D2BF50C258C1144AA9371826CD04F166B110AEE21F696D0F776B35BAEA",
- "metadata_key": "094A54CF97E267D0FDBC858C3CB5EAF7",
- "section_mic_hmac_key": "8C3E857F64C351326BB726B05274A8645176C8C8678C82E9190604DAC1841CEA",
- "section_salt": "433A9544240B8BEFDA531A895B5FC46D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BC9A5197755D9A5679DCC87B79E1C9CA",
- "aes_key": "374CF6450374370DD377AB35C40FE17C",
- "data_elements": [
- {
- "contents": "017B0CD8B639ED915D35886531E1",
- "de_type": 58
- },
- {
- "contents": "F66ECBCA7F402517158769BDD4E7D50CEBC2DF10F32E41911B510F",
- "de_type": 856
- }
- ],
- "encoded_section": "65901307620D1E9A1EE0D4752BAF1CE59141EF911000BAF72D3D61009CA97C8FDD9CCBEF10ED9001E882E442913D85A2CC21169B9257EDCEC72349678006BF72A6C7FD18C85BBCF02E9843BC4ACE539C23AE19D1A79F63EC8886B34A7A32091C8873921F61BE",
- "identity_type": "private",
- "iv": "B5DB29371481C403B0349A10A7E33855",
- "key_seed": "431919386DE84007C979116DF20230D0A60088C81C4CCE8491FD0CD5EF0C07E7",
- "metadata_key": "78F91A3FC436CE326988B3C55EA9B5E7",
- "section_mic_hmac_key": "B9CF0EFBF1F1F6CD77E6F8314FCB3DADFF55DE06B6B684E8739DD6B793BF7442",
- "section_salt": "BAF72D3D61009CA97C8FDD9CCBEF10ED"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "33F99E993A3416EC161F0044EC71B42F",
- "aes_key": "BDA1D8D59CFC0C0E3C0232944E5A82DA",
- "data_elements": [
- {
- "contents": "C0F5E75C8B80C62DA67A5834B00A",
- "de_type": 720
- },
- {
- "contents": "894B67C2BF3458",
- "de_type": 977
- }
- ],
- "encoded_section": "5290139B54D6302AB388F8B952001F3F233723911000DA579BCFC70266C882B420E1B122710D90018D8C89DA498ACF2DDD060B59D48A85249435080F054A5479432EAFD1089FCEFF46465BB7A63332561CFE19",
- "identity_type": "private",
- "iv": "F4DA1B762699DECE3FBEB755A3C8F7DC",
- "key_seed": "E615C6F1F6494D3CB1EFEDB1CA97EDD096997DDDB0F840FB4B8A9A9AD8FF68CC",
- "metadata_key": "9CCB7E17B8E4F311F5217BEE076FE193",
- "section_mic_hmac_key": "08A3425953011FB61CDF4F73BFDF0FAFD337C6192847B028580392CA1920BDE3",
- "section_salt": "DA579BCFC70266C882B420E1B122710D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4F729B7E8A3DA79951DB474393B34C05",
- "aes_key": "D4CFDC392B5398DA8EFF9761AC883BED",
- "data_elements": [
- {
- "contents": "7B3D33709DE248C8C6E55A17681634BBD51B9AD16CB70AFE732D434F73",
- "de_type": 950
- },
- {
- "contents": "572C1E1284C61CD3191CA7FD48278E69A871061C",
- "de_type": 519
- },
- {
- "contents": "F26F1FFF732399534BB9",
- "de_type": 462
- },
- {
- "contents": "25D3DA009DF358AA2B1502B102",
- "de_type": 760
- },
- {
- "contents": "696815F62069A011E27DB2B6",
- "de_type": 116
- }
- ],
- "encoded_section": "9990133BA7F84BD37A8ECFF8991F41816603D9911000A24D83B5B489290033B0FB399D50278C90048830A62074CC528A053D57B871559B428C52947FE6AC380E6C409A9FE4CB2C778D396C9EB33D284ADC7AADB7FA26F64AD1E77EF8700C7D5011EB4188B8EB69C6AB8B247A3A408C296E0E9505DED7DC9B6B81B6AE18BDFE328F76BF28194F1C9FAACEA61A1305D8853B62E00E92B3B5DA906B",
- "identity_type": "provisioned",
- "iv": "27D31B8F040B8147F00DBE3EDA8DEB3A",
- "key_seed": "E4ECAB1DF51BDE39E140E09E592023B0EBB70D51EF925AE06F55BAF1F232F965",
- "metadata_key": "A74B0FB29ACAF1F6DCBF1D4B80D05D7C",
- "section_mic_hmac_key": "064478CDA8ADA4303610AA070F13AB89C7FEFA11044EB17C620B4843A1D2B185",
- "section_salt": "A24D83B5B489290033B0FB399D50278C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "532A9B509151D3891A89EC8122177A00",
- "aes_key": "65CA1FBDA266B5CC1F687F05BCFFD91E",
- "data_elements": [
- {
- "contents": "28CAF4164DF090AF",
- "de_type": 267
- },
- {
- "contents": "2BC0D162D9A11B1592505DD0A88C222E3A05F584",
- "de_type": 344
- },
- {
- "contents": "5F0BE74A54E9C769E93876",
- "de_type": 663
- }
- ],
- "encoded_section": "679013D6A5733B956C24C026EB4CD77CD241FF911000BA40F9A069E1D2864028AE47BC7FBF5790021A2F29AF45309E075686A17B858A7453DE7F746B1A9AA04C68901F0BAEE8474D84BC96034338542D2FCA389DB128BEC31B187D96C2A7BA001B53B5F3E4B058B9",
- "identity_type": "trusted",
- "iv": "3B7CD74E54AFBF2903999BDAB75C4E77",
- "key_seed": "65A6D38463734CF87E73D55D9695658B0C08ED9F35838884F08DE839C224AD9D",
- "metadata_key": "DDE0C29AAF70BC5299D0945DFDB2A320",
- "section_mic_hmac_key": "5E63974EFE6650031F0244E69A2533ACCEDDD75479D939E5DCCDFE355FFA52D0",
- "section_salt": "BA40F9A069E1D2864028AE47BC7FBF57"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D5487414BA08F69CE9D13560766378D9",
- "aes_key": "4597450D328A4398969C6984A4812726",
- "data_elements": [
- {
- "contents": "5594877DB8046C",
- "de_type": 749
- },
- {
- "contents": "D49D19549FA675ECB739E031",
- "de_type": 1
- }
- ],
- "encoded_section": "4F9013F87D55A4AA36BD81DEB11033F76E60A9911000F948EAC4A61D540FAF5BF958C0AA15029004969211CDDBF8AE4D251A89A69378E93D41D2C6E1FAA39580C4606EE81B99B2F7146566D5F3A2D187",
- "identity_type": "provisioned",
- "iv": "7251B83564C131AEE0ED8E7D4B2657B3",
- "key_seed": "32055A58CFD37AC838F8978ABEDCC2A30BC8752D9985DC4F24AA8010B4855B06",
- "metadata_key": "1C85CA810627CA299F3E7C5D8F2CD904",
- "section_mic_hmac_key": "20D173254B6DF487603D339E1BB394DBE0BBF19F4680F2FD3DD3EB3E389215EB",
- "section_salt": "F948EAC4A61D540FAF5BF958C0AA1502"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7443AED9489E3C74C778C996DE9B67C3",
- "aes_key": "D131442579CCEA76DA56F4E5171F09A6",
- "data_elements": [
- {
- "contents": "C879C6B33BAB741D400BB9A06533672BAC016E",
- "de_type": 367
- },
- {
- "contents": "5ED5",
- "de_type": 783
- },
- {
- "contents": "0C31C60E1A246200DF872DD766E501",
- "de_type": 288
- },
- {
- "contents": "38B9BAACCDD2C285CE1DD7D4C101E8FAF4DECE26190B08E1942D71D30434",
- "de_type": 835
- }
- ],
- "encoded_section": "859013856E63F667D52C056607CD1EC8638385911000E3196F7725B52982CA91690DCCAF3D15900132BC6722DBC8E95809378C5569E0FBBE845D96271B645007A3D4A698F25B8A816924D66453873D49313DDFDDD5158FF1A9C0318C0EF5CC5604A58C9E6EA95E2DFAFD40939E4DA0BC33B5DBB471A83773D6E1CB927E79C0509447CB9291D2",
- "identity_type": "private",
- "iv": "6EF81828124A99A5798762BDCD4F0CA7",
- "key_seed": "01281A1DCC6627FB7336A190C0E316C0225EEBEB3DAFD6E79DF86BE811EB5B1F",
- "metadata_key": "5DB0440215FE4B0B403027E82DD05BF1",
- "section_mic_hmac_key": "FD0BCBD301B26D355985422BC65A0414C2FF451AC7837EE31DDFCE060E6F76C0",
- "section_salt": "E3196F7725B52982CA91690DCCAF3D15"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "01CDD6964C7DCD733D0365A455354A94",
- "aes_key": "F9EB800C6E2AB6E3457E3DADDA4E14EC",
- "data_elements": [
- {
- "contents": "05013630B53FA97478A6B3B4E9617A2B35C4200EA5D1B29D86184A",
- "de_type": 161
- },
- {
- "contents": "591FB0F89D67D7B2FF2FB27D6B8C",
- "de_type": 821
- }
- ],
- "encoded_section": "66901370C473297041FA4A4260B3995CDF0851911000BB3A62B2E753295B664F3C1B06172B33900186CB039689830CF401848577471BF720CB31EE848CA200D7705C87C3EEBEF421399B027060C18731B7FF977CCB90406E7BFDF0A4D389D6EFD11F426B89B35E",
- "identity_type": "private",
- "iv": "2195E6D71AC6C2AE69D6DC7E7440FCDE",
- "key_seed": "B9AE3932FF811CC014314D266D048E145DE60956DA53BB98D96CBBA136314389",
- "metadata_key": "F43D7EDF61357AC7B512D6502D5F1EC7",
- "section_mic_hmac_key": "5685062CCF0CF66F8EC8F0601442AE4FF9CB028F7F693235555A7918B83CDC44",
- "section_salt": "BB3A62B2E753295B664F3C1B06172B33"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "201E65F2C73E6749E104294C5B80BD0A",
- "aes_key": "9FF2BAEB97F201967B41A9001556C782",
- "data_elements": [
- {
- "contents": "42AD133E97FD6C468A8BB259F4FC05",
- "de_type": 673
- },
- {
- "contents": "D7B8495F3785063C4A4B988EEB3804CC5E7040",
- "de_type": 973
- },
- {
- "contents": "FA600360B5B21558266D62",
- "de_type": 30
- },
- {
- "contents": "6E90096C876401A20FD96E0A307C57C08893C533C3013A894380ACCFAA",
- "de_type": 176
- }
- ],
- "encoded_section": "8C90132F63EC2519B043C70FF4BC0AEA11B040911000B950743AFE9EA5BD4C03AAEDD3D0736C90044510CBC7D4252D98D4AD42CBFDF678C7D2A145E3EBF06D19FD695399D65444D16D7208A4E71B6CD26FAB2990E0A1F7308F5E2B73461BB7D81BD86EF287D1DCD3467F846DB7B9231F17C535082924817941954F82B95791BFEF9530BEC4D3177495EA68B59A",
- "identity_type": "provisioned",
- "iv": "3A32A1543E3241B3C6C7D7C40430B793",
- "key_seed": "8E5C4D3AC2D07C2092CFE2D34E54C63A572CD8187316161E3DBC78AD90F8353B",
- "metadata_key": "6389D90BE57C99D0147423C3088C8433",
- "section_mic_hmac_key": "421BC7BAC32D064027C7D3A5609CDC742FE9988282040A0DDF07BA67FED68DBE",
- "section_salt": "B950743AFE9EA5BD4C03AAEDD3D0736C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BF4149101EBD062FD66BB8A15D8D97C4",
- "aes_key": "D25E758A7A3B45C004D6CC5D04BA496E",
- "data_elements": [
- {
- "contents": "6E73EAB3E73F8231F2E9985E31B82C1DE362F26327FF355E45",
- "de_type": 457
- },
- {
- "contents": "173120937001D3979F203D7008E83A2452",
- "de_type": 115
- },
- {
- "contents": "D857E0E0C4FD3A32A4167DE23D9F4B67",
- "de_type": 989
- }
- ],
- "encoded_section": "7990130DDE44464CAA38BDE84281442900A8509110005ADFF0C03105B2B399A18E9B17168E6D9004AE5A46E81D5F0C9569137015FDEA89BB572AC008302F09D2AE7BB332431A38B0034756E35370BB6F6408594F8CF8898565D4C7C985124484911ADAB72BFF3DA57A6D37618AD5EDB2093AF1C05C186AC624F3",
- "identity_type": "provisioned",
- "iv": "22ADBBC7329D0E519D5F94A63E763E74",
- "key_seed": "FAF2516570FE1256279CD47301C50DF52C2327E6DD7A5653AC6231CA6D788B35",
- "metadata_key": "350488F862C7604DDFA0272A3D21B786",
- "section_mic_hmac_key": "D2824640C9C9593142EB2CFA6E58AD8E4B6A27F97422A429DAC36D0FF98DD312",
- "section_salt": "5ADFF0C03105B2B399A18E9B17168E6D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3DC3253CAA257609187D246F31331F3A",
- "aes_key": "73A354EF72BCC07FC9473B64843E5669",
- "data_elements": [
- {
- "contents": "9835B7634A82F3DFE1EB3B0D25EACF27B111",
- "de_type": 786
- },
- {
- "contents": "AE349EDFD372502D738B6CE186BD30A24BB77E",
- "de_type": 462
- },
- {
- "contents": "27A1F50AB7CCEB9B0D69DE538604F8957E44EB05D27608",
- "de_type": 570
- },
- {
- "contents": "FF7EBE",
- "de_type": 960
- }
- ],
- "encoded_section": "82901331D537AAB3FF00D04936F0A31A2FD4499110006D7E10C60B7F564BD819EEF42810D82290015B0B2252207FC9225CFC1A3E91FA6BCEC5EE55CBC4B9D4CE2C809C666602339E88B12F6A145C89C06C744499988D39A8CF69A2C73B3625C54DD58A74DAC3511558EA11A36ACF302DB6FBC1091E0018672C1299D834A56FE53E6562",
- "identity_type": "private",
- "iv": "82F350EB514C88202688646DEADC2AE5",
- "key_seed": "B7846E30DE6251075FFE9DFF3EF493655033CE4DA3721204249FDAC0FEA81EE4",
- "metadata_key": "D6848E0588A7653DBB03F88A3984F6FA",
- "section_mic_hmac_key": "EA643D83A79705A66FE8DDBD3ECCBAF88E3C1F80B68C2C406216F65CD1A232B8",
- "section_salt": "6D7E10C60B7F564BD819EEF42810D822"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E31F9F8EB3513BDFB44EF96AA620AAFB",
- "aes_key": "4258A9B2525ECF4A5E58E1C2A9063DD5",
- "data_elements": [
- {
- "contents": "ADF8FCECA7E191B3517BD0CED3",
- "de_type": 968
- },
- {
- "contents": "B87EF036921C2A821A7F1870DE5322CB54C78317881EBC0464EA4CA53C",
- "de_type": 932
- },
- {
- "contents": "EB",
- "de_type": 660
- }
- ],
- "encoded_section": "6B9013F16715F33E9D6F1CB228C7980AEDBF909110009EF4C8B8957C9963F83740019009F8CB9004BA838E0DF9D06746AE2BE8D725EA825AEA40D89326B71B94F0182B2F1187359CA49DE5B68FEB2F489617FBD98183BD84D2A015061EE9D1586BE943BB3AF7631C2BFFEED3",
- "identity_type": "provisioned",
- "iv": "E4C0765EE932EC49F352EE800E95BF09",
- "key_seed": "39F40C082855D864F9EAD4D2E01AABDCFB3AEEA2D6E3CF8BCB5319EA1AAE1C5B",
- "metadata_key": "BD48F853813C1365B9D7E7B62FF934B5",
- "section_mic_hmac_key": "9FC866D3FA1D25D6A429BA6E8D8BC12C64860E5FBFA2995B6F5C27C3D8C7B940",
- "section_salt": "9EF4C8B8957C9963F83740019009F8CB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BCF433EB76C6DC46D6E21B55EF890A62",
- "aes_key": "4E79EBA2284EEFAF313F7ED5BCA05ABA",
- "data_elements": [
- {
- "contents": "D15571FE1145DD2C7490910BDD0C",
- "de_type": 910
- },
- {
- "contents": "170565A8A4",
- "de_type": 762
- }
- ],
- "encoded_section": "509013C3275F9959C9B6B3984A4D9D7ADBF846911000FF62C0D98902FFC817A5262C7AAEFF34900297B89286BBE1563519BD6A4D344DA0D02A56227C8F15BD7419D3191EE89E07DEDAAEA2C80F44A3BCAC",
- "identity_type": "trusted",
- "iv": "337A5A9380E964FA6BC47A318FCC34D3",
- "key_seed": "E7166D09CDE23D2758F900FE5256262B4E9854C004C565E86240856C6C9C5936",
- "metadata_key": "7C7DF4DDE672B397105EDFC764E8E659",
- "section_mic_hmac_key": "2DA615C9E80E2528B13F1EC95860BA8BFCE20D5BB09B3B60FA9CC4429AE7B58F",
- "section_salt": "FF62C0D98902FFC817A5262C7AAEFF34"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "944EE800BE99462E7D2CD5B33FD5E63D",
- "aes_key": "567FDB0D6E7E46FA89779F09423DAAB4",
- "data_elements": [
- {
- "contents": "BDE03470416E865C3BABD4",
- "de_type": 462
- },
- {
- "contents": "D6CCF4C7C2F63DCC143C3D9DE7F43227D61E670D42C8B68180257EB370",
- "de_type": 128
- },
- {
- "contents": "20C72E3A955F310EB699",
- "de_type": 101
- }
- ],
- "encoded_section": "71901353E7C27131F33499622E7CE6CF74E3A391100046B0B64F499BC8A30778C7EE5E5D53C890045B77D7B11E140D541F75ED8F022F45EE22DF1E033AB90EFB89C5FA7EFE75869168A17A3E5923DFDEF8E94BD2714B039A98FFF4C834E4ED222C88CD29501B34BBD59E294039D5D8AAC305",
- "identity_type": "provisioned",
- "iv": "429662A647C2A5C874388D09ECBD3863",
- "key_seed": "B08E79ED71A776EC7A12D208D40263839BCA251400D223DD604FB46006B16016",
- "metadata_key": "3BC1E5BA014BDC2F3E86557B27439B42",
- "section_mic_hmac_key": "3C3A1354B81E8F4BF020D00025F63B060526C77F98F41EE759A002AB5E80BAC0",
- "section_salt": "46B0B64F499BC8A30778C7EE5E5D53C8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "40C50798CB6B90E84B28C2DA92DEFE6A",
- "aes_key": "E9EA2C7ADF7FFD2FF4AD9FE602B1FC1A",
- "data_elements": [
- {
- "contents": "B8C8CDEE",
- "de_type": 793
- },
- {
- "contents": "9A",
- "de_type": 749
- },
- {
- "contents": "E449D3660409413C63",
- "de_type": 588
- },
- {
- "contents": "BF5F66ED2CDF72FE206A9E",
- "de_type": 52
- },
- {
- "contents": "EC62382023B21EA450983368754FE9B2AE",
- "de_type": 39
- }
- ],
- "encoded_section": "6E9013C9617663F4A258ECAC1D10242CE9C20491100044AC3079A59D58FE95ACACC78E24D4CD90015F59D0C643A5B519A0B0AA437E113BA30E055830AA3D8DFDC8B0CE7BC4F01FFC4472BD93362308715535B643DC58C7C9288EED97CA0687EBC5AF4C2DD4E48464B7974101F424E7",
- "identity_type": "private",
- "iv": "0E0F84344052E7671CC153002EE1CBD9",
- "key_seed": "15F230069139FF86FBC71850F7AA9275ED0BA1A471AFDD4F6F4F32718FC180C1",
- "metadata_key": "99FDD5669D2B0D5F466C202F80898CFA",
- "section_mic_hmac_key": "F933F36F11D6751204A7D4AA5D00F6D930CA7947DEDFA8E588AE32CDC50355FA",
- "section_salt": "44AC3079A59D58FE95ACACC78E24D4CD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C39D831B39DADA8A4D2FDE8CADD7AD5A",
- "aes_key": "40777A255D48F7182CE23A787B7C5765",
- "data_elements": [],
- "encoded_section": "379013F6D0187446372B4CEA0E67575D4EB9E09110001ABDA9EC38BF3FF2C4E6CEA7CB296FAB90021EB5EB4EE1AC52FA36C007F242C903B1",
- "identity_type": "trusted",
- "iv": "8BF471907B22592267F1C653662E40CB",
- "key_seed": "630FE25E7432AC0D3A4DF3B2FD196CA8B774674B7F65CBC1B7EC8C680EDC88DE",
- "metadata_key": "CA7D44E7F05D3FE953991E5E2F4F65E6",
- "section_mic_hmac_key": "3EE2C708429DF966A211FEAEB99AC02D4B4F88A1AA6D1B3350E0E72D6916472F",
- "section_salt": "1ABDA9EC38BF3FF2C4E6CEA7CB296FAB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "97552E387E6AE7F19813273C95BC98DD",
- "aes_key": "C6F2E67244DF14B25370D81999B3B703",
- "data_elements": [
- {
- "contents": "48294D8737F6689CA1224806F2BE96746AA3F7E9",
- "de_type": 281
- },
- {
- "contents": "046A03298AC6CC74C9875F01C585EBFA285FAEE43330",
- "de_type": 662
- },
- {
- "contents": "5772009914B0F7D03D99EF3848500E5CE2CF1BB8967A4802489DB999",
- "de_type": 294
- }
- ],
- "encoded_section": "86901375877260F8680F64A523EAEACB6A70A6911000C9BED517D11AD9DE1BD79769B4BF1E6F9002B350E0DD7516F6310B5565EF2CFC16FD0F7ABB3C9672D2A4273D874DAD2A50F90B827E7DD2D1F3144E9F44CA56A8F5B8CFBC080004EBDEBD57572915FC3B3ADD1722FECF6DE45A91F1E383F15C990E22790A81DACBD72D7664F3941D15CF05",
- "identity_type": "trusted",
- "iv": "9343721F3C8067E079543B212BB2889B",
- "key_seed": "02AB71C90D39A12A244CF71B024542CC16A83A213203F410FB5E68A9E047C59E",
- "metadata_key": "303F6356D15193128F6E6B381E88EE17",
- "section_mic_hmac_key": "4E43FFB12A718E30D9F2455E985C46D0998D11D65E84CEAA3DF88E5012AAD482",
- "section_salt": "C9BED517D11AD9DE1BD79769B4BF1E6F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "71BC9ADC29579DC8A0E0487EAA5230A7",
- "aes_key": "9620661A0AFDB63AD16819514497C47E",
- "data_elements": [
- {
- "contents": "1C1A3657E3A21392",
- "de_type": 220
- },
- {
- "contents": "6C9F1CA43BCFAB1857D7805A84E4A516FC4D9E7C9678DDCE",
- "de_type": 740
- },
- {
- "contents": "089BE9",
- "de_type": 171
- },
- {
- "contents": "331FCCD6645D0E6C2FDC35F3AF3AF969F2FD0282A81D061DD11111EA08",
- "de_type": 645
- },
- {
- "contents": "60A8B144593D90FEFD6253F416B570B8E55F1BBE4A5D",
- "de_type": 986
- }
- ],
- "encoded_section": "9C90139CA48B7A14644F84BDB15949D54E4D929110009744CE2971F1B4E26F8073C4B4849A10900130945DF1008EF4B256752CAC699B2CBCD0A736335A415D81671FE6C4E62E1AA6721CB7B9A862FDE44D4865E8CA00D9689848B19ECD766EF2612D73BE4E7DF50E81C75FA990DD295777F5F9D4B89D619023163C2ACEB31EE43CFCDEA866EFA0F1F98DAAFD0097DFE4564D5158B26EDBF3943E7D1624",
- "identity_type": "private",
- "iv": "7D0C9BE18436626C75E5F109E9FA6505",
- "key_seed": "06AA79A2060D335E6035AFD4807E33B665C0AA91D672258386D3C8A18BF62730",
- "metadata_key": "7011E726D054C8F0A3AF0A64CEB3C04D",
- "section_mic_hmac_key": "FC9ADB7DEA9F8B9BC8AE7EE4E37290FBE67F49938209F722BAF94F00F5AD8A3D",
- "section_salt": "9744CE2971F1B4E26F8073C4B4849A10"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "96AE4A65693FECD0AE7DC294E815285B",
- "aes_key": "766190BC62AA978ECD78A5FB1B9393AC",
- "data_elements": [
- {
- "contents": "E2819425AA7B8D06E07D12EBAA19",
- "de_type": 112
- },
- {
- "contents": "668F51765E67802E8D947DC83432A82F4F9FCDC3FE56DBEA",
- "de_type": 997
- },
- {
- "contents": "9F",
- "de_type": 189
- },
- {
- "contents": "B7A803AB085D7464012E7141C92759CD5ABB1D5EE20252D40B",
- "de_type": 910
- }
- ],
- "encoded_section": "8290134C5FE3E874324FF0481B9CF6C7BD23DB91100042F06DF6293FE7CF1755C951BE41DCA190029B0054551005D376488CBF35207D28173DD036E39F6D2DB18CEB5F87FA981F7695589EA3C6CED88CA59C664CBA7F19F5AEA26ED8B819F1A98A2290E8AD88955C9B1CE698BA709C76E66BCD3E0EC22BB6AEE6E2D45619A100FA717C",
- "identity_type": "trusted",
- "iv": "D5A0D32FD5106E9435882D01E1B6367E",
- "key_seed": "1D64C492D1FDA772BFB5BF34A65A186C4571F0B131A19A15C40644C5D597F7D2",
- "metadata_key": "18AE245FF683EA4D131CB3B9CBC5AD5B",
- "section_mic_hmac_key": "C147044183E1BA4466D363443FFB1F6868D7B9B52D128E702757AF3A8872E2DD",
- "section_salt": "42F06DF6293FE7CF1755C951BE41DCA1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D6A98C7976ED88F4776F57E55051BA42",
- "aes_key": "D6F42BD59A9A4D83D113E168F945476D",
- "data_elements": [
- {
- "contents": "33E7567D2554B29992ABFF5F",
- "de_type": 733
- },
- {
- "contents": "1CEB66A7934CD81BDE08E0B4C68F418C",
- "de_type": 235
- },
- {
- "contents": "221A4083EE6BD86567C08EE459ECAF0592714C08F3C4541C254EF7B1",
- "de_type": 664
- },
- {
- "contents": "9802DC6EEC151819FBCBD2208784FC5F45E439518A33BA49C30C9812",
- "de_type": 700
- },
- {
- "contents": "F59E9C167060C57F524B06FC2CFE8C30B7C245A5C9F02657EBBC2E7F",
- "de_type": 938
- }
- ],
- "encoded_section": "B690133CE3C2FA05766D5CA1A3D5EB51D94E5B911000C154515607DCD6F34C441B78BA3E68A2900155F5CC8E4A8A8E627FBB74C83F67F73F72C7B6F84B5897C890D28B73C4302EFD9EB62782B56E9D0C9F64B75CE36FA88E9C912A29CE40AE572A564E74BE9DCD07E0F252C228F235DFB4CE51B033D4D93BB28E05147464D77673CCF87AF583F02574484839C5407D83B93676066F280BD2E62E586A465D1D62AD7CA1902CD7FDD1C69ADC1A99A85BBD1E56BEA1F7B6AF",
- "identity_type": "private",
- "iv": "8A66F137E1DD93ABF2E6F8DB8E5629A5",
- "key_seed": "0ED34984F8608A1ED2420168D3E39EAB29CAE89E6E00F577A2FE2435E371BA8B",
- "metadata_key": "6D78B0D9464EF03BAB914959BF7471D3",
- "section_mic_hmac_key": "F77AA75CDBE8F413D63FED4997A9DF7B110A1EE1238ED913DEB1510213F82FDB",
- "section_salt": "C154515607DCD6F34C441B78BA3E68A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95D42E733AAB2A8F4623607AE3AAFA1A",
- "aes_key": "307EB5096605C93D74051BF3019140FB",
- "data_elements": [
- {
- "contents": "CF43",
- "de_type": 272
- }
- ],
- "encoded_section": "3C901309D2D105A3900C7562AD0B847A6BDCD2911000719CA000E206EBB7E414B1F331D8879790017D362D435E3C563734593A7A7A1F6FB1DEDD3FA0A4",
- "identity_type": "private",
- "iv": "CE936BD2A93680E285FE69D3519B37E5",
- "key_seed": "3CACB47DF80E06C8E73F10B1CA40BF090558409363E97E32EDE98ADDC25B7948",
- "metadata_key": "70936418E7BFF920321C1D1B1E22E5A5",
- "section_mic_hmac_key": "37593B2D5BA45C77CB0E2C19246AF6FD05B182409983BE087D9C100BDCC2B7DD",
- "section_salt": "719CA000E206EBB7E414B1F331D88797"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7C6A5E9D266FBE338500EF4B1A9AE1C9",
- "aes_key": "37B697BF854925E9E7CA558956992E29",
- "data_elements": [],
- "encoded_section": "379013BACA5D191A040F13B2D30C356C3C383E91100026E263D75F5CFB71AAC091E648255C629002BA53540471CBE7FCAF7339225583900B",
- "identity_type": "trusted",
- "iv": "88A2CC9AD86FE18152AEDFE96F0264F7",
- "key_seed": "666B0E3B2CE558955F83D1992C4F3CE552B1591BE1FBC39E7578A33D4A66015B",
- "metadata_key": "9EBB6E6E93A85AAA2629A791B4760394",
- "section_mic_hmac_key": "8FE26D7990CF7ED06F5FD77E2F78F5D99DD08D6F366D2C6166286A8C92478306",
- "section_salt": "26E263D75F5CFB71AAC091E648255C62"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F8170168CDB98E6054D980DC4F486BB3",
- "aes_key": "A723C83FFDB884866843D23669DC6225",
- "data_elements": [
- {
- "contents": "F7844444403E9C",
- "de_type": 782
- },
- {
- "contents": "8233B24F5F14FFE07565AE42",
- "de_type": 69
- }
- ],
- "encoded_section": "4F901345A324F37CB55A5C0949CBAD49CC11BD911000668B8E44F0078A09F12829F40AD701F79004F968AECCC04CCB53902EA8B7A9AB90AC9D3507DA5708488D8A6D1A681DAF59454152EEEA00D55441",
- "identity_type": "provisioned",
- "iv": "FD415093D0B11FCFCD62D5EF7EBA2EB1",
- "key_seed": "1661E1DB8407DDF7EB6909B99391A568FCD11321E9D340BA2C5D3E802753436D",
- "metadata_key": "443844D2B1B640CC1C9A4CB862BD5B5A",
- "section_mic_hmac_key": "CE882FC63AF0978CD195CB6DDFA2FD4F77162F138567CF2795776F32B834D7B0",
- "section_salt": "668B8E44F0078A09F12829F40AD701F7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7F1798862045B2359834FBEFA172D80F",
- "aes_key": "612224E493519B499DA8E37EA72BD934",
- "data_elements": [
- {
- "contents": "440654B4248B492CE5D00CA61809",
- "de_type": 768
- },
- {
- "contents": "D417931E9C9816A0289BD8855D855FCB21",
- "de_type": 166
- },
- {
- "contents": "E8C520AFADCD6D672723D0DA5828F73C6FB01B9F0DC6F7B4D6",
- "de_type": 139
- }
- ],
- "encoded_section": "7890130D0ADE5589F80B65A31269B928FF63D0911000489AA2FF0B570F1558FBCEBDA587BAE590040E64FFDBC2E0CD5EC3C8DF92196E4AF3057ADE7C296F26DA271D95A20FE7C1ECD2C28A8947CFF6007D293217FFA58261AD7F3D223DC7F1C2F2B19F696ED43E593593FDDD0E3AA714D6D646F34DBDD6C298",
- "identity_type": "provisioned",
- "iv": "FDCB3FCDD56A66B6C933BBFDF96A9FB5",
- "key_seed": "8293C98B9D0BF923A3721AC82F2AD92EBB1CA01487D3CEEEAC8CD21CDD69F4DE",
- "metadata_key": "78F9E8DC1BE37E91D04C8AF24505C390",
- "section_mic_hmac_key": "8B092819354220EA5B74C6332BDDC7D8D817B74789F17501F6D2E13230D93633",
- "section_salt": "489AA2FF0B570F1558FBCEBDA587BAE5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8140D71FE04244D8BCA21C9B5080A385",
- "aes_key": "CDF733CFB60B594C37C1F1970F06F23D",
- "data_elements": [
- {
- "contents": "9EAA4D737BC194651FF11D027E653915B66F89CE",
- "de_type": 146
- },
- {
- "contents": "85",
- "de_type": 517
- },
- {
- "contents": "B2D927",
- "de_type": 37
- }
- ],
- "encoded_section": "579013EE370B2CFFB5850F24E31EA18EA165E59110009CE7EBE57787FE3B841AAA34A9CEA8879004B79F8E5622D80A40CD40274BD5D19B70D57D842372B67C2220EBC1B075DDDEAE5B7A6E9BC8BB0C1104357CD7F9E27856",
- "identity_type": "provisioned",
- "iv": "3A43AAD47E0F8DF1D833F633226CE6F4",
- "key_seed": "645E00EBE423EDD4AB5A50D7EDD53F4B94B75EDB68D8FD639D72FC1474AAAB6A",
- "metadata_key": "AE54A918EEA35A8FF008113B344C0707",
- "section_mic_hmac_key": "8D07A0FEDA41154101D987AC882BE0C42375C3F66179A2260997983912026192",
- "section_salt": "9CE7EBE57787FE3B841AAA34A9CEA887"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6D9C63CC15928B2584D3A469A65E0BE8",
- "aes_key": "3571B4319B4687C0D5D54F436896C228",
- "data_elements": [
- {
- "contents": "782C0F67D4BBA10130696435243010144820F4752910F9B0E3F80FC0",
- "de_type": 381
- },
- {
- "contents": "9B336B1421B796A9C8F97A20705F",
- "de_type": 870
- },
- {
- "contents": "9F23ADFBB8E3EE4C54450A49552A6A",
- "de_type": 506
- }
- ],
- "encoded_section": "799013F321877FD6CAD817E2C641F8A90FEF4C9110009A96FEBC9A8FBEA4A344561254552C7F90046293184DBBFB610A416EF1FA50075E891A3937FAB2E51B6F0812D0E3ED51EBAC6849CC78AD2B85DAC2992CAFF2D2D2908E1F5A90889CFC1FE1CCBEDF435FEA597C4E2A2C2D220E4228E8463755D57BFEB5EC",
- "identity_type": "provisioned",
- "iv": "DA7041AB2C2B7685E1DC21095428E0D4",
- "key_seed": "839C80E9283189E3AB98E48862F375C4B87CFC3B6F6C044DB5E26AD4DE364323",
- "metadata_key": "BBF2E5F0D26483F19588EEC82EDC6C12",
- "section_mic_hmac_key": "12445B6BAD94883AC9E4DB8F94BA02D08DDB9F7A070EEB7D3A8A6FDC10F176E2",
- "section_salt": "9A96FEBC9A8FBEA4A344561254552C7F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "35A8251868DD2E1A9194786BE8C64BFA",
- "aes_key": "A7B21AEEA0C66BE702188CAAE0EA6512",
- "data_elements": [
- {
- "contents": "A9055442F2B47596B0DB0A971C07",
- "de_type": 961
- },
- {
- "contents": "D71C",
- "de_type": 677
- },
- {
- "contents": "E57B64B155CF7527D751CC68B263A792C2",
- "de_type": 265
- }
- ],
- "encoded_section": "619013AA0300E2A8F8624386FC6A4F5F403591911000837E4DF997864CBF37E0B55EB497A1C490027D171341BA6F6E8007CEA0ABBF21B146571A065717806FDAD5CC16C8122394811D1EB1F4B25D784D9CD216CD06A40CAC8DEFE77C0A19BF542ECB",
- "identity_type": "trusted",
- "iv": "BE19F81834F18C01B380AA4092DE5F1D",
- "key_seed": "5787FAEC4C0349041EE656ED1407458B8F07064FA7FF965C37E01938E0939071",
- "metadata_key": "23C90D62E06A3A03EA5E4DB7E27387A6",
- "section_mic_hmac_key": "790A1AEA80F909DB3A515737E1260748040994491F71C97E02BE9042B5F0FE83",
- "section_salt": "837E4DF997864CBF37E0B55EB497A1C4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F3C6A0D85CF7280DA0AE087536D46D4F",
- "aes_key": "714CFB9897FC29FC146F4ED1980F8A02",
- "data_elements": [
- {
- "contents": "CA93EB016F5AB0EAEE15BAAF19508C09E9FBE3ABF0CE6DA662CDD7",
- "de_type": 966
- },
- {
- "contents": "AA7C1AEB498A8A539C7F9CA7C6AC",
- "de_type": 924
- },
- {
- "contents": "9A7BFF",
- "de_type": 856
- }
- ],
- "encoded_section": "6C901340616A3CEEE6E3DB8958540220AB0DF8911000D6C0D020C67736CA0DA95743E11FB3559002E77AB2D50E5622942872D90F79889A1211EA3DFD68974FD22077EF7E297B27655072A61CA8148751503D2F945419CC3A41D10116203246F7A29D557ACB20AFEC92FDC3F6A5",
- "identity_type": "trusted",
- "iv": "CFF129908DEBC64E87D30CEBD7CFB92C",
- "key_seed": "E76585B665156041F17624D98389BC90CFB1F7B5FC98395CBB0C92BF39275F08",
- "metadata_key": "11E5F0AD1D1064EE76EF482287716210",
- "section_mic_hmac_key": "D388B45C5104F5EFF3114BFA514843F086F9CDD012E32ACB4322B3AFC3EF25F8",
- "section_salt": "D6C0D020C67736CA0DA95743E11FB355"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "899E72C0ACE8467E62C1534EC6C7A9F4",
- "aes_key": "0ED6FFDFAB0E1775C01399C65FC1EAC2",
- "data_elements": [
- {
- "contents": "46E4",
- "de_type": 164
- },
- {
- "contents": "1CD5EB57C26AB946B644C8C6D2EA",
- "de_type": 147
- }
- ],
- "encoded_section": "4D9013D876C620764709BA76B867262A767E9891100003C6477E17249A35DB289D156146DCE19002C34E905787280A485090274A6BE1EB6BAA83C8A860B7E10EF6E68170CD6CD856D47F1B5212E4",
- "identity_type": "trusted",
- "iv": "9A9EC26A4DF843F67A50C2883B2049E5",
- "key_seed": "D093FD917DC3D0AACFB61D214DEC5CD7E9F4D9D1B38A16DC4746005201209030",
- "metadata_key": "47EF5956F658168934538B98AD8039EE",
- "section_mic_hmac_key": "15D1AE58C9F76DD3D6AF7D332A79746DAC7CA69EEED1E03DE1BA3C2CBE6D0D34",
- "section_salt": "03C6477E17249A35DB289D156146DCE1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "37D4F69D0CD26B40E94ACE2A5DBCCEAD",
- "aes_key": "ED777D47AA2B1CD9A18A679A11D2D4BF",
- "data_elements": [
- {
- "contents": "3A3396B74739FCE4",
- "de_type": 813
- },
- {
- "contents": "",
- "de_type": 280
- }
- ],
- "encoded_section": "4590131BEA8B2830E5C0EF21FAA31033A5E5D8911000795CDD085DB06D32AE5FD26F7BCDDBB79002B6A7C8FB0E06CD39246BE00D8F824C8CBFBE5FB5B4CC94298EEC5CBDF16F",
- "identity_type": "trusted",
- "iv": "BDB607DE3CD62030073D459C5B8D6C93",
- "key_seed": "338B03B03A5E620E3B27EAF5E57D5A3E91B50113DC68FD76CCB906A0CD6AC15D",
- "metadata_key": "C7C3232A78820948E56ECFBEB230CB6F",
- "section_mic_hmac_key": "6A734BE5E220BD0FD824A54573671C3D15CF7B4BB57AA2B505EB6BF0B0CAC0D9",
- "section_salt": "795CDD085DB06D32AE5FD26F7BCDDBB7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4DD5ECE3088AAB59CB1D292B33F366C",
- "aes_key": "639007FB19AE47F1C559685FDA3EB75A",
- "data_elements": [
- {
- "contents": "E88F621FE3EB583D38E8BAC78F77C628",
- "de_type": 933
- },
- {
- "contents": "75ABDDF8",
- "de_type": 54
- }
- ],
- "encoded_section": "509013AF1C7CA2B228255162CA076C8B11BE46911000F45D6C318697B0191B1D88F3CF9D00F39004ABE13C11D4EE0C8DB3480A7B4B3BDC25563B1C28D8665AD58EDF8794E2B9AF89F46772315982210EEA",
- "identity_type": "provisioned",
- "iv": "7178DC1EF12587D629C2D6FECFF095CA",
- "key_seed": "98AAA87C26694BE9E3BBCC696C76246465B0239410B523EC447C9A2049D1EC0B",
- "metadata_key": "A278B435B2A9CA7EBAD385FC6B7E3F15",
- "section_mic_hmac_key": "80B3F75573897BDE6A79AF64C8FA3E66E60E12DCA0F934D92464B8FC037944A7",
- "section_salt": "F45D6C318697B0191B1D88F3CF9D00F3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "98345469CAFE42F15D87F5EEFC770569",
- "aes_key": "EAD0F193D218EF675EA19B2DAE377F02",
- "data_elements": [
- {
- "contents": "AB6691F16BD89FBEC7EA564644B836DF20E3",
- "de_type": 396
- },
- {
- "contents": "33283B4AC99D1351B01D0FAC70AC124EA0C18806F4EB79A81DD0C7B7",
- "de_type": 761
- },
- {
- "contents": "338FA25539C9F603E8AA",
- "de_type": 545
- }
- ],
- "encoded_section": "789013E04AD2F52216D16070E3AE142996253A911000908F07CC93A0157CA88C95EA00D2F8B09001801529DCA17EFD27E94D8A309ECE9126B84DDEF670D9AE859FC518535A5EF9E512C84FCA40EA028006D89902575457662EEF326EC7A07B9169BF15231DBE29B408E134074E7A1037F445C293EEF0F50051",
- "identity_type": "private",
- "iv": "628570BB5423D437AFFAD6A68E7D7C51",
- "key_seed": "D16A1A2DEF6A5A281D1345AE625CC996CE718409EC67F52C2126D4F4F35A240B",
- "metadata_key": "5D5A62A4FC06971533C17C6914A2ECB1",
- "section_mic_hmac_key": "B4027E120D33DDF70FDB320E58DC27EC588E7D0F16E413200A8A834D4FC06B6C",
- "section_salt": "908F07CC93A0157CA88C95EA00D2F8B0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "473589D555027506C32625BD8CC7DEC7",
- "aes_key": "3EEAA4B0A65FE6A149E92A3ACD460F2B",
- "data_elements": [
- {
- "contents": "00706503DDE2E48069E553BA253443985B15A915D6536999F1F8",
- "de_type": 655
- },
- {
- "contents": "152C59162A8FD170",
- "de_type": 261
- },
- {
- "contents": "29121F0B063A6B6F863E730BE1563CE5136F4B76",
- "de_type": 1000
- },
- {
- "contents": "A4E52EACF159",
- "de_type": 503
- },
- {
- "contents": "986D5DEC9898E595883F738E6313D79A010DA5",
- "de_type": 413
- }
- ],
- "encoded_section": "9590132BFDDDC9034E622342FD8689E276F16391100053743B86B516991B130398CD526856669001C9112F3BEA177009F48C84164DB23C8A235D39B30B30621639A06493FDCA70371EF4670D5D7F6F35D41573DCA035DFA187060D4509A3085763A2FC46AA05E1414D3A83151E7E8268A1CF1A1F6453114622E36FC069C6FA97D4DEAC4F2BBFC0E2E066BE2BA08D102E0FF80C67AE64",
- "identity_type": "private",
- "iv": "F4CFB23D5B57AB5DD39B7FA98B5BCE5D",
- "key_seed": "A949CA927245FE4AE45D4F369FDF339B2542427E268A92A4FB56D818E1585080",
- "metadata_key": "2D5AA2AE17FA3B780595B442816D577A",
- "section_mic_hmac_key": "5E2FAD4AD9AD36D0FEFEC43FA96CDDA06B95035C188A02188FA134AF1C039B35",
- "section_salt": "53743B86B516991B130398CD52685666"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "25EFD74B18D28C38561611A4E0EFA653",
- "aes_key": "D62A62981F5281FF40D4559D01F3D42E",
- "data_elements": [
- {
- "contents": "29CD91ECAD1EEAA72B8343AC127EA910C60103006ECF8AB36941",
- "de_type": 469
- }
- ],
- "encoded_section": "549013834CCF10766629D4E328E20F100325A09110001875FF4F2F9EB5B632BA383003DE4C139001D4CD5795AC80238CEA4265BB4D2A4668F9569493BC5936F84442A51F9F93144DC7F0B9855D6E2D8892965D0D75",
- "identity_type": "private",
- "iv": "583AAA53E4CB858B5425E6CAA806020C",
- "key_seed": "2FC71501293477514573A265C5C8704E9C86047A7A6B14A67EF489DF5844E0DD",
- "metadata_key": "9CF9951B23AA2C216A88920C36927BDE",
- "section_mic_hmac_key": "2DE14E1989C82EF73E9F57D5F31BF1D4C01B96488D633FBA7FD93C8F07DAE841",
- "section_salt": "1875FF4F2F9EB5B632BA383003DE4C13"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "230C6C323653F615C3EDD59CA5C3E4CD",
- "aes_key": "8DA0B2533F0BB0B636C0DD2C5F4C2325",
- "data_elements": [
- {
- "contents": "0F06B38FC8A536260ED355C9FC9E14E7DDD7929CD568A0E2B11F4417",
- "de_type": 196
- },
- {
- "contents": "E9DAE7C7DE865122E920DE218A959DC66B87191B880164152496328A4D",
- "de_type": 564
- },
- {
- "contents": "93DA2F2DDF4E29DD44012394C9A9AC64405DFFCBEB",
- "de_type": 257
- },
- {
- "contents": "F56469A172DCCA67832689D1C2",
- "de_type": 228
- }
- ],
- "encoded_section": "9E9013D58191FEFB4A9B9BDA6B037A0CC63F939110007B2BEA4E28BBEBC044F1282B590D42209002FB5F97FE4F62B89E614F28D1CC810522FB81A03B4C526D66C7B23A95AC861BE8072D5AC673D1E91DDFF56B3354305C6C5798E51B4C34F3AA0B8E49179F988718FA0A500B2F0F1A369DEB3A2DB6E99799CBD3B9970489B773C2C41E567328EE044FEE336F9120673102432E3A80EC7306705CCD5486A3A1",
- "identity_type": "trusted",
- "iv": "616285E84578D5625166925EDFABF2F0",
- "key_seed": "CEA74ABC6E8F5BC365B2A23575FBC9A5242A1175298E8D93900459C42D129730",
- "metadata_key": "37E8237111A63B854880506BC5B086F5",
- "section_mic_hmac_key": "3DAA034FE225951D1CCF0289F091B047D091F350A6566A0CE44A60152EBEFFE5",
- "section_salt": "7B2BEA4E28BBEBC044F1282B590D4220"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5D324887E76C3F9433D2B4A42FCAF044",
- "aes_key": "66E4331038810B466F236AF2610624D4",
- "data_elements": [
- {
- "contents": "985840558092746F07B1",
- "de_type": 498
- }
- ],
- "encoded_section": "44901326F885F961FE74FFCE3BBB43648CB811911000D8A99AE153719865050D04CB7D1673FC900256ED4D9FF8B3A8B57F704B5ECC167466004EDBC803DF32767BA4885780",
- "identity_type": "trusted",
- "iv": "49465FE445A423A5A4D9C893C7124241",
- "key_seed": "BB5DB5AE369B6C5D2EBCAA7A14B03F9A249DA93B87C24356475341E34CE211B7",
- "metadata_key": "88F87FCEC4D05BCAEB97098A827FAA80",
- "section_mic_hmac_key": "2B66622A6228FFDE6DBCE6808DA2A207F942EF38059457C1E84D49D65D5EA0EB",
- "section_salt": "D8A99AE153719865050D04CB7D1673FC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "492310415125301AF370F3A28F99C923",
- "aes_key": "3E60451A7487BD9CC8EF9CD117EC06C3",
- "data_elements": [
- {
- "contents": "7E0B2E1CB803",
- "de_type": 96
- },
- {
- "contents": "",
- "de_type": 4
- },
- {
- "contents": "5FFD2C7DAB0C",
- "de_type": 557
- }
- ],
- "encoded_section": "499013A8190AECB7A7CAAC7A41BCCC1BB23EB99110003D9D5DA626D91FD8CB8910200ADDDCDE9001C4A2BBA08569798DA7CDD17B9434EFFDAB07119526363656E66DD52D79BFE6402756",
- "identity_type": "private",
- "iv": "C512212E4B03688C91E6742FD6CE85D0",
- "key_seed": "303426E69CF0478D3546C376E523B59976BEECE4CD7E5D73A253EFD37AE59596",
- "metadata_key": "2EE9CB59D9ED13C836389363377F0C10",
- "section_mic_hmac_key": "177318DF2F5E18A2BA15AE658285E89541A870D219C47C5260C77D286E9EAE11",
- "section_salt": "3D9D5DA626D91FD8CB8910200ADDDCDE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "34B38738AD29FF67B98A87A5E632B403",
- "aes_key": "31A27BC1F826FB2A14BAF5D41AD7EF32",
- "data_elements": [
- {
- "contents": "8FF21C1E9727057BF441B8845924AF2652",
- "de_type": 561
- },
- {
- "contents": "59354C8203E3D49D708164F64A8E94FD37DC4AB3170AF86EB2DE23",
- "de_type": 143
- }
- ],
- "encoded_section": "6990137AED32E0B427E327EB555684B103FAF09110009FC7D83B3BFFDF9324A3DD576C83C25F9004860BEA1F0A861519D2F64FD943CB247C301755CF3FC0F9688CC9C3A59D712C0A45DCBC0C4A4BACC93E9206E1A1F01AD375047EE9CDC415AACF23CED21082D0D6F2F4",
- "identity_type": "provisioned",
- "iv": "95AA62BEE82A7EB218781305E16CF180",
- "key_seed": "EE9B03BA6F99F320443D9EC2D4080AFE8669D55E64A55476B910609E79804BE5",
- "metadata_key": "791FFA37592A73FBE2748C91CBE5EDEC",
- "section_mic_hmac_key": "B31DEDF27A541AAEB000A61976F06FB1137AB359B3D86DAC2E30C3DDFE8B85F4",
- "section_salt": "9FC7D83B3BFFDF9324A3DD576C83C25F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6F1A5550F40245579FD1FEDB994C60E1",
- "aes_key": "EF74CF6922AF88727876DD6180BADDDB",
- "data_elements": [
- {
- "contents": "10F27CAB4FB6B95F77A5C6",
- "de_type": 998
- },
- {
- "contents": "7F4C192988A13A4E53C57A52F5DC",
- "de_type": 961
- },
- {
- "contents": "F676A115F3B1DD",
- "de_type": 176
- }
- ],
- "encoded_section": "609013305284C016C6D4FB8B85A6853EFE3BE1911000A883FB09F88AEBC1CC6CB4375B6F309B90027F59BF0ED26EFD7FC2826D3C353F894B923AAEAAF953CA9710D76864FF689AC4E3AB2109BD45AC5F1DD5578251BBA54D47002CF28B741222F6",
- "identity_type": "trusted",
- "iv": "3076D26E01CAAE164B6DD68DF2C98D6D",
- "key_seed": "F7701383A99913E39E948F24FE4375388A477B5885BCE42E1136D694EC5940E4",
- "metadata_key": "FCA9E9D4A7FC73EE0A84DD20EBFEFCD0",
- "section_mic_hmac_key": "3090F43370303CEFE295DE610007E4521B9C61EDC8413FDCEDB1A1E827193103",
- "section_salt": "A883FB09F88AEBC1CC6CB4375B6F309B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "91652221827572DFBD2DECCFDEBC0623",
- "aes_key": "93D4594F6D83065E87736A4B1C8B5D90",
- "data_elements": [],
- "encoded_section": "379013CCA0DA07331E1D50F654EF152E8BE56C9110002EBA87F24986E786C3CF5E687E930F6D9001AF4C55F24D83258BC9CFC3ACE6DD4F77",
- "identity_type": "private",
- "iv": "7407BF39844950F7C02EFA0DB33EE20A",
- "key_seed": "62C96793C0C0A1AD2EAA5D77B983C772D1117BFAEFEF6F1880D15A138CF02BA7",
- "metadata_key": "493DA0C9159C6E0A451EF59760E8A037",
- "section_mic_hmac_key": "59E78109732E338964B9D72691182ACCE1F13B1FB2AF815D0D9E107BDA483E99",
- "section_salt": "2EBA87F24986E786C3CF5E687E930F6D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49A2D6913773EC08C26776F5D82EC4C9",
- "aes_key": "61B9D6C9A96D8195A2448D9A4A9FCC50",
- "data_elements": [
- {
- "contents": "9F6F",
- "de_type": 985
- },
- {
- "contents": "585537C36483C7D6D71A12EF0E",
- "de_type": 650
- }
- ],
- "encoded_section": "4C9013598C8EAEB8D51BC3FE88DAF09FB46EDC911000A381CE76EA131827A0C0BD7720D36AE59004DCC9D1BAB25D0CCBA65658980D6DBE61D2F02E7300B983FD2D944B9BED0E9ACA1AE77591F1",
- "identity_type": "provisioned",
- "iv": "DB8334CADCA491D2C65763FED225BEB7",
- "key_seed": "076B4CB28DFCC1192ACE62FD2078B9D7A719A4FD023E5C806D60464AD004F54F",
- "metadata_key": "C8B3594B1DE8BCC1698D794EB9159D32",
- "section_mic_hmac_key": "05F49F228F859D213855BEBDCE762E3297CFFD51ECBB2088CFD8DC8E90E0F1B0",
- "section_salt": "A381CE76EA131827A0C0BD7720D36AE5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FDB28EC49C232187F4B313D338CB401E",
- "aes_key": "CBDD90D1BA86EBD8B627412AD9097632",
- "data_elements": [
- {
- "contents": "67B75AB60CE23E879336887B5D9F5775A2078C1B2BC755B1B40901A14D7C",
- "de_type": 482
- },
- {
- "contents": "CF980B5189EA458B3E9EEA80758E9FCA5195E09F06",
- "de_type": 167
- },
- {
- "contents": "5B619E636C2E",
- "de_type": 759
- },
- {
- "contents": "0A408A22E62FC9245250A072273ADD497C300228",
- "de_type": 387
- },
- {
- "contents": "94",
- "de_type": 481
- }
- ],
- "encoded_section": "949013E4CFAF2BE466963149A6224ABCFB0C0C9110006886CCB0F507AC5B4E3A33B6F31D03EE9002F2392C3A765BB4AD1BAA31BFAC8FA8B5987DDEDF99E0B1F4AB5BD84ECE46D3701BC1B28DCBA2EA465B7F4EDD078FE699CAF1E3E9C2EACD89849EDE3E13B4E9C69A2381755448C9E0113843A4A22BBFFCF7C11BB0EA70C08A606952234B4B6108EC83040C10C6DAD374A5F05EDB",
- "identity_type": "trusted",
- "iv": "C028C5B6F9A36584545FB179C379BFB2",
- "key_seed": "F6F00C19B4792C24EEF3D27D69993076230247603F817E90B855099E413F2B07",
- "metadata_key": "67746BF043260C6C49EAA6197157A491",
- "section_mic_hmac_key": "61E943AF30DDED5473FBA40F5118C7C2F350103F84A444FB4F7550667228977A",
- "section_salt": "6886CCB0F507AC5B4E3A33B6F31D03EE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1EBECD2EA3A8364948252CDAA5B96320",
- "aes_key": "5C07BF2012F7917650BBA25DD8F336CC",
- "data_elements": [],
- "encoded_section": "379013BF51B7882CB99C30571F24D1DDD05BAA911000E3F0D6C54BC850F9A48E98054374ED5F90020F71BA6B33808FA225AD2296003121C5",
- "identity_type": "trusted",
- "iv": "BC7CAF3B06416475990D575B2B3AFF29",
- "key_seed": "D140C25596258623F7D0A978CFB6875793307B7210A9965CF4A09927E23848EE",
- "metadata_key": "A62C713646FA57E510CEA5E76377164F",
- "section_mic_hmac_key": "B606AF244BA59DCBBF6929DDBC3EF9B7FA0A968EE4958F8D628946460E0B574E",
- "section_salt": "E3F0D6C54BC850F9A48E98054374ED5F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "34B8D0AA1B6076CACFCD67EAA56205CE",
- "aes_key": "D18687CE96E0D9B21847502E60CDCD25",
- "data_elements": [
- {
- "contents": "53493339",
- "de_type": 153
- }
- ],
- "encoded_section": "3E901369FD29BDD5FCAE64EAE91DA4C76BE48D9110007999D3B31650C18756A1D319773212AE9001275F57FE6AFB60B6DC87B624099A9B24569491F5F49121",
- "identity_type": "private",
- "iv": "5564C020A460380637EE5661E0F18465",
- "key_seed": "51CD66A9B8455A1C61806C6575710F29B99AA5C08B5FB6883E2656EFD4EF4B98",
- "metadata_key": "7A089FA25B6301D9D8413F0AA49603CF",
- "section_mic_hmac_key": "B6E66D366DD2C413AA66A99E8CACDAA9761BA51C95898458F7B4D37988F135E3",
- "section_salt": "7999D3B31650C18756A1D319773212AE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA23F3D623563CA554B644B8944836A5",
- "aes_key": "952EDF3A3A92D45B9DED25777352BA23",
- "data_elements": [
- {
- "contents": "A0A99C479635E3819E8702A34BDBAB13",
- "de_type": 852
- },
- {
- "contents": "E0253587563A4C07",
- "de_type": 385
- },
- {
- "contents": "1FF104D3D8A66917AE8B770463E08516393A6FE29A",
- "de_type": 654
- },
- {
- "contents": "DD0D3D55183C193476966F12ABFFCF2C65AE5E9000E57E93DDBEEA6B47",
- "de_type": 807
- }
- ],
- "encoded_section": "8D9013E81D950CC4779370E13B06AC5F9BFA749110003F78335FFD99A2E7A40D78D6314F7713900211BBD3B4F8A56E26538F9FAE57F0AA9114CC34411E8D4408B53039E144A6F0F6E3FC4C4E32563A97C177FAB41C6AB5D6ED9EBB41E98627ED5DC9B196432ED1C0036FCD729E492A25D4976723C777333C52ABDDC04D9E7F8654ABE7CBC319DDA5BDBFC37DF51D",
- "identity_type": "trusted",
- "iv": "2A0B516ECD2E3ED9E8491CB2A23BE7BE",
- "key_seed": "9A76DCD6488802F550A1A5B2D68A21B45850BDB5D04F6BFCE6737EE9065459B2",
- "metadata_key": "7A82BA273F40F1D7147503A0521EA07D",
- "section_mic_hmac_key": "D0071AD96C81ED47B74B6141DD9BBA6467D69ADEE3C4B23556525ED204FE5450",
- "section_salt": "3F78335FFD99A2E7A40D78D6314F7713"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EBCA2068CEB2497377233BA55556143A",
- "aes_key": "B7CAB93856D36C4234AB9B7E3FF2C2CA",
- "data_elements": [
- {
- "contents": "B906252C6FF66DCECE5745A021B149F9AFDF854A258D184B",
- "de_type": 9
- },
- {
- "contents": "113F12D313183B2C0F0080EB04",
- "de_type": 401
- },
- {
- "contents": "33B9E9DBD10F",
- "de_type": 838
- },
- {
- "contents": "EDF90FB1E1E1D0B56F88F8E52E9F28",
- "de_type": 649
- }
- ],
- "encoded_section": "7C9013B26979B83B32E69A1562F16DE75E14319110006B6BC738CBF9DE91F89702F34C609C239004E53E0A53B0F500690D822ECF8B51533921124980942C4C52D2BDF88BE78D4CCCE1F7B9334FE9EF5FA7846D447BABD7149F092C75AFC759AA705A511848528674C4A75131D2B0FEFBDA757DEF4319F405DAC80EF1D9",
- "identity_type": "provisioned",
- "iv": "84465E974A7F46A57204E7B87ED0AAFF",
- "key_seed": "E00C8B52A62D38CD16051B45E43ED15D643A93FD6F673B03448250D608D10535",
- "metadata_key": "3E2F563D9D36B4AF7752C0C19548A5AF",
- "section_mic_hmac_key": "5FA9E23CC79D9776D137B5928675B099089A5EFB01BF98F6687C66BBDB3C334E",
- "section_salt": "6B6BC738CBF9DE91F89702F34C609C23"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "246DD4A6A94037FE404D0A0EF4606013",
- "aes_key": "B80A4E7A36FECD53741D1832DA6135AC",
- "data_elements": [
- {
- "contents": "FF7E4C70C4C530F2728E854ECF67475F62905652931C8B7D95CE",
- "de_type": 867
- }
- ],
- "encoded_section": "549013AD258AE82CE83D89E404223234B3AC95911000D4C424C2D921D1248156D8D5AE0B40A2900108EBB7D35A6FB92BBAC4DFF57F860E87A043D0B90A06B94C6282265F668887704AFE03D7D6582F0816A5326028",
- "identity_type": "private",
- "iv": "2CF2A660A004D8D204498034A9C28C04",
- "key_seed": "03982AE5B7459AED3DF2C506B459A366A17E98F81BD7DF3BC27492D0C60AB88E",
- "metadata_key": "26C5F75F61DBD2E1E014D7EBD5259EDD",
- "section_mic_hmac_key": "CAB0A73023E9B8CBDF76C30DFE90FEC62423FF1328BB239C7F7064E49255464D",
- "section_salt": "D4C424C2D921D1248156D8D5AE0B40A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "14369DBB0C59ED5213EC3886FCC36B32",
- "aes_key": "3BE5F37F21F48652E478248A61745106",
- "data_elements": [
- {
- "contents": "7B5BB22FBEBF31",
- "de_type": 256
- }
- ],
- "encoded_section": "419013E3C20D9A0D8CFF73CD40DC2EA192F87D911000E26F9F9CEE62E88574F9614FDF510F5B9004BA4F3353BF508F98B6B06BB3B36442AD6F00882B337E8202F717",
- "identity_type": "provisioned",
- "iv": "16BB18DA1471AE79153EC619BC92D006",
- "key_seed": "E351CE8EA42F777F5490CA51A37836EFFC360847D086D0181F34C50B48A84CC3",
- "metadata_key": "17170F758D7A1BF5D584322C73297E1C",
- "section_mic_hmac_key": "5BBECE4B2E6F573B52BECA481ECC505F4C38A17657A5CC75B418754E5D19B4D7",
- "section_salt": "E26F9F9CEE62E88574F9614FDF510F5B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8C8E6A84C29BEDCE24FEEE95F310A81",
- "aes_key": "D0BE22BCB73BD71C3FE37C497EE212EA",
- "data_elements": [
- {
- "contents": "95",
- "de_type": 110
- },
- {
- "contents": "1CA6BD05453648BD3FF1",
- "de_type": 606
- }
- ],
- "encoded_section": "4790131C7F79B0F1E2086443460FE2AE232E95911000FC13C4CD5778C7E95DDB96C09062B64E900238A595E5A0F6964E89CDED56CDA41DD8391A91782768A7ECD119D3C12A98E0A5",
- "identity_type": "trusted",
- "iv": "2E84FA52101610AAD88549E7608A3849",
- "key_seed": "A06EE64788DDE83EB17B56B49A8EC7596A559E9782A491BD87861F63D4EFCCAB",
- "metadata_key": "B6B79621B08ABE548DB74B2C2910B691",
- "section_mic_hmac_key": "B51522E30B6E35A9C74467E74B32E6319A059BD8C2B60343FE9C6DAE4E881613",
- "section_salt": "FC13C4CD5778C7E95DDB96C09062B64E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1961134C789B5EA15AEFD01B020E6C6A",
- "aes_key": "AFD569DB55FEE7DD324325167509AB92",
- "data_elements": [
- {
- "contents": "ADE5",
- "de_type": 666
- },
- {
- "contents": "5A78B8137C56F49AA2A402",
- "de_type": 744
- },
- {
- "contents": "CD1FEAFD54E39FA95E0C492E25",
- "de_type": 758
- },
- {
- "contents": "5D931A41C7E445F6C6EECE448FFC54839DB9F5D1F854D9",
- "de_type": 74
- }
- ],
- "encoded_section": "7390131DD3C5EF126658F5E2DD60B357AEC97B911000A97D706FAD3538F852E485B8E91B9B4D90029973B762AC2D40747B49B7DF31B7BB0071DA2E4F5B4E371E3745A05FA602B3872F4DB9F9805FCFBD6E9E9624E8B05CEE407A25EE98E0865FCD11C08E04F706C96E673BF69E353B692B771DB8",
- "identity_type": "trusted",
- "iv": "E1BA0D8B2C19F6336353D6019F0D8D59",
- "key_seed": "7B0C9CAC1C6FB86BE8E0634E24CF942B571EF10B5BEF56A254E269F931D741F5",
- "metadata_key": "61B2052FB3E72679CD7AF270FEF714DD",
- "section_mic_hmac_key": "66217CD102C260D78F693E1E5C070009ED91981060E8554C670B6101AB87D67E",
- "section_salt": "A97D706FAD3538F852E485B8E91B9B4D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BE37D2BF26F95DA0420AB793F2FD51C3",
- "aes_key": "94CAC64FAF0883BC5A905AB0D27402CD",
- "data_elements": [
- {
- "contents": "45C8134F7E3A2B0952A12FA06074C1F55E228C",
- "de_type": 641
- }
- ],
- "encoded_section": "4D9013921E779C25C2F1969FE5EFE492EF05F49110004857A1A663E286BB45649A4E2A95E4C090020E887CA55C65C8F304D7367060AB2D4C08538F57B150310D0DDB8FE2BFD75DEE9C4E0B2D5201",
- "identity_type": "trusted",
- "iv": "3F059AB52F8DC52A14C635AAB44A7A58",
- "key_seed": "DF5565B416A2E7AB41E62C7E2DF6857DF2E35D5EDC4AD2A070E168287A20836A",
- "metadata_key": "073410FCAA7FABF86F28C9921B05AD72",
- "section_mic_hmac_key": "A93B302F32C8F81FCEA9AF1011CD9F657B33BE4090CC7F351E0AEC32BF3C4EB5",
- "section_salt": "4857A1A663E286BB45649A4E2A95E4C0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "771F89E3B46AC6611C69451AD4EDFC64",
- "aes_key": "F915BE6D3B134480D0A5D7455D4BFE4B",
- "data_elements": [
- {
- "contents": "EFA11DE2127527F334FE8B3458C817A05EC0A227",
- "de_type": 784
- },
- {
- "contents": "9C33AA668F95CC399ECE329BFDEEDAE8CD1599BFEC83C51738",
- "de_type": 704
- }
- ],
- "encoded_section": "6A9013B37D84C2D193043679822C766E68B552911000C913144F7DAFC50ABA66049304D883B3900169CD7BC8EC1BF46A0A81358228CA475A03C7730C36BCF2A69161E8AFFF092DDEA4A8B97783C80CB47CA5E777C43A6C840FCB619B23919CFD33FE5DA1EE4CE37F03875A",
- "identity_type": "private",
- "iv": "8ECB870D9F4F3DF7E0F61B0F37FAA178",
- "key_seed": "8A62A2DECFA4345C616E196C18739C2ED2DBEFCF45BFCD3A68D4BBD673ABC400",
- "metadata_key": "30BBDD7957FFE92AD9AC8F4D638186FE",
- "section_mic_hmac_key": "57A0D17FD7D3C257222D2862C4EDA3EF89D525634689B41442D4F408940A76DB",
- "section_salt": "C913144F7DAFC50ABA66049304D883B3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E862AAC7000736B663C508376E8BD3ED",
- "aes_key": "26BB6FAB1BF2E0042949DB8877820B26",
- "data_elements": [
- {
- "contents": "402462632AADDD04C6419557",
- "de_type": 818
- },
- {
- "contents": "9E6730409FF8",
- "de_type": 605
- },
- {
- "contents": "F47F7D404EA0D495FF62A49520",
- "de_type": 873
- },
- {
- "contents": "287092DE18F81EA128A63774FA885821AE34DF",
- "de_type": 903
- }
- ],
- "encoded_section": "75901340D2D16C893F60F75377B5BC6D7C15799110008CAF5A78B1E6790F346DB14AFC187FC190028FDC753F6FDF59AB4C30DA74B57848A69A5DA9DD03C4F8069D71CCE6307E698277D98C7C83A4DD5E162C542D51E763C65B88B7F9082AA40B37D55BF387851F2EF0C0124D81C610962905D4022114",
- "identity_type": "trusted",
- "iv": "3E1E75C62AA622FD5D532FA03221A5E8",
- "key_seed": "89112D0AB38C09870723291EB34F41CC1276649D22EC916559C37E5ADA6BC495",
- "metadata_key": "742683BB2FE3A781C335B64655BDE1F7",
- "section_mic_hmac_key": "F1FF987DEF82976AE3323B0794E8B55DAF78097FAEC13971E2DC110033ED4B06",
- "section_salt": "8CAF5A78B1E6790F346DB14AFC187FC1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8E2730566E4C094460D3430F556F601C",
- "aes_key": "DD80F41866B5C2305F7EDB83DDB2314F",
- "data_elements": [],
- "encoded_section": "3790135D8F74283C3477E5A48A53983576A3789110005962F214FD66C62FAFD7ADB0449C91D9900101D4C5113DD0A160D67C7694A365EA98",
- "identity_type": "private",
- "iv": "BF345DAE8603A50EBA6E1F53D639EBA4",
- "key_seed": "7EDDBBCA0C3D3E70E8A1AE0D1537F660F8E17DD7AC70E2B12AD710AD270C7499",
- "metadata_key": "49E7FD99EA8806E02F7D9266C51E58AE",
- "section_mic_hmac_key": "FB24F853F734086D0360DE9B5036D6C9262BB446F78E3E8594351A966A95FAC5",
- "section_salt": "5962F214FD66C62FAFD7ADB0449C91D9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B07E55E2700925068EDB49793A5FBC2E",
- "aes_key": "00FA5878B9B5C9C67B6B78EA6F7C987E",
- "data_elements": [
- {
- "contents": "E23741BC5357278D7F1FAF6FD06F",
- "de_type": 381
- }
- ],
- "encoded_section": "4890135E703F79C8BBCC5412BB7F51D7C65ED7911000123652CC63D81642784356825AEFA5149002B8471E8B3673496EA7D67B901D2A0DF2607B9AF1C329F0F716E0D127A22EB3143F",
- "identity_type": "trusted",
- "iv": "1D38B3322CD6A4B1E5DD0626D6B3F4D5",
- "key_seed": "C0F3DDCA80EB2A1A1BF349A2CB48E9EDA04153DAA1DADD20C760C5C4E712D1D2",
- "metadata_key": "657257C54ED238136FB1CD0F38189EA6",
- "section_mic_hmac_key": "83CE2AA9DE2D247CF7DDD33519F40F49C6672DD7B68C321153C59501E7527226",
- "section_salt": "123652CC63D81642784356825AEFA514"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F0B2624C966B5ABB55D185559CC05BEE",
- "aes_key": "B0CC1C99F199D7B0DFA6A8818D97E3AF",
- "data_elements": [
- {
- "contents": "F8E673AE46653F33686B67CF9641406F176FD36E",
- "de_type": 534
- }
- ],
- "encoded_section": "4E9013B619CC5D111EE3DD731057171A8E147C9110003777191AEC924C44BDB4A82B1B8CF55990044D4549D7A1B2AB4EB43666D6E04C1AB21F3053ACA9C3C8A8EF4F34DCD75AE8E3443C0BCE6FDE25",
- "identity_type": "provisioned",
- "iv": "9CAB7FD16B0FBDA87A216F5BC3C64D84",
- "key_seed": "D389626DA719AB4CF557F675341E1E959782CC0A975BABAEA6E7B6F106105786",
- "metadata_key": "CEC5D039323AB0A6EFC0871786DD4B9D",
- "section_mic_hmac_key": "B2FA1282A7DD0C829E6BEA74AD23B119DA99F144359027FAAAD3BEB2E12AA1E4",
- "section_salt": "3777191AEC924C44BDB4A82B1B8CF559"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D709C7EFFF43F8B5F50357511634199F",
- "aes_key": "D9BDAB1A62CD59915C6D87AFD81DCC66",
- "data_elements": [
- {
- "contents": "FB75717581E26ADACE888FC7B65251F8ABAC3C40613A",
- "de_type": 775
- },
- {
- "contents": "1764F1",
- "de_type": 536
- },
- {
- "contents": "30EC19D6A92E42606B66FA4436A8BF35786D",
- "de_type": 154
- },
- {
- "contents": "491A5D8D776B0370",
- "de_type": 563
- },
- {
- "contents": "1A2C2252D95ECF1233A5A83D20CE56501E741FD8A3A1",
- "de_type": 74
- }
- ],
- "encoded_section": "8E9013E6FA247F24A139082788D9F9137009EC911000F52EC2909102AA8CD7731AFB755087CF9002A6FA67CF1B1D109A5BF9A45AA25FF44E68CFA66213A90B891313055BAA791C98EA2450AD923CB7A039FB8DF6A1D6F99F7023386BFCE77936BE122B9D9DB17353689C19177F07D850BF2697B3FDF09D4A3C0A4EAEB24D9E147AD481667EDE2C323CE7607A3E31D3",
- "identity_type": "trusted",
- "iv": "1326B2D61CDFE279821BA574CD22D395",
- "key_seed": "E23E916F47CA7077773636B248F20DCC8B3570F5B7035886BCBD4A4C6983225B",
- "metadata_key": "51C25C132D519D0B8A3D62697731A46C",
- "section_mic_hmac_key": "AF5C6E5D054F422A1958AF447AA500C6695FBB24A28A30F1AD85898A960C5D6B",
- "section_salt": "F52EC2909102AA8CD7731AFB755087CF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A90C5F9A4D5EE8C0F093DA60D34E4F7A",
- "aes_key": "5BBDF9E43276717F469C46331CCDBDF2",
- "data_elements": [],
- "encoded_section": "3790131EDB1EE9AAB1D9913865783E4ADD8EA891100068D0833BCDA158BBC5B7486992DFD73190010C8E5201A178300C0997D19C63660359",
- "identity_type": "private",
- "iv": "D037D4F2047D995CBB869FE4C0AFB002",
- "key_seed": "2222133F9A08B0B6DF5DE67AA09B19BBF3279767D9E924533FE77A3E681870D5",
- "metadata_key": "3527338EBB73E631F165D4334A5845AD",
- "section_mic_hmac_key": "A4C47342B039235D55E3BFA54E273BD3C250C2B3A9B8C60F846450FDC55D6C2F",
- "section_salt": "68D0833BCDA158BBC5B7486992DFD731"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B01C0A512EF90678274BFCFEB65B9BFB",
- "aes_key": "FB0A68F0FAACC559B8B7CE60692B5578",
- "data_elements": [
- {
- "contents": "D1BD",
- "de_type": 244
- }
- ],
- "encoded_section": "3C9013E9A1064EF69CF0E99BE8718C433CE4039110009532E764C5200635AD10A03DC30287399002DACB0D8438EFED4CD36A27C1AEFDFB48627927EC4E",
- "identity_type": "trusted",
- "iv": "36F33FE9F30FF5F345261E94AD27670C",
- "key_seed": "A95137212D3A3C03BD4A78822E2F55955D833BA2AE8454DA2EDF749F06DD0E19",
- "metadata_key": "98C80C93560E9287602B9DC167933921",
- "section_mic_hmac_key": "1E0A6D7D2E12C5E918490B41A8D0B2F1AF8CDDFCF7D968F507BD84B5028B34C2",
- "section_salt": "9532E764C5200635AD10A03DC3028739"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6EEAB27FB59D9E6CC29C4A77DDA80073",
- "aes_key": "E272F73E7FF2C352CB16961A117DA4B8",
- "data_elements": [
- {
- "contents": "AC9F54867C2D3A343EE15B46BB21",
- "de_type": 920
- },
- {
- "contents": "B21F47CC9AE7F415AC85AD33E360",
- "de_type": 3
- },
- {
- "contents": "A4F7ECCEF25FCBB7DF7C",
- "de_type": 251
- },
- {
- "contents": "4AD51198F063055EE851A62002E4150C537144FB5C1D1A",
- "de_type": 918
- },
- {
- "contents": "6B78A9AABA9F",
- "de_type": 742
- }
- ],
- "encoded_section": "889013985769BEEFB87EFAEFD9016724CB70209110007285FAB75391A148A7EAF2CDB3E7312390015929069EC6D45F3249513153B9AE3CF8BBC891ABC84001532CC0BE7F9068D906C3FA96D915DEF7F6CCE423D22F23F98B6F62CEE6A6206265707AA7C191231B94222884B904BEDC7269016B982B57BCAC107CC419EA378A2FABAB9A9AF413DFFAA8",
- "identity_type": "private",
- "iv": "2D1CFBB0145D7E9FE2E12C8E060834A8",
- "key_seed": "2E8DB347C722FE8FC819707AC6B1D9F1244D91CD7B7A76E35E379F17DF92018D",
- "metadata_key": "90B7D0F0D7AD2041C06A6F07D4C12DC2",
- "section_mic_hmac_key": "903E4F3ED660355AD0FDC44DCD556A5A325BA002E430C9015D43495EA3ACFA24",
- "section_salt": "7285FAB75391A148A7EAF2CDB3E73123"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0B34E362BE1CCA7EA27E689A78185921",
- "aes_key": "0B25B59E48937801A1B8B2E567E38A58",
- "data_elements": [
- {
- "contents": "3AFF6623B18BF5A2FCAD751E561111AABB6A6BB5F6F33E5D",
- "de_type": 901
- },
- {
- "contents": "7E6522479D7F",
- "de_type": 337
- },
- {
- "contents": "A1DA1D6D618A",
- "de_type": 221
- },
- {
- "contents": "EE348B17E8A41816E716",
- "de_type": 18
- },
- {
- "contents": "F96BBF72D4138318",
- "de_type": 639
- }
- ],
- "encoded_section": "7B9013F45B179A1FF35CAAE790906F2B6B039691100014D27591E7A5B662518B0D93211411239002FE9D30D12DAB1418665668DA1CB7F5EC4DAA9CF88CA252CBEAB6D02BBF81945CB5FDB217EC422556D09938E338C8438632BBEE86118F54D7FDA189CE7060AFF1E279D7FC726EB59F1D74CEE318348F248B0A9D77",
- "identity_type": "trusted",
- "iv": "41224E5FEA506EA36F51CE022F3ABB1A",
- "key_seed": "8CEDB96BA8CB14FF94B7C7A3A37A3864C597406E194D69FCF5A871FEAA16CECB",
- "metadata_key": "08E48EDD4E12AFF47F8AAF55C517C8FA",
- "section_mic_hmac_key": "2463AF9C4F677BD099151DF4759A4F3632D51F1C41BC96E97EB4476658F3D6B0",
- "section_salt": "14D27591E7A5B662518B0D9321141123"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A904E6EDDC39B1F3213F1D74FAEBE57B",
- "aes_key": "AE2236A355CAAAE9D7044AF1B9FE08B4",
- "data_elements": [],
- "encoded_section": "37901350FA595EF5F19AA58600FA8356264FC19110007A69E35A44477408600F40C1EA6020F990019BA326E5C0DC4D3DA39BE3EABA175E37",
- "identity_type": "private",
- "iv": "05CA9ACE5528AF680023C92BACAEE8D8",
- "key_seed": "5038A07C7783575EC758DBFA22B5B0C961C9C7BACE1AB44549C547DA05167B2A",
- "metadata_key": "39CEC4870B31445FF870008CBB598309",
- "section_mic_hmac_key": "00277572EF8546C2B9D70D0E7D668FD59FEA252347333A76B0FD6A353830BD03",
- "section_salt": "7A69E35A44477408600F40C1EA6020F9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0E75F1D12F3EF90599341DDCC4E6CAF0",
- "aes_key": "C63FD8AF5CF7A9B46934298ABBC00693",
- "data_elements": [
- {
- "contents": "E10020BD5E92D8B6D3ADDC0232197F7AD8EA8B10F82DB6",
- "de_type": 94
- },
- {
- "contents": "9B56332DD723E56CA51F89D5FD126FD40BF6953679",
- "de_type": 255
- }
- ],
- "encoded_section": "6890138541962B9DAD2E109AA523E949E8D3B5911000C939914DDC703A7FBC857AFA6C1A94369002AFB0809D9C92645644E0A2276F90707E45256A92643432D9288702769AEF6AC4D0C778159A5B4AA0531C612940DE6D832F64DCF9A6EC457C76D3CF42FB5ACFB3B7",
- "identity_type": "trusted",
- "iv": "864721546276C7A96CC880DBF5B8DC7B",
- "key_seed": "9D096BB52548302F9A0F8C6D2DDF1601F2E96F799FE76187DFE2138E7A3FBE4A",
- "metadata_key": "81C35203EFCFCBE083726B15AC9DC275",
- "section_mic_hmac_key": "6CA85DEF3BE730365475A93E71330031A6DBD9E48E04BB295FDA5321F496D8D4",
- "section_salt": "C939914DDC703A7FBC857AFA6C1A9436"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D007D878C6FFFACE78778BC06B98E8D5",
- "aes_key": "8C1265F1ABAC004CA2D681256B5C502F",
- "data_elements": [
- {
- "contents": "",
- "de_type": 734
- }
- ],
- "encoded_section": "3A90136B53F00BC73427570D56B25245E31E709110003F1EA18FEF5037CCF30402C46130A70F9002E563FA84C94D3ADEC61DCE418FA76320E5BAAB",
- "identity_type": "trusted",
- "iv": "C892BFED70D002EBDCA25750710BFE76",
- "key_seed": "C4915C71ACA0B455710629B063B5D9286E2CED111FA1C9D638C7069DA933F2D5",
- "metadata_key": "B44812E7A415896300387540FA9C4DE8",
- "section_mic_hmac_key": "CF8E967F00EBC62D8729A9A1C4AAFA3288EAE5ED966B12953837CE736FCEF820",
- "section_salt": "3F1EA18FEF5037CCF30402C46130A70F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4C0A0A8717305E60D1E1F4EDACB40F1",
- "aes_key": "B64935A371108F799E67FD260F6FBC97",
- "data_elements": [
- {
- "contents": "BC6B8FC4A146298C2C7C4C04B0BCA9",
- "de_type": 256
- },
- {
- "contents": "A3C4D6D6",
- "de_type": 148
- },
- {
- "contents": "82ACEC78D07CA4CC55D05CA5455FE192",
- "de_type": 755
- }
- ],
- "encoded_section": "639013159D08B00F5A835AB8977FAC857298BF9110009B3429DD955B53030DE7A0949F8051C590019BEDC8B153588FB31C3D7C0B8EB3B0876208647BE21E2AFCC19CC883A03E5A42636CE85778E8D0D7ECAC63B1E5AD97B095EB538ED53C0F20E31A7B5C",
- "identity_type": "private",
- "iv": "CBC6CAD2BE51F64BAC34C059A1CDBA3D",
- "key_seed": "1B755890B9282E3D75A62CF30D8B507C526AC4D69A87DB688EE1ADE45E6FE64C",
- "metadata_key": "F1C7FA9D59151B942260D9095ACB804D",
- "section_mic_hmac_key": "8B88E568964992FFEA8B172CEC92CF35A09C17DA53E3B6A4178F30C69E30AC94",
- "section_salt": "9B3429DD955B53030DE7A0949F8051C5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "46D9D063223E48E1437D30D40B5753F8",
- "aes_key": "F648B73CE969976B039A16A28433F333",
- "data_elements": [
- {
- "contents": "",
- "de_type": 181
- },
- {
- "contents": "4E76A9FE722A",
- "de_type": 265
- },
- {
- "contents": "8CC7337D6BB03B7659C537AF883BA4CB5A6831CFC821ED8F",
- "de_type": 571
- },
- {
- "contents": "61137B10A9EB95EC8B9988C92C8AE58084962EA4EB8A0DD54F4E28AF82",
- "de_type": 963
- },
- {
- "contents": "F90154329E618F408A44",
- "de_type": 319
- }
- ],
- "encoded_section": "8B901349AA55BEBA93CB2C7A54840B9FBB35CF911000FDB1B9359452E3E2CEAC0DD0CDD50EFC9004984C75297EBDC0AF9A194C52F8B51C4E091EFBBE21423579FDD7E020426A58EFE96C0B50D4FDE6835CF20CEBAC6A24718A4423E3420765508987C19C056C8E56231261FE9537C604057D374C7F21B3C7EF84FECD99476B2ED180E4B2E60C0D066F71808D",
- "identity_type": "provisioned",
- "iv": "B52F5E947B987B2B1BFDA86CFBAEB325",
- "key_seed": "71264001CD0F41F3851E55A3694A78A3503C5E9FE5A0B3B3B7AB8D502E49E667",
- "metadata_key": "85510A6F5299C7CEB851856A36EC426D",
- "section_mic_hmac_key": "194A3B0426B099DD77F0381EA83D71887298EF577A42D30518B18C7A34B51A07",
- "section_salt": "FDB1B9359452E3E2CEAC0DD0CDD50EFC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E0858ABAACE0527B975B26851C8292C8",
- "aes_key": "CDF94C859322D6AA6A30EFE4D2038652",
- "data_elements": [],
- "encoded_section": "3790138224408F0C54B5D42BEE2FC498F3011D911000DB852F256100992EE97EF0F6F931193B90049FD1BC537CFC7F362C6398CE8C7746C0",
- "identity_type": "provisioned",
- "iv": "D19FDC0000D6D76E0CE605C96FE3ED88",
- "key_seed": "A67946C15E4AEFCAEA932BE2B26CA22A3631CAF3963BF24BDB7A839CBC4215B1",
- "metadata_key": "034314A9C047377E60A04D4D6D24B67E",
- "section_mic_hmac_key": "D37426DEC6209A1AED271135308F665981D7DE9C2250A7982A68FD129FBC597F",
- "section_salt": "DB852F256100992EE97EF0F6F931193B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E5D850A6B98731806DD70FE80D14C57F",
- "aes_key": "45F17F2A11C37D39EA2E14EB6F2CE1B2",
- "data_elements": [],
- "encoded_section": "37901322ACBF267B3AC6BBD623E29E4C3CA73A9110003B6349B2E28BFC8EAD832D04EE1D41C6900495D0821E110F23240CF70BDC718DC1E0",
- "identity_type": "provisioned",
- "iv": "8A38DECA4DE45018DF71E0F5613FE0B5",
- "key_seed": "FF31FA9C59DF8135328628787FA48637CD6AF39EF0787506983782D7E32BE634",
- "metadata_key": "6C2A4E42EBE23C4D726F76B9FEEE9C18",
- "section_mic_hmac_key": "F05B9956C3C0EF6621FDADB68DDE990EF64AEC91603107F728EC761C32FC3C17",
- "section_salt": "3B6349B2E28BFC8EAD832D04EE1D41C6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "92BC4AC64813CE0FBCBF063580B8450D",
- "aes_key": "46FC81523837471CC7B1132E3EAAF8F1",
- "data_elements": [
- {
- "contents": "3C5DB709AF6BEF1A6DB5",
- "de_type": 44
- }
- ],
- "encoded_section": "439013E00AB739B468075FF17A2F097CA281CC9110004DAC6BD9A7A7499B7171120940ED042990018B201683ED366466ADFB2EB853E969162DA6AFAD259C2FCECB94858B",
- "identity_type": "private",
- "iv": "2F91E5A6914064B461D1C006ED76FA2F",
- "key_seed": "863FB479EFCB6FB70859DFEB44427143E0D5784CDA22DEE6280D75E217720D82",
- "metadata_key": "7A7F61C5B138A412235574D1A509D1B3",
- "section_mic_hmac_key": "1FCF532394A9A225DF35E2544418E724EACC389FA5E033F8958EDFF1717C6D87",
- "section_salt": "4DAC6BD9A7A7499B7171120940ED0429"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A47C02A4CFF31760341922681C976C9B",
- "aes_key": "CCC21FB62FFFAE008ECF5BD0AA3AF62C",
- "data_elements": [],
- "encoded_section": "3790138F26A8BE5D75A6F6F8F6CE5ED388FE35911000FCEDAA0772047E6085B7A3DE0656591B900427E950F6D62A13D2BF10F3AE70CF99B1",
- "identity_type": "provisioned",
- "iv": "748F18DC41E1742BBC685E0F699A8A9C",
- "key_seed": "43902BBA2C0D479E16711B145C936CAFDE2EA717B06E48F913861605673E4352",
- "metadata_key": "225F23821A1821430F1518C514C45FDE",
- "section_mic_hmac_key": "EAD438CB4DBB42665F5EBB51578C6889268CF032E82446E6DB78F538CF8D2008",
- "section_salt": "FCEDAA0772047E6085B7A3DE0656591B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "529EA628E2445A5F44FE204E7287CB83",
- "aes_key": "D077D4226135FE3CC4E82D9136D013D5",
- "data_elements": [
- {
- "contents": "9B815B76A0BE",
- "de_type": 794
- },
- {
- "contents": "F0176B0CD2D7ADE497BD",
- "de_type": 585
- },
- {
- "contents": "FBBD3620FADB7987C5",
- "de_type": 951
- },
- {
- "contents": "6E6D2A26D45B22C48FBFBF5BA353822DB5",
- "de_type": 689
- },
- {
- "contents": "",
- "de_type": 824
- }
- ],
- "encoded_section": "709013ACD9FD3F06A15506252D036301A1D1289110007FD227289748907CC788A03478E4C4A490040BDE2788F193C43DCFE364FAD39822E9693F9A61EC2AF84BF6E409352D804375946F04F76B6C8CA105D29896668E6509C7D9A2B12345E0FCA01318A33066A052344AA55973E26EC11C",
- "identity_type": "provisioned",
- "iv": "21FB688EE8D48AE0204DD0FB6723BDFD",
- "key_seed": "09BC65B83D4A9DD8E665C350AFCD428364EE0C429A26432718129B954AABF45F",
- "metadata_key": "0A4BF92CCFBE7EE7BA20212B2C9BD9C2",
- "section_mic_hmac_key": "2B29674CEDF3923E447AEC380E9A5971EA8858B669B79ABE829731A48A69D46F",
- "section_salt": "7FD227289748907CC788A03478E4C4A4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "27F532D8AC32634E4CA75D32B8F21CF0",
- "aes_key": "C286EC660EBA9F0D2EC7A6303A73DCC8",
- "data_elements": [
- {
- "contents": "556D2EB5364D03B0D15BB6C2FF22",
- "de_type": 982
- },
- {
- "contents": "250D3A6C86F50DA0",
- "de_type": 215
- },
- {
- "contents": "B0D390472D2E4730981C8C9B5520",
- "de_type": 879
- },
- {
- "contents": "4BD0DDF2F7A591B4F423B8",
- "de_type": 519
- },
- {
- "contents": "2DF0B2BF2276228A5DA4C99B0E308A7F75B4288A73230B0516",
- "de_type": 301
- }
- ],
- "encoded_section": "8E9013B2FE9B4E230BDE0A6B4C680E38425A88911000AA44252B7B0597D8CAD27BB2DE2E932B90024B03F77517B8733BDD7FC4A6EFF00D0CD0E9136611DF78E7069F61888E95212A50981F152A7962DA910D35D28A87D0FF7AF72A0698459C5AB90373F3ADF7952A8565B1787C0D5FA6C2AD85E3F2C818AF0D7FCC321D29632B3FE1A9E5B0953249ACF71A5D6D6A20",
- "identity_type": "trusted",
- "iv": "40F91D78B10069B117960376FABD0D24",
- "key_seed": "2FD8F442EDD094DD39EC00AA2CFB7FD0675A1BD7F7941D4F53D0CBD82753E8CB",
- "metadata_key": "4C3D9AFFE510E1966AC131A89E1F7620",
- "section_mic_hmac_key": "A54C280F5756F9FA52C63779EBA43987D19A7EDEFB9967AB425BADC59BF61817",
- "section_salt": "AA44252B7B0597D8CAD27BB2DE2E932B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D4E5C889DF978118233B27AA4104654B",
- "aes_key": "970E140CD44D7A04EFB008734CEC7010",
- "data_elements": [
- {
- "contents": "85C4B76453D6E516D361CC73B263CE9D034720445802DA220ECF657A5F3E",
- "de_type": 271
- },
- {
- "contents": "E32FD49D906691",
- "de_type": 731
- },
- {
- "contents": "7B3C90A05085048B6179D21AD5A6A86A6ED4F13A5DDCAA6AE04E6B98",
- "de_type": 768
- },
- {
- "contents": "032F3243",
- "de_type": 307
- }
- ],
- "encoded_section": "889013714CDBCFDC9979F2A631D817CD6F5D81911000B686CC2DD9B1CAF68D2D40641EE8586990022E34067C0F459E6DC7270F4800ADB3332572AAF09C0F3F02D96F7B1886C9AB3337693E4FF929CA72EF3EE3CC4F5A812200784AF925FA20CCAD85A5AD7852BB76CA82B942A1A9BF7BADB315844E595BEA39AFCC17E1DBB66B6E048C605B7441F676",
- "identity_type": "trusted",
- "iv": "82D4C9AA85D158ECEF4066430E4CA88A",
- "key_seed": "08D94818510EF93C263C2F1F29CF026DD9492D6A51C9A8CDA500CA1286DC8548",
- "metadata_key": "14EC5B29C281FEB2AF4832FB60E1906A",
- "section_mic_hmac_key": "51694A80381B233D9DAF1ADF4486927BEB090BE27033C68E4C767C3AD81FBD32",
- "section_salt": "B686CC2DD9B1CAF68D2D40641EE85869"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8B3ACC135A6B5C8563C100BC132C3012",
- "aes_key": "EB39B2E41C39888C378B488AE2905CEB",
- "data_elements": [
- {
- "contents": "5CED8B3EE06AE3BF23221CD8516F5A320D",
- "de_type": 306
- },
- {
- "contents": "D44E64F4CCBB96259885825F",
- "de_type": 621
- },
- {
- "contents": "9993FECFD946C4409519E9A3178868E99C9C2F715A",
- "de_type": 956
- },
- {
- "contents": "D61947350812F913D6FCA86D0BE8543C399D",
- "de_type": 641
- }
- ],
- "encoded_section": "8790132D65B8942498CCEA42A0D804A1C01A6F911000D8E290276E0858486D84502DD4CA687D9002D38DF4747B01659AF237FA5A531219AE5136549DADC2B7E717B8F02BC335EE5C1F0D56EC2F477DC8E5F6BD3D376FCF4E0D9D5DCA895BC72F259F18A7F731F595156293CE9237BD2CF392B34332ED00E56695AEF9AB71DBEB9E03784760D8FDF2",
- "identity_type": "trusted",
- "iv": "3E60B91D4AA0323C5F01E0E597ECF1CC",
- "key_seed": "7ABA9927D395596BAE76B09B53E3747C14DDFF26299CEC1C3D27251187E18D53",
- "metadata_key": "01F04DC463DFCAAF77C09879E550F4DF",
- "section_mic_hmac_key": "9CAA148E03F3E71D5E61C523CA945873AAF055D6B30AD66FE2D4D00B3701769D",
- "section_salt": "D8E290276E0858486D84502DD4CA687D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FF3B16C4698751E68F84DE97F35A5FA0",
- "aes_key": "3BF5EE085D208F3D6E5A6442013C725E",
- "data_elements": [
- {
- "contents": "ACC85C",
- "de_type": 664
- },
- {
- "contents": "83F79F7267E22A6F772DE90F3B3AFA",
- "de_type": 179
- },
- {
- "contents": "50B49C934D255C07EDEDB85D21754295DEE043",
- "de_type": 991
- },
- {
- "contents": "9BB5F0D259BDFA70B9",
- "de_type": 118
- }
- ],
- "encoded_section": "709013B5B1766D569DF4A453ACE83B0F38E916911000E37D1545FE3474350536BBFDA3FF986790028E3033EFFCDD3FF351F65DF657B9E78DC235D1597CFA8775D2CA4C2F8B6BB104CD9EFF986A2448B871BFEC865668788447245F0AC1B6E24C869C93D25DEFD64D3935B781AEB3D6A8AE",
- "identity_type": "trusted",
- "iv": "F2878B2027076B2D71D6F9871A2F0D03",
- "key_seed": "A7548D59575A8ADF65ED6E5C2B91BDAF3E49F4420BCEA25A47F2DFFA66A6FB40",
- "metadata_key": "A7689FBC874B5252F84B652A6C801ACC",
- "section_mic_hmac_key": "1B247C85EAEB89FAE3D9A6F57B342AA2EF11A3D31F99B92B2BEDC33F25E24365",
- "section_salt": "E37D1545FE3474350536BBFDA3FF9867"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "376B1E2353FDBBEE04421E92268F2137",
- "aes_key": "B99788E0D39B29BCD2CB9914602DB519",
- "data_elements": [
- {
- "contents": "9DEF31274C87EAF90C3BE1E286CA6ECE487A9592AAA5",
- "de_type": 832
- }
- ],
- "encoded_section": "509013D0FE03AA8832621507D192A7A032A6AA911000B672CC780DFC5CA8872ED98841695B5190014330021041DAE80CAF03A0921B48EE4DAE14F5A1D5B70B181E47B17DDE48F9E7EE753FB7461464C071",
- "identity_type": "private",
- "iv": "8A479EBF518ABDD0F8B6E2DD6E6C3DFE",
- "key_seed": "038F101C0818A96A4697FCD0C04F83A5E8B305D020C2B1EBD9EF9F2DD47A3A68",
- "metadata_key": "74BB45EF94F7CB36DA9A6E8922F968BA",
- "section_mic_hmac_key": "DE187BC6A18B7BEEB0F080D19CAE3A966B04B11F2DE3E0B3A4839B4DAF642BF9",
- "section_salt": "B672CC780DFC5CA8872ED98841695B51"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4A68B75255C47966CFD09D3E6F4D0F00",
- "aes_key": "F40B55E81D5218A9C153B4A518EF7965",
- "data_elements": [
- {
- "contents": "1206302B0C2DA5BEF95E297A1002C931B1A561AC0FEF82E59232",
- "de_type": 975
- },
- {
- "contents": "4C7B43DDC3DCEDFBDBD82A0E",
- "de_type": 106
- }
- ],
- "encoded_section": "62901370EF584FCB26A18F3353C63B2C6E550A9110002346BA971CCC84FDB572925FDD8415EA9001C180B71BDFB6D03797769B28831D787CC1E34B3D68475BE6BD52BD446FC1F98D46CE95A4E95D6675F751158AA2F32E80E31EBBCC9849E1B38B61CE",
- "identity_type": "private",
- "iv": "3C79194828BD1CAB4830FA2EDAE139B5",
- "key_seed": "E702E9695C5F7A8FB6B07D8826DAB5E93DF485453C1D47729736C247BB5B1989",
- "metadata_key": "9496D7B7F81FEB95A795BF7D0094DD22",
- "section_mic_hmac_key": "ED70B19FD1BBC280589C9760473339DE84CAAABD844B7E5B6F373B4F2DFEA1B8",
- "section_salt": "2346BA971CCC84FDB572925FDD8415EA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A7DC2F6205111E24BC5D3E96A4036E2D",
- "aes_key": "948FB743319951D6EF15792E57C44CD0",
- "data_elements": [
- {
- "contents": "17FF183A55CFC3D6F761A4319DE5D307A3BEBB8337945B",
- "de_type": 437
- },
- {
- "contents": "14FE4641B1B15E",
- "de_type": 850
- },
- {
- "contents": "309BBBC5FD371BD50A09BF5C1935638EBBA64CED26",
- "de_type": 578
- },
- {
- "contents": "82FA4B93D7E9E8E48C452C3765F30212C5D0CE308E",
- "de_type": 986
- }
- ],
- "encoded_section": "8B9013531B7DDA6851D5A468CF7BA6FCC96AF19110009595A85248F0E068EEBDBFFC4A67064D9004A0AD96175DB820F281BCA29136E3FA64A1E0599AE13172AB44649AAC952DCA3FE132D516C5735C86E2AF6D741A69D75D3362D18D9C9CF9218ABDB944A24C8DAF25648A3C76334BF4668F17C1A693891BB74CFCB98A0E6F3E4F7B5E7F63ADFD626CA50BAE",
- "identity_type": "provisioned",
- "iv": "2C85C7E9AD55CD74962F7494F73F381B",
- "key_seed": "7C486876D239CE8820A1F0B2DB610DB41CA61A7AE8B6BEEB0C908624D6F8C73C",
- "metadata_key": "4C62329C44D38B35F5A124CDB6DDB4ED",
- "section_mic_hmac_key": "A147DDB86022B7B38A5A0EF46FD8A5A3AA8EF58F1A3B29D67692E8DB21CDCDA1",
- "section_salt": "9595A85248F0E068EEBDBFFC4A67064D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7AC5CB315FF73D315B9D7BA673EBBA60",
- "aes_key": "506C8FB709BD805F07907F3CADA63A4D",
- "data_elements": [
- {
- "contents": "2FF3236ED0BE30DBA2EFF7B322460D50CBA1CEA89A73D48E002122",
- "de_type": 189
- },
- {
- "contents": "29325485",
- "de_type": 667
- },
- {
- "contents": "BE1D11D85F08DC5096CB2C",
- "de_type": 755
- },
- {
- "contents": "E5A8D258FA69",
- "de_type": 265
- },
- {
- "contents": "54E1452EF7918625F1C2066886",
- "de_type": 395
- }
- ],
- "encoded_section": "839013313C5AB1D44BB73DB9DCE0A44381CA5F9110007CAAF0C331734518BAD5BC0AE39D6EA690024326AFCA074771D3B7122DDEAD650CC13735E349EE776FCBFE42C28D8AF0B04F72F453412F9ED8F79D05387362CCEB5893D18016C30315C51493E7A4DA3F0AED6B48B92F3A1CA3A7F3EC8508E26C18B1DF167AF4220A79383D06C697",
- "identity_type": "trusted",
- "iv": "38F542B60DDCF1889C98F636AED0DB70",
- "key_seed": "AE9FA4DBE8FE02012923C404592B04CB6645B07CBC053BBC849BC860169B968A",
- "metadata_key": "52EAB1D56E20ACE3BFA4998ECD77E75E",
- "section_mic_hmac_key": "0F5609DDE1DE5F239BD1F96B1441DE52BC2D5ACD27064FA3007C0652064124FA",
- "section_salt": "7CAAF0C331734518BAD5BC0AE39D6EA6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1371D42BB56CC9589A4E711E94003CF1",
- "aes_key": "F89B50E8D592AF6598CFFDD4631B98F7",
- "data_elements": [
- {
- "contents": "BD965E4D7FE3BE0983",
- "de_type": 915
- },
- {
- "contents": "71317D36EEBF7AA7C774",
- "de_type": 130
- }
- ],
- "encoded_section": "5090134DE55CD88FD6657759CA777FE2A6A5389110006380196708715DC7A15514FCF0C680BA90043BE3270FC1B56DC645FB6F2FE08340A78A7AEE99B6E701C28398BF90CF6A234F664F39263F0B1C12B8",
- "identity_type": "provisioned",
- "iv": "6D5FF6F65CCD1AD3CE0E402B14996B5D",
- "key_seed": "2A965EA9FE93E8AD29738534A581AE4063AE843A84FA26BF5AC4DE9EDE3CD9FB",
- "metadata_key": "2F754F4C60734B33C40721F3E3F65157",
- "section_mic_hmac_key": "53F2A6DFD7AEEFDE014E55D7BF8840E5D7A573029BD9BC789F4AF5D83A0FE4FC",
- "section_salt": "6380196708715DC7A15514FCF0C680BA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5852F713F32A45F394D6CF1503681E71",
- "aes_key": "53579F776F4D91AE48BAA741D51273CC",
- "data_elements": [
- {
- "contents": "264965713C4FF4C23F6058",
- "de_type": 957
- }
- ],
- "encoded_section": "459013250493378F298B2F0FD41D3F26496997911000E097C08787305AFFF05C26120584ADCC9001FCBDE7AD1AD06682B2B4E0E9BFBA96CF731B887DF56996A8D3F184BDC5B2",
- "identity_type": "private",
- "iv": "586BF8EBA8BFC91CF524513850FA6CB7",
- "key_seed": "C1DC5EEA6320D89745E956A59829A9F12BFBB0E84D5702D4323A073153A402D0",
- "metadata_key": "CABC965DC85DE1CC03766E3C3AD89955",
- "section_mic_hmac_key": "E5BBD68BC259259BD8D7456D0028F4F9ADE138BD9ECBF8B08121095E5385A104",
- "section_salt": "E097C08787305AFFF05C26120584ADCC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B6AFC51F6469A1134FC9F3B79C63B648",
- "aes_key": "0AEFE23D6E06401C54B9EDFD128EB043",
- "data_elements": [
- {
- "contents": "E592EE15CC4A379D37A1336E8AEA",
- "de_type": 177
- },
- {
- "contents": "16A5D19E7D776BB328AAA2",
- "de_type": 167
- },
- {
- "contents": "7667074E7BAC9ED1071F6D802D",
- "de_type": 32
- },
- {
- "contents": "6422E8",
- "de_type": 397
- }
- ],
- "encoded_section": "6B90131C4A85CB414A096694AE91D2F80F642B911000B029880034337B48522C5743B764F6379002C54B4FDA4EE62DED8E3CEDE200278112467A6BC315CE1394D3305D6AD8389019B042E52B123A729F5FE8AB7D12E16D97D997E926B5B77E72E744C28708F78FD46C9DA7C1",
- "identity_type": "trusted",
- "iv": "00CAEF5FD9AC22C1D4D849A1F8405E97",
- "key_seed": "CAA6234004DDC5868F8754AF727A16EB9CE58007EA363B77ACFA131DA8B8DE64",
- "metadata_key": "E0EB0DCE07B9F33812599159F0966193",
- "section_mic_hmac_key": "72A1D922D6D948622CE8A79C84EB61176C5A4624E5879BCE31312C46B7A124A0",
- "section_salt": "B029880034337B48522C5743B764F637"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FAD0410EFA60449825FFC8516A0FB3B5",
- "aes_key": "3A65582FCAFB3BDAD34815AAB02C6A0F",
- "data_elements": [
- {
- "contents": "F1E69503995E087568407D6D4A43E62530AAE4D1F234446F",
- "de_type": 395
- },
- {
- "contents": "D324E4CA9472C8AB06D88FE419426C232D883A67CBAF486BC6C3",
- "de_type": 260
- },
- {
- "contents": "BEB0E1",
- "de_type": 153
- }
- ],
- "encoded_section": "759013EA5DB79A4B63F265C79FAE27A1E26D32911000FB31E0B50B916E1F3ECDE7E827BF50E29001F006CF03659E34A07A5AAC66EB68D19ABD36C2B2B95105487E089604722037191C1B864033FEAE9E902C9085A4DAA25167B29E6158B30DF8E0FFEA9F8AC5523813593B4EB612BA146E7FC0020902",
- "identity_type": "private",
- "iv": "B9B5A13C98A85049E31086ED7F63A8BD",
- "key_seed": "5ACDFEBC110EFEAA985EDC3499B192C4C63780076D69CA3453E33AA31B1FD782",
- "metadata_key": "415BB381B6F26519F4A8C16B3A2B2E38",
- "section_mic_hmac_key": "617D53C2A4797B14451D556CA739B28CDC74C11599BCA1AA0CC5137AE1E06D64",
- "section_salt": "FB31E0B50B916E1F3ECDE7E827BF50E2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A0672D9DBDAC66877E4CADA6575E629E",
- "aes_key": "FE14C2D672CD9D635AA444035A977DCD",
- "data_elements": [
- {
- "contents": "370473F9E9A4CD",
- "de_type": 331
- },
- {
- "contents": "1091627363EA5D",
- "de_type": 599
- },
- {
- "contents": "26D956645FD5C2BB41",
- "de_type": 831
- },
- {
- "contents": "725282C70B7EFAFA41DCFB83486789",
- "de_type": 703
- },
- {
- "contents": "A6FCE9D3F92AFF803A2EAEC9ED854C84DBD836C2E53DAFF2FBF42EF9",
- "de_type": 208
- }
- ],
- "encoded_section": "889013DE18750F74B8F143F9531EC602C6F8D3911000DE2483B00AB55A180FF1F9B1F841FD2F9001155420E62FB73633F34D463D6FB6BE6C43CDB46D66BCE9BED579D8C8AF270939D8CD5B758458BB6BF168DD2189A818A421C46177C681B3AEB51971C7EAF979D286C5AEE7C5C8B9F4B2A024629B0481555FB6B91D72136640AA6259C98B6A161869",
- "identity_type": "private",
- "iv": "7FC34F901F1CA946F025BEE913D80805",
- "key_seed": "0E323E4FA86CFC101E020EC3794DC949AB5583CC705081F7EF17098750114567",
- "metadata_key": "F6DD9E9867B8367443C7454962722B5A",
- "section_mic_hmac_key": "8B0D6438887EE9AEA8B4AA0C8A3B51348696F8D714ACFC329ADCCAA94D3FA90A",
- "section_salt": "DE2483B00AB55A180FF1F9B1F841FD2F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "96F1F913702F12AE480B7EAB21F2E29F",
- "aes_key": "7286CA7480D60CCE64380194BBB16219",
- "data_elements": [
- {
- "contents": "2D8051",
- "de_type": 395
- }
- ],
- "encoded_section": "3D9013A36724A659838BA6715EC43B10B6018D9110004A50460AFDA8F4151FA5F0D09AB9D3119004351C5DAC336A78804914EABF3048100B413604ED1804",
- "identity_type": "provisioned",
- "iv": "9FD8B714A92F6DF61BD8313AE3F7A49A",
- "key_seed": "3A032816A0CB8C6047394D942A569235A698EF81EECCDA4CE2EA03319FD31EF7",
- "metadata_key": "DCFEE171874E4F3F44CE3F4C25284136",
- "section_mic_hmac_key": "4F27828BA59BEBB1BC8D5491A8DABF3B0695E48243CEAC341E6B466FFB1E45BC",
- "section_salt": "4A50460AFDA8F4151FA5F0D09AB9D311"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49C3EE4484207ADDF24542801C4A8BE1",
- "aes_key": "CB1A44E35190A0A40391E9AC0352CF0D",
- "data_elements": [
- {
- "contents": "D13E6A67AF69CD4831EA837B4EED38",
- "de_type": 118
- },
- {
- "contents": "6CBA9A5D81EE86",
- "de_type": 576
- },
- {
- "contents": "91806A710A3CB7C48C7F9B",
- "de_type": 141
- }
- ],
- "encoded_section": "609013306C20AA4B9DAC542AE193249ED0B4F0911000EFE9FADED32A35322200ECAC8AA2881A90029272DBBD9AAC8A12D6F6004F781D1F4D52EA2D558745FB470410EBBD4C176D934B79E574A2E302C32B6AC058CFC3C4A97099EE579974607E94",
- "identity_type": "trusted",
- "iv": "8B897A7D823EAC1B4DCE4088B1239438",
- "key_seed": "97C8CEE0EB78ADDA0E9ED93B32D7578C1C79FD019B59C4FFC93C243608CE3FDA",
- "metadata_key": "07C3B3BE5A728497F903AC14CEB46CAD",
- "section_mic_hmac_key": "8D485452833BE483BCCCFD8AC29D62E88798A74B7B0211930CEF86928D20D8E0",
- "section_salt": "EFE9FADED32A35322200ECAC8AA2881A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "29332896433E0267F1BEC7C68F39BD0E",
- "aes_key": "52F52B3912CC1D4375D4C7CC363A06C8",
- "data_elements": [
- {
- "contents": "E71F91C189472E376B422A2BBCE9CBF608F93D7480",
- "de_type": 480
- },
- {
- "contents": "147B9B4DCB0E6D249DE2C41A2AAF577F6EAB2662D792ABE203A602B7C1E8",
- "de_type": 382
- },
- {
- "contents": "193DB2CE325FF3211237EF564F4876",
- "de_type": 447
- },
- {
- "contents": "22F03DCAE07E9F63B095F57A37A90C72708295C66BA5B46669272AA16D",
- "de_type": 335
- },
- {
- "contents": "6223ED9F71639C2228485250CAFE33C98E294D76C1704A539157C6CD5FDF",
- "de_type": 324
- }
- ],
- "encoded_section": "C390132F02AE5C28B3D32341611CA5B50CB2D491100071C1B6B18B6BE3F8B10456DAFC58DE4190028D41A79087A8FF6623388489853F49A93D41BF1B458A34D85AAC3688B1E883037A0DEB66DC2A3948DBE513A5A2FE44AF75A3CE8DB96F36C7B7F289FF212BDECF375BE179F3200EEBB9FB185E4356005527031F37151971D546F2973D46F00B4F6A0C669725E69A70B6726BAB0553B65CD4FA49F1B56BFABF1A34A7B9543A474B7BA7E74CF7D212F9FDA74A93071B20ADC6A385081922658E66B27267",
- "identity_type": "trusted",
- "iv": "C86F257947D0FBEB5F1C7A0F9901D101",
- "key_seed": "DB73F443904842E9F64F60B67EF63825A2FE8AA122B4633B5782B6FDB976BC47",
- "metadata_key": "7F5EE2AA799A8E4E3F79C30E7B77B176",
- "section_mic_hmac_key": "FDC07A4B26BEA7D99987AABF4E031FAE14538A0386922659B5FCCD66913FAB57",
- "section_salt": "71C1B6B18B6BE3F8B10456DAFC58DE41"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3709DEC44BEDBB170C7652F0248E9DE7",
- "aes_key": "400777F0893097082B132E298D6B2B0C",
- "data_elements": [
- {
- "contents": "0C4B67C6D9434B025D8E75580C8534E0C7851104F102E9666B131B",
- "de_type": 269
- },
- {
- "contents": "E2C34FB045408D602FBA91CBE2DCADFA",
- "de_type": 815
- }
- ],
- "encoded_section": "689013405BED7C212DD107163732A69097B11E911000861DEAA6AD7EFF607DA016E4DE278FD29004937E2B1A97EA25A4AEFF38D95D57B4188ADC5AA57A1B38E4A86FEDCDFD5903ADC9EDBB7EB35B96A689D83FF35BFD7962DA302437DD32394EFC9B8DA42CD33CAA5A",
- "identity_type": "provisioned",
- "iv": "1CAE6EB0B86F8C40C325FCAD7BC975A3",
- "key_seed": "C91B9ECAE0A8EF1646B96E3C6F06B99C5A01B0904E98349BF7974E1ACBBCDC68",
- "metadata_key": "DD8A480B4A601C38C0FB3B382E646A61",
- "section_mic_hmac_key": "9BBD9E8CC618CBA17F36BA2593ED4C05DEB69B0F69F2D2917CF37285E62DB629",
- "section_salt": "861DEAA6AD7EFF607DA016E4DE278FD2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4992036A41F8E54D00A1D3D4359A9300",
- "aes_key": "69BECDC75EB309182C3DADE59FEEDF92",
- "data_elements": [
- {
- "contents": "8B591A5CAF41CEF237A220785B",
- "de_type": 941
- }
- ],
- "encoded_section": "47901308D7B199CE04C602DE931C37B8E0CDB29110001463D56B2F97E53F05117D1D414DB9A39001CB5CF571A7859271C1CA2D95AE0F4557A8B146FF2FC636B1A6C948A7136E6F10",
- "identity_type": "private",
- "iv": "6B12EF5D3282AC2EE71A0398322D3655",
- "key_seed": "B306946230C730CCD3B93C0FD74760734AFD01F5DAF1A17BD648505A6439C3A2",
- "metadata_key": "C42D7A526D780B5D5E46603943A3FFB0",
- "section_mic_hmac_key": "821AF2677045D3BAF8341C06C72F0476DBF407FA38967F3B08F060E42E2A0525",
- "section_salt": "1463D56B2F97E53F05117D1D414DB9A3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "04CC1B63DDC7EFE20F035A5CA57AEA43",
- "aes_key": "60046C736A3EFCD5DEA769D6BCFE3654",
- "data_elements": [],
- "encoded_section": "379013C978E90C73B9CE22075761B22E7B66B0911000C031142EF1CFE2DBCFA88DBE7038F4339001EA998FA7111B16AAEE5D76DCCE34F832",
- "identity_type": "private",
- "iv": "1425BF85545089772F7A0EC13B31F218",
- "key_seed": "29C84402ED9B668C4B419AF8CCF3FC53BB771A5E41BBA83FC8D5264E5847F719",
- "metadata_key": "0102525542E84C81FE13D0E70A4512CF",
- "section_mic_hmac_key": "4A51F7871DC1B6363526C10EFFFD3492F38B5C352DFE2EEF206A9D8508BB8FB8",
- "section_salt": "C031142EF1CFE2DBCFA88DBE7038F433"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2C87AF2AA5587D0D186ED5420388AEC2",
- "aes_key": "2DA61DF51325B07DBC63B481DDCDE64F",
- "data_elements": [
- {
- "contents": "6DFF113A772C2EBFEF3BBF18A36294FEF1D734BFC360C376",
- "de_type": 548
- },
- {
- "contents": "89A698C96D173176BBFC3538AFBEF049CC59B34B14",
- "de_type": 546
- },
- {
- "contents": "E2F16DB52F89",
- "de_type": 266
- },
- {
- "contents": "DA22DAEC64B917FD589D805253",
- "de_type": 685
- }
- ],
- "encoded_section": "839013EAA633D971185BFABB394355E4E31064911000C21027A41702F6DFAE49F1629A8E39699002BF31A3881922775031E2AAE919D18CBDFD195B02DA0445F61DEB7B7E655C8A975938B4A47F0FB27356C8A419774DF6A0FE213E84BA6EA1A0EF45F40EAED8ECBE37E53BC6542DFD0D3E582227E27A113785022CCEEFF15D15D94FFCA0",
- "identity_type": "trusted",
- "iv": "AEFC3DD760BF1C8A0C4D3F4D6F4332B6",
- "key_seed": "63CB4A41E5862904E15594B7FB570AB2D20BEAF67CD053241796583FC4BBD471",
- "metadata_key": "D1A562E45D9D59A9011D511728F7543D",
- "section_mic_hmac_key": "BA11FB7271F9021364AD11352009E9452A74EB81FB340C526D9D2F5DA0CBEFBF",
- "section_salt": "C21027A41702F6DFAE49F1629A8E3969"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "79906A0C8EF398B55A1B7D6626F780B2",
- "aes_key": "36EAEBAA45DA5B60809CA32832414FC5",
- "data_elements": [
- {
- "contents": "FA3FA3A9F0756E567E2A801656",
- "de_type": 868
- },
- {
- "contents": "45F76C1B",
- "de_type": 816
- },
- {
- "contents": "B3816FC81347A8D40FA3937BC2CC82C137D7B6067751AD29CCEFF635702C",
- "de_type": 379
- },
- {
- "contents": "360C1E18456ECFF656F8AD95220EC360ACD246BF31",
- "de_type": 213
- }
- ],
- "encoded_section": "8790133E894393E3BA6C82A326DA85D9031F089110008C2D013111DCC58A0DA04E0EFE9C45319004864DE8CBBF7C31B013DD161A12A92A2C25E57FD4465391B1E1A51F6A7420EB21A6E72917783613E65E885B08BDA69B1A6015E249A2912B3EC997B8972459459270601B6AD2A41BC1E73976A86D8FBE6473C844C32157575412717212D045EDE9",
- "identity_type": "provisioned",
- "iv": "0E4490BF80B78BC51FE57DB85EB61ACC",
- "key_seed": "A8850343015360DFD5FF867CA561B5B41CC0B6BCCE62CAB56055E57AD7EE2614",
- "metadata_key": "84CDFC0DC3222FFDBBE864870E67A8D7",
- "section_mic_hmac_key": "35A9250370418DA082D0649DCA2C1F2C5581EA3B444905B33D83601A1B16C1FB",
- "section_salt": "8C2D013111DCC58A0DA04E0EFE9C4531"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7DB249FB5D7BFD40D6D94D4AB36E91D5",
- "aes_key": "1236191281B7E6536582FBEDAF9DA8E5",
- "data_elements": [
- {
- "contents": "119D4427C80B8E",
- "de_type": 760
- },
- {
- "contents": "EC6A6CBDDF6848B16FF08DA7CF3FA284",
- "de_type": 739
- },
- {
- "contents": "B0E04C01243711008D6EA5D07C161F6195C5D3",
- "de_type": 462
- },
- {
- "contents": "DD978C138650CDBAE4",
- "de_type": 743
- },
- {
- "contents": "675E333C4398FBDB5DA8E19C",
- "de_type": 403
- }
- ],
- "encoded_section": "859013ED4DDEB3D0D051B4EED779AC376BDAD1911000C0643734B37286129B4562EE0BBD13909002B4989BEBC63EA94FB8B876A2BED6797B0BC4FB7579D7406D5BA3E0BB069BCA2503A413B61DDC92002924E14321086EDB5799981AE6375534852E18BBD7497FA7AF7613020DBA383848020A7D2503027F2141669BFEA617C2195E5608407C",
- "identity_type": "trusted",
- "iv": "9F2743DFAAC832E0F80884CD326918E8",
- "key_seed": "03B79B00D65494F60FF94D2606BB2E27ACBDC599D7255B2A74B96F631EB0CB0E",
- "metadata_key": "996FB9AF1F3A5C5465BF8704F76410FD",
- "section_mic_hmac_key": "49A636DF6F31E0E4D2A77EB1E6209ACF98AD16DB3E177E50F528116D445D3FA9",
- "section_salt": "C0643734B37286129B4562EE0BBD1390"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CEB98B4B0D841160C2E35158B1037983",
- "aes_key": "F053887925734FF405C94A8F3092C193",
- "data_elements": [
- {
- "contents": "5F8FE0C8238878BB",
- "de_type": 994
- },
- {
- "contents": "CDED7F45F36DD2BB6C5E5BE59E",
- "de_type": 566
- },
- {
- "contents": "B8E19720ADA1842AFBD9F20A979CB6",
- "de_type": 22
- },
- {
- "contents": "ADC17706EEF38EA4BF6842C76B00B7A0",
- "de_type": 864
- }
- ],
- "encoded_section": "769013FB3E7BE1C7C57B079D1C68C1FDF94F499110005B21E275525D3CB89AE0C75679294F3A900115D44F49C8842FF45C041D7D9D3715675882EEC328AE875937FF27A2F98D28FC0FA595179DFB5DF10527AA494524553C57B7E76DDDD9F18724CD4BD2891947A5CECA8486F0C59A5C62387BE80B7DB8",
- "identity_type": "private",
- "iv": "E0052D908B8B534F17012FE22FD8C1C2",
- "key_seed": "042A0DDEB37D4E1243415F80E9AC5FEBC7902B0F4EE29E7B0DCF9F6527D6ADF6",
- "metadata_key": "4393A5FFB48F851733D1B5A7B790BA35",
- "section_mic_hmac_key": "A85552BEAFCCC741A72DF287A142CF3F998231B97755E3C70FBA249989C053A1",
- "section_salt": "5B21E275525D3CB89AE0C75679294F3A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "745AFAFC0D37846B5E0C490DDCA6B0FA",
- "aes_key": "806FF3273840321E8944A21CBA372A14",
- "data_elements": [
- {
- "contents": "73B86820241EC5E7D125D74FE3D2",
- "de_type": 315
- },
- {
- "contents": "56DB7131D8D9555B",
- "de_type": 495
- },
- {
- "contents": "8E6A76DC340E0AEC07D79C",
- "de_type": 895
- }
- ],
- "encoded_section": "619013D03954EA8469566EFA768C74AC4D2261911000FB23753432B9B3628220D45365F2AF579001083DF8CE07930F669C932656AEE1259E713C6D323E8D102093CE210868F5BBA9B4851B1294C512B9D778BF43BAD9A859BF57409A14294A756E35",
- "identity_type": "private",
- "iv": "0E3C4A8E72AEF423375202C1176EB2B1",
- "key_seed": "60144BFB597852910B428D8DE204D6D6E7EABFF8CCB6B61F8274C2B38CD02BC1",
- "metadata_key": "BB66D2E7C096B7AEE4BB671BE9071AF2",
- "section_mic_hmac_key": "596D58D71B171946CF75F706CEF421DAD978584AD60E979DCC737D95BB7C0CCF",
- "section_salt": "FB23753432B9B3628220D45365F2AF57"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9B363547BB9948D07B69AA3892AA525A",
- "aes_key": "08E1C799F15F1C96C27A4A1B37AEC7A6",
- "data_elements": [
- {
- "contents": "E553E23A099E8329DB",
- "de_type": 754
- },
- {
- "contents": "D9037BB04B6E600107E7DF0A67566115EA3F619158D938",
- "de_type": 244
- },
- {
- "contents": "3571B7",
- "de_type": 517
- },
- {
- "contents": "60C498C9A191CF99BDB4C8BBC9201BABE9BAB9AB30",
- "de_type": 377
- }
- ],
- "encoded_section": "7B90138719640172A7CA979ECE524C2CCC5B0F911000C470C9EC5726236DC6C06A591EBBAE7590021E80E98CE6E81A29B6EA96E5B7EC0B496E21D40C10F430851949B30F38A1071A3E98BF8BBFC9CC8A13AB30B73518AA59D96DED687C9409A3C46EE8AB3A4B0BA118AD67F2492522AC66391FFE18E7F41520F12458",
- "identity_type": "trusted",
- "iv": "6E4892B791E5664DC249425A2E7FBC7C",
- "key_seed": "5A08FAE5D0EBAC61590102AA36711002B7800BF744CB7863766BA932F048B8B3",
- "metadata_key": "EA9F3E7C877395501F3D890721C96996",
- "section_mic_hmac_key": "2D774C8BF3CE278132DD7EA105A125A95ABFE9EE1EEDEF7A191DCCB02155B816",
- "section_salt": "C470C9EC5726236DC6C06A591EBBAE75"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "017CB0E1120225BD43E6B17407129A4A",
- "aes_key": "236EDB5FE7F023E81E2772AE8C371905",
- "data_elements": [
- {
- "contents": "FC6C",
- "de_type": 842
- }
- ],
- "encoded_section": "3C90139BDA46CDA896DC46E1953D4DF84DFFDC911000491F606D2C12BABECB46793C4FD4DD9D90029E9A317E650F42EABBEF539D64E97459ECE92C7716",
- "identity_type": "trusted",
- "iv": "3E43A43F32F7416F10FCAC7AA29F53CE",
- "key_seed": "C536746CE8AB786BF064E636500981AFD86FDAF6D4631B161AA93FE09EA47F0E",
- "metadata_key": "AE51F9455468275B5F1F3624602A4E76",
- "section_mic_hmac_key": "BA03F46EBC0147C0582AA5BBAEF21D69737DEEE365F042F2767D660B6597B2F6",
- "section_salt": "491F606D2C12BABECB46793C4FD4DD9D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8134AC1B9E894BFA8F57429D27BE03FE",
- "aes_key": "8E466BF38FD6488483AB864A1B9B2463",
- "data_elements": [],
- "encoded_section": "37901372B0E373CBA7A88E17D27393CEED2A9B911000580E141B47F88A102003E045B3306ECE900260CEC45B63507146E4F2021A989E4107",
- "identity_type": "trusted",
- "iv": "9ADDE95FF00ECAFC9BB6DBE00CF4D420",
- "key_seed": "DB86E0A4E7BAECD6971FD06F4EA08B999E321D18139B295E3820C5C0A1D9EA6D",
- "metadata_key": "AECE395205E92B4E824736CD2EE10388",
- "section_mic_hmac_key": "A892FDFC74404F4639A18BD6AA1C732FA67A3F76EA9A4455C241346FB6088646",
- "section_salt": "580E141B47F88A102003E045B3306ECE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0E11B8EB767BF23776B2242E7F80A17A",
- "aes_key": "CA4F5AC11D27A32BA5813B32CE9FD176",
- "data_elements": [],
- "encoded_section": "379013437CE707D51EAD22AF0E3D32C70129AD911000679009A3AB6E4C7835C13FA51C82745D900428D8BCD3A330E9A52A90BCD6C042E918",
- "identity_type": "provisioned",
- "iv": "4A026ADB419CF7A487500F4358C45D59",
- "key_seed": "D373D3E85CF5AA0813907E92771B96A67823D7D7644AFAAB76324814008DBB89",
- "metadata_key": "9E23DE492588EF5A6F10A9DFAA038A16",
- "section_mic_hmac_key": "C4A11FF865C6FD2544C54CB7D16DB70136AD68A4B663DF5F530DE273EE36DE4E",
- "section_salt": "679009A3AB6E4C7835C13FA51C82745D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C9CC54A5BD1EBB46FF5246ABC60AAA8D",
- "aes_key": "BF5E5C3153CF9792AFD6CDF96A2C5344",
- "data_elements": [
- {
- "contents": "9D4B5F1E5AB4A177310F992112F9BEA680",
- "de_type": 886
- },
- {
- "contents": "2D36CF0F4C8F1B36DDA5D23FF20EB6CD379F92",
- "de_type": 70
- },
- {
- "contents": "342637079BF30209525A62AE1D233B717E",
- "de_type": 396
- },
- {
- "contents": "D112664E69B12FDF70",
- "de_type": 38
- },
- {
- "contents": "D9AF0F568322C795328C8B4C1788987C398192A22A",
- "de_type": 678
- }
- ],
- "encoded_section": "979013282215741E4345A78D01377EFF9E84189110005B4B4A350A45FF863C3EAF2AB7F71C0790011B34CF8E42769B0FB7FB3F66C45BBB7B7F2160D74F03D27F7F1AA2D8C52FDC024CF2CF9A7EF240540C04FEBA619ABFAF2D79C7BC35421D09D20FACCE2A115C262624A87057FB67B440D453259A65476D5134E1E263A128B7192920FC7DE545B0EE63F83AD8963197C51E056FA2C6200F",
- "identity_type": "private",
- "iv": "B084B7392E0FF2BA4DEC9EF8E26B1A93",
- "key_seed": "33565BCB2529940138116B4DB968D4D320B749D470FB480FEB2B9A6D6971EAE5",
- "metadata_key": "A3988254E6FEAA0D759AE32D048013AA",
- "section_mic_hmac_key": "41B9C812B94BD2AC4AC218F8DDE986E2D45EEBB89A0882C438933B001DAB2181",
- "section_salt": "5B4B4A350A45FF863C3EAF2AB7F71C07"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4144053F0E007DD7F1D38291852FE2A4",
- "aes_key": "1E65E2D1E7718EBBD972BC2042B9B11F",
- "data_elements": [
- {
- "contents": "3AC4BEE4E3E37B706980475F09EBDD",
- "de_type": 102
- },
- {
- "contents": "7876A28FE5101EC499AAAB",
- "de_type": 112
- }
- ],
- "encoded_section": "559013343E829B75A77E72E1F5C0EC1ECE8EC49110004F47C2E91506FF96DA391B2BBE842F2E9002B9E7953047832B10DFC880CB57E7F569953E97CE5469368BFDC23E298878D41A775E405A97B0944DE64EFFACEE3A",
- "identity_type": "trusted",
- "iv": "AC1839A4D9EBBC369DF0E5DE3E9FB486",
- "key_seed": "F53B91BB8F5F267901F6D0C2E6B511D37F23F41356B514C5BDCE04AEF60A7624",
- "metadata_key": "B82E90A5753E1604C5C50790383528B3",
- "section_mic_hmac_key": "FBB75466A337A9EF19DAE241B45E6366B3ACAA49B3678F6D410CF6A4B915EBE6",
- "section_salt": "4F47C2E91506FF96DA391B2BBE842F2E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DFBED8D9AE83990BB427226E21034CB0",
- "aes_key": "AD572A7C029F77B3C54ED924525D3229",
- "data_elements": [
- {
- "contents": "3E120DC6A27E75C6B4D1D1A1C9F7A29C6B3B9B0F14E45D175F418711",
- "de_type": 213
- }
- ],
- "encoded_section": "569013F5A38DF3EC99C4156E794798A6F296D9911000986627D3A935F5C710D101A38FF8286890024F59E49C79DC9C0E298AD99275CECC28E1B8EDDEF0C3C2B4A7C984A2CE21DDAFE6E918D16575D2D6624D8C44673699",
- "identity_type": "trusted",
- "iv": "AA8AD31CCD7C59E5EA8186E39301A7F0",
- "key_seed": "AACADF297C376735AF0138DD2F3F4B5CFABF32A8762275DFCA9EA2295E86A28E",
- "metadata_key": "19528CA6D4629802FCA9D11353A60C2C",
- "section_mic_hmac_key": "79F40360C6EDB9881CC05F01929B36746DB5F046093AFF5C2F3721BC5DB54A8B",
- "section_salt": "986627D3A935F5C710D101A38FF82868"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8BEC81AF56FA2AC4193B05558C125204",
- "aes_key": "AE9C86DE09A15A4F3859D801E0678262",
- "data_elements": [
- {
- "contents": "4340F3E3DB2B1E56361256AF51DC6526",
- "de_type": 221
- },
- {
- "contents": "CF0E82",
- "de_type": 309
- },
- {
- "contents": "3EAD73DC8251FB1A5921E8255EC3CE3C12BE13839BF284A799BC",
- "de_type": 508
- },
- {
- "contents": "E261280F5BEFFFACD5D0ED3CC81F0C1BC1631C2E5D9A",
- "de_type": 929
- }
- ],
- "encoded_section": "869013F05F6FE5E4F7979EEE836171656BBA54911000465E3D595AAD47749A7384B123CA18E9900246F59681BA8A29A4B50D6B4EB3A5A37571EA7EBECCADE01435C0AA8A59440DCC455EC858FBEC686DC4CC3BB20F562B161BD729338C4FA13753F30FE021F5747CF11957D338E0256D07F3AF7A9D2A949DB748A997D6466F6CC5C6F80614B2A9",
- "identity_type": "trusted",
- "iv": "2E91EDDDC24CC419B76CC16976B8833A",
- "key_seed": "11FD266669C2E6C279D8EA69F540B784989D11A09568A19F66D2ED0C1D6DBE08",
- "metadata_key": "9B21D37E086FFA839142C0A22F3D65F6",
- "section_mic_hmac_key": "A7F1A78902BB05FBB7B54D35CE9225330B349654936258EF908C11D4E6F3BB47",
- "section_salt": "465E3D595AAD47749A7384B123CA18E9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "801D4CA35A70D4C283D2629EA148170E",
- "aes_key": "65B82E5D5498A2A0557B1D39C0F5950F",
- "data_elements": [
- {
- "contents": "A02494863822B1EA59AC8EB4",
- "de_type": 243
- },
- {
- "contents": "4C200134B8F4ED2481229F256DEBECCB6C5EFF7A8ECBB9684BAF",
- "de_type": 900
- },
- {
- "contents": "1CECAE0187941B94F8",
- "de_type": 950
- },
- {
- "contents": "DB6AF61301EA124E883131733344543394B9EB2D18",
- "de_type": 77
- },
- {
- "contents": "",
- "de_type": 542
- }
- ],
- "encoded_section": "8990135245B0569137C5BE751DB35223449F6E91100054E61830D0D0DD6A1F6B3DE7013EF06D90044DAE7D1C3F0BF3E5104C1DD01FDD1C5DFC6963613291EC87DEE2ABBC16C9D2BCA620921CA07A64D1DF36C733EAC39D997BCBF38E4D252F232C58CFF37697A13C04EA5284FF0BF47C11E85805018DC6E3495D61EFA87FA298724C267F1F29031B2C9D",
- "identity_type": "provisioned",
- "iv": "DA7D5D3FB17D06F46DD8AFB6647A44AE",
- "key_seed": "78D9D6D609D520DA4339EBF814B40DC3C80AA0096C2E7948D5D4B92FB9243084",
- "metadata_key": "ADCD26D03B8A1AF8C0FD9B3188124D19",
- "section_mic_hmac_key": "B0430F46E286EA342ACB84CA42C151174AA8650353CBE5B064BA37DE66D823AE",
- "section_salt": "54E61830D0D0DD6A1F6B3DE7013EF06D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0CEA8476765E2C9409E38AAD4F554E63",
- "aes_key": "BD88F43CAB6E5D6B2BCB69424BCEC9F9",
- "data_elements": [
- {
- "contents": "D831FF5C4756",
- "de_type": 24
- },
- {
- "contents": "8689F2BAF45E",
- "de_type": 805
- }
- ],
- "encoded_section": "489013E6F67A18C298C579609785D002870A829110004B7B840D8A6CC70F61B178722D71FD419004B85364FEB66321ACEEBA3A8C7133634867852A5A6A1B2A18FA032B1853288CEB84",
- "identity_type": "provisioned",
- "iv": "1FC05B651BB33F007EE45A02E7AC904F",
- "key_seed": "667CD8F62F8A77492DD85747934C30D23D3658252198EBA915382603CD2B6CDB",
- "metadata_key": "68CF855C510241813831D894E104173F",
- "section_mic_hmac_key": "9BF0F323006089DCFB6181BE51EBD8DDAC8692E6C8B36A69EFBF85A7C073E31A",
- "section_salt": "4B7B840D8A6CC70F61B178722D71FD41"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EC30A0D58034A34B8E5C559F280F509E",
- "aes_key": "728B0357E323756231894D94286C3AB8",
- "data_elements": [
- {
- "contents": "A7F5481741CB91CDE0",
- "de_type": 894
- },
- {
- "contents": "2AB65DA2EC0508A1",
- "de_type": 303
- },
- {
- "contents": "380AEEF682FD5EDB89F02A05",
- "de_type": 920
- }
- ],
- "encoded_section": "5D90134D517709AEF9711FA7C2AE7B5ACC3ECA91100080E251133A8F0A7747C29C80983F07A790024BD1D93EE6C137F6504D32C8CAC34BCE856EB4FA298CE7801B8F56463E85457A15C15F7075F06F2EC32AA68CF9794298E42F07AACFFB",
- "identity_type": "trusted",
- "iv": "1C296F5143FB2934F70CDC21DA10965D",
- "key_seed": "955963D16FDBA60A066C6F698845F5A28A9D6D0099B4C77B443B56B249CBB1D6",
- "metadata_key": "4AB7C96061268E4C9778E218F0E34ECB",
- "section_mic_hmac_key": "D0496A75DFD42062C8DC17A2424ECC60EFF3890942702CF45733DCFEE97C58FA",
- "section_salt": "80E251133A8F0A7747C29C80983F07A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EDB71DD72EEABB1066B3E8250E2E6838",
- "aes_key": "B0BE972933B74F340C2FD12F033D470A",
- "data_elements": [],
- "encoded_section": "3790132359338C99B060B1F9B0CA90849B5B7C91100073BA46B076BAB82D101B0761C8B676B590026EE24CD8FE1FEA2573DBCFF4F2E712CC",
- "identity_type": "trusted",
- "iv": "47E21BB24E2B6E7E524F3B9EE2B3D661",
- "key_seed": "2F6D9575641AD9DB592DB0D601A38DC7C33EA96141E7E46F2C12D1DD4FB5DB58",
- "metadata_key": "16897C47EAD110C4A40E872DE97BE7BA",
- "section_mic_hmac_key": "B383738B32E347E6CA30DD1AB86CD8C6C6F3817FF5DCA69E5927FFE970966B30",
- "section_salt": "73BA46B076BAB82D101B0761C8B676B5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF3696F6CB3680CB90959720B0C0C8B0",
- "aes_key": "DEFB7155A421A3C00BCA9521B9802212",
- "data_elements": [
- {
- "contents": "BB94E1E012E8C01D78B367A8676B719687FA84832A",
- "de_type": 100
- }
- ],
- "encoded_section": "4E90130470C8FD4D0863A99E0655588B3677999110001560EF35DC8690A269985B834F5DF50C90015F68C10A7D7C940497ED4E77972D7A694E425C5CB5CD557378D55E31F445E7D38CF41BACC3584D",
- "identity_type": "private",
- "iv": "C493FA8A5AA5716991EA0A1825B88634",
- "key_seed": "DFFB9A504328A5836EC19500C592E8706E45A8CC9530A63B6D57A50D81DE4368",
- "metadata_key": "24DBE2F5B5592F053F7E969D336384F9",
- "section_mic_hmac_key": "6A0717E12EC5CD7EC7B18B3A0A597CB73650649DE6E9B11947ECF3552E72BB80",
- "section_salt": "1560EF35DC8690A269985B834F5DF50C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "96C29DB449A05ABD7BD2AA8292B5B1A3",
- "aes_key": "48A7161729D51256FB3A22D800C9F4F8",
- "data_elements": [
- {
- "contents": "2A33FFE5AF0D",
- "de_type": 146
- },
- {
- "contents": "61F2724E94BF6C6B841EA6DA24",
- "de_type": 777
- },
- {
- "contents": "79013E7CBF1E6757B28357C09CD8DF3F06EA5C8B29790B6AF12FAD",
- "de_type": 19
- },
- {
- "contents": "4E31D2948A6FCB9981BA3423",
- "de_type": 85
- }
- ],
- "encoded_section": "7B901309CDADEFBB30DF2A333B1F1211EFF789911000317126A212B7088BCA01CEAC599314F39002C21EC35FE4B66BE19DC9DAE8FEFC0FA8E0CEDAF4DE232FD592D75432B7D99511A15AB00D4359120C22D4934C0FE24C00B612684FAD1B4B8ACADC18BDE97D5C7BA24454248F2B816DBFC326EB73A7ED11C5F4B3F8",
- "identity_type": "trusted",
- "iv": "D85729A8ED6F4206E1557D6C0B1A6767",
- "key_seed": "76BCB5FF9343256A836AA5AEAD8462A0FFFC2111B70F095635995A2AA6C60FFC",
- "metadata_key": "B89DC800A35AC2C0AFE5A91834D7AD2F",
- "section_mic_hmac_key": "A9C86D50FB79A6B609EF7F805E8EE1738B278AE7FCC46A0B5462089755752E6E",
- "section_salt": "317126A212B7088BCA01CEAC599314F3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C827366ACD1EB08E13FFBF22716C436B",
- "aes_key": "420312434A398DF54C75FDE9FC81E919",
- "data_elements": [
- {
- "contents": "79",
- "de_type": 784
- },
- {
- "contents": "290E4DAAAF",
- "de_type": 11
- },
- {
- "contents": "",
- "de_type": 225
- }
- ],
- "encoded_section": "449013BD50CA32BC08AA861296C928AFD29D20911000F29D169C5E837778E5A31231ADEA015C900287033FD9D655A2A75CFB2D920787BFB3A9BD5574A01CF64B3BFBEEE838",
- "identity_type": "trusted",
- "iv": "88016DDA898C2FEF943D1EA8E96C9A87",
- "key_seed": "69722E285E4866039C057956F5CA697047315D8C4C72ABE50D586695683FAD60",
- "metadata_key": "475C542B15D91FAED80364C9399C1A17",
- "section_mic_hmac_key": "636441B2DC928073663261C3E1A69B80272551D557AEF7F6BED9BC2B86C419BB",
- "section_salt": "F29D169C5E837778E5A31231ADEA015C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5A822E5B54BDEF7F5009548D324BBB5B",
- "aes_key": "6C2B767028935ECB4D5259451A6FD38C",
- "data_elements": [],
- "encoded_section": "379013C45F3FC194B77E7CEA94559ECF8B2CEA911000C29DD4EACB5AA9ABB862A37A0BE5EF7B90027B67A1CA38161CDD01B235691A241DC6",
- "identity_type": "trusted",
- "iv": "10FBB6D3CED80733229DC291931A5F62",
- "key_seed": "A25CF787076C32D614D8D7A292FA70FCBC0B24A48CCF9F48126E9A083E9A3B3E",
- "metadata_key": "615711C7C51985FB53AD38EA82645DAA",
- "section_mic_hmac_key": "092803121B8DA22AA60360C830EA1A5DD8C4FDB5A474914FC4ECB717D13BFE76",
- "section_salt": "C29DD4EACB5AA9ABB862A37A0BE5EF7B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3BA5CCE53243F98AD868DE1CD3E9F63E",
- "aes_key": "7E3B147189BE67DBA984C1682CEAA129",
- "data_elements": [
- {
- "contents": "434D0E7DB4C0BBD5674A83C484DA072FEA",
- "de_type": 0
- },
- {
- "contents": "6AFA19CB7C46BEF2EA5369837FF9F4C834",
- "de_type": 413
- },
- {
- "contents": "1070DA173252B48ECD95EE5AD376",
- "de_type": 410
- },
- {
- "contents": "9A09FE8AFA0D8C036D3670E709658C3F67BD13352BF689",
- "de_type": 27
- }
- ],
- "encoded_section": "88901314095DFFE2EEE0485F9947690F21701C91100093DDBC1927840E03F6449B6CB0FFA110900226C7CBC3BA4BD4FCA1E8EF197562C5F485BCA2B259F0A214E3D5C2A68492BBE242E720DA326C82CEF19D79A430D4F2F23E7F36811D5878DF371D6AB23FAB74235DA55E21AC6BA52BEF2F86B4D3DE92F79AD995CA6AA796AD37BA43FBFC9AE913B5",
- "identity_type": "trusted",
- "iv": "A8976278B12AE5463AE984157E0205F6",
- "key_seed": "6D57B2178FBD724251697132B807A3CFBD68DE400362C57CCF9108CCEDD973AD",
- "metadata_key": "0D5B558D2890FFB2E5FEB48ED21150B7",
- "section_mic_hmac_key": "F79CE3F6795EB7F1B65DC1FF2D997397B02C3975B304B62C7E49C7D0AF3037F2",
- "section_salt": "93DDBC1927840E03F6449B6CB0FFA110"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1E4EA1B93504696BC87BBA1AE230DFBC",
- "aes_key": "65F515D0D4AFB386BC2D9D1C37A46C92",
- "data_elements": [
- {
- "contents": "0EF8D96C53C49ABD11B69751",
- "de_type": 258
- },
- {
- "contents": "B945DFECDE411CC9B1FA63",
- "de_type": 728
- },
- {
- "contents": "AE610E4798CA99",
- "de_type": 212
- },
- {
- "contents": "18526E1BEACEF8F0FDFC34AA7F0992387B",
- "de_type": 765
- }
- ],
- "encoded_section": "729013B0AC05E79DD417567F17EF2ACF4A48C8911000D05DF80E62306F8629AE61A8270A7CBE90018D38E80AC68E0B71973CD3BB0A4D58D10932C58303F629C6497ABDAD814AAE32A7CD767EDB9F4F6E7B3E1245F15D6D1D6D45B175C6535A701B2C0A19E6ED9BCFF379255F23992E877887ED",
- "identity_type": "private",
- "iv": "2CBF8042D27B1F49DDA990A4BFF88509",
- "key_seed": "09E15C8F181659969AF6C6C2375A564A9E8271EA13B1EDCB8A1F7809406E95D1",
- "metadata_key": "F7411DB79645E475BD12C015B15ED0FE",
- "section_mic_hmac_key": "AE6FC455FBD017A6B7B80052C2EE240019CAFC961605EA703F0E6F1EF9CF44F9",
- "section_salt": "D05DF80E62306F8629AE61A8270A7CBE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "967CD8FA43AF6DAC8E445A080A65B16D",
- "aes_key": "0A01B5E36CC69764CCE3A74DD544B1B3",
- "data_elements": [
- {
- "contents": "4747E589E226F4F9093067D1E5227412CD7590",
- "de_type": 212
- }
- ],
- "encoded_section": "4D9013F9C57DAF3EEE1AAC80E7C06F1066F0929110009A52343FA860D361860C5072654AD99A9001A6D1DE2BC661B5E9AEE33FF8034275C5308DD4AE9340C637DFABE250FD8A31813DDAFE0BE84A",
- "identity_type": "private",
- "iv": "9643C2FA43D519B44896490C005E01B5",
- "key_seed": "882D996C004CD5A1A8E00F436F97DB555099408BD3DFC845416A55179EF22C3F",
- "metadata_key": "9ABA26D1743D347716204D2AAB927133",
- "section_mic_hmac_key": "7CF80AA4D38DE78937E2C09F53E5C71081A5036309D4D3732DCAD4B6D2F82E5A",
- "section_salt": "9A52343FA860D361860C5072654AD99A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A703D473C6044C05892027F1F0B60F72",
- "aes_key": "2FA998F537E61F6E8195C5CBB96457B3",
- "data_elements": [
- {
- "contents": "E1A624CA4950C406697EF34E02A7",
- "de_type": 902
- }
- ],
- "encoded_section": "4890134D9EC007C7BCB6530D03FD5F58F0B753911000737B467B6EA222531CD57C3DE300F0BE9004B24DABEFA8C0B41D78ED1E5201E4BBB51D8BC92D8976081E6FFC732C2E483E4547",
- "identity_type": "provisioned",
- "iv": "F09BCD4A5B8D538621858D272F8357F4",
- "key_seed": "D41FE25607634264613845B1FAAF6735778475A69D76DDAA067279DF982667BA",
- "metadata_key": "08C6FC8B190221DE2134ACB569BD9002",
- "section_mic_hmac_key": "8D5B13DBD8411D3E2012F8B17F42FA32F12212905D7B123C6C8F5A794C28FD17",
- "section_salt": "737B467B6EA222531CD57C3DE300F0BE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "225DAE6F894DBA4F2E24E053E5DF0926",
- "aes_key": "0C13A76631F9D2FF50D2B7943578F342",
- "data_elements": [
- {
- "contents": "DDCF88A122E86BBA27EDA33BCE5C8C92A5CDD960E3D401DBBF8235",
- "de_type": 860
- },
- {
- "contents": "EED509DC49EB0688DAE0EF2B694BD257D334656BAE46BA",
- "de_type": 281
- }
- ],
- "encoded_section": "6F901307E6D989A7D4580033D10CDCD0BB35C0911000AB498A5AC0AF52C5CA35710B455BA21F9002AC340BD4B1E47545097AA869F28CDFCEF69744505C494AAED292AD78A9A4F2018CA12E1587B9AB701BB58F91C587B32155674BE664214638B527597315F0F1975D8A6AF1995EE16C",
- "identity_type": "trusted",
- "iv": "23513AA8837D20F3D7696AAAD240E477",
- "key_seed": "7BC68EEFD9B2B6410C33AB48E86A7F66719AE9475ADF6F0A132F869A82BF0297",
- "metadata_key": "6E06556BE6FB79950C5DFAE4A2E674ED",
- "section_mic_hmac_key": "9016C1CDC6CB002A1B2F89D05DD939B8DC0215BD625C2BB468ED6EF69B9257AD",
- "section_salt": "AB498A5AC0AF52C5CA35710B455BA21F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2E9D2DFCBE85982F854C1D4F0E6D93E5",
- "aes_key": "D2C5575DDBC1CDD5CE0FE02422980767",
- "data_elements": [
- {
- "contents": "",
- "de_type": 888
- },
- {
- "contents": "B9D74B1C7C57A773B30E7A1BBE85531092",
- "de_type": 717
- },
- {
- "contents": "9D7507067864040C",
- "de_type": 743
- }
- ],
- "encoded_section": "5990134C8FE31670AD6DF853D9B25DF0C1793591100095C176F7E36BE5C6DA5004DDB3C65D7290029317FD5A115128CC9331C1610AC7B2797FA680F094169BF66D48E7E6E1E08D541B89EDF9C3342E8BFAA9F6B2DF6AE881C718",
- "identity_type": "trusted",
- "iv": "BC20E92086374ECD11A19A07E3E2CF3F",
- "key_seed": "02D4DE8B5FF08DCF8256D575084CA4983548DD3F55E7AD54336A4985E3351112",
- "metadata_key": "7FCE36BF9B0479FF853DF40B4EF98956",
- "section_mic_hmac_key": "7C13466EA8471C744D721F3A584E59B5FED47C7CE25B9C47D2CFF2036920C9C6",
- "section_salt": "95C176F7E36BE5C6DA5004DDB3C65D72"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "39808BC788108E6F5B6D34DCC09FA9C7",
- "aes_key": "08F97FD75991B8686F0FB843EE31A1D0",
- "data_elements": [
- {
- "contents": "9FA77C23C482636D020CE064",
- "de_type": 370
- },
- {
- "contents": "BC99",
- "de_type": 68
- },
- {
- "contents": "83E5",
- "de_type": 573
- },
- {
- "contents": "1EEF6D24",
- "de_type": 145
- }
- ],
- "encoded_section": "569013BAAEDE05A06A54EFEB6D88CBB00A8A7A91100066CDE62F4772FF4E97566A182D5C03329002FED2FF0BFD3A6103DBD82114343B47F4846B6B2A001E7533606442DB32EE91EBD21245F80F6AD615FF03DB2C35118D",
- "identity_type": "trusted",
- "iv": "5EA3B7F4C64F94FDE824BA20F150F5F9",
- "key_seed": "3BB0AA21375B167B2A4777D850C4A2432C0EC93A3BDF6021456508619433F97D",
- "metadata_key": "41537838EB8E6DD487D4F2B26182EB72",
- "section_mic_hmac_key": "249AD0CAC358E0402D1F0905EF4BCB199B9988D958C17F4A91CC01249061EACE",
- "section_salt": "66CDE62F4772FF4E97566A182D5C0332"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8659FDC730244DA2ED976154CCE7794",
- "aes_key": "1217C04A0210C3DA505F5EB9123372D6",
- "data_elements": [
- {
- "contents": "84ADCF3C26D68CB75E3D7290C59D6F86BFD9B23E10065C2886",
- "de_type": 795
- },
- {
- "contents": "221C330B2C2A3F16F957C02D806C5EC9FB18117D9EBE45A32D9E4C",
- "de_type": 534
- },
- {
- "contents": "2C858E1D7D841372",
- "de_type": 544
- },
- {
- "contents": "B5DC82A3D20F6601D1",
- "de_type": 629
- }
- ],
- "encoded_section": "8890133129E43BE247688922EFFC1C06A2976191100097BBA7CE5BEDE598EE61AA356BFA3DB09001E23B0136E0AB1C5D8DE60F20A809FD1D5B787159DB77B950B9F353C38D777D290ED5586BE886CABCDC8E07909FAB3FD375F42F3855D01FC55B4F29DA7951456624CABD2D4454E45AABD9758EF277C1E25B631E897C52201E53D44C8F3FDCE1C82A",
- "identity_type": "private",
- "iv": "4322ADCB565A23AB23CD40565F78C009",
- "key_seed": "FA744BF2436D127CDE08772282F961254C68C88CA37CF683420F04A4321CFAB3",
- "metadata_key": "7119BE6A5D9DB6AEFF8C4ACA38E43DAA",
- "section_mic_hmac_key": "70A522C74AE34A81184EC55874314B13532145C99D47324BFAFC08041E0755AF",
- "section_salt": "97BBA7CE5BEDE598EE61AA356BFA3DB0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6AD3D60D04723C57A58AEE240F6BBACE",
- "aes_key": "43D34DFDF2BCCCC8DB6216E7C35C61AE",
- "data_elements": [
- {
- "contents": "E2",
- "de_type": 132
- },
- {
- "contents": "19855C45342ACA24BF3C73CB79",
- "de_type": 696
- },
- {
- "contents": "E2E48F8ACAD7CCAA6910E3",
- "de_type": 265
- },
- {
- "contents": "76FD5B530D0014",
- "de_type": 236
- }
- ],
- "encoded_section": "639013E9ACAAAE5E2D8CB5E46DCFC19FA72E519110000675F279365CE50B3AA51B78DB0DB4B2900235FD3644D84D6326F596083705677D0F50B4E9C8C25FAE3E08308E09C28D388BB5C0FF248FF9789030675D9B4C73C5EAD088ED65169869A8F20F3FBE",
- "identity_type": "trusted",
- "iv": "7FC53B20EE21524D8567BB6EE0B24693",
- "key_seed": "ADFF7F0DAE8A0314B915683C900FDB5EA48F05D1FB65771E44C1772C2BDD3287",
- "metadata_key": "42CFED512703687B96EAAB7E8E402877",
- "section_mic_hmac_key": "6CF494AA61E6BEE966D48FAF7E2672F82527FDD1C3075B7637550E7AF90BE358",
- "section_salt": "0675F279365CE50B3AA51B78DB0DB4B2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9DE0357046BC21405E3FAA9554F7E58A",
- "aes_key": "F9793D17386DA59EE51F7D32A8A151CA",
- "data_elements": [
- {
- "contents": "6C85DE2E1644563269414164604499D1A2C443969711F381",
- "de_type": 473
- },
- {
- "contents": "12E30D7E922A107B3803092257C476D6CA8795F03A9E",
- "de_type": 759
- },
- {
- "contents": "00",
- "de_type": 527
- },
- {
- "contents": "FE4B43A8995BEA8FAD5746D92ED6F9BAEA918E51F433D47E71C12FD7B9FB",
- "de_type": 57
- }
- ],
- "encoded_section": "8F9013962F6EDF9C4DF87F7C4C5DD8CA42CFA6911000963BE50C9F0419B34F64BAE61586A95790010869544823FB9E1FEFF595AE61CB1806C2996320388AAC60CD987CA7EE6DC1272B2EA4DCC069C3E127ECFB9F616F4B9A9633A355861DF6B463084236E9E8E6FC4860EEB27F65803C8E18C898123DDFCC6621A9F74780D038D3051795B536F9D2D90CBA19090A0978",
- "identity_type": "private",
- "iv": "ADB30AE2A8D404F6B9EC3C5C7F40C87E",
- "key_seed": "C88CA68847CC9E39EBA84A18D9882BA9284276ABF72E3A71E046BD0061A0F946",
- "metadata_key": "0A59A06A76CC860B8843AF5DB75DF85C",
- "section_mic_hmac_key": "2805BC04A45CC27210E07D9A5C74E95FE7E53C4AA59BCD95D4EA877509C25416",
- "section_salt": "963BE50C9F0419B34F64BAE61586A957"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "57BBEA707A339197563A41AA0E0DF11A",
- "aes_key": "1434B77F9FF8ED4472524CEAD5E2600E",
- "data_elements": [],
- "encoded_section": "37901317C3340DD8DE24DD7038087A0AF9F8919110003A25A320C3B2AF5602DBCC5ECB87F5049001B989234629FFC24C7AF47AC6F5591241",
- "identity_type": "private",
- "iv": "FAD343C30CA085B82CD74F2EB90EEC36",
- "key_seed": "7618055D281738547A4B524FE0C6EABF1BBEE14AFBDD654010569DCEC71EBD5C",
- "metadata_key": "2CDE85BDEB42F4A684CB85402EF2050F",
- "section_mic_hmac_key": "780A1086ED611E46176DB2BBC18D9922D10CD2505B65C948C3AF08D1EBEBA1C0",
- "section_salt": "3A25A320C3B2AF5602DBCC5ECB87F504"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "69F7A5E815A8018FA3C12A5259619FED",
- "aes_key": "1EEA4B9B9FABAC2BB81EA1833E7A9C05",
- "data_elements": [],
- "encoded_section": "3790137E34824746AA819ACC4C60043B9B3D2791100065C80E3A90B498B761A7C07ECFD92DF69001FAA0CC5A0DBDC1AAA92FF3ECD5297778",
- "identity_type": "private",
- "iv": "5407E8912C6A7CC71C741306C0848964",
- "key_seed": "567ED96D44DD13369424A930E8340DFB1B3A5423A3A8EC36EF30A5CF95B0CBDD",
- "metadata_key": "6265BC696E8C105ABBD597107653950C",
- "section_mic_hmac_key": "102CB9E93C412A3E2D267FB56147326CBBBB34CA36471AE61B00EDF4BB24B35E",
- "section_salt": "65C80E3A90B498B761A7C07ECFD92DF6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA4E1434567DB6531BCCE1A5D8142D5C",
- "aes_key": "52CA47EBCB645595D4CAEE61A9B3C181",
- "data_elements": [
- {
- "contents": "53ED1098F6A0BAE7CF9EC6",
- "de_type": 128
- },
- {
- "contents": "A435650C36CB2E6CE210E52065405617925507797DD8",
- "de_type": 761
- },
- {
- "contents": "F3E6",
- "de_type": 242
- },
- {
- "contents": "D4B6AC531A7CC0B6296463AE4E98D99FEFE577CF473CFA4D",
- "de_type": 556
- },
- {
- "contents": "185BBD798D78329142610AF413428555C31F543D65093312003D17BAF8",
- "de_type": 388
- }
- ],
- "encoded_section": "9E90130A0D321186AF0AB2F4AA4379978B717B911000221CA03F0091EF740A7A59E45C6A8B4B9002AEB4E9389E0828052CECEBAB082423E0349E44EA64E5532DCF3C323319E13345127A426379FB1E494C9BB9D6DB2DF56FABAA87E47E7901F2D4805002F428B000CC4DFFDCFE8CC9209596718BD5636C25C177E7726AE4730FA153ABA0CDBBEF47A077EC595144440F725EE5CF6914DD6FAB91AFB8B1FCC5",
- "identity_type": "trusted",
- "iv": "4936E010A41A65BA9541DC9709158FD1",
- "key_seed": "9E67123907427CA52C8260AD5B362365EFEE24A87BBFD9EECD3B17C0A9560CED",
- "metadata_key": "E2A5139BC71D9F56DDA6FD58CAF4C72C",
- "section_mic_hmac_key": "0E95D0175A99B701BD80DD3B51C02D70DE1D67FDED07F96D3870A89D995B5D27",
- "section_salt": "221CA03F0091EF740A7A59E45C6A8B4B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D3721817C8956FE858948C1931BCF455",
- "aes_key": "E929945B8EE42B6E003C3E073189C621",
- "data_elements": [],
- "encoded_section": "379013036FE7F04378A9A1C2894954362311F3911000044A465A357C84AA284FC794D2668FE99004AE1D9D5ED13C9D6409BB549FE27B8814",
- "identity_type": "provisioned",
- "iv": "66FC1EA30719B09F2E504C0AEFE155D1",
- "key_seed": "67E133E44ABB305A340F39B513135EF0353DAAFD23092784520DC9199E9D14F4",
- "metadata_key": "1A031A4C41C8DBDBF482E9945F3E928A",
- "section_mic_hmac_key": "5FCAD75E7446707C69045518E605986A8BB0F25A0F986648516727E5B885D78E",
- "section_salt": "044A465A357C84AA284FC794D2668FE9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4B352B0757FB0D8DC0AFD2AD77FC8F30",
- "aes_key": "FBFE41732E1EADFADC6DB41D32E7B56D",
- "data_elements": [
- {
- "contents": "93E38ED62D376819",
- "de_type": 571
- },
- {
- "contents": "91B3ADEBDF3A97DA0A772CE21F2272BD4E1EFFA70DE4A3014EE66C",
- "de_type": 921
- },
- {
- "contents": "348345",
- "de_type": 660
- }
- ],
- "encoded_section": "66901389B03B6684D250EF07E1913E8A54843B911000908608D294CFE21DCAD59E6B65063026900457E91F0F06E7F3A59FCEEDDCCCEAF0BB6FC1C31762C5FF7E60EECBD37BE8FA1CFA439D9FD3F5EC98F22B497151EFF602C8868F429469544FFACDCBBEA6056D",
- "identity_type": "provisioned",
- "iv": "BD6A74E891B7616A8704F0D2B5361A22",
- "key_seed": "9ADEF374AE5C0763B4C81FAFACFC3FDD00BB31EC2BDABF08F72E0CC25C8F8A0B",
- "metadata_key": "D925195F47F2C12E5837398262F9894B",
- "section_mic_hmac_key": "D4CCE814EEB5CD71C084A1E98D5C3F1A0632DF311D665CC6F1225C1E20561B94",
- "section_salt": "908608D294CFE21DCAD59E6B65063026"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "08B9B51BCFBE04D4523BFAA17837286D",
- "aes_key": "23C322B350234D1FA4023DA8FE2D381B",
- "data_elements": [
- {
- "contents": "57148223",
- "de_type": 549
- },
- {
- "contents": "ACE590C4F65B4143CF4BB7801CDD",
- "de_type": 957
- },
- {
- "contents": "39FD3C339EB0A86E78FC096FB33BB284",
- "de_type": 22
- },
- {
- "contents": "",
- "de_type": 120
- },
- {
- "contents": "A840D248AD83380304C9BDC1",
- "de_type": 534
- }
- ],
- "encoded_section": "72901304935566CA4CD8AF2420D84128E1F8A891100051A5D7C9F920639AF9C89DB51DC724079001821FD769D4AAE093F00DB6744A7E61A70B1EA33D810F7F266AF3FCD2841A2177DED23CA8C60E4574DF4EFFA31C21D27E39731EB7EDB802287ED62D075FACABC42C9407F742D333A00B6F40",
- "identity_type": "private",
- "iv": "FFE0673572F02D6F02CB5CD380B2F345",
- "key_seed": "80C545E5E6F1E3531C0FDE45C8DF59910DDAE325F822C84F4999C344E7B6E572",
- "metadata_key": "A473658E9F2E4B02A48FE08F5A9A03A0",
- "section_mic_hmac_key": "279DFAB67F702246B59FA57F0700ECFB97580F0D8F2EA56C621FDC55626B13A3",
- "section_salt": "51A5D7C9F920639AF9C89DB51DC72407"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "397658B7EB19939359DB8BDF7DC09977",
- "aes_key": "355D838167010BFCD65619044A34AF0C",
- "data_elements": [
- {
- "contents": "A329FFEB42E67FA6E8C08620E087CE7E85FEFCBCA1EFAF765F",
- "de_type": 885
- },
- {
- "contents": "157803B1904DAED114559F0AB2",
- "de_type": 480
- },
- {
- "contents": "703A8005A3EC894539CAAE34",
- "de_type": 354
- },
- {
- "contents": "596FB5EFEB49350FC8F683C80926EED7054787",
- "de_type": 187
- }
- ],
- "encoded_section": "889013C5BDBD074C803C8A17E3185E1BA6A571911000395E87FC0DF8B105176174C1D832DDC090044B65DD586A362858D7A824EA454FE3671CC784DF5ABC89CE611C470D04F2F44C9D474610D038A521A619F9703BBE8B0DCF18289A924A01516C63272F03524DEB885D5FD708D66D9D673C553578B27D514441ED938BC1754D94DFAE47BE20B6E2B7",
- "identity_type": "provisioned",
- "iv": "22D55CE5BCCD3D372782C35F5ECE49C3",
- "key_seed": "DD3D65E71C5DFE02F5BD548BBBBA3F38FE8926D0CA9A50804EDA24B3EF7A2868",
- "metadata_key": "888FC2EA55F320201E6252FB7DDBA66B",
- "section_mic_hmac_key": "AA0724D6E22D4887021B351D9D201A618F8F303201E283F79D95AFE23DDA4CDF",
- "section_salt": "395E87FC0DF8B105176174C1D832DDC0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "653ED3515E8811D572C1B7765DC268E9",
- "aes_key": "686C0B1F2970A3CAD0E2B1209A5A5B78",
- "data_elements": [
- {
- "contents": "B17112",
- "de_type": 147
- },
- {
- "contents": "FD920FDBDAC1D5",
- "de_type": 721
- },
- {
- "contents": "C817A535ECD2C643341E6230F44B67C8D06F228B8EDD",
- "de_type": 612
- },
- {
- "contents": "B6D4633DC57509F731479DE1127117E11E333682374DFB",
- "de_type": 544
- },
- {
- "contents": "5321F349",
- "de_type": 876
- }
- ],
- "encoded_section": "81901327A67FBB0CF04078320EE77A2873B8E09110007D7C2E8E278663EB6A532BC7848229B4900227C099A8BD586C51B776FB08D9D29D095070255058F840466D79C5E306488458771690C02C4AF052F3A53EFD7920D40FDAEA1354F4E5B87C375652F2DA4ECC2D744C36C74FA3380799223848829E7C594479214C31205A740524",
- "identity_type": "trusted",
- "iv": "263DAD92EC0DB2C39822FD26F2AD62D3",
- "key_seed": "428968D9A9F686878BF560B65ECDFE3B38569FF712AF4EFC58564CD92AF3D980",
- "metadata_key": "BC7405270D0F5841C3A3D3D40FE79873",
- "section_mic_hmac_key": "A463136592A1F07BF2CC6D80071A290077283DB827AB456A4CDA64588019494F",
- "section_salt": "7D7C2E8E278663EB6A532BC7848229B4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "31E689DE84F116A3C449F0B5D8A7288D",
- "aes_key": "A6E2770208FAF2A476A475D770A3800C",
- "data_elements": [
- {
- "contents": "DFF2C917C345C09B31E08B347E588FC64DF374BA28",
- "de_type": 218
- },
- {
- "contents": "3484B697920F1CBC",
- "de_type": 764
- },
- {
- "contents": "FB57C8A58AE76571",
- "de_type": 686
- },
- {
- "contents": "386218D2313E3A5EA2",
- "de_type": 723
- }
- ],
- "encoded_section": "7190132B37ADFB276B7EB4C503CECB801FA3F3911000CDC1162295B9A8A4CCA4AB56810D571A900273FB6BEA176F6DE9E6140EF7A28FAAD0A9DA45DDC9E40E4CE30B514CC388036F31BD93B0AB6F9EDC96583E089F70DEAABB3A6811E35A5463452308A5684FBDE3CA57D9CE8D9458C18606",
- "identity_type": "trusted",
- "iv": "3B99F43C244F3D82B2F519F26B2FD6F6",
- "key_seed": "A80F5C4AC0EDDD45BD9CCE9240FFC30E4616F733172FBC34E7BF903E052A08D8",
- "metadata_key": "3C7D19DC3473CE74F9629F28BD35D441",
- "section_mic_hmac_key": "B9C76D0EFC21D1EA2AF1A595745B91DE11AEAE661FB727846B887C85AFC79039",
- "section_salt": "CDC1162295B9A8A4CCA4AB56810D571A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A95C623FA8B0993A51FED27660FC46C",
- "aes_key": "F6FEE1C8CC0D3E0E0B994591AFA98C35",
- "data_elements": [
- {
- "contents": "6C0370D55999B1BA966C80E76E5A3143B0A6E9D0766601",
- "de_type": 508
- },
- {
- "contents": "EC68D3C546",
- "de_type": 542
- }
- ],
- "encoded_section": "599013A1EA22CB6A535194CA61B0F1D589DE5B911000D80A718BB8F999D070DC63B1FA1AB2629004697B686559499F94149621FF9F55241F4B64FFFD0A441863DFEA40E65ED5212335F948EDCB6DAA735F19776A404221BC469D",
- "identity_type": "provisioned",
- "iv": "D6FBED76B19AABBD88C9EA200FC3C231",
- "key_seed": "8A4E313D9ED5FB9056A2A329BC4BA88A75C1BA5540496647765AC14FDD884FDA",
- "metadata_key": "F3D9C6ED1DECC720D7640D5B0FA3BFCF",
- "section_mic_hmac_key": "C7A6BD4AC4BF8386D2EFB23E0497F7F1C74CE0C45DDF2DF851D857F2EAC01435",
- "section_salt": "D80A718BB8F999D070DC63B1FA1AB262"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "15D51D5529B6554802E05F2B0EF4DC28",
- "aes_key": "F4EFE9267FF46EDD2B41456BB04F5EEB",
- "data_elements": [
- {
- "contents": "7CE8",
- "de_type": 187
- },
- {
- "contents": "88EB094065F1E658E0B8265BC3F782C4",
- "de_type": 643
- },
- {
- "contents": "5720AB47DDC16762C5AA",
- "de_type": 248
- },
- {
- "contents": "0579EB83BD637F0CD137C57BF03F232166577572F6",
- "de_type": 760
- }
- ],
- "encoded_section": "749013DAA2590C575668648A3B6F693BB83D6E911000A98545FD8338EC5A966F1F501EBD5316900192E54C5C045F96FE474951DDA6BFE1E45CF6CB0F1FC97E9959BDB0AC58C60B5804E852491D23E443DCD3DFEEE8EA634974AB9952BFA30DA8B11DD97C0CB154A2A32C5A5E301E28C550DC2409C3",
- "identity_type": "private",
- "iv": "72EC916B14A083F2E7B345730323CC8B",
- "key_seed": "AF922192993E36A50CAC64F9BE2ECE249DB8B2CD256D74B729551D2F45FABAE9",
- "metadata_key": "21BEA9236D94154587759956D3F73485",
- "section_mic_hmac_key": "F1FCD0DE064ED425D757B87220A95FF47F6B3B9DFC12A1E8D2C31B5C37CC067F",
- "section_salt": "A98545FD8338EC5A966F1F501EBD5316"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7EE7B0CA063CE2CC1A2DCEED5FF6714C",
- "aes_key": "BDDC38B2F185FD0B4F644ED613987035",
- "data_elements": [
- {
- "contents": "19E3F28620",
- "de_type": 502
- }
- ],
- "encoded_section": "3F9013528238500EB32504E2DF4B101C2D7FE4911000BC04AE42E6A53E5EB4E86672375D905C90041372637B3F4839D1CCBCEAE0B52A6572106DD6E116AA3488",
- "identity_type": "provisioned",
- "iv": "1600C8A4C762DF0E381EEF9244F0BCB2",
- "key_seed": "503A4D71E1FAD56FE3DD7F8FEB65ACC7F116E09E19B8E7BE7EE89E46D0366B1B",
- "metadata_key": "9BC9C621E4AB6A57CAA69475ABB06C4F",
- "section_mic_hmac_key": "B7D4BEAEB788E9CA0445663C6EC20E21A73EDF73FC4A8DD61A948CB6C21C5CEA",
- "section_salt": "BC04AE42E6A53E5EB4E86672375D905C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "84ECCB6CC061557F886B9245936C76D0",
- "aes_key": "7F3B0C1BA0EDD583625029C096DD029A",
- "data_elements": [
- {
- "contents": "CA7963078A11D0A7228C6CBA3744CC798AC512FB3DD9DCFE",
- "de_type": 967
- },
- {
- "contents": "C7D4BCE12696450F47D9EA845672",
- "de_type": 431
- },
- {
- "contents": "177DB2DED349ED0EC2447742",
- "de_type": 910
- }
- ],
- "encoded_section": "729013B836C7E8CD3614C380121EC46833E761911000FD700ECE83DE5196B3247F17E0C7B8C2900471D9B6AD99D7935EB289FEAA1BECBD93D8E91AAEBF23F71D856A1D211558A798F1593DF65C74FF1A11691490EE59F50088E778193E2B82F10B63A019F699E6276425DE74B67A6997E7A199",
- "identity_type": "provisioned",
- "iv": "2A30A215680833E42AF075488E76C5C6",
- "key_seed": "47C165ECD9CE942B7213F794280434AF22A2BA002C5C841D3AB6D53F8AD6F3BC",
- "metadata_key": "0D9AF4F93F888702495D34C8C38C9C1A",
- "section_mic_hmac_key": "804B6DE7ED0C8CD36BD95E305C4E03946C8E398E2CD8E6D1D6C0D987E01897D2",
- "section_salt": "FD700ECE83DE5196B3247F17E0C7B8C2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C52DD0C0E31D56FCDA7804C58A6F3399",
- "aes_key": "0E2385A585A2092D068EEB158B3B816C",
- "data_elements": [
- {
- "contents": "7A1AD7A0F081FB5E75D2AEEE6B34E40AA9C45FE2BB68C0F4",
- "de_type": 552
- },
- {
- "contents": "78598CA8AA45EB9D46",
- "de_type": 810
- },
- {
- "contents": "",
- "de_type": 233
- },
- {
- "contents": "30827F3E80566B78620FDBFFE3FE2D31EA2FB8AA41E7EF2FCA",
- "de_type": 557
- },
- {
- "contents": "7BA140F266BEB8206478BA90",
- "de_type": 880
- }
- ],
- "encoded_section": "8C9013B90FBFD47BDC1DCFB3485BF6F2C909039110007D1B4708E6954D4C0804966FC950EB44900475C5B49C69BB677D07FC03DBE39284AFFAA42C55793F626211D1CC5907A788409D6A3CBFD4733A315BF3F2462B8C178BE54FDEDD30AA166BE53268874FD8873ABF7B2F33C42ED03E57F54B94023F17A7C6C7CE53C370513D892F41ECCAC88F501E55DFECD2",
- "identity_type": "provisioned",
- "iv": "2CBD7DCD77B66F17326CA3E36E31DA3E",
- "key_seed": "6C7E8B7296170D5C035E8738E66032688E1392FDD96567E94592D1B001E4833B",
- "metadata_key": "ABD68F6323A32F1FDB2F278439E1D526",
- "section_mic_hmac_key": "9B87D3AEC1B5C3199643D8542122D7EC1C619A6241F194B04929609E8598825A",
- "section_salt": "7D1B4708E6954D4C0804966FC950EB44"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "835DD484D2FB9B6ECA4A3EEC6067A7F6",
- "aes_key": "2DA3CA25BB833993F56C8A66D16ED327",
- "data_elements": [
- {
- "contents": "C44E2A5E5625A6",
- "de_type": 860
- },
- {
- "contents": "2134F33D2359D4F288D3A7977D0C8001EA2B4EEC98BC93DE27F9DE0FA7",
- "de_type": 523
- },
- {
- "contents": "993DA1984ABC29C3B21A11F03125",
- "de_type": 683
- },
- {
- "contents": "C1ACD752F8FD5786645E11DEAAA13BCE",
- "de_type": 865
- },
- {
- "contents": "341BAA9E743EA09FEC2E9282EA6B132D48309B8DD7F1F946AE68EFD43028",
- "de_type": 613
- }
- ],
- "encoded_section": "A690132E3DED612DE97EF7F9A44BE590A63D2B91100032FB76369CEB20CA101F1007ECE8694A900403BBD86CE0A9D8F2188B771C6025C47E9B3B31DF6640F8254189CC17F45B61470F01CEF3C0F22720B9ED4EAC50100F4015DD4049B640741067959EFCA41ACA09A216E34BF48DB9377CBF1EA080665151195475CC8FEA2CCB1BCA845314547E3540C1184B0D27C59BD76642114F823391E1358A05FF9817F31C19125F1C5DFF",
- "identity_type": "provisioned",
- "iv": "1C0CFBCAD7A73BE78ACEEC5AD98A6506",
- "key_seed": "10E128D39BF362EC6FFD8E8E1686E0BDD731892BC2A40524346E46905AB097AF",
- "metadata_key": "EFB6BBA329C8523F0D9593F267ADCFE3",
- "section_mic_hmac_key": "19B833BD8554B60C5A689185D7E087A08B15186B42AEDFDCE2238A7BBC3A120A",
- "section_salt": "32FB76369CEB20CA101F1007ECE8694A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "771BE78E465BE4E1C94ACB5E4B4ED943",
- "aes_key": "52956780EC21E2BAF2C9BF59C7C03E3A",
- "data_elements": [
- {
- "contents": "3369A56AD364F5A53D4790B0C56E920F79",
- "de_type": 743
- },
- {
- "contents": "7C7FA8A3BB5B8239EB0AF0D3BF",
- "de_type": 344
- },
- {
- "contents": "0CE02F21FF72540ED4351A6F04276489D0BCCB",
- "de_type": 649
- }
- ],
- "encoded_section": "71901301F306AEF69B7E55C7198404150FD74491100042AFBE3BB7529B6CE1957A34DD897301900416173A7AD7E611475C2FBE369D84DF2C53203A301A4CD74CE4B1C52BA023FB02B145DB1BDA8040E38F09290D173FA538917FDED3CDDA945A215A954B9B627FF1C724F32B958044C7AD01",
- "identity_type": "provisioned",
- "iv": "104F4E9AE0F9B86C604E225E535AED28",
- "key_seed": "E36C5E16253B098CF1A878723BC88CAE483B7CE4F075210834DF5F4232B3D721",
- "metadata_key": "506A4A3A85045F7ABCB2AC0D381C86EA",
- "section_mic_hmac_key": "F79D72CE2DA34D0B002EBD4CEFC93DE588B78E3D252E44D9F154EDB987BCF86D",
- "section_salt": "42AFBE3BB7529B6CE1957A34DD897301"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C8E0431CA117B1831BB6671CA7AA07EF",
- "aes_key": "E7AA3598705D6B36C70661E4AAEFC72B",
- "data_elements": [
- {
- "contents": "E50F0C47F610A27F273715EFD96E61AFC41F07F2",
- "de_type": 424
- },
- {
- "contents": "EA8A291C59E1",
- "de_type": 432
- }
- ],
- "encoded_section": "5790136D1DDE2484AA68F62E5BE1167BFFEF169110009500FA6CDDCD547D0BEDA1D6AFC6F04090024468565BA0402401B76CF55C729B5FE569695A820992D12CE45A465092D826C730310E13D9F8EC5D7D5717DA77C6CF46",
- "identity_type": "trusted",
- "iv": "71D6A3CAE2740361D9ABA1066E7330F8",
- "key_seed": "DD5E65D75F8C056BFDA78D3EECFD5A42A9397ED1F0BB12378D085F0B70F8750F",
- "metadata_key": "6C92FE3FDA57C9A3553A09FA5B37D77B",
- "section_mic_hmac_key": "71C6651A3B4956C3C5782D13E4FE870B4D5492C3CE9BEE8374F1D5298147D14F",
- "section_salt": "9500FA6CDDCD547D0BEDA1D6AFC6F040"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "09371C9C7EAF87C2E11BFA366EB616AF",
- "aes_key": "84BEEAF36C24AA0C83C825E4BE3F10A3",
- "data_elements": [
- {
- "contents": "4281AE866AE1A0745A5E6C3842",
- "de_type": 254
- },
- {
- "contents": "637873B552AB893BBE8CBFFA65E859CB95F2",
- "de_type": 935
- },
- {
- "contents": "F0AC06ACF732D6E74DBA2367CE64432210F0C03A9C1093",
- "de_type": 950
- }
- ],
- "encoded_section": "769013BCFA668DEBAAEEFE66D7CB5AFF0DDBC5911000178E6852E46CE22115DEAC0CBE53D4A8900479D4969091D3685CE787E51C0B7BAE37FBCA6A67BA8CB03A1BB9D1A08E0D7E6365AB4AE42CC2E445E6E302A7C1BCF28E69ECE32FFADD69F0BD5EA0297DB7241022BFFFF7746884B4A7A55FE41E2A50",
- "identity_type": "provisioned",
- "iv": "972F1E1A54C9BF5A318CD2F381001A0F",
- "key_seed": "20054A2AD5787C8190261524586AC1317AB9A939D775FC8A5559736F67F8EDC3",
- "metadata_key": "29A2753D8D2D165B52677B4478E148BC",
- "section_mic_hmac_key": "0F498B4B84396C4E4BBD8EA8AC04D100CFD0993AAF4630865665155399FD7CE9",
- "section_salt": "178E6852E46CE22115DEAC0CBE53D4A8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "312B34C1F8D62CEF39CC22C6718F2AB7",
- "aes_key": "1393D21C5EE04A4ADFB2A154F1BC0CE7",
- "data_elements": [
- {
- "contents": "897F9A471F5A3E7ED36837AC9911A40B3546DCCA1FD9DE7874ADC67A",
- "de_type": 852
- },
- {
- "contents": "4DF6900031FFFCE8F2E54A3AA4337FF095D50D25B677AC204B57",
- "de_type": 813
- },
- {
- "contents": "850EB9276E6B8A933DD66B44F18F2CA5",
- "de_type": 44
- },
- {
- "contents": "E814D95425E1DDC645357D54D569E223CE74",
- "de_type": 822
- },
- {
- "contents": "CD7697BDE298D3F2C6",
- "de_type": 97
- }
- ],
- "encoded_section": "A590135059149E5A7168D5647488D33E4C5D1291100043760DEB67DD337023E74D8057F8D0B190015EEC17F40A65777B5FD8DFD42A41610D7405BE1ADA0FEC3FF9582ACFA1BADA3027626CC70E0975642DC341B332E735BA412C8C217BC425C11B515077701A5384F7E66F54AF4137938CA1F8BF584C54AEA4FEC7A508FCDE1F7F045182F31C1DC9A486DB90340F79ED72F39D26D658C766AA4A149387CCAE407EC5013B7A61",
- "identity_type": "private",
- "iv": "CE7902AEF1D998C6ED70A23CAD78AEE8",
- "key_seed": "9B2B2B4455F675F8BFD7D6EF0D11DB025DCA56B8FDCC3F91E381A5F588F2AEBD",
- "metadata_key": "AC5D5DFCB4B394A76C768472CE1C4DB7",
- "section_mic_hmac_key": "A42A8C6554F3CE2FA45E52702A152F0B5AC825789727105DD723478778B410D6",
- "section_salt": "43760DEB67DD337023E74D8057F8D0B1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1E2C19C423EA98927CE4F1FFD50DE67E",
- "aes_key": "36C1EC0F045707BE7FB3744C95E33F09",
- "data_elements": [
- {
- "contents": "9427449425",
- "de_type": 409
- },
- {
- "contents": "FA4CC2EE4D6A",
- "de_type": 341
- },
- {
- "contents": "CEA2CA161176B4C3B33134476EF837EF32B5D278660CDE48E6B03C81F17F",
- "de_type": 102
- }
- ],
- "encoded_section": "68901308621A6F1E729548386EEE826FB947109110003A5233398F5D3BE64AE007254529830690022A40871AEDE5A3A73C83A9E5220F800AF29C2D8CC34A6EE29734B811823BBB805D32FE9C34BD588DE52C3C9B5FFDF5722DCD625D10AA0B72943A2BB61BFF5E5109",
- "identity_type": "trusted",
- "iv": "FCE402A294C3AE2A8D0F94417F0A990C",
- "key_seed": "E4DA5C79DB8653F6C010ACEC3D8D3A728690FCAE87811AB4B442CF8888597E7D",
- "metadata_key": "140A593CCC7E365D5E08D7B30ACE7B1C",
- "section_mic_hmac_key": "410D6C692C1A6E677B21261AC4EE2D61087FE874265E1A23BD3996208779682A",
- "section_salt": "3A5233398F5D3BE64AE0072545298306"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "88E66F0BCB2F75310F193D23254ABE27",
- "aes_key": "3BC020A4C2A62B57BF29E29668DB8E5C",
- "data_elements": [
- {
- "contents": "B7",
- "de_type": 727
- },
- {
- "contents": "A75A29",
- "de_type": 909
- },
- {
- "contents": "8DD038868341",
- "de_type": 505
- }
- ],
- "encoded_section": "4A901365F4100A29450DCA93B0632DA7DABEA79110008CD04A9DF97342A29F966C6BAFC2A962900112DF363FE2D500C29E75E28E5D7831F485B3CF426A87B4BA74379063395A62240A0F5D",
- "identity_type": "private",
- "iv": "28152DA95BB94508449CD3C229459A76",
- "key_seed": "A03E79B5DC16D85A779CB85A0771817415A6DF256701B261C1ACCD6B4D5CD2D6",
- "metadata_key": "3FAB498CA08113604E40C3D5F393006C",
- "section_mic_hmac_key": "3F13BE4FDECBFFDED1AE34D92642C7CEF5C406B877DE00B647EE908C12E6A95E",
- "section_salt": "8CD04A9DF97342A29F966C6BAFC2A962"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AEE14DB3ADD86B7B5DF9484C853A3781",
- "aes_key": "8B112E04E5BD800D5169E31665A707A9",
- "data_elements": [
- {
- "contents": "C01854F342050239D5A83BC58D8BCC107B",
- "de_type": 364
- },
- {
- "contents": "B06F3F2E6DCE4B0C488F1FBA9A3E09FAC662",
- "de_type": 793
- },
- {
- "contents": "A516FB2431DB05EBF5514F03650339568203BFD3FD5844765D3BA41A",
- "de_type": 57
- },
- {
- "contents": "0321515318EC9D9071445D0600A67EF2971E",
- "de_type": 688
- }
- ],
- "encoded_section": "939013ABCA1090D779D697AC56F3591EFF812E91100042E5D94F3697DAE433EB544B01407F509002E58E223728C742FE9FDDDFC05278550FBD564FA0520DF322B90B6F2C18C3E281896D409BF9CFDBE0306DAB483B407019ABAD11FB0B52420CA2CF238C20C05A31ACCF6911C5E2C3488705144CA481B31672D7BF316EF49CB3D88BEA3115DFBE71B69EE065D12039CE5166C9FC",
- "identity_type": "trusted",
- "iv": "3BB0C86F4784D62474D2310BB337A09F",
- "key_seed": "EDAA78185A1A5175083E82BCEC82F099C8331C5C132E9719C5CFD92154857279",
- "metadata_key": "7FC7DF905655640A265CE4249EF2343C",
- "section_mic_hmac_key": "FD55BD1DF6A3A7B11CE1F6CD6F54B5D5F467908CA565EE5EF51D8E87DAD23F3E",
- "section_salt": "42E5D94F3697DAE433EB544B01407F50"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B7611E4DB66970C64C508B012B19D038",
- "aes_key": "2AB8E62B732603133EFE0A777862A3B8",
- "data_elements": [],
- "encoded_section": "3790134C043B652FC7D9BB7E47E7C074C00E9A9110003B975A14294937B99D71E213A16D49749002D1804746ED376A0B7412BA53650D6F5E",
- "identity_type": "trusted",
- "iv": "896CA16D40C2FE9EF467463B781B2D30",
- "key_seed": "C8CC1B103276D084459C1C0ACF7EB4E360F9E700891FED6676E6D1075B19A369",
- "metadata_key": "141C175A69BC895A7B2F6DEED99F036C",
- "section_mic_hmac_key": "D3219E1AB65611823B84767FF42E79D91D19EACC7C057CE11954FF13B1E1876F",
- "section_salt": "3B975A14294937B99D71E213A16D4974"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3647592C7FBDF648CD7EDB024F33BD04",
- "aes_key": "3A1A12B6FACDF29899EE462AEBA9B344",
- "data_elements": [
- {
- "contents": "88A9B2A6",
- "de_type": 712
- }
- ],
- "encoded_section": "3E90137DA38E03A36C9F9176947F63FB67C12491100062620E36B963B4DE09225791E16F486690016BB6BB370C97BE4450674D73D9130B348323C380B88DC8",
- "identity_type": "private",
- "iv": "1BC76C617AFC378D7A296ABA4757EA3F",
- "key_seed": "C61557026D3D253A85F7AC194BAE74A1E761F59DAD126F47136E993CF2F5B6DE",
- "metadata_key": "D0ABA18228B34F9AF59D7248CC844111",
- "section_mic_hmac_key": "8FC4925A00CBF30B6ACB61EE98B832AEEBB03CE0ADDBEB4D989FAC453FF32F15",
- "section_salt": "62620E36B963B4DE09225791E16F4866"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "40952DC0D221AE688E3E7162C0923F0C",
- "aes_key": "19B5C1C6D9E48CC519A20E81D5D63604",
- "data_elements": [],
- "encoded_section": "379013E18D5027806A73D9048564062FA8098991100014034FE308AA953FDA2D86F85CCCEA57900257D1F879E535C6C429BC4A2BE220EE7E",
- "identity_type": "trusted",
- "iv": "BEA9A319D926C16A93C7C563D3A4725B",
- "key_seed": "F701D04F3AB67A553F3F007677AE499E1F573CC2AC9219EC6386AC9C001A55B7",
- "metadata_key": "758A0996ABFD4059E79623EEE974A91D",
- "section_mic_hmac_key": "B2C8BB02DF87BBEACA0088A3DD4B94036C80788AFE9D7BCCCEEF03265C97B824",
- "section_salt": "14034FE308AA953FDA2D86F85CCCEA57"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "756FDFECA95A8AD628CC57BB41E734AC",
- "aes_key": "94D6D7BB94A5503D75AEF2C51C940589",
- "data_elements": [],
- "encoded_section": "37901353D770C75B341EB54A72DE3DD4D0CC899110003B7992CACB34F3A9C66283E73D212F1D9001E853DD8ED1E580D63FAF80B4FB4F620B",
- "identity_type": "private",
- "iv": "8121921E27A4466509E573B3255F16CB",
- "key_seed": "A14520D1E0ADBEA8EDBD90360368C3B198C604A2340EF83FEA134721D6C79613",
- "metadata_key": "7AE0BBF927B2590C49791320A4325B68",
- "section_mic_hmac_key": "D5727682C5055A4090FAE17716DF6B0B0E321019C4D0809E8200850A4CBF458B",
- "section_salt": "3B7992CACB34F3A9C66283E73D212F1D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "82B7393BD43AE40BB06D1A3A2823133D",
- "aes_key": "469CBADC1BB8023F1BA0DA05A9310B22",
- "data_elements": [
- {
- "contents": "40A863DCCD4054C96E",
- "de_type": 667
- }
- ],
- "encoded_section": "439013C0F02349BBB2FDECE00F7C9296899417911000EF4B9DE242CE6D6AB6DA0B896C786F389002B25529FA48ADEF1CE9AFD454048A8390B4713EE35D5B6314919CD64D",
- "identity_type": "trusted",
- "iv": "D7DE8E7D886512AD0339056C7CC54C62",
- "key_seed": "BD980624836660BA2C0982812F6F23078802E982DCEA461EE94BD4E8922BC8B5",
- "metadata_key": "060B8DD7D93EFDDCE3FA26ABE785B9E0",
- "section_mic_hmac_key": "BE821CA0FD33D9E57C3BCE1371AC54A6DC461EA194D0910EA9B38691F76434E2",
- "section_salt": "EF4B9DE242CE6D6AB6DA0B896C786F38"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E4160F1914D232240945FBF05EC8DA4D",
- "aes_key": "673A79D26DA0EEBFC56E507EDB61F814",
- "data_elements": [
- {
- "contents": "BC315F251FB68CF65A3663343CA7",
- "de_type": 562
- },
- {
- "contents": "DE7CC83BD90D587EE41E2EBEFEB39E85BCCB1B876DE2A3ED7B9CD046",
- "de_type": 259
- }
- ],
- "encoded_section": "679013B3FABC50AFB0E2CC60D03D341293DFFE9110000AB560F9226EAE8DFF4EDA62A661E9819004946BD0DE5F133F9AFA422180C709FF504E166A3FF94760F24B0248E830D4E848058AF863E9F4296908B3F1061FC8668480676FDA3DCDCCDD5B6C11A9AAB632B5",
- "identity_type": "provisioned",
- "iv": "3DC82BB10A656986B8EE35FCC6C4D681",
- "key_seed": "DD867E8AAA962AEAD05B0A027C1D0BF098AC2B5A9BB81F6629A09A3DB6DF77A9",
- "metadata_key": "EBED6F7F0D41A90BCFFD07DC38AD4E7F",
- "section_mic_hmac_key": "52835EE8B0354CC1819B4543F5216BDB806D6202C824FF1BA2B1EAEAEF7B667F",
- "section_salt": "0AB560F9226EAE8DFF4EDA62A661E981"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "23EC2882AE29D794E00F3C929ED4EE82",
- "aes_key": "21B174B8C2B2C1C32A151FFB3BEE8682",
- "data_elements": [],
- "encoded_section": "3790137AE67F61984C37A01FB8B94165B8EB269110002A37AE16791BE17CF76D244E7714E43190024E181B5BBB9F5FB00E6A774D12FD3C00",
- "identity_type": "trusted",
- "iv": "A9BF6682AABD317E8A06D867766A652D",
- "key_seed": "A9804B5A70F86AC25E6D501C3CE9EB2E2125DEEAB3AD5D05F0BEEDB0B70F8E89",
- "metadata_key": "640AE8DF2C5FD30430D67174765B5D9C",
- "section_mic_hmac_key": "33C747147E7BF5C0E36AF6EA7071655381568471DAFA92ABEBE4C78677219216",
- "section_salt": "2A37AE16791BE17CF76D244E7714E431"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BCF6CA8BA694336C8555B15D6E06F5AE",
- "aes_key": "18375E93FA4431A762A9B737D2336ED5",
- "data_elements": [
- {
- "contents": "A84F3A8B3FC540FD359F5DBBC001EF57",
- "de_type": 462
- },
- {
- "contents": "75029C04F876937EF2CF8BE2BB09B1241CFFB0A631DE263E",
- "de_type": 960
- },
- {
- "contents": "7A26076DF65B13D39494",
- "de_type": 555
- },
- {
- "contents": "BD1C",
- "de_type": 307
- },
- {
- "contents": "DF3E8C",
- "de_type": 513
- }
- ],
- "encoded_section": "7D9013BA96BEE6CEC0F79A25B8BAEB823DA45B911000F11199E929FB5DE7474EC679FE4B5A4E90022C2DA6326BC23D58AA4E77AE3ABF66A8B261E4E78FF193835D2B9A5F3AC971BE4949847D170429A80B5D763F7D136E9063D7F40A75AABD4F956710B6D5EA391C631FEF5310261634D6578A6A7F7184508FE7CF52E224",
- "identity_type": "trusted",
- "iv": "0CA6D1FB7354E9E4CEF190EB8ED327C9",
- "key_seed": "ED623407DB6E29C91192E1EDE3B83BF57EEECFE10EA5E2547C59F31F836634B2",
- "metadata_key": "A6DD5533AE1DE0719410FABB85400660",
- "section_mic_hmac_key": "B34016F96945E2AFA191598597EA58E6D5F5AE9EF8158B45AD50F60EF436C732",
- "section_salt": "F11199E929FB5DE7474EC679FE4B5A4E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DDCCACFAD9051E1B99C43C413148B0EE",
- "aes_key": "E247320C16C197987CA928AD87BA1030",
- "data_elements": [
- {
- "contents": "",
- "de_type": 720
- }
- ],
- "encoded_section": "3A9013BCFE98BDFD2205C5C668EED3FFB8E672911000DDBE757080D8CA7B65921FC3A638646190046065B7703FFC69AF2E14B00D90BAE51F9111E6",
- "identity_type": "provisioned",
- "iv": "BCD763E963B259C4E19C8A6F62F05810",
- "key_seed": "406F13FCBECBF6E301208FC9C4AFBE541728D2241C987C38D7DE961A95874752",
- "metadata_key": "FB990D13C3D0EBE79AF30E19B6262D66",
- "section_mic_hmac_key": "D441BE8D9C7952F3B60B023069D64BF2397257FC8FEC7A2BBC090CB2646238C9",
- "section_salt": "DDBE757080D8CA7B65921FC3A6386461"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FAD923151B5EE843B58C5E02C8636EDE",
- "aes_key": "D6353A97771C8967BCA9F7AE4884DAC9",
- "data_elements": [
- {
- "contents": "DE7E13DAB250CEC845BABCD1",
- "de_type": 860
- },
- {
- "contents": "6531B82D346C3AFD2D276FA5E02E2A93",
- "de_type": 274
- }
- ],
- "encoded_section": "5990134AC7CD530495F2BAFB85AC93EC6F012B911000438C5B3D5AC51F66F6C683C9ACDD401D9002AC396666585E471439C0A5EF4DC05AF49B9600A96284D58D2C72807902769EBBCD923F31743ABB3F7440C3AD394CC436244B",
- "identity_type": "trusted",
- "iv": "30D9DC82B1A62B353A8B52CA627211A0",
- "key_seed": "77524ED887D0A9A1A96782470380EF5672938C21EC13CC43658246E6520D3D75",
- "metadata_key": "76EA680B23CE5062373D8F0AC9FB0912",
- "section_mic_hmac_key": "A83C77A67D7CD424BB55C400C3F12E4FB47F6602FE03F0ED8A1E2DF1A311D1F6",
- "section_salt": "438C5B3D5AC51F66F6C683C9ACDD401D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A5EBA3EC2EDC3DD714C2EB3288F5E142",
- "aes_key": "CE45D560B190E915974255CA1378211D",
- "data_elements": [
- {
- "contents": "80677B0D8386DC",
- "de_type": 102
- }
- ],
- "encoded_section": "4090133665BFF6F114B04DCD82E3E6627CEB879110003295E996819A16214D393D240335FD779002F049668CE0B95A53D2EB885B92DB5BBC901C37F3C5F350C0C9",
- "identity_type": "trusted",
- "iv": "D9E137F6608666AF35D69A5EBEEE38E1",
- "key_seed": "F33CB9D14DD2597AD7D68D0A4F7BC85C4F32D2B7F4EE7227DABFF6FC5FDAD466",
- "metadata_key": "AD9CC4271E2075FB353A9CB5DCD07162",
- "section_mic_hmac_key": "0D0174A3186C8CF1D9A57AFAAECB8B284D7E08E82ACCF3AF6C39F0A27199B496",
- "section_salt": "3295E996819A16214D393D240335FD77"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1AC1B2E96E974AEFAE2BD3E1CE81AAD6",
- "aes_key": "BA47EF9390032854FC6FAB604892F729",
- "data_elements": [
- {
- "contents": "E6063E542EED02F65B9B7BC296A3F78D",
- "de_type": 413
- },
- {
- "contents": "A5D1",
- "de_type": 969
- },
- {
- "contents": "7ADCCC9D04EE88E04EACCBEBB555CBC4A2479E1425656DC017568B74DA",
- "de_type": 919
- },
- {
- "contents": "2F0BDAD9E57D070C4667F38E193B",
- "de_type": 949
- },
- {
- "contents": "8CF202B2A335336F0A5F2589FDC3CCB21E46658B549A787021",
- "de_type": 618
- }
- ],
- "encoded_section": "9C90135BB284FDF4C800B87360099389CDDB9B911000BA4FBB4D16C95F10913371D7DCE9D3E390020CE61C619DB74977497E427B1C0E9CD9F9D3581D42AE5D15081AB1494E46914E962366A6FADD9C79CC4C64BD0B3E7A83011385919B57F8C04E17CC46D31EB470B7580195A2608C816EA4D5D34296AFD1CF3DB51A99327E8420F15A73539B451D7A7BD9915F56D2D9CBB7684C07146564B6E24B5CBF",
- "identity_type": "trusted",
- "iv": "42F6C7EF706340A72B05C5C6A99E316C",
- "key_seed": "B04216F33F8E756F288B27E645564265383CC9335CFBFF47F439629236A697F3",
- "metadata_key": "A1FCFBA76475B80E589617C587806CC1",
- "section_mic_hmac_key": "1C62F6D1D011A26040C16859D31494E66A00896B20C852B3FCA34B065DFD48C1",
- "section_salt": "BA4FBB4D16C95F10913371D7DCE9D3E3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "89BF5E643860DA08F54E99325545E0E3",
- "aes_key": "B6EBB7A5B193254333D9EBA863ECDC2A",
- "data_elements": [
- {
- "contents": "7A10F256CC3DF91E78DF65B24F052339E8C81DEE572D96C4",
- "de_type": 833
- },
- {
- "contents": "A15E536C45941AD26F38EE81E50E6F5C54C5DFFA12BEE0E3D25E8CC5CF",
- "de_type": 607
- },
- {
- "contents": "12CE431D2ED376FD594A80943044EA856C642D11DC0F2D9450",
- "de_type": 31
- }
- ],
- "encoded_section": "8D90139DB6F3EB17792669F56F53FA03DE87C09110003AD9600CE15FC3CE465D0228FC8CCE769001CBA6140B22FB73FB1B0E4F8950351659BD43415DC971F0FA325B81986C47A74F3FB2CB7E7374C278ACE925EBF2B7067F8E6488C4CC57BA6AEB832C8B1B4D9A002C8870DFB147033F652EF25CCF19D8D59727EA6BF61A0B52D489106BD21BF8788EBB015E1465",
- "identity_type": "private",
- "iv": "AEF47384658A554A58363D62F7DB13CF",
- "key_seed": "056214B06D0378EBC92E13F6C5EB0FAD7564243DD2317D66CA38C340BE54BB4F",
- "metadata_key": "813ED8A5314A2505023A99227D91A6A9",
- "section_mic_hmac_key": "618FDE5AEB4E190D45EFF78AB4BF2DE14BA35855973E688853E749A69E3A47FE",
- "section_salt": "3AD9600CE15FC3CE465D0228FC8CCE76"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5D5F06D37BE24A3EAEDC3F746FF4E579",
- "aes_key": "E713EE216EDE341FE268F6237725F725",
- "data_elements": [
- {
- "contents": "FB504B451A1F0820FE29A2FA",
- "de_type": 164
- }
- ],
- "encoded_section": "4690137FD2067B6E15D4CC6AB3E34A8295F66F911000E9A8A1CB24E1555E9EF384F4124C6BE29004A963964B7D5921A4FB27CD39CC194268B8CF554ED279FCA799130371519A31",
- "identity_type": "provisioned",
- "iv": "13C7A35EAACE574E2EAF7A13B0A6A32B",
- "key_seed": "22A1BCD9F24ECC0BC71F4525D8E531EE7A5E40BAE308C43DA07F034C883C8396",
- "metadata_key": "E6A03218FDE3E27FD782B86E176647BD",
- "section_mic_hmac_key": "C0FB0F118A976D4B19E95AEE65EA88359C9F071CDB15ACBED9211A5B1EAF958C",
- "section_salt": "E9A8A1CB24E1555E9EF384F4124C6BE2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95B989A608C0D6967B551F8C7CA6EBE3",
- "aes_key": "0B231EEBD178E593D7F473D51406B900",
- "data_elements": [
- {
- "contents": "36520A4632FCCBDE9AD34A32301A30B2439AB22E330AA7A18C3A61",
- "de_type": 275
- },
- {
- "contents": "5B2B4C836A013A651571B13DB670155FB746325B8F",
- "de_type": 620
- },
- {
- "contents": "DEF0BBB8C8B205",
- "de_type": 41
- },
- {
- "contents": "1B5CCECF35D720A442BB0AE56E1E91D5EE0CF2BDF5DD6240",
- "de_type": 719
- },
- {
- "contents": "6BEADE80570A85CC0D95AAB0E3DD76DC2A8123DC48D395380C",
- "de_type": 789
- }
- ],
- "encoded_section": "AD901306AE4285463C53926B1BD6FADF6E1C5691100045E4F8E6A509CEB6F9A49BE5A9B9C20C90011A4BB20D968C614C735D4923F5CAEBC4CB1C56FC8F02B3319B998A5069B4ED1BE73891C3F7D0A6F4211183456B571768FCB52280F32D2D9BF903D21EB5B98781A86FD0548F68A78703F17E0C2929BEA276A85041F8B8EA24B9D6E7D6A627A49812349B564141338E2B3C207B17EF8729E4A3E3A0079D08F33A7B34CC1499CC47A5D460CA1DBB",
- "identity_type": "private",
- "iv": "AFC59E49ECE5A97EF0FAEACE62660170",
- "key_seed": "17FD257E62CE7BC878DA16C5043579B98F79732B0B817B4F2EC51738CB77527E",
- "metadata_key": "3186CBA7D7424D1B8B47B2897F11732E",
- "section_mic_hmac_key": "2594DDF724498B52B29F3DFD0CCA6283C3403310AFC8E4EF37FC475E30367BD0",
- "section_salt": "45E4F8E6A509CEB6F9A49BE5A9B9C20C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EBEC6D0EF372E4BBFD8A88C319852FFC",
- "aes_key": "AAB99254BC7CFFE24CB438DF3C727AD1",
- "data_elements": [
- {
- "contents": "",
- "de_type": 432
- }
- ],
- "encoded_section": "3A901307CC248287D8A88DB671E1586D3FB9CC9110002CC36DDB7D7A279AEAE122BA13AA019990046C51B7CFA17821450A90C98A7B38BD5DBE4FBC",
- "identity_type": "provisioned",
- "iv": "685AD69EF191E56EF06D7C86714348D9",
- "key_seed": "5F065E34B94CD90CC221ACED8910D641D4FC4C6F56934780189E4E6E67DA4901",
- "metadata_key": "A592DE8232D18AE8E195363D4B6CD07A",
- "section_mic_hmac_key": "0264B54BB116AB3514B39B737B87ABEE206F8CD594CBB3E9B24648C5F53E635F",
- "section_salt": "2CC36DDB7D7A279AEAE122BA13AA0199"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "94DD0021538CC04AA70A5F77125BE600",
- "aes_key": "F0C472163938A1BD47B15B942FAFC48B",
- "data_elements": [
- {
- "contents": "A00EFC0F33C01F0AAC4F5DC6541F53C8CA5B34",
- "de_type": 481
- },
- {
- "contents": "B12B24",
- "de_type": 630
- },
- {
- "contents": "81319ED0F5EE75A123443AAA795D81B9278993C6BF",
- "de_type": 503
- },
- {
- "contents": "8224C14BE4C7CCF408C4E3",
- "de_type": 435
- },
- {
- "contents": "681B900D27F4699C820155209DAE07AD857DE896C037DC49876E1E",
- "de_type": 951
- }
- ],
- "encoded_section": "979013E5CA4E440ED0EB31935166AF13C4256A9110001ED58C6BF2B47B9556A5D909E29A7AB49002DC33B008D4CF57AC179104B3F5DDABE7D56D19EAEF9BA28100DE838F8D6B98CD2CF81FF9BA53847382E6F71E502F127A858FEBB8AE77D0A504D685DCD638CB167B60DA02ADCE29E3F57BEA20F1113C7718CED429E7A813E03208194C0C99421F55D22265B201A2D80FFB254F5FD619F1",
- "identity_type": "trusted",
- "iv": "807C9838F5A3DF8073FDFBAC74766862",
- "key_seed": "ECA0F4886F264A9CFE0BD7255F6FA88B64AEE99627DD204D4100523CCD96A354",
- "metadata_key": "8344533765DC97CD1FF2B037CABBD8D8",
- "section_mic_hmac_key": "F0D7ABF7AC2B3A3945209EF72944671D98A4EBD63BF94CDE96EE2D364699342A",
- "section_salt": "1ED58C6BF2B47B9556A5D909E29A7AB4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C112DEFB7B31A43E9EA8571DBA1CCAB4",
- "aes_key": "383D18B559037EE81B05F2A3A636A6EB",
- "data_elements": [
- {
- "contents": "27C28C2FF32016A4829B967FDDEC6CC7C0B5BFF5EB412D4899BC2C4A754D",
- "de_type": 382
- },
- {
- "contents": "4650A741B70621E3D576483481C56AA21F9C",
- "de_type": 310
- }
- ],
- "encoded_section": "6D90136D9098A3888E98C30DA05CCF9EC57EA6911000FBB0F01A46FADCBB680D50359653C27490017AA7C1CE5BBC717C0A1D0003F112B244703260E60034777FAB79B3B9CAB5A5E8E2A955F11A4CD50FF0D7D1FB7F8E17944795C73E8A24161A13FB2F578F549A82B2822D63668E",
- "identity_type": "private",
- "iv": "B87F931962984B01923EA47FD3193409",
- "key_seed": "A9A9F32E48740489BAC39106C497D0350B42C553BFFAEE0A88D67B4A5B424D5D",
- "metadata_key": "745B81AF3E8CC9B2FA7203A71AFEA41A",
- "section_mic_hmac_key": "0AD484AD1377BC263AB10E7FD0990D6AF7A9F70BC9CEA564EE60913EFFBB13F4",
- "section_salt": "FBB0F01A46FADCBB680D50359653C274"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8F20FB3600592D6EAAF2F1E74BD0CEB0",
- "aes_key": "F9A37408AD4AB15C048209D298BF9C3B",
- "data_elements": [
- {
- "contents": "348A6AC7D6951E86456352AE6DC70519FBC5",
- "de_type": 869
- },
- {
- "contents": "07BFAD354EEEABB377E35A3CA9F93C2919D63A5F60F47E9A6E6452",
- "de_type": 379
- }
- ],
- "encoded_section": "6A9013F3CCF8ADF413726CF270C2464A7D6D0A91100075FB92C2BDB77630B96A7871350B3CCA90018B5CB809F8B85ADB3582601C38071C20A3D7C776D0FDEA4E4386B23278FF5C05EF39173B35ED5E64B5E63F5299971353BB80A3E88226FDE3610113FAE3650A87EF3BE8",
- "identity_type": "private",
- "iv": "F48F1E40820CDCF7DB3E6107C448A32B",
- "key_seed": "771A683FBB41544543E3000270F62B0E75BE97DE1E8931A5B0E30874A315B40C",
- "metadata_key": "CDBA3FBDB8051258774E18B2A19647A9",
- "section_mic_hmac_key": "58F7FF2CB350E0FEE347D0DD9DB0A50D1074F737E04E34351E5D897545149F01",
- "section_salt": "75FB92C2BDB77630B96A7871350B3CCA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0718AFF8D3F260798EF3336D840814F9",
- "aes_key": "1978A74AB0D377A6443E38504531BEA4",
- "data_elements": [],
- "encoded_section": "379013792A0670A6E601F9061A049EDD5E34FF911000B179453D2FB79CF56E8A31CFA8B15A389001BBE562860A2039D0152A0496133E865B",
- "identity_type": "private",
- "iv": "167401B2B2AD0240F0E57038F262961B",
- "key_seed": "003D1A9D017396CD95C9138D152B44E500408A013CC2E3E50B0D01B2E9CD80BD",
- "metadata_key": "77C3866FBD457BE09D29A90CE12E1689",
- "section_mic_hmac_key": "B3A6886A924FE33D724385D45E5FE158AD66370D2791BA5DC553D5E66327001D",
- "section_salt": "B179453D2FB79CF56E8A31CFA8B15A38"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "21E532A86E771C51558095090F8AB251",
- "aes_key": "68075EA0842A1D448F7B244E5FC6B29D",
- "data_elements": [],
- "encoded_section": "3790133308F2B9AB4434656EC8305913A01C089110001708C5DD384808FF64D2BA400F2312A290013A8342F0CC39E9B96584E5CA7DF1DE7C",
- "identity_type": "private",
- "iv": "227DB4C6845BF40B82073BC0783EC727",
- "key_seed": "C2EFBD062A6498B9E52733922A598BF3D4949A74FDB57D92D0ED064239E5C37F",
- "metadata_key": "41C0037D03840085364AC811B553003C",
- "section_mic_hmac_key": "452A3B6B009FFDF2B2E8F6CC57A2C741418F33E7A85D9FFBD33FA2A8ECEE28BB",
- "section_salt": "1708C5DD384808FF64D2BA400F2312A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "52F9C4E2952B34DF2C0296D50B197CBE",
- "aes_key": "507A391115EA010FC7DCD6F69DAC200E",
- "data_elements": [],
- "encoded_section": "37901397A0CBA6F76625846FD918D0DFA8B5EC911000807D0ADCFE480829130092A629C43B779004E57DD041E63A98C2398922E8C6780738",
- "identity_type": "provisioned",
- "iv": "2CFF04243F275FBF2A33912ED849608C",
- "key_seed": "C39B6A57CC29C43B34A9B24B6AA5F88B68249F3EF3FA242B7A227A7FC5B9F013",
- "metadata_key": "F902EDE5E988C6DFCB6E550C739CACBB",
- "section_mic_hmac_key": "F5914A0D86F740B26A39165146FBE172469E9C3B6A8D7FF5659E8C3A3C40FAAE",
- "section_salt": "807D0ADCFE480829130092A629C43B77"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "560AA4E7A57E03DBFAE7FBD4EFDA7CDC",
- "aes_key": "9638DDE581FE5B67F2DD50376E3A99D4",
- "data_elements": [
- {
- "contents": "F2AED0A54D5317974CEA1732E79EFB900594C5660907",
- "de_type": 56
- },
- {
- "contents": "",
- "de_type": 992
- },
- {
- "contents": "",
- "de_type": 86
- },
- {
- "contents": "61F5EFF11047065B2933557CA2EA9356A4B569A20B362C760A",
- "de_type": 748
- },
- {
- "contents": "8754249571E61C93D55CA58B9DDB23402C",
- "de_type": 790
- }
- ],
- "encoded_section": "849013203F5A7282936A2C5F6B7D31F2C2B3F1911000350FBAA0A5C14EE71DD5564DF054F7059001F63722D44C16939F37A228801E10C7AF0D3AB2DB910CB4A915A66C9AC57A057E79A46BEAE2B01B7B2422C789156152DB2C0C3C31EFCAFB6260012D7B01D8E55C0DC93FDCE2C9E3883DFBCF4D97E76A4F557470AFE3F6F3630A59DB334D",
- "identity_type": "private",
- "iv": "5FA4D01E917F4AF96837EAC84C94033C",
- "key_seed": "AE37490A40777E13212927937035E5D5CAB7CFDB227BEF01AFCA1D4CFB348910",
- "metadata_key": "7C0861BE5B2DA8F097517E544D50EC5D",
- "section_mic_hmac_key": "A2CCBE29DCC3756A8B56810F1D9BB20F3087F60A04CF2968CAFB067298BF1FF0",
- "section_salt": "350FBAA0A5C14EE71DD5564DF054F705"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "136C515299513C1C23396C72472A869C",
- "aes_key": "F8E96AD115365C1DA32ACE0E955D707B",
- "data_elements": [
- {
- "contents": "0004ACDFC6E1BF2DFE084CEBD5210494FA370D8D",
- "de_type": 439
- }
- ],
- "encoded_section": "4E9013B093C4394DF11527B26EF2770B65B0579110007923EAF675A0D97190BC856AAA92FA5D90015BC232EFAAFFE8486D932A63D9121426BC5FEE983041B15F40194FFF44A3470C0F5862DFA2DF7F",
- "identity_type": "private",
- "iv": "2F972A959571317A323BAEC64650D9E0",
- "key_seed": "653D1790B9B4E73D40ED58AF3548C01EEE9A1CA7EDBB6788113943F29BB8A7A8",
- "metadata_key": "85BB2BE74E51ACB8D631E31C193730C6",
- "section_mic_hmac_key": "01A9931123C16D70DF660545EBDC39099DBDE472CA53ECB8CF65CFA3FA67033F",
- "section_salt": "7923EAF675A0D97190BC856AAA92FA5D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D877A078133B36B3035B3D2FD091B01",
- "aes_key": "F141257F9BECEC2DA61B11F67E4E107D",
- "data_elements": [
- {
- "contents": "21F663C2B4668DBB030C2D2EB1506BDA8A77FAEA98B4567E8A91CA",
- "de_type": 173
- },
- {
- "contents": "71",
- "de_type": 401
- },
- {
- "contents": "FB19",
- "de_type": 751
- },
- {
- "contents": "755DF137F59366F68158D6BEA4F7877F1D2BB7CCF6962137",
- "de_type": 748
- },
- {
- "contents": "A286226956337347E1A54B",
- "de_type": 192
- }
- ],
- "encoded_section": "8790134D927FD029D5F95E67D68D646A6A361491100039D2819931C23ADD06B49F18423BC84C9001B112FAE321EEC67D926158ECED1C2B19CBD9F742E45F25925FE6C6795BE721A2F72638DAB903CF4C970C4B3C35DD693FDAB3DEB719FAED9DDC1711F51F631B36FD26BFC34F9039E535BCB78D1A14D5113270D00F96A956D0DF082E2F30901283",
- "identity_type": "private",
- "iv": "32F841444267601174749E94F87DE1C2",
- "key_seed": "E9333F52CFC570120ED0105ED56952CCE1FC9645367619713FEBAD14AFF0E76C",
- "metadata_key": "6E13A84FE3BA463ED9E607F5B1BBC9B4",
- "section_mic_hmac_key": "3C44C33189816BB62961DC5FFCF2C71D910C0730BEC3953C5411489DF41ADFAF",
- "section_salt": "39D2819931C23ADD06B49F18423BC84C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "71A9A746DB966A4456DDE375B6F12606",
- "aes_key": "1D5C27ED10C3063737A421D25B061C89",
- "data_elements": [
- {
- "contents": "39D427B897A964131313B227CCC4DE10B368B8",
- "de_type": 519
- },
- {
- "contents": "3A67A2E11BF608DC073983D1FB0DA3",
- "de_type": 701
- }
- ],
- "encoded_section": "5F9013B8AF9217D548709840B3AC857034ACB9911000B4F398A8A439BC972F70E2609A6C7CA990022A637108B4F22FC613C0A0E75AC2471132DD1D972FCC1174BE70BB6CAFBB3F6998C49DDBEA8A425CBB28664071BEF42114A0701F112D37A7",
- "identity_type": "trusted",
- "iv": "F2754259EF584E77196E83CA8B4B49EA",
- "key_seed": "B1939F4E5BF1BBA5B56B4C53FCFE87EC1873876B1869B215D79AE2B742AFAD08",
- "metadata_key": "E35B349B13DD23987416D3C506A26EDA",
- "section_mic_hmac_key": "2DBDE1B077515A353314FB3D933F17F37893CA377766A4C8A3BEFE1E8E2FE8A1",
- "section_salt": "B4F398A8A439BC972F70E2609A6C7CA9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0633A7D37D0E75C82950F86658617ADE",
- "aes_key": "1EEFF97162B2CE8A3E6C657B8AFB9DF5",
- "data_elements": [
- {
- "contents": "0A263635A12CA6",
- "de_type": 461
- },
- {
- "contents": "13696B3B2D423455ADE08CE7E3BEDE",
- "de_type": 304
- },
- {
- "contents": "4382E5A1567DDC",
- "de_type": 911
- },
- {
- "contents": "",
- "de_type": 3
- }
- ],
- "encoded_section": "5E9013C561581D56E580C0221BE31A9F5A97D4911000F341712F781AD354FB9444AEB9813A769001EF9DCFE8941FC69C1BDA3B6E61D484BE3CD363AFA8F753EF60E93BC52D8721FBD05DFD27C74584E9087B7645148A9696148501617ECEA1",
- "identity_type": "private",
- "iv": "1442CE37668B7EE9935E4E400C7051BC",
- "key_seed": "E999377BE50FBB31279CD98440114E6CFD0019FA212A47015B9EE5EAC4BD49D3",
- "metadata_key": "D489962146D1E488C02D148298B86ACC",
- "section_mic_hmac_key": "48392CA50B2CEA5B7AB937397A530A54E1EF8320EE64E23E377333DC1A0725CB",
- "section_salt": "F341712F781AD354FB9444AEB9813A76"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E5BCB2BFB4497D55C0BFE5EDE0CDC6A6",
- "aes_key": "59A78870C55690255DBD141A15F090CD",
- "data_elements": [],
- "encoded_section": "37901330292E7FF856BD9476F0190AEE3ECA199110009029F02502CCA11E12A7809D3BA9304D9004901405D5FDA5DE684E4D372DEA766905",
- "identity_type": "provisioned",
- "iv": "08584E585B5ACA5124277D06708F34AE",
- "key_seed": "8AAF95575F0A0E04188D3E42DA9F50AA3740E28DA9BE4815B98E74707B02AA15",
- "metadata_key": "537EA5D04F0A1B31DC898C1FEAECBAD4",
- "section_mic_hmac_key": "F8DCF1DBF531FA564EBA22F2809144AF11DF8BC792A54F77513AE58406FACE1C",
- "section_salt": "9029F02502CCA11E12A7809D3BA9304D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4579CC1B14F511A11A441B67B89E39DA",
- "aes_key": "7E0F6C860EF0D264F8ED7FDFA9D843DA",
- "data_elements": [
- {
- "contents": "F8CDB7B169E1147E9B47779FF86A1F7BB2",
- "de_type": 284
- },
- {
- "contents": "A7FCB30D4379892BD07112349F7580699FE8B8",
- "de_type": 603
- }
- ],
- "encoded_section": "619013E68A36F6574C0776D73BADC793720D31911000115B858A780FD00A4B1D74707D2F85679002F3B4DC9017DFCB21B818ECDA648233753AD42FEE0C77901D741C38EEFF3188811EA6EC7BDED6517DDF15636024BF3DD27B6CFE7A479848AB9DD9",
- "identity_type": "trusted",
- "iv": "37288FF7CCDB400825540E0E494D3A30",
- "key_seed": "1577AFD72DCFDE648AB3084F07F93F275D98D58FEBC60A6CDBCBB1B1EC0E2F05",
- "metadata_key": "77A66776AD508B9319A72FFAE4F45720",
- "section_mic_hmac_key": "E2AC40D5A99B858D41D224CDB76685071E9DA4A1A4313E913C7C57DB5C05E76D",
- "section_salt": "115B858A780FD00A4B1D74707D2F8567"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "AD85D70775BA4E741F713229A6EF6529",
- "aes_key": "28A1B46194B2DDC3497E5AAE297539AD",
- "data_elements": [
- {
- "contents": "F3F9AD43482D0E8DC791D639C671542CA0EF24E4A3",
- "de_type": 292
- },
- {
- "contents": "C32E4B8D3F8F7B308A",
- "de_type": 578
- }
- ],
- "encoded_section": "5B90137F7A54A12574145B6DB3F5E27E73E7BF91100024E555596DD4D3555D08243513295FBC9004A301DDBBD6272926BB9DC0B9885A79507EE94B5969DD57C197A16CA97315534F7708D2B98743EFB67CDE8880B55CB6FB6048F9BF",
- "identity_type": "provisioned",
- "iv": "6899C0DEC131BB47E9D9DC98DD724BAB",
- "key_seed": "59F841FD000EB3E98DA6DA3035D326B9242698347F0C972E2C45E6D28C2B7A2D",
- "metadata_key": "A90DB67D319DE8549F8B31EE91B69FD0",
- "section_mic_hmac_key": "B903E393AFE19D7DC80AEDAC8222CD5B99E60102BB471E4767F06DF32561F7FF",
- "section_salt": "24E555596DD4D3555D08243513295FBC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1BDF3C712E3AE53D63309EE3B8023A87",
- "aes_key": "980CA9E6379B483E443DC1E160D5201C",
- "data_elements": [],
- "encoded_section": "3790130534A9410FE91114106C1CA9A8062F9A911000E578AE0019A2141EF58F01365677B05490047AC84A7E04229A68A6F7F3308374957A",
- "identity_type": "provisioned",
- "iv": "7D7E507A0BE6403325935B1DFA05A9F3",
- "key_seed": "ABA16E9B7EE1835A8CC675D390FDD4616623AC235379B657C1233FEF741FA690",
- "metadata_key": "2D8A58D701172EDA89904C96AFE41524",
- "section_mic_hmac_key": "54E5FA2CE95932EEA68CDD1BD3D445AB83FEF2DCEF7E3A9B2C3785A92B228302",
- "section_salt": "E578AE0019A2141EF58F01365677B054"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CBDCE43E4A6BED0CA0C6D08F3065F633",
- "aes_key": "CEBF5E518C10D4684BEC405850BC032C",
- "data_elements": [],
- "encoded_section": "379013FE585D545653A98465FB672C230E014491100043DB7392F99B019A671A05708D588FA79002DCE155F4602E46063A0C523C88E2DC50",
- "identity_type": "trusted",
- "iv": "4B26BC7185A6C854190C227BCAC402BD",
- "key_seed": "5916B9D7017269DE9134B2C7612BB1EFD625FB48BFAA111A0A2C093F2277EA26",
- "metadata_key": "9D9A222628AF278F409455DDEF8461A8",
- "section_mic_hmac_key": "A03260EB043E0791406F9CBBAA2E3F35EA9D3E5E0DE545C3BA5BAF070DACF5A6",
- "section_salt": "43DB7392F99B019A671A05708D588FA7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E39DC77B87C9B486CF0A220E9F96005B",
- "aes_key": "710AB1ABB206738BF8B7CD25F447C6FC",
- "data_elements": [
- {
- "contents": "4B",
- "de_type": 934
- },
- {
- "contents": "66F3ECB89A6EEEF79D7B7E56D0322DF39B288742A2C1C501ADA9A41B6DB7",
- "de_type": 110
- },
- {
- "contents": "16C065D0395BF1207051A48B11E8CADF",
- "de_type": 386
- },
- {
- "contents": "98BB36DA75",
- "de_type": 76
- }
- ],
- "encoded_section": "759013A2B7ECF2852EA59A6C5F1CCAAD2756979110002854AECD9C5381CCBF80A06371B88FB690040E78B4D151F14503F20A32EC29FF08EF3B152E32D1A0A6262EFC3A259020C14B6387DC646B3E16ED8F3D3E519266F723184D8B9833BA01AE0320B0F40CBC89431D479F1C6A77A8B91F75CD625434",
- "identity_type": "provisioned",
- "iv": "907158F1F28F23E9346C336D15BAF4F4",
- "key_seed": "7974330F2BF907399B0A00CC0732BBC1A06946E0B1D581E4A4186F99E778F076",
- "metadata_key": "6B05DBBF085163F895C1A797DDAB7BB7",
- "section_mic_hmac_key": "D10DD1068B113669C31BE18259AA3C6E077D61E97CDF58A6C6139E14C9CB4229",
- "section_salt": "2854AECD9C5381CCBF80A06371B88FB6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D2778817F879B9E6369EDFE544E22294",
- "aes_key": "C1691E7FCE0574DF8952878B6381739F",
- "data_elements": [
- {
- "contents": "EDF6EEE118AEE831E7451217",
- "de_type": 925
- },
- {
- "contents": "EC9312D8F49AFF",
- "de_type": 220
- },
- {
- "contents": "CFBC75",
- "de_type": 681
- }
- ],
- "encoded_section": "569013718B15A1291DF01695B0DE521D99FB57911000947D8B59F619BDD6502FDF257004C9819002E4348AED16D25DA49B95C26845BF7DE590721FCF8952532E2002ADD53B5A98AD19B3F10E85425FB761FC9641FD6182",
- "identity_type": "trusted",
- "iv": "4077CA3D2F7BB0F5D8CEE41F01482B98",
- "key_seed": "18A71701D5DEE8400E61168A3B3EF1AD1DDA90BC194C446C8BA40B6480C30CDC",
- "metadata_key": "D1FE231F740FC03B295276053B2BAC3F",
- "section_mic_hmac_key": "82AE800A495516651B39F72786BD066F05890A592D64AE7C1FEB9071FEE6C4D5",
- "section_salt": "947D8B59F619BDD6502FDF257004C981"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "587A03C7955F9860870984298B058015",
- "aes_key": "331E9D1FF1937D5F85F0668282E65C29",
- "data_elements": [],
- "encoded_section": "3790130FB6023392D2A41095E8206D06D7FF0E9110000D85431BAFF333B2573911AFB2EE969B9004E7FD0D3F84B425FCE63798DC6DD93C29",
- "identity_type": "provisioned",
- "iv": "77A5EAB32784959211B1E7EFD4086F70",
- "key_seed": "E46D0C46C240ADB0C96768BDEA14323BAA3AF59DA10695DD2AA96963FB75F633",
- "metadata_key": "0364468086B86E4E69D4998412D9446A",
- "section_mic_hmac_key": "B8A88D796B1F5CD4E1B3FA421F911CEBFBB33203B5F54D397B77AB08C6A4CECE",
- "section_salt": "0D85431BAFF333B2573911AFB2EE969B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7A1632119CD401B77764CD3CBA1B7E48",
- "aes_key": "367BA98DF8FDBDF8D92C9E223204F9E7",
- "data_elements": [
- {
- "contents": "660362F50CAC47EB6D5C372ECB360FED6010E33CFE2BF3",
- "de_type": 744
- },
- {
- "contents": "2E27FF821CD7CE8C7A",
- "de_type": 864
- },
- {
- "contents": "24CA67B8",
- "de_type": 38
- }
- ],
- "encoded_section": "639013B6F61D3EB8ABF5F504C50AC36A94EEA191100040B91207E7595A02CAF00DACEEB362229004899D84903A3B24808A0C8B7F59194E87CE3801D9A364D3232D8C9A1825EF6116E5C80E0ED3BC09DF178FBE1C6D28BAA73E8492380E14FDB44EFCAF61",
- "identity_type": "provisioned",
- "iv": "6A91D4D5C4DFDDFC880B73A3B7240702",
- "key_seed": "EB30836609013EE83889ED5ABF6FC302F243144E118A2965AADDCC8C3987566F",
- "metadata_key": "0BC8A5D803D9916D0BA83CBC5E0D3F30",
- "section_mic_hmac_key": "D89DB6FD35D1A9A236C7B32B2713282376AB727EE4D22775E9A6E7AB64719479",
- "section_salt": "40B91207E7595A02CAF00DACEEB36222"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA9BCBE55A09A0AD1993D33AACDCEF3F",
- "aes_key": "D480AB0495AC86543854653CF7AF5605",
- "data_elements": [
- {
- "contents": "5743AE7D722BF57D",
- "de_type": 59
- },
- {
- "contents": "254368832881E13E4BCD68DD622D7B27BF77F0B248799E3F6BCF903334",
- "de_type": 42
- },
- {
- "contents": "172233F269FC283AFE876265C41CF433148DB69C743C8965E791",
- "de_type": 792
- },
- {
- "contents": "C007E7BC097140AA592C287EAA90479BCE00838A84B7D529",
- "de_type": 531
- },
- {
- "contents": "9678CB4436B9DB612DF2BEA08AD619C84DDF8B58DA67CBA0CC491D",
- "de_type": 177
- }
- ],
- "encoded_section": "B69013EB88670C74254B7E3124F568EAB21AB39110003CD98524158254D763A056D3D7B95EB890028EAD7A637F8D0F6CAF0D74B4A65BFC4C6DF88868FA11D9F5A5B179A5D884CD2C8693AA26F7AD7A949830EDBC504133BE5D5DA8317E74CEFC303FE55553BA1734B63ECDDEE36D3E90127BD85DFF414089E19356CC288B316AD5C88F7237EFA35AF07DC32C636D7DA300C8ED550F4409BD32BCEEC5CCEED448C4C049C19AB21C3E2FBA27F94F7C8402C98F5E60E23783",
- "identity_type": "trusted",
- "iv": "EBD45E06E481E15D113570B3CD3A690C",
- "key_seed": "99F26C755B35B9E8F02471B50155868AD1B5415A36A8A09AEF2CC16B23E93484",
- "metadata_key": "98AE7741589B65DC2BF7D9A9F725F908",
- "section_mic_hmac_key": "66C7980C46970BE68B05B5263A65D5E3401D4E91DCC084AAF19D401694607A57",
- "section_salt": "3CD98524158254D763A056D3D7B95EB8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6F9CFB4554053A39150CCBCFE3D0AF1E",
- "aes_key": "9D3541DE5EF0E257E4B8321145F57B4C",
- "data_elements": [
- {
- "contents": "A43F33AE23920C0423748C754B99D99129E9DB",
- "de_type": 37
- },
- {
- "contents": "729C9F3BFCA94ACFEF114794B2",
- "de_type": 109
- },
- {
- "contents": "AC",
- "de_type": 730
- },
- {
- "contents": "5559BAE1D900",
- "de_type": 729
- },
- {
- "contents": "2EB49A44A2641ABDF0CDDC03EF43B7F3F52C449A892F",
- "de_type": 44
- }
- ],
- "encoded_section": "8090134F6688FA1A2E7BA04ECB6DDCB44035359110006AD7D11C0944CB91DB95B631C734D8949004E082EDC66A42BB6B05378C26D87B38BA4186497644057393408F087328EC5885E174BFFBD7466E158C474C51F5D524FF92A558F10761A4844FF9F9E1BDCC1C6E0AEEAB7E74BF4D04F79D6366857D63E74633C326B74396A4D9",
- "identity_type": "provisioned",
- "iv": "BFA35B0ADEC12C33F4A25CE69E314D44",
- "key_seed": "585B91BAE582CFCA04B2CB0F4EF6228BF9D3ED8757858BC946567C7C056452D1",
- "metadata_key": "ADD1DD5D5AFBD1297CB46459564779B8",
- "section_mic_hmac_key": "3CC8495681BD196A59435B9E92678852F7229B3A17222A46F35AEB19872E8736",
- "section_salt": "6AD7D11C0944CB91DB95B631C734D894"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0D008FD70A96D4922781509DC8233AC3",
- "aes_key": "B6597B106536DB997B33270C1FBBFD01",
- "data_elements": [],
- "encoded_section": "37901319D976A449635BF9366F08B28550A32A911000540F306324634FD806109D2FA0F888719002A37EF91C879233705329EB6E1C7C1F3B",
- "identity_type": "trusted",
- "iv": "1F610FE4CEBFFBF09ECAB7001A9715FB",
- "key_seed": "F000887AE6054C5ED93C14654F9CCB540E4ABD072E4A03C741D446809FB90C61",
- "metadata_key": "F774AD3779D9F9C3CAFD222AA8FC1791",
- "section_mic_hmac_key": "C5CA0D48EB97535C6759CC5851C60CCC59EFD96218C3AF81E97AF2A492C9DB42",
- "section_salt": "540F306324634FD806109D2FA0F88871"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A0697BBCB8D71C0E3CBBF61383BBA0AF",
- "aes_key": "2F302DFBB66FACFA11C38E4437398B74",
- "data_elements": [
- {
- "contents": "247B14830A72CDBE2687D79D9216D81F4E3E545B01D75A5B75E29756E4",
- "de_type": 20
- },
- {
- "contents": "387C2B46942623D8615696845A90B3DE25FF253A159C89A2A3C340",
- "de_type": 793
- },
- {
- "contents": "F45668C015DDA58C872A0171AA605889E691398726",
- "de_type": 252
- },
- {
- "contents": "1474A3653170C9",
- "de_type": 181
- },
- {
- "contents": "E49C82D1F206",
- "de_type": 10
- }
- ],
- "encoded_section": "9D90138CFDF8CCDED054C4D7003AD4CB75765F911000C8C6351ECBBE018D1CAB2041141387E9900264E5A396E06459D7AD5061A8D1E6D6DB9A4DABC2338C9D39F291289A3948F91D3BAB928C47FE7503089FBEB195056064D7893AB1F884E7637AD93079312F00D1DAD71FE98C10370C42C1707C48358951AAFBD6F72889E26C67D846D13273A21E244DC751C76197BB577738B327CC39F017F56D4753BD",
- "identity_type": "trusted",
- "iv": "E73D0D0D01F12F05E954418529D9F056",
- "key_seed": "E7513A0CF82FE239A9CC581240AD1BF40C7546506BAD18C1A754B8A50F190FFA",
- "metadata_key": "094D5377650F8BFD60DDFC55521E1C61",
- "section_mic_hmac_key": "7FAD140CC4B335530A8754A5CCD4A423AA3EC678ED3CA3D817906EE925AA90F0",
- "section_salt": "C8C6351ECBBE018D1CAB2041141387E9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "66AB56CCB8DCF4E02102C595173AE0AE",
- "aes_key": "080E3256F009193CFC48DBECD6A596ED",
- "data_elements": [
- {
- "contents": "5FFE88F1F3AD43AC0BD206FB1261",
- "de_type": 554
- },
- {
- "contents": "C5C5120C2AD8114C0D7223CA0D4B",
- "de_type": 376
- },
- {
- "contents": "AC57EE249B96DD8F426FE4F02031E48B3AB4A248",
- "de_type": 74
- },
- {
- "contents": "1CF30B1E1C519ABDCED6",
- "de_type": 358
- }
- ],
- "encoded_section": "7C90137CF07245A7C2E4D9159C8C517CA1336691100063F671E6C1543317418A20C1BA7C01319002F7A70A1BD5393866D2E1E43D580C3C81FD09C428377BC94E8125F1ABAA938A5CB37C29DC9C9232679D1BDE10E8C586905A2EB8CBD52CDD1A50ABE0633360F0311BE2C3E60F32CA5ADDA8212D0D820A5442CBF1F122",
- "identity_type": "trusted",
- "iv": "6686516893FC3245873F63E6FFCFCBC7",
- "key_seed": "226D0D4CBF82EF7C5636C8D21ADE2455DA18017EF11D9855A1C6623D7F52C49D",
- "metadata_key": "B24F2E75B0207CA3039D2627726F15BC",
- "section_mic_hmac_key": "DFCBCF569269B4C4C73D69E96B0589931C3BE5F7B5CC80B473A68ACB0D036DF3",
- "section_salt": "63F671E6C1543317418A20C1BA7C0131"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A11C310F925DDFD146F831393D6D0FB9",
- "aes_key": "1AE54656FB14E83D942075C749E2115B",
- "data_elements": [
- {
- "contents": "BD45361322D9A02B2048A177A0103CF3",
- "de_type": 926
- },
- {
- "contents": "2A214CB5FBCA350A5BB0CB335B9FEA40CDEB6455C037B6821A599F17",
- "de_type": 708
- },
- {
- "contents": "2680C9A00A375A0A9DCE72BA1CE694B2E29CA12A",
- "de_type": 273
- },
- {
- "contents": "B79A1762E7073C6A46BA17EC05",
- "de_type": 988
- }
- ],
- "encoded_section": "909013FD6CFE2EE955035DE89C9F166B3E5EA4911000D1B1FB53397FE51B93F74900975CD47E9002924278101267E2D8E228B4C34D0A648C8A6B294E3CC9D07B62D1EF749C7BE05103940D261EC73D1F1C12C99A4B4F8ED3F468AA17CAE45B46E532F632012B8EE8E5C99014BAC4E2B5E20FBD1ED9DC6C6CB2D755E1FED2D3D8A5ACABF57ABF0D012C45D94137FB93592D",
- "identity_type": "trusted",
- "iv": "892E1A354B6DE952C5B014C7907EC182",
- "key_seed": "FAAEE89538A2E2D5786C8946E6A0CEF832F309174B38DF73E4F84A99F15935E5",
- "metadata_key": "0DB3D13A2E4FD91A299522F1D8119843",
- "section_mic_hmac_key": "99CB5D0E2B02142282326CBFF5F9DA1E0233F2CFFC8C28BE12CEB87B9CC6FE6C",
- "section_salt": "D1B1FB53397FE51B93F74900975CD47E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8CD7AD20B2C8317FFA8C35639F74A2BE",
- "aes_key": "04A4C39B860940DCBE6D31E645C6C979",
- "data_elements": [],
- "encoded_section": "3790130B2D888B589284B7A0756A14D057BA899110005EB69F216C556E3154B71449355FEEF590012148C3FFABD2C9E7021C7025F13AF42D",
- "identity_type": "private",
- "iv": "82B3040C024A93C9E9FA070F5751EF54",
- "key_seed": "44A25B92833732691F61F166743F7EC9F9BED95D496117FB2C0D5FE8ADF243B9",
- "metadata_key": "58D26BDAFC8C232C9AE6BD1466626518",
- "section_mic_hmac_key": "15F5A03411DE20F46038D7081E95D728EF120D4DD04A6D17A89E2BC7EA240C6E",
- "section_salt": "5EB69F216C556E3154B71449355FEEF5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9ACA1AFA24CCE7E90657920FB0F97ABC",
- "aes_key": "C6114A9A61EBAA0683432F07A306BAAC",
- "data_elements": [
- {
- "contents": "67F0136B918AA30006",
- "de_type": 450
- },
- {
- "contents": "3A54424FDE3D",
- "de_type": 210
- },
- {
- "contents": "BC4E6711DB9D574C249ADB",
- "de_type": 362
- },
- {
- "contents": "DD7AB44C2783A1",
- "de_type": 994
- }
- ],
- "encoded_section": "64901398942DA061F73AD3DAC7FE04713E897F91100075C50E7D6DFA055F5967BDA20F6011D59002528E07C9E1AB8195BED4404ACF13B5C463F7F522DD45BA62C382337A18053527ECB87D1190488DB8FA1CAFD71DAE0F337F1F27E30405F2B3AA562A4000",
- "identity_type": "trusted",
- "iv": "C8D5BEDD1D514F4163FDC162E170E8E5",
- "key_seed": "0E2E25E5F01089D937936CC39D8D004DC28C1F10D75552A9F66E98D510282092",
- "metadata_key": "481B6CCAD1368A7FB57B226F25C5CD38",
- "section_mic_hmac_key": "B9E11ECDC5E537C1669EC49389B73866E18AF8E13A0B6934CDD0B50154662368",
- "section_salt": "75C50E7D6DFA055F5967BDA20F6011D5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D78B4DA01181538E9901A89BCEB17DD",
- "aes_key": "79793A9EED14B1E7431C0B803ACE76D6",
- "data_elements": [
- {
- "contents": "1A14E4524B490E8107DACC2F7FF359791012B7BD73F680",
- "de_type": 889
- },
- {
- "contents": "7F4DD2AE08BEF6906DA8",
- "de_type": 173
- },
- {
- "contents": "F8559AE2EDEEC96166AE99",
- "de_type": 718
- },
- {
- "contents": "EA7FBF2AD229DD26D55B6E4A69B5720BEC80F14221",
- "de_type": 447
- },
- {
- "contents": "6F72657C",
- "de_type": 217
- }
- ],
- "encoded_section": "8B90134FCA585270ECB11CA2D19FCD187E629391100076B4769D60E7810AF314C92E4F4AD22D90010CBA514F61328A8DF741F39426A6414A35993D0ED3645543ADCFC7F60039A16AA7B7544789824A630C6FAE0338828514A802D34E22F2677F5EF92D21B245E2C6BE89E118332EF6820C9298D64708D7E84C0E5A688C13EF9AF0139916E1ADE41C038EA24C",
- "identity_type": "private",
- "iv": "06676937E3AC4BB809DB29D5D0A0D238",
- "key_seed": "13176067BCE094304F0D3D7B34200618EEB8338DC62F8B93B6DF1568D10892EB",
- "metadata_key": "867EDB530C4387B741E3F8D5A90297BE",
- "section_mic_hmac_key": "35533CF432DA85D9C9C797381EE7F410A1ACA2FAFAC320336E538C4CBC21973A",
- "section_salt": "76B4769D60E7810AF314C92E4F4AD22D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "024C6620A23F3720DD27159A314223D9",
- "aes_key": "FAAFC4270BFEF0C1B99EE28F255DF188",
- "data_elements": [
- {
- "contents": "B748E7AFEF028374C9FEDACA76",
- "de_type": 172
- },
- {
- "contents": "85CFCC",
- "de_type": 913
- }
- ],
- "encoded_section": "4D901386135E41C81BF815C35F82210AA987D2911000FDBB2C065FECBF1CC2EE41B51CB6E636900217D0F0543708CCCAE565509D685542ED3F434A7B4CFFDC00B0FDD4A704B31768296C7783A0FC",
- "identity_type": "trusted",
- "iv": "5F7CCCFC3E69E1B0A4A75BCD2DDCC596",
- "key_seed": "6B3B7B151F380162B9E0B70910ECDC784ED5397B3A10BDDE199A7A94BC6D8D75",
- "metadata_key": "E138A6D9CD4C8852E08ED89542C192A8",
- "section_mic_hmac_key": "42942C5BA5773295A61EC1C494BBA596E1F2E382026FED016C73CF9CCD6CC3E8",
- "section_salt": "FDBB2C065FECBF1CC2EE41B51CB6E636"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "26E8D6DCAF6B89C14D2967CD2F996C3E",
- "aes_key": "F93420FD82E0E4006F5BCD4BCAEE619F",
- "data_elements": [
- {
- "contents": "DCC21604B26103BF2FF0DA36696709C57DD113AE10",
- "de_type": 167
- },
- {
- "contents": "CAB2EAF5F472143204",
- "de_type": 996
- },
- {
- "contents": "EF46C11CC5D0B3D06BC6001DF168281A0FB050B2EFE53D191E68D555D7C1",
- "de_type": 635
- },
- {
- "contents": "8DDE68F7309765DFF675",
- "de_type": 575
- }
- ],
- "encoded_section": "899013EA913BF87D8BB4054C1A63591555992D91100097BE3649478AA55F3B0F450D35B50306900432491F1FBEC83775BC41FC1166D59DE10EF12EB01455B22479FC697A8B2B10B7A56C289D21C2AA3E8DB4FFF376ED4B1AC9C8874F0A99E32E2803F7E745244F53B47EE60BB3581AD954B33BE2DE4807AE5D39CCF10C5A38616AB4A17799ECDB7C895D",
- "identity_type": "provisioned",
- "iv": "48710ADDD5BF6C5BA7557EF8363238C5",
- "key_seed": "90C710688CFB0274A65B1A98B01C42367DB55644917B4590AC7D20BE4045E96C",
- "metadata_key": "88E7BD8F22B0BCF3E7017B889AB3BDF4",
- "section_mic_hmac_key": "93370F2F5EE939E87A903BEF02707B3AC8C0D39716C741D8D513552EA0EA451E",
- "section_salt": "97BE3649478AA55F3B0F450D35B50306"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "57D01240BF129C429A6CF751CC3D53F9",
- "aes_key": "AA74FA6AF836204298237570AC35EB9B",
- "data_elements": [],
- "encoded_section": "379013E8FB0C142819D59A85D20CE6346FC4C59110000F0472D2D144D008039AECA7226B8B49900139DFE67E4EE80F46A9B96D3AA6194470",
- "identity_type": "private",
- "iv": "B6E84BB2A3014E5614393F4DEF92C247",
- "key_seed": "CEFEE1454C0BB63E85B73102F7323B441AD6589E484827D94DB7F50B158CC225",
- "metadata_key": "18446FD698B121EFD552FB4D893FE1E7",
- "section_mic_hmac_key": "E88F3731EEB10ACC952F79D2CFE41D9387D5544317EA307E0E929786E80184F9",
- "section_salt": "0F0472D2D144D008039AECA7226B8B49"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BFF12B5AC3846F17A4F2671DD201DB7B",
- "aes_key": "80165990CF33C6AEE8F5D706CA9C16B8",
- "data_elements": [
- {
- "contents": "1D",
- "de_type": 225
- }
- ],
- "encoded_section": "3B901383873E9BB7C281BED884A6BC9D81E2F491100008BC6FA4DAC8237B4FCA4D351D456A8C900173A35B84F1311BDB48EEEDF03B44AB0A30DEDF0F",
- "identity_type": "private",
- "iv": "E79024DAB46DC39BF1C41E950EF68F0A",
- "key_seed": "0191678E34EB80CC23F8BE780AFA6A323757EE2357B81903F0A11F586A343D74",
- "metadata_key": "76BA1F4EE04F37541F620FF3CB0E341D",
- "section_mic_hmac_key": "590C297824EBFCEC438E2227989EC334BD8549944587C0EF0CE8647D0CA733E8",
- "section_salt": "08BC6FA4DAC8237B4FCA4D351D456A8C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8D64601B3CEDFC33A6EB41F2A57273FB",
- "aes_key": "EDC4F0B53EDEC5D458373413BA40EF91",
- "data_elements": [
- {
- "contents": "FB",
- "de_type": 843
- },
- {
- "contents": "78B36066A5E407DD1DBE7E3592273857C096A23CB16EE780DC5E",
- "de_type": 996
- },
- {
- "contents": "66BD25982401D8BA12065C6FE90A2EB5964D62038F03E23FBC1145AF5F29",
- "de_type": 723
- },
- {
- "contents": "7CA1830470E3E82A",
- "de_type": 601
- },
- {
- "contents": "D40D41F3E365762AFC055B",
- "de_type": 437
- }
- ],
- "encoded_section": "929013782EBB1DAC3CB17A3F3640824931823E91100064AFBAFD7BC4C4E2CA5BAFA2431EAFC290016E594B07A92708C2BD85FF96A3D9AFA5094F73F05E2BB84CAA0DF5ABDC504C9DFAF179F3DA8206A8DD374E6EEC568B1EDA5A194AA461C4685800FE4E512788300E64D570FF745A9E108CDA5912EBE36316E1856DF794B73B40A53C5B179094622859204F1F22606CD1A94B",
- "identity_type": "private",
- "iv": "D1317E1FAA030298FF8C5AB6BA81773A",
- "key_seed": "62B5DBB64DFFAC377EA82F2D42A7377853DEA50F09D3DAFC4B412B687A66B8C5",
- "metadata_key": "1427037C5581AF92467699C6A6751E32",
- "section_mic_hmac_key": "213813B05FE7AAF9777E792FF12E2B5A66055002E83ECC0AC7FD46A652AAB8E0",
- "section_salt": "64AFBAFD7BC4C4E2CA5BAFA2431EAFC2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "373BF3D6F965BB823E05E5F7BD3078A1",
- "aes_key": "5CCBD9E3100D52C9CD11F35654668482",
- "data_elements": [
- {
- "contents": "22E0417B",
- "de_type": 599
- }
- ],
- "encoded_section": "3E90139A0E4A93DA7F646DE9A87E125128EE8A911000AD455E1C688FF04A371C03BF7796CD7690019F04EE8F7762B6F109719AEC910F1942B2F58CF6A6686A",
- "identity_type": "private",
- "iv": "B2B8D3700005E09ECD4FE23F302E100C",
- "key_seed": "57A38204ACF2ED7C4C7CBA7C9546BAA0F9FCCCF9BA57335938A4965281FE65B0",
- "metadata_key": "86405D9921CAB755B452C98A0C6CA34A",
- "section_mic_hmac_key": "DDBAE43D3E5B9D620B2FC4E64C02035A75DA47DFD0805E0C2E5BAD62793C712D",
- "section_salt": "AD455E1C688FF04A371C03BF7796CD76"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1A1D7E95B4475678CE4A355E6D120EBB",
- "aes_key": "29D17ED2A3D5BFB193E169120EE20B3F",
- "data_elements": [],
- "encoded_section": "3790135990E82336FE3240D282B7BADCBD28A4911000A9F95C7985EF9A9EE72717C842A698F79002CACF57FE3D1D585998EA9C305C48D2B4",
- "identity_type": "trusted",
- "iv": "F6DBFADE261C4E9A73026B059AEC9D34",
- "key_seed": "7B750CDCFE6B606CA494110409A4EE9860FF6544C8EA98C11F5335546FAFBB15",
- "metadata_key": "7635C7A2DE6BF4015EF7903C840EECD9",
- "section_mic_hmac_key": "0566AC9D4AB6EC0FA38115AEE5A469D65014629D8E68DFAC42419EEB722ADB1A",
- "section_salt": "A9F95C7985EF9A9EE72717C842A698F7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "30FBABC3717AEA2AA0477BD6A3E1E475",
- "aes_key": "DED9CC135A79C82BA7FBFB0C96B046BE",
- "data_elements": [
- {
- "contents": "2A350BE1BA1985F4",
- "de_type": 111
- },
- {
- "contents": "307AD47A1F29D017ACAAE833FAC539D70D1BC0",
- "de_type": 417
- }
- ],
- "encoded_section": "579013871E5F454397F1878BB4CF0647E411F4911000DDED3531E375331992E98F425EB86541900416A66E5A7082A9FBBB4099EE5F0B9A4A92DDB5C2EC4579C5D9948DABEDA010AEE1A7A0472B542C390C7FB6B3C0AA529F",
- "identity_type": "provisioned",
- "iv": "CB385978490958F65666D5C60B05EF91",
- "key_seed": "F429DB5FE75E0AA2E9F2A14A68A3E15458A719C5E4558AE46C00A665BA452154",
- "metadata_key": "D8AA437E16803D5F18FCC89767240901",
- "section_mic_hmac_key": "0BE552F6D9EC8E01B4E870E90566D0B774B5C26DA534D86AAFB5D2920BC8BEEA",
- "section_salt": "DDED3531E375331992E98F425EB86541"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EF01B4E820D20AE81C749A58C3DDFEE1",
- "aes_key": "F0E49A06F5B9AC50E7421833A986FA98",
- "data_elements": [
- {
- "contents": "41E065F83C",
- "de_type": 299
- },
- {
- "contents": "B680D15D9511D833860DE3CB6F2F6743FDF449",
- "de_type": 908
- },
- {
- "contents": "871078FFADADD8D86DEB9029E47B2031AC1A2BD31E1F5467C46B81F4",
- "de_type": 3
- },
- {
- "contents": "E8EB3A2427E5BC1225A8CF35D067D3B9CD241CB40066D6C6695B214E45",
- "de_type": 138
- }
- ],
- "encoded_section": "93901384E18167330C033B062C2369F35593D5911000D42B13BDC2120ED6935DA267E6E0757890043CF778DB9F3A7B9C9B0C798274C1C554F3C741D7F939836D65A1052A504CD928FD797216793071AC4B25B292BD19E3C5C47DC5907D29BB01B90C8E923E297B519EE368E979319E6017C6A69D938F638C61803CE45536CA0DD754E846E6ECCFB1AA7A93547FAC69C50663EA8F",
- "identity_type": "provisioned",
- "iv": "DC1E3FB599A1E7D1608626E6E17C2521",
- "key_seed": "3A8FB9BF059E71E53718B02FE78E571CF44AB722527298D272420F549676859A",
- "metadata_key": "1F44220ECB96C20C54640633D69DCAD1",
- "section_mic_hmac_key": "E91278BE56B332D705A53E313E1DF4E490511699296BD4B60E121E66585D69C3",
- "section_salt": "D42B13BDC2120ED6935DA267E6E07578"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "782D32501734250795AC4AF93A4300A4",
- "aes_key": "D50EF6CEC2A54EF8B77C4EDA8F36BD32",
- "data_elements": [],
- "encoded_section": "379013F040E084112EDBDC93B5FCCB7448296F911000805E7F20E7FA28F518264F5E082CAF04900441FD6FCD160E311319C10A6893D3C924",
- "identity_type": "provisioned",
- "iv": "EAF6D250FC4F0A6672101E0674B06BCB",
- "key_seed": "7620AA14EE8667D1EC09FAAA941346DF595B47B3BE63CB04D4641F6A8D5C760C",
- "metadata_key": "B09416A05A492EC78D6F64669DA3402E",
- "section_mic_hmac_key": "68601BACC6F7B0E429AC7C1EA88FF78605C1230693A2FA9B3CA393A64CD30A53",
- "section_salt": "805E7F20E7FA28F518264F5E082CAF04"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FC449A50721817F66C05B8EF876F9E78",
- "aes_key": "A1318CC4CE689EF7FBD7FE22B21E9ADC",
- "data_elements": [
- {
- "contents": "D8D569D2CD36FEFEFECF0358CE1EB87EA9BB533B36B46EA7",
- "de_type": 372
- },
- {
- "contents": "06AE898607F5596FA8AD05475ECA2E9640BF3305527F30D4",
- "de_type": 863
- }
- ],
- "encoded_section": "6D901349CA53B009B567A031F330D4606450FF911000DC9E659B8BBB254934876CC5D008CBC090049ABF95152E79A7E59C2B1D293B3A354ABEB1ECBEE2CCCC5FF05D49FC9899F2126FEB50C3DD45B7E2693BF171BAAB2987301A1192D902834A4A90D24B18972DF864945E535828",
- "identity_type": "provisioned",
- "iv": "1EBF95D7139416EC9B1818FD5F97EF91",
- "key_seed": "F02A2F8CD34C8A8B257B87ED39B6E9ACB1E27980726732B9E5D6B01FFD7876DD",
- "metadata_key": "0F8F4189804AE28E4A464E7F3980FE8C",
- "section_mic_hmac_key": "6FD39C4C89A6ACAF5AD70F154C3A597DBA3EE96C2F596420AE8776AFF63FD62B",
- "section_salt": "DC9E659B8BBB254934876CC5D008CBC0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A9206D9C925FC35391F2CCB66843BB6",
- "aes_key": "B164F108D4101003D41F5A265069E16C",
- "data_elements": [],
- "encoded_section": "379013E56300B4C0E142D630D8BF19AF1E5B0F911000BB25DB4C1E1998DC75AB7738E7A0C00990018AE9A810448A770F700B86CB37C14F74",
- "identity_type": "private",
- "iv": "1093DDCAD240A78B323FEEDF79291D33",
- "key_seed": "BE17A1F7DE7B872D67ED89E58DEE8899E9786A71ED62E797F590B3DE30905966",
- "metadata_key": "548B24FD91CE28150F24118488E8C650",
- "section_mic_hmac_key": "73F14DB10E850262C42FE6527C0E5A26F62203277C1F4AF40C12356CF1639732",
- "section_salt": "BB25DB4C1E1998DC75AB7738E7A0C009"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "419DC54AAA22D76C4FAA100A8B597761",
- "aes_key": "B0C19ADDA557D389AEA1D65BA47DE9A2",
- "data_elements": [
- {
- "contents": "",
- "de_type": 970
- },
- {
- "contents": "791EDC67",
- "de_type": 186
- },
- {
- "contents": "42EBC555C54FC8AB0241758981E329839EC9B543E9",
- "de_type": 47
- },
- {
- "contents": "42EAE840E0F23077AAC76B4FDABB671F",
- "de_type": 237
- }
- ],
- "encoded_section": "6B90131A017BAB4BEC196E0F84C5E587C025D7911000686C4845F376C37C9C3C443EF4E29E9290024E453EB1A34E995C296614A6993FF632E9F97B2DE3D624825569175BD0A9C96B5B9B87531A9FACAAAC69833461463E3C5FCB1D89B23086CA868D4303B56DCE0339C156B9",
- "identity_type": "trusted",
- "iv": "5321A3B70C166516A62ECAA30FB2AC90",
- "key_seed": "404A64651191A344B06BA775AB47A6D961042C751B62DFAFBD4F05C6B692A75A",
- "metadata_key": "F8C1EC9CDC2C188F4A9F599CF84E07A8",
- "section_mic_hmac_key": "47AE068E71F04816286AAA0F28FF01D4F2271EF59E4A3A37E4B1ADFF9A028BC5",
- "section_salt": "686C4845F376C37C9C3C443EF4E29E92"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F1B3435490631CC0996A289568DDA5E5",
- "aes_key": "B66949CE919A7F877E207F57739276BE",
- "data_elements": [
- {
- "contents": "CC223F25545F",
- "de_type": 109
- },
- {
- "contents": "E80181074A42346CB9CD0787A2D568",
- "de_type": 780
- },
- {
- "contents": "03",
- "de_type": 733
- }
- ],
- "encoded_section": "5590132B1C10D0A90A025571E857B2E49A4054911000837E16BED64DBA81BEE53BE1DBB1DA679001A44E99184E6B16B0499F2E19314E25CF83C93DC0D4B5AF1E140BC3EE578092057599F5C716FA6042D492852F68AF",
- "identity_type": "private",
- "iv": "3FDFFB73C30D8BC45F8126A86D889C43",
- "key_seed": "5D36273BC56672627108B613CB0C12EC04806C65D019A6FE4DB8C8B20DC0963C",
- "metadata_key": "BCFE519169AEFCC4E6986C8D370FBA39",
- "section_mic_hmac_key": "11A4EF7B955F8050A56C65D331E17EEB0299EE364DF3B99109523110D2018E01",
- "section_salt": "837E16BED64DBA81BEE53BE1DBB1DA67"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "712EAEC308AE64A4ED14E1F7DCB13C43",
- "aes_key": "98F6C204DA7BAC2C924E2511E15FBC44",
- "data_elements": [
- {
- "contents": "9D35F9D040F2AC28D7A81524EDB41589771336127BF26D70AF503DC2",
- "de_type": 380
- }
- ],
- "encoded_section": "569013B73F41BD53CBC78A6861EB9435FA5EBC91100023BDF35A690FDB5ECF141A3899D22F42900246967897B21A2DE7A7F9D49A25BCD939FDBAEF13807F0FF86E4F1BF007728E98849A3FE70D206C883DDC097E1EFE8A",
- "identity_type": "trusted",
- "iv": "078ABCE52C402BFFE7A5EB49C4AFB40F",
- "key_seed": "40D30613640F1FA84C9F670F63C9394E0464C6FED6CA7C3F2CE787B11CCB085A",
- "metadata_key": "10DD3208F3A5D1CE9E5FAEA859F84C40",
- "section_mic_hmac_key": "D8EF775C6AAFB173BD2956F817257FA3A5A6F4318439ED4E78BC5B95D9B18290",
- "section_salt": "23BDF35A690FDB5ECF141A3899D22F42"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1F407B57564489497A0CC7E672852C63",
- "aes_key": "AFE6419A004892A3074D6F302B525CCB",
- "data_elements": [
- {
- "contents": "0BC923FB8124E54605284885D20FEA3B0531ED991206A7E1E66A0D3A",
- "de_type": 366
- }
- ],
- "encoded_section": "56901342667136A1FA39944C42FA485384005A9110008916195D190EFCC6885AA87B1C7346CE9001A0FDD44366F8DEDC29560EA4943979E58082609D7F54CD6D6FDD694E5D75F1C8ED256ADD1D96425321273A8C6B484D",
- "identity_type": "private",
- "iv": "833FAB9A4D9EFA4B9D4A8A68DBC2905E",
- "key_seed": "E9F13B36B01E9571788A504A9AFA132B9E57EDE7F29BDC43EE5E8AFB81CE8928",
- "metadata_key": "88BC13E7EAE2D056BEB2093A95BD5064",
- "section_mic_hmac_key": "2E07197705F025A3E7D117E721682E8D2C3931076CD3E0FB3CA04C4D63BBDB29",
- "section_salt": "8916195D190EFCC6885AA87B1C7346CE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D22AC6AF30509C332CFA4656125E4FDE",
- "aes_key": "278ADF6744B1BEA0A5E31953A0A25A08",
- "data_elements": [
- {
- "contents": "DF4143D4A169A64ECC8904D569296CDA879F48",
- "de_type": 801
- },
- {
- "contents": "DD214F021EDE84B893813CA1B0F66B98AEBB5FF094",
- "de_type": 820
- },
- {
- "contents": "066A6F1A28BF90A3000A56399A0145BC",
- "de_type": 867
- }
- ],
- "encoded_section": "789013F978EE7FC9B30B192FD29EDE12023D9E91100053AD38BC511698060EC41429F1B120C590014E843B18ACC329051B5DC84693336EE6692A3865FF84858AF8E0D10C37F25DF9765DAF75F880A98656987FF6D40A4F1B4A908C1BDA79667F29FC2922AB4B512749BC50DA3E20E2E6736C501006BDDE1026",
- "identity_type": "private",
- "iv": "EA05DCAF6A26E50E57F282173E8D6C5C",
- "key_seed": "B58DCFEC3705289C33368810E98B7E70368EDE274184B1E2CC42DFD597F4E874",
- "metadata_key": "F412B16221AE5038F4C5112C7D1EFC57",
- "section_mic_hmac_key": "552EC08151491F3DFF44DB0B5D13F691E064B4E8F09AE41CB98FFC17A607D4AC",
- "section_salt": "53AD38BC511698060EC41429F1B120C5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "36D0C4D6C12715D7287FE97F02251BE2",
- "aes_key": "FAD2E4C7807F81D34D2491ADBA670024",
- "data_elements": [
- {
- "contents": "434F8FFE447B6BD8FA9CAA8653928D6BE5E8D3",
- "de_type": 853
- },
- {
- "contents": "57B611D2196D0DAE89249493C060AB27EA4377DF",
- "de_type": 652
- },
- {
- "contents": "433B21A811",
- "de_type": 648
- },
- {
- "contents": "ECB728637AC60A94BDC4EDCBAADF7782CDD4031A18B3F3",
- "de_type": 172
- }
- ],
- "encoded_section": "869013E40676A01D66A6DEB421518859371BFE91100055020FF3DB29354D80E8E03397C0E74D9001FCEB97DFB9567B4C57BA8061A646B54559230AF6CCE3CCE6871C4C767C42C70208035162D535FC3B9565AC7FCA3A9D8019AF94D65C38CC7564AF0AD3339822C939570E57181E5CDD40AEB04E64130E4C44A7A4B3C0EDAB655451F585C19750",
- "identity_type": "private",
- "iv": "4C44E4C5CB13EFA82A8785FB1C4064E0",
- "key_seed": "7DB299F572F69A530306BFFD37D3AA1D5702DDE5E8D295A1EE1A89964B2664BE",
- "metadata_key": "0BA1602DB4E23F70EEAC5ADD65D9EBDE",
- "section_mic_hmac_key": "3B6687807F35C44E71AC08178485BBE20ECACA722061443ED733077FE09812A1",
- "section_salt": "55020FF3DB29354D80E8E03397C0E74D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6A0271AA5747B448F81BA095AE218E9F",
- "aes_key": "FE81F30B457DB3B5A2B12C9E62126168",
- "data_elements": [],
- "encoded_section": "3790132CA2D928B14971ABFD0410DCBFEC710D9110006ED067EB08676C51C40F3C1848F89858900418EF11F7818FB2284E8261AAB63CA532",
- "identity_type": "provisioned",
- "iv": "463F849F17AE15B5D63FC3AD59728ACF",
- "key_seed": "BBFC469077C9725D263D54D042C203F6356D60F55F050050CF10928BFA8EF48D",
- "metadata_key": "632558DBBDBDE655DB4FDB6CB0280AB1",
- "section_mic_hmac_key": "DE884F0B125AD4F4AEBFBB562EC79A8556AAC9C1654E75E79E59C874DB4C554A",
- "section_salt": "6ED067EB08676C51C40F3C1848F89858"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D0CBA45C99E9FA404A4B0CCE1750C1BA",
- "aes_key": "D5F6E5822FD550CD3592877794A9FA54",
- "data_elements": [],
- "encoded_section": "3790135A82DE2CAC2C840A7A525B98295A2B0E911000C8A8DC0A221A9E73736816B12FADEE9990012AD90295A4695F2AA1CDCE65858F6319",
- "identity_type": "private",
- "iv": "CE0AE01F467A25649172788288036955",
- "key_seed": "1EF3F6BFA77940DECF68C92C4916DB9DDCF12D2FC671F80F133A0E64CE643CC4",
- "metadata_key": "1DD57E55893D8C7C66F30AB5BE78E5E0",
- "section_mic_hmac_key": "6C18E5729C77197AA709F37CC196DDEBE97CBF5109E6AD8B686F6A193E7B839A",
- "section_salt": "C8A8DC0A221A9E73736816B12FADEE99"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F33D12D40B9C8B9AE1C47C8AADCC0CAA",
- "aes_key": "1E64FCFA53A6CEE7E20F1C616A672CA7",
- "data_elements": [
- {
- "contents": "081EC010879E34E2E36E07DF44D5",
- "de_type": 686
- },
- {
- "contents": "ABB15E5E47C51C9C5247E1256387260BB0E688",
- "de_type": 184
- },
- {
- "contents": "71DF0AF4F9666A099E6DF57EDBEB",
- "de_type": 797
- },
- {
- "contents": "",
- "de_type": 866
- },
- {
- "contents": "A1D4",
- "de_type": 57
- }
- ],
- "encoded_section": "76901346AEBDCA4CD4F32C73CFA95B0152AAEA91100019C67F054994EBF76B86A9910B24442590020889DA34F813D8ED74273096EC54618EBC62DDBBB2001CF6F1EA30C6FCC4082B55FC170EA5144776585B7D30E0C4CF9C54318C7115E41490ACE3849B79499C829F5EE6F63D5CD6F725FD7DFB2F0AC8",
- "identity_type": "trusted",
- "iv": "D3CEEDC1A3009457FF17D6F2C2C6CC45",
- "key_seed": "FE080591FBA4B25B2326713AA17FFD1B64C32B4B7D1746571C01D6F23931EE37",
- "metadata_key": "6FBB76CBC7FF309E679EB284FC5001F3",
- "section_mic_hmac_key": "A72DB4B90E985E04BAF697CC358CC84BC077BF0E863DFDE644E829A40F72C0D3",
- "section_salt": "19C67F054994EBF76B86A9910B244425"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D67DAFD17744D0F8241D3DD1F3A1B14A",
- "aes_key": "8A065DADD8CB1CC9967868C01070DE8D",
- "data_elements": [
- {
- "contents": "3310FE973462496D27BD963268D98A27A6F848",
- "de_type": 506
- },
- {
- "contents": "FBEB9691FC08C103F9E7E74092DF32C3DA848F",
- "de_type": 947
- },
- {
- "contents": "",
- "de_type": 942
- }
- ],
- "encoded_section": "669013A84927C93EF891F3684515177D57F56E91100075EE531A506096BA0F5C07F1123C5CA990025FF39825FC892166579828672F8D9953F02014743C0B7CA7ED00C694A5BC3BF1C3BBBC16C1FEB9489022CB014A97A6E7077B52BD521E811D78A3C3733517D9",
- "identity_type": "trusted",
- "iv": "75518BA2DDD3E7B3DB43F868ADFE2A20",
- "key_seed": "26B3A85EECA4EC7AC1B7855ACBD28EBA1B0E9F96E9198A15078172407708C268",
- "metadata_key": "3E9E3098DF63D01ED466C1870EC6B4F3",
- "section_mic_hmac_key": "646D3C3381952F4E489A408AFFD2586981B31E9470339C0A196F02D7724A5349",
- "section_salt": "75EE531A506096BA0F5C07F1123C5CA9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EC458F9E453AE59CE56316C9A18F2698",
- "aes_key": "E4C77487A10D78704F4FA0678EACDC3D",
- "data_elements": [
- {
- "contents": "4DE4C93DCD045609E8C0D59A5D232BEA345A8805",
- "de_type": 106
- }
- ],
- "encoded_section": "4D90135B2E85AEDCA13DBF678DBD9A491899F89110006EE872C19FAC3E06FF7B1087D7DA70CD9001524A8CCEB50207DD133EE928A16AFDA97AB9D56B798C15BEC3A8878F9CB23FC0A9F1DA69E868",
- "identity_type": "private",
- "iv": "39EB9D090BBD36CF20FEE1A7B383170C",
- "key_seed": "E571F9737891BF4B91A55DECAF950FC0C3C14AFCBCB578BA64369691004CD99B",
- "metadata_key": "78DABB32CF166CBF9340B1B6F566A91B",
- "section_mic_hmac_key": "26C2433BF4859BDBFDE86F9B14CE9A166C8003185F3C606D58C6F865670F3B63",
- "section_salt": "6EE872C19FAC3E06FF7B1087D7DA70CD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "91E89D93CAD7F35D9AB9C6BF4325A2E8",
- "aes_key": "70EFA33873D2E345D1F56CCA9665054A",
- "data_elements": [
- {
- "contents": "",
- "de_type": 649
- },
- {
- "contents": "9EE549A8C30E5CB17E60804FF9F7885BA0DE9AD888AD102A4F40E3675A57",
- "de_type": 267
- },
- {
- "contents": "E3F347E2C9170891B6437DA81E",
- "de_type": 594
- },
- {
- "contents": "CB572B98DDD51E9122EDF481FF59D3A692BF43",
- "de_type": 642
- },
- {
- "contents": "A3CCC2D85DE09207CE8CFA88FBC2A27F5032A9661B89340EB2B45F54",
- "de_type": 712
- }
- ],
- "encoded_section": "A09013053B0E55A309DB4CBBFB63F693F097C1911000C252DDB368B81DF337A9E6C22C1AB1E29002E8784CA2E7E1C22823BD8C71E457C78618A334565C5A4931F291603EF5F5DA43C2E791D65FE4029AD8BC8AF31CCB9FC66300C80CB4A7A026C7F5FCDA97D406D8891C8E36B5DE49F57F4843C0EC57CC01A303C6989D0779114255B7357EC89BDE5935AE4ABF2245A13E0540FFDA726C4BBF33BA356F3FB52B5F",
- "identity_type": "trusted",
- "iv": "4AAD555F0E8B2B0BD7F8B5B3288EFBB8",
- "key_seed": "235725D5AF71A8B364F576DDF5FDE5794F379B1157FFCEF16E0962ED9E7C69F0",
- "metadata_key": "221424FDAF49E89693F960537A19185F",
- "section_mic_hmac_key": "BF1850DF168537FD74F15A0D907D2205509C03DF1E0B2D3C9C659DA296FBBA12",
- "section_salt": "C252DDB368B81DF337A9E6C22C1AB1E2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5F21199702D08F17E8C31D8CACC752B7",
- "aes_key": "78055B5877F2DC9100DCC8C026FEAE01",
- "data_elements": [
- {
- "contents": "0C9E929580674F44BCA192B4988E1186E73C0553339E077DDC537C2F7CFF",
- "de_type": 49
- }
- ],
- "encoded_section": "579013B616F28CC69FE4BD9566BC9C28E7997A91100005F57B353ACC660C1C893CE24C2AB4139002C3B30303F662EF836D765C8CF334F356DD1A214E25294934896D0E54AF12F9740FE06684DBE3E9BB01CF1DADCAE0DD25",
- "identity_type": "trusted",
- "iv": "5CCF9429D65B8856E1D1DC0F0600DAAD",
- "key_seed": "49EDD7CBD630CF1EB36750CF0B84887F9B9036350EBCF09EBD36E1B1D6C412A0",
- "metadata_key": "34875210235E1D2D25478D12066C155C",
- "section_mic_hmac_key": "45FC0D8B7794850569590818996D2E7F2EDA7E38A2090D37B5D6A5E7A4C24B4F",
- "section_salt": "05F57B353ACC660C1C893CE24C2AB413"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ADDC564B44D0313C8BE7BB31D9591C73",
- "aes_key": "E89A463D3116A6596F4E0E20AAE69439",
- "data_elements": [
- {
- "contents": "24C93D94C0",
- "de_type": 130
- },
- {
- "contents": "EB7F3A5D86354B56D639609F502BAC8A292026254288A116C2",
- "de_type": 608
- }
- ],
- "encoded_section": "5B90137D5718E198489D40D7EF03459A4336B0911000BD284D68208CDB356CFDE5EBE234902D900279864896227AE76218FAD91C906B62334298BA923DE515265337355814BB2FB2AB4A9969C34EBFF5F396EB39ED8A605FD7241A5D",
- "identity_type": "trusted",
- "iv": "36208616A6E3B31472F125A2DC4F51E5",
- "key_seed": "B7C8C5EC411AA108CE8EE9B6BBDEAF9CCADA1252DD7C7929E20D12F8E09541D4",
- "metadata_key": "CC1BAD820BD0B97A8B5A5FAA4419DBF0",
- "section_mic_hmac_key": "2DCD3B2806A4F52453EDE021A1C167C5BBC3FFA9E8BD14C7D1FEEA9EDDACBA1D",
- "section_salt": "BD284D68208CDB356CFDE5EBE234902D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5E8E972BE173F38D85F411A2ED26003E",
- "aes_key": "9FD558DA6B7A1A5184EB545BF703858F",
- "data_elements": [
- {
- "contents": "194E56962B21A139D89B79A1509FF3E0DCE71684B72DF74416848286A710",
- "de_type": 278
- },
- {
- "contents": "C1276C6B7402",
- "de_type": 575
- },
- {
- "contents": "A64FC3",
- "de_type": 589
- },
- {
- "contents": "5CF1B952B38E5CAA8E",
- "de_type": 883
- },
- {
- "contents": "DBA4F3AB1BF2A6F5D325FB9130D5391AFAED7B0792F2DF430F50",
- "de_type": 122
- }
- ],
- "encoded_section": "8F90138745AC668A56139F98DE7B63F8E75D55911000A91454CAB75AB191C1EFCD50DA1C31A490018019E926591F29A634CB84E2B5852C661047B96EB0522EF34BCEA20C8148CBE779FB9FB95AF044F20A6532804C303DEAE0D287D40D2D0050ACE7923A2116360B7F1FA82E888316057B56112C26C1D49865EA7357A73308415CF1CF17D7874D442103DCF4969FE59F",
- "identity_type": "private",
- "iv": "CC6E95261D63DBDA7B9A379984AC5860",
- "key_seed": "D767BD6AAA4F821C12CFDAD0839649B26DE111C270B746948DD3816B42361F6E",
- "metadata_key": "99B29D708B6AC3929AD7860847ADF25B",
- "section_mic_hmac_key": "7F566273E7867C6044B63B51B1FDD564EB972A1DA7ED441739396A15C85870CB",
- "section_salt": "A91454CAB75AB191C1EFCD50DA1C31A4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "890508C1E419677CE3D82C8C634D9A8D",
- "aes_key": "B58487F205E25C8FFC6BF799D7123167",
- "data_elements": [
- {
- "contents": "9DBDF9ECBCE565A86F0316355BBAE4",
- "de_type": 729
- },
- {
- "contents": "894E7DCE8E717CCB6BE7A2B727AE1F038FD81F2D",
- "de_type": 556
- }
- ],
- "encoded_section": "609013BCDC003EF848E2552698FEEF4B5BE538911000FEC9A473F042542F1594E8374E690CD790019456A748B13AE47C66888BFDD3BF5D69259E33B8223572975CFDBEC12D566C8516182DEDDE70B61A0C83091AA7D675C516AC6426395265023B",
- "identity_type": "private",
- "iv": "3266A4DD70BF6DE22B52D786A665139A",
- "key_seed": "1F19488144728397A56FEDF8EF3C71F1C784BF98A8FC5DD3EFC14B733322AB5F",
- "metadata_key": "B15E02D56B9062FD82C73E2F1DF3DDDD",
- "section_mic_hmac_key": "A3096941E32118FFBA5B57A5A151D49CC0C0E4CBB74658669C6E1C9024FDEDE4",
- "section_salt": "FEC9A473F042542F1594E8374E690CD7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8298F26DF0ACD9B9784CF50C1FA31CD5",
- "aes_key": "32599218CF7379D323531C4BBAFC94A0",
- "data_elements": [
- {
- "contents": "BCF691D7FF954D04836873F6822A",
- "de_type": 458
- },
- {
- "contents": "4F0E8EBC44028D314F3BA98B806DDF652722",
- "de_type": 177
- },
- {
- "contents": "9B4173AC",
- "de_type": 242
- },
- {
- "contents": "7F5213584393",
- "de_type": 204
- },
- {
- "contents": "5C77CCF36304E367291A1B2A3F7F58",
- "de_type": 585
- }
- ],
- "encoded_section": "7F9013102BD6F16710F91D224A7DAE68FC3A2A91100071658BD652281D3C02E63780F9FB687A9001C61A8B00D08E33EDEA32453B605CE6AC3259641D1E0DF3726A164491FBAEE8BC4EB237178E1F55C6C811F14BBB32764330185DAFAF2B3495FBF8AE3368F46DD21D46F0C670448F9D517731F0F7F2118762CADB6E306F2C8C",
- "identity_type": "private",
- "iv": "75FB79B913CCB164010CEB9C2F003B79",
- "key_seed": "FC02A056FAE91FA6DE95CEEBA9EADB65777603F77F123004515D21B281FD1AC3",
- "metadata_key": "9B055D228F084D0BEB418876908EC39F",
- "section_mic_hmac_key": "58E406BFD5609A7642B7B19AE11FA144D53BB56B583C55694665F8265C09E9B2",
- "section_salt": "71658BD652281D3C02E63780F9FB687A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8DE8CF158AF393D2993F59D151D92FE7",
- "aes_key": "C3ED1758DD53889D70F1D523EA467752",
- "data_elements": [],
- "encoded_section": "379013F55E075DEADB5808B48E3D7520302EF991100084AF13307448C2326837E2A2760876A290017A8BE69D8EF995E77620EBED461B2AE2",
- "identity_type": "private",
- "iv": "58A62B7FDF9BC814F3209DB583F52017",
- "key_seed": "60F7A17633D7D73127CECC969609F9AE6638C0E00B95C4464B686A5FCEDD3E2E",
- "metadata_key": "A4A17957FC404BF5D50A42BDC3D4857D",
- "section_mic_hmac_key": "B1D557333696A1E1AD29866C78BC4086C8C6ED43711A3FF4862709A08F62E214",
- "section_salt": "84AF13307448C2326837E2A2760876A2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D767403957E9D3E90C2C17EE950E7122",
- "aes_key": "041C51D75D894A63E83E7D6862723202",
- "data_elements": [
- {
- "contents": "423FE65EEEC743FB7781376641FD9CB31D5E37480D5313BDA90A7A",
- "de_type": 623
- },
- {
- "contents": "8B5DC36EE664C72FC16840A0CEB5BCAAEBAEF09694",
- "de_type": 250
- },
- {
- "contents": "CBD97F852E7BA0",
- "de_type": 633
- },
- {
- "contents": "B2E5FDFFCA6859D1",
- "de_type": 230
- }
- ],
- "encoded_section": "829013CA3F3F33B038546D0583551F01CED15A91100014C5C9F74FFA4509A87523AB284DE2AD9001E09EA5B8DB9CAE3E53DC93FE2CE7669CDE9FD349982E2744F9700745E409F926C1568C527923BE14BB9356179E1F36E072A08EB2BB6559D460BEB251F5C8179DB02B903655D54043000FD1A9A272EE8849391915C9B5E27CCFF6FC",
- "identity_type": "private",
- "iv": "404AB007A1717B22258CCDADA622C4A6",
- "key_seed": "6E0ADE4BB6B948EA0412A3BFE1B3D8F97CC95BF9F8531E91632E6393378F12BA",
- "metadata_key": "D211AF1D1753DC34098F73AE56F188D7",
- "section_mic_hmac_key": "0CE5B2335330EE0DF2491432539E311627A00E59FA3A6B8858BE6124AEEA67C3",
- "section_salt": "14C5C9F74FFA4509A87523AB284DE2AD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EAA4670B96668CC6F80D1C5879AE3AE7",
- "aes_key": "B001298B920AD8FFA727BBD08983DB33",
- "data_elements": [
- {
- "contents": "2C5BD7EE8B257AF6D9F3BAA45266B450",
- "de_type": 676
- },
- {
- "contents": "6A87A498F333D0EA885BE02FCAAB20A7848264ADF1C536E1",
- "de_type": 24
- },
- {
- "contents": "5C7816C6CB0D3513FAA77CAC05568E8BFEC1D5338799A27FC5",
- "de_type": 275
- },
- {
- "contents": "93356AF6AE0C944E5276",
- "de_type": 93
- },
- {
- "contents": "D6EFB581D317A392",
- "de_type": 946
- }
- ],
- "encoded_section": "9790131ECC1BB30CD53E32B1D49E2C3F686D3D91100013EC472339FE487D5C13C57B3DFED24A9004F8431796FC123097DCDF156B695ED780A62033B4FEF0EB38807631D6C1409B6176694B32A5439E8433393B9354782C64DEEDD9B243521963FDBDF13B9CAB502654981751782EAA352313FC17503998C0F31C20833424AE008FBC003BFF7EFAA0CEFBD144744BE7B55963F9EDAA6F06CB",
- "identity_type": "provisioned",
- "iv": "CC88BD5D473FFBD1B9E8C25D278E8DB0",
- "key_seed": "A0AF2537313F70D3C9ACF9C3670093A73F6DD52E775814785A459C99D925D1F1",
- "metadata_key": "5A91F28B272C105013A774EFE06F2D21",
- "section_mic_hmac_key": "1D5897008DEDDF91DC33C812DB0D7FF20D32F21A22011CA4AE01E27DD46A71B9",
- "section_salt": "13EC472339FE487D5C13C57B3DFED24A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "94BC22D840D0F083167EDCFC6AEF8C49",
- "aes_key": "1A26CB30822972EE2ABE2791A009C412",
- "data_elements": [
- {
- "contents": "B72CE5E1E1C2",
- "de_type": 692
- },
- {
- "contents": "47",
- "de_type": 287
- },
- {
- "contents": "1DDEC34D828DDB5CC0F84CD20B5DB7B19EF25F95DB123AD9",
- "de_type": 86
- },
- {
- "contents": "CACCBF6A6B8EAB0047",
- "de_type": 314
- }
- ],
- "encoded_section": "6A9013F5710533AE4FCCEF7B5ADE33EFE5239991100005533C388684983561E9177E61EF12A790043935815AA283938A76A1C359BCB9F4A227EE4D5C756C2FE0E784A728D7A1E04D67778E7AD79C64701C3F5BDC0E9A630BEAA2BDEBC0A6C70B81F289EB1A8EEF6AC534CB",
- "identity_type": "provisioned",
- "iv": "AE327DDA6E6F62742E607A4D558165F5",
- "key_seed": "4F26D99EC0F6EAAD77C9A99A96BAE0433F7CF061701FA46D9694E85F8A53E3C2",
- "metadata_key": "8F5507A58C555112EF53DC37B8B35299",
- "section_mic_hmac_key": "E5B47398C87A33856D04E6D5DE9FD03830179BBD0B441A0308B6D2D5B0D4C693",
- "section_salt": "05533C388684983561E9177E61EF12A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D3E0E38F22BB30B42170FE476EAAF4A7",
- "aes_key": "4E1CFC0FDB6BBB26913B5A0EC39B018C",
- "data_elements": [
- {
- "contents": "4E9E5BB8C4F9751BAD57AC939AC519FC688076F39FE424",
- "de_type": 861
- },
- {
- "contents": "9DE1BC6BC8",
- "de_type": 315
- },
- {
- "contents": "",
- "de_type": 995
- },
- {
- "contents": "FE3A1A1793B12DC2E2CBEA6DC461",
- "de_type": 722
- }
- ],
- "encoded_section": "6D901328E5F50CDF08199DCDA8953EC535073B911000B629F236825E4F1DAA2A828FAD8B10139001DB295D2AD40736D82A98069FEA37D688BD2D602F52E02554AEBEACBE7BD00AA0E553253B44F645A0BF6F6602583A2ECC26390107D5E1E3832A31784B5E0FB83F74FFFA23F0B2",
- "identity_type": "private",
- "iv": "512C19498A4E6BBA5958FF68EF833524",
- "key_seed": "AAF59E43323B8E5BC14542E4E4B1D6FED664FFA9C4565FC137C53D9F234F687C",
- "metadata_key": "E96E09BE304022E2062E3309FBEE197B",
- "section_mic_hmac_key": "D4A3BEB6ACBC8497213299435EB3BD8504DB6C82979374D7F918C1D41AECC7E8",
- "section_salt": "B629F236825E4F1DAA2A828FAD8B1013"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "36B6EBFC8957EE9D957D592B1C0293C6",
- "aes_key": "EF8A7FB2585A093B212749546DDE83E7",
- "data_elements": [],
- "encoded_section": "379013FEE47BCD621E2BA1966989BC933A8789911000DD18243E63B52FC8BD6E6237FAC5C0939001FC37D819D217F558FC19D2DDC5A7AC12",
- "identity_type": "private",
- "iv": "209F0DA89053E84ED00F71B53155B760",
- "key_seed": "D82BA7F2F0A36BC58334EC711E2AEDA662999D22F7D7D9B07564C73CDC51E282",
- "metadata_key": "226F121645E6F4EC151AA15B31382A13",
- "section_mic_hmac_key": "D2906FD8EC224CDA8FE20EB4F77A1FCBC0494238E7BE0FDE3575184CCF2CD5F7",
- "section_salt": "DD18243E63B52FC8BD6E6237FAC5C093"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "99A6BB55ABC4CC161FAD1CB8DE6AC727",
- "aes_key": "4DDEDCC1BDABD7190C999F9F5F239FC6",
- "data_elements": [],
- "encoded_section": "37901348313C15FC6D0809D5C003E835396037911000C62DFB45DF8452EF58E761232FF95ACA9004924D826FEED7FDE6BCC4585637AE50BC",
- "identity_type": "provisioned",
- "iv": "CA78EFA5E951531B543EC499C60D48B7",
- "key_seed": "CC3937AB3F6ADBCCD479ECC12AB4C648EDAF2D715FC61272D90285E2051270AF",
- "metadata_key": "249790EE67EA75470D5CA38274206943",
- "section_mic_hmac_key": "1720B0888207C03723165DA9C7F2BE23F19DCCF3666947E208F6F1E4D61BF28F",
- "section_salt": "C62DFB45DF8452EF58E761232FF95ACA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF9AFE50ADA0A3975C49A50CA4592CD0",
- "aes_key": "8309EFC8132EEB8924884C37F023FAFD",
- "data_elements": [
- {
- "contents": "",
- "de_type": 930
- }
- ],
- "encoded_section": "3A9013E3B37AB96E385112C61C57C59E5AA4789110008C658E80B19AA3F9A91CF5CAB5EDE9FB900194F75F6B920DFAEDC253BEE8CD72586B3A55A7",
- "identity_type": "private",
- "iv": "1F9A54370AF4AA8257003C4083115700",
- "key_seed": "B180DADD23E531D4693AF1361DEE2B82CB4EAD3CCB7B440822C791DE23808B24",
- "metadata_key": "5B70CB9828BF7082D582E80BF68A95D0",
- "section_mic_hmac_key": "C7151B084FF92A1D77EB527978F3341F4E26C888AFA801DBD5AD66FEAA09A886",
- "section_salt": "8C658E80B19AA3F9A91CF5CAB5EDE9FB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0AE4ACDBB6B969EA9C655FBDFAB3BD24",
- "aes_key": "9C721D6592B96CC3EC1A069C8257D53C",
- "data_elements": [
- {
- "contents": "D6E933C73088AF72DC86CDD2B472AF67C0EF9BF2485481930DD803C8F0",
- "de_type": 646
- },
- {
- "contents": "C85DDB36AF2574",
- "de_type": 692
- }
- ],
- "encoded_section": "61901310131C4E228092D296F758A3526A9A5391100034B70164C7A05EB4D4166BC4F4CC16BD9001D717BE347A4DB6CB0DBEF2D099D6883842035FD21A6B9D7C92A7D3848E7C64388913DF0AD468382D17EB97C0264F457DE26298EE9729E2551EEE",
- "identity_type": "private",
- "iv": "1830392917044736F4ED55A186631167",
- "key_seed": "BD733DC39589B1AAEDD1C0AF32E3F1D0C67C85A426C76DC1C436F5FBCB4CB8F8",
- "metadata_key": "A65E981CDB9BFACB2FAC9048FB5F86AA",
- "section_mic_hmac_key": "9A95A15A85545A8F5BF3BF598C68C6B1DD8B717A1C860B306D2C56260D3D144F",
- "section_salt": "34B70164C7A05EB4D4166BC4F4CC16BD"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CF43BA7DB832370445F2B85CC9DC0820",
- "aes_key": "1510B1459D6070F66F102C553E6BB690",
- "data_elements": [
- {
- "contents": "44D8251E75FF1AC54A2EFB7738044961C77736CF6D",
- "de_type": 460
- }
- ],
- "encoded_section": "4F9013827424047389DEE800447D83ADA0BA13911000DC2F440F30E53E4B029CCFF297104D479004BFB36E2F23E45F49E6C7101D5C1A95B530019C645BE8ED2455D28D7DE4F01D2349EB0AD6EFD768EE",
- "identity_type": "provisioned",
- "iv": "FBF5782EFC3F038150A57A003453B289",
- "key_seed": "0597F824745D4FCA4922A4A641E27C7F0DF3E3754F18229CDC11ABB6731C1E0C",
- "metadata_key": "3D982630FB96976DEF7CC0D1DAFD1B80",
- "section_mic_hmac_key": "09AFB1227469C31F3FD01CFEE970327FD85AE9557364DC7BDBABDD3E0AD596B7",
- "section_salt": "DC2F440F30E53E4B029CCFF297104D47"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4BF365A1E62CB517ADF3C96EC86A695C",
- "aes_key": "06773F17BF41CFC952BC520FA06E907A",
- "data_elements": [
- {
- "contents": "F1897D930A5877FA1CD661DCDF2C9225B1ABCB3EB937D674B3E1C444",
- "de_type": 404
- }
- ],
- "encoded_section": "5690136721E5046A5398712F086DCFCCFEBB4E9110009C3172327BA6B8B09FC3AD2A285A4FF09004DD9D9AEE9370F474D9EBEA89CC7BC5EDE99547F14269862FFE642BFA9C51216EB10EC71B5D462DBF155E7F9282ABEB",
- "identity_type": "provisioned",
- "iv": "2039CD9D8979F45554A8165952138CD0",
- "key_seed": "74C768D045E9145CA61115534306A970AD184F166A1DFCAE8FA44019E9274F94",
- "metadata_key": "94E9F6F9C99423A6352CCC6D1689BC8A",
- "section_mic_hmac_key": "CB0A779AD5C3F5514E1A2D4094600DD5AA50C3756958F80BAD2229A87F170D38",
- "section_salt": "9C3172327BA6B8B09FC3AD2A285A4FF0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1CDBA11F9479A51F6C7F5A892FDBF196",
- "aes_key": "EE83B59FF4FE53B13B348E8BB40B5B54",
- "data_elements": [
- {
- "contents": "9E6AF7AFA04A",
- "de_type": 60
- },
- {
- "contents": "4CA08F4DD378B99F005502048E577335307332",
- "de_type": 69
- }
- ],
- "encoded_section": "54901361D8AD4F0C8E4E18A1D898278B2BC137911000AC75C0FEA579E3F958E4395F9CBEE3B39004C88B0EA35E1F251FA0CA9AA6E42EFA999D69E852E0CAB982BB1A974486BD912507617D5F7F70195010ACCBF83C",
- "identity_type": "provisioned",
- "iv": "6E4B7653CBB755ECC8927EFE06CABB64",
- "key_seed": "D029E2ED3571789462F357D5C3755AFD6D3B91FBA2D2BE1B9AD671E370F9056D",
- "metadata_key": "2E36E40B8B0155FF11B92A8077932CA2",
- "section_mic_hmac_key": "90D1EE3CC14FCD4F7B5734A40CA42AD27EEE5892C2CF5B26729C34D3C2B143C4",
- "section_salt": "AC75C0FEA579E3F958E4395F9CBEE3B3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3690113DBB16570F0CBF9C3A2716C6CF",
- "aes_key": "FEFF29107072AAA0681873034994F017",
- "data_elements": [
- {
- "contents": "2C4DA1F7E021E1354FAC8A76445E1283BB22D1A47DA113",
- "de_type": 426
- },
- {
- "contents": "AF46",
- "de_type": 241
- },
- {
- "contents": "C12A5AE9835106753CDF5C961EA2B3A09E5345C15A8BF2878B05",
- "de_type": 131
- },
- {
- "contents": "021A8B90BA962F",
- "de_type": 628
- },
- {
- "contents": "4065CC7C14A9A1",
- "de_type": 956
- }
- ],
- "encoded_section": "879013651C94A1F7CFDA39FE974613772127A4911000FC81D58B27C193143B37E79A070730019001AC6EF8D82E470B38CB13558B2F2E0A0E7E28E0D70630BACD41B508B19550BC2301B46B8A64B8BFA3099D2DC6AAED4F125EFCE470FB97D8166834239B1B55880E969318422EBD021FB94EEC47F9602181B9F19A983926D42F185E1B3007D899CA",
- "identity_type": "private",
- "iv": "80342BF18D7C5776BD7FDE0A2F8AC447",
- "key_seed": "5FBD9471E75E2C59F62A8B341120BE518410FBC2DC9C73E01B0892A6BBB6390F",
- "metadata_key": "070C25B363FB7C308E15D378FE49E66A",
- "section_mic_hmac_key": "811B501ECD17C5CA3483A7B2CB4DBDA18DA36A8A0070A336FA4D4EC7AD617C4D",
- "section_salt": "FC81D58B27C193143B37E79A07073001"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C108BD4A771CAD2F6E7814121E2ACF0D",
- "aes_key": "C842C0FAD03E38DED3004C68FDE4FF7C",
- "data_elements": [
- {
- "contents": "37F07E9ABF51F94A2FEDCA5EB096BBB6A2C98BF5D792EC10B8",
- "de_type": 86
- }
- ],
- "encoded_section": "529013AAE6FEC854ECB31E4A0638F9C3459BD4911000D314E0A6FADC0C898CFC47B121C5D0439001D0049C43DE3BB4FC114A4E261443B33B87E3D0CDE141BEEE14A6B252BFE7654A53C6F5E087D7871E936406",
- "identity_type": "private",
- "iv": "9B140F556904B7BB90D90FE1D7053837",
- "key_seed": "C422D717FF3CFFB8A1799B7EBE928C327C3C6CECD0EB6F6A5ADDAE450C2E4A43",
- "metadata_key": "FA01F1000E65A2B4CF29A61C94B48C0E",
- "section_mic_hmac_key": "346DA5C873307F1DE6B6D50DDA7565FD3B64D62BEE8FA5449878CB9B04B8219A",
- "section_salt": "D314E0A6FADC0C898CFC47B121C5D043"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "195580FBA34790E8277954C3BC9D2082",
- "aes_key": "E2803B4903235BA7D86D3148185D8CC5",
- "data_elements": [],
- "encoded_section": "3790132C00FD339FEFDA9A33EA05F0B61C1C559110009E3B063ABD78AACCBA9411EBED90BF029002569640B7F099D81C9F82A9C45AB8F38E",
- "identity_type": "trusted",
- "iv": "6CB76A799DA3B1D880221B61FCD13BB2",
- "key_seed": "85F01432030780C4EF09D81B8B7F3E6F6181AE5E35818A9327B90B513B18D39E",
- "metadata_key": "CF225E1482E9DDC1EC23BEE3830BB297",
- "section_mic_hmac_key": "E59C266F44177561A92FAD0E914787F91B75102D557AFDD8A90E15E4C517870C",
- "section_salt": "9E3B063ABD78AACCBA9411EBED90BF02"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6E020398D55EFAAE4811261EDA98FD6D",
- "aes_key": "116A369A261D68D0CCBC42A18C347ED3",
- "data_elements": [],
- "encoded_section": "379013DE1AC91E9B00462A9A9BA642DC5849799110006116C6CF4A3C7D6BA18B8D226D2301C890049ABE79E404D562A6885996894ED53AD0",
- "identity_type": "provisioned",
- "iv": "1D018BD16FD2DE9E649CEBABD581DD2B",
- "key_seed": "F7826F803023E18562041D581E30C68B18F3BD079ED331AB08959EA9D6A4BFD5",
- "metadata_key": "7B3DFC9C93D7749184D6D74358823E85",
- "section_mic_hmac_key": "CB330A1CF99F0FF314EA31874A09A1C7160318E971FA13D268337D59814C7B1A",
- "section_salt": "6116C6CF4A3C7D6BA18B8D226D2301C8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "567D9E7C592385238EAE53144E8BA230",
- "aes_key": "136470023C70C08029F4DFBAE9F95B7B",
- "data_elements": [
- {
- "contents": "A561C92ACC2252C6C62DFEFA992BC2C5A9C48D04F9",
- "de_type": 248
- },
- {
- "contents": "683961187D5DB39339DF9785A2C45271D1CD68611D",
- "de_type": 816
- },
- {
- "contents": "B56F",
- "de_type": 910
- },
- {
- "contents": "6166018060BFB398E173C269377CED91731BBD70",
- "de_type": 507
- }
- ],
- "encoded_section": "839013A7C4F33A2ECDC37D6C1CF6252071A5AB911000935A35412D351D8B3D41105173987C0A900266AE9A51DBD974D99670EC791804347809108459DE0B339FBF2C78B1B283B5D47C3B890744DB38733464E8125F101CC220E1BFA52CE6E8871A2E40FBC4E9F7619175B7E3903D7FEEC02B5571A874F22785BE608D844AD1E62A3CD1E1",
- "identity_type": "trusted",
- "iv": "B2FA1B41C649211A7EDE06841F5BB38F",
- "key_seed": "76761CBE3E4C5C59C635770D6712FE9DA60F3EC7DB730C2A2E269D022F253043",
- "metadata_key": "4ECF0D1A14561713F994E2DD7B685FC0",
- "section_mic_hmac_key": "E05AAD376A660745E2DAA4552147B6301FE2D8BF56586011AC28893DB5856E96",
- "section_salt": "935A35412D351D8B3D41105173987C0A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "21A510F6CE3823A53764724B62FD6B7C",
- "aes_key": "05C066DCB8F0B98888E96B567579C868",
- "data_elements": [
- {
- "contents": "C15CB0D22F013348DD0E70231A556608480E31D9E890D830B3A553415DAE",
- "de_type": 37
- }
- ],
- "encoded_section": "5790135C827FF620A9B1F9F152963942D6E026911000FEC1DBF803354DC1673A835893AED9DE9004A715F76EFCE834E20F88537CF36933F54809CEF7842962A6DAC2D1D3AF22CAB9E5E855FA6D5F7BBFEC371F21056A8A1A",
- "identity_type": "provisioned",
- "iv": "B758108B3902E3BCA1ED0C889CC5FA60",
- "key_seed": "2F56D486D5C63D844C2FDEEE2180803AD2D1EE5905BA717461135123670C399D",
- "metadata_key": "D468A60519C50394C3162E0E02BEE109",
- "section_mic_hmac_key": "250E47FD6AEBEB5E33DF17AE8F5819EF98D0839A011BA4FEC04AFB39E75D9F79",
- "section_salt": "FEC1DBF803354DC1673A835893AED9DE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "80B928DB65B720EE90833AA09FD5DC89",
- "aes_key": "EF85E00C15787C5B8CFA20A31C1EE64B",
- "data_elements": [],
- "encoded_section": "379013023A8AF0E5E41435B4DE9FD9229166A49110009C4B81AEB3D407915348130AF8B9D1609004E4309CF504F37E93F69C559457182D38",
- "identity_type": "provisioned",
- "iv": "BDE415E1EBCFE566354779AA734A0F9C",
- "key_seed": "70F30CBE76BDBF3E99847FFE02242A380D50E2A9C444696C62790E927665196C",
- "metadata_key": "0777B0D07118272EF18915210E67D4B6",
- "section_mic_hmac_key": "67978F51212E8DB9187E5EF52DBE96714EED071C716D8FC27905A138C597FB6E",
- "section_salt": "9C4B81AEB3D407915348130AF8B9D160"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DE84590AD5159AE889FE5191762775ED",
- "aes_key": "58AE0ED041CB11626C1E135A8FDA418B",
- "data_elements": [
- {
- "contents": "787F",
- "de_type": 864
- },
- {
- "contents": "D1F4A82599F6",
- "de_type": 876
- }
- ],
- "encoded_section": "459013A9C4AFAD3ADB46F107137C6E33B1BEE7911000039933B91DD5D7C409512651661B032990014642BBCF512BA6F71FD38D6E73BAEF600156F6FB689FE5BC6943B6A121EE",
- "identity_type": "private",
- "iv": "D961D3EFC14523C97BCCF93C47DE7AE9",
- "key_seed": "D29C5FF82F0D66CE956927333836E3354CB86DD41EAAAB8392225693E897A2EA",
- "metadata_key": "B544F56E3A995CCEDFA8549780BC793B",
- "section_mic_hmac_key": "D5833BC069C1B314C6A3F7D67320098E72CD93F3770F1E45EBBA5742AF3EC288",
- "section_salt": "039933B91DD5D7C409512651661B0329"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2FF79874212D7CDA93645F988AF6421B",
- "aes_key": "9BEABC1D25ECDB374914B8700638C7D9",
- "data_elements": [
- {
- "contents": "F9B8FB6EC10F68",
- "de_type": 896
- },
- {
- "contents": "C08B48B41244100DE3CD2B0DD489",
- "de_type": 32
- }
- ],
- "encoded_section": "5190133A88E7EB3645A94ED695EBA85F75AD1B91100037608F6EBDF46AAE033ACF587848E6639004B805DD3CA0249ED6FA1EAE1244D8E3A49F354370746BE13814E00D5839741ABE795D2752CCB57897FD07",
- "identity_type": "provisioned",
- "iv": "217FB82980A6995AEC010E921FAC6243",
- "key_seed": "DFCB8691CEFEB4ECF09ED9F0719E45C25B4AF43AA8DD405801D670610F508F65",
- "metadata_key": "0917CF2905CE9FB3113357F3963AC8C1",
- "section_mic_hmac_key": "B797F2EAF9EC7F43CE59E70D7456B0B487AE6A428BF133FF7EDF35C16C2522B5",
- "section_salt": "37608F6EBDF46AAE033ACF587848E663"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BC78512327F1C8471CF01C0AA4FDEF2A",
- "aes_key": "7CD9D0ECED9B92B058C164C72DAA07A0",
- "data_elements": [
- {
- "contents": "0FE510DCD7D804",
- "de_type": 739
- },
- {
- "contents": "7C23D2D6EB1B8B3BC85F16DCCB34459904D415F286",
- "de_type": 217
- },
- {
- "contents": "4CD0B17F3AD93405736BC91F9C4DE76669F2",
- "de_type": 763
- },
- {
- "contents": "E91721441BA575F21A84CF4DD20B61FA14C6",
- "de_type": 938
- }
- ],
- "encoded_section": "839013AC1DD11822478EA0E8FE591CD90238209110004D8A533E493907664027DA6A4F3183F29001D65670948662735E7A7F129595196B44B94D1AFE368ADD6E5DAF03AACA8E3C4077F46A164F0BE076022417C86F21E8646A103E333AAAE689E33DF411784E6B7D48607C4C8FF6B977AE9F7C55B07DE52F88A54ABB35DC20F128D1E647",
- "identity_type": "private",
- "iv": "A706CDD672985D91B0CD4F308DE1CC70",
- "key_seed": "EEAAE365B3DA449EEB6F25B891B7023EBC5FF1B9B675FA12DEA7525354773CF6",
- "metadata_key": "88335D0BD8B53CF2FA24E5EB2D004E91",
- "section_mic_hmac_key": "EEED7FAEA65FAAC630EEDE3F70681E796AC19D2E64EEEE5BED29F65BC5064E35",
- "section_salt": "4D8A533E493907664027DA6A4F3183F2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D1573ED4ECDCE4A879E65C68B1165F45",
- "aes_key": "4FED88141D37FF7790CEFDD9E5A7E9F2",
- "data_elements": [
- {
- "contents": "430F28BC",
- "de_type": 204
- },
- {
- "contents": "32EE03B85DF71B06B43CC1C8AC17C3421756FA83ADF098CAB3",
- "de_type": 518
- },
- {
- "contents": "F0A965818855",
- "de_type": 542
- },
- {
- "contents": "",
- "de_type": 390
- },
- {
- "contents": "CADA0F0AB15928451A346544ABBF",
- "de_type": 84
- }
- ],
- "encoded_section": "7690138D3D5ACB2206D76CD2F0DD909F8D0DE69110005A4E8669652BD77496780CC8085FF28B9001B94FB713B235D2EB84DD453FAC955BA8994A4796E3ABC89E7D9BA85085AA727777981A901A11ED6E68F97EC32031FCCEC7BAAB22A20F4DD1E81D811CBACA821E4CD75266B386079896AB4EF9376970",
- "identity_type": "private",
- "iv": "DEDC56F368F3719F6507F18862DF2F21",
- "key_seed": "7474B5856B73AA33803B8F16B5F9230EDDF0E805842BB2494A1F8FE87B8DD10E",
- "metadata_key": "0989622EEDCA93001550750A77E81D52",
- "section_mic_hmac_key": "88CA9441457FB574EBFC546DF423D2996213B2FE20674FB96BEC57B15E4802DC",
- "section_salt": "5A4E8669652BD77496780CC8085FF28B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3379B3B44F19BBEFBAEAF20E742D9209",
- "aes_key": "BC6242695C247BA13FB5E1B0A15B7F00",
- "data_elements": [
- {
- "contents": "4E92C67ED663F28F0D1E3FBC3E295B",
- "de_type": 891
- },
- {
- "contents": "6D09BFCB10C38724315FA37FBD9F4B01169D5D2F",
- "de_type": 497
- },
- {
- "contents": "674AB7E0797190073A3AE9",
- "de_type": 731
- }
- ],
- "encoded_section": "6E901332F1F41C1274F02153C590E9582228A79110003A467B2E8A05693603A106F0CC3EFD2A9004CA7F77623D873F7E349A56A149DE733DBFD129501BF46EED93A56BCA17BC3DE92AF5ABFD1B340451D013535A4E939C2BFD78382ED9E661B3C906B20B9B5AF2A8B9C56C544DC7C7",
- "identity_type": "provisioned",
- "iv": "97CBFEE77A69EC3AB70CFA9DEC69D8B6",
- "key_seed": "396536E9DF44FCADA1064F4571A5AAC5646FC8B3EDEE0D33A5DF52C7AE61876E",
- "metadata_key": "74B5E5F9F6E2E1F4E23B9250CDBBD802",
- "section_mic_hmac_key": "E10F34CE2FF4F91DEF8BCC12EFC3B9FEA40F02CBA57B0C714C3358862C9834EF",
- "section_salt": "3A467B2E8A05693603A106F0CC3EFD2A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "27CDB6CBFC3BF4820E0A953BB46AE4EC",
- "aes_key": "F2963BFFFB81BABEE97F57E2264B4D2E",
- "data_elements": [
- {
- "contents": "2EC8FD8FAF7CF8B52193",
- "de_type": 797
- },
- {
- "contents": "DDEFB34CB3BB4D52ACBAC8602A8975FFA878FC21E99C",
- "de_type": 715
- },
- {
- "contents": "9A2F3ECD9492F6C8D7F5A38C4A213D895D",
- "de_type": 46
- }
- ],
- "encoded_section": "709013AF7171A0C034F3DA55BE657C572FBDFD91100079434D607EADF68D155698ED3AC192F49001A96F812E44AB68004FCF2B067BA95BBCA6CC41B11F4B8A99282FFB2A8BE34E170C129E1041CBA3F9E63B426C54D6A2221407494B54F373E2EC8A11421D6AADAC787180B6A076434327",
- "identity_type": "private",
- "iv": "93020ED0EF291C73688089CFCE540F62",
- "key_seed": "64E35F579F6D8BEA4A3B9646779CC1C21EA2D2878266A7EBCB0773976DED9D26",
- "metadata_key": "B913D7031986423EB7BF3339608702D3",
- "section_mic_hmac_key": "DB938326214EDA6FB2FA5F84B9DD0ADAF589302CAED778C1A5155473CB9FAA61",
- "section_salt": "79434D607EADF68D155698ED3AC192F4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "74D392DC20C0813FF03FB08EBEE968CD",
- "aes_key": "C42393145979EE5678C0F02913E457C2",
- "data_elements": [
- {
- "contents": "A249A3E9418CE41DC5B3EA515726B651DF5DC1A992B2",
- "de_type": 786
- }
- ],
- "encoded_section": "5090136279969B1461D2CC0840ACCCFAD1B3EE9110006A843ADF7B539F71779C57B18939E37B9002D14999977E208361FEFF91D231EB62DD0B461BBF47B33CE9F4DA9A5466D6FE7142E7A2536B9790A1B3",
- "identity_type": "trusted",
- "iv": "F2A0D1AF937909CC82BD391A38FB00BE",
- "key_seed": "10FA3986A299426275917865D774D86FAD4AFA8D83E7A92FC11B2B454E90477A",
- "metadata_key": "59C6C47FE675122BDA465398F91BA5B8",
- "section_mic_hmac_key": "26150B11FE754225C2DFD776DA88595D6F59333D7DE50DF56ECC216FAB7BE68D",
- "section_salt": "6A843ADF7B539F71779C57B18939E37B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "49709E72975E1423DA5EB84983796A68",
- "aes_key": "8C3FEDC1AAF1E282DBFBE2A2826F593E",
- "data_elements": [],
- "encoded_section": "3790136B0AB5062670A1F2CFA73A8A0C3E2FC3911000E5070EE95C545EDF7C37A169D35F7A469001DB7F2B2790C2DCD64A7684D80219EEF7",
- "identity_type": "private",
- "iv": "52BE6FCAC177DB189EB7CBE873855789",
- "key_seed": "E0C4131D54945581E0A6E7053C42B1C20483EB908F17B3F430745224648F0653",
- "metadata_key": "2D6FCA5EA2F20F86394769CB9FC4F743",
- "section_mic_hmac_key": "E27951578700D0C5D6BA74098639A6AC7EF5F10CE611AA0E490ACF9A21A07D00",
- "section_salt": "E5070EE95C545EDF7C37A169D35F7A46"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1CDE5651C61DB529D7A871B8F2C0F913",
- "aes_key": "E599DE7996E01F12260F13DF78E15B59",
- "data_elements": [
- {
- "contents": "097A4A5AFB2B6CFDEDD5A15130",
- "de_type": 749
- },
- {
- "contents": "3D15EB4E149B5A",
- "de_type": 478
- },
- {
- "contents": "D6D18F999A8934363B5C8FF561A7A62597FED9C6D40A",
- "de_type": 489
- },
- {
- "contents": "",
- "de_type": 952
- },
- {
- "contents": "C20A8E031417669DC55C7B5A7E64BBBA59",
- "de_type": 76
- }
- ],
- "encoded_section": "8090135046F9F1E83B423043631D49D56C9723911000B5BD5514A8DE674976FBAC499AAA9F529004B235B4809AACD74289EFFF94FE9DF1B36194DD4B93B2EFAB21D946571476CD1B1A07280EE656539DE4C54CF3E47D9A0C87A60D58EE613F49C5977750DE5011A6BB52C63C6E175695097AC3012E519D7FF2E18445DC2D063666",
- "identity_type": "provisioned",
- "iv": "6C3A04584261C50FC965FC088BCE4FC7",
- "key_seed": "A0862227764FF19586A9C36D4D5EA8AA743ECCA8E0708995CAA04D3BEFED5A95",
- "metadata_key": "F5F1E4D56284CBAC633932CAE89D0D4C",
- "section_mic_hmac_key": "2D8B8B4C0356D9767D6EFF979E049A139571CA43F70C7FD08DE658501FAB0674",
- "section_salt": "B5BD5514A8DE674976FBAC499AAA9F52"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B2FC3B369282CA10A016A4F84A430812",
- "aes_key": "668D21A8160ABC3CE12BCF6175D086A5",
- "data_elements": [
- {
- "contents": "5D3B4A3DBD0B402681",
- "de_type": 933
- },
- {
- "contents": "08666D6E86796DDDD4C185D7CD3B9C4BAAB698D7154302D0",
- "de_type": 239
- }
- ],
- "encoded_section": "5E90134107A4267522159AB8C37627D144A05F91100049DB288036A3BC3695F0F55D0BE639A19002557A8352F4128B631F38921E110A33279C46B3A97E74B9E4537062A4E23BC831A8866394105243C1EC880F62EE49F7E5E4D65BBB01B4BE",
- "identity_type": "trusted",
- "iv": "924712790182ECC211328405178D9EFB",
- "key_seed": "BAB08FAE6AE8EC56D52961D055D99713CF5BC3742FBCA0F5B5DB63ED6D33F088",
- "metadata_key": "BF508276E08064CD62E2DDD3CE52419E",
- "section_mic_hmac_key": "C0AC82805FD560115A26DADE1F4ACA30E680503F73A730B9573F039B1A8D1E48",
- "section_salt": "49DB288036A3BC3695F0F55D0BE639A1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7A1D241939F1129FC8A7BA9692CC15B0",
- "aes_key": "02D06DE435FAC2E542496072E93B32BE",
- "data_elements": [
- {
- "contents": "0FF9683813B3ADB28F18966B3BF4",
- "de_type": 221
- }
- ],
- "encoded_section": "489013E0D22FB9284C2AE55EE6E93EDF4AA41E9110002F2750ECF08560F8382C78B66352FA359001151B5F5F92C8382D02BAFA80C1205644F2A858A39F0576CA5C41ED6FC8F620D78A",
- "identity_type": "private",
- "iv": "CB1AE27FC7370085ACC737B2D16C3ADE",
- "key_seed": "560A88DA8D8D99F0AA9B78F5C717070E814F73513DD8404D2842023C704E5F61",
- "metadata_key": "2FCE6A6844717E567B6453D433C396C4",
- "section_mic_hmac_key": "3110C125D838A53C13AA866C2BEA9BE4665D3E9917D780C44E06EBB679F0FCD0",
- "section_salt": "2F2750ECF08560F8382C78B66352FA35"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "92318118DA2EEE83E2EF5E45DFB5DCAC",
- "aes_key": "6BDD0921765C3F1BBC2A777EFCBCA39E",
- "data_elements": [
- {
- "contents": "C5F864769C033B1C4C908B1B9486DDA0DEACFEF5C8AAC5088A4B89",
- "de_type": 246
- }
- ],
- "encoded_section": "5590131C9D39D7CA06A454FB1963E0CD54B457911000250CCCF922CFB098C5A4B835742B50D290027433FF5EC8DC7CDCF92F5A5E299F359427BC71F6BCE090A69A8B3FB71149E628FC8F8414C225D8A9884CCE9C3E05",
- "identity_type": "trusted",
- "iv": "CBDC742C7977835B4958757B70C41CB5",
- "key_seed": "7605F725592CA87DE9BAAAEE0E22182AF0623EF1E43BF7C69C3E1B1600A31BAD",
- "metadata_key": "52235475342B8095F3E5DB1A9DAD23AD",
- "section_mic_hmac_key": "3298422E72C9D0E74C2F9A62D0B2061D7CCDF4C57728AC803D56E327C937A62A",
- "section_salt": "250CCCF922CFB098C5A4B835742B50D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F26D981FC5BAD9D1E76BF8F50E8B6A34",
- "aes_key": "6AFA08461D980105081BEFC1BED15573",
- "data_elements": [
- {
- "contents": "6C3FF38F38B1E556419512BAE94A24293321886158ACB54AB4F606F3",
- "de_type": 925
- },
- {
- "contents": "13E28EBBFA5679",
- "de_type": 685
- },
- {
- "contents": "12220C039D132FFA3F990A8800",
- "de_type": 189
- },
- {
- "contents": "BE1C6812",
- "de_type": 825
- },
- {
- "contents": "F65EA4C141184E27B5",
- "de_type": 536
- }
- ],
- "encoded_section": "8390134D53E258FB8B450831D776B4843DE2C691100013ED736F16EE6A2CED580FC6659D24E9900115C96C37DF9232D13C0A77058FD38C7904318CCC73B59DDE8D698753D1A81242B9F2D4988F75BD49B1EB7669ADEBB5C943C2B622790D8DDE98ED5CE2F6CE54E24BE94DE1B9DE3702CC611AECECB6124E6A4A8E78F077BFBBEDF1246C",
- "identity_type": "private",
- "iv": "6CFC6056865E1D43A9F198D6CB5DEB0A",
- "key_seed": "2E66473794E7D76F52E4F4EC27BC04B52DD0878E4AE728E030DBA17ED1BF5165",
- "metadata_key": "645B2EAEE90C3EDD564BD70CAC5EA05E",
- "section_mic_hmac_key": "80802998858AE3DF52E4C02A934CC27B218CB1B83BAF7AB7545B0A3D1A4A1559",
- "section_salt": "13ED736F16EE6A2CED580FC6659D24E9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BDD3E6E05FC1EF8F97B872F320EA5EC5",
- "aes_key": "C955629D757D92E065B1C843B3E62502",
- "data_elements": [],
- "encoded_section": "3790134859D4915A9669BAD25DBD6612C483539110007DB7203CE87A8753D5DF7D7B3B9548B390048800DFAFB1AE182D1F43A11B68CD9964",
- "identity_type": "provisioned",
- "iv": "7379BD491B8D004FD0BF5E572E1086BB",
- "key_seed": "BAA5B1933026681281A49FE55D3D359FF8A37B171836604BFD789EB52978C2F2",
- "metadata_key": "472C0CE0246A17A1F29A4083C8680C88",
- "section_mic_hmac_key": "81106F3E642560B70CAF5243B430480127CA1B1025C1E9EE45E9600429C81EE5",
- "section_salt": "7DB7203CE87A8753D5DF7D7B3B9548B3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0324729B74E497693C66C538B8E377F7",
- "aes_key": "6A0FD2D178986806E8D99448C6E03D39",
- "data_elements": [
- {
- "contents": "E779A71A22F13932159115D92842A7432D9273B15F9EFC0E",
- "de_type": 5
- },
- {
- "contents": "5AB6447296CE47957BEA513C4A78D7DB718DF085A3C5B6056313C5E97A3E",
- "de_type": 164
- },
- {
- "contents": "9BE2E0FEE14367E5F9904AD071327559AE351FF343",
- "de_type": 492
- }
- ],
- "encoded_section": "8A90130B1EAC69A3BBA0198791DFD7ABD975CE911000504754FB80080D08BDF20CFB89BAE2F4900232633668B94BD4B723F1A0C2F64D15F01A1121E86CB529C8C08D097252B3A5CBD6B1EA4797372EE51F4C8E0C11F6C7B15957C920FD00950144724D287E5A45893315E3E6613BF0A55F55E6F7E156A879A6EB7F31136810B1F31252E60E4EE8AB54D529",
- "identity_type": "trusted",
- "iv": "1EA7A7228D5E0B9BC2C467DE0F3E8D7C",
- "key_seed": "DE985E83ED8102B2850B579CB045EB10DCDB95A908CD2C11A3EC2AFB5C65D264",
- "metadata_key": "43C47B2AEFE02C363B05E235A6BD410A",
- "section_mic_hmac_key": "81B93FE732216DCD0036BBFD425D451A502DE7BF6834110FC665CD07E90806B7",
- "section_salt": "504754FB80080D08BDF20CFB89BAE2F4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "ECDD1DC8D4FD989DB4580FFFFD4EAF58",
- "aes_key": "26343238F4AE3E3E5F07808B3B012394",
- "data_elements": [
- {
- "contents": "19EEE80B7E463D4FA91175C1201E05ED27AD",
- "de_type": 418
- },
- {
- "contents": "138E9FFB3689657E3D2C4504596445",
- "de_type": 313
- },
- {
- "contents": "C96F4E4F9DF91F8DC2EA8AB25A49D112F5",
- "de_type": 272
- },
- {
- "contents": "3BF1B1D5B80FD33B4E13EA34AFD2B04997",
- "de_type": 607
- },
- {
- "contents": "60E79858BE9E3880F5840B8EDFA2AED9A1",
- "de_type": 657
- }
- ],
- "encoded_section": "9A9013C071629B70BA9DEDE2D6BE7C3EE50A89911000CFBC29C1DB6233359093D46F6B6268729002AA827CE8FB3E7D10578627C549FC3EDAFC546CF7FA5C5B8774321832389BC08CF65BF7008E138B2229C21112326A972D327C3FCEC4A5E447465FB6FB2A3D65F7C53D0BC3A7DE1664B0113E3E3F05DAFACF935775E1D7CEE288220BDF2920F1C0B6F0DBF2B7300EDAAC262A35D2207A9159F577",
- "identity_type": "trusted",
- "iv": "5D4306FF65CEFE2E7C434BB00E18B020",
- "key_seed": "509ED43FECE08BE6BF6379CD1778649C806AB7266610F065B2A6365442DCC4A6",
- "metadata_key": "A36A66D7F731890EF9193D882DE89F1B",
- "section_mic_hmac_key": "FBBE31414827EFDAD0A31F4BDDD281C958AD680F43AA856DD0319B01961F2E6B",
- "section_salt": "CFBC29C1DB6233359093D46F6B626872"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "876404A488F733AFF2480B84937DC32B",
- "aes_key": "F9AD44914D756A3E46E6BAFDD137CDA6",
- "data_elements": [
- {
- "contents": "804E497B2E573E7F2E93CE434493E636",
- "de_type": 446
- },
- {
- "contents": "70E3CFF3391999B63BB8F6FBF914969C40AC6A8B69A388CBFD5B5667BE8B",
- "de_type": 144
- }
- ],
- "encoded_section": "6B90133B3BC844AE809C69DD3FDABBAD762AA49110000330AE82E82A5CFCD43DD63947D7B25D9001D96A4D7255C420618CE01331413D4D7428210A004EAF8BA0A2B41DE9129DF151FF58CFD9BD8626FD3201CA27F55156CAE585EC593FA08E260A9591962B7F7F6A28FFFAB2",
- "identity_type": "private",
- "iv": "F4D1BB95A18F23894E8E694B2C95FDCF",
- "key_seed": "E1B4FF787998B33BD7E33250E2386F2BB8A0491EEC4CDF640A2879D09DA19E8D",
- "metadata_key": "048E9FBB34067F84D69B4D14ECAEA6D5",
- "section_mic_hmac_key": "D606CEE9D49A0D1DBA0E7F07022FF962F6F6DB04608FF2437F2AB436C4BD007F",
- "section_salt": "0330AE82E82A5CFCD43DD63947D7B25D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "68E03983FBB92FD3B3ABFFA9B536FAEC",
- "aes_key": "79F938C4FA735CA8FF0AB1C65AFA5116",
- "data_elements": [
- {
- "contents": "F2E5FF2AB3237D9375F716D5",
- "de_type": 490
- },
- {
- "contents": "9D808B5A5BBC1473FFB8DAAB95FD4D9FF675A1DE9A40",
- "de_type": 905
- },
- {
- "contents": "B90F45006C8FBC5A50DAF69EC332341C8FF71168EE6970523C6C548D6371",
- "de_type": 128
- },
- {
- "contents": "E541744FDDA8A39D91664C22A2C359BB8EDB4DE026",
- "de_type": 496
- }
- ],
- "encoded_section": "989013DFA3B7763EB39454DE5B2D1F11C74D459110004E4E42F39F331D403DAAC6FD2012DF5890026C8B35E350004277C3C63E5791CE1D8DF6EAF71F950F24A66EABE93ECA5E8BCD39470A09686924CC844A27FF303F73F9EBC2F1D8B15BB2844F4BE645F215E58105A6AF75A88234FEC0E4E83257FB377F595BE77CA1ED1735F929F928138D0AE987E2B094CAD8C91D20C349B2291D54397F",
- "identity_type": "trusted",
- "iv": "0EB2E5BAE1992B95A34004153725D67A",
- "key_seed": "BF2D76E1C94D308C2E27207081573B6C5B18749DCEEAE1CC6858E044396DAD75",
- "metadata_key": "766DDCDA99EAC37E0B6715030718F389",
- "section_mic_hmac_key": "65F998A2F910AC50F14613F0025A14062D5FD55D2BE2445E01DDF2AD3AFD4CB3",
- "section_salt": "4E4E42F39F331D403DAAC6FD2012DF58"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F512FD19534C6D30B3D6B6C64F735252",
- "aes_key": "C919354EE8916B537AF0C80B01CDFE3A",
- "data_elements": [
- {
- "contents": "97FF5DD7CF10CA400439FAD93E73DF7BF31C0840B47CC8625908F64F9D",
- "de_type": 884
- },
- {
- "contents": "E17E6D5BF307A79257F432B833BED7631896236A77DC8991244F02BF28F1",
- "de_type": 773
- },
- {
- "contents": "128F4E5BF9574E0C5D3E0C287DCBEFA2146ED9",
- "de_type": 43
- },
- {
- "contents": "F19F873AC214CF412446FCF92FC26F4F96",
- "de_type": 989
- },
- {
- "contents": "0090C56C3B45810987944B0D74EF0CE7BF771A24A4",
- "de_type": 996
- }
- ],
- "encoded_section": "B99013C5864027C79888996629813A4E22D8FE9110005A6F75A015A7BD183C08ED51EA3406A890022FF7107FDCB387636B67554BA545F04F63A89E41B3547AC27E871BA24BED6B4E347E83DCA86FBB188B18EFEB48E6CAA8923090905BC4974559534DB81313EB69E94BDDC2F397E1CE6247259C046D724DB1AE74ADAAD252F57E477A3C5FD472690839152E8D8571B70C0CF9F486E0125BD74B3E5535D456C966B61E6045995F384D61A2CCD360DF06CB3408A43BC9EF24F861",
- "identity_type": "trusted",
- "iv": "AC1E6DEE532335A11CC00AA26D211142",
- "key_seed": "0654E589CAC8FDDD66324A9E33795A884AB11FDA325C6A1FFC9184981B547C11",
- "metadata_key": "BFCD84710DFB3F2C3BF10DFFF9E1DEFE",
- "section_mic_hmac_key": "FE6CC88BE6EBD51916AADCB0525D7C7F817DFB061781676C1C5258D466DF7CD6",
- "section_salt": "5A6F75A015A7BD183C08ED51EA3406A8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1020365708197FA134F58032B0736A93",
- "aes_key": "23C5D746F33EA244CD01AAA605FC0D12",
- "data_elements": [
- {
- "contents": "D6D87CC0",
- "de_type": 969
- },
- {
- "contents": "F19C90FB",
- "de_type": 138
- }
- ],
- "encoded_section": "4590130680B536392B1C55C8A39F7575ECD678911000AB790910EBD2510A516A52F216386F5690024C190A81E7249A478324EAD802CC0A72F631AB3ED55CBBC330E0CA3ED6FB",
- "identity_type": "trusted",
- "iv": "18E15943B98E5BE79E0726008C289E41",
- "key_seed": "E7ADE77256E2288534314126F088557EBC87BD3E0034FA36B5E2E414B2BD3089",
- "metadata_key": "243CFFF6C8ED39CCE1D20ACEE1E8C6F8",
- "section_mic_hmac_key": "90DC367708ADA4748D498E819BC4218C62FA48A828308197F421D9B13B3402F4",
- "section_salt": "AB790910EBD2510A516A52F216386F56"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F3F2711088CD0EE74DC97A20DAF1C2D8",
- "aes_key": "71FF934D1E8D517FBE367CD46BBB17F8",
- "data_elements": [
- {
- "contents": "A302",
- "de_type": 512
- },
- {
- "contents": "01F2F27578CA1CB5AEA3747DCE36EEB290376B14E08854",
- "de_type": 770
- },
- {
- "contents": "C712547AEAA2158286610804E3EEA4C1071F90B9178F4E93E6F8",
- "de_type": 622
- },
- {
- "contents": "8338102992C864649A9D8A78C497490CC8EE5750E12EF9",
- "de_type": 962
- },
- {
- "contents": "BC3B3A70C610A20D7C",
- "de_type": 754
- }
- ],
- "encoded_section": "999013DC39E4693F8C1317955AA5920150891A911000B7A64ACC26B3A13A6E1EAF8566807D159004E9CD0DFC4280A635682B3A8DC254119A26AD228C86A032FFBFE926391FD32C81741EF29655A09920EA7FB7090E73359C6B1E61D67D4ADA3BC78F124E1829F6C877453C1200F4FBCA32D7514AC9C2A98F5CC300760F2B114FA5A39701AC236A8E15FC028169E8A7EE42A72EF54829AAB35F5D",
- "identity_type": "provisioned",
- "iv": "A4AF64AE89D6ED2187780610289F118D",
- "key_seed": "9A118BA5B630A910A034F4CF3B9244F57A23BFD59FC0E4934F672CD63E020145",
- "metadata_key": "9815FBD7BB8FA24AF2053C9D01F8862B",
- "section_mic_hmac_key": "AD345DE497CD73EAEA71EA56EC7098FFD71E65A87FC7B01247643435342EF5C4",
- "section_salt": "B7A64ACC26B3A13A6E1EAF8566807D15"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "420F8EDDBCEF536ECFE0823E0A64150E",
- "aes_key": "3E58CA6C9C2E9494CDFDED070763FB07",
- "data_elements": [
- {
- "contents": "C41B59CE2AD957CA07959684FB6D5E3FDE89D31EDAE877",
- "de_type": 280
- },
- {
- "contents": "D0DDD13D28FB08B9C19C290C3347",
- "de_type": 120
- },
- {
- "contents": "1834",
- "de_type": 45
- },
- {
- "contents": "A3BFD5AEA1634D500CD9D436",
- "de_type": 896
- }
- ],
- "encoded_section": "749013C498F161B727AABCE678B9D94DFEBB0D911000873C3CADAF81A693213597DBD9C53D8690019FD0E7986B2509A457A42866D34E0A892FE47105171A1CE2A245193130B6A1FEC7A6F485EE8AF0FC67ED58B9B732DC93C2671F682805343994C0CDECB5D6E725698F135192C657C569FD81F0CF",
- "identity_type": "private",
- "iv": "22BCDB28787B9F7343729B59C9F06F87",
- "key_seed": "5D3AA5329E3AD5BC9A4C16E276FED94699221C782DBFDCEDEDFFB81FB32FFAFF",
- "metadata_key": "CDB698B8C76457DA2631586E44409C35",
- "section_mic_hmac_key": "81392F1B099B77B1D7DD7EF7B8C9E58CB4A2444C56CB40D955E238A2BBA5C39E",
- "section_salt": "873C3CADAF81A693213597DBD9C53D86"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D2F959AAB5DE3FD53094D768D669B969",
- "aes_key": "DBE6CC0A7A07592FEBAD3CFF364A5ED5",
- "data_elements": [],
- "encoded_section": "379013D2960FA7CD8C566FB6722FE0AFB4BDA1911000C5272B1D1A6B168B77D90348D5A8F11E9002FF37EC6DB5FFE7B653EC43A49A0F079E",
- "identity_type": "trusted",
- "iv": "98C8F75EB86F93E39301FB09266AB286",
- "key_seed": "4CB698ADA80C2A298CE7F3C7AC4EE3DEA2E3152F314DBFE595FD550E8895383F",
- "metadata_key": "EB0F5B5FB454BA99B963BBC853069E33",
- "section_mic_hmac_key": "37E1AFAC60FE9EB5B3976AD6DE229A72890F74395CEB0354DA6E39E24251F5D4",
- "section_salt": "C5272B1D1A6B168B77D90348D5A8F11E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "14E183839363D1DC8DD63971B165D847",
- "aes_key": "15A23D3D9E70A3323BE7E5E0ACF62EAD",
- "data_elements": [],
- "encoded_section": "3790138678FBDD1D4B2FED10D2044D7E75F2D1911000E67C5ACF5A491028D74192897BE7C8C89004FD23DE541F708C9F0E8412122769EF79",
- "identity_type": "provisioned",
- "iv": "853E925894CF1B53548A9547B9D5D2BB",
- "key_seed": "59DCCE265D17F292C21FDAB1AE190050BE79B24CA9598F341CF3CF28B54C65C0",
- "metadata_key": "CA9C149B9147EADE4FDDA3483B5CD694",
- "section_mic_hmac_key": "AFE7942059529B6761E08237FD3DFD1B1E5375AB75D993318B04F92DF26CF4A8",
- "section_salt": "E67C5ACF5A491028D74192897BE7C8C8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0EF53E475C49FF12FFFAD62075DC0D5D",
- "aes_key": "E7EC797302AEE2AE931B498246B49B27",
- "data_elements": [
- {
- "contents": "03BC28F6",
- "de_type": 538
- },
- {
- "contents": "78",
- "de_type": 119
- },
- {
- "contents": "7E",
- "de_type": 436
- },
- {
- "contents": "140001B5FD493CCB4EF775",
- "de_type": 67
- },
- {
- "contents": "A82250F3EF3A3EC7AD986144C53E1385FDD7E32920DA628A36E7C4EC40",
- "de_type": 177
- }
- ],
- "encoded_section": "729013E7032F673DF5F16041DDECC78F5ADCA691100099970A2BE5CA4702AB5F94CD52BA12D29004856D9D48E7BA32C0E1D609F1077585A0386531F8456FD5716E5B16E5025A50A2866307253B298F8FEE9FD51C4E2C15FFBDA0FDA07F1B72402FDB1021BDEAFC707FF2E398B0125E73C43D08",
- "identity_type": "provisioned",
- "iv": "9A6B50EE556D600EBFED50255A635666",
- "key_seed": "3CD3990FBBFE4A88391309E9A3314A987602DB087E403C9AB34E5EDEF94E20D8",
- "metadata_key": "4A1BA5934FF66FB454D46083D338B99A",
- "section_mic_hmac_key": "357EBA3A7167F44A6BE8E10DBF1EB509A0DA2F1998FA8DD0338BD2DFC20CD716",
- "section_salt": "99970A2BE5CA4702AB5F94CD52BA12D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9E5270F2FD83C70EC6A8316A5B3DA3F7",
- "aes_key": "BC2F869516A306EAB00FC86189F94B33",
- "data_elements": [],
- "encoded_section": "379013994A578360FD876E664C89C68C4B4A94911000029A499D61FE555DCE2FD9B72E293E7590025902F37B71C8D6336FB581272FC20E0E",
- "identity_type": "trusted",
- "iv": "EFACD81C00A66A18B186EDD153827783",
- "key_seed": "132CECE9A4A70E8BA66CC013D3A7802E0C394E2CB6FF70934B7FE0793D87D365",
- "metadata_key": "2D71D02CB1BB8194F317CB46FE0F91EE",
- "section_mic_hmac_key": "6BD9C9248FEB3255BB7A215A55E5A75B6E6BD1D2DB77CAE09E0A7082042CDA56",
- "section_salt": "029A499D61FE555DCE2FD9B72E293E75"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "21C3D6A19DFF28652E68CCF2EB17B6DF",
- "aes_key": "03C7A896A16535EEC2C6A351C3C17401",
- "data_elements": [
- {
- "contents": "1F896905",
- "de_type": 229
- }
- ],
- "encoded_section": "3E9013756F991A26E044E25C8F3A005852033F91100068CBC39EBC593EF92F0A7852D4CFAB2E9002385D85A14F31B33F8EFA86FABAE5B8CDF1302D8D83AB8B",
- "identity_type": "trusted",
- "iv": "54BD3DC6A8F78CEDF672FF5722264019",
- "key_seed": "313399F9F3EBA494B79B76AB2EC128CA4F090DEB39FAA941B6BF1C5D64C3D21F",
- "metadata_key": "E975C7A248514BB2EA89E1F61CCAB17C",
- "section_mic_hmac_key": "CA509CB5DE76153AB5AB8605FF2B18119515FEC7667E42D1EB783847D9E7BFCF",
- "section_salt": "68CBC39EBC593EF92F0A7852D4CFAB2E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "98BFB3E0F0510DFE082F97B7179DA50C",
- "aes_key": "5494153569CE0A4AE2EC9504E949F5C1",
- "data_elements": [
- {
- "contents": "893281811CA83052DCA1F09C4BB9F66B979F",
- "de_type": 891
- },
- {
- "contents": "DB4CBE98092EB7FA4E53",
- "de_type": 679
- }
- ],
- "encoded_section": "5990137998FC158FECFA5BA42953873097E86091100031BFE75E39CC61D315D73D7D17637BB59002E498BFC92B873AD59BF1A8B4D00F2E3C223B9D764D32AE999EB9407B7C5E10ED655EFA33CA62B9AD7FABBD760AB4046F32C0",
- "identity_type": "trusted",
- "iv": "71319F6EE32F01F7442755A48314D90F",
- "key_seed": "DE2E4CE127E2C5B34556CF992FBD5A97A9ACB072210657E6D7234CECEA835947",
- "metadata_key": "28AA7545DCF4B6861C4379FCC6A51547",
- "section_mic_hmac_key": "86A9DFAEF782CF536B2BCA2E2B70280C6D001D6E79C7E1286DBD3BDF0B273EA2",
- "section_salt": "31BFE75E39CC61D315D73D7D17637BB5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F792CC0735D975CBDAA95FDEED64CC34",
- "aes_key": "6CFA85E9D7E5F331492B7B7EA0FEC8F7",
- "data_elements": [],
- "encoded_section": "37901374CC86109CA20F39080D2176D95C0A399110008CFBEA96CDC8317DFC83180AEB0E3781900294B9DD5B5BBBE70EBDBEF59583D9DEFA",
- "identity_type": "trusted",
- "iv": "F2BD046CD8B55DE3DA138D23F2836888",
- "key_seed": "217BC510C941A4F4CED29FC8918C5DA9446B947D15241150D615386A80A5DA07",
- "metadata_key": "2E50D416BDCF795FD7B5543B26FAEB27",
- "section_mic_hmac_key": "7CDCB29ED9C12538B161F13A6E8CC784700FB5FFC7E2DA4F6F34FD933DBB5D77",
- "section_salt": "8CFBEA96CDC8317DFC83180AEB0E3781"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0459E861ED82466586CB38BA820A08F0",
- "aes_key": "E2A53ACBF8D874D7E3446A77DAB8C00B",
- "data_elements": [
- {
- "contents": "73C550",
- "de_type": 154
- }
- ],
- "encoded_section": "3D901386F0FA8E4C1631979E805860E37B810791100053C835177E42543EA07364331BDB0B9D90026DBC4D371F252DEB9EC232757C0FFF54B0AA5AA7D4CC",
- "identity_type": "trusted",
- "iv": "42A1D51EFAE859C62164F4D13EFBB665",
- "key_seed": "0BF7A81876C2775C3D1A8BF926D2B32C6EA0BFEA2C677DECECA4D82A40627CE5",
- "metadata_key": "DA02A311B1BE6E2FF7F35ED04F2BA935",
- "section_mic_hmac_key": "C224D779048C9F41DC725298EDC634A13F54D0726070153C90AF7747543ABB7C",
- "section_salt": "53C835177E42543EA07364331BDB0B9D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "716BD818239FEC609FD83E0E655D99DB",
- "aes_key": "E510FAB4977C76912B8A434666935A8E",
- "data_elements": [
- {
- "contents": "36B8E05F3ADFC6EB9748E93DA4CAA90DFBA993E4A623B5387F",
- "de_type": 773
- },
- {
- "contents": "32DA679152",
- "de_type": 979
- }
- ],
- "encoded_section": "5B9013DA850EE1EE94DF5815178A410C55BE0C911000E78A10BE08D7C230574BD056D8478F8C900496535593BB99B5FF19FA00B4673B4EDA76BFA04DB8DF0CBCD14807D518F0B500206AAD90F34FFC1A1CC22F37C9057C4642D732AE",
- "identity_type": "provisioned",
- "iv": "96F876599B14A21FC060A042F5E134E6",
- "key_seed": "F9A248BAE31270E5C543E5EAE28C6552E62BF7DD99F7BE518B5CE78D52C535A8",
- "metadata_key": "41CE67094AA58CB68886D68D0193E9FC",
- "section_mic_hmac_key": "ED41BD675FE9FC9D386D5F7BDF85A090E0CDD06C654B74F9A925466A616B314F",
- "section_salt": "E78A10BE08D7C230574BD056D8478F8C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7F3CC424F187398A9D04E051B12744F9",
- "aes_key": "32FE6B6BFDC54C7C3D190731779B9BDE",
- "data_elements": [
- {
- "contents": "9F8CAF983F9440011F44B7C1E739BD66CA201CD553ECD202C61CC3",
- "de_type": 597
- },
- {
- "contents": "86636F77095B43A7D8CF9409D3FB56CB184EF894C68733",
- "de_type": 351
- }
- ],
- "encoded_section": "6F901363F63944D3D3B62852E1C29317DC53B4911000D1CD81A105ACF9921968705EAEE9D92A9001DF86E28C415ED0E45F886965EE16475E0C63561C5D876E9F6E5B24E64419C905FCABB21DF8039EB945DC929888A4C7AF8F4729023C726132918DAD5603E12E1A152D57961025B1D9",
- "identity_type": "private",
- "iv": "5FEB88C9EE2B3558BD1E1CACF0CE8DB7",
- "key_seed": "8D82AA87D9535AC9B95629FF003748F0D846D09DCF4577EEAD0F46351AB74B41",
- "metadata_key": "4B7CD0359387387945A934B6DF464C8B",
- "section_mic_hmac_key": "ADAA329E70F13AE3122A74DF74E84A7C6F1EEFC966617408BE3FC279AC4BB8F6",
- "section_salt": "D1CD81A105ACF9921968705EAEE9D92A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FB3D9837C28AC67707ACFE168B79802F",
- "aes_key": "DE1ECC3710EE70A72F458CCCBE684022",
- "data_elements": [
- {
- "contents": "311806935DDC",
- "de_type": 932
- },
- {
- "contents": "941A",
- "de_type": 262
- },
- {
- "contents": "4B70C0E6758C665694CEF8D27E2169098693AEA61570C940FBC453",
- "de_type": 20
- },
- {
- "contents": "BDF524A91132073481B23A0D20C19E3E57D365C37A90FFBA8E41",
- "de_type": 474
- },
- {
- "contents": "9C36B683253A6AADD79843",
- "de_type": 965
- }
- ],
- "encoded_section": "8D9013794200979A65FAFD9C31FEBA2DACE1B29110001C6B6EF087BAD3E1CF545DF1A9A9CE99900432FAD109DF59A7DEC426A1DB051FCC95F420A321410D13AA0FDCA4E22DC7A7D6873AE13CC3173D14B2BB9CE969E9B0A8B6745D7E913D03BA9031E8EE7A09BDB9689C80DD630CF7D193B233F3F3F1ED1054D9939D8EAFB7EC55BA71A7103F7961A29A1C26B888",
- "identity_type": "provisioned",
- "iv": "4EF171E764B3E218255391C9D368765E",
- "key_seed": "FAF02B1CF86D9A97BCF9E2C0FE5850688E3D49E53616224ADE0238C91860371F",
- "metadata_key": "07D64CAB902E683E5C6B3BDC257F2ECB",
- "section_mic_hmac_key": "01108F72B3239D936073126F7DA309D55A68509567CABF6F7742DE6B12154D8C",
- "section_salt": "1C6B6EF087BAD3E1CF545DF1A9A9CE99"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "38E22156A8185E55F335A47037F8E2F7",
- "aes_key": "6CF70F3F165CE847A9C63F50D8547C21",
- "data_elements": [
- {
- "contents": "4D8D46ACD86C6961C4094DCB13D4E916F3A83CF8",
- "de_type": 508
- },
- {
- "contents": "C4688F335D",
- "de_type": 78
- }
- ],
- "encoded_section": "559013CFE4D705FD9D6A0D8079500CE2E92B14911000C625AEF2F9BD3C56372C63173571103D9002D5600B9D26063F4622FC6CECBAB259B3BBD63F3B3E304465A897B891B7DB0039B8BFEF525691FA300DC955A09E17",
- "identity_type": "trusted",
- "iv": "33820EA628D605D7F5DF12E15E0F202A",
- "key_seed": "401411AE44BA8795773F4EF0049F07051344BFE4C7255D4E7D975C63738B27E6",
- "metadata_key": "1B003DF5AFD3B438F2D367697DEBFCEA",
- "section_mic_hmac_key": "23BD2994A6DC828B1115E7CF2D7A2197ACDFDA21D8030167F845E9A42461EF51",
- "section_salt": "C625AEF2F9BD3C56372C63173571103D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4A5CE7E83CA2E1C0B57C8E06D0E6F742",
- "aes_key": "F085865AF5C9A124298272AAC0C459F4",
- "data_elements": [
- {
- "contents": "EA412396D4",
- "de_type": 360
- },
- {
- "contents": "5B36B6971907900EA4D176E7F96C99C6075CB81A",
- "de_type": 151
- },
- {
- "contents": "7672075A67196562CFA6A05A1C9A803FAC914E665661",
- "de_type": 669
- }
- ],
- "encoded_section": "6F90135C5E8470AB022D8D60D1362A898BB18C91100072034CD97D55545F76310C999D548F7190014D3248EE4C4B1A52F45BD578C3AFDDDC2F3213EDF205D719FCFDD964A9B580DE8DCF620F5E3B7386389CD569E2CB17B8BA70FF1B739080481A336376DC599322D9952717784ACDA5",
- "identity_type": "private",
- "iv": "6890DDE4612EEFF53CF9BAA9A0A57B20",
- "key_seed": "86589F54F57C9F0AB5245C0F6635B611F802EA256A94441B12160C2605AA2D1D",
- "metadata_key": "DDFA0DD062ABE2CD427A72F1C1F81DC4",
- "section_mic_hmac_key": "0FD9C77FE8E953E2B8526DA6414A2857E02A4A3213F2BB484799E9CC977A2219",
- "section_salt": "72034CD97D55545F76310C999D548F71"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4ECC54C7A3A3EA811EB6C2D753C41C19",
- "aes_key": "5EE028B37AE8B25ADD419427E31E23AB",
- "data_elements": [],
- "encoded_section": "3790139322D0756986F1FD123C6B04CDF3EAF091100057FFD16AA68473D0582E5BEEE3868910900201234FC414E25E21A3EFACA4A5E5A999",
- "identity_type": "trusted",
- "iv": "87F0BB8A2FCD03EFEE2AC5C1453F55F0",
- "key_seed": "598FF7D9FD66BA3E660DAEB8B3E5C6C82FA6AB758D3D1076691C4D0542EF067F",
- "metadata_key": "9857B87C8DFE289C01F9F9708B692FBC",
- "section_mic_hmac_key": "1F7BC70DC4FB9665A7E21929DBC300EE2F91AA7A7AA775222A26149F60EB5345",
- "section_salt": "57FFD16AA68473D0582E5BEEE3868910"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C73AD85B0EF01E161F1E7764010C1EA5",
- "aes_key": "79E30C89ED65C6F40882254563A75E17",
- "data_elements": [
- {
- "contents": "18609C222BA9D3D5DB036F555AB0CCEC09ADE5179EC2CA9F",
- "de_type": 99
- },
- {
- "contents": "EC187ACF3F4C481BDF000D552EB3",
- "de_type": 658
- },
- {
- "contents": "BF556150F61584A4CF7A5C624E",
- "de_type": 383
- }
- ],
- "encoded_section": "7290139ED0E2B0FDC39CD26D661DFFF11234169110001E20C1E816FA9F2D34542BD1BCF7ED9F9004EAACB664A85B0349C8431A0EA7D7E87FEB22B32F30C074D0285840584A1026F19E1DCD4BF133020C1550E42725C77B4E6E60DEEB1A354FEF5E481E41075F40D790546805FDB5F0CF6EB7D4",
- "identity_type": "provisioned",
- "iv": "C430A8DCAED7C039B0E33CA4FD4F093B",
- "key_seed": "EF0BC6EE51E35093FA4C893AAD43B1951B91C650EF6D401C7C03975AA916A507",
- "metadata_key": "0FCBFF2F8DA457F6279FB66C50203DF3",
- "section_mic_hmac_key": "BC9E4B32DAB0A23BF9FBC776DD2AD5530E1AE56337FB5DCBDA1FC45E5C34598C",
- "section_salt": "1E20C1E816FA9F2D34542BD1BCF7ED9F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2B287CE2F08F4BCCBC505B6FB2ABEC15",
- "aes_key": "A2391D2B8D95B3B22079BAE241145DF8",
- "data_elements": [
- {
- "contents": "2A6C741FAC614B55AB5B",
- "de_type": 746
- },
- {
- "contents": "B82E6D8CFF3DEC1962D2CF4134A7D30C04F4A3",
- "de_type": 972
- },
- {
- "contents": "A03D72AC4A8A200BAF89714A92FC5BC3753529",
- "de_type": 271
- },
- {
- "contents": "C89C68F269FCE8",
- "de_type": 462
- }
- ],
- "encoded_section": "7A901325D43FF30DB60387156458D420A2551C911000F8647C38B6266104D6ECE9E5CE7E879190015383810EBB8184B419130D8EABE9C911D7EDF89EA2A9008D98C5EAA9E8D2B550252267595D53A0BC8E7AB281846867F6A54FE0A048F208D38F660D69E6341DE617223D80A2D2B96947630EBD69EDE868FBF659",
- "identity_type": "private",
- "iv": "FE04A94DEBB042153B2C96CF5D4DE41F",
- "key_seed": "F37257303C8330286B67468749200BD24155F76D9EAE8CF6F4A1B11632F9461E",
- "metadata_key": "7216F11C49F946FEF51139ABE587B632",
- "section_mic_hmac_key": "4C21C99F1C75A9641AE865D73D38BAD22B11A67009ACDFD40F8003D80CB6ECC6",
- "section_salt": "F8647C38B6266104D6ECE9E5CE7E8791"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A1133D9CB487CF507E85AB45A5225A3B",
- "aes_key": "E2BE917DE14406C0FCF09FC4FDEE1FF5",
- "data_elements": [
- {
- "contents": "71238E",
- "de_type": 839
- }
- ],
- "encoded_section": "3D90132C5CB47E0A288D59348CA9F66DC3AF9A911000523C6B069BD40FBB9C6BF1C8E10865E69002AC2424CD59DA02E42EF7E44168236A9C325B591A7DE3",
- "identity_type": "trusted",
- "iv": "FBC8CDB92CE0F89BBFF8C1BFD00F6541",
- "key_seed": "F7982DAFD3732E72F79D778A65DB2174686D0AFC94A8FDD356DE6B74B0917497",
- "metadata_key": "ABDAA0345C02A6AF84BBCCE12BDBB38E",
- "section_mic_hmac_key": "55EEAD0385A2BF321ADCB7C14075438ABB04AC96A68B93A9F2C53490431561EE",
- "section_salt": "523C6B069BD40FBB9C6BF1C8E10865E6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BB53EC5F4F7ED20F852C88CAE0D7D2FD",
- "aes_key": "27166277389D14C33C6EC6FCF087D4DB",
- "data_elements": [
- {
- "contents": "8CAD688B88D91C820CC9DDE89763",
- "de_type": 976
- },
- {
- "contents": "8430D62B44C83C85BDB6697D00A8A53518CD8DA7FCA68AA1AD6E",
- "de_type": 166
- },
- {
- "contents": "7A0FFFA6068B33AF9AEB4798863FCF",
- "de_type": 957
- },
- {
- "contents": "7AEF9A74325D4192B1B99E704D9FBDEAD1C027388D8F3B0E7FC72BE44A",
- "de_type": 533
- },
- {
- "contents": "0AD6320E89875A983E2B1507A7F212C5AFE5",
- "de_type": 177
- }
- ],
- "encoded_section": "AC901330A161EB463AD006A1F925054A3A0F8A911000BB38DF610A30BC926FC6C4582D37660D9004243511EB4B95CC7EFF1E37F4559CBE73254459AB1A8AC32FDE866F96C56D5299D575FEEC58639D153EB6466758D10465A65674923DD5BAAE80B5D400AC70B2965FBA05961B31D9C3CE295361741B5DA19C60A13C103B0DEC97C664FC391A1A105F6E8A4FC70CA84EC842DFDBF8B6A86B21DA28E828F78F23DD27F8EC040A6D26309D9BCFB3",
- "identity_type": "provisioned",
- "iv": "E5930F69FFAF33C673D10B1BCF790387",
- "key_seed": "928F3472A71D094F7842799035E83349496DD9963F46E4587FC0BEC618BC68FC",
- "metadata_key": "0B9BF0598FA164D48423A5A07C65D3FD",
- "section_mic_hmac_key": "FBCAF9F7E6996F5EFF05649E26A30814CF72CA895BC9B6B19B21BD433845D247",
- "section_salt": "BB38DF610A30BC926FC6C4582D37660D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "D0BA76FCD350C9F9F7951F23F2C51481",
- "aes_key": "35C13E514AD41A4D733FE99E7D1AD0D8",
- "data_elements": [
- {
- "contents": "1D84D057F7999067EA441E2ED2E55BAAA302AD",
- "de_type": 651
- },
- {
- "contents": "D2C79A4B046101959D",
- "de_type": 695
- },
- {
- "contents": "1B1C33AF7CD34DAA62A8B03451EAB120EF9BD2B9CE24D8240CFEBEE8ED",
- "de_type": 566
- },
- {
- "contents": "8C874DFF95B449C595963601D5FDB2",
- "de_type": 315
- },
- {
- "contents": "E805B80A4D8759A73DEBFF39B881152CE26BC2D440",
- "de_type": 42
- }
- ],
- "encoded_section": "A2901311EB79E0E8D59F0B3C047B92D8CA72BF9110009A2C839A95308FA66A28E37D5346161F90015F33031A6C9AAC27A4B2179E39E69DC705D70EAC406CC05F02C776643CC00D087180158DE32FE190D0DEB2D2DE6D2DEA033605D6CCF77D5207F406C872A1CA1DC19D97DC4FF2D4C3B6CA4548C31DE16C35EEF910818B982851FCF6DEBE5C4C9BA458D2AA51F3B55A5A909E2268580D8AAAAC6FD0ADFC16FCD8BADB",
- "identity_type": "private",
- "iv": "14105F10774008066E6F963762594EE2",
- "key_seed": "6D3436A21EC875EE57134E1DECAE0C2A3B1496945F8D1E11BB96B92F7D47246C",
- "metadata_key": "888F65EDB3AB4C3A68E0823136F3D256",
- "section_mic_hmac_key": "A7498162FC9BD07510499868B87AFF66AEB0536EF48116381D1CD09EEED03935",
- "section_salt": "9A2C839A95308FA66A28E37D5346161F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "08B3CEC91E020D1D4484B0343BAAAFE3",
- "aes_key": "B32745DAAEA6C4E7D467DCC28E7BDB1A",
- "data_elements": [
- {
- "contents": "DE5A73510005E7983B15546A1C8978D6",
- "de_type": 238
- },
- {
- "contents": "6551FCA60C84C5227D009AE786796634EF3DE920CDF7CC",
- "de_type": 993
- }
- ],
- "encoded_section": "64901365E99B278344696A56F13E914616080F911000E05F4117821F694AC893206AE14EF9C69002F00FA0F6E4F18BA8AE1B88AFFED9C59347B2777757E02B7763BB589A19E1718B87E0E429B4602770861BAD7938B0A6AB0394EFA1E5D06492404993B0CF",
- "identity_type": "trusted",
- "iv": "2931F4D5430BD5F2392929FFD93A2BDE",
- "key_seed": "0BA7DFFE886190D25ABCE6232E5CBCF588F071DFA0899C9F145BC5480061F522",
- "metadata_key": "5B1CA7665FA68A63D48E11A291B13E15",
- "section_mic_hmac_key": "871BEA00E0DE1FDF73CE65FDDC64963FAFB2DB32842BA39D1B98C0B326C08CFB",
- "section_salt": "E05F4117821F694AC893206AE14EF9C6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "526A3175C83BD7923662BE998A0D026C",
- "aes_key": "48DBA531822D93F3D6FEDA0CE7FF67DE",
- "data_elements": [
- {
- "contents": "8B52817C4B3FAFEF79A65D",
- "de_type": 670
- },
- {
- "contents": "46",
- "de_type": 801
- },
- {
- "contents": "E1F3439D0AEAD4CB9F77",
- "de_type": 671
- },
- {
- "contents": "6DF3745B08B4FEF27F336A",
- "de_type": 288
- }
- ],
- "encoded_section": "649013AE841A17AE95BD4355024766953D137291100031E1FF9DC6275DE2D6CFFDFBD4ABF2BA9004DBA83D7B18E1768B0A74F4540B159871FB9C14BE48F656157533EAD1E5ECC8228A55124E283885BC099481EEF4F1913D09B1E3D5B603D420D5E41EB331",
- "identity_type": "provisioned",
- "iv": "D4B8B04708827F5B94AD1C4B4AAD0502",
- "key_seed": "65F30FB0C0DBE40E8B6DB35012BD4AE37FEF2C62A90EAD5F367CD41D0B4D06E2",
- "metadata_key": "E4FBEF567E6D11D3A9C21CEF8687354F",
- "section_mic_hmac_key": "61B7897EC3760B6EE3E94E7EC85D1BAC7891D62B9C958EB6754F349DF51B56F3",
- "section_salt": "31E1FF9DC6275DE2D6CFFDFBD4ABF2BA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "607FCD5903490C79A012D2CC218C8E14",
- "aes_key": "1B4926A4AE50E442685876D28E738DC5",
- "data_elements": [
- {
- "contents": "92193507655A3CFC554D76AB",
- "de_type": 703
- },
- {
- "contents": "3E93C4EF1F7BB3773E6DF1A44C64A63EBBB84CC12DB6704A2512",
- "de_type": 863
- },
- {
- "contents": "281F78E0212C7ABB",
- "de_type": 785
- },
- {
- "contents": "D605E7E6548983FBC54C139E2792F218A1",
- "de_type": 674
- },
- {
- "contents": "56C18EA4A5CB10EC724D6017F192CC06763AB5",
- "de_type": 874
- }
- ],
- "encoded_section": "989013929D8225107A0F13E5F33951FFF57792911000BC967854BE9AE8680BF37D35FC3247879002F417C437991FCD5F8830F88C9CC8ABD364588908090C416784CB0784383558C9DB80A3EC0945B122D09DDCE9718ECA2DE69F0A4E444DAF5432ABC60AE72624996EBCF0D5D4B3FEEBD7C93DB5DE4FF19BC16971B4BD672738994696EE1EB9020448360ECB9E5B4D14BEDDAACDDDECCD2ECB",
- "identity_type": "trusted",
- "iv": "18EE01B860AD7549AD1C27D0D1719333",
- "key_seed": "BC65AB7D447AED92E7AF15FBA242DE64F51CB5505C7538DF7606E5BBCFF251FD",
- "metadata_key": "4EC192FA9236683FB8EE6098F5AB2058",
- "section_mic_hmac_key": "0BC73A07FD0D047E1F83EEF451E5FBA8DBAACB166B8BB3200AF94CF39BC391F7",
- "section_salt": "BC967854BE9AE8680BF37D35FC324787"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "1F4428A4B286CB63540A9B96DD5755C6",
- "aes_key": "E7AD8FAE2DD846979CF83C2925603C18",
- "data_elements": [
- {
- "contents": "5FB025BDB59D9975EFC6EF5E4F77",
- "de_type": 266
- },
- {
- "contents": "A3ECE156745E1E9DDBB39696F06D01B045E3A4A0948C27B5B38F2F",
- "de_type": 293
- }
- ],
- "encoded_section": "6690132001AABFE31D558D81FB2EACCB49044B91100055A992A831E3F554842A50CC1A0F6FD59001B2D52D0A60F5AAA760A47640C2A4BA9F66739355B0A13BFDF1262EB114C6582CDC7186A33416FB0DD4A59F72E83A6913259F07029F9A9B17C79B1CE9286DAC",
- "identity_type": "private",
- "iv": "3C257D68DE3391B34584EF9F5617E9BA",
- "key_seed": "67F1DE60563E3E0DECE3191A8B38107DD8AFC36AE838AC1667D9FA2ABA01B192",
- "metadata_key": "5DA221E4FBF5632037F2C38760158865",
- "section_mic_hmac_key": "80F62DA2E814A7FC4A5729E1347BC6E0E1ECBCC2A69E94A31201CBC9CA264C71",
- "section_salt": "55A992A831E3F554842A50CC1A0F6FD5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0B6FAB3C87525BE1EF6338CC7B44586B",
- "aes_key": "9D8AA7E968ED807E12A1BFCB358B2500",
- "data_elements": [
- {
- "contents": "A8F4C5FF",
- "de_type": 250
- },
- {
- "contents": "393C6F0B53FCB39895D4673589995BAD266D8C1F37B8EFAEDF715C5E",
- "de_type": 891
- },
- {
- "contents": "897DD504C7FB519F408359177CA09EBB3285A8D07C047DAEFCAAA9",
- "de_type": 195
- },
- {
- "contents": "223F0E3959FFFA4BA2C2EF990BE541",
- "de_type": 109
- }
- ],
- "encoded_section": "8C901388894975700558396618D4C5B6DD75AA911000976919A685F1DB72B863D392566395789001BEDDCCFBF8B26CDCCEDF6FDDDDFEF284781D90CF4C669B8E712ADE147F3A055C6927205B7751438812A0AC612BACC422F753A248C921F763A4834D260F66D4C3BEE187B5059BA90DF97BB8D88B8D5EB57B349AD5A5A2C0F4E8048A3903495296C0946F8FBA",
- "identity_type": "private",
- "iv": "4EB6A4C8E8AD7A198198AF5B3F157ED6",
- "key_seed": "7FF31B2DD4EF85589AC7E8DBAF320DF047DFD5383F762946277B9514C19B957A",
- "metadata_key": "6DD18E7B8BB136DAF7A00E03A68BA11D",
- "section_mic_hmac_key": "32596C515AB3091AC5C0892934243A0E134A5DE300B5934134ED4EDF0551CE41",
- "section_salt": "976919A685F1DB72B863D39256639578"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4840B5430E2C99864061A0B7BC506FAC",
- "aes_key": "305CBBB94EC7BF4B1575082301513A20",
- "data_elements": [],
- "encoded_section": "3790139F09A81379D3DD32A26A50B29B791D7C9110003BAC436861F7119425262BA2F41ABA479002871FBCB559E18575502D8A4E205CD26B",
- "identity_type": "trusted",
- "iv": "9523644A9EC5EB4D03F9682F6B71EAFF",
- "key_seed": "B7AAD921C1C4B99238DF4FA3E2799F6AAE57B1189D6E886D38DEE52DBAF17272",
- "metadata_key": "6159AC2C4F82C220C822A0B02382AC52",
- "section_mic_hmac_key": "B0B2F95C1E37B287F9CDC028DEBB10B717883252404112A6E2A0884F4A39E2B3",
- "section_salt": "3BAC436861F7119425262BA2F41ABA47"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B0DD88926A85214061D588D046C40D39",
- "aes_key": "0A9D24DA0E9CD688FEE88EEF7105D736",
- "data_elements": [
- {
- "contents": "E1CC37DC8F60ABE02709940B49FF8CB7B467E95F",
- "de_type": 706
- },
- {
- "contents": "1E743AE7B4E54237E661B287998DC1303A",
- "de_type": 87
- }
- ],
- "encoded_section": "61901372401FC11144842B442B965C2F4409749110004E00BE0F929E9D09AC9DD996314507AB90015154576D8110400CD950E8FA2AF870E462D4FDF664B7F9E099BA14A7683B729FEFBAEA36A0B1D1F76A2D4149FF198765456514682E5CDB01F75F",
- "identity_type": "private",
- "iv": "A061006730444D3FE601B1B9A96D5582",
- "key_seed": "C7E8A62C5DB5B1E6B07C55D4A3171C26B346BFD476CC4D835F52C40FE4FACF9A",
- "metadata_key": "C88A3F7A29198F2E0BA655DEAA8192B2",
- "section_mic_hmac_key": "9BDF103979B01A474F89368E167707AFF7C35913263B5709CFB61FA4BC63732F",
- "section_salt": "4E00BE0F929E9D09AC9DD996314507AB"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3E57C49387523CFE6CDAC323282CB768",
- "aes_key": "828E644A59749E1081F44C309EF285B5",
- "data_elements": [],
- "encoded_section": "379013461457D7D8208806838F38643B30805C911000602E288251DC86DB4FC88DD50BDBB5B79004E1385E22902422B0DAA09CFE046D4480",
- "identity_type": "provisioned",
- "iv": "984B98EAAB7855E8E58B90BE045A98D4",
- "key_seed": "B2DD1B6846A6C730D35C7DD5F7E66EF0DECC00BC6FC4BCDE5AF7B7A8CA29927F",
- "metadata_key": "5F47855ABC1C9E6F40C278922556F9B9",
- "section_mic_hmac_key": "2F811707CCF2E89920CCD2E8AF5712BC621F3ADD42AC4C4E945D667BF519E7B0",
- "section_salt": "602E288251DC86DB4FC88DD50BDBB5B7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FAA87B7470D9B709BA24C03C0556B201",
- "aes_key": "AD00E01086C81CD4ADF2F225D4EC40CF",
- "data_elements": [
- {
- "contents": "C6710B42",
- "de_type": 259
- },
- {
- "contents": "B775BA2BC90617E3A1D053C887C95D93928D732E01C596B085",
- "de_type": 518
- },
- {
- "contents": "C1902A",
- "de_type": 542
- }
- ],
- "encoded_section": "6090136EC2E8301A171621686D256328800A5391100086D384F2BE92C175DBC065A4441DB88C900412860361D567258D47AD2373ED132B0D455A36D52E13E8A60A4D14137633019A9376150FF9C5C3E876A665940CBC3159D26A6DB2A7C726FB7B",
- "identity_type": "provisioned",
- "iv": "4019E22DE255D0AE7010AD5142D1BFB5",
- "key_seed": "45C69BCAE63391CA52F9D2C1C04E9699727876ABE5041DCC006A68270893A46C",
- "metadata_key": "CEB8DAB98EC23439D98C713AF4F2D4D7",
- "section_mic_hmac_key": "C2DD8B720D968C3A290A9C2038070F134A91E53C09F6214682B7C8D40A0FF543",
- "section_salt": "86D384F2BE92C175DBC065A4441DB88C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "185871AE8F13E0BC01646BBE8CD93E7D",
- "aes_key": "3F4388DB5F2E556979CE2D22B9FF45E5",
- "data_elements": [
- {
- "contents": "659643C0F6B85BF24446E841",
- "de_type": 119
- }
- ],
- "encoded_section": "459013A62C3DC6BD3EFFBEE575BE8D47E584E6911000C87758744B4E7C881111F2CD34F4D7F79001DCA97B6125D1DAC4E21D5D0D2E7A986FC7867F78551EC031B808FE7D331D",
- "identity_type": "private",
- "iv": "715E94C49314243FB3D9438BE0B5FC4B",
- "key_seed": "B19545CBC53FECBF01DF0794B5E2BBE1FB077D963E6B5AAF7BF3B41B09655E55",
- "metadata_key": "8A571C405199BDEBC9E0A996C066BC98",
- "section_mic_hmac_key": "EE32E0FF4AE8937E99101C31545DF832EB4424E20F6FFC90DCF47610EC6D4B1F",
- "section_salt": "C87758744B4E7C881111F2CD34F4D7F7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C4C2159CFB937F5A7A2FFE48D07C7C70",
- "aes_key": "E616EA700DE6B20016EFD092679337E6",
- "data_elements": [],
- "encoded_section": "379013F8000289CA6BA6E4115BAD0BAE228BDC9110002F0E0B5A5A511C3B0DD2E02FD72510DE90013F4EFCB8C2CB33A2696F2D5405E460D3",
- "identity_type": "private",
- "iv": "26BC1ECC5F5D6B109307FFEA76907026",
- "key_seed": "B872DAA9F9DA74E0D37859F20901854233A6C6E66F537D404A6CDF32863413DB",
- "metadata_key": "B86BB6F2B8B3E89B4A3E2672BE4DE433",
- "section_mic_hmac_key": "DF0F2BDA3016890F67FA244C72A22AAD605BC9C8732B812826B39C729DFD2858",
- "section_salt": "2F0E0B5A5A511C3B0DD2E02FD72510DE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FB11A8102A3D19E567CC0EA7A856BB99",
- "aes_key": "D8F09716F9CA40B2576E70575E6788D4",
- "data_elements": [
- {
- "contents": "7489EF6D168E7528A568454A79B13C99051EFA8CB54D790A676B2E",
- "de_type": 144
- },
- {
- "contents": "3D489FBBD523E0F6545E9FCABE2FABD575CB66",
- "de_type": 278
- }
- ],
- "encoded_section": "6B90137A6B943C979446674641A75443D0FD539110001445E273F719B3991BC855505C7524CA9002936D5265ABC1014D62D7A0AE1232524F648A170154BB721C65A99DCD7D3B8B31118047E8071AF25223AC9DA6DA3275B5AEC1DC81074FA85C3EA6BE8568E008793268E231",
- "identity_type": "trusted",
- "iv": "C41905D73CF82367AFDA74A2171728F6",
- "key_seed": "3D0D1F01B8DDA465B6B3C07A589C94E3A1272651DB2CAE2038B1DAC1265418CC",
- "metadata_key": "B5948EB880BE8DF16056872DDB37723E",
- "section_mic_hmac_key": "86D2D4079CB6D1A6E43AA9CEF8B9830580749A245457F823096FE7B72BF9E7AC",
- "section_salt": "1445E273F719B3991BC855505C7524CA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B6EC9A6945B754FAB8D7FF959F03997F",
- "aes_key": "9B4980C3EE6BE117259F7B1377A31A75",
- "data_elements": [
- {
- "contents": "2A966E923416C51DE8CD04D2FFBD7129FA00F9B0",
- "de_type": 367
- },
- {
- "contents": "0953BDEEC1AD8F034790",
- "de_type": 452
- },
- {
- "contents": "5734C9069ADCEFD63F6DF5E815",
- "de_type": 21
- }
- ],
- "encoded_section": "6A9013D8A4420DA699AA047DA37216590D7361911000193B30E46CAAD820AAED6A871B0DDE3D9002E1DDBA0DC773691E6F5E35467C16D5B90BE6B4794FADFFB35D17D5959F7DA4E0508BA05C7A0E75D733827A23241815076553276D897F9D7F9857C88BCD15251B6A59FD",
- "identity_type": "trusted",
- "iv": "7596E4CF2D76B0B7B6D57BB31536794D",
- "key_seed": "10CDC0E8F2081B6383B5E770324E8A2A0EE7BCD33A06F4AB1C13CC441B1576AA",
- "metadata_key": "8B6C66FB4F911DD9D302B58389A38E2F",
- "section_mic_hmac_key": "02435909F7FC7DCF6AD2C5782C4454EDDA6825A3F03E2FAE631827EF23C75802",
- "section_salt": "193B30E46CAAD820AAED6A871B0DDE3D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3BE86057455C4EAF637B2E2D5A3D203D",
- "aes_key": "E49BA1CF3158EBD91ABCD623CF652A88",
- "data_elements": [
- {
- "contents": "1D",
- "de_type": 789
- }
- ],
- "encoded_section": "3B90134A40A37A0F1F7FFA41DBA69CF401562B911000FF2F1817375B764380DAE5464D94377890017B523500C616F3CC02DB071A8FEDF8A4A77EEF03",
- "identity_type": "private",
- "iv": "D0B1E3FD976AEF6BC9764DD4C2C77D9F",
- "key_seed": "F6C21731E2A651A2A3E69BDB7628AE4D170E03F1290FF07E6B5D53EC4B3A9E07",
- "metadata_key": "A67ADD8BB31728F1CBAB049EA30784D0",
- "section_mic_hmac_key": "32D1CADC23733164A58E0DFD391F62623DF7CBA2B2C482B97E824837F126A2EF",
- "section_salt": "FF2F1817375B764380DAE5464D943778"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F835784D7AB18BA808A7F69B57D4815E",
- "aes_key": "1BA538EB97A7B39A85A8AE30F3E7F74E",
- "data_elements": [
- {
- "contents": "3EF58FCB910F",
- "de_type": 471
- },
- {
- "contents": "B7A97511C7241A87D93CEC34DBE0",
- "de_type": 781
- },
- {
- "contents": "3B7873329F6042E0",
- "de_type": 591
- },
- {
- "contents": "4D",
- "de_type": 155
- },
- {
- "contents": "8B19AB",
- "de_type": 459
- }
- ],
- "encoded_section": "669013321C3BAAF7D8D726DA7B24CB448A7CEF91100060BAA8C3E9B5DE735AB5E20549288EEF900459F48BF2DA6EC0C9509A54CD9EAB469FAEABDB1C0469C4AAE88E000102F20F0410588ADC95DC5CB9F1E618CD9B5D7282AE636F046F0BAF41CB330F90231371",
- "identity_type": "provisioned",
- "iv": "61B4EC1132186567C1992B337414B65A",
- "key_seed": "82DB684D3D3EAAB31A410F59959F697C1A3F06F0225400F7F93973B38E900F48",
- "metadata_key": "670D421A6387FAE7387E7687E683FF91",
- "section_mic_hmac_key": "4B60F9DB5B3A4C383A3F7D15A90CC70496A30476D9158CD07832E3B34430A386",
- "section_salt": "60BAA8C3E9B5DE735AB5E20549288EEF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "97AC9B949680B2F11F1C07562473BC5D",
- "aes_key": "8893DA49A2A51A183F1A99A688B11CBF",
- "data_elements": [
- {
- "contents": "B7CFBC4A38F6E5C1EF5529C01E0EC57DEF14",
- "de_type": 487
- },
- {
- "contents": "76F12E3859EAFC1C47332C188435203DA7BAA2C11219B3287FDB",
- "de_type": 699
- },
- {
- "contents": "CEAA9D",
- "de_type": 474
- }
- ],
- "encoded_section": "6F901300C1D813793E3D565D7BDF96D4729AD1911000D87C74058CEB77E6047D8FB6FCDE2A84900462BC3ACC414A1075616F631658C6F59BD8313C6D040F237912A83C8391E481F8260C25C001E842C5CF8C9899A39E81497CD14AE3B95C42D4613D5B94AD5A43FCD06FFBBB880771D4",
- "identity_type": "provisioned",
- "iv": "31692EECD347BB8B790FFE491DC6AA03",
- "key_seed": "D7DB5F3D01EB449493F604FC7625AEA837CF2B59C099BBA604A4289E7D130F3A",
- "metadata_key": "5B0B450F9073E98F2713D56B6F8B6F45",
- "section_mic_hmac_key": "8CCD7DE04D0D174F4071227616AE28B1541FD3DCB20559E49DDB9D7E1E61DF5C",
- "section_salt": "D87C74058CEB77E6047D8FB6FCDE2A84"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E702551D59055A4C268DE48352D1D471",
- "aes_key": "B2C74066FA0433B54D2C41E23E6EF2A1",
- "data_elements": [
- {
- "contents": "C87DA9FA2AE6",
- "de_type": 753
- },
- {
- "contents": "0F09EBD5E1FB0403D5FB6EC758FD99969CD51B",
- "de_type": 938
- },
- {
- "contents": "68",
- "de_type": 659
- },
- {
- "contents": "EE7C4403DFDF257703D7307BD90FA19F1234",
- "de_type": 367
- }
- ],
- "encoded_section": "6F901313354100352D54F8E69864F4D81E5F40911000D31E9F9EB135D9B417465F14DD616CAE900241F17700C7C522B251D69077C5D83A57C91C76E9608FF7AEBAA9E6D6DEB4FBB4C0FA7A846161B449867B0DEF8857575DB871772C1A32A50C3FC8B5B7BFCE1F9E863B0B3BB540A538",
- "identity_type": "trusted",
- "iv": "E9CE72D40C0AD1AB24A01A82F2A07826",
- "key_seed": "53B877350CAB817BBD44D7EEB318798EA7BBA2D4A1A71D89D36716AE92749BA2",
- "metadata_key": "99976B723F002988F4F55EB36FEEF71D",
- "section_mic_hmac_key": "99808417006A0BC9AEEB5E57189464625982B170D83E339770A664DA612A8FA2",
- "section_salt": "D31E9F9EB135D9B417465F14DD616CAE"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2ED0C092724864890A6F1F704D800668",
- "aes_key": "DE9D2AF9D5E73B5DCB99478AB10596E8",
- "data_elements": [
- {
- "contents": "C60493B51521D08E1301A6BA8DDCB0B8C80EB593EE",
- "de_type": 626
- }
- ],
- "encoded_section": "4F9013FB0AF3D967DD7A4DB45338A490E57ED3911000955B8212E6D3B3D51F527D3FA95E5A7D900137E439BCDE00D86C1F7636F036F39C1E747B84D893FF30148A60A0FED2A9630C05074B851C56CFBB",
- "identity_type": "private",
- "iv": "0C778E8BBE426243CCFAB25E5FAD4AB1",
- "key_seed": "E52C0B2498CB2E81CA1D7826956E5CA96643FF387FBCEC351EB3E573E8267E6B",
- "metadata_key": "89100169ABB76A810E0689FF4E1CB32C",
- "section_mic_hmac_key": "1AE31170876F62388380093D8BBCF2C7EE39CBBFEB704B3FACB3AB58FA218A0F",
- "section_salt": "955B8212E6D3B3D51F527D3FA95E5A7D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "97D8796AAFFFF0391918C4D843EC7182",
- "aes_key": "2DB81BBEEF3CB201FED12F870DD1A6D4",
- "data_elements": [
- {
- "contents": "AC7A11",
- "de_type": 42
- },
- {
- "contents": "47F36D",
- "de_type": 476
- }
- ],
- "encoded_section": "42901334B6E677BB68B303430CBE489918DD1A9110004FC550638C733514F55D80678B35E8BF9001D6527838298D839E0AFB36258BC8CBDA19AC72F0C0F1C1D21D1FEB",
- "identity_type": "private",
- "iv": "88D3B3269364CFD877B4B349E5232F78",
- "key_seed": "D2721BAEDB71C77EAD4016BE0B47482E6FE7ED6D8BE89ECBF2874DC8379532B7",
- "metadata_key": "E6CF02F6881821F85F695322B753C232",
- "section_mic_hmac_key": "23BCDEBB78C2D48D14441FDF8E69E3419DED64FF26E80707BC4D74C23E9985EC",
- "section_salt": "4FC550638C733514F55D80678B35E8BF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E29DEA8F8EB14530304F3980D3B1D734",
- "aes_key": "36FCBB41B48F5DE8FAFE45582F12BCAD",
- "data_elements": [
- {
- "contents": "BF2DD9987F4FFF036F7EBEA0",
- "de_type": 648
- },
- {
- "contents": "F6739557F6F35CC9D3",
- "de_type": 600
- },
- {
- "contents": "7A461FEDFE239F482570B8",
- "de_type": 773
- },
- {
- "contents": "755576B7F701C110D30DE8A8A6055E861330AD3038B48369",
- "de_type": 910
- }
- ],
- "encoded_section": "7B90134C1E3F6ECC9F2A87270584D6B556739B91100000B42582A3DDC746C8C72882FC1E3CF29001E801CB59638B55AD760247985729C427C701BF1FC270D0846820E3F3CDAF26FE33F9C42DCCE3B580CD8ED52C8C84A1497C02B8CF858E82598DE51CAE0A9222FC649F0F74FDEAB2980ABB47259919E6AD0E5BF8CD",
- "identity_type": "private",
- "iv": "45B269C614463C479DAFE5D92A9EA559",
- "key_seed": "C35089F1053EEE4A91E2931F7A8AC693D00AAE4A81E7175018BEE21CBAE51145",
- "metadata_key": "A458B645925159650706A2E4C8BFCB64",
- "section_mic_hmac_key": "668DDB981A4777D6A00612FC5AC0B10287C5E786DEE8A47BC127A87734A51AB8",
- "section_salt": "00B42582A3DDC746C8C72882FC1E3CF2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "2A1A6C8D295ECF8C0202668F1489A414",
- "aes_key": "28CC2DD441CA8E4B7BB065E70D54F066",
- "data_elements": [],
- "encoded_section": "3790132CE9BA72A592AFC9A154431AD9BF678A9110006F7AFAA6E74352E98FC6F26F271B53A79001C1E8B3BC3B1DC537843A058B3CFC77CE",
- "identity_type": "private",
- "iv": "CEB816A49DA26AB4B8D0DA3F35D84FD4",
- "key_seed": "33ED4D742A7EF0E3B7A7A3A6DFC520B17D56970B3882F8CE0093A65364F26BAB",
- "metadata_key": "D013A0446A6D5925AEB112989FCF8B6A",
- "section_mic_hmac_key": "A5C57E34BFE28F270E4D4DBFEE7B2B439825F138CE6246EF84DD1A1B362ACD34",
- "section_salt": "6F7AFAA6E74352E98FC6F26F271B53A7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C57C5AEC61B254B68BFA1263F09D08ED",
- "aes_key": "37606EE34F9AA21C044064B8C1A2886C",
- "data_elements": [
- {
- "contents": "B11514CC76AABC274DF8F8C6CFC2ACB4E22B53",
- "de_type": 472
- },
- {
- "contents": "",
- "de_type": 457
- },
- {
- "contents": "508791F872F0B674D72C29",
- "de_type": 688
- }
- ],
- "encoded_section": "5E9013C8A8A7AFFD886F274CC65659F5A059E1911000B4610CB1B2740CD7D6BA48AE95773889900401416AF0F3FF6BE99E89149A173F289199DB5ADBE086901F6BB884EFE7B8F26B8447A95553BADBA369BFA1FC97FA8253CE897B05AF5679",
- "identity_type": "provisioned",
- "iv": "7745CE454FFD689BA9F97F294D8A88A8",
- "key_seed": "0E252068D453031E6D3E8512F54A93023AB47D40DF65477E1799169584D49A34",
- "metadata_key": "ADD4C2CE5C0675D81B04C0CBA49C24F8",
- "section_mic_hmac_key": "A1BE55F257B3AEC15DB0CBEFE6B8C9EDF5EC2D5D5D80A2B8365C62E03A18FAF3",
- "section_salt": "B4610CB1B2740CD7D6BA48AE95773889"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "010247C596F6FE045EC36550B5CF9BE0",
- "aes_key": "56D59B20C8A02E3EA56FEC1F085E6B43",
- "data_elements": [
- {
- "contents": "71885D121CE06D7983CE03903E41",
- "de_type": 749
- },
- {
- "contents": "6429B148C4524881",
- "de_type": 197
- },
- {
- "contents": "0C10",
- "de_type": 915
- }
- ],
- "encoded_section": "589013A6678EE465A615810F963BC8524823C49110005A5B7E64F50792684B2A8F6A79718EA7900406B7D7E7FCA48BD47114CFD66F0847C883DF7FD6782B352737A61D21EB05EFAF560E2E0CD50D9FD1E940752E6EB6E2D2D7",
- "identity_type": "provisioned",
- "iv": "F5A4C94B269FA033FE14BFA63ACBED1D",
- "key_seed": "B69E0F9C1C0B1F48E8670D5DE996DEEF779C2DD31BA96E3D40FC6A91E97F5CD8",
- "metadata_key": "DEA55C1AA38639015CE0CA62436712FE",
- "section_mic_hmac_key": "2342FF7DB9270407FAC870A89EC58DA18193CD6761B4A6A186F1DFC8F5097EBB",
- "section_salt": "5A5B7E64F50792684B2A8F6A79718EA7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "202E08A90937C2075EAD5A59F7E1F826",
- "aes_key": "85AD6EF749C1F3785582882A509D2A38",
- "data_elements": [
- {
- "contents": "5BC965A20DFA04542BEC2459E2BD3E6C124C1E6CF676ABDD2B9C",
- "de_type": 722
- }
- ],
- "encoded_section": "5490135A9C9FEAABD949E8780F74645F6A3C8E911000822CC18C14AD885BC2B6450890F27E1090046DA21AA7BBABC3DBB63EE5653FA4B3CC619F4000A1E82649C1F516F162FB6AE4CB3975928A5E12E27A7E5A47B1",
- "identity_type": "provisioned",
- "iv": "48D37CB313151B5A637562436E0AD944",
- "key_seed": "1BED4881AA77F955F19F3E02484DC66EE385DB9780DBE97D61F72285EAC8C886",
- "metadata_key": "3EE77F6213BD622E7A7FC71A63DF2F41",
- "section_mic_hmac_key": "789EAE25B10C4671328052CF168517ED74AC64002E81384E4C27F676EBAFBD94",
- "section_salt": "822CC18C14AD885BC2B6450890F27E10"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "25E36ADBBF4FE51E8692897477FBDF1E",
- "aes_key": "E820954AF8A47313941F0DFF6F7D8E56",
- "data_elements": [
- {
- "contents": "F0E521B07A2BA4632B7522FFCBC8868A84B596E0E788",
- "de_type": 308
- },
- {
- "contents": "BC1B944236DAA3",
- "de_type": 650
- },
- {
- "contents": "9DD55DF02A53DCF3EAC75B805A2E468FDE7293E8D033456CD75B84B2C2",
- "de_type": 202
- }
- ],
- "encoded_section": "7A901374488D1F21525687674574AC556A759D911000B989B1E6C00C664909F417385FC3184690015D885FA6EABFC8A8AF8155D6022A502AA86FF128A90F7E92CF2E05A9FD1AAA7572DC42D5EB157D8845E144108D4E528D1B247732774F1C7EEBA1441EFBEBC97B3B550F520D4A31AFBB7D94C248BC9883889333",
- "identity_type": "private",
- "iv": "2A718490018706C03F9A6E4D1058369A",
- "key_seed": "0674E67302C41BA299713DE1C1EA641C82F9345120CFFBD8705C8CF1D99D9F24",
- "metadata_key": "DF696B20166A8F6C89A3A4999ACC7E66",
- "section_mic_hmac_key": "2230661E0FE82FC883CA43379DB99B5F867AC35A6C854FA271576E91DFD44FCD",
- "section_salt": "B989B1E6C00C664909F417385FC31846"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "77A50A93AD1DE5BD21FBA890648EA0F6",
- "aes_key": "A5C13EBB1931A7ECCB4D1FFC456D950D",
- "data_elements": [
- {
- "contents": "F248E8798E08955BB2B8C739C290BB910A2876078AF4E2FC3EBC839080EE",
- "de_type": 299
- },
- {
- "contents": "",
- "de_type": 115
- },
- {
- "contents": "6E863CFDE1C1B9EC5C5CE6",
- "de_type": 207
- },
- {
- "contents": "A78CBD078A98045B5CA79E19",
- "de_type": 62
- }
- ],
- "encoded_section": "769013B2E1239BB6FEFB97B6EA19C9619129D191100030FE3722857D4340D20F7C483E37F2DC900249E2354F02B0D9DAFBE5ECB30730C4A70236F4C59860A3633EEF571C2A024510BD9EEA4A46C1604CE18E0EE914A6B9001FC07FB1FDDA5807E075E7F594DC16D60E86B75246E93F301F7595583BE980",
- "identity_type": "trusted",
- "iv": "FF98DAB9B88B46C4982566F95B068A02",
- "key_seed": "E56913363141DD1C2F0D5F93FB6A9EA6CE5212D0DA2FDCAC3CCE6BB15097283E",
- "metadata_key": "661BF758E6697E46F133979F25395A26",
- "section_mic_hmac_key": "EE035FE53ADF345F73E4AE77C4BA8FFF96D12CE39F3924939DB827E14ABB715B",
- "section_salt": "30FE3722857D4340D20F7C483E37F2DC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "EA8DA1BDB85D6AE965D351EE9B8EB881",
- "aes_key": "042F1CC32A48B7714A58BB51469C260F",
- "data_elements": [
- {
- "contents": "C24EE733EAC66F8A54A814A1",
- "de_type": 708
- },
- {
- "contents": "C24D41A652EC0E16DC1E23A473850585795417447B",
- "de_type": 565
- },
- {
- "contents": "CC8DA80690986563A3815792",
- "de_type": 594
- },
- {
- "contents": "5C279B02235F4678698B16545905C95D121FC57EE7B68A387F",
- "de_type": 549
- }
- ],
- "encoded_section": "899013132CE522524AD6D5864DC7C43C07D4EB911000EE856613E81A2B970A62219E03CC698E900172071B9F49F539C94EECF7B8736EE09CFEE8A70BA28CC824951769B286E21B889B408D20E9EEE2A57E93E0CFFCE13E3093224880C88EC85C6B253363B24BCD2CCA07129487B2552240BC7C99C3469521F171065D3F14DC9F02E282DC03185849325A",
- "identity_type": "private",
- "iv": "55654AA16120C9192CF4251DB48F6811",
- "key_seed": "87EAA9BF3F195F050804C1E9CC5A29E15FA3D409EE515096E4AB412F341F63EC",
- "metadata_key": "25C515A0D455F2EADF60C5CFD02F5704",
- "section_mic_hmac_key": "0B106484613F91290A8AF8552F4FE3E517AB03AD99C7B49884E75E13D6A2F03D",
- "section_salt": "EE856613E81A2B970A62219E03CC698E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "C83B117035EA70F9B5EE8514818D9563",
- "aes_key": "5786A3D45C88BC5BF15E63BEABECC7DD",
- "data_elements": [
- {
- "contents": "96DFAF82E5E8",
- "de_type": 722
- },
- {
- "contents": "1A52EE0785ED4F5E",
- "de_type": 529
- },
- {
- "contents": "4070E0708BEB0EC5715AE4BBC7614AE65D6EC5",
- "de_type": 220
- },
- {
- "contents": "078FDF57A9D79648DF0C6AE6650D3745B4E5AB8F4230328BFCFD2CFDE8",
- "de_type": 534
- },
- {
- "contents": "2A683899E3C29BE4296CD5E63F156DD06650B98B6C",
- "de_type": 434
- }
- ],
- "encoded_section": "999013C17A273FC6F3CC1726484BB95C107A5A91100087114931992E6A90DA25ECA40CAA7FA090028868628BFA23AA55C7CE84DC579C73667AE77FD0519B69DD4D27F5F7E274C52807FA63E8BD0646F5317F7109770240A53B3EE772E019E226051DFD5274D641EBCBD1CD122A2222FA5769A2DB47B0C351AFF6F70394D3D39472981534D00428DB1ED731882A0D746990A730B5BD00A15E0729",
- "identity_type": "trusted",
- "iv": "F9A836CAA147035106E7454E9DD33840",
- "key_seed": "CCA2DEE077D57B7BD51A23F80E6E2B4E8CF22B489B31D50DFC0E2C8A51323DEB",
- "metadata_key": "2DB7D7E9F6C9CC9ADB3CDA79F1A17A7D",
- "section_mic_hmac_key": "0C0C3FBB7B4382A1965F1A0D21B0B76C80E9F5311D048B80C6279E53A9E59F0F",
- "section_salt": "87114931992E6A90DA25ECA40CAA7FA0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "CB188E83DDB89D62C114F1F1360015DF",
- "aes_key": "7BE45751AD3A8B7E49BE27F2D6247688",
- "data_elements": [
- {
- "contents": "560C374E10F3B1004D6BDA",
- "de_type": 930
- }
- ],
- "encoded_section": "459013537088C101C2FB104B6D3769B2211B1A9110005A675076A273B1935CA8836A8F568EBC90040DDCEEB9121864F9364571A4765FF4B14ABC63F8816880AFAAE4DD3CACCE",
- "identity_type": "provisioned",
- "iv": "494F76CEC4C372BA61E09E832CA023D7",
- "key_seed": "A6DB88D2495FD0F4DA2DDE97BFCF5799017DD7BFC5BB1AF9FB92B365D4690335",
- "metadata_key": "45C398B6E4E8B0A5540E19300C0913E4",
- "section_mic_hmac_key": "28FC3EAEEBD68AA836A746C2BBF26DE3ECB6AB774440232E986203C9D0F1DC77",
- "section_salt": "5A675076A273B1935CA8836A8F568EBC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E2F803555E499AB4ADD6E1BE05823C79",
- "aes_key": "5B23E3C06BE7BC3F4ED4E25348249AB1",
- "data_elements": [
- {
- "contents": "DCAEF3A98B4FC0",
- "de_type": 539
- },
- {
- "contents": "D4D1",
- "de_type": 417
- },
- {
- "contents": "CC7A7E6C0801E825F2CF606643C8B4E1",
- "de_type": 96
- },
- {
- "contents": "C3695CBF18E06D255425E2210E6A0072109062A4883EB67E",
- "de_type": 553
- },
- {
- "contents": "B426A715DABAF6CDE325699E12F3488EC0B0AD4CC23BBE641DEE",
- "de_type": 334
- }
- ],
- "encoded_section": "9090137453B44CAD941E40F0B10F59070543CA9110006ABC65E438219705DA90C55843E268F590042B17F2F7D33F64EF416A906477269B3EB1E98B647E497F07BEEBE093B0439D16F08DA3AEDA48CB30BA4B1324432337A801C89DBA6DB87CB7335E34663B29B7AFC589B0B18EB82E60B39D235F1143458AD5A0D7CFD18CD4154F180F840BB20CAF7CA5F701428934279A",
- "identity_type": "provisioned",
- "iv": "0D1E0A06889E8F9607C7BFD987F16DCC",
- "key_seed": "0442221D74C5BD01B2274C2A7C37280A192CC1D12208DC72B7DED708CAA5FCFA",
- "metadata_key": "53DDA5FB2357A599D7650F5B3F3344EB",
- "section_mic_hmac_key": "D56A4747E6404C01FFE0BCD9F85B7D99B07046CFDF5F6B9330F09161AD207FF5",
- "section_salt": "6ABC65E438219705DA90C55843E268F5"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4B5EA533159CE934C52A8AED1C7FA66D",
- "aes_key": "6979C3C75DF7004EE8EB62C5AFD4EB6B",
- "data_elements": [
- {
- "contents": "4E3FB80E",
- "de_type": 151
- },
- {
- "contents": "4E637AC7ECFB76369C9B878CEA3EEB802A",
- "de_type": 105
- },
- {
- "contents": "34A2A98FE7C7EE",
- "de_type": 134
- },
- {
- "contents": "698C29A5FB482A7ED59214E49F2C2295F8",
- "de_type": 992
- },
- {
- "contents": "09B28A3CA96A72",
- "de_type": 1
- }
- ],
- "encoded_section": "7790134C59AE20A1D6653BEBD70DC858E3D81E911000D0329D85697985F6E05E42949541149690043EE28E5F836FC134AE452135DBE0EF28E3C8B01718233AAC3699D43C79AD0FF0FD315FFCBC70477A534EE60C7D0006B6B0098838A7A33E2C2D240CB7A38E5340268EA91D9A9A017B8499F5E4B5218F9D",
- "identity_type": "provisioned",
- "iv": "3356ED13FC96C65324E87673693A1432",
- "key_seed": "8EC14F57AE7137067103789D1C2CC872D5F784DB8CFA491CA57D6EED842185F1",
- "metadata_key": "969E204773BA54E9F873D6EB28624AE9",
- "section_mic_hmac_key": "B502F11F87DAFE0E3700EF8AB8AD420D74DE34FE550E300E899D850C4DF5EC04",
- "section_salt": "D0329D85697985F6E05E429495411496"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "17A088DCDAF83A58AF2753313613B039",
- "aes_key": "1F2E0EE3496322D7D8D365E67EA1A0B9",
- "data_elements": [
- {
- "contents": "62DD2615146476EDDBDA10A1D1F2FCC03BD164C53AFF75DE",
- "de_type": 144
- }
- ],
- "encoded_section": "529013C7B81E1AE9557999FD71E2ECE5F7663F911000749DC9438016B9B31672E361489B94D29002F0D3FDD1FB26395746C6E8145821FEF4DE853AF48008677E47057EA33AEAE5AFDD8A6815A57B9A5B58625A",
- "identity_type": "trusted",
- "iv": "DA09A3AA5D1AACBA826AFB2E549BFC80",
- "key_seed": "EFB6CA23E03746A98605BBC2B163B08507D83D86AAFF789D08CA6DB1225F7D72",
- "metadata_key": "E590519575ACD07B7CA73CE1A80E30CE",
- "section_mic_hmac_key": "4241619E81FC51B75394A479F56F007762E3CEDC5722CA93375EC5B3FFA44124",
- "section_salt": "749DC9438016B9B31672E361489B94D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9A580D81461EAADF79556203CA735C95",
- "aes_key": "4045DA22088C072BF80A09B8C2BCE1F6",
- "data_elements": [
- {
- "contents": "FEBDF44538E9E70781B5B0E283DF4C13BAB1E49B6DC8242EDBEEA1",
- "de_type": 68
- },
- {
- "contents": "350B4FB802500AFB0D769352F8A6B9DFCEC2BA61",
- "de_type": 318
- },
- {
- "contents": "A9ABA29AA6E72DEB67C8E824171876C26CD1",
- "de_type": 379
- },
- {
- "contents": "3D84",
- "de_type": 212
- },
- {
- "contents": "DFBA842E5EC56C53390D21A019801B6F0D",
- "de_type": 431
- }
- ],
- "encoded_section": "99901366302C66D9F00F5C3C65DEF7C64F0BE1911000CA70480E790B6FA473C74E3A4E003D269002D07BC8320C3B78FDEE1D1F68E4DCA09AE32B16573455513DEA228C33E7926D26BDCCA638518BF9CB2FD36566D9DB0D6ACD64D0A6F8B2B5EE6F3DB463FF3FDDC485D5BCAEC66F1E982ECC008D3A45A36CE1F81049F95AD6BB6309326428220E8E59EEBAF4AE38A5863886056B57E25D682A7E",
- "identity_type": "trusted",
- "iv": "D70E519F3DA3F2668D9F8AABB50810BA",
- "key_seed": "AFD5C0D98921E1D241A7906F68D8A04F3AD3E81B1A0550D35EE4C6C8DB57DDFF",
- "metadata_key": "DC273523F44A001AFA17F0F4FFE6057A",
- "section_mic_hmac_key": "DD78AFB4D983C325EFDE1FE20D9BC988335CF2C9B37A75AB9A519DBF0776E6E9",
- "section_salt": "CA70480E790B6FA473C74E3A4E003D26"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5033210306BA9AB77E2D3EA6B2A88AEE",
- "aes_key": "58ABC0465E84B9EC15FCD58D2E34A481",
- "data_elements": [
- {
- "contents": "D9485F980546BB684977FEE260590F8C94F3DBC5A4D5ABAF3CA68FE902C7",
- "de_type": 891
- },
- {
- "contents": "CEE448E265CD2D5B240D0389A1D19CC70C39",
- "de_type": 962
- }
- ],
- "encoded_section": "6D9013975E455A5A9DE86D218DF7B84D5B1D549110001B4A179B3A4048FDA263D917D21145EF9001B30134E7DF109B194C1342F0B49E2769BBDA370C5D76748EB77A583F75248CDD1A20CAC314C29429B88FB99979BE4B468B6A9EA4DBF9C3CED9AFBE95FE44E4761A501D8505BF",
- "identity_type": "private",
- "iv": "9DDE36E1B51C439ECB53A803239075B4",
- "key_seed": "FBBA5082E277FF50246090C3607AE6B59192F350244A4E1B38F1F737E1297AAC",
- "metadata_key": "078882BA8177D36A63C48E4FB81487D0",
- "section_mic_hmac_key": "73B3E2977B6A0722AE497D1F9B52ECB47BF0AD7B0C53C91F66F27F0C4464B4BE",
- "section_salt": "1B4A179B3A4048FDA263D917D21145EF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "24560C643ACF024603DBC6745F73BBFD",
- "aes_key": "96648935E3EA6534930CCEF9FF46157C",
- "data_elements": [
- {
- "contents": "E9F020541040899D",
- "de_type": 609
- },
- {
- "contents": "192E2705B3ED51257DE39187071CBE006F59FE797A380C690B7361",
- "de_type": 884
- },
- {
- "contents": "EA",
- "de_type": 284
- }
- ],
- "encoded_section": "6490130799AC2E188C075DE6FAFFFEB23E085F91100050AC82B4D7F3A6BBC2114DA1F733ACF2900469467DF82CC82A6C8D02AD6C485973D1DE960AEC200EC2925C15CC0AF18C59EF8A21F16C6247F07032029F42F727AAE4F0C0A02E8B92824556A6588409",
- "identity_type": "provisioned",
- "iv": "C369FA65B5EB270813A60DD29E99F52C",
- "key_seed": "75B90F739FC2B807804A7D201D758B8F2CFA5023BC95546EB70AF106B3EFD2AF",
- "metadata_key": "0FDB27FCE4A6AEBD5CF6440316B299E5",
- "section_mic_hmac_key": "455CE9502152FC7EB6BB721DA5BD1095DB8A8581F1B3F893B5D5FDDF98DCDF55",
- "section_salt": "50AC82B4D7F3A6BBC2114DA1F733ACF2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F18489FDCD6520D71418C0A0E7636910",
- "aes_key": "C6A5270EE01BAD049F2823A3FB9B3B60",
- "data_elements": [],
- "encoded_section": "379013450221F90903BE11C937E8F2518999B691100078488DBF62F4D446B6213AB3AFD286AF9001D1AF3AF9D2172A123E854A9564EE1A80",
- "identity_type": "private",
- "iv": "2C15E2EDEABE3742E25A9EC8E8288C48",
- "key_seed": "EFDC60A5D965B43E0181ACDEF1073D8C9CAEA8EB1133CE5538D17D00987411B5",
- "metadata_key": "BFD25D2E0822E743638D21199C657DE0",
- "section_mic_hmac_key": "12F2F8446F6E90B917D3453DD1543FECD35B7E35D16FE8B966E95A50221FCB88",
- "section_salt": "78488DBF62F4D446B6213AB3AFD286AF"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DD8077D99C25E5AD861B96702256EF3B",
- "aes_key": "4C007FBF6A6921EF95877D207A61EE5B",
- "data_elements": [
- {
- "contents": "78B194E3A0895DC7",
- "de_type": 835
- },
- {
- "contents": "EFFC63F96EB172632387FB9B0AAAE82514388876D62D1B4C03",
- "de_type": 419
- },
- {
- "contents": "00945CF6A5A4",
- "de_type": 585
- }
- ],
- "encoded_section": "679013E41F6BF179F1F1AE413826061C017577911000EFB6DBDE8071C59CD70D626D43FECFE990013F29BDE37417ED94EC2EE33631A7B72D39ECB033BD9B6E12D923E007A716DC8A48BD159DCF6CB77C304394CFD2E198D43DA39B0E37870FB6F5AE1CE44FCE153A",
- "identity_type": "private",
- "iv": "3DC0231F80F3F2B132B09BDE9CC40759",
- "key_seed": "7562411D7931D839A229013E52C55F4DC5A3EEFF1117E408AFA3F4AC426F10C5",
- "metadata_key": "ED09172ECDC74F027C0AA0E418BB4AA7",
- "section_mic_hmac_key": "CD75F9BE138CDC579730D22DF33B653D0250CC0747B1702A4878DE8302DB7C44",
- "section_salt": "EFB6DBDE8071C59CD70D626D43FECFE9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A288ED7E1B68D033C3F4690420B90D7C",
- "aes_key": "675CED7A7336FEF07E17C17F959EA288",
- "data_elements": [],
- "encoded_section": "37901300926ED675109AF07704A987C309566591100015847DEC4B348DCCCA189D05D7D5174C90019395E4BDFD6A6B7A68215CE58AF169AF",
- "identity_type": "private",
- "iv": "F2B76940B657CD501B1B9D188E69B582",
- "key_seed": "C3D8A38ECF7392E4879D99A8C9E21759E23B95860D04E10C33D0F4FC988D219C",
- "metadata_key": "B8A8C3055E2FDD6D00A905324E758F5A",
- "section_mic_hmac_key": "C6F39BC5C3EFF0F8F09FF1FB23728F5DB138B208032B91EDDCC2888C1405647E",
- "section_salt": "15847DEC4B348DCCCA189D05D7D5174C"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "623E52E555A5421C80C40236F560973B",
- "aes_key": "201A7FC4CF51C7C389EB70B4528F0A4F",
- "data_elements": [
- {
- "contents": "E696D48DEBC719E0BC6B9BFAA01B37363F213EA19B2508E3F65CB81A44",
- "de_type": 776
- },
- {
- "contents": "F6A3106D966E9E033943DA151E9D520B",
- "de_type": 699
- },
- {
- "contents": "3822C8B9",
- "de_type": 473
- },
- {
- "contents": "286476C80CE4C19E40D7F7096A30B4E1AAB2F1AF07",
- "de_type": 964
- },
- {
- "contents": "801E59E8",
- "de_type": 196
- }
- ],
- "encoded_section": "9090131E9A577C252A33B78982AB45DC475FF091100025F94B814B7033833230BB2CD9C0132A90043C21957E1606423DB86A914AC7B2451502B5206DD412CBAA364FE638AAA8DF0C9AC173462492AB53726A000223D6F74047E9D784B4377D0DC5930404A4C4AE0E3598CCAF70608D9CA0973A8D71C683C163EA16A5D9944F24A510DA586058A498C61CDD9A278D970C82",
- "identity_type": "provisioned",
- "iv": "402E1DF4ABC0651C160A910297E96D42",
- "key_seed": "755AE4BA0D148487644F6661D42583CC5710CBC0C35A1F0CA1013B33378665EE",
- "metadata_key": "2C5769C63A6C4DEF4DB33A0FA7C96D5B",
- "section_mic_hmac_key": "928C6F5D55ECE19FD96C26CCB0F30481962702DB2E33218E05B5849057BF0221",
- "section_salt": "25F94B814B7033833230BB2CD9C0132A"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "BD9442F4DA1F1E45298431632FBCA1BA",
- "aes_key": "C86D801FF7EE0765384862985B3A8FFF",
- "data_elements": [
- {
- "contents": "940AF7EFA6B964475032932CA2C94F6455CAE937032FE323D9A1EBBFD2",
- "de_type": 584
- },
- {
- "contents": "9A84386F3D32F5F816B255",
- "de_type": 722
- },
- {
- "contents": "FA216768C3D6FE14E93C86AF8A45CF2A05BBA5",
- "de_type": 722
- }
- ],
- "encoded_section": "7B901306526801CFB4D0DCB662F3B77BBF1539911000847811E9F14841A70D3129366BC733F39001BDA5621D9D26B5F59BF25279EF7A6A4FC7CA64AFC8F15B42B765D498DACFC4087145C2E8D580B3DCF2F9B3F6E8CF495CE47BD4DF868479F3CA530D0A24B0998A23AF4DCBFE6B6E432FC7EA66491240CE29EDBA2B",
- "identity_type": "private",
- "iv": "AD35B9BB2AD04BFFAD8A635D7DCB26F4",
- "key_seed": "C10655F54E87123FC6B537E38DA1212E290613C97285C4D28BE15593E506919A",
- "metadata_key": "487166EB4E0DA027A655BD7D5D952894",
- "section_mic_hmac_key": "23B54AE40FE38715E903223F80F2149346D9D34E2A24414ABD7B3933A4CB4337",
- "section_salt": "847811E9F14841A70D3129366BC733F3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "95A1E9359B39032DFD81BFBEAFD092F8",
- "aes_key": "C4A0945C3A1352D1B8D62904D7F9EE9A",
- "data_elements": [
- {
- "contents": "DDB9062EEE56D10231CF606B139CB1E2AB77BE00F7F12B9E85358111",
- "de_type": 939
- },
- {
- "contents": "344F840369",
- "de_type": 67
- },
- {
- "contents": "09DF9B7F9F0CA5708F2D2EAA28",
- "de_type": 807
- },
- {
- "contents": "90025E283882C5255D19FFB273FBF7AE",
- "de_type": 115
- },
- {
- "contents": "2D268EF42716C19253E88FCC196D731E774E7472F16D5C",
- "de_type": 541
- }
- ],
- "encoded_section": "9990131968FC75E9DB7C11135F77963495199A911000B2A08BBED54FECC10AC797794F3EC4309002CE86072EC393E15DF60923BFF3977190C76EB76737DA68A858A1A21B956681334E67CAA59B11E0186BE23474A30F87138D238C37608F498F56B70548D984E57959B5AE73731F4F5E20AD34B80909739F891A5E493667E1C6B316F4E0CE6BDE3D397449AD77F1653B1A3E2C43B5ED711387A8",
- "identity_type": "trusted",
- "iv": "6B19CF9740AE6EB6EBD37FA0CB3D3902",
- "key_seed": "F87D44A4D5B28B4BA5D73383B98268E3114BF761756D000E85274BAC3032AE9C",
- "metadata_key": "17DFA18739929CE57D4B46B0BC5B0E66",
- "section_mic_hmac_key": "274695928C408DA10D19DC3DB46FA78F29D51CB0DDFE304FC5182C785AA21F4A",
- "section_salt": "B2A08BBED54FECC10AC797794F3EC430"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0CBE6D655846706C41AA38BA89A49466",
- "aes_key": "D1217535D1A28CA4A79A5D361D10381A",
- "data_elements": [
- {
- "contents": "715FD19363404B5B4BF8814D7D6F988BE275D43E4C935E",
- "de_type": 257
- },
- {
- "contents": "5FECCFADB93B95ECC6E8EDE452FA15B0FD1A96A67A9FAE898A15810CC6",
- "de_type": 255
- },
- {
- "contents": "40BE80BAFB55E63E12B9F5D5F15E7417DE",
- "de_type": 924
- },
- {
- "contents": "3D878AB8B130EE71B7A74387CA7AF3466AAF2F14",
- "de_type": 259
- },
- {
- "contents": "1D6A8D083172AE3E8702D0EE72E9E4D287A4D5E38C3A7E1495E401CCE3BF",
- "de_type": 539
- }
- ],
- "encoded_section": "BD90134CC217C0FBD454E2D3D0949340E43A9D911000EE29E650BBB7FBD251916DF635D491D290040E58986C5A7EAF8ABC13233D237727F371CA25E439F4EC85113F22A1976C74DEBF832FDEF351800FE7F2905DE22D101751999D5B7DE13736E3E77A2F2D07023F8E8FFCD09D1AF91F1688047ABE64023E386EB8883400886CB44B5FE43D6F93CE97A54AA75D277798754B4F1B5F3022095772463B1D354C89E943EBD608C6120B65DA030FFC13F78298E9BBAAFC12B24896A11A8F6F56",
- "identity_type": "provisioned",
- "iv": "BBCA152795FB88152D57F449CA9603B1",
- "key_seed": "6F2DEADD30B4CCA84A011C445661F91CC6FF5786B49AE3F9154CC5841FD56555",
- "metadata_key": "35D37C707ECA65275536D1236D349205",
- "section_mic_hmac_key": "D83FE1496B06CD24079B117B21F94EF6603338EA01D295FFE274131046071F58",
- "section_salt": "EE29E650BBB7FBD251916DF635D491D2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0F459E925172A519DD2828299C75FE2B",
- "aes_key": "1B1249ED7D76FE4886B6E526C6C9282E",
- "data_elements": [
- {
- "contents": "308DE47A8F42DEB39111A2096C20F7356B9839FE3AABA7",
- "de_type": 399
- }
- ],
- "encoded_section": "51901322B7BBBF38950918837234007AA875FF911000264878B5796B1E75ADFE1ED50D18D19F9001049CA71F9B829E07EA5B5F30E7C9B2BAEC9D27BC5038EAD21DF880707BFFD71D641B82DAB89CAEFEEE01",
- "identity_type": "private",
- "iv": "AF47AAA871EB40799888E96730D541A9",
- "key_seed": "EF12CF54E077C01AD5E5B289415D4AFFA7F2221BADF1D898E6F18629A0F1D91F",
- "metadata_key": "77C71712C8591629DADB5FAEC758CDF9",
- "section_mic_hmac_key": "8EFA1E5AD01997162F01D27CED8DD1A3EE69A32B54C6BDA3E46952F49E418DE0",
- "section_salt": "264878B5796B1E75ADFE1ED50D18D19F"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3A6690DC2DDD695AA5A9075341B084EC",
- "aes_key": "34DFB2535A916D318BAB185BF9A35783",
- "data_elements": [
- {
- "contents": "F06FA2",
- "de_type": 506
- },
- {
- "contents": "D4CB2D400A28",
- "de_type": 335
- },
- {
- "contents": "6DCEC9E8A721AC77680D2F1662",
- "de_type": 831
- },
- {
- "contents": "D17C7919F930699E",
- "de_type": 762
- }
- ],
- "encoded_section": "619013C7CFFF40F84A407D614398DA241E9E4D911000D32C0F73924D558D708BEBB99A3EB0609002E22E4C8ADB99837CC58EC7E97001719A89E37F9B92E37168434E56311EBF0E5EBB3F9EE662EE2DFE006FDF44EE75196FA08CC8CC3D33B6CF236F",
- "identity_type": "trusted",
- "iv": "04F8366E46600D1C30CD191211A750DE",
- "key_seed": "647DB8957DA90BA5FF55CF490C364BAA8C056638C1BD1D3D5F70302C92CD3A2A",
- "metadata_key": "CD662BBD791D7F8C1E30395AF98E5D04",
- "section_mic_hmac_key": "1A53E143075E92DE50221DF59303E82CB35533DD879EBFED762B353AFDBA1B5A",
- "section_salt": "D32C0F73924D558D708BEBB99A3EB060"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6D431878AF6AC725647D2A3932D48049",
- "aes_key": "05EE18F99215AD48B14552410229A4BF",
- "data_elements": [],
- "encoded_section": "37901341A817093CF4C8AAE012B9A9F6B79BB6911000290931A59120D1286A389550AAB835209002C91C9ADD7B5DC4E51AC8DAA513E4A209",
- "identity_type": "trusted",
- "iv": "4713233E1B8526CBDF59EBDAF4DF2A9F",
- "key_seed": "2B25BBCB002C26DEBDAFF430909946F7B022041043BFC5232AFB086B348F1F42",
- "metadata_key": "35BCFCCEEE33537EEDF1853BF0378767",
- "section_mic_hmac_key": "0B1B7CEC50A244D8A31571BD3E1CCEDB22981CFE1AF50CA57626C072F9CD14C7",
- "section_salt": "290931A59120D1286A389550AAB83520"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "07510B91F77CAE102F146FC8BE46C659",
- "aes_key": "779622B3641D512BDEDF2AE0650BC794",
- "data_elements": [],
- "encoded_section": "379013993CC70660FF52F2412FFC739C7453679110000FD5F8913D590B72580DE20C140E88809002190029DE26AE807D727B820A4AF588A4",
- "identity_type": "trusted",
- "iv": "91B96C70926C3FB16CE4CAFE91CD827B",
- "key_seed": "4F81B6AD805AC41891E439D788B1D5C1FD33F97457AA12D6CA697E328584A24A",
- "metadata_key": "9F62C8E787A9B44783A738A566E1FE23",
- "section_mic_hmac_key": "87ADAA31C70470F253F408E88D004DBC4B99B7BD22C0159DF93A1C268BB84B45",
- "section_salt": "0FD5F8913D590B72580DE20C140E8880"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7C1B9BDF63664F7A78C8FF842A3E5BE5",
- "aes_key": "B14C39586FEC0DA3E623173EDF55E246",
- "data_elements": [
- {
- "contents": "68EB2518D2D2DC509CD7",
- "de_type": 364
- },
- {
- "contents": "A78A0427BF54D74DC902EC",
- "de_type": 1000
- },
- {
- "contents": "F234",
- "de_type": 882
- },
- {
- "contents": "E7",
- "de_type": 916
- }
- ],
- "encoded_section": "5B90137644015B5C1628811212B508B4EF15829110003826BEB04A106A0C2B31C1EDC4B1A3389002C812F2014CFFBE215C1E0E1B040ABE8141945625C65300B5D2BF5564AF2E364C119C51EDAD83D99F339C21E6DE0F64C6B9F15C2A",
- "identity_type": "trusted",
- "iv": "1A7EEEE592C2E95079FCC1C2DB5B3C87",
- "key_seed": "2F9AD59747B7A30E2D1D22E49F0A80F5FF8BAD5A540E65970CF0A9E9158A9CC3",
- "metadata_key": "178A25DC5E2BFB2F016763C039CAA9DA",
- "section_mic_hmac_key": "98B93838BF427995042BF3FEBE6F53DE0BB0A01C400E80E6215E16ED3C8BD32B",
- "section_salt": "3826BEB04A106A0C2B31C1EDC4B1A338"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "DFBE483FF56C948B67B543FA3C3B6810",
- "aes_key": "0546270E29B03208CCF711096350B437",
- "data_elements": [
- {
- "contents": "4938A69A3826",
- "de_type": 976
- },
- {
- "contents": "AD51E90DCE",
- "de_type": 985
- },
- {
- "contents": "50D528C99515",
- "de_type": 915
- }
- ],
- "encoded_section": "5190130C8A041604CB78FBD9BA86C48BDA6F5E9110001BF3E6C8ED3648CAAB9137B09117BF8E9001ED1A785EB628A70EBA116E5DB97F8D30605A40CC18B0D7493863758CD712B26F782CB123E25ACD13FBA1",
- "identity_type": "private",
- "iv": "8E27D6BD840DF5E03F5D9CF83E10A51F",
- "key_seed": "BB595D62CC6E3A83C3CEB9FFC054E1EED6F7665F233FFE054DD17F93FB2DCB6A",
- "metadata_key": "66E246479EF32D514A6203715F97CCA6",
- "section_mic_hmac_key": "151D73D770876023679FB2AF853C5AC6180690F91A5464A8105025F6E963BF43",
- "section_salt": "1BF3E6C8ED3648CAAB9137B09117BF8E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "993426DE3C76F95E6AE6EAF16EE882B1",
- "aes_key": "23FF6D33822767F47C6EA2E7A3659F5A",
- "data_elements": [
- {
- "contents": "9F4B62",
- "de_type": 40
- },
- {
- "contents": "DD75CCA8B6EE91CA96B0F660DA7AEA0C787B6E4DD0BB8C0D68BF63",
- "de_type": 250
- }
- ],
- "encoded_section": "5A901310EAAF5CC6F82AED3F7018345C326FED91100094461B35D320D920CFE92855684DC0889002752E76A47C2FFDC9C86586181F3AD4DEF62B1F4AD8AB6FD7832F108CA27D96405ED31670CE51A9582C2005E275A97EF3936F6E",
- "identity_type": "trusted",
- "iv": "908A568A36D18A8151DB2E23FEA891A6",
- "key_seed": "891B77B866BC1361E8A953BF5776A9AEB8CE7AA8B34C48D0FD44EAE0C08137F0",
- "metadata_key": "F7CE950ABACD4CC08649F5D72141AFAE",
- "section_mic_hmac_key": "D948570C35BBC468884A3C9BF04ADB86D30132BAE6F39F4C6F6E4060D788AF43",
- "section_salt": "94461B35D320D920CFE92855684DC088"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7EA92251924B66DF513A5012A6C6D568",
- "aes_key": "7AF5D9EB8C289F13007A8024AA3E0954",
- "data_elements": [
- {
- "contents": "1D5E12A67C6225BD455705E9C6D5AB253A",
- "de_type": 56
- }
- ],
- "encoded_section": "4A90130C02BBD5A0B4584C65E3B7D88A9EC7CA911000DD5511FCD7D808F50FF0080A6A41B3F99002965B9AA07C06770BDB145D5CC2C5D535D99E30DFD043BD92E9A89D29A0699B5F09A200",
- "identity_type": "trusted",
- "iv": "3A2CB91A70F515B1F1B9290FB1F0809E",
- "key_seed": "25B553E985E762AA9F3B03F4B89BAC1FD0A3E9F7F9CCF586FF47F3F1E83DAD34",
- "metadata_key": "980DE36843A6418160C53B68085FDBF7",
- "section_mic_hmac_key": "D674880D748C81B5C248BF6EC8608323A5EE2F6E916E5AD2C24823C569492A0E",
- "section_salt": "DD5511FCD7D808F50FF0080A6A41B3F9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E84BF8A1E7FBDA1FCAB241D541A4B647",
- "aes_key": "5B21560F602267F7E7DB688C69B10A5E",
- "data_elements": [
- {
- "contents": "BBD418E93E17C83B5AF5E67F2203094C",
- "de_type": 667
- },
- {
- "contents": "009A5DA2492D6E5DD01DED55B7A9BE695A",
- "de_type": 849
- },
- {
- "contents": "FB321D91",
- "de_type": 529
- },
- {
- "contents": "6D1B46C2935B79287C75EB347FEE52DD196F03B98188DFF4",
- "de_type": 971
- },
- {
- "contents": "D9299E84D9B7E84D3682BA",
- "de_type": 68
- }
- ],
- "encoded_section": "8D9013F0B3089838810E7704B15BD78D08A685911000295591FB4D665C4B3388BFAAF769AFD09004E208729A8980B56196049A6C2B389E7EEFDC1842D4B0738B62C6C9E4A00D7C998A329B13A54F7741EFD8C22B34E996ECAB49B5B3D8A549EFA1EFBABCC4B90C45D434DDDA3C0A19D2BFEAEEF1103BC0D5925BC692A04C1E7A7BF76EE82785D75507448921F48F",
- "identity_type": "provisioned",
- "iv": "960F4158B1AEBCA6DB066F0B48984889",
- "key_seed": "9BA51AB24D27BEF6575942CBE58DE2795F2D6A9C67EBBA56F938C23C15531A48",
- "metadata_key": "A174838932FD40B5E30FCCA95BC31E0F",
- "section_mic_hmac_key": "2680C01C16E0EFEEE4C602D9AAAB80FE3B83D8F85A2CE1D52EBCC2C0A48DAB09",
- "section_salt": "295591FB4D665C4B3388BFAAF769AFD0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0D89ECCEEE97F4AE796752548C4477B0",
- "aes_key": "CB51E81286DECD8DABC11341AAF565E5",
- "data_elements": [
- {
- "contents": "7B3636268051172202DBCB2BEF58FFB325",
- "de_type": 125
- },
- {
- "contents": "6BE1759110F2DE04CA9F033B49E2E5ADCEE66BC5",
- "de_type": 383
- }
- ],
- "encoded_section": "619013C9EBFF7BA86B7D87A821163495CD75AF91100063ECCD115CEE939180370ABB6AADB8E09004B8E73E111A704D49A74051C8D5A88261C3BBC9C79500E9F54203007442BB22C0C23AE735D4B462D85A6B31E0A77015E386C713DEFCC331C87688",
- "identity_type": "provisioned",
- "iv": "40553B60D6076492812FE60B01CA6804",
- "key_seed": "26CB810DCB795E439A93DEEE6BB911B1F636B556FD8C53F23459F6302275C7C8",
- "metadata_key": "8832629DC35BBB214C9B90ED4AC52608",
- "section_mic_hmac_key": "107F6753902D9632AD49A70B0F9872D374E15B4FC9ACD9A4DD077550E73787C0",
- "section_salt": "63ECCD115CEE939180370ABB6AADB8E0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8980475911C04D64CB9BBBE789A8ED79",
- "aes_key": "8F48B997309C0264316824863B46A5E5",
- "data_elements": [
- {
- "contents": "",
- "de_type": 955
- },
- {
- "contents": "85F677EB8010B1E049BBE2750E744709740338",
- "de_type": 849
- },
- {
- "contents": "545399ECE6558120CAC6843E616D2A66C625B46CAF51",
- "de_type": 175
- }
- ],
- "encoded_section": "699013F558FE32291733B23028F005263532F19110003532D026D9F6B2293231174EF173744390028FBEF73FC61522088993E06CCEB4BBDEA63ACA01E37D68A8241A8BD29CE0C58A17D7C278B9AB5D1BCE16FBD9489B8BFC30AFA25A2042DB00F97BB0DF285544B6D66D",
- "identity_type": "trusted",
- "iv": "29D344C509673521133F5850EA86AF2E",
- "key_seed": "F2EA3582730BDFE282331B42AE97121E21BDF182DBD69B91727A205BAA579037",
- "metadata_key": "99E2FF341D58AB75D0127FDD2D425200",
- "section_mic_hmac_key": "881AAE5C6151C026780977F62A81903441024E55B9F186791CC3E38B63AB6056",
- "section_salt": "3532D026D9F6B2293231174EF1737443"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "3D35695472AF0B0EABB5D2C51648E491",
- "aes_key": "FA32718DEE6BCF406BBF3ED62D576156",
- "data_elements": [
- {
- "contents": "8CEEA14D",
- "de_type": 890
- }
- ],
- "encoded_section": "3E9013BEA8415E76EB477D7CC18D98804303C19110001EE74524224EF14F78BFFFECEE148AD8900257A6CAABEBAE9381D8760C36858DACC5C915E94E62BB4C",
- "identity_type": "trusted",
- "iv": "C4E5EB3B1C38A64D16F6D998AEEA72ED",
- "key_seed": "5F46CCC0833C98CC451ADD9220D928E9CE89E58D26DC1A0A2E33764B39B9F870",
- "metadata_key": "2D5B9A4F7AFD2191247BBA150037597C",
- "section_mic_hmac_key": "7730037D7F614061B40B893A02995EB25A63E4EC8AAC72DD8B8CEF2B461F3BC5",
- "section_salt": "1EE74524224EF14F78BFFFECEE148AD8"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A5ECCE03A7C2509BAA2AB1D6BE71E928",
- "aes_key": "0B587FBC29C6D813154219CCE15116F5",
- "data_elements": [
- {
- "contents": "DF191813F52A",
- "de_type": 647
- },
- {
- "contents": "725563C23F3804C841FDE67E6E51461F0F2DC9F840",
- "de_type": 899
- },
- {
- "contents": "1B5D86F0D9C956574F6A3A27C2044B10AB81A255377D7D8AA9",
- "de_type": 364
- },
- {
- "contents": "D63DA88FC2DBD10C8A92B0",
- "de_type": 256
- }
- ],
- "encoded_section": "829013AD8991F88073B5CA5DAFB2FE708649929110006B0F8560F8FFD0C6E71A028CDDE232F390010E56B36364E1D87122920F29C303A359319472A2B83A3FB385359CFF3F51E2C87F1ECD965F036D359DC840E1B104E530C8F35B796C2E72447468E7219900C8484FAC302632DA4A8F447CE411CAFFFACF26066F40CB9BBA739C8A36",
- "identity_type": "private",
- "iv": "00429B2681196B02A26C1C02684BB3ED",
- "key_seed": "78060E15116E06B5825588FB3C02A33BF1FA963E58CE8DA6C99E7C70137FA362",
- "metadata_key": "0ABCAA033AE39B19FB9D30501F5819B8",
- "section_mic_hmac_key": "09CA0501CD4C4E1C040C4BC108ABB945485B06655D749FB7793D11139657FC89",
- "section_salt": "6B0F8560F8FFD0C6E71A028CDDE232F3"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B60D3EADB0A155E05F9BBE78238857EA",
- "aes_key": "6FEEE0BCCBDB7BC1D3082DDE80DCF582",
- "data_elements": [
- {
- "contents": "AAD964BBFDF41816E109E9A6A9C2B9FFEB5B08C45E2039",
- "de_type": 271
- },
- {
- "contents": "27F1E36F467A1DF69F379F26AF8C26652BF1189B33D2860620AD",
- "de_type": 724
- },
- {
- "contents": "D77DB60BA95D50366DAF4E0B23",
- "de_type": 329
- },
- {
- "contents": "C1C4B4CAA02C898493DDF5B8C0159C199A3AC2E3A50C",
- "de_type": 528
- }
- ],
- "encoded_section": "9790131AEB7D53743A85CDDA3D06FD34E5D30B911000F3F0F371BA25F95A5604E8812C8E2D819001A09AB5DA90086A8CFB40E9C57E544CD80CE73710CB80D8A4AF0B284883866397C4E741F4F16EDC191CBEA93E8F9C8C94AD22DD699741F68704B6CEE74C61CC59B07FA970378357BE11F4DAAB1157C045AACCF979342D934D5A7154574C5FAC9C522D0F8228BAF6F82D5AB851CEADED82",
- "identity_type": "private",
- "iv": "411A5DB92AEFACD6A6B37B000586D0AC",
- "key_seed": "A04AD3E70302B99AEF07906B2B762047B970EF8A200D1ED6CBD28476BD85A331",
- "metadata_key": "A023B5E00CA83ADAA212B1D64A5D06A1",
- "section_mic_hmac_key": "3C1DEF68478B281B581A8747F7D8A5B2ADF5FB49A495EF554110685F2B7DC5D2",
- "section_salt": "F3F0F371BA25F95A5604E8812C8E2D81"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5661C7B50F7399E237F33E4766620EF6",
- "aes_key": "386BA145F32F66CDAF5F1216248C4FBE",
- "data_elements": [
- {
- "contents": "12C2775438394CAC486D9352543D4F28970AB925AE",
- "de_type": 708
- },
- {
- "contents": "08FD1092CCC12B09D300519B0CDC6401DD",
- "de_type": 706
- },
- {
- "contents": "618B6E2DF482703D2CE2C8DAF386B929F8DABEB0CB7B203EA0",
- "de_type": 395
- },
- {
- "contents": "84DA0F232629",
- "de_type": 95
- },
- {
- "contents": "D8EFB0C07BB7F632E268EAEECBFD5580EC1A5B0EF432C03DD861A5",
- "de_type": 570
- }
- ],
- "encoded_section": "A5901317309D406C29FEF9E2B0625DF0610CFC9110000B472B8FBFFC54950637585AFA22D5509004FF43D777C9F0350F5CC37D073CCE92BF1304DA2FA06451DA01A1E1741040FCF892BE87A46E3599ED878980B2618C7877DFD0CF1D805062677CE60BF8EF94376E283B17D6BFD2B3E47A14B183E0A8DA63E193F90FA0C5B3A5CF88274725414FDE243394B596BD72CFF6764A983AC46FFF3E66EE489B2C480F63AE1D2A6672",
- "identity_type": "provisioned",
- "iv": "BC345684E602976E5451D5F182330582",
- "key_seed": "8FB21F7DA6D21B3C74FA79DA8B1D2C1C9F08C6D5D92A788EBFBE686CDA2363F7",
- "metadata_key": "BD24EEB64110C56897A7526D714C1B9D",
- "section_mic_hmac_key": "966F0302B8CB8BA4C588CC61A8C613212E5AB8AA530C3FDE9956F4675D188453",
- "section_salt": "0B472B8FBFFC54950637585AFA22D550"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "E8AC69F87CD8D8E7AC003EB05319318C",
- "aes_key": "4762F0AF4F9DBE629D3FA4E7F5EF69ED",
- "data_elements": [
- {
- "contents": "584B9E443F799CF5A237ED1A90BC64A5347D4CF5B6F6",
- "de_type": 700
- }
- ],
- "encoded_section": "5090133125A01F41198B89512B2E6789D97CBC9110009DEEFC57FD2CC2691604CDB0037C5ADA90011ED9AEBD11CDF10F03FA38E223D5EEB742C6A1FE96FCA9D8E574B3AFC3B23E9009B06F25DE8FA9149C",
- "identity_type": "private",
- "iv": "9E710005012C74225422BD12E64463A3",
- "key_seed": "9E86D7D3AA5528D0D529681C941AEC12D605868B4D8504402A0E871AF45C0E72",
- "metadata_key": "68DC6B506A83F52A9376958D6528B4AD",
- "section_mic_hmac_key": "877EE9AAB694D7C9CFE7A28C7EFC208047CD35B6F802E0A4804C4ADB877037E8",
- "section_salt": "9DEEFC57FD2CC2691604CDB0037C5ADA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "661FCB47FA67B5328E1C07086CF91032",
- "aes_key": "4A67204896566D0EA552408DEFE37A2B",
- "data_elements": [
- {
- "contents": "C6DEE49C7944A768E00242ECD44129EAD078153F7F5128B3",
- "de_type": 825
- },
- {
- "contents": "7951",
- "de_type": 998
- },
- {
- "contents": "8779555409E658B45F916687961397D88E2484D4",
- "de_type": 21
- },
- {
- "contents": "",
- "de_type": 289
- },
- {
- "contents": "77246DD4865D6982E24BA67FAAF627E5BE8370FF91ED97F2EA97DF",
- "de_type": 75
- }
- ],
- "encoded_section": "8D9013DEECEA5F0980DFE5FF791C6B9D245BA3911000995E99F9B9E2BDD3036ED14D6904D6B19004056DB3CDC392922A66EE7CB5AB5966BC3C8970EC5DDEA9A88237BC7BBBCFB6F30FD944F7820BD45CF5D63334BD3A5F392CAAC8BFC8460F60C17CEC1CE0D56839FCC1F9D412E47BB2E7B4D1C49908ABEBE1DD7BFE99D4F1C09116B47DB746E5D67A015B46908A",
- "identity_type": "provisioned",
- "iv": "A37E4E6E61BEF6E55B309AE5C746F5AC",
- "key_seed": "FA6D33246E99E41066ACFD0381D778B908A0E298D510508C8238161EB9FB57C9",
- "metadata_key": "A9E99B3DB7BC2DC0861959FA9EABA87F",
- "section_mic_hmac_key": "532A8F76A3BBE0711005A126C8A63A59A76702A80372D6AA08301BBEA5878019",
- "section_salt": "995E99F9B9E2BDD3036ED14D6904D6B1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "6C1F3486166215C3D44981140FA00E7E",
- "aes_key": "03D881B6A9D22AE7E5393547A0AF68BD",
- "data_elements": [
- {
- "contents": "93C31033E2",
- "de_type": 236
- },
- {
- "contents": "8516881D4AE2302077E4226597AE397845E301EDC63AF3DBBF254F3D84",
- "de_type": 350
- }
- ],
- "encoded_section": "5F9013BF2225F68FCF6A2A9CF8F08DC7BDE6559110005A42B78DFE6ECD8495FD94FFC5218D9B90041E49AC53C6D6FB0CD1B59CE9AA0FC8B5E584EF2AC261B30354675A04BA9CDD34C665732CA32F8BF64CA7A9E44A8D1BA0EADE42A4C2C7CCE9",
- "identity_type": "provisioned",
- "iv": "738D2E87250EBA0133B45061C943FD51",
- "key_seed": "8A91F91C0C7164722766182BEFE0C7676AE00DEF732D440FAC83E1C046BE96F8",
- "metadata_key": "C373EBB8A7AE60D0845F6D3E3DB0F466",
- "section_mic_hmac_key": "A67E1FCB4BE3644D1F8B613607C1AA671F9271C33E463569600D799F07B6D557",
- "section_salt": "5A42B78DFE6ECD8495FD94FFC5218D9B"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A4F5D9BA01D3BE606F216EBAD7775C60",
- "aes_key": "A9ED3079B7139B65069F9D03015280B3",
- "data_elements": [],
- "encoded_section": "3790130E4539939983645FFCD1D23BA41A0C7B911000EC62B07DEFAAD4E56591479BEFBE6224900422DC0DE0453B7C022EA9CA53AE356878",
- "identity_type": "provisioned",
- "iv": "4E934E8CD83DF483CA10D638290AA616",
- "key_seed": "44C2B3506DCEB5A58E373F469167188F4F806E5543358C29CF8A3BCEC1DD5722",
- "metadata_key": "D2B68CCA820BEEBBD9F539D605DF3DCA",
- "section_mic_hmac_key": "8D76FBB29C7430E47F34C044AFFFEB3F3BDFFD257B8DD69AA4F5C3FBC9E8A923",
- "section_salt": "EC62B07DEFAAD4E56591479BEFBE6224"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5F6FB995D7CC9770A1045F3A9F40CA81",
- "aes_key": "242F9B8083541ED747A8BBDFCA8ECDA9",
- "data_elements": [
- {
- "contents": "0F12B68A338AAFA90DE62513B994AB5F8F1494C7079FFDF1",
- "de_type": 233
- }
- ],
- "encoded_section": "529013E54379FA3C4A05471414BB4A36EBAB09911000145B207075C013CA154C2913861B1AA09002ABC9352B5B4386BFC54CDF208613E44078F3A071B32DD27ED6033ACC3FA4C1FD4F207FF131DC16D300F123",
- "identity_type": "trusted",
- "iv": "F98E66FF52AB84CFA560C55213C7F797",
- "key_seed": "E36464273854858918F264C2C20998686BBC15865B7800265D4CA044BCEDAFA4",
- "metadata_key": "64DE8C2420A8C35F2790555177AD2FB5",
- "section_mic_hmac_key": "2B5B7C883EDE52F3F0CDBB631C818C4F979DF1A577716C1F2DC06F5F187B66BD",
- "section_salt": "145B207075C013CA154C2913861B1AA0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F87B918636F2CCA6489523D683C7794A",
- "aes_key": "42C6CC3C0F38EF9F9F90D66FCE0E7F2A",
- "data_elements": [
- {
- "contents": "CA17436867B321AB43AEDC6B17B5F7E2B70F",
- "de_type": 287
- },
- {
- "contents": "3F3980E7C64BEDC344F09E8A38EC428699F46B4730",
- "de_type": 1000
- },
- {
- "contents": "425DE4D96BE2CC3BC3157FDA90E79329D55A475866",
- "de_type": 960
- }
- ],
- "encoded_section": "7C901313F5E405835EFB18227A9A724CBDF2CB911000C071FB4FBFAD007203E02441A50CF9E7900408F48FC18E9E5AB227158F46527D2DF1E3E8B5860EF2B8D15F4267B131735E0E883A0EE7F9702CB3BB73EEB51FCC3086D903053EE88C2B19D0DA3D7854ACB4DF69317530486D18ED42617F74FD5820C7A1B33229E7",
- "identity_type": "provisioned",
- "iv": "EF3F84E7847D4B31B3FF9B5B0428550D",
- "key_seed": "F486B9021DA5ED704CFDBD9825F6D70A5906482EDEABF0226FB45DD75FB969A8",
- "metadata_key": "C5D3486E302957ADD4338FEFBE46B3D6",
- "section_mic_hmac_key": "96D349AEC4ADB8D9510E3A3093A0C782CF8EA7B6FCF1CC8ED7B5EE269DB1948C",
- "section_salt": "C071FB4FBFAD007203E02441A50CF9E7"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "A7711441846DEA01B5B115B07EE0E586",
- "aes_key": "DF79F55B1148D2412CE4907F5017A956",
- "data_elements": [],
- "encoded_section": "37901336311674D31A1B1ABCA412E87C7206BF91100000E2924EE1771AC6B83C73EE8A6EF9C690013F081118E055F4F4DAA14FBC14EC82BA",
- "identity_type": "private",
- "iv": "18A45DB774486000FB318F4D68FC75DD",
- "key_seed": "02F2C8B3CDA9BC0D8B46B5ABFF653966E444DB5F5A2471474CFB15D5F8D0FE64",
- "metadata_key": "23BDAA88D6A6ABEB5C52575E903B68DE",
- "section_mic_hmac_key": "55730CBE224F5744D3ABC9666FAFAE3075A3AB1BA891CA8D050E32BB644A4479",
- "section_salt": "00E2924EE1771AC6B83C73EE8A6EF9C6"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "77A40860E9F2D85C18352FE4DA31AE6E",
- "aes_key": "F7EB2CE11EE2C72B3E98A799AE37B71D",
- "data_elements": [
- {
- "contents": "60ABBA2292C2",
- "de_type": 249
- },
- {
- "contents": "A4870338A81FFC6CEAE2C7",
- "de_type": 779
- },
- {
- "contents": "B63A10F37A861B79084AA7C6F0C79BE8DBE1B308C7A01C0ABC2A",
- "de_type": 711
- },
- {
- "contents": "640CDFF15C509989A5BFA77595B5CE348F4E31F6FD34027B08",
- "de_type": 410
- }
- ],
- "encoded_section": "8790133735FEFE7C6C40C0AE2247E7E636393191100025B25F70B4E9701CD2E3D445FBAE117890018D0D255253A4086BE0770494720E0660480571F5F2218A4DAC55FB99D9D18AC77ECD3E4D6C73B27443D8FD663193029BDA29F6394E6F93DB00C33C8F4FF3CC95AD718972008088394F42C6E7A13B8C1374D4F666D6B8179B1AFAAF9BB23E80A4",
- "identity_type": "private",
- "iv": "7A1B11E2E1BBFC21137D5DB6812BECF8",
- "key_seed": "71564841B0C867D87B9EDCB4BD520E0697AF8F85E3782D3430B8BC37DD23B43D",
- "metadata_key": "3A3DCC0C22746DF5545BDD3BA1684B67",
- "section_mic_hmac_key": "5CC0B01B3F01D3099CBF99A7D3F71F0A91E6FDB26818353271F1B455763BCBAD",
- "section_salt": "25B25F70B4E9701CD2E3D445FBAE1178"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "4F1859CAFEFC8C2B5658B634D7678C20",
- "aes_key": "CFCE78B7C4624ADD1507D3D9A63EF82F",
- "data_elements": [
- {
- "contents": "DE41EA88487B4999D93602",
- "de_type": 499
- },
- {
- "contents": "48C8543DF38BB0CB7A4B439160",
- "de_type": 22
- },
- {
- "contents": "35210282",
- "de_type": 730
- },
- {
- "contents": "75BD",
- "de_type": 338
- },
- {
- "contents": "92668CFD5C1B",
- "de_type": 956
- }
- ],
- "encoded_section": "69901392227E7E09CD7396BFBD624A49AABC7E9110000DB9529357BB517E42EDFDC2FE4DC8B090013B4FEF7464D942431636A3E5860668B2FED6C3283B785E83A3BC45B1512C66F382BF7AD7868A9CAB33ABB4D335035B21D1E4396C945F1B8066E8568CC40BCE5D9A5C",
- "identity_type": "private",
- "iv": "2259C71FC8CDC81D9403EF089F159308",
- "key_seed": "7C22FDE6E42BEF50DB73033774ADC18BAF2A3C0A53CA30D36ACFC5582EB25100",
- "metadata_key": "DB170CBF39A5D48D3F6B0D40140A4257",
- "section_mic_hmac_key": "35235B50A5E921ABEFF4BF621956CA22F581D42BB3325A39C8C2D102F75D333E",
- "section_salt": "0DB9529357BB517E42EDFDC2FE4DC8B0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "0985A4C1FC767EF248AFAA00E0ED2E47",
- "aes_key": "0CE73306D8D0AB56045815F2AD20B25A",
- "data_elements": [
- {
- "contents": "D3D3905C6BEA12C7123B74AB40858D04",
- "de_type": 792
- },
- {
- "contents": "713F3EB42E57458D4038D809B35106DFF259EA4C4F1F17819E96",
- "de_type": 720
- }
- ],
- "encoded_section": "6790130FC5A44C70B4AD43316DD6D38C4A4845911000026C2E6E34CC1156B5E7EE8221D4A7F290043DD0DB3E9C9BF801CB74473C77DDE2D6329F38BFBD336FE971057F3D2C8C8EF610AFCBF1A5D8C24EFDA93762195F1A863CDC617CB8D317746EA52A7BB0961F3F",
- "identity_type": "provisioned",
- "iv": "D732D335C908BBF51DFFC3F80FBC75C7",
- "key_seed": "F72828A9E550CCB3EE653BEA22E097839072D8D60280AFC2FBE2435D5095979F",
- "metadata_key": "ADC1B18C69F7FD30DAC6EC2696F70EAE",
- "section_mic_hmac_key": "0F64E025E91492D0AC4434D844FF48CD98C61BCD3E25F9CCC8E1333A81D27A9D",
- "section_salt": "026C2E6E34CC1156B5E7EE8221D4A7F2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F753952E84F321276818619F5E2DB7A5",
- "aes_key": "BA5479576FEC84060B7986F71751215E",
- "data_elements": [
- {
- "contents": "174BFD",
- "de_type": 274
- },
- {
- "contents": "99B7C0C5CE238C6F963A4722865CFACADBBA8B95B18C70AD4267727F81",
- "de_type": 212
- },
- {
- "contents": "2EF69250213CDA930A85A93BA85F087B9780",
- "de_type": 81
- },
- {
- "contents": "87",
- "de_type": 13
- }
- ],
- "encoded_section": "739013700384F06906581AC9BCFBCBC2AD496491100096C7B1C5DEFCAFC64251AC87CDCEFCED9001D2B0215328C8DB53DECBDB25F97DBA53A67D02E1DC1F83D6E91AC7B2CF8DCCA4277ED359F6838431E078A50199B4310AEA200307AB216B82348B0024206A6D0A3C79E89CBD254D8426E7BEC1",
- "identity_type": "private",
- "iv": "FFA79DBF3BA0EBDE530A72A2D8018930",
- "key_seed": "132DDE0DAAAC4F4A03CF1CB2B8F4A8FE41327C212AC3CE1B1C854EFA2EE3060B",
- "metadata_key": "E61C0407C95D18D5DA193C062801B3F2",
- "section_mic_hmac_key": "65CF0A0155EEC7EAABA2C02875F773696CECBDC64FB57E0BB9B7884B174EAF42",
- "section_salt": "96C7B1C5DEFCAFC64251AC87CDCEFCED"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "7C6A90B2F9FAC1C86AEFF121052D076C",
- "aes_key": "E73FDA1B40CF93E9561E963B728E2D8B",
- "data_elements": [
- {
- "contents": "B4F512F3B1639C980A124C94E365",
- "de_type": 848
- }
- ],
- "encoded_section": "489013E7D5DEA0D3B68FCB72D18D623072BDE991100089D76603BB207098A3E6631BFBEF7C329004FB1B665EBA76ACCCE96C07AD83F4BC53948171B9D2DD42122AAAEBF0827973918D",
- "identity_type": "provisioned",
- "iv": "7B8C0BE7E83DFE973D0817AEB6CB6F63",
- "key_seed": "67E08A4FC51867E3A0F57543149D05A2B1DD58C2B77B39F5F4EC5B707007E46A",
- "metadata_key": "AF5A1254567F43ED18CCC0C024010B4B",
- "section_mic_hmac_key": "8914563971948EA279A2189CDC04749B53E5DA3429FDA1C6F161E96465A76413",
- "section_salt": "89D76603BB207098A3E6631BFBEF7C32"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "FB3EAE2C571C503CED9B656B14BFD0B8",
- "aes_key": "30A2ECDA5B5CADF19936D88CD6078144",
- "data_elements": [
- {
- "contents": "908D4CC782C9EC6222B92FEF8662DF086B",
- "de_type": 816
- },
- {
- "contents": "2E23352D",
- "de_type": 290
- }
- ],
- "encoded_section": "5290131C34CA643645201E9143E49FEFFBC4C29110000290E81B48B49A315AF4EB0A583B626E9004D8209185C733910032E4252CF793BAD9F4F50FEFC22E595EF0FABD10B50361B7AEF6780F22A2AB9E82D359",
- "identity_type": "provisioned",
- "iv": "83D6520D6383658D1BCEE9223496A13B",
- "key_seed": "C33B862F2494CC516A5CB13A5B8F8905E854AD720F4AEB3C2A0788B194920AC5",
- "metadata_key": "1170B8A823A46A9F89D03AB849A8B6C7",
- "section_mic_hmac_key": "618F13964E241E73FE3D19F653606FD22DC35E8B402BBE581766F12918B2C749",
- "section_salt": "0290E81B48B49A315AF4EB0A583B626E"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "8CD348B153FFFF829FF59CE087B45052",
- "aes_key": "0BA7C51985112928B9DC28E7F65425F1",
- "data_elements": [
- {
- "contents": "5749",
- "de_type": 817
- },
- {
- "contents": "F5B9E550C46360EC4810134DAA69B4775E96F03AE0",
- "de_type": 10
- },
- {
- "contents": "C213FC8E1F6F5335E8",
- "de_type": 937
- }
- ],
- "encoded_section": "5F9013088BC9173D4977CA45D6A1C619348876911000C5D9A37193D9E39A5EDB0F67163977C49001D8FEA804E8BC4013FD7B414D7FEF6ECE162DB0B42893FFBC581ED0B3A3AEABD9530827277802B92E4C2C55F628405E6EA653E237A672ADB1",
- "identity_type": "private",
- "iv": "A135C384B47C184EC4482051FF8C2E31",
- "key_seed": "07B091E071F437A31B8703BBC3936997184E61121AD4F7EB5F492E3DF8DCEA53",
- "metadata_key": "01A9B84A7827975243E7B3B2003D084A",
- "section_mic_hmac_key": "77B8E093C3E828051F2B2518EDEA3011F482628A8ADA7746887F96E340F412AE",
- "section_salt": "C5D9A37193D9E39A5EDB0F67163977C4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "B40F18FA69C0FC048DFB0AAA5B0AF0BF",
- "aes_key": "3709DF5F4E0A2AAE14602A75EF722DC2",
- "data_elements": [
- {
- "contents": "B753D510831709EA0C3D738C6033D01A271601AD5978633E9D",
- "de_type": 48
- },
- {
- "contents": "8367AFEE3BBC94F736A29A7E2714845B5360021AD4FC68FE97E0DF36",
- "de_type": 263
- },
- {
- "contents": "05D52FCEF6F06D00BF235214C2207E8FB73E3574515D1325A0F8",
- "de_type": 595
- },
- {
- "contents": "4958A61B59ECC3D66E",
- "de_type": 573
- },
- {
- "contents": "C4E5F7EA67D7A3F95CF318762C89",
- "de_type": 276
- }
- ],
- "encoded_section": "AB901366A1922F253CFA26D8D248EC4A83156A911000664460D3622578B621D4F753C362904090041092245FE1A57603009BC851D8758A0C7BAEC65F18C94BEE0C0CF6B209BF24B4EC66421EADC280BF1E943750125723D6D59E2B4E0325F9D439BEC4C630B1BC28613DD0F07C2BCDEE6F0A87E8C503B0A4DB22EA76CCA4D86815FA48A96D034570E6CC5FD1E888AE0435D5B784012AA6F0B2E32A10FEC8E2365DBE2A379355E3D65553E2BB",
- "identity_type": "provisioned",
- "iv": "6F4B43F8D4FABA78459CD81AA33BE4CC",
- "key_seed": "BACC0678BD1412CE8F69457D531543891E60D6D28FEA990794BFB40D21AA0949",
- "metadata_key": "884C8032F452425CDD66B638C8FB39F6",
- "section_mic_hmac_key": "3CEDAF60E90EA68B0E4B4FE3D631A93C699417513FCEC675EB4B0F685EC4BAD8",
- "section_salt": "664460D3622578B621D4F753C3629040"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "83E1288467CC4B24710B345A19B062D5",
- "aes_key": "3872F4A171D57E391B108FC34280941E",
- "data_elements": [
- {
- "contents": "FE41644BF9217FC149AE426A3A110D8684EB",
- "de_type": 837
- },
- {
- "contents": "CEA178B6B05E1B76FAB7B6C490BC2EAC7704BFD6",
- "de_type": 284
- },
- {
- "contents": "BF",
- "de_type": 363
- },
- {
- "contents": "A08F2A4028CEAD4E909837",
- "de_type": 141
- },
- {
- "contents": "DD907152A5",
- "de_type": 296
- }
- ],
- "encoded_section": "7D90135402E36E007ECD6B8F063C2AF686CEC59110006EC04E6CB0B5DCBCCA90417478CA71FA90010CE62BF979B4123E409ACD9785748E8A30110CD82591D58B1090BCAE8031E1EBCB0B50B914F9C3A616D670ADBBEACF2DA6D5A9E7903EA5A285EAB9FC52D80D54B98576FDEDA10E108BBCE4A44725D5D11AB69EDB3A11",
- "identity_type": "private",
- "iv": "948B1C0AEFF273FA05E61AB83A67B1E7",
- "key_seed": "948CFB8CE79FE0285B4F35335C83A9C12BE88049A60CDDA8A54F03EC5E8B188D",
- "metadata_key": "14FB446FDF7BC2DB3BB63D91B78835ED",
- "section_mic_hmac_key": "A50B781DE993B3D37EEED3B5957AF0A16DE356C4E5EA6206E010B8542B8180B8",
- "section_salt": "6EC04E6CB0B5DCBCCA90417478CA71FA"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "F7FA2B1220E713D37D5D4219E841D866",
- "aes_key": "6C09B48D2E9252886CB8476628E49EA6",
- "data_elements": [
- {
- "contents": "FE93A34B0B728ECB4A1A23B7",
- "de_type": 938
- }
- ],
- "encoded_section": "469013713B65A9B2834CC302E660F1516FDC529110004BAED26B52E7D85BAD585AACA26600A990012172B89B62912AE533F371A8CE4F587B90B48A534F119A5F6CB20BDD6FCD32",
- "identity_type": "private",
- "iv": "A6AD44BD75DDB36D3E11CA72047ED68C",
- "key_seed": "47690302DC37FEBF9C4D5CC6453DCEFC40DBB204E5A7A81D0B30E74247BCDA80",
- "metadata_key": "C114855EDA0E56FA324577137E531FEC",
- "section_mic_hmac_key": "B4904367A2141DBFE77167BAC1FE7D508DC07B7496B26448682FD7FF3215B8AB",
- "section_salt": "4BAED26B52E7D85BAD585AACA26600A9"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "397B5F51522DFEA7E1B243BC5D947FDA",
- "aes_key": "7BF127F44E510A7B407A4C35B82172B8",
- "data_elements": [
- {
- "contents": "9E3AD15489CC97EFA791DBD20D6D59F1D9A1D055F080076C9E0849",
- "de_type": 313
- },
- {
- "contents": "0F8046",
- "de_type": 262
- },
- {
- "contents": "3A76F640ADDA98B2009266BAEC469C8F33D2991D9AE4F48D13E5",
- "de_type": 693
- },
- {
- "contents": "B98E5D7725F819C7860151C7C6E0B6",
- "de_type": 970
- },
- {
- "contents": "8E497812B532C1731A1E42BB0D",
- "de_type": 131
- }
- ],
- "encoded_section": "9A9013623FFEC846FA4EC80AEEE5874F724150911000E4DCFCC4EE61C6352DF5285906A7ACA19002CE3757CF407DBA7A4AC984C7CE89DC1E5E88F6B6DE50085A04894DD3DDB94DBACD840C7744A81D9273C6D6B389314C7DE82B39FA0EEA7F9EF932B412F2B43EF444E59722BA59A51E54162417D4D510FFF996861298FC0346008F9A960744495B72F646ACA5B3607F8EA4C345AFD418DFE65A5F",
- "identity_type": "trusted",
- "iv": "DC4BBB79EC29CCC02C79BEBD45C7BB70",
- "key_seed": "874471CC674DCC5A5BD7E8207CB62F4862C69B6FB28F86BE947A8249F8AD45CA",
- "metadata_key": "B8420F0DC2CAD8BE94C2878461F62CA7",
- "section_mic_hmac_key": "A60A350281B1B0C59E0F9E44DE3F139D4D5278D21E9325B60A0C1099981C4D47",
- "section_salt": "E4DCFCC4EE61C6352DF5285906A7ACA1"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "14A4E23F310594A923AC2B00CD26FDDF",
- "aes_key": "033A7FAED90FD1A0FF7080EDC2D150AD",
- "data_elements": [],
- "encoded_section": "379013EE55550B8DB3B2D0626ABA7D899DCB1B911000F83C0914EC025DD986BF39B9AA4633D090018687E96989F94FF3D2365FB2CDB89BEF",
- "identity_type": "private",
- "iv": "E4838E64DC9F04328312FC0952FE1955",
- "key_seed": "32AC43A2C4F720EA7255D9B5025B7219801F4A728DAD5DE4C841480BFC6CAF0B",
- "metadata_key": "DCD150DA1D4622EA1FB364C64CC56352",
- "section_mic_hmac_key": "5713D6A91073B3FC250693CF7608174F7B5C8BB0B89717849AF78745F4BB74FA",
- "section_salt": "F83C0914EC025DD986BF39B9AA4633D0"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9A5A6E11C1791C48E6BC440FD2B275BC",
- "aes_key": "54D9612F2A7BE396A390954DFD2F2DB0",
- "data_elements": [],
- "encoded_section": "37901371B7C653BFB0E41F1BDA3228F707E39E91100058E26761B259F743F644564A6B23A0CC900155CA0E1E76DF190C54E9142FDBE55CFE",
- "identity_type": "private",
- "iv": "6B14BB04BBC14392A524A69EB6316F51",
- "key_seed": "965BB1781732640C7237DDD1679D07C089927C6A869442EBB23960B536262A9F",
- "metadata_key": "7FA623CCF685E489F680D2898580DD72",
- "section_mic_hmac_key": "D3FC8D9843906152A789A16A150C0BAACA74BB5AF33A886552CBFA7C6D529029",
- "section_salt": "58E26761B259F743F644564A6B23A0CC"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "64006DB572776637FD097DE973732A7B",
- "aes_key": "669E44E9F98F153D8179E44A19F25623",
- "data_elements": [
- {
- "contents": "7B",
- "de_type": 638
- },
- {
- "contents": "F00D4AB2C34F139458F1AF9265FA9EA175ED4EE85167",
- "de_type": 958
- },
- {
- "contents": "87417FB6114F",
- "de_type": 499
- },
- {
- "contents": "683ED3E93B91EB3FAED44E29457BE80D878415985D41B5F460",
- "de_type": 129
- }
- ],
- "encoded_section": "7990133E374729219551A1BB61EFF4D5AD6B6791100034159DC9EEC690F4ECD6A20A569E8CD29002A28031BC640DEB07E8AC9C7F941289B1327A5247718B0AD60B2A8769AF9749567EAF8A236425CDDF878FE17A735BF4AAB4ECCC4FC34AF217238857F87A06AE9EFAEC7C85452D2439BC5E9E08CF568AB5C7FD",
- "identity_type": "trusted",
- "iv": "26F5D4D8B5EB6069AEF2B6E435D30DB8",
- "key_seed": "15A1B8E687F0DF912101CE373495959EE40D2D1FECB951B41C87DB9A0B4C3EF2",
- "metadata_key": "4ED47FC3167C69F90160E2A9BDDC6A8B",
- "section_mic_hmac_key": "7DE079745790A823A62470384F692A5CE4AD1C757AFE96917811EF13AD2CC8BC",
- "section_salt": "34159DC9EEC690F4ECD6A20A569E8CD2"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5DDB5AA2FA3F0A61D18C52E9DE22CDE6",
- "aes_key": "E60C3ACE2E521468137DAE60C115B3F5",
- "data_elements": [
- {
- "contents": "8DD936",
- "de_type": 244
- }
- ],
- "encoded_section": "3D90138C161B53E44488EDAE5C545A49CB632F9110007272DFA635A1B1F42A62BE9147CCC4429004CE40129E8D256DA63B8B6AFA1FD16791EB33FD546813",
- "identity_type": "provisioned",
- "iv": "C03127C86766B5299AA2A30C42931072",
- "key_seed": "A0F876D63DFEBBBC68F52B9A52582992D53E8DBC84DCA86598DDD6B41F1994D8",
- "metadata_key": "189A12F2813D0C3D6E6A852F1298AE8A",
- "section_mic_hmac_key": "853A31A3BBD636810AE5DEA65BC5739408F9D7DC1661B56D0E54A60A9C59DFE8",
- "section_salt": "7272DFA635A1B1F42A62BE9147CCC442"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "9D031FAD682DAA4BBCA6912CCBB83C09",
- "aes_key": "E1B5FA0F1A67F72E01B807F6495C6393",
- "data_elements": [
- {
- "contents": "BA0688D5",
- "de_type": 327
- },
- {
- "contents": "CB0502569855FDA6DDA289FB7CA7F8447CB118E542",
- "de_type": 880
- },
- {
- "contents": "99FF",
- "de_type": 940
- },
- {
- "contents": "",
- "de_type": 195
- }
- ],
- "encoded_section": "5E9013101E7BB804EC51155AFE647EF89D6FAB91100042441ECF37BAF5319477A42541165CE49001AB8ACECCD8F482909FBC48F308CE76945B74681CE578A664996962BF4F4960586B4D100A83BCEFC21C073BE5407B32F6FE37E4181A8416",
- "identity_type": "private",
- "iv": "006B7FFEC2A4BC7AF80376E12B9CF206",
- "key_seed": "3FDC2376B9AA5ABAA54091F4C3D17E62453E5C4BCA3F7E97D02C087E3D3E56EC",
- "metadata_key": "2A9A5CD0C8BBE65B4DA2AC93A3646ADB",
- "section_mic_hmac_key": "409C1FA5A935DF46FD0B0BA1F4B6676DC8E53F92992C41B1E167DCAAF92C6B75",
- "section_salt": "42441ECF37BAF5319477A42541165CE4"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "402E548FE3E9094AE8327C5D67323EF3",
- "aes_key": "74A450709337C059E4B06AA7339A847A",
- "data_elements": [
- {
- "contents": "DDEE0C575B876057217E9EBD9A54DC6DDEC5E09A7C8B5AF9B2699B2F4D",
- "de_type": 370
- },
- {
- "contents": "CD8ECC401DC9D100AB80772990FD586CD51C0F63BCC51C1BC1",
- "de_type": 762
- },
- {
- "contents": "D4219120DC8A3A5A31C38174E515",
- "de_type": 447
- },
- {
- "contents": "A7B56D78AA8970937A2B0E39A94148EFE9BE381F0B",
- "de_type": 890
- },
- {
- "contents": "4C4E4BB8BC53C76E9BDEDAAF9D853E00A0556A6A",
- "de_type": 561
- }
- ],
- "encoded_section": "B39013556E8D35D3BFBCC66BA7FE806642527C9110005AFB2CBC5F6FF709C77C5E5B44FEC2639001302F90C4EE1CC3A669EBC8C94F549755BCBC764D07AC7B44259C7E72BAD6B0603D2618A56A1D5D9D0F8F3361A4F4BA89B14F98D3E27F95F1CA5DB58B7C9710E5785C12C126D0199B28A6955E728FE9E0D56AEA4522B7289D149FFA9AC110B751ACC06CD17F40F3E0EE67191DAF9E12EF7897E526F0037E46E22CD772FFB6A8FA8A6075E7BD51BE635A620EE8",
- "identity_type": "private",
- "iv": "91B130A57119A917BE672E882CD24F0A",
- "key_seed": "349BAC58EA19F4DFC1E615A8F712C39D4A8F9D9371C92914FF7FEB3273EAFA96",
- "metadata_key": "ECB79F56C63D39774DA1093D67A2E2BE",
- "section_mic_hmac_key": "EC055CD96AA83E58972330916292606A56E320F4078D3E37125FD521366D2C13",
- "section_salt": "5AFB2CBC5F6FF709C77C5E5B44FEC263"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "5FC40591E60B01771FD86CA3E3EFBAA9",
- "aes_key": "527134D81C8BB7C6BECF31F34C4FB7EF",
- "data_elements": [
- {
- "contents": "342CFE0C131BCA582A2B7F241FDDC5ECF120E98493391304BAFA",
- "de_type": 217
- }
- ],
- "encoded_section": "5490131A3E437EC13FDD67C82E5A3E273E9CD391100014444BDF8E6863B041C4F0C1CDEC855D900484ADD7102010AF6513B7367DD4D398FC2D1670B31EB05EB75F6451ABC3AF64D23D067AD0B26AEDEC08DD6BF5F5",
- "identity_type": "provisioned",
- "iv": "B58720B7A9092A88B216BDC537A2C0C6",
- "key_seed": "7795E9287DF02DB694AA5A17909EF3ABAF2B3A67D317F0BA403077B148680D3A",
- "metadata_key": "719D474AF4AC20EA51773F7D689FCBC8",
- "section_mic_hmac_key": "CA2941EF019C602CD34C2D7A728687EBB9D640E5DFA764616AB435EF32B4955E",
- "section_salt": "14444BDF8E6863B041C4F0C1CDEC855D"
- },
- {
- "adv_header_byte": "30",
- "adv_salt": "64E4BB1721EA0A79B18FA4CF2DFCF10C",
- "aes_key": "4FC66B746D81042C4012C9CA05EB0F52",
- "data_elements": [
- {
- "contents": "F3F4EFB14E81119C7C2E98F2",
- "de_type": 608
- },
- {
- "contents": "C41DD9601061BB775DBC3608789A30523E95B3B05B",
- "de_type": 966
- },
- {
- "contents": "B33460D6D8E3DF0ADF19BDD666E4",
- "de_type": 973
- },
- {
- "contents": "CDE289B7ECC9B6CDE5EA6BB595AC3019FE7F",
- "de_type": 480
- }
- ],
- "encoded_section": "849013AACDF54AA823590AF5804916E75A4517911000EF56099BC3FE4347649E0E59527C7A6190015C377B56675F536A451BF7CCFB4F79940DFE2ACB47AFB42B017C572E08DF98CFA55C5EC810CBEC57BC340A59E1F3414E7FCA6E17CD675EC950EFCCA7F589D4187557EA6AEA5F0E752B32C9540691FA07A9904598AE2FF4703638729108",
- "identity_type": "private",
- "iv": "9862F303568F4CEEEE16790805706ADC",
- "key_seed": "790EEE3F64023DF0E967BECC5F9C1881A0E23AABE20BF85D35F0CA9E212D4C9B",
- "metadata_key": "5C624608CAB1BE8DE5DF6A058AC025AE",
- "section_mic_hmac_key": "F6216E6FCE355E0BD447D8B39A621A566767EEC8EE2F3AF3E86777DCC894B63B",
- "section_salt": "EF56099BC3FE4347649E0E59527C7A61"
- }
-]
-
diff --git a/nearby/presence/np_adv/tests/examples_v0.rs b/nearby/presence/np_adv/tests/examples_v0.rs
index f7b7d5e..b00fd61 100644
--- a/nearby/presence/np_adv/tests/examples_v0.rs
+++ b/nearby/presence/np_adv/tests/examples_v0.rs
@@ -15,21 +15,25 @@
use crypto_provider_default::CryptoProviderImpl;
use ldt_np_adv::*;
-use np_adv::legacy::data_elements::TxPowerDataElement;
+use np_adv::credential::matched::{
+ EmptyMatchedCredential, HasIdentityMatch, MetadataMatchedCredential,
+};
+use np_adv::legacy::serialize::{AdvBuilder, LdtEncoder};
use np_adv::{
credential::{
book::CredentialBookBuilder,
- v0::{V0DiscoveryCredential, V0},
- EmptyMatchedCredential, MatchableCredential, MetadataMatchedCredential,
- SimpleBroadcastCryptoMaterial,
+ v0::{V0BroadcastCredential, V0DiscoveryCredential, V0},
+ MatchableCredential,
+ },
+ legacy::{
+ data_elements::tx_power::TxPowerDataElement, deserialize::*, V0AdvertisementContents,
},
- de_type::*,
- legacy::{deserialize::*, ShortMetadataKey},
shared_data::*,
*,
};
use serde::{Deserialize, Serialize};
+#[rustfmt::skip]
#[test]
fn v0_deser_plaintext() {
let cred_book = CredentialBookBuilder::<EmptyMatchedCredential>::build_cached_slice_book::<
@@ -41,21 +45,19 @@ fn v0_deser_plaintext() {
let adv = deserialize_advertisement::<_, CryptoProviderImpl>(
arena,
&[
- 0x00, // adv header
- 0x03, // public identity
+ 0x00, // version header
0x15, 0x03, // Length 1 Tx Power DE with value 3
],
&cred_book,
)
- .expect("Should be a valid advertisement")
- .into_v0()
- .expect("Should be V0");
+ .expect("Should be a valid advertisement")
+ .into_v0()
+ .expect("Should be V0");
match adv {
V0AdvertisementContents::Plaintext(p) => {
- assert_eq!(PlaintextIdentityMode::Public, p.identity());
assert_eq!(
- vec![PlainDataElement::TxPower(TxPowerDataElement::from(
+ vec![DeserializedDataElement::TxPower(TxPowerDataElement::from(
TxPower::try_from(3).unwrap()
))],
p.data_elements().collect::<Result<Vec<_>, _>>().unwrap()
@@ -84,42 +86,45 @@ impl IdentityMetadata {
}
}
+#[rustfmt::skip]
#[test]
fn v0_deser_ciphertext() {
// These are kept fixed in this example for reproducibility.
// In practice, these should instead be derived from a cryptographically-secure
// random number generator.
let key_seed = [0x11_u8; 32];
- let metadata_key: [u8; NP_LEGACY_METADATA_KEY_LEN] = [0x33; NP_LEGACY_METADATA_KEY_LEN];
- let metadata_key = ShortMetadataKey(metadata_key);
+ let identity_token = V0IdentityToken::from([0x33; V0_IDENTITY_TOKEN_LEN]);
- let broadcast_cm = SimpleBroadcastCryptoMaterial::<V0>::new(key_seed, metadata_key);
+ let broadcast_cred = V0BroadcastCredential::new(key_seed, identity_token);
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let metadata_key_hmac: [u8; 32] =
- hkdf.legacy_metadata_key_hmac_key().calculate_hmac(&metadata_key.0);
+ let identity_token_hmac: [u8; 32] =
+ hkdf.v0_identity_token_hmac_key().calculate_hmac::<CryptoProviderImpl>(&identity_token.bytes());
// Serialize and encrypt some identity metadata (sender-side)
let sender_metadata =
IdentityMetadata { name: "Alice".to_string(), email: "alice@gmail.com".to_string() };
let sender_metadata_bytes = sender_metadata.to_bytes();
- let encrypted_sender_metadata = MetadataMatchedCredential::<Vec<u8>>::encrypt_from_plaintext::<
- _,
- _,
- CryptoProviderImpl,
- >(&broadcast_cm, &sender_metadata_bytes);
+ let encrypted_sender_metadata = MetadataMatchedCredential::<Vec<u8>>::
+ encrypt_from_plaintext::<V0, CryptoProviderImpl>(&hkdf,
+ identity_token,
+ &sender_metadata_bytes);
// output of building a packet using AdvBuilder
let adv = &[
- 0x00, // adv header
- 0x21, // private DE w/ a 2 byte payload
+ 0x04, // version header
0x22, 0x22, // salt
// ciphertext for metadata key & txpower DE
- 0x85, 0xBF, 0xA8, 0x83, 0x58, 0x7C, 0x50, 0xCF, 0x98, 0x38, 0xA7, 0x8A, 0xC0, 0x1C, 0x96,
- 0xF9,
+ 0xD8, 0x22, 0x12, 0xEF, 0x16, 0xDB, 0xF8, 0x72, 0xF2, 0xA3, 0xA7,
+ 0xC0, 0xFA, 0x52, 0x48, 0xEC
];
- let discovery_credential = V0DiscoveryCredential::new(key_seed, metadata_key_hmac);
+ // make sure output hasn't changed
+ let mut builder = AdvBuilder::new(LdtEncoder::<CryptoProviderImpl>::new([0x22; 2].into(), &broadcast_cred));
+ builder.add_data_element(TxPowerDataElement::from(TxPower::try_from(3).unwrap())).unwrap();
+ assert_eq!(adv, builder.into_advertisement().unwrap().as_slice());
+
+ let discovery_credential = V0DiscoveryCredential::new(key_seed, identity_token_hmac);
let credentials: [MatchableCredential<V0, MetadataMatchedCredential<_>>; 1] =
[MatchableCredential { discovery_credential, match_data: encrypted_sender_metadata }];
@@ -134,12 +139,12 @@ fn v0_deser_ciphertext() {
adv,
&cred_book,
)
- .expect("Should be a valid advertisement")
- .into_v0()
- .expect("Should be V0")
+ .expect("Should be a valid advertisement")
+ .into_v0()
+ .expect("Should be V0")
{
V0AdvertisementContents::Decrypted(c) => c,
- _ => panic!("this examples is ciphertext"),
+ _ => panic!("this example is ciphertext"),
};
let decrypted_metadata_bytes = matched
@@ -152,12 +157,10 @@ fn v0_deser_ciphertext() {
let decrypted = matched.contents();
- assert_eq!(EncryptedIdentityDataElementType::Private, decrypted.identity_type());
-
- assert_eq!(metadata_key, decrypted.metadata_key());
+ assert_eq!(identity_token, decrypted.identity_token());
assert_eq!(
- vec![PlainDataElement::TxPower(TxPowerDataElement::from(TxPower::try_from(3).unwrap())),],
+ vec![DeserializedDataElement::TxPower(TxPowerDataElement::from(TxPower::try_from(3).unwrap())),],
decrypted.data_elements().collect::<Result<Vec<_>, _>>().unwrap(),
);
}
diff --git a/nearby/presence/np_adv/tests/examples_v1.rs b/nearby/presence/np_adv/tests/examples_v1.rs
index 6e93a3d..57e41fa 100644
--- a/nearby/presence/np_adv/tests/examples_v1.rs
+++ b/nearby/presence/np_adv/tests/examples_v1.rs
@@ -14,36 +14,45 @@
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::indexing_slicing, clippy::panic)]
-use crypto_provider::{CryptoProvider, CryptoRng};
+use crypto_provider::{ed25519, CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
-use np_adv::extended::data_elements::TxPowerDataElement;
-use np_adv::extended::serialize::{AdvertisementType, PublicSectionEncoder, SingleTypeDataElement};
-use np_adv::extended::NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT;
-use np_adv::shared_data::TxPower;
+use np_adv::credential::matched::{
+ EmptyMatchedCredential, MetadataMatchedCredential, WithMatchedCredential,
+};
+use np_adv::extended::deserialize::{Section, V1DeserializedSection};
+use np_adv::extended::{V1IdentityToken, V1_ENCODING_UNENCRYPTED};
use np_adv::{
credential::{
book::CredentialBookBuilder,
- v1::{SimpleSignedBroadcastCryptoMaterial, V1DiscoveryCredential, V1},
- EmptyMatchedCredential, MatchableCredential, MetadataMatchedCredential,
+ v1::{V1BroadcastCredential, V1DiscoveryCredential, V1},
+ MatchableCredential,
},
- de_type::*,
+ deserialization_arena, deserialize_advertisement,
extended::{
- deserialize::{Section, VerificationMode},
- serialize::{AdvBuilder, SignedEncryptedSectionEncoder},
+ data_elements::TxPowerDataElement,
+ deserialize::VerificationMode,
+ serialize::{
+ AdvBuilder, AdvertisementType, SignedEncryptedSectionEncoder, SingleTypeDataElement,
+ UnencryptedSectionEncoder,
+ },
+ NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT,
},
- PlaintextIdentityMode, *,
+ shared_data::TxPower,
+ AdvDeserializationError, AdvDeserializationErrorDetailsHazmat,
};
-use np_hkdf::v1_salt;
+use np_hkdf::{v1_salt, DerivedSectionKeys};
use serde::{Deserialize, Serialize};
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
+
#[test]
fn v1_deser_plaintext() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
- let mut section_builder = adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de(|_salt| TxPowerDataElement::from(TxPower::try_from(6).unwrap()))
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
let cred_book = CredentialBookBuilder::<EmptyMatchedCredential>::build_cached_slice_book::<
@@ -69,12 +78,11 @@ fn v1_deser_plaintext() {
V1DeserializedSection::Plaintext(s) => s,
_ => panic!("this is a plaintext adv"),
};
- assert_eq!(PlaintextIdentityMode::Public, section.identity());
let data_elements = section.iter_data_elements().collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(1, data_elements.len());
let de = &data_elements[0];
- assert_eq!(v1_salt::DataElementOffset::from(1), de.offset());
+ assert_eq!(v1_salt::DataElementOffset::from(0), de.offset());
assert_eq!(TxPowerDataElement::DE_TYPE, de.de_type());
assert_eq!(&[6], de.contents());
}
@@ -104,14 +112,13 @@ impl IdentityMetadata {
fn v1_deser_ciphertext() {
// identity material
let mut rng = <CryptoProviderImpl as CryptoProvider>::CryptoRng::new();
- let metadata_key: [u8; 16] = rng.gen();
- let metadata_key = MetadataKey(metadata_key);
- let key_pair = np_ed25519::KeyPair::<CryptoProviderImpl>::generate();
+ let token_array: [u8; 16] = rng.gen();
+ let identity_token = V1IdentityToken::from(token_array);
+ let private_key = ed25519::PrivateKey::generate::<Ed25519ProviderImpl>();
let key_seed = rng.gen();
let hkdf = np_hkdf::NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
- let broadcast_cm =
- SimpleSignedBroadcastCryptoMaterial::new(key_seed, metadata_key, key_pair.private_key());
+ let broadcast_cred = V1BroadcastCredential::new(key_seed, identity_token, private_key.clone());
// Serialize and encrypt some identity metadata (sender-side)
let sender_metadata = IdentityMetadata {
@@ -121,36 +128,40 @@ fn v1_deser_ciphertext() {
};
let sender_metadata_bytes = sender_metadata.to_bytes();
let encrypted_sender_metadata = MetadataMatchedCredential::<Vec<u8>>::encrypt_from_plaintext::<
- _,
- _,
+ V1,
CryptoProviderImpl,
- >(&broadcast_cm, &sender_metadata_bytes);
+ >(&hkdf, identity_token, &sender_metadata_bytes);
// prepare advertisement
let mut adv_builder = AdvBuilder::new(AdvertisementType::Encrypted);
let mut section_builder = adv_builder
- .section_builder(SignedEncryptedSectionEncoder::<CryptoProviderImpl>::new_random_salt(
+ .section_builder(SignedEncryptedSectionEncoder::new_random_salt::<CryptoProviderImpl>(
&mut rng,
- EncryptedIdentityDataElementType::Private,
- &broadcast_cm,
+ &broadcast_cred,
))
.unwrap();
section_builder
.add_de(|_salt| TxPowerDataElement::from(TxPower::try_from(7).unwrap()))
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
let adv = adv_builder.into_advertisement();
let discovery_credential = V1DiscoveryCredential::new(
key_seed,
+ [0; 32],
[0; 32], // Zeroing out MIC HMAC, since it's unused in examples here.
- hkdf.extended_signed_metadata_key_hmac_key().calculate_hmac(&metadata_key.0),
- key_pair.public().to_bytes(),
+ hkdf.v1_signature_keys()
+ .identity_token_hmac_key()
+ .calculate_hmac::<CryptoProviderImpl>(identity_token.bytes()),
+ private_key.derive_public_key::<Ed25519ProviderImpl>(),
);
let credentials: [MatchableCredential<V1, MetadataMatchedCredential<_>>; 1] =
- [MatchableCredential { discovery_credential, match_data: encrypted_sender_metadata }];
+ [MatchableCredential {
+ discovery_credential,
+ match_data: encrypted_sender_metadata.clone(),
+ }];
let cred_book = CredentialBookBuilder::build_cached_slice_book::<0, 0, CryptoProviderImpl>(
&[],
&credentials,
@@ -181,21 +192,52 @@ fn v1_deser_ciphertext() {
let section = matched.contents();
- assert_eq!(EncryptedIdentityDataElementType::Private, section.identity_type());
assert_eq!(VerificationMode::Signature, section.verification_mode());
- assert_eq!(metadata_key, section.metadata_key());
+ assert_eq!(&identity_token, section.identity_token());
let data_elements = section.iter_data_elements().collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(1, data_elements.len());
let de = &data_elements[0];
- assert_eq!(v1_salt::DataElementOffset::from(2), de.offset());
+ assert_eq!(v1_salt::DataElementOffset::from(0), de.offset());
assert_eq!(TxPowerDataElement::DE_TYPE, de.de_type());
assert_eq!(&[7], de.contents());
+
+ // Uncomment if you need to regenerate C++ v1_private_identity_tests data
+ // {
+ // use test_helper::hex_bytes;
+ // use np_adv::extended::salt::MultiSalt;
+ // use np_adv_credential_matched::MatchedCredential;
+ // println!("adv:\n{}", hex_bytes(adv.as_slice()));
+ // println!("key seed:\n{}", hex_bytes(key_seed));
+ // println!(
+ // "identity token hmac:\n{}",
+ // hex_bytes(
+ // hkdf.v1_signature_keys()
+ // .identity_token_hmac_key()
+ // .calculate_hmac(identity_token.bytes())
+ // )
+ // );
+ // println!("public key:\n{}", hex_bytes(key_pair.public().to_bytes()));
+ // println!(
+ // "encrypted metadata:\n{}",
+ // hex_bytes(encrypted_sender_metadata.fetch_encrypted_metadata().unwrap())
+ // );
+ // std::println!("offset is: {:?}", de.offset());
+ // let derived_salt = match section.salt() {
+ // MultiSalt::Short(_) => panic!(),
+ // MultiSalt::Extended(s) => {
+ // s.derive::<16, CryptoProviderImpl>(Some(de.offset())).unwrap()
+ // }
+ // };
+ // println!("DE derived salt:\n{}", hex_bytes(derived_salt));
+ // panic!();
+ // }
}
#[test]
fn v1_deser_no_section() {
+ // TODO: we shouldn't allow this invalid advertisement to be serialized
let adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
let adv = adv_builder.into_advertisement();
let cred_book = CredentialBookBuilder::<EmptyMatchedCredential>::build_cached_slice_book::<
@@ -219,19 +261,18 @@ fn v1_deser_no_section() {
fn v1_deser_plaintext_over_max_sections() {
let mut adv_builder = AdvBuilder::new(AdvertisementType::Plaintext);
for _ in 0..NP_V1_ADV_MAX_PUBLIC_SECTION_COUNT {
- let mut section_builder =
- adv_builder.section_builder(PublicSectionEncoder::default()).unwrap();
+ let mut section_builder = adv_builder.section_builder(UnencryptedSectionEncoder).unwrap();
section_builder
.add_de(|_salt| TxPowerDataElement::from(TxPower::try_from(7).unwrap()))
.unwrap();
- section_builder.add_to_advertisement();
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
}
let mut adv = adv_builder.into_advertisement().as_slice().to_vec();
// Push an extra section
adv.extend_from_slice(
[
0x01, // Section header
- 0x03, // Public identity
+ V1_ENCODING_UNENCRYPTED,
]
.as_slice(),
);
diff --git a/nearby/presence/np_adv_dynamic/Cargo.toml b/nearby/presence/np_adv_dynamic/Cargo.toml
index 74d6e3a..5eb6863 100644
--- a/nearby/presence/np_adv_dynamic/Cargo.toml
+++ b/nearby/presence/np_adv_dynamic/Cargo.toml
@@ -11,5 +11,5 @@ workspace = true
array_view.workspace = true
np_adv = { workspace = true, features = ["alloc"] }
crypto_provider.workspace = true
-thiserror.workspace = true
sink.workspace = true
+np_hkdf.workspace = true
diff --git a/nearby/presence/np_adv_dynamic/src/extended.rs b/nearby/presence/np_adv_dynamic/src/extended.rs
index 5e1328c..c25be74 100644
--- a/nearby/presence/np_adv_dynamic/src/extended.rs
+++ b/nearby/presence/np_adv_dynamic/src/extended.rs
@@ -13,9 +13,10 @@
// limitations under the License.
use crypto_provider::CryptoProvider;
+use np_adv::extended::salt::MultiSalt;
use np_adv::{extended::data_elements::*, extended::serialize::*, shared_data::*};
use sink::Sink;
-use thiserror::Error;
+use std::fmt::{Display, Formatter};
/// An advertisement builder for V1 advertisements where the
/// presence/absence of salt is determined at run-time instead of compile-time.
@@ -32,39 +33,48 @@ impl From<AdvBuilder> for BoxedAdvBuilder {
/// Error possibly generated when attempting to add a section to
/// a BoxedAdvBuilder.
-#[derive(Debug, Error)]
+#[derive(Debug)]
pub enum BoxedAddSectionError {
/// An error which was generated by the underlying AdvBuilder wrapped by the BoxedAdvBuilder
- #[error("{0}")]
Underlying(AddSectionError),
/// An error generated when the boxed advertisement builder is unsalted, but the section
/// identity requires salt.
- #[error("Error generated when the BoxedAdvBuilder is unsalted, but the section identity requires salt.")]
IdentityRequiresSaltError,
}
+impl Display for BoxedAddSectionError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ match self {
+ BoxedAddSectionError::Underlying(u) => {
+ write!(f, "{0}", u)
+ }
+ BoxedAddSectionError::IdentityRequiresSaltError => {
+ write!(f, "Error generated when the BoxedAdvBuilder is unsalted, but the section identity requires salt.")
+ }
+ }
+ }
+}
+
+impl std::error::Error for BoxedAddSectionError {}
+
impl From<AddSectionError> for BoxedAddSectionError {
fn from(wrapped: AddSectionError) -> Self {
BoxedAddSectionError::Underlying(wrapped)
}
}
-fn wrap_owning_section_builder<C: CryptoProvider, S: Into<BoxedSectionBuilder<AdvBuilder, C>>>(
+fn wrap_owning_section_builder<S: Into<BoxedSectionBuilder<AdvBuilder>>>(
maybe_section_builder: Result<S, (AdvBuilder, AddSectionError)>,
-) -> Result<BoxedSectionBuilder<AdvBuilder, C>, (BoxedAdvBuilder, BoxedAddSectionError)> {
+) -> Result<BoxedSectionBuilder<AdvBuilder>, (BoxedAdvBuilder, BoxedAddSectionError)> {
match maybe_section_builder {
Ok(section_builder) => Ok(section_builder.into()),
Err((adv_builder, err)) => Err((adv_builder.into(), err.into())),
}
}
-fn wrap_mut_ref_section_builder<
- 'a,
- C: CryptoProvider,
- S: Into<BoxedSectionBuilder<&'a mut AdvBuilder, C>>,
->(
+fn wrap_mut_ref_section_builder<'a, S: Into<BoxedSectionBuilder<&'a mut AdvBuilder>>>(
maybe_section_builder: Result<S, AddSectionError>,
-) -> Result<BoxedSectionBuilder<&'a mut AdvBuilder, C>, BoxedAddSectionError> {
+) -> Result<BoxedSectionBuilder<&'a mut AdvBuilder>, BoxedAddSectionError> {
let section_builder = maybe_section_builder?;
Ok(section_builder.into())
}
@@ -85,42 +95,42 @@ impl BoxedAdvBuilder {
/// builder, if the operation was successful. Otherwise,
/// this advertisement builder will be returned back to the
/// caller unaltered as part of the `Err` arm.
- pub fn into_section_builder<C: CryptoProvider>(
+ pub fn into_section_builder(
self,
- identity: BoxedIdentity<C>,
- ) -> Result<BoxedSectionBuilder<AdvBuilder, C>, (Self, BoxedAddSectionError)> {
+ identity: BoxedEncoder,
+ ) -> Result<BoxedSectionBuilder<AdvBuilder>, (Self, BoxedAddSectionError)> {
match identity {
- BoxedIdentity::PublicIdentity => wrap_owning_section_builder(
- self.adv_builder.into_section_builder(PublicSectionEncoder::default()),
+ BoxedEncoder::Unencrypted => wrap_owning_section_builder(
+ self.adv_builder.into_section_builder(UnencryptedSectionEncoder),
),
- BoxedIdentity::MicEncrypted(ident) => {
+ BoxedEncoder::MicEncrypted(ident) => {
wrap_owning_section_builder(self.adv_builder.into_section_builder(ident))
}
- BoxedIdentity::SignedEncrypted(ident) => {
+ BoxedEncoder::SignedEncrypted(ident) => {
wrap_owning_section_builder(self.adv_builder.into_section_builder(ident))
}
}
}
- /// Create a section builder using the given identity.
+ /// Create a section builder using the given encoder.
///
/// Returns `Err` if the underlying advertisement builder
/// yields an error when attempting to add a new section
/// (typically because there's no more available adv space),
/// or if the requested identity requires salt, and the
/// advertisement builder is salt-less.
- pub fn section_builder<C: CryptoProvider>(
+ pub fn section_builder(
&mut self,
- identity: BoxedIdentity<C>,
- ) -> Result<BoxedSectionBuilder<&mut AdvBuilder, C>, BoxedAddSectionError> {
- match identity {
- BoxedIdentity::PublicIdentity => wrap_mut_ref_section_builder(
- self.adv_builder.section_builder(PublicSectionEncoder::default()),
+ encoder: BoxedEncoder,
+ ) -> Result<BoxedSectionBuilder<&mut AdvBuilder>, BoxedAddSectionError> {
+ match encoder {
+ BoxedEncoder::Unencrypted => wrap_mut_ref_section_builder(
+ self.adv_builder.section_builder(UnencryptedSectionEncoder),
),
- BoxedIdentity::MicEncrypted(ident) => {
+ BoxedEncoder::MicEncrypted(ident) => {
wrap_mut_ref_section_builder(self.adv_builder.section_builder(ident))
}
- BoxedIdentity::SignedEncrypted(ident) => {
+ BoxedEncoder::SignedEncrypted(ident) => {
wrap_mut_ref_section_builder(self.adv_builder.section_builder(ident))
}
}
@@ -132,29 +142,29 @@ impl BoxedAdvBuilder {
}
}
-/// A wrapped v1 identity whose type is given at run-time.
-pub enum BoxedIdentity<C: CryptoProvider> {
- /// Public identity.
- PublicIdentity,
- /// An encrypted identity leveraging MIC for verification.
- MicEncrypted(MicEncryptedSectionEncoder<C>),
- /// An encrypted identity leveraging signatures for verification.
- SignedEncrypted(SignedEncryptedSectionEncoder<C>),
+/// A wrapped v1 encoder whose type is given at run-time.
+pub enum BoxedEncoder {
+ /// Unencrypted encoder.
+ Unencrypted,
+ /// An encrypted encoder leveraging MIC for verification.
+ MicEncrypted(MicEncryptedSectionEncoder<MultiSalt>),
+ /// An encrypted encoder leveraging signatures for verification.
+ SignedEncrypted(SignedEncryptedSectionEncoder),
}
/// A `SectionBuilder` whose corresponding Identity
/// and salted-ness is given at run-time instead of
/// at compile-time.
-pub enum BoxedSectionBuilder<R: AsMut<AdvBuilder>, C: CryptoProvider> {
+pub enum BoxedSectionBuilder<R: AsMut<AdvBuilder>> {
/// A builder for a public section.
- Public(Box<SectionBuilder<R, PublicSectionEncoder>>),
+ Public(Box<SectionBuilder<R, UnencryptedSectionEncoder>>),
/// A builder for a MIC-verified section.
- MicEncrypted(Box<SectionBuilder<R, MicEncryptedSectionEncoder<C>>>),
+ MicEncrypted(Box<SectionBuilder<R, MicEncryptedSectionEncoder<MultiSalt>>>),
/// A builder for a signature-verified section.
- SignedEncrypted(Box<SectionBuilder<R, SignedEncryptedSectionEncoder<C>>>),
+ SignedEncrypted(Box<SectionBuilder<R, SignedEncryptedSectionEncoder>>),
}
-impl<C: CryptoProvider> BoxedSectionBuilder<AdvBuilder, C> {
+impl BoxedSectionBuilder<AdvBuilder> {
/// Gets the 0-based index of the section currently under construction
/// in the context of the containing advertisement.
pub fn section_index(&self) -> usize {
@@ -166,28 +176,28 @@ impl<C: CryptoProvider> BoxedSectionBuilder<AdvBuilder, C> {
}
/// Add this builder to the advertisement that created it,
/// returning the containing advertisement builder.
- pub fn add_to_advertisement(self) -> BoxedAdvBuilder {
+ pub fn add_to_advertisement<C: CryptoProvider>(self) -> BoxedAdvBuilder {
let adv_builder = match self {
- BoxedSectionBuilder::Public(x) => x.add_to_advertisement(),
- BoxedSectionBuilder::MicEncrypted(x) => x.add_to_advertisement(),
- BoxedSectionBuilder::SignedEncrypted(x) => x.add_to_advertisement(),
+ BoxedSectionBuilder::Public(x) => x.add_to_advertisement::<C>(),
+ BoxedSectionBuilder::MicEncrypted(x) => x.add_to_advertisement::<C>(),
+ BoxedSectionBuilder::SignedEncrypted(x) => x.add_to_advertisement::<C>(),
};
BoxedAdvBuilder::from(adv_builder)
}
}
-impl<'a, C: CryptoProvider> BoxedSectionBuilder<&'a mut AdvBuilder, C> {
+impl<'a> BoxedSectionBuilder<&'a mut AdvBuilder> {
/// Add this builder to the advertisement that created it.
- pub fn add_to_advertisement(self) {
+ pub fn add_to_advertisement<C: CryptoProvider>(self) {
match self {
- BoxedSectionBuilder::Public(x) => x.add_to_advertisement(),
- BoxedSectionBuilder::MicEncrypted(x) => x.add_to_advertisement(),
- BoxedSectionBuilder::SignedEncrypted(x) => x.add_to_advertisement(),
+ BoxedSectionBuilder::Public(x) => x.add_to_advertisement::<C>(),
+ BoxedSectionBuilder::MicEncrypted(x) => x.add_to_advertisement::<C>(),
+ BoxedSectionBuilder::SignedEncrypted(x) => x.add_to_advertisement::<C>(),
}
}
}
-impl<R: AsMut<AdvBuilder>, C: CryptoProvider> BoxedSectionBuilder<R, C> {
+impl<R: AsMut<AdvBuilder>> BoxedSectionBuilder<R> {
/// Returns true if this wraps a section builder which
/// leverages some encrypted identity.
pub fn is_encrypted(&self) -> bool {
@@ -198,15 +208,16 @@ impl<R: AsMut<AdvBuilder>, C: CryptoProvider> BoxedSectionBuilder<R, C> {
}
}
/// Gets the derived salt of the next DE to be added to the section,
- /// if this section-builder corresponds to an encrypted section.
+ /// if this section-builder corresponds to an encrypted section that can
+ /// provide per-DE salts.
/// Otherwise, returns nothing.
///
/// Suitable for scenarios (like FFI) where a closure would be inappropriate
/// for DE construction, and interaction with the client is preferred.
- pub fn next_de_salt(&self) -> Option<DeSalt<C>> {
+ pub fn next_de_salt(&self) -> Option<DeSalt> {
match self {
BoxedSectionBuilder::Public(_) => None,
- BoxedSectionBuilder::MicEncrypted(x) => Some(x.next_de_salt()),
+ BoxedSectionBuilder::MicEncrypted(x) => x.next_de_salt(),
BoxedSectionBuilder::SignedEncrypted(x) => Some(x.next_de_salt()),
}
}
@@ -217,19 +228,16 @@ impl<R: AsMut<AdvBuilder>, C: CryptoProvider> BoxedSectionBuilder<R, C> {
/// if any salt has been specified for the surrounding advertisement.
pub fn add_de_res<E>(
&mut self,
- build_de: impl FnOnce(Option<DeSalt<C>>) -> Result<BoxedWriteDataElement, E>,
+ build_de: impl FnOnce(Option<DeSalt>) -> Result<BoxedWriteDataElement, E>,
) -> Result<(), AddDataElementError<E>> {
match self {
BoxedSectionBuilder::Public(x) => {
let build_de_modified = |()| build_de(None);
x.add_de_res(build_de_modified)
}
- BoxedSectionBuilder::MicEncrypted(x) => {
- let build_de_modified = |de_salt: DeSalt<C>| build_de(Some(de_salt));
- x.add_de_res(build_de_modified)
- }
+ BoxedSectionBuilder::MicEncrypted(x) => x.add_de_res(build_de),
BoxedSectionBuilder::SignedEncrypted(x) => {
- let build_de_modified = |de_salt: DeSalt<C>| build_de(Some(de_salt));
+ let build_de_modified = |de_salt: DeSalt| build_de(Some(de_salt));
x.add_de_res(build_de_modified)
}
}
@@ -237,32 +245,32 @@ impl<R: AsMut<AdvBuilder>, C: CryptoProvider> BoxedSectionBuilder<R, C> {
/// Like add_de_res, but for infalliable closures
pub fn add_de(
&mut self,
- build_de: impl FnOnce(Option<DeSalt<C>>) -> BoxedWriteDataElement,
+ build_de: impl FnOnce(Option<DeSalt>) -> BoxedWriteDataElement,
) -> Result<(), AddDataElementError<()>> {
self.add_de_res(|derived_salt| Ok::<_, ()>(build_de(derived_salt)))
}
}
-impl<R: AsMut<AdvBuilder>, C: CryptoProvider> From<SectionBuilder<R, PublicSectionEncoder>>
- for BoxedSectionBuilder<R, C>
+impl<R: AsMut<AdvBuilder>> From<SectionBuilder<R, UnencryptedSectionEncoder>>
+ for BoxedSectionBuilder<R>
{
- fn from(section_builder: SectionBuilder<R, PublicSectionEncoder>) -> Self {
+ fn from(section_builder: SectionBuilder<R, UnencryptedSectionEncoder>) -> Self {
BoxedSectionBuilder::Public(Box::new(section_builder))
}
}
-impl<R: AsMut<AdvBuilder>, C: CryptoProvider> From<SectionBuilder<R, MicEncryptedSectionEncoder<C>>>
- for BoxedSectionBuilder<R, C>
+impl<R: AsMut<AdvBuilder>> From<SectionBuilder<R, MicEncryptedSectionEncoder<MultiSalt>>>
+ for BoxedSectionBuilder<R>
{
- fn from(section_builder: SectionBuilder<R, MicEncryptedSectionEncoder<C>>) -> Self {
+ fn from(section_builder: SectionBuilder<R, MicEncryptedSectionEncoder<MultiSalt>>) -> Self {
BoxedSectionBuilder::MicEncrypted(Box::new(section_builder))
}
}
-impl<R: AsMut<AdvBuilder>, C: CryptoProvider>
- From<SectionBuilder<R, SignedEncryptedSectionEncoder<C>>> for BoxedSectionBuilder<R, C>
+impl<R: AsMut<AdvBuilder>> From<SectionBuilder<R, SignedEncryptedSectionEncoder>>
+ for BoxedSectionBuilder<R>
{
- fn from(section_builder: SectionBuilder<R, SignedEncryptedSectionEncoder<C>>) -> Self {
+ fn from(section_builder: SectionBuilder<R, SignedEncryptedSectionEncoder>) -> Self {
BoxedSectionBuilder::SignedEncrypted(Box::new(section_builder))
}
}
diff --git a/nearby/presence/np_adv_dynamic/src/legacy.rs b/nearby/presence/np_adv_dynamic/src/legacy.rs
index 191ef75..68eb1bc 100644
--- a/nearby/presence/np_adv_dynamic/src/legacy.rs
+++ b/nearby/presence/np_adv_dynamic/src/legacy.rs
@@ -12,15 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use array_view::ArrayView;
use crypto_provider::CryptoProvider;
-use np_adv::legacy::actions::*;
-use np_adv::legacy::data_elements::*;
-use np_adv::legacy::serialize::*;
-use np_adv::legacy::*;
-use np_adv::shared_data::*;
-use np_adv::PublicIdentity;
-use thiserror::Error;
+use np_adv::{
+ legacy::{
+ data_elements::{actions::*, tx_power::TxPowerDataElement, *},
+ serialize::*,
+ *,
+ },
+ shared_data::*,
+};
+use std::fmt::{Display, Formatter};
/// Wrapper around a V0 advertisement builder which
/// is agnostic to the kind of identity used in the advertisement.
@@ -29,10 +30,10 @@ use thiserror::Error;
/// Generic over the Aes algorithm used for any encrypted identities,
/// since that is generally specified at compile-time.
pub enum BoxedAdvBuilder<C: CryptoProvider> {
- /// Builder for public advertisements.
- Public(AdvBuilder<PublicIdentity>),
- /// Builder for LDT-encryptedadvertisements.
- Ldt(AdvBuilder<LdtIdentity<C>>),
+ /// Builder for unencrypted advertisements.
+ Unencrypted(AdvBuilder<UnencryptedEncoder>),
+ /// Builder for LDT-encrypted advertisements.
+ Ldt(AdvBuilder<LdtEncoder<C>>),
}
/// Wrapper around possible errors which occur only during
@@ -41,7 +42,9 @@ pub enum BoxedAdvBuilder<C: CryptoProvider> {
pub enum BoxedAdvConstructionError {
/// An error originating from a problem with LDT
/// encryption of the advertisement contents.
- Ldt(LdtPostprocessError),
+ Ldt(LdtEncodeError),
+ /// An error from encoding an unencrypted adv
+ Unencrypted(UnencryptedEncodeError),
}
impl<C: CryptoProvider> BoxedAdvBuilder<C> {
@@ -49,15 +52,17 @@ impl<C: CryptoProvider> BoxedAdvBuilder<C> {
/// leverages some encrypted identity.
pub fn is_encrypted(&self) -> bool {
match self {
- BoxedAdvBuilder::Public(_) => false,
+ BoxedAdvBuilder::Unencrypted(_) => false,
BoxedAdvBuilder::Ldt(_) => true,
}
}
/// Constructs a new BoxedAdvBuilder from the given BoxedIdentity
- pub fn new(identity: BoxedIdentity<C>) -> Self {
+ pub fn new(identity: BoxedEncoder<C>) -> Self {
match identity {
- BoxedIdentity::Public(identity) => BoxedAdvBuilder::Public(AdvBuilder::new(identity)),
- BoxedIdentity::LdtIdentity(identity) => BoxedAdvBuilder::Ldt(AdvBuilder::new(identity)),
+ BoxedEncoder::Unencrypted(encoder) => {
+ BoxedAdvBuilder::Unencrypted(AdvBuilder::new(encoder))
+ }
+ BoxedEncoder::LdtEncrypted(encoder) => BoxedAdvBuilder::Ldt(AdvBuilder::new(encoder)),
}
}
/// Attempts to add a data element to the advertisement
@@ -66,10 +71,10 @@ impl<C: CryptoProvider> BoxedAdvBuilder<C> {
/// if something went wrong in the attempt to add the DE.
pub fn add_data_element(
&mut self,
- data_element: ToBoxedDataElementBundle,
+ data_element: ToBoxedSerializeDataElement,
) -> Result<(), BoxedAddDataElementError> {
match self {
- BoxedAdvBuilder::Public(public_builder) => {
+ BoxedAdvBuilder::Unencrypted(public_builder) => {
//Verify that we can get the data element as plaintext
let maybe_plaintext_data_element = data_element.to_plaintext();
match maybe_plaintext_data_element {
@@ -93,15 +98,10 @@ impl<C: CryptoProvider> BoxedAdvBuilder<C> {
}
/// Consume this BoxedAdvBuilder and attempt to create
/// a serialized advertisement including the added DEs.
- pub fn into_advertisement(
- self,
- ) -> Result<ArrayView<u8, BLE_ADV_SVC_CONTENT_LEN>, BoxedAdvConstructionError> {
+ pub fn into_advertisement(self) -> Result<SerializedAdv, BoxedAdvConstructionError> {
match self {
- BoxedAdvBuilder::Public(x) => {
- match x.into_advertisement() {
- Ok(x) => Ok(x),
- Err(x) => match x {}, //Infallible
- }
+ BoxedAdvBuilder::Unencrypted(x) => {
+ x.into_advertisement().map_err(BoxedAdvConstructionError::Unencrypted)
}
BoxedAdvBuilder::Ldt(x) => {
x.into_advertisement().map_err(BoxedAdvConstructionError::Ldt)
@@ -112,143 +112,133 @@ impl<C: CryptoProvider> BoxedAdvBuilder<C> {
/// Possible errors generated when trying to add a DE to a
/// BoxedAdvBuilder.
-#[derive(Debug, Error)]
+#[derive(Debug)]
pub enum BoxedAddDataElementError {
/// Some kind of error in adding the data element which
/// is not an issue with trying to add a DE of the incorrect
/// packet flavoring.
- #[error("{0:?}")]
UnderlyingError(AddDataElementError),
- #[error(
- "Expected packet flavoring for added DEs does not match the actual packet flavor of the DE"
- )]
/// Error when attempting to add a DE which requires one
/// of an (encrypted/plaintext) advertisement, but the
/// advertisement builder doesn't match this requirement.
FlavorMismatchError,
}
-impl From<AddDataElementError> for BoxedAddDataElementError {
- fn from(add_data_element_error: AddDataElementError) -> Self {
- BoxedAddDataElementError::UnderlyingError(add_data_element_error)
+impl Display for BoxedAddDataElementError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ match self {
+ BoxedAddDataElementError::UnderlyingError(u) => {
+ write!(f, "{0:?}", u)
+ }
+ BoxedAddDataElementError::FlavorMismatchError => {
+ write!(f, "Expected packet flavoring for added DEs does not match the actual packet flavor of the DE")
+ }
+ }
}
}
-/// Trait object reference to a `ToDataElementBundle<I>` with lifetime `'a`.
-/// Implements `ToDataElementBundle<I>` by deferring to the wrapped trait object.
-pub struct DynamicToDataElementBundle<'a, I: PacketFlavor> {
- wrapped: &'a dyn ToDataElementBundle<I>,
-}
+impl std::error::Error for BoxedAddDataElementError {}
-impl<'a, I: PacketFlavor> From<&'a dyn ToDataElementBundle<I>>
- for DynamicToDataElementBundle<'a, I>
-{
- fn from(wrapped: &'a dyn ToDataElementBundle<I>) -> Self {
- DynamicToDataElementBundle { wrapped }
- }
-}
-
-impl<'a, I: PacketFlavor> ToDataElementBundle<I> for DynamicToDataElementBundle<'a, I> {
- fn to_de_bundle(&self) -> DataElementBundle<I> {
- self.wrapped.to_de_bundle()
+impl From<AddDataElementError> for BoxedAddDataElementError {
+ fn from(add_data_element_error: AddDataElementError) -> Self {
+ BoxedAddDataElementError::UnderlyingError(add_data_element_error)
}
}
/// Trait for types which can provide trait object
-/// references to either plaintext or ciphertext [ToDataElementBundle]
-pub trait ToMultiFlavorElementBundle {
- /// Gets the associated trait object reference to a `ToDataElementBundle<Plaintext>`
+/// references to either plaintext or ciphertext [SerializeDataElement]
+pub trait ToMultiFlavorSerializeDataElement {
+ /// Gets the associated trait object reference to a `SerializeDataElement<Plaintext>`
/// with the same lifetime as a reference to the implementor.
- fn to_plaintext(&self) -> DynamicToDataElementBundle<Plaintext>;
+ fn to_plaintext(&self) -> DynamicSerializeDataElement<Plaintext>;
- /// Gets the associated trait object reference to a `ToDataElementBundle<Ciphertext>`
+ /// Gets the associated trait object reference to a `SerializeDataElement<Ciphertext>`
/// with the same lifetime as a reference to the implementor.
- fn to_ciphertext(&self) -> DynamicToDataElementBundle<Ciphertext>;
+ fn to_ciphertext(&self) -> DynamicSerializeDataElement<Ciphertext>;
}
-/// Blanket impl of [ToMultiFlavorElementBundle] for implementors of [ToDataElementBundle]
+/// Blanket impl of [ToMultiFlavorSerializeDataElement] for implementors of [SerializeDataElement]
/// for both [Plaintext] and [Ciphertext] packet flavors.
-impl<T: ToDataElementBundle<Plaintext> + ToDataElementBundle<Ciphertext>> ToMultiFlavorElementBundle
- for T
+impl<T: SerializeDataElement<Plaintext> + SerializeDataElement<Ciphertext>>
+ ToMultiFlavorSerializeDataElement for T
{
- fn to_plaintext(&self) -> DynamicToDataElementBundle<Plaintext> {
- let reference: &dyn ToDataElementBundle<Plaintext> = self;
+ fn to_plaintext(&self) -> DynamicSerializeDataElement<Plaintext> {
+ let reference: &dyn SerializeDataElement<Plaintext> = self;
reference.into()
}
- fn to_ciphertext(&self) -> DynamicToDataElementBundle<Ciphertext> {
- let reference: &dyn ToDataElementBundle<Ciphertext> = self;
+ fn to_ciphertext(&self) -> DynamicSerializeDataElement<Ciphertext> {
+ let reference: &dyn SerializeDataElement<Ciphertext> = self;
reference.into()
}
}
-/// Boxed trait object version of [ToDataElementBundle] which incorporates
+/// Boxed trait object version of [SerializeDataElement] which incorporates
/// all possible variants on generatable packet flavoring
-/// (`Plaintext`, `Ciphertext`, or both, as a [ToMultiFlavorElementBundle])
-pub enum ToBoxedDataElementBundle {
+/// (`Plaintext`, `Ciphertext`, or both, as a [ToMultiFlavorSerializeDataElement])
+pub enum ToBoxedSerializeDataElement {
/// The underlying DE is plaintext-only.
- Plaintext(Box<dyn ToDataElementBundle<Plaintext>>),
+ Plaintext(Box<dyn SerializeDataElement<Plaintext>>),
/// The underlying DE is ciphertext-only.
- Ciphertext(Box<dyn ToDataElementBundle<Ciphertext>>),
+ Ciphertext(Box<dyn SerializeDataElement<Ciphertext>>),
/// The underlying DE may exist in plaintext or
/// in ciphertext advertisements.
- Both(Box<dyn ToMultiFlavorElementBundle>),
+ Both(Box<dyn ToMultiFlavorSerializeDataElement>),
}
-impl ToBoxedDataElementBundle {
- /// If this [ToBoxedDataElementBundle] can generate plaintext, returns
- /// a trait object reference to a `ToDataElementBundle<Plaintext>`
- pub fn to_plaintext(&self) -> Option<DynamicToDataElementBundle<Plaintext>> {
+impl ToBoxedSerializeDataElement {
+ /// If this [ToBoxedSerializeDataElement] can generate plaintext, returns
+ /// a trait object reference to a `SerializeDataElement<Plaintext>`
+ pub fn to_plaintext(&self) -> Option<DynamicSerializeDataElement<Plaintext>> {
match &self {
- ToBoxedDataElementBundle::Plaintext(x) => Some(x.as_ref().into()),
- ToBoxedDataElementBundle::Ciphertext(_) => None,
- ToBoxedDataElementBundle::Both(x) => Some(x.as_ref().to_plaintext()),
+ ToBoxedSerializeDataElement::Plaintext(x) => Some(x.as_ref().into()),
+ ToBoxedSerializeDataElement::Ciphertext(_) => None,
+ ToBoxedSerializeDataElement::Both(x) => Some(x.as_ref().to_plaintext()),
}
}
- /// If this [ToBoxedDataElementBundle] can generate ciphertext, returns
- /// a trait object reference to a `ToDataElementBundle<Ciphertext>`
- pub fn to_ciphertext(&self) -> Option<DynamicToDataElementBundle<Ciphertext>> {
+ /// If this [ToBoxedSerializeDataElement] can generate ciphertext, returns
+ /// a trait object reference to a `SerializeDataElement<Ciphertext>`
+ pub fn to_ciphertext(&self) -> Option<DynamicSerializeDataElement<Ciphertext>> {
match &self {
- ToBoxedDataElementBundle::Plaintext(_) => None,
- ToBoxedDataElementBundle::Ciphertext(x) => Some(x.as_ref().into()),
- ToBoxedDataElementBundle::Both(x) => Some(x.as_ref().to_ciphertext()),
+ ToBoxedSerializeDataElement::Plaintext(_) => None,
+ ToBoxedSerializeDataElement::Ciphertext(x) => Some(x.as_ref().into()),
+ ToBoxedSerializeDataElement::Both(x) => Some(x.as_ref().to_ciphertext()),
}
}
}
-/// Boxed version of implementors of the Identity trait.
-/// A is the underlying Aes algorithm leveraged by ciphertext-based identities.
-pub enum BoxedIdentity<C: CryptoProvider> {
- /// Public Identity.
- Public(PublicIdentity),
- /// An encrypted identity, using LDT encryption.
- LdtIdentity(LdtIdentity<C>),
+/// Boxed version of implementors of the [AdvEncoder] trait.
+pub enum BoxedEncoder<C: CryptoProvider> {
+ /// Unencrypted encoding.
+ Unencrypted(UnencryptedEncoder),
+ /// An encrypted encoding, using LDT encryption.
+ LdtEncrypted(LdtEncoder<C>),
}
-impl<C: CryptoProvider> From<PublicIdentity> for BoxedIdentity<C> {
- fn from(public_identity: PublicIdentity) -> BoxedIdentity<C> {
- BoxedIdentity::Public(public_identity)
+impl<C: CryptoProvider> From<UnencryptedEncoder> for BoxedEncoder<C> {
+ fn from(encoder: UnencryptedEncoder) -> BoxedEncoder<C> {
+ BoxedEncoder::Unencrypted(encoder)
}
}
-impl<C: CryptoProvider> From<LdtIdentity<C>> for BoxedIdentity<C> {
- fn from(ldt_identity: LdtIdentity<C>) -> BoxedIdentity<C> {
- BoxedIdentity::LdtIdentity(ldt_identity)
+impl<C: CryptoProvider> From<LdtEncoder<C>> for BoxedEncoder<C> {
+ fn from(encoder: LdtEncoder<C>) -> BoxedEncoder<C> {
+ BoxedEncoder::LdtEncrypted(encoder)
}
}
-impl From<TxPower> for ToBoxedDataElementBundle {
+impl From<TxPower> for ToBoxedSerializeDataElement {
fn from(data: TxPower) -> Self {
- ToBoxedDataElementBundle::Both(Box::new(TxPowerDataElement::from(data)))
+ ToBoxedSerializeDataElement::Both(Box::new(TxPowerDataElement::from(data)))
}
}
-impl From<BoxedActionBits> for ToBoxedDataElementBundle {
+impl From<BoxedActionBits> for ToBoxedSerializeDataElement {
fn from(action_bits: BoxedActionBits) -> Self {
match action_bits {
- BoxedActionBits::Plaintext(action_bits) => {
- ToBoxedDataElementBundle::Plaintext(Box::new(ActionsDataElement::from(action_bits)))
- }
- BoxedActionBits::Ciphertext(action_bits) => ToBoxedDataElementBundle::Ciphertext(
+ BoxedActionBits::Plaintext(action_bits) => ToBoxedSerializeDataElement::Plaintext(
+ Box::new(ActionsDataElement::from(action_bits)),
+ ),
+ BoxedActionBits::Ciphertext(action_bits) => ToBoxedSerializeDataElement::Ciphertext(
Box::new(ActionsDataElement::from(action_bits)),
),
}
@@ -258,8 +248,10 @@ impl From<BoxedActionBits> for ToBoxedDataElementBundle {
/// Boxed version of `ToActionElement` which allows abstracting over
/// what packet flavors are supported by a given action.
pub enum ToBoxedActionElement {
- /// A context-sync sequence number.
- ContextSyncSeqNum(ContextSyncSeqNum),
+ /// Action bit for cross device SDK.
+ CrossDevSdk(bool),
+ /// Action bit for call transfer.
+ CallTransfer(bool),
/// Action bit for active unlock.
ActiveUnlock(bool),
/// Action bit for nearby share.
@@ -268,12 +260,6 @@ pub enum ToBoxedActionElement {
InstantTethering(bool),
/// Action bit for PhoneHub.
PhoneHub(bool),
- /// Action bit for Finder.
- Finder(bool),
- /// Action bit for Fast Pair/SASS
- FastPairSass(bool),
- /// Action bit for Presence Manager.
- PresenceManager(bool),
}
/// [`ActionBits`] with runtime-determined packet flavoring
@@ -284,6 +270,18 @@ pub enum BoxedActionBits {
Ciphertext(ActionBits<Ciphertext>),
}
+impl From<ActionBits<Plaintext>> for BoxedActionBits {
+ fn from(bits: ActionBits<Plaintext>) -> Self {
+ Self::Plaintext(bits)
+ }
+}
+
+impl From<ActionBits<Ciphertext>> for BoxedActionBits {
+ fn from(bits: ActionBits<Ciphertext>) -> Self {
+ Self::Ciphertext(bits)
+ }
+}
+
/// Error which is raised when the flavor of a [`BoxedActionBits`]
/// does not match the supported flavors of a [`ToBoxedActionElement`]
/// upon attempting to add the action to the bit-field.
@@ -300,7 +298,17 @@ impl BoxedActionBits {
}
}
- fn set<F: PacketFlavor, E: ToActionElement<F>>(
+ /// Returns whether a boolean action type is set in these action bits, or `None`
+ /// if the given action type does not represent a boolean (e.g: a context-sync
+ /// sequence number).
+ pub fn has_action(&self, action_type: ActionType) -> bool {
+ match self {
+ BoxedActionBits::Plaintext(x) => x.has_action(action_type),
+ BoxedActionBits::Ciphertext(x) => x.has_action(action_type),
+ }
+ }
+
+ fn set<F: PacketFlavor, E: ActionElementFlavor<F>>(
action_bits: &mut ActionBits<F>,
to_element: E,
) -> Result<(), BoxedSetActionFlavorError> {
@@ -317,18 +325,24 @@ impl BoxedActionBits {
) -> Result<(), BoxedSetActionFlavorError> {
match self {
BoxedActionBits::Plaintext(action_bits) => match to_element {
- ToBoxedActionElement::ContextSyncSeqNum(x) => Self::set(action_bits, x),
+ ToBoxedActionElement::CrossDevSdk(b) => {
+ Self::set(action_bits, CrossDevSdk::from(b))
+ }
ToBoxedActionElement::NearbyShare(b) => {
Self::set(action_bits, NearbyShare::from(b))
}
- ToBoxedActionElement::Finder(b) => Self::set(action_bits, Finder::from(b)),
- ToBoxedActionElement::FastPairSass(b) => {
- Self::set(action_bits, FastPairSass::from(b))
- }
- _ => Err(BoxedSetActionFlavorError),
+ ToBoxedActionElement::CallTransfer(_)
+ | ToBoxedActionElement::ActiveUnlock(_)
+ | ToBoxedActionElement::InstantTethering(_)
+ | ToBoxedActionElement::PhoneHub(_) => Err(BoxedSetActionFlavorError),
},
BoxedActionBits::Ciphertext(action_bits) => match to_element {
- ToBoxedActionElement::ContextSyncSeqNum(x) => Self::set(action_bits, x),
+ ToBoxedActionElement::CrossDevSdk(b) => {
+ Self::set(action_bits, CrossDevSdk::from(b))
+ }
+ ToBoxedActionElement::CallTransfer(b) => {
+ Self::set(action_bits, CallTransfer::from(b))
+ }
ToBoxedActionElement::ActiveUnlock(b) => {
Self::set(action_bits, ActiveUnlock::from(b))
}
@@ -339,10 +353,6 @@ impl BoxedActionBits {
Self::set(action_bits, InstantTethering::from(b))
}
ToBoxedActionElement::PhoneHub(b) => Self::set(action_bits, PhoneHub::from(b)),
- ToBoxedActionElement::PresenceManager(b) => {
- Self::set(action_bits, PresenceManager::from(b))
- }
- _ => Err(BoxedSetActionFlavorError),
},
}
}
diff --git a/nearby/presence/np_c_ffi/Cargo.lock b/nearby/presence/np_c_ffi/Cargo.lock
deleted file mode 100644
index bce44c6..0000000
--- a/nearby/presence/np_c_ffi/Cargo.lock
+++ /dev/null
@@ -1,1215 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aead"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
-dependencies = [
- "bytes",
- "crypto-common",
- "generic-array",
-]
-
-[[package]]
-name = "aes"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
-dependencies = [
- "cfg-if",
- "cipher",
- "cpufeatures",
-]
-
-[[package]]
-name = "aes-gcm"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
-dependencies = [
- "aead",
- "aes",
- "cipher",
- "ctr",
- "ghash",
- "subtle",
-]
-
-[[package]]
-name = "aes-gcm-siv"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
-dependencies = [
- "aead",
- "aes",
- "cipher",
- "ctr",
- "polyval",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "array_ref"
-version = "0.1.0"
-
-[[package]]
-name = "array_view"
-version = "0.1.0"
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "base16ct"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
-
-[[package]]
-name = "base64ct"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "block-padding"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "bssl-crypto"
-version = "0.1.0"
-dependencies = [
- "bssl-sys",
-]
-
-[[package]]
-name = "bssl-sys"
-version = "0.1.0"
-
-[[package]]
-name = "bytes"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
-
-[[package]]
-name = "cbc"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
-dependencies = [
- "cipher",
-]
-
-[[package]]
-name = "cbindgen"
-version = "0.24.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d"
-dependencies = [
- "clap",
- "heck",
- "indexmap",
- "log",
- "proc-macro2",
- "quote",
- "serde",
- "serde_json",
- "syn 1.0.109",
- "tempfile",
- "toml",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "cipher"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
-dependencies = [
- "crypto-common",
- "inout",
-]
-
-[[package]]
-name = "clap"
-version = "3.2.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
-dependencies = [
- "atty",
- "bitflags 1.3.2",
- "clap_lex",
- "indexmap",
- "strsim",
- "termcolor",
- "textwrap",
-]
-
-[[package]]
-name = "clap_lex"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
-dependencies = [
- "os_str_bytes",
-]
-
-[[package]]
-name = "const-oid"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
-
-[[package]]
-name = "cpufeatures"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crypto-bigint"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124"
-dependencies = [
- "generic-array",
- "rand_core",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "rand_core",
- "typenum",
-]
-
-[[package]]
-name = "crypto_provider"
-version = "0.1.0"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "crypto_provider_boringssl"
-version = "0.1.0"
-dependencies = [
- "bssl-crypto",
- "crypto_provider",
-]
-
-[[package]]
-name = "crypto_provider_default"
-version = "0.1.0"
-dependencies = [
- "cfg-if",
- "crypto_provider",
- "crypto_provider_boringssl",
- "crypto_provider_rustcrypto",
-]
-
-[[package]]
-name = "crypto_provider_rustcrypto"
-version = "0.1.0"
-dependencies = [
- "aead",
- "aes",
- "aes-gcm",
- "aes-gcm-siv",
- "cbc",
- "cfg-if",
- "crypto_provider",
- "ctr",
- "ed25519-dalek",
- "hkdf",
- "hmac",
- "p256",
- "rand",
- "rand_chacha",
- "rand_core",
- "sec1",
- "sha2",
- "subtle",
- "x25519-dalek",
-]
-
-[[package]]
-name = "ctr"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
-dependencies = [
- "cipher",
-]
-
-[[package]]
-name = "curve25519-dalek"
-version = "4.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "curve25519-dalek-derive",
- "digest",
- "fiat-crypto",
- "platforms",
- "rustc_version",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "curve25519-dalek-derive"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.38",
-]
-
-[[package]]
-name = "der"
-version = "0.7.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
-dependencies = [
- "const-oid",
- "zeroize",
-]
-
-[[package]]
-name = "digest"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
-dependencies = [
- "block-buffer",
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "ed25519"
-version = "2.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
-dependencies = [
- "pkcs8",
- "signature",
-]
-
-[[package]]
-name = "ed25519-dalek"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
-dependencies = [
- "curve25519-dalek",
- "ed25519",
- "rand_core",
- "serde",
- "sha2",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "elliptic-curve"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914"
-dependencies = [
- "base16ct",
- "crypto-bigint",
- "digest",
- "ff",
- "generic-array",
- "group",
- "hkdf",
- "rand_core",
- "sec1",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "errno"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
-dependencies = [
- "libc",
- "windows-sys",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
-
-[[package]]
-name = "ff"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
-dependencies = [
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "fiat-crypto"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a481586acf778f1b1455424c343f71124b048ffa5f4fc3f8f6ae9dc432dcb3c7"
-
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
- "zeroize",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "ghash"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
-dependencies = [
- "opaque-debug",
- "polyval",
-]
-
-[[package]]
-name = "group"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
-dependencies = [
- "ff",
- "rand_core",
- "subtle",
-]
-
-[[package]]
-name = "handle_map"
-version = "0.1.0"
-dependencies = [
- "lock_adapter",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hkdf"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
-dependencies = [
- "hmac",
-]
-
-[[package]]
-name = "hmac"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown",
-]
-
-[[package]]
-name = "inout"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
-dependencies = [
- "block-padding",
- "generic-array",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-dependencies = [
- "spin",
-]
-
-[[package]]
-name = "ldt"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
- "ldt_tbc",
-]
-
-[[package]]
-name = "ldt_np_adv"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "ldt",
- "ldt_tbc",
- "np_hkdf",
- "xts_aes",
-]
-
-[[package]]
-name = "ldt_tbc"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.149"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
-
-[[package]]
-name = "lock_adapter"
-version = "0.1.0"
-
-[[package]]
-name = "log"
-version = "0.4.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
-
-[[package]]
-name = "memchr"
-version = "2.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
-
-[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
-name = "np_adv"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "lazy_static",
- "ldt",
- "ldt_np_adv",
- "nom",
- "np_ed25519",
- "np_hkdf",
- "sink",
- "strum",
- "strum_macros",
- "tinyvec",
- "xts_aes",
-]
-
-[[package]]
-name = "np_adv_dynamic"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "np_adv",
- "sink",
- "thiserror",
-]
-
-[[package]]
-name = "np_c_ffi"
-version = "0.1.0"
-dependencies = [
- "cbindgen",
- "lock_adapter",
- "np_ffi_core",
-]
-
-[[package]]
-name = "np_ed25519"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "sink",
- "tinyvec",
-]
-
-[[package]]
-name = "np_ffi_core"
-version = "0.1.0"
-dependencies = [
- "array_view",
- "crypto_provider",
- "crypto_provider_default",
- "handle_map",
- "lazy_static",
- "ldt_np_adv",
- "lock_adapter",
- "np_adv",
- "np_adv_dynamic",
- "np_hkdf",
-]
-
-[[package]]
-name = "np_hkdf"
-version = "0.1.0"
-dependencies = [
- "crypto_provider",
- "ldt",
- "xts_aes",
-]
-
-[[package]]
-name = "opaque-debug"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
-
-[[package]]
-name = "os_str_bytes"
-version = "6.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
-
-[[package]]
-name = "p256"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
-dependencies = [
- "elliptic-curve",
- "primeorder",
-]
-
-[[package]]
-name = "pkcs8"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
-dependencies = [
- "der",
- "spki",
-]
-
-[[package]]
-name = "platforms"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0"
-
-[[package]]
-name = "polyval"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "opaque-debug",
- "universal-hash",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
-
-[[package]]
-name = "primeorder"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
-dependencies = [
- "elliptic-curve",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.33"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
-name = "rustc_version"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
-dependencies = [
- "bitflags 2.4.1",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
-
-[[package]]
-name = "ryu"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
-
-[[package]]
-name = "sec1"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
-dependencies = [
- "base16ct",
- "der",
- "generic-array",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
-
-[[package]]
-name = "serde"
-version = "1.0.190"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.190"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.38",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.108"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha2"
-version = "0.10.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "signature"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
-
-[[package]]
-name = "sink"
-version = "0.1.0"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "spki"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
-dependencies = [
- "base64ct",
- "der",
-]
-
-[[package]]
-name = "strsim"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-
-[[package]]
-name = "strum"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
-
-[[package]]
-name = "strum_macros"
-version = "0.25.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn 2.0.38",
-]
-
-[[package]]
-name = "subtle"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall",
- "rustix",
- "windows-sys",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
-
-[[package]]
-name = "thiserror"
-version = "1.0.51"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.51"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.38",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
-
-[[package]]
-name = "toml"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "typenum"
-version = "1.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "universal-hash"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
-dependencies = [
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "version_check"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "x25519-dalek"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
-dependencies = [
- "curve25519-dalek",
- "rand_core",
-]
-
-[[package]]
-name = "xts_aes"
-version = "0.1.0"
-dependencies = [
- "array_ref",
- "crypto_provider",
- "ldt_tbc",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
diff --git a/nearby/presence/np_c_ffi/Cargo.toml b/nearby/presence/np_c_ffi/Cargo.toml
index 86bbd53..517c2c5 100644
--- a/nearby/presence/np_c_ffi/Cargo.toml
+++ b/nearby/presence/np_c_ffi/Cargo.toml
@@ -5,27 +5,18 @@ edition = "2021"
publish = false
[dependencies]
-np_ffi_core = { path = "../np_ffi_core" }
-lock_adapter = {path = "../../util/lock_adapter"}
+np_ffi_core = {workspace = true, default-features=false}
+lock_adapter.workspace = true
[build-dependencies]
-cbindgen = "0.24.5"
+cbindgen.workspace = true
[features]
default = ["rustcrypto"]
rustcrypto = ["np_ffi_core/rustcrypto"]
boringssl = ["np_ffi_core/boringssl"]
+
[lib]
# boringssl and bssl-sys are built as a static lib, so we need to as well
-crate-type = ["staticlib"]
-
-# build profile optimized for size
-[profile.release-min-size]
-inherits = "release"
-panic = "abort"
-codegen-units = 1
-lto = true
-# z optimizes for size
-opt-level = "z"
-strip = true \ No newline at end of file
+crate-type = ["staticlib"] \ No newline at end of file
diff --git a/nearby/presence/np_c_ffi/cbindgen_configs/c_config.toml b/nearby/presence/np_c_ffi/cbindgen_configs/c_config.toml
index 88483b0..b2967cf 100644
--- a/nearby/presence/np_c_ffi/cbindgen_configs/c_config.toml
+++ b/nearby/presence/np_c_ffi/cbindgen_configs/c_config.toml
@@ -19,7 +19,13 @@ header = """
See the License for the specific language governing permissions and
limitations under the License.
*/
+
+// clang-format off
+"""
+trailer = """
+// clang-format on
"""
+
pragma_once = true
autogen_warning = """
/*
@@ -44,7 +50,3 @@ rename_variants = "QualifiedScreamingSnakeCase"
[parse]
parse_deps = true
include = ["np_c_ffi", "np_ffi_core"]
-
-[parse.expand]
-crates = ["np_ffi_core"]
-default_features = true
diff --git a/nearby/presence/np_c_ffi/cbindgen_configs/cpp_config.toml b/nearby/presence/np_c_ffi/cbindgen_configs/cpp_config.toml
index 5a2ba2a..50de758 100644
--- a/nearby/presence/np_c_ffi/cbindgen_configs/cpp_config.toml
+++ b/nearby/presence/np_c_ffi/cbindgen_configs/cpp_config.toml
@@ -16,7 +16,13 @@ header = """
See the License for the specific language governing permissions and
limitations under the License.
*/
+
+// clang-format off
+"""
+trailer = """
+// clang-format on
"""
+
pragma_once = true
autogen_warning = """
/*
@@ -38,7 +44,3 @@ rename_variants = "None"
[parse]
parse_deps = true
include = ["np_c_ffi", "np_ffi_core"]
-
-[parse.expand]
-crates = ["np_ffi_core"]
-default_features = true
diff --git a/nearby/presence/np_c_ffi/deny.toml b/nearby/presence/np_c_ffi/deny.toml
deleted file mode 100644
index ca51e11..0000000
--- a/nearby/presence/np_c_ffi/deny.toml
+++ /dev/null
@@ -1,213 +0,0 @@
-# This template contains all of the possible sections and their default values
-
-# Note that all fields that take a lint level have these possible values:
-# * deny - An error will be produced and the check will fail
-# * warn - A warning will be produced, but the check will not fail
-# * allow - No warning or error will be produced, though in some cases a note
-# will be
-
-# The values provided in this template are the default values that will be used
-# when any section or field is not specified in your own configuration
-
-# If 1 or more target triples (and optionally, target_features) are specified,
-# only the specified targets will be checked when running `cargo deny check`.
-# This means, if a particular package is only ever used as a target specific
-# dependency, such as, for example, the `nix` crate only being used via the
-# `target_family = "unix"` configuration, that only having windows targets in
-# this list would mean the nix crate, as well as any of its exclusive
-# dependencies not shared by any other crates, would be ignored, as the target
-# list here is effectively saying which targets you are building for.
-targets = [
- # The triple can be any string, but only the target triples built in to
- # rustc (as of 1.40) can be checked against actual config expressions
- #{ triple = "x86_64-unknown-linux-musl" },
- # You can also specify which target_features you promise are enabled for a
- # particular target. target_features are currently not validated against
- # the actual valid features supported by the target architecture.
- #{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
-]
-
-# This section is considered when running `cargo deny check advisories`
-# More documentation for the advisories section can be found here:
-# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
-[advisories]
-# The path where the advisory database is cloned/fetched into
-db-path = "~/.cargo/advisory-db"
-# The url(s) of the advisory databases to use
-db-urls = ["https://github.com/rustsec/advisory-db"]
-# The lint level for security vulnerabilities
-vulnerability = "deny"
-# The lint level for unmaintained crates
-unmaintained = "warn"
-# The lint level for crates that have been yanked from their source registry
-yanked = "warn"
-# The lint level for crates with security notices. Note that as of
-# 2019-12-17 there are no security notice advisories in
-# https://github.com/rustsec/advisory-db
-notice = "warn"
-# A list of advisory IDs to ignore. Note that ignored advisories will still
-# output a note when they are encountered.
-ignore = [
- #"RUSTSEC-0000-0000",
-]
-# Threshold for security vulnerabilities, any vulnerability with a CVSS score
-# lower than the range specified will be ignored. Note that ignored advisories
-# will still output a note when they are encountered.
-# * None - CVSS Score 0.0
-# * Low - CVSS Score 0.1 - 3.9
-# * Medium - CVSS Score 4.0 - 6.9
-# * High - CVSS Score 7.0 - 8.9
-# * Critical - CVSS Score 9.0 - 10.0
-#severity-threshold =
-
-# If this is true, then cargo deny will use the git executable to fetch advisory database.
-# If this is false, then it uses a built-in git library.
-# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
-# See Git Authentication for more information about setting up git authentication.
-#git-fetch-with-cli = true
-
-# This section is considered when running `cargo deny check licenses`
-# More documentation for the licenses section can be found here:
-# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
-[licenses]
-# The lint level for crates which do not have a detectable license
-unlicensed = "deny"
-# List of explicitly allowed licenses
-# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
-allow = [
- "MIT",
- "Apache-2.0",
- "BSD-3-Clause",
- "Unicode-DFS-2016",
-]
-# List of explicitly disallowed licenses
-# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
-deny = [
- #"Nokia",
-]
-# Lint level for licenses considered copyleft
-copyleft = "warn"
-# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
-# * both - The license will be approved if it is both OSI-approved *AND* FSF
-# * either - The license will be approved if it is either OSI-approved *OR* FSF
-# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
-# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
-# * neither - This predicate is ignored and the default lint level is used
-allow-osi-fsf-free = "neither"
-# Lint level used when no other predicates are matched
-# 1. License isn't in the allow or deny lists
-# 2. License isn't copyleft
-# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
-default = "deny"
-# The confidence threshold for detecting a license from license text.
-# The higher the value, the more closely the license text must be to the
-# canonical license text of a valid SPDX license file.
-# [possible values: any between 0.0 and 1.0].
-confidence-threshold = 0.8
-# Allow 1 or more licenses on a per-crate basis, so that particular licenses
-# aren't accepted for every possible crate as with the normal allow list
-exceptions = [
- # Each entry is the crate and version constraint, and its specific allow
- # list
- #{ allow = ["Zlib"], name = "adler32", version = "*" },
-]
-
-# Some crates don't have (easily) machine readable licensing information,
-# adding a clarification entry for it allows you to manually specify the
-# licensing information
-#[[licenses.clarify]]
-# The name of the crate the clarification applies to
-#name = "ring"
-# The optional version constraint for the crate
-#version = "*"
-# The SPDX expression for the license requirements of the crate
-#expression = "MIT AND ISC AND OpenSSL"
-# One or more files in the crate's source used as the "source of truth" for
-# the license expression. If the contents match, the clarification will be used
-# when running the license check, otherwise the clarification will be ignored
-# and the crate will be checked normally, which may produce warnings or errors
-# depending on the rest of your configuration
-#license-files = [
- # Each entry is a crate relative path, and the (opaque) hash of its contents
- #{ path = "LICENSE", hash = 0xbd0eed23 }
-#]
-
-[[licenses.clarify]]
-name = "ring"
-version = "*"
-expression = "MIT AND ISC AND OpenSSL"
-license-files = [
- # Each entry is a crate relative path, and the (opaque) hash of its contents
- { path = "LICENSE", hash = 0xbd0eed23 }
-]
-
-[licenses.private]
-# If true, ignores workspace crates that aren't published, or are only
-# published to private registries.
-# To see how to mark a crate as unpublished (to the official registry),
-# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
-ignore = true
-# One or more private registries that you might publish crates to, if a crate
-# is only published to private registries, and ignore is true, the crate will
-# not have its license(s) checked
-registries = [
- #"https://sekretz.com/registry
-]
-
-# This section is considered when running `cargo deny check bans`.
-# More documentation about the 'bans' section can be found here:
-# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
-[bans]
-# Lint level for when multiple versions of the same crate are detected
-multiple-versions = "allow"
-# Lint level for when a crate version requirement is `*`
-wildcards = "allow"
-# The graph highlighting used when creating dotgraphs for crates
-# with multiple versions
-# * lowest-version - The path to the lowest versioned duplicate is highlighted
-# * simplest-path - The path to the version with the fewest edges is highlighted
-# * all - Both lowest-version and simplest-path are used
-highlight = "all"
-# List of crates that are allowed. Use with care!
-allow = [
- #{ name = "ansi_term", version = "=0.11.0" },
-]
-# List of crates to deny
-deny = [
- # Each entry the name of a crate and a version range. If version is
- # not specified, all versions will be matched.
- #{ name = "ansi_term", version = "=0.11.0" },
- #
- # Wrapper crates can optionally be specified to allow the crate when it
- # is a direct dependency of the otherwise banned crate
- #{ name = "ansi_term", version = "=0.11.0", wrappers = [] },
-]
-# Certain crates/versions that will be skipped when doing duplicate detection.
-skip = [
- #{ name = "ansi_term", version = "=0.11.0" },
-]
-# Similarly to `skip` allows you to skip certain crates during duplicate
-# detection. Unlike skip, it also includes the entire tree of transitive
-# dependencies starting at the specified crate, up to a certain depth, which is
-# by default infinite
-skip-tree = [
- #{ name = "ansi_term", version = "=0.11.0", depth = 20 },
-]
-
-# This section is considered when running `cargo deny check sources`.
-# More documentation about the 'sources' section can be found here:
-# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
-[sources]
-# Lint level for what to happen when a crate from a crate registry that is not
-# in the allow list is encountered
-unknown-registry = "warn"
-# Lint level for what to happen when a crate from a git repository that is not
-# in the allow list is encountered
-unknown-git = "warn"
-# List of URLs for allowed crate registries. Defaults to the crates.io index
-# if not specified. If it is specified but empty, no registries are allowed.
-allow-registry = ["https://github.com/rust-lang/crates.io-index"]
-# List of URLs for allowed Git repositories
-allow-git = [] \ No newline at end of file
diff --git a/nearby/presence/np_c_ffi/include/c/np_c_ffi.h b/nearby/presence/np_c_ffi/include/c/np_c_ffi.h
index aab2a30..0eb9ecd 100644
--- a/nearby/presence/np_c_ffi/include/c/np_c_ffi.h
+++ b/nearby/presence/np_c_ffi/include/c/np_c_ffi.h
@@ -13,10 +13,12 @@
limitations under the License.
*/
+// clang-format off
+
#pragma once
-/* Generated with cbindgen:0.24.5 */
+/* Generated with cbindgen:0.26.0 */
/*
WARNING: this file is autogenerated by cbindgen. Don't modify this manually.
@@ -33,33 +35,160 @@
#include <stdlib.h>
/**
- * Result type for trying to add a credential to a credential-slab.
+ * The possible boolean action types which can be present in an Actions data element
+ */
+enum np_ffi_ActionType {
+ NP_FFI_ACTION_TYPE_CROSS_DEV_SDK = 1,
+ NP_FFI_ACTION_TYPE_CALL_TRANSFER = 4,
+ NP_FFI_ACTION_TYPE_ACTIVE_UNLOCK = 8,
+ NP_FFI_ACTION_TYPE_NEARBY_SHARE = 9,
+ NP_FFI_ACTION_TYPE_INSTANT_TETHERING = 10,
+ NP_FFI_ACTION_TYPE_PHONE_HUB = 11,
+};
+typedef uint8_t np_ffi_ActionType;
+
+/**
+ * Result type for trying to add a V0 credential to a credential-slab.
*/
-enum np_ffi_AddCredentialToSlabResult {
+enum np_ffi_AddV0CredentialToSlabResult {
/**
* We succeeded in adding the credential to the slab.
*/
- NP_FFI_ADD_CREDENTIAL_TO_SLAB_RESULT_SUCCESS = 0,
+ NP_FFI_ADD_V0_CREDENTIAL_TO_SLAB_RESULT_SUCCESS = 0,
/**
* The handle to the slab was actually invalid.
*/
- NP_FFI_ADD_CREDENTIAL_TO_SLAB_RESULT_INVALID_HANDLE = 1,
+ NP_FFI_ADD_V0_CREDENTIAL_TO_SLAB_RESULT_INVALID_HANDLE = 1,
};
-typedef uint8_t np_ffi_AddCredentialToSlabResult;
+typedef uint8_t np_ffi_AddV0CredentialToSlabResult;
/**
- * The possible boolean action types which can be present in an Actions data element
+ * Result code for the operation of adding a DE to a V0
+ * advertisement builder.
+ */
+enum np_ffi_AddV0DEResult {
+ /**
+ * The DE was successfully added to the advertisement builder
+ * behind the given handle.
+ */
+ NP_FFI_ADD_V0DE_RESULT_SUCCESS = 0,
+ /**
+ * The handle for the advertisement builder was invalid.
+ */
+ NP_FFI_ADD_V0DE_RESULT_INVALID_ADVERTISEMENT_BUILDER_HANDLE = 1,
+ /**
+ * There was not enough available space left in the advertisement
+ * to append the given data element.
+ */
+ NP_FFI_ADD_V0DE_RESULT_INSUFFICIENT_ADVERTISEMENT_SPACE = 2,
+ /**
+ * The passed data element is not broadcastable under the
+ * identity type of the advertisement (public/private).
+ */
+ NP_FFI_ADD_V0DE_RESULT_INVALID_IDENTITY_TYPE_FOR_DATA_ELEMENT = 3,
+};
+typedef uint8_t np_ffi_AddV0DEResult;
+
+/**
+ * Result type for trying to add a V1 credential to a credential-slab.
+ */
+enum np_ffi_AddV1CredentialToSlabResult {
+ /**
+ * We succeeded in adding the credential to the slab.
+ */
+ NP_FFI_ADD_V1_CREDENTIAL_TO_SLAB_RESULT_SUCCESS = 0,
+ /**
+ * The handle to the slab was actually invalid.
+ */
+ NP_FFI_ADD_V1_CREDENTIAL_TO_SLAB_RESULT_INVALID_HANDLE = 1,
+ /**
+ * The provided public key bytes do not actually represent a valid "edwards y" format
+ * or that said compressed point is not actually a point on the curve.
+ */
+ NP_FFI_ADD_V1_CREDENTIAL_TO_SLAB_RESULT_INVALID_PUBLIC_KEY_BYTES = 2,
+};
+typedef uint8_t np_ffi_AddV1CredentialToSlabResult;
+
+/**
+ * Result code for operations adding DEs to a section builder.
+ */
+enum np_ffi_AddV1DEResult {
+ /**
+ * The DE was successfully added to the section builder
+ * behind the given handle.
+ */
+ NP_FFI_ADD_V1DE_RESULT_SUCCESS = 0,
+ /**
+ * The handle for the section builder was invalid.
+ */
+ NP_FFI_ADD_V1DE_RESULT_INVALID_SECTION_HANDLE = 1,
+ /**
+ * There was no more space left in the advertisement
+ * to fit the DE in the containing section.
+ */
+ NP_FFI_ADD_V1DE_RESULT_INSUFFICIENT_SECTION_SPACE = 2,
+ /**
+ * The data element itself had invalid characteristics,
+ * most likely a length above 127.
+ */
+ NP_FFI_ADD_V1DE_RESULT_INVALID_DATA_ELEMENT = 3,
+};
+typedef uint8_t np_ffi_AddV1DEResult;
+
+/**
+ * Result code for [`V1SectionBuilder#add_to_advertisement`].
+ */
+enum np_ffi_AddV1SectionToAdvertisementResult {
+ /**
+ * The section referenced by the given handle
+ * couldn't be added to the containing advertisement,
+ * possibly because the handle is invalid or the section
+ * has already been added to the containing section.
+ */
+ NP_FFI_ADD_V1_SECTION_TO_ADVERTISEMENT_RESULT_ERROR = 0,
+ /**
+ * The section referenced by the given handle
+ * was successfully added to the containing advertisement.
+ * After obtaining this result code, the section
+ * handle will no longer be valid.
+ */
+ NP_FFI_ADD_V1_SECTION_TO_ADVERTISEMENT_RESULT_SUCCESS = 1,
+};
+typedef uint8_t np_ffi_AddV1SectionToAdvertisementResult;
+
+/**
+ * Enum common to V0 and V1 serialization expressing
+ * what kind of advertisement builder (public/encrypted)
+ * is in use.
+ */
+enum np_ffi_AdvertisementBuilderKind {
+ /**
+ * The builder is for a public advertisement.
+ */
+ NP_FFI_ADVERTISEMENT_BUILDER_KIND_PUBLIC = 0,
+ /**
+ * The builder is for an encrypted advertisement.
+ */
+ NP_FFI_ADVERTISEMENT_BUILDER_KIND_ENCRYPTED = 1,
+};
+typedef uint8_t np_ffi_AdvertisementBuilderKind;
+
+/**
+ * Discriminant for `BuildTxPowerResult`.
*/
-enum np_ffi_BooleanActionType {
- NP_FFI_BOOLEAN_ACTION_TYPE_ACTIVE_UNLOCK = 8,
- NP_FFI_BOOLEAN_ACTION_TYPE_NEARBY_SHARE = 9,
- NP_FFI_BOOLEAN_ACTION_TYPE_INSTANT_TETHERING = 10,
- NP_FFI_BOOLEAN_ACTION_TYPE_PHONE_HUB = 11,
- NP_FFI_BOOLEAN_ACTION_TYPE_PRESENCE_MANAGER = 12,
- NP_FFI_BOOLEAN_ACTION_TYPE_FINDER = 13,
- NP_FFI_BOOLEAN_ACTION_TYPE_FAST_PAIR_SASS = 14,
+enum np_ffi_BuildTxPowerResultKind {
+ /**
+ * The transmission power was outside the
+ * allowed -100dBm to 20dBm range.
+ */
+ NP_FFI_BUILD_TX_POWER_RESULT_KIND_OUT_OF_RANGE = 0,
+ /**
+ * The transmission power was in range,
+ * and so a `TxPower` struct was constructed.
+ */
+ NP_FFI_BUILD_TX_POWER_RESULT_KIND_SUCCESS = 1,
};
-typedef uint8_t np_ffi_BooleanActionType;
+typedef uint8_t np_ffi_BuildTxPowerResultKind;
/**
* Discriminant for `CreateCredentialBookResult`
@@ -72,33 +201,44 @@ enum np_ffi_CreateCredentialBookResultKind {
*/
NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_KIND_SUCCESS = 0,
/**
- * There was no space left to create a new credential book
- */
- NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_KIND_NO_SPACE_LEFT = 1,
- /**
* The slab that we tried to create a credential-book from
* actually was an invalid handle.
*/
- NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_KIND_INVALID_SLAB_HANDLE = 2,
+ NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_KIND_INVALID_SLAB_HANDLE = 1,
};
typedef uint8_t np_ffi_CreateCredentialBookResultKind;
/**
- * Discriminant for `CreateCredentialSlabResult`
+ * Discriminant for `CreateV1SectionBuilderResult`
*/
-enum np_ffi_CreateCredentialSlabResultKind {
+enum np_ffi_CreateV1SectionBuilderResultKind {
/**
- * There was no space left to create a new credential slab
+ * The attempt to create a new section builder succeeded.
*/
- NP_FFI_CREATE_CREDENTIAL_SLAB_RESULT_KIND_NO_SPACE_LEFT = 0,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_KIND_SUCCESS = 0,
/**
- * We created a new credential slab behind the given handle.
- * The associated payload may be obtained via
- * `CreateCredentialSlabResult#into_success()`.
+ * We're currently in the middle of building a section.
*/
- NP_FFI_CREATE_CREDENTIAL_SLAB_RESULT_KIND_SUCCESS = 1,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_KIND_UNCLOSED_ACTIVE_SECTION = 1,
+ /**
+ * The advertisement builder handle was invalid.
+ */
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_KIND_INVALID_ADVERTISEMENT_BUILDER_HANDLE = 2,
+ /**
+ * We're attempting to build a section with an identity
+ * kind (public/encrypted) which doesn't match the kind
+ * for the entire advertisement.
+ */
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_KIND_IDENTITY_KIND_MISMATCH = 3,
+ /**
+ * There isn't enough space for a new section, either
+ * because the maximum section count has been exceeded
+ * or because the advertisement is almost full, and
+ * the minimum size of a section wouldn't fit.
+ */
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_KIND_NO_SPACE_LEFT = 4,
};
-typedef uint8_t np_ffi_CreateCredentialSlabResultKind;
+typedef uint8_t np_ffi_CreateV1SectionBuilderResultKind;
/**
* A result-type enum which tells the caller whether/not a deallocation
@@ -108,11 +248,11 @@ typedef enum {
/**
* The requested handle to deallocate was not present in the map
*/
- NP_FFI_DEALLOCATE_RESULT_NOT_PRESENT = 0,
+ NP_FFI_DEALLOCATE_RESULT_NOT_PRESENT = 1,
/**
* The object behind the handle was successfully deallocated
*/
- NP_FFI_DEALLOCATE_RESULT_SUCCESS = 1,
+ NP_FFI_DEALLOCATE_RESULT_SUCCESS = 2,
} np_ffi_DeallocateResult;
/**
@@ -165,14 +305,14 @@ enum np_ffi_DeserializedV0AdvertisementKind {
* The associated payload may be obtained via
* `DeserializedV0Advertisement#into_legible`.
*/
- NP_FFI_DESERIALIZED_V0_ADVERTISEMENT_KIND_LEGIBLE = 0,
+ NP_FFI_DESERIALIZED_V0_ADVERTISEMENT_KIND_LEGIBLE = 1,
/**
* The deserialized V0 advertisement is illegible,
* likely meaning that the receiver does not hold
* the proper credentials to be able to read
* the received advertisement.
*/
- NP_FFI_DESERIALIZED_V0_ADVERTISEMENT_KIND_NO_MATCHING_CREDENTIALS = 1,
+ NP_FFI_DESERIALIZED_V0_ADVERTISEMENT_KIND_NO_MATCHING_CREDENTIALS = 2,
};
typedef uint8_t np_ffi_DeserializedV0AdvertisementKind;
@@ -184,11 +324,11 @@ enum np_ffi_DeserializedV0IdentityKind {
/**
* The deserialized identity was a plaintext identity.
*/
- NP_FFI_DESERIALIZED_V0_IDENTITY_KIND_PLAINTEXT = 0,
+ NP_FFI_DESERIALIZED_V0_IDENTITY_KIND_PLAINTEXT = 1,
/**
* The deserialized identity was some decrypted identity.
*/
- NP_FFI_DESERIALIZED_V0_IDENTITY_KIND_DECRYPTED = 1,
+ NP_FFI_DESERIALIZED_V0_IDENTITY_KIND_DECRYPTED = 2,
};
typedef uint8_t np_ffi_DeserializedV0IdentityKind;
@@ -208,28 +348,6 @@ enum np_ffi_DeserializedV1IdentityKind {
};
typedef uint8_t np_ffi_DeserializedV1IdentityKind;
-/**
- * The DE type for an encrypted identity
- */
-enum np_ffi_EncryptedIdentityType {
- /**
- * Identity for broadcasts to nearby devices with the same
- * logged-in-account (for some account).
- */
- NP_FFI_ENCRYPTED_IDENTITY_TYPE_PRIVATE = 1,
- /**
- * Identity for broadcasts to nearby devices which this
- * device has declared to trust.
- */
- NP_FFI_ENCRYPTED_IDENTITY_TYPE_TRUSTED = 2,
- /**
- * Identity for broadcasts to devices which have been provisioned
- * offline with this device.
- */
- NP_FFI_ENCRYPTED_IDENTITY_TYPE_PROVISIONED = 4,
-};
-typedef uint8_t np_ffi_EncryptedIdentityType;
-
enum np_ffi_GetMetadataBufferPartsResultKind {
NP_FFI_GET_METADATA_BUFFER_PARTS_RESULT_KIND_SUCCESS = 0,
NP_FFI_GET_METADATA_BUFFER_PARTS_RESULT_KIND_ERROR = 1,
@@ -357,6 +475,24 @@ enum np_ffi_GetV1SectionResultKind {
typedef uint8_t np_ffi_GetV1SectionResultKind;
/**
+ * Discriminant for `NextV1DE16ByteSaltResult`.
+ */
+enum np_ffi_NextV1DE16ByteSaltResultKind {
+ /**
+ * We couldn't return a 16-byte DE salt, possibly
+ * because the handle to the section builder
+ * was invalid, or possibly because the section
+ * builder was for a public section.
+ */
+ NP_FFI_NEXT_V1DE16_BYTE_SALT_RESULT_KIND_ERROR = 0,
+ /**
+ * A 16-byte DE salt was returned successfully.
+ */
+ NP_FFI_NEXT_V1DE16_BYTE_SALT_RESULT_KIND_SUCCESS = 1,
+};
+typedef uint8_t np_ffi_NextV1DE16ByteSaltResultKind;
+
+/**
* Structure for categorized reasons for why a NP C FFI call may
* be panicking.
*/
@@ -376,15 +512,91 @@ enum np_ffi_PanicReason {
*/
NP_FFI_PANIC_REASON_ASSERT_FAILED = 1,
/**
- * Error returned if action bits inside of a V0Actions struct are invalid. If the struct was
- * created by this deserializer, the bits will always be valid, they are only invalid if
- * a user reaches in and changes them to something invalid.
+ * Error returned if the bit representation of a supposedly-Rust-constructed
+ * -and-validated type actually doesn't correspond to the format of the
+ * data structure expected on the Rust side of the boundary, and performing
+ * further operations on the structure would yield unintended behavior.
+ * If this kind of error is being raised, the C code must
+ * be messing with stack-allocated data structures for this library
+ * in an entirely unexpected way.
+ */
+ NP_FFI_PANIC_REASON_INVALID_STACK_DATA_STRUCTURE = 2,
+ /**
+ * The maximum amount of allocations per type is `u32::MAX`, this panic handler is invoked
+ * with this reason when this is exceeded. Clients should never need more than 4 Billions
+ * handles and would certainly run into other issues before reaching that point
*/
- NP_FFI_PANIC_REASON_INVALID_ACTION_BITS = 2,
+ NP_FFI_PANIC_REASON_EXCEEDED_MAX_HANDLE_ALLOCATIONS = 3,
};
typedef uint8_t np_ffi_PanicReason;
/**
+ * Discriminant for `SerializeV0AdvertisementResult`.
+ */
+enum np_ffi_SerializeV0AdvertisementResultKind {
+ /**
+ * Serializing the advertisement to bytes was successful.
+ */
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_KIND_SUCCESS = 0,
+ /**
+ * The advertisement builder handle was invalid.
+ */
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_KIND_INVALID_ADVERTISEMENT_BUILDER_HANDLE = 1,
+ /**
+ * Serializing the advertisement to bytes failed
+ * because the data in the advertisement wasn't
+ * of an appropriate size for LDT encryption
+ * to succeed.
+ */
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_KIND_LDT_ERROR = 2,
+ /**
+ * Serializing an unencrypted adv failed because the adv data didn't meet the length
+ * requirements.
+ */
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_KIND_UNENCRYPTED_ERROR = 3,
+};
+typedef uint8_t np_ffi_SerializeV0AdvertisementResultKind;
+
+/**
+ * Discriminant for `SerializeV1AdvertisementResult`.
+ */
+enum np_ffi_SerializeV1AdvertisementResultKind {
+ /**
+ * Serializing the advertisement to bytes was successful.
+ */
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_KIND_SUCCESS = 0,
+ /**
+ * The state of the advertisement builder was invalid
+ * for the builder to be closed for serialization, likely
+ * because there was an unclosed section builder.
+ */
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_KIND_INVALID_BUILDER_STATE = 1,
+ /**
+ * The advertisement builder handle was invalid.
+ */
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_KIND_INVALID_ADVERTISEMENT_BUILDER_HANDLE = 2,
+};
+typedef uint8_t np_ffi_SerializeV1AdvertisementResultKind;
+
+/**
+ * Discriminant for `SetV0ActionResult`.
+ */
+enum np_ffi_SetV0ActionResultKind {
+ /**
+ * The attempt to set the action bit failed. The
+ * action bits were yielded back to the caller,
+ * unmodified.
+ */
+ NP_FFI_SET_V0_ACTION_RESULT_KIND_ERROR = 0,
+ /**
+ * The attempt to set the action bit succeeded.
+ * The updated action bits were yielded back to the caller.
+ */
+ NP_FFI_SET_V0_ACTION_RESULT_KIND_SUCCESS = 1,
+};
+typedef uint8_t np_ffi_SetV0ActionResultKind;
+
+/**
* Discriminant for `V0DataElement`.
*/
enum np_ffi_V0DataElementKind {
@@ -393,13 +605,13 @@ enum np_ffi_V0DataElementKind {
* The associated payload may be obtained via
* `V0DataElement#into_tx_power`.
*/
- NP_FFI_V0_DATA_ELEMENT_KIND_TX_POWER = 0,
+ NP_FFI_V0_DATA_ELEMENT_KIND_TX_POWER = 1,
/**
* The Actions data-element.
* The associated payload may be obtained via
* `V0DataElement#into_actions`.
*/
- NP_FFI_V0_DATA_ELEMENT_KIND_ACTIONS = 1,
+ NP_FFI_V0_DATA_ELEMENT_KIND_ACTIONS = 2,
};
typedef uint8_t np_ffi_V0DataElementKind;
@@ -421,7 +633,20 @@ enum np_ffi_V1VerificationMode {
typedef uint8_t np_ffi_V1VerificationMode;
/**
- *A `#[repr(C)]` handle to a value of type `super::CredentialBookInternals`.
+ * Holds the count of handles currently allocated for each handle type
+ */
+typedef struct {
+ uint32_t cred_book;
+ uint32_t cred_slab;
+ uint32_t decrypted_metadata;
+ uint32_t v0_payload;
+ uint32_t legible_v1_sections;
+ uint32_t v0_advertisement_builder;
+ uint32_t v1_advertisement_builder;
+} np_ffi_CurrentHandleAllocations;
+
+/**
+ * A `#[repr(C)]` handle to a value of type `CredentialBookInternals`
*/
typedef struct {
uint64_t handle_id;
@@ -432,7 +657,6 @@ typedef struct {
*/
enum np_ffi_CreateCredentialBookResult_Tag {
NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_SUCCESS = 0,
- NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_NO_SPACE_LEFT = 1,
NP_FFI_CREATE_CREDENTIAL_BOOK_RESULT_INVALID_SLAB_HANDLE = 2,
};
typedef uint8_t np_ffi_CreateCredentialBookResult_Tag;
@@ -446,36 +670,19 @@ typedef union {
} np_ffi_CreateCredentialBookResult;
/**
- *A `#[repr(C)]` handle to a value of type `super::CredentialSlabInternals`.
+ * A `#[repr(C)]` handle to a value of type `CredentialSlabInternals`
*/
typedef struct {
uint64_t handle_id;
} np_ffi_CredentialSlab;
/**
- * Result type for `create_credential_slab`
- */
-typedef enum {
- NP_FFI_CREATE_CREDENTIAL_SLAB_RESULT_NO_SPACE_LEFT,
- NP_FFI_CREATE_CREDENTIAL_SLAB_RESULT_SUCCESS,
-} np_ffi_CreateCredentialSlabResult_Tag;
-
-typedef struct {
- np_ffi_CreateCredentialSlabResult_Tag tag;
- union {
- struct {
- np_ffi_CredentialSlab success;
- };
- };
-} np_ffi_CreateCredentialSlabResult;
-
-/**
* Cryptographic information about a particular V0 discovery credential
* necessary to match and decrypt encrypted V0 advertisements.
*/
typedef struct {
uint8_t key_seed[32];
- uint8_t legacy_metadata_key_hmac[32];
+ uint8_t identity_token_hmac[32];
} np_ffi_V0DiscoveryCredential;
/**
@@ -503,8 +710,9 @@ typedef struct {
*/
typedef struct {
uint8_t key_seed[32];
- uint8_t expected_unsigned_metadata_key_hmac[32];
- uint8_t expected_signed_metadata_key_hmac[32];
+ uint8_t expected_mic_short_salt_identity_token_hmac[32];
+ uint8_t expected_mic_extended_salt_identity_token_hmac[32];
+ uint8_t expected_signature_identity_token_hmac[32];
uint8_t pub_key[32];
} np_ffi_V1DiscoveryCredential;
@@ -519,7 +727,7 @@ typedef struct {
} np_ffi_V1MatchableCredential;
/**
- *A `#[repr(C)]` handle to a value of type `super::DecryptedMetadataInternals`.
+ * A `#[repr(C)]` handle to a value of type `DecryptedMetadataInternals`
*/
typedef struct {
uint64_t handle_id;
@@ -565,7 +773,7 @@ typedef struct {
} np_ffi_GetMetadataBufferPartsResult;
/**
- *A `#[repr(C)]` handle to a value of type `super::V0PayloadInternals`.
+ * A `#[repr(C)]` handle to a value of type `V0PayloadInternals`
*/
typedef struct {
uint64_t handle_id;
@@ -598,7 +806,7 @@ typedef struct {
} np_ffi_DeserializedV0Advertisement;
/**
- *A `#[repr(C)]` handle to a value of type `super::LegibleV1SectionsInternals`.
+ * A `#[repr(C)]` handle to a value of type `LegibleV1SectionsInternals`
*/
typedef struct {
uint64_t handle_id;
@@ -608,8 +816,17 @@ typedef struct {
* Representation of a deserialized V1 advertisement
*/
typedef struct {
+ /**
+ * The number of legible sections
+ */
uint8_t num_legible_sections;
+ /**
+ * The number of sections that were unable to be decrypted
+ */
uint8_t num_undecryptable_sections;
+ /**
+ * A handle to the set of legible (plain or decrypted) sections
+ */
np_ffi_LegibleV1Sections legible_sections;
} np_ffi_DeserializedV1Advertisement;
@@ -677,7 +894,7 @@ typedef struct {
} np_ffi_TxPower;
/**
- * The bitfield data of a VOActions data element
+ * The bitfield data of a V0Actions data element
*/
typedef struct {
uint32_t bitfield;
@@ -752,18 +969,14 @@ typedef struct {
*/
typedef struct {
/**
- * The identity type (private/provisioned/trusted)
- */
- np_ffi_EncryptedIdentityType identity_type;
- /**
* The ID of the credential which
* matched the deserialized adv
*/
uint32_t cred_id;
/**
- * The 14-byte legacy metadata key
+ * The 14-byte legacy identity token
*/
- uint8_t metadata_key[14];
+ uint8_t identity_token[14];
/**
* The 2-byte advertisement salt
*/
@@ -902,10 +1115,6 @@ typedef struct {
*/
typedef struct {
/**
- * The identity type (private/provisioned/trusted)
- */
- np_ffi_EncryptedIdentityType identity_type;
- /**
* The verification mode (MIC/Signature) which
* was used to verify the decrypted adv contents.
*/
@@ -918,7 +1127,7 @@ typedef struct {
/**
* The 16-byte metadata key.
*/
- uint8_t metadata_key[16];
+ uint8_t identity_token[16];
} np_ffi_DeserializedV1IdentityDetails;
/**
@@ -966,6 +1175,230 @@ typedef struct {
} np_ffi_GetV1DE16ByteSaltResult;
/**
+ * A `#[repr(C)]` handle to a value of type `V0AdvertisementBuilderInternals`
+ */
+typedef struct {
+ uint64_t handle_id;
+} np_ffi_V0AdvertisementBuilderHandle;
+
+/**
+ * A handle to a builder for V0 advertisements.
+ */
+typedef struct {
+ np_ffi_AdvertisementBuilderKind kind;
+ np_ffi_V0AdvertisementBuilderHandle handle;
+} np_ffi_V0AdvertisementBuilder;
+
+/**
+ * A byte-string with a maximum size of N,
+ * where only the first `len` bytes are considered
+ * to contain the actual payload. N is only
+ * permitted to be between 0 and 255.
+ */
+typedef struct {
+ uint8_t len;
+ uint8_t bytes[24];
+} np_ffi_ByteBuffer_24;
+
+/**
+ * The result of attempting to serialize the contents
+ * of a V0 advertisement builder to raw bytes.
+ */
+typedef enum {
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_SUCCESS,
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_INVALID_ADVERTISEMENT_BUILDER_HANDLE,
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_LDT_ERROR,
+ NP_FFI_SERIALIZE_V0_ADVERTISEMENT_RESULT_UNENCRYPTED_ERROR,
+} np_ffi_SerializeV0AdvertisementResult_Tag;
+
+typedef struct {
+ np_ffi_SerializeV0AdvertisementResult_Tag tag;
+ union {
+ struct {
+ np_ffi_ByteBuffer_24 success;
+ };
+ };
+} np_ffi_SerializeV0AdvertisementResult;
+
+/**
+ * Cryptographic information about a particular V0 broadcast credential
+ * necessary to LDT-encrypt V0 advertisements.
+ */
+typedef struct {
+ uint8_t key_seed[32];
+ uint8_t identity_token[14];
+} np_ffi_V0BroadcastCredential;
+
+/**
+ * A FFI safe wrapper of a fixed size array
+ */
+typedef struct {
+ uint8_t _0[2];
+} np_ffi_FixedSizeArray_2;
+
+/**
+ * A `#[repr(C)]` handle to a value of type `V1AdvertisementBuilderInternals`
+ */
+typedef struct {
+ uint64_t handle_id;
+} np_ffi_V1AdvertisementBuilderHandle;
+
+/**
+ * A handle to a builder for V1 advertisements.
+ */
+typedef struct {
+ np_ffi_AdvertisementBuilderKind kind;
+ np_ffi_V1AdvertisementBuilderHandle handle;
+} np_ffi_V1AdvertisementBuilder;
+
+/**
+ * A handle to a builder for V1 sections. This is not a unique handle; it is the same handle as
+ * the advertisement builder the section builder was originated from.
+ */
+typedef struct {
+ np_ffi_V1AdvertisementBuilder adv_builder;
+ uint8_t section_index;
+} np_ffi_V1SectionBuilder;
+
+/**
+ * The result of attempting to create a new V1 section builder.
+ */
+typedef enum {
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_SUCCESS,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_UNCLOSED_ACTIVE_SECTION,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_INVALID_ADVERTISEMENT_BUILDER_HANDLE,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_IDENTITY_KIND_MISMATCH,
+ NP_FFI_CREATE_V1_SECTION_BUILDER_RESULT_NO_SPACE_LEFT,
+} np_ffi_CreateV1SectionBuilderResult_Tag;
+
+typedef struct {
+ np_ffi_CreateV1SectionBuilderResult_Tag tag;
+ union {
+ struct {
+ np_ffi_V1SectionBuilder success;
+ };
+ };
+} np_ffi_CreateV1SectionBuilderResult;
+
+/**
+ * Cryptographic information about a particular V1 broadcast credential
+ * necessary to encrypt V1 MIC-verified and signature-verified sections.
+ */
+typedef struct {
+ uint8_t key_seed[32];
+ uint8_t identity_token[16];
+ uint8_t private_key[32];
+} np_ffi_V1BroadcastCredential;
+
+/**
+ * A byte-string with a maximum size of N,
+ * where only the first `len` bytes are considered
+ * to contain the actual payload. N is only
+ * permitted to be between 0 and 255.
+ */
+typedef struct {
+ uint8_t len;
+ uint8_t bytes[250];
+} np_ffi_ByteBuffer_250;
+
+/**
+ * The result of attempting to serialize the contents
+ * of a V1 advertisement builder to raw bytes.
+ */
+typedef enum {
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_SUCCESS,
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_INVALID_BUILDER_STATE,
+ NP_FFI_SERIALIZE_V1_ADVERTISEMENT_RESULT_INVALID_ADVERTISEMENT_BUILDER_HANDLE,
+} np_ffi_SerializeV1AdvertisementResult_Tag;
+
+typedef struct {
+ np_ffi_SerializeV1AdvertisementResult_Tag tag;
+ union {
+ struct {
+ np_ffi_ByteBuffer_250 success;
+ };
+ };
+} np_ffi_SerializeV1AdvertisementResult;
+
+/**
+ * The result of attempting to get the derived V1 DE
+ * 16-byte salt for the next-added DE to the section
+ * builder behind the given handle.
+ */
+typedef enum {
+ NP_FFI_NEXT_V1DE16_BYTE_SALT_RESULT_ERROR,
+ NP_FFI_NEXT_V1DE16_BYTE_SALT_RESULT_SUCCESS,
+} np_ffi_NextV1DE16ByteSaltResult_Tag;
+
+typedef struct {
+ np_ffi_NextV1DE16ByteSaltResult_Tag tag;
+ union {
+ struct {
+ np_ffi_FixedSizeArray_16 success;
+ };
+ };
+} np_ffi_NextV1DE16ByteSaltResult;
+
+/**
+ * Represents the contents of a V1 DE whose payload
+ * is stored in a buffer which may contain up to 127 bytes,
+ * which is the maximum for any V1 DE.
+ *
+ * This representation is stable, and so you may directly
+ * reference this struct's fields if you wish.
+ */
+typedef struct {
+ /**
+ * The DE type code of this generic data-element.
+ */
+ uint32_t de_type;
+ /**
+ * The raw data-element byte payload, up to
+ * 127 bytes in length.
+ */
+ np_ffi_ByteBuffer_127 payload;
+} np_ffi_V1DE127ByteBuffer;
+
+/**
+ * Result type for attempting to construct a
+ * Tx Power from a signed byte.
+ */
+typedef enum {
+ NP_FFI_BUILD_TX_POWER_RESULT_OUT_OF_RANGE,
+ NP_FFI_BUILD_TX_POWER_RESULT_SUCCESS,
+} np_ffi_BuildTxPowerResult_Tag;
+
+typedef struct {
+ np_ffi_BuildTxPowerResult_Tag tag;
+ union {
+ struct {
+ np_ffi_TxPower success;
+ };
+ };
+} np_ffi_BuildTxPowerResult;
+
+/**
+ * The result of attempting to set a particular action
+ * bit on some `V0Actions`.
+ */
+typedef enum {
+ NP_FFI_SET_V0_ACTION_RESULT_SUCCESS,
+ NP_FFI_SET_V0_ACTION_RESULT_ERROR,
+} np_ffi_SetV0ActionResult_Tag;
+
+typedef struct {
+ np_ffi_SetV0ActionResult_Tag tag;
+ union {
+ struct {
+ np_ffi_V0Actions success;
+ };
+ struct {
+ np_ffi_V0Actions error;
+ };
+ };
+} np_ffi_SetV0ActionResult;
+
+/**
* Overrides the global panic handler to be used when NP C FFI calls panic.
* This method will only have an effect on the global panic-handler
* the first time it's called, and this method will return `true`
@@ -988,6 +1421,12 @@ typedef struct {
bool np_ffi_global_config_panic_handler(void (*handler)(np_ffi_PanicReason));
/**
+ * Checks the current count of all outstanding handle allocations, useful for debugging,
+ * logging, and testing
+ */
+np_ffi_CurrentHandleAllocations np_ffi_global_config_get_current_allocation_count(void);
+
+/**
* Sets an override to the number of shards to employ in the NP FFI's
* internal handle-maps, which places an upper bound on the number
* of writing threads which may make progress at any one time
@@ -1006,72 +1445,6 @@ bool np_ffi_global_config_panic_handler(void (*handler)(np_ffi_PanicReason));
void np_ffi_global_config_set_num_shards(uint8_t num_shards);
/**
- * Sets the maximum number of active handles to credential slabs
- * which may be active at any one time.
- * Default value: Max value.
- * Max value: `u32::MAX - 1`.
- *
- * Useful for bounding the maximum memory used by the client application
- * on credential slabs in constrained-memory environments.
- *
- * Setting this value will have no effect if the handle-maps for the
- * API have already begun being used by the client code, and any
- * values set will take effect upon the first usage of any API
- * call utilizing credential slabs.
- */
-void np_ffi_global_config_set_max_num_credential_slabs(uint32_t max_num_credential_slabs);
-
-/**
- * Sets the maximum number of active handles to credential books
- * which may be active at any one time.
- * Default value: Max value.
- * Max value: `u32::MAX - 1`.
- *
- * Useful for bounding the maximum memory used by the client application
- * on credential books in constrained-memory environments.
- *
- * Setting this value will have no effect if the handle-maps for the
- * API have already begun being used by the client code, and any
- * values set will take effect upon the first usage of any API
- * call utilizing credential books.
- */
-void np_ffi_global_config_set_max_num_credential_books(uint32_t max_num_credential_books);
-
-/**
- * Sets the maximum number of active handles to deserialized v0
- * advertisements which may be active at any one time.
- *
- * Useful for bounding the maximum memory used by the client application
- * on v0 advertisements in constrained-memory environments.
- *
- * Default value: Max value.
- * Max value: `u32::MAX - 1`.
- *
- * Setting this value will have no effect if the handle-maps for the
- * API have already begun being used by the client code, and any
- * values set will take effect upon the first usage of any API
- * call which references or returns a deserialized V0 advertisement.
- */
-void np_ffi_global_config_set_max_num_deserialized_v0_advertisements(uint32_t max_num_deserialized_v0_advertisements);
-
-/**
- * Sets the maximum number of active handles to deserialized v1
- * advertisements which may be active at any one time.
- *
- * Useful for bounding the maximum memory used by the client application
- * on v1 advertisements in constrained-memory environments.
- *
- * Default value: Max value.
- * Max value: `u32::MAX - 1`.
- *
- * Setting this value will have no effect if the handle-maps for the
- * API have already begun being used by the client code, and any
- * values set will take effect upon the first usage of any API
- * call which references or returns a deserialized V1 advertisement.
- */
-void np_ffi_global_config_set_max_num_deserialized_v1_advertisements(uint32_t max_num_deserialized_v1_advertisements);
-
-/**
* Allocates a new credential-book from the given slab, returning a handle
* to the created object. The slab will be deallocated by this call.
*/
@@ -1101,18 +1474,7 @@ np_ffi_DeallocateResult np_ffi_deallocate_credential_book(np_ffi_CredentialBook
/**
* Allocates a new credential-slab, returning a handle to the created object
*/
-np_ffi_CreateCredentialSlabResult np_ffi_create_credential_slab(void);
-
-/**
- * Gets the tag of a `CreateCredentialSlabResult` tagged enum.
- */
-np_ffi_CreateCredentialSlabResultKind np_ffi_CreateCredentialSlabResult_kind(np_ffi_CreateCredentialSlabResult result);
-
-/**
- * Casts a `CreateCredentialSlabResult` to the `SUCCESS` variant, panicking in the
- * case where the passed value is of a different enum variant.
- */
-np_ffi_CredentialSlab np_ffi_CreateCredentialSlabResult_into_SUCCESS(np_ffi_CreateCredentialSlabResult result);
+np_ffi_CredentialSlab np_ffi_create_credential_slab(void);
/**
* Adds the given V0 discovery credential with some associated
@@ -1122,8 +1484,8 @@ np_ffi_CredentialSlab np_ffi_CreateCredentialSlabResult_into_SUCCESS(np_ffi_Crea
* which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
* so concurrent modification of the array from another thread would cause undefined behavior.
*/
-np_ffi_AddCredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(np_ffi_CredentialSlab credential_slab,
- np_ffi_V0MatchableCredential v0_cred);
+np_ffi_AddV0CredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(np_ffi_CredentialSlab credential_slab,
+ np_ffi_V0MatchableCredential v0_cred);
/**
* Adds the given V1 discovery credential with some associated
@@ -1133,8 +1495,8 @@ np_ffi_AddCredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(np_ffi_
* which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
* so concurrent modification of the array from another thread would cause undefined behavior.
*/
-np_ffi_AddCredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(np_ffi_CredentialSlab credential_slab,
- np_ffi_V1MatchableCredential v1_cred);
+np_ffi_AddV1CredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(np_ffi_CredentialSlab credential_slab,
+ np_ffi_V1MatchableCredential v1_cred);
/**
* Frees the underlying resources of the decrypted metadata buffer
@@ -1291,38 +1653,6 @@ np_ffi_GetV0DEResultKind np_ffi_GetV0DEResult_kind(np_ffi_GetV0DEResult result);
np_ffi_V0DataElement np_ffi_GetV0DEResult_into_SUCCESS(np_ffi_GetV0DEResult result);
/**
- * Gets the tag of a `V0DataElement` tagged-union.
- */
-np_ffi_V0DataElementKind np_ffi_V0DataElement_kind(np_ffi_V0DataElement de);
-
-/**
- * Casts a `V0DataElement` to the `TxPower` variant, panicking in the
- * case where the passed value is of a different enum variant.
- */
-np_ffi_TxPower np_ffi_V0DataElement_into_TX_POWER(np_ffi_V0DataElement de);
-
-/**
- * Casts a `V0DataElement` to the `Actions` variant, panicking in the
- * case where the passed value is of a different enum variant.
- */
-np_ffi_V0Actions np_ffi_V0DataElement_into_ACTIONS(np_ffi_V0DataElement de);
-
-/**
- * Return whether a boolean action type is set in this data element
- */
-bool np_ffi_V0Actions_has_action(np_ffi_V0Actions actions, np_ffi_BooleanActionType action_type);
-
-/**
- * Gets the 4 bit context sync sequence number as a u8 from this data element
- */
-uint8_t np_ffi_V0Actions_get_context_sync_sequence_number(np_ffi_V0Actions actions);
-
-/**
- * Return whether a boolean action type is set in this data element
- */
-uint32_t np_ffi_V0Actions_as_u32(np_ffi_V0Actions actions);
-
-/**
* Gets the number of legible sections on a deserialized V1 advertisement.
* Suitable as an index bound for the second argument of
* `np_ffi_DeserializedV1Advertisement#get_section`.
@@ -1425,6 +1755,251 @@ np_ffi_GetV1DEResultKind np_ffi_GetV1DEResult_kind(np_ffi_GetV1DEResult result);
np_ffi_V1DataElement np_ffi_GetV1DEResult_into_SUCCESS(np_ffi_GetV1DEResult result);
/**
+ * Attempts to add the given data element to the V0
+ * advertisement builder behind the passed handle.
+ *
+ * This method may invoke the panic handler if the passed DE
+ * has an invalid layout, which may indicate that the backing
+ * data on the stack was somehow tampered with in an unintended way.
+ */
+np_ffi_AddV0DEResult np_ffi_V0AdvertisementBuilder_add_de(np_ffi_V0AdvertisementBuilder adv_builder,
+ np_ffi_V0DataElement de);
+
+/**
+ * Attempts to serialize the contents of the advertisement builder
+ * behind this handle to bytes. Assuming that the handle is valid,
+ * this operation will always result in the contents behind the
+ * advertisement builder handle being deallocated.
+ */
+np_ffi_SerializeV0AdvertisementResult np_ffi_V0AdvertisementBuilder_into_advertisement(np_ffi_V0AdvertisementBuilder adv_builder);
+
+/**
+ * Attempts to deallocate the v0 advertisement builder behind
+ * the given handle.
+ */
+np_ffi_DeallocateResult np_ffi_deallocate_v0_advertisement_builder(np_ffi_V0AdvertisementBuilder adv_builder);
+
+/**
+ * Creates a new V0 advertisement builder for a public advertisement.
+ */
+np_ffi_V0AdvertisementBuilder np_ffi_create_v0_public_advertisement_builder(void);
+
+/**
+ * Creates a new V0 advertisement builder for an encrypted advertisement.
+ */
+np_ffi_V0AdvertisementBuilder np_ffi_create_v0_encrypted_advertisement_builder(np_ffi_V0BroadcastCredential broadcast_cred,
+ np_ffi_FixedSizeArray_2 salt);
+
+/**
+ * Gets the tag of a `SerializeV0AdvertisementResult` tagged-union.
+ */
+np_ffi_SerializeV0AdvertisementResultKind np_ffi_SerializeV0AdvertisementResult_kind(np_ffi_SerializeV0AdvertisementResult result);
+
+/**
+ * Casts a `SerializeV0AdvertisementResult` to the `Success` variant,
+ * panicking in the case where the passed value is of a different enum variant.
+ */
+np_ffi_ByteBuffer_24 np_ffi_SerializeV0AdvertisementResult_into_SUCCESS(np_ffi_SerializeV0AdvertisementResult result);
+
+/**
+ * Attempts to create a builder for a new public section within
+ * the advertisement builder behind this handle,
+ * returning a handle to the newly-created section builder if successful.
+ *
+ * This method may fail if there is another currently-active
+ * section builder for the same advertisement builder, if the
+ * kind of section being added does not match the advertisement
+ * type (public/encrypted), or if the section would not manage
+ * to fit within the enclosing advertisement.
+ */
+np_ffi_CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_public_section_builder(np_ffi_V1AdvertisementBuilder adv_builder);
+
+/**
+ * Attempts to create a builder for a new encrypted section within
+ * the advertisement builder behind the given handle,
+ * returning a handle to the newly-created section builder if successful.
+ *
+ * The identity details for the new section builder may be specified
+ * via providing the broadcast credential data, the kind of encrypted
+ * identity being broadcast (private/trusted/provisioned), and the
+ * verification mode (MIC/Signature) to be used for the encrypted section.
+ *
+ * This method may fail if there is another currently-active
+ * section builder for the same advertisement builder, if the
+ * kind of section being added does not match the advertisement
+ * type (public/encrypted), or if the section would not manage
+ * to fit within the enclosing advertisement.
+ */
+np_ffi_CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_encrypted_section_builder(np_ffi_V1AdvertisementBuilder adv_builder,
+ np_ffi_V1BroadcastCredential broadcast_cred,
+ np_ffi_V1VerificationMode verification_mode);
+
+/**
+ * Attempts to serialize the contents of the advertisement builder
+ * behind this handle to bytes. Assuming that the handle is valid,
+ * this operation will always result in the contents behind the
+ * advertisement builder handle being deallocated.
+ */
+np_ffi_SerializeV1AdvertisementResult np_ffi_V1AdvertisementBuilder_into_advertisement(np_ffi_V1AdvertisementBuilder adv_builder);
+
+/**
+ * Creates a new V1 advertisement builder for the given advertisement
+ * kind (public/encrypted).
+ */
+np_ffi_V1AdvertisementBuilder np_ffi_create_v1_advertisement_builder(np_ffi_AdvertisementBuilderKind kind);
+
+/**
+ * Gets the tag of a `SerializeV1AdvertisementResult` tagged-union.
+ */
+np_ffi_SerializeV1AdvertisementResultKind np_ffi_SerializeV1AdvertisementResult_kind(np_ffi_SerializeV1AdvertisementResult result);
+
+/**
+ * Casts a `SerializeV1AdvertisementResult` to the `Success` variant,
+ * panicking in the case where the passed value is of a different enum variant.
+ */
+np_ffi_ByteBuffer_250 np_ffi_SerializeV1AdvertisementResult_into_SUCCESS(np_ffi_SerializeV1AdvertisementResult result);
+
+/**
+ * Gets the tag of a `CreateV1SectionBuilderResult` tagged-union.
+ */
+np_ffi_CreateV1SectionBuilderResultKind np_ffi_CreateV1SectionBuilderResult_kind(np_ffi_CreateV1SectionBuilderResult result);
+
+/**
+ * Casts a `CreateV1SectionBuilderResult` to the `Success` variant,
+ * panicking in the case where the passed value is of a different enum variant.
+ */
+np_ffi_V1SectionBuilder np_ffi_CreateV1SectionBuilderResult_into_SUCCESS(np_ffi_CreateV1SectionBuilderResult result);
+
+/**
+ * Gets the tag of a `NextV1DE16ByteSaltResult` tagged-union.
+ */
+np_ffi_NextV1DE16ByteSaltResultKind np_ffi_NextV1DE16ByteSaltResult_kind(np_ffi_NextV1DE16ByteSaltResult result);
+
+/**
+ * Casts a `NextV1DE16ByteSaltResult` to the `Success` variant,
+ * panicking in the case where the passed value is of a different enum variant.
+ */
+np_ffi_FixedSizeArray_16 np_ffi_NextV1DE16ByteSaltResult_into_SUCCESS(np_ffi_NextV1DE16ByteSaltResult result);
+
+/**
+ * Adds the section constructed behind the given handle to
+ * a section builder to the containing advertisement it originated from.
+ * After this call, the section builder handle will become invalid.
+ */
+np_ffi_AddV1SectionToAdvertisementResult np_ffi_V1SectionBuilder_add_to_advertisement(np_ffi_V1SectionBuilder section_builder);
+
+/**
+ * Attempts to get the derived 16-byte V1 DE salt for the next
+ * DE to be added to the passed section builder. May fail if this
+ * section builder handle is invalid, or if the section
+ * is a public section.
+ */
+np_ffi_NextV1DE16ByteSaltResult np_ffi_V1SectionBuilder_next_de_salt(np_ffi_V1SectionBuilder section_builder);
+
+/**
+ * Attempts to add the given DE to the section builder behind
+ * this handle. The passed DE may have a payload of up to 127
+ * bytes, the maximum for a V1 DE.
+ */
+np_ffi_AddV1DEResult np_ffi_V1SectionBuilder_add_127_byte_buffer_de(np_ffi_V1SectionBuilder section_builder,
+ np_ffi_V1DE127ByteBuffer de);
+
+/**
+ * Gets the tag of a `V0DataElement` tagged-union.
+ */
+np_ffi_V0DataElementKind np_ffi_V0DataElement_kind(np_ffi_V0DataElement de);
+
+/**
+ * Casts a `V0DataElement` to the `TxPower` variant, panicking in the
+ * case where the passed value is of a different enum variant.
+ */
+np_ffi_TxPower np_ffi_V0DataElement_into_TX_POWER(np_ffi_V0DataElement de);
+
+/**
+ * Upcasts a Tx power DE to a generic V0 data-element.
+ */
+np_ffi_V0DataElement np_ffi_TxPower_into_V0DataElement(np_ffi_TxPower tx_power);
+
+/**
+ * Casts a `V0DataElement` to the `Actions` variant, panicking in the
+ * case where the passed value is of a different enum variant.
+ */
+np_ffi_V0Actions np_ffi_V0DataElement_into_ACTIONS(np_ffi_V0DataElement de);
+
+/**
+ * Upcasts a V0 actions DE to a generic V0 data-element.
+ */
+np_ffi_V0DataElement np_ffi_V0Actions_into_V0DataElement(np_ffi_V0Actions actions);
+
+/**
+ * Gets the tag of a `BuildTxPowerResult` tagged-union.
+ */
+np_ffi_BuildTxPowerResultKind np_ffi_BuildTxPowerResult_kind(np_ffi_BuildTxPowerResult result);
+
+/**
+ * Casts a `BuildTxPowerResult` to the `Success` variant, panicking in the
+ * case where the passed value is of a different enum variant.
+ */
+np_ffi_TxPower np_ffi_BuildTxPowerResult_into_SUCCESS(np_ffi_BuildTxPowerResult result);
+
+/**
+ * Attempts to construct a new TxPower from
+ * the given signed-byte value.
+ */
+np_ffi_BuildTxPowerResult np_ffi_TxPower_build_from_signed_byte(int8_t tx_power);
+
+/**
+ * Gets the value of the given TxPower as a signed byte.
+ */
+int8_t np_ffi_TxPower_as_signed_byte(np_ffi_TxPower tx_power);
+
+/**
+ * Gets the discriminant of the `SetV0ActionResult` tagged-union.
+ */
+np_ffi_SetV0ActionResultKind np_ffi_SetV0ActionResult_kind(np_ffi_SetV0ActionResult result);
+
+/**
+ * Attempts to cast a `SetV0ActionResult` tagged-union into the `Success` variant.
+ */
+np_ffi_V0Actions np_ffi_SetV0ActionResult_into_SUCCESS(np_ffi_SetV0ActionResult result);
+
+/**
+ * Attempts to cast a `SetV0ActionResult` tagged-union into the `Error` variant.
+ */
+np_ffi_V0Actions np_ffi_SetV0ActionResult_into_ERROR(np_ffi_SetV0ActionResult result);
+
+/**
+ * Constructs a new V0 actions DE with no declared boolean
+ * actions and a zeroed context sync sequence number,
+ * where the DE is intended for the given advertisement
+ * kind (plaintext/encrypted).
+ */
+np_ffi_V0Actions np_ffi_build_new_zeroed_V0Actions(np_ffi_AdvertisementBuilderKind kind);
+
+/**
+ * Return whether a boolean action type is set in this data element
+ */
+bool np_ffi_V0Actions_has_action(np_ffi_V0Actions actions, np_ffi_ActionType action_type);
+
+/**
+ * Attempts to set the given action bit to the given boolean value.
+ * This operation may fail if the requested action bit may not be
+ * set for the kind of containing advertisement (public/encrypted)
+ * that this action DE is intended to belong to. In this case,
+ * the original action bits will be yielded back to the caller,
+ * unaltered.
+ */
+np_ffi_SetV0ActionResult np_ffi_V0Actions_set_action(np_ffi_V0Actions actions,
+ np_ffi_ActionType action_type,
+ bool value);
+
+/**
+ * Returns the representation of the passed `V0Actions` as an unsigned
+ * integer, where the bit-positions correspond to individual actions.
+ */
+uint32_t np_ffi_V0Actions_as_u32(np_ffi_V0Actions actions);
+
+/**
* Converts a `V1DataElement` to a `GenericV1DataElement` which
* only maintains information about the DE's type-code and payload.
*/
@@ -1435,3 +2010,5 @@ np_ffi_GenericV1DataElement np_ffi_V1DataElement_to_generic(np_ffi_V1DataElement
* an unsigned 32-bit integer.
*/
uint32_t np_ffi_V1DEType_to_uint32_t(np_ffi_V1DEType de_type);
+
+// clang-format on
diff --git a/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_functions.h b/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_functions.h
index ffd63b0..d197bc8 100644
--- a/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_functions.h
+++ b/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_functions.h
@@ -13,10 +13,12 @@
limitations under the License.
*/
+// clang-format off
+
#pragma once
-/* Generated with cbindgen:0.24.5 */
+/* Generated with cbindgen:0.26.0 */
/*
WARNING: this file is autogenerated by cbindgen. Don't modify this manually.
@@ -59,6 +61,10 @@ extern "C" {
/// but a bare `loop { }` when this crate is compiled without.
bool np_ffi_global_config_panic_handler(void (*handler)(PanicReason));
+/// Checks the current count of all outstanding handle allocations, useful for debugging,
+/// logging, and testing
+CurrentHandleAllocations np_ffi_global_config_get_current_allocation_count();
+
/// Sets an override to the number of shards to employ in the NP FFI's
/// internal handle-maps, which places an upper bound on the number
/// of writing threads which may make progress at any one time
@@ -75,64 +81,6 @@ bool np_ffi_global_config_panic_handler(void (*handler)(PanicReason));
/// API call.
void np_ffi_global_config_set_num_shards(uint8_t num_shards);
-/// Sets the maximum number of active handles to credential slabs
-/// which may be active at any one time.
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on credential slabs in constrained-memory environments.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential slabs.
-void np_ffi_global_config_set_max_num_credential_slabs(uint32_t max_num_credential_slabs);
-
-/// Sets the maximum number of active handles to credential books
-/// which may be active at any one time.
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on credential books in constrained-memory environments.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential books.
-void np_ffi_global_config_set_max_num_credential_books(uint32_t max_num_credential_books);
-
-/// Sets the maximum number of active handles to deserialized v0
-/// advertisements which may be active at any one time.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on v0 advertisements in constrained-memory environments.
-///
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V0 advertisement.
-void np_ffi_global_config_set_max_num_deserialized_v0_advertisements(uint32_t max_num_deserialized_v0_advertisements);
-
-/// Sets the maximum number of active handles to deserialized v1
-/// advertisements which may be active at any one time.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on v1 advertisements in constrained-memory environments.
-///
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V1 advertisement.
-void np_ffi_global_config_set_max_num_deserialized_v1_advertisements(uint32_t max_num_deserialized_v1_advertisements);
-
/// Allocates a new credential-book from the given slab, returning a handle
/// to the created object. The slab will be deallocated by this call.
CreateCredentialBookResult np_ffi_create_credential_book_from_slab(CredentialSlab slab);
@@ -151,14 +99,7 @@ DeallocateResult np_ffi_deallocate_credential_slab(CredentialSlab credential_sla
DeallocateResult np_ffi_deallocate_credential_book(CredentialBook credential_book);
/// Allocates a new credential-slab, returning a handle to the created object
-CreateCredentialSlabResult np_ffi_create_credential_slab();
-
-/// Gets the tag of a `CreateCredentialSlabResult` tagged enum.
-CreateCredentialSlabResultKind np_ffi_CreateCredentialSlabResult_kind(CreateCredentialSlabResult result);
-
-/// Casts a `CreateCredentialSlabResult` to the `SUCCESS` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-CredentialSlab np_ffi_CreateCredentialSlabResult_into_SUCCESS(CreateCredentialSlabResult result);
+CredentialSlab np_ffi_create_credential_slab();
/// Adds the given V0 discovery credential with some associated
/// match-data to this credential slab.
@@ -166,8 +107,8 @@ CredentialSlab np_ffi_CreateCredentialSlabResult_into_SUCCESS(CreateCredentialSl
/// Safety: this is safe if the provided pointer points to a valid memory address
/// which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
/// so concurrent modification of the array from another thread would cause undefined behavior.
-AddCredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(CredentialSlab credential_slab,
- V0MatchableCredential v0_cred);
+AddV0CredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(CredentialSlab credential_slab,
+ V0MatchableCredential v0_cred);
/// Adds the given V1 discovery credential with some associated
/// match-data to this credential slab.
@@ -175,8 +116,8 @@ AddCredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(CredentialSlab
/// Safety: this is safe if the provided pointer points to a valid memory address
/// which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
/// so concurrent modification of the array from another thread would cause undefined behavior.
-AddCredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(CredentialSlab credential_slab,
- V1MatchableCredential v1_cred);
+AddV1CredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(CredentialSlab credential_slab,
+ V1MatchableCredential v1_cred);
/// Frees the underlying resources of the decrypted metadata buffer
DeallocateResult np_ffi_deallocate_DecryptedMetadata(DecryptedMetadata metadata);
@@ -278,26 +219,6 @@ GetV0DEResultKind np_ffi_GetV0DEResult_kind(GetV0DEResult result);
/// case where the passed value is of a different enum variant.
V0DataElement np_ffi_GetV0DEResult_into_SUCCESS(GetV0DEResult result);
-/// Gets the tag of a `V0DataElement` tagged-union.
-V0DataElementKind np_ffi_V0DataElement_kind(V0DataElement de);
-
-/// Casts a `V0DataElement` to the `TxPower` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-TxPower np_ffi_V0DataElement_into_TX_POWER(V0DataElement de);
-
-/// Casts a `V0DataElement` to the `Actions` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-V0Actions np_ffi_V0DataElement_into_ACTIONS(V0DataElement de);
-
-/// Return whether a boolean action type is set in this data element
-bool np_ffi_V0Actions_has_action(V0Actions actions, BooleanActionType action_type);
-
-/// Gets the 4 bit context sync sequence number as a u8 from this data element
-uint8_t np_ffi_V0Actions_get_context_sync_sequence_number(V0Actions actions);
-
-/// Return whether a boolean action type is set in this data element
-uint32_t np_ffi_V0Actions_as_u32(V0Actions actions);
-
/// Gets the number of legible sections on a deserialized V1 advertisement.
/// Suitable as an index bound for the second argument of
/// `np_ffi_DeserializedV1Advertisement#get_section`.
@@ -365,6 +286,179 @@ GetV1DEResultKind np_ffi_GetV1DEResult_kind(GetV1DEResult result);
/// case where the passed value is of a different enum variant.
V1DataElement np_ffi_GetV1DEResult_into_SUCCESS(GetV1DEResult result);
+/// Attempts to add the given data element to the V0
+/// advertisement builder behind the passed handle.
+///
+/// This method may invoke the panic handler if the passed DE
+/// has an invalid layout, which may indicate that the backing
+/// data on the stack was somehow tampered with in an unintended way.
+AddV0DEResult np_ffi_V0AdvertisementBuilder_add_de(V0AdvertisementBuilder adv_builder,
+ V0DataElement de);
+
+/// Attempts to serialize the contents of the advertisement builder
+/// behind this handle to bytes. Assuming that the handle is valid,
+/// this operation will always result in the contents behind the
+/// advertisement builder handle being deallocated.
+SerializeV0AdvertisementResult np_ffi_V0AdvertisementBuilder_into_advertisement(V0AdvertisementBuilder adv_builder);
+
+/// Attempts to deallocate the v0 advertisement builder behind
+/// the given handle.
+DeallocateResult np_ffi_deallocate_v0_advertisement_builder(V0AdvertisementBuilder adv_builder);
+
+/// Creates a new V0 advertisement builder for a public advertisement.
+V0AdvertisementBuilder np_ffi_create_v0_public_advertisement_builder();
+
+/// Creates a new V0 advertisement builder for an encrypted advertisement.
+V0AdvertisementBuilder np_ffi_create_v0_encrypted_advertisement_builder(V0BroadcastCredential broadcast_cred,
+ FixedSizeArray<2> salt);
+
+/// Gets the tag of a `SerializeV0AdvertisementResult` tagged-union.
+SerializeV0AdvertisementResultKind np_ffi_SerializeV0AdvertisementResult_kind(SerializeV0AdvertisementResult result);
+
+/// Casts a `SerializeV0AdvertisementResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+ByteBuffer<24> np_ffi_SerializeV0AdvertisementResult_into_SUCCESS(SerializeV0AdvertisementResult result);
+
+/// Attempts to create a builder for a new public section within
+/// the advertisement builder behind this handle,
+/// returning a handle to the newly-created section builder if successful.
+///
+/// This method may fail if there is another currently-active
+/// section builder for the same advertisement builder, if the
+/// kind of section being added does not match the advertisement
+/// type (public/encrypted), or if the section would not manage
+/// to fit within the enclosing advertisement.
+CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_public_section_builder(V1AdvertisementBuilder adv_builder);
+
+/// Attempts to create a builder for a new encrypted section within
+/// the advertisement builder behind the given handle,
+/// returning a handle to the newly-created section builder if successful.
+///
+/// The identity details for the new section builder may be specified
+/// via providing the broadcast credential data, the kind of encrypted
+/// identity being broadcast (private/trusted/provisioned), and the
+/// verification mode (MIC/Signature) to be used for the encrypted section.
+///
+/// This method may fail if there is another currently-active
+/// section builder for the same advertisement builder, if the
+/// kind of section being added does not match the advertisement
+/// type (public/encrypted), or if the section would not manage
+/// to fit within the enclosing advertisement.
+CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_encrypted_section_builder(V1AdvertisementBuilder adv_builder,
+ V1BroadcastCredential broadcast_cred,
+ V1VerificationMode verification_mode);
+
+/// Attempts to serialize the contents of the advertisement builder
+/// behind this handle to bytes. Assuming that the handle is valid,
+/// this operation will always result in the contents behind the
+/// advertisement builder handle being deallocated.
+SerializeV1AdvertisementResult np_ffi_V1AdvertisementBuilder_into_advertisement(V1AdvertisementBuilder adv_builder);
+
+/// Creates a new V1 advertisement builder for the given advertisement
+/// kind (public/encrypted).
+V1AdvertisementBuilder np_ffi_create_v1_advertisement_builder(AdvertisementBuilderKind kind);
+
+/// Gets the tag of a `SerializeV1AdvertisementResult` tagged-union.
+SerializeV1AdvertisementResultKind np_ffi_SerializeV1AdvertisementResult_kind(SerializeV1AdvertisementResult result);
+
+/// Casts a `SerializeV1AdvertisementResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+ByteBuffer<250> np_ffi_SerializeV1AdvertisementResult_into_SUCCESS(SerializeV1AdvertisementResult result);
+
+/// Gets the tag of a `CreateV1SectionBuilderResult` tagged-union.
+CreateV1SectionBuilderResultKind np_ffi_CreateV1SectionBuilderResult_kind(CreateV1SectionBuilderResult result);
+
+/// Casts a `CreateV1SectionBuilderResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+V1SectionBuilder np_ffi_CreateV1SectionBuilderResult_into_SUCCESS(CreateV1SectionBuilderResult result);
+
+/// Gets the tag of a `NextV1DE16ByteSaltResult` tagged-union.
+NextV1DE16ByteSaltResultKind np_ffi_NextV1DE16ByteSaltResult_kind(NextV1DE16ByteSaltResult result);
+
+/// Casts a `NextV1DE16ByteSaltResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+FixedSizeArray<16> np_ffi_NextV1DE16ByteSaltResult_into_SUCCESS(NextV1DE16ByteSaltResult result);
+
+/// Adds the section constructed behind the given handle to
+/// a section builder to the containing advertisement it originated from.
+/// After this call, the section builder handle will become invalid.
+AddV1SectionToAdvertisementResult np_ffi_V1SectionBuilder_add_to_advertisement(V1SectionBuilder section_builder);
+
+/// Attempts to get the derived 16-byte V1 DE salt for the next
+/// DE to be added to the passed section builder. May fail if this
+/// section builder handle is invalid, or if the section
+/// is a public section.
+NextV1DE16ByteSaltResult np_ffi_V1SectionBuilder_next_de_salt(V1SectionBuilder section_builder);
+
+/// Attempts to add the given DE to the section builder behind
+/// this handle. The passed DE may have a payload of up to 127
+/// bytes, the maximum for a V1 DE.
+AddV1DEResult np_ffi_V1SectionBuilder_add_127_byte_buffer_de(V1SectionBuilder section_builder,
+ V1DE127ByteBuffer de);
+
+/// Gets the tag of a `V0DataElement` tagged-union.
+V0DataElementKind np_ffi_V0DataElement_kind(V0DataElement de);
+
+/// Casts a `V0DataElement` to the `TxPower` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+TxPower np_ffi_V0DataElement_into_TX_POWER(V0DataElement de);
+
+/// Upcasts a Tx power DE to a generic V0 data-element.
+V0DataElement np_ffi_TxPower_into_V0DataElement(TxPower tx_power);
+
+/// Casts a `V0DataElement` to the `Actions` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+V0Actions np_ffi_V0DataElement_into_ACTIONS(V0DataElement de);
+
+/// Upcasts a V0 actions DE to a generic V0 data-element.
+V0DataElement np_ffi_V0Actions_into_V0DataElement(V0Actions actions);
+
+/// Gets the tag of a `BuildTxPowerResult` tagged-union.
+BuildTxPowerResultKind np_ffi_BuildTxPowerResult_kind(BuildTxPowerResult result);
+
+/// Casts a `BuildTxPowerResult` to the `Success` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+TxPower np_ffi_BuildTxPowerResult_into_SUCCESS(BuildTxPowerResult result);
+
+/// Attempts to construct a new TxPower from
+/// the given signed-byte value.
+BuildTxPowerResult np_ffi_TxPower_build_from_signed_byte(int8_t tx_power);
+
+/// Gets the value of the given TxPower as a signed byte.
+int8_t np_ffi_TxPower_as_signed_byte(TxPower tx_power);
+
+/// Gets the discriminant of the `SetV0ActionResult` tagged-union.
+SetV0ActionResultKind np_ffi_SetV0ActionResult_kind(SetV0ActionResult result);
+
+/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Success` variant.
+V0Actions np_ffi_SetV0ActionResult_into_SUCCESS(SetV0ActionResult result);
+
+/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Error` variant.
+V0Actions np_ffi_SetV0ActionResult_into_ERROR(SetV0ActionResult result);
+
+/// Constructs a new V0 actions DE with no declared boolean
+/// actions and a zeroed context sync sequence number,
+/// where the DE is intended for the given advertisement
+/// kind (plaintext/encrypted).
+V0Actions np_ffi_build_new_zeroed_V0Actions(AdvertisementBuilderKind kind);
+
+/// Return whether a boolean action type is set in this data element
+bool np_ffi_V0Actions_has_action(V0Actions actions, ActionType action_type);
+
+/// Attempts to set the given action bit to the given boolean value.
+/// This operation may fail if the requested action bit may not be
+/// set for the kind of containing advertisement (public/encrypted)
+/// that this action DE is intended to belong to. In this case,
+/// the original action bits will be yielded back to the caller,
+/// unaltered.
+SetV0ActionResult np_ffi_V0Actions_set_action(V0Actions actions,
+ ActionType action_type,
+ bool value);
+
+/// Returns the representation of the passed `V0Actions` as an unsigned
+/// integer, where the bit-positions correspond to individual actions.
+uint32_t np_ffi_V0Actions_as_u32(V0Actions actions);
+
/// Converts a `V1DataElement` to a `GenericV1DataElement` which
/// only maintains information about the DE's type-code and payload.
GenericV1DataElement np_ffi_V1DataElement_to_generic(V1DataElement de);
@@ -377,3 +471,5 @@ uint32_t np_ffi_V1DEType_to_uint32_t(V1DEType de_type);
} // namespace internal
} // namespace np_ffi
+
+// clang-format on
diff --git a/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h b/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h
index b5908ef..ba3ed34 100644
--- a/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h
+++ b/nearby/presence/np_c_ffi/include/cpp/np_cpp_ffi_types.h
@@ -13,10 +13,12 @@
limitations under the License.
*/
+// clang-format off
+
#pragma once
-/* Generated with cbindgen:0.24.5 */
+/* Generated with cbindgen:0.26.0 */
/*
WARNING: this file is autogenerated by cbindgen. Don't modify this manually.
@@ -36,23 +38,98 @@
namespace np_ffi {
namespace internal {
-/// Result type for trying to add a credential to a credential-slab.
-enum class AddCredentialToSlabResult : uint8_t {
+/// The possible boolean action types which can be present in an Actions data element
+enum class ActionType : uint8_t {
+ CrossDevSdk = 1,
+ CallTransfer = 4,
+ ActiveUnlock = 8,
+ NearbyShare = 9,
+ InstantTethering = 10,
+ PhoneHub = 11,
+};
+
+/// Result type for trying to add a V0 credential to a credential-slab.
+enum class AddV0CredentialToSlabResult : uint8_t {
/// We succeeded in adding the credential to the slab.
Success = 0,
/// The handle to the slab was actually invalid.
InvalidHandle = 1,
};
-/// The possible boolean action types which can be present in an Actions data element
-enum class BooleanActionType : uint8_t {
- ActiveUnlock = 8,
- NearbyShare = 9,
- InstantTethering = 10,
- PhoneHub = 11,
- PresenceManager = 12,
- Finder = 13,
- FastPairSass = 14,
+/// Result code for the operation of adding a DE to a V0
+/// advertisement builder.
+enum class AddV0DEResult : uint8_t {
+ /// The DE was successfully added to the advertisement builder
+ /// behind the given handle.
+ Success = 0,
+ /// The handle for the advertisement builder was invalid.
+ InvalidAdvertisementBuilderHandle = 1,
+ /// There was not enough available space left in the advertisement
+ /// to append the given data element.
+ InsufficientAdvertisementSpace = 2,
+ /// The passed data element is not broadcastable under the
+ /// identity type of the advertisement (public/private).
+ InvalidIdentityTypeForDataElement = 3,
+};
+
+/// Result type for trying to add a V1 credential to a credential-slab.
+enum class AddV1CredentialToSlabResult : uint8_t {
+ /// We succeeded in adding the credential to the slab.
+ Success = 0,
+ /// The handle to the slab was actually invalid.
+ InvalidHandle = 1,
+ /// The provided public key bytes do not actually represent a valid "edwards y" format
+ /// or that said compressed point is not actually a point on the curve.
+ InvalidPublicKeyBytes = 2,
+};
+
+/// Result code for operations adding DEs to a section builder.
+enum class AddV1DEResult : uint8_t {
+ /// The DE was successfully added to the section builder
+ /// behind the given handle.
+ Success = 0,
+ /// The handle for the section builder was invalid.
+ InvalidSectionHandle = 1,
+ /// There was no more space left in the advertisement
+ /// to fit the DE in the containing section.
+ InsufficientSectionSpace = 2,
+ /// The data element itself had invalid characteristics,
+ /// most likely a length above 127.
+ InvalidDataElement = 3,
+};
+
+/// Result code for [`V1SectionBuilder#add_to_advertisement`].
+enum class AddV1SectionToAdvertisementResult : uint8_t {
+ /// The section referenced by the given handle
+ /// couldn't be added to the containing advertisement,
+ /// possibly because the handle is invalid or the section
+ /// has already been added to the containing section.
+ Error = 0,
+ /// The section referenced by the given handle
+ /// was successfully added to the containing advertisement.
+ /// After obtaining this result code, the section
+ /// handle will no longer be valid.
+ Success = 1,
+};
+
+/// Enum common to V0 and V1 serialization expressing
+/// what kind of advertisement builder (public/encrypted)
+/// is in use.
+enum class AdvertisementBuilderKind : uint8_t {
+ /// The builder is for a public advertisement.
+ Public = 0,
+ /// The builder is for an encrypted advertisement.
+ Encrypted = 1,
+};
+
+/// Discriminant for `BuildTxPowerResult`.
+enum class BuildTxPowerResultKind : uint8_t {
+ /// The transmission power was outside the
+ /// allowed -100dBm to 20dBm range.
+ OutOfRange = 0,
+ /// The transmission power was in range,
+ /// and so a `TxPower` struct was constructed.
+ Success = 1,
};
/// Discriminant for `CreateCredentialBookResult`
@@ -61,30 +138,37 @@ enum class CreateCredentialBookResultKind : uint8_t {
/// The associated payload may be obtained via
/// `CreateCredentialBookResult#into_success()`.
Success = 0,
- /// There was no space left to create a new credential book
- NoSpaceLeft = 1,
/// The slab that we tried to create a credential-book from
/// actually was an invalid handle.
- InvalidSlabHandle = 2,
+ InvalidSlabHandle = 1,
};
-/// Discriminant for `CreateCredentialSlabResult`
-enum class CreateCredentialSlabResultKind : uint8_t {
- /// There was no space left to create a new credential slab
- NoSpaceLeft = 0,
- /// We created a new credential slab behind the given handle.
- /// The associated payload may be obtained via
- /// `CreateCredentialSlabResult#into_success()`.
- Success = 1,
+/// Discriminant for `CreateV1SectionBuilderResult`
+enum class CreateV1SectionBuilderResultKind : uint8_t {
+ /// The attempt to create a new section builder succeeded.
+ Success = 0,
+ /// We're currently in the middle of building a section.
+ UnclosedActiveSection = 1,
+ /// The advertisement builder handle was invalid.
+ InvalidAdvertisementBuilderHandle = 2,
+ /// We're attempting to build a section with an identity
+ /// kind (public/encrypted) which doesn't match the kind
+ /// for the entire advertisement.
+ IdentityKindMismatch = 3,
+ /// There isn't enough space for a new section, either
+ /// because the maximum section count has been exceeded
+ /// or because the advertisement is almost full, and
+ /// the minimum size of a section wouldn't fit.
+ NoSpaceLeft = 4,
};
/// A result-type enum which tells the caller whether/not a deallocation
/// succeeded or failed due to the requested handle not being present.
enum class DeallocateResult {
/// The requested handle to deallocate was not present in the map
- NotPresent = 0,
+ NotPresent = 1,
/// The object behind the handle was successfully deallocated
- Success = 1,
+ Success = 2,
};
/// Discriminant for `DecryptMetadataResult`.
@@ -117,21 +201,21 @@ enum class DeserializedV0AdvertisementKind : uint8_t {
/// The deserialized V0 advertisement was legible.
/// The associated payload may be obtained via
/// `DeserializedV0Advertisement#into_legible`.
- Legible = 0,
+ Legible = 1,
/// The deserialized V0 advertisement is illegible,
/// likely meaning that the receiver does not hold
/// the proper credentials to be able to read
/// the received advertisement.
- NoMatchingCredentials = 1,
+ NoMatchingCredentials = 2,
};
/// Discriminant for deserialized information about the V0
/// identity utilized by a deserialized V0 advertisement.
enum class DeserializedV0IdentityKind : uint8_t {
/// The deserialized identity was a plaintext identity.
- Plaintext = 0,
+ Plaintext = 1,
/// The deserialized identity was some decrypted identity.
- Decrypted = 1,
+ Decrypted = 2,
};
/// Discriminant for `DeserializedV1Identity`.
@@ -143,19 +227,6 @@ enum class DeserializedV1IdentityKind : uint8_t {
Decrypted = 1,
};
-/// The DE type for an encrypted identity
-enum class EncryptedIdentityType : uint8_t {
- /// Identity for broadcasts to nearby devices with the same
- /// logged-in-account (for some account).
- Private = 1,
- /// Identity for broadcasts to nearby devices which this
- /// device has declared to trust.
- Trusted = 2,
- /// Identity for broadcasts to devices which have been provisioned
- /// offline with this device.
- Provisioned = 4,
-};
-
enum class GetMetadataBufferPartsResultKind : uint8_t {
Success = 0,
Error = 1,
@@ -239,6 +310,17 @@ enum class GetV1SectionResultKind : uint8_t {
Success = 1,
};
+/// Discriminant for `NextV1DE16ByteSaltResult`.
+enum class NextV1DE16ByteSaltResultKind : uint8_t {
+ /// We couldn't return a 16-byte DE salt, possibly
+ /// because the handle to the section builder
+ /// was invalid, or possibly because the section
+ /// builder was for a public section.
+ Error = 0,
+ /// A 16-byte DE salt was returned successfully.
+ Success = 1,
+};
+
/// Structure for categorized reasons for why a NP C FFI call may
/// be panicking.
enum class PanicReason : uint8_t {
@@ -252,10 +334,57 @@ enum class PanicReason : uint8_t {
/// The panic handler is used to assert conditions are true to avoid programmer errors.
/// If a failed assert condition is hit, this panic handler is invoked with this reason.
AssertFailed = 1,
- /// Error returned if action bits inside of a V0Actions struct are invalid. If the struct was
- /// created by this deserializer, the bits will always be valid, they are only invalid if
- /// a user reaches in and changes them to something invalid.
- InvalidActionBits = 2,
+ /// Error returned if the bit representation of a supposedly-Rust-constructed
+ /// -and-validated type actually doesn't correspond to the format of the
+ /// data structure expected on the Rust side of the boundary, and performing
+ /// further operations on the structure would yield unintended behavior.
+ /// If this kind of error is being raised, the C code must
+ /// be messing with stack-allocated data structures for this library
+ /// in an entirely unexpected way.
+ InvalidStackDataStructure = 2,
+ /// The maximum amount of allocations per type is `u32::MAX`, this panic handler is invoked
+ /// with this reason when this is exceeded. Clients should never need more than 4 Billions
+ /// handles and would certainly run into other issues before reaching that point
+ ExceededMaxHandleAllocations = 3,
+};
+
+/// Discriminant for `SerializeV0AdvertisementResult`.
+enum class SerializeV0AdvertisementResultKind : uint8_t {
+ /// Serializing the advertisement to bytes was successful.
+ Success = 0,
+ /// The advertisement builder handle was invalid.
+ InvalidAdvertisementBuilderHandle = 1,
+ /// Serializing the advertisement to bytes failed
+ /// because the data in the advertisement wasn't
+ /// of an appropriate size for LDT encryption
+ /// to succeed.
+ LdtError = 2,
+ /// Serializing an unencrypted adv failed because the adv data didn't meet the length
+ /// requirements.
+ UnencryptedError = 3,
+};
+
+/// Discriminant for `SerializeV1AdvertisementResult`.
+enum class SerializeV1AdvertisementResultKind : uint8_t {
+ /// Serializing the advertisement to bytes was successful.
+ Success = 0,
+ /// The state of the advertisement builder was invalid
+ /// for the builder to be closed for serialization, likely
+ /// because there was an unclosed section builder.
+ InvalidBuilderState = 1,
+ /// The advertisement builder handle was invalid.
+ InvalidAdvertisementBuilderHandle = 2,
+};
+
+/// Discriminant for `SetV0ActionResult`.
+enum class SetV0ActionResultKind : uint8_t {
+ /// The attempt to set the action bit failed. The
+ /// action bits were yielded back to the caller,
+ /// unmodified.
+ Error = 0,
+ /// The attempt to set the action bit succeeded.
+ /// The updated action bits were yielded back to the caller.
+ Success = 1,
};
/// Discriminant for `V0DataElement`.
@@ -263,11 +392,11 @@ enum class V0DataElementKind : uint8_t {
/// A transmission Power (Tx Power) data-element.
/// The associated payload may be obtained via
/// `V0DataElement#into_tx_power`.
- TxPower = 0,
+ TxPower = 1,
/// The Actions data-element.
/// The associated payload may be obtained via
/// `V0DataElement#into_actions`.
- Actions = 1,
+ Actions = 2,
};
/// Information about the verification scheme used
@@ -280,7 +409,18 @@ enum class V1VerificationMode : uint8_t {
Signature = 1,
};
-///A `#[repr(C)]` handle to a value of type `super::CredentialBookInternals`.
+/// Holds the count of handles currently allocated for each handle type
+struct CurrentHandleAllocations {
+ uint32_t cred_book;
+ uint32_t cred_slab;
+ uint32_t decrypted_metadata;
+ uint32_t v0_payload;
+ uint32_t legible_v1_sections;
+ uint32_t v0_advertisement_builder;
+ uint32_t v1_advertisement_builder;
+};
+
+/// A `#[repr(C)]` handle to a value of type `CredentialBookInternals`
struct CredentialBook {
uint64_t handle_id;
};
@@ -289,7 +429,6 @@ struct CredentialBook {
union CreateCredentialBookResult {
enum class Tag : uint8_t {
Success = 0,
- NoSpaceLeft = 1,
InvalidSlabHandle = 2,
};
@@ -304,33 +443,16 @@ union CreateCredentialBookResult {
Success_Body success;
};
-///A `#[repr(C)]` handle to a value of type `super::CredentialSlabInternals`.
+/// A `#[repr(C)]` handle to a value of type `CredentialSlabInternals`
struct CredentialSlab {
uint64_t handle_id;
};
-/// Result type for `create_credential_slab`
-struct CreateCredentialSlabResult {
- enum class Tag {
- NoSpaceLeft,
- Success,
- };
-
- struct Success_Body {
- CredentialSlab _0;
- };
-
- Tag tag;
- union {
- Success_Body success;
- };
-};
-
/// Cryptographic information about a particular V0 discovery credential
/// necessary to match and decrypt encrypted V0 advertisements.
struct V0DiscoveryCredential {
uint8_t key_seed[32];
- uint8_t legacy_metadata_key_hmac[32];
+ uint8_t identity_token_hmac[32];
};
/// A representation of a MatchedCredential which is passable across the FFI boundary
@@ -352,8 +474,9 @@ struct V0MatchableCredential {
/// necessary to match and decrypt encrypted V1 advertisement sections.
struct V1DiscoveryCredential {
uint8_t key_seed[32];
- uint8_t expected_unsigned_metadata_key_hmac[32];
- uint8_t expected_signed_metadata_key_hmac[32];
+ uint8_t expected_mic_short_salt_identity_token_hmac[32];
+ uint8_t expected_mic_extended_salt_identity_token_hmac[32];
+ uint8_t expected_signature_identity_token_hmac[32];
uint8_t pub_key[32];
};
@@ -365,7 +488,7 @@ struct V1MatchableCredential {
FfiMatchedCredential matched_cred;
};
-///A `#[repr(C)]` handle to a value of type `super::DecryptedMetadataInternals`.
+/// A `#[repr(C)]` handle to a value of type `DecryptedMetadataInternals`
struct DecryptedMetadata {
uint64_t handle_id;
};
@@ -409,7 +532,7 @@ struct GetMetadataBufferPartsResult {
};
};
-///A `#[repr(C)]` handle to a value of type `super::V0PayloadInternals`.
+/// A `#[repr(C)]` handle to a value of type `V0PayloadInternals`
struct V0Payload {
uint64_t handle_id;
};
@@ -438,15 +561,18 @@ struct DeserializedV0Advertisement {
};
};
-///A `#[repr(C)]` handle to a value of type `super::LegibleV1SectionsInternals`.
+/// A `#[repr(C)]` handle to a value of type `LegibleV1SectionsInternals`
struct LegibleV1Sections {
uint64_t handle_id;
};
/// Representation of a deserialized V1 advertisement
struct DeserializedV1Advertisement {
+ /// The number of legible sections
uint8_t num_legible_sections;
+ /// The number of sections that were unable to be decrypted
uint8_t num_undecryptable_sections;
+ /// A handle to the set of legible (plain or decrypted) sections
LegibleV1Sections legible_sections;
};
@@ -505,7 +631,7 @@ struct TxPower {
int8_t tx_power;
};
-/// The bitfield data of a VOActions data element
+/// The bitfield data of a V0Actions data element
struct V0ActionBits {
uint32_t bitfield;
};
@@ -576,13 +702,11 @@ struct GetV0DEResult {
/// Information about the identity which matched a
/// decrypted V0 advertisement.
struct DeserializedV0IdentityDetails {
- /// The identity type (private/provisioned/trusted)
- EncryptedIdentityType identity_type;
/// The ID of the credential which
/// matched the deserialized adv
uint32_t cred_id;
- /// The 14-byte legacy metadata key
- uint8_t metadata_key[14];
+ /// The 14-byte legacy identity token
+ uint8_t identity_token[14];
/// The 2-byte advertisement salt
uint8_t salt[2];
};
@@ -691,8 +815,6 @@ struct GetV1DEResult {
/// Information about the identity which matched
/// a decrypted V1 section.
struct DeserializedV1IdentityDetails {
- /// The identity type (private/provisioned/trusted)
- EncryptedIdentityType identity_type;
/// The verification mode (MIC/Signature) which
/// was used to verify the decrypted adv contents.
V1VerificationMode verification_mode;
@@ -700,7 +822,7 @@ struct DeserializedV1IdentityDetails {
/// matched the deserialized section.
uint32_t cred_id;
/// The 16-byte metadata key.
- uint8_t metadata_key[16];
+ uint8_t identity_token[16];
};
/// The result of attempting to get the identity details
@@ -746,5 +868,184 @@ struct GetV1DE16ByteSaltResult {
};
};
+/// A `#[repr(C)]` handle to a value of type `V0AdvertisementBuilderInternals`
+struct V0AdvertisementBuilderHandle {
+ uint64_t handle_id;
+};
+
+/// A handle to a builder for V0 advertisements.
+struct V0AdvertisementBuilder {
+ AdvertisementBuilderKind kind;
+ V0AdvertisementBuilderHandle handle;
+};
+
+/// The result of attempting to serialize the contents
+/// of a V0 advertisement builder to raw bytes.
+struct SerializeV0AdvertisementResult {
+ enum class Tag {
+ Success,
+ InvalidAdvertisementBuilderHandle,
+ LdtError,
+ UnencryptedError,
+ };
+
+ struct Success_Body {
+ ByteBuffer<24> _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ };
+};
+
+/// Cryptographic information about a particular V0 broadcast credential
+/// necessary to LDT-encrypt V0 advertisements.
+struct V0BroadcastCredential {
+ uint8_t key_seed[32];
+ uint8_t identity_token[14];
+};
+
+/// A `#[repr(C)]` handle to a value of type `V1AdvertisementBuilderInternals`
+struct V1AdvertisementBuilderHandle {
+ uint64_t handle_id;
+};
+
+/// A handle to a builder for V1 advertisements.
+struct V1AdvertisementBuilder {
+ AdvertisementBuilderKind kind;
+ V1AdvertisementBuilderHandle handle;
+};
+
+/// A handle to a builder for V1 sections. This is not a unique handle; it is the same handle as
+/// the advertisement builder the section builder was originated from.
+struct V1SectionBuilder {
+ V1AdvertisementBuilder adv_builder;
+ uint8_t section_index;
+};
+
+/// The result of attempting to create a new V1 section builder.
+struct CreateV1SectionBuilderResult {
+ enum class Tag {
+ Success,
+ UnclosedActiveSection,
+ InvalidAdvertisementBuilderHandle,
+ IdentityKindMismatch,
+ NoSpaceLeft,
+ };
+
+ struct Success_Body {
+ V1SectionBuilder _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ };
+};
+
+/// Cryptographic information about a particular V1 broadcast credential
+/// necessary to encrypt V1 MIC-verified and signature-verified sections.
+struct V1BroadcastCredential {
+ uint8_t key_seed[32];
+ uint8_t identity_token[16];
+ uint8_t private_key[32];
+};
+
+/// The result of attempting to serialize the contents
+/// of a V1 advertisement builder to raw bytes.
+struct SerializeV1AdvertisementResult {
+ enum class Tag {
+ Success,
+ InvalidBuilderState,
+ InvalidAdvertisementBuilderHandle,
+ };
+
+ struct Success_Body {
+ ByteBuffer<250> _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ };
+};
+
+/// The result of attempting to get the derived V1 DE
+/// 16-byte salt for the next-added DE to the section
+/// builder behind the given handle.
+struct NextV1DE16ByteSaltResult {
+ enum class Tag {
+ Error,
+ Success,
+ };
+
+ struct Success_Body {
+ FixedSizeArray<16> _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ };
+};
+
+/// Represents the contents of a V1 DE whose payload
+/// is stored in a buffer which may contain up to 127 bytes,
+/// which is the maximum for any V1 DE.
+///
+/// This representation is stable, and so you may directly
+/// reference this struct's fields if you wish.
+struct V1DE127ByteBuffer {
+ /// The DE type code of this generic data-element.
+ uint32_t de_type;
+ /// The raw data-element byte payload, up to
+ /// 127 bytes in length.
+ ByteBuffer<127> payload;
+};
+
+/// Result type for attempting to construct a
+/// Tx Power from a signed byte.
+struct BuildTxPowerResult {
+ enum class Tag {
+ OutOfRange,
+ Success,
+ };
+
+ struct Success_Body {
+ TxPower _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ };
+};
+
+/// The result of attempting to set a particular action
+/// bit on some `V0Actions`.
+struct SetV0ActionResult {
+ enum class Tag {
+ Success,
+ Error,
+ };
+
+ struct Success_Body {
+ V0Actions _0;
+ };
+
+ struct Error_Body {
+ V0Actions _0;
+ };
+
+ Tag tag;
+ union {
+ Success_Body success;
+ Error_Body error;
+ };
+};
+
} // namespace internal
} // namespace np_ffi
+
+// clang-format on
diff --git a/nearby/presence/np_c_ffi/rust-toolchain.toml b/nearby/presence/np_c_ffi/rust-toolchain.toml
deleted file mode 100644
index 271800c..0000000
--- a/nearby/presence/np_c_ffi/rust-toolchain.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[toolchain]
-channel = "nightly" \ No newline at end of file
diff --git a/nearby/presence/np_c_ffi/src/credentials.rs b/nearby/presence/np_c_ffi/src/credentials.rs
index 3cbd76f..d03f0f6 100644
--- a/nearby/presence/np_c_ffi/src/credentials.rs
+++ b/nearby/presence/np_c_ffi/src/credentials.rs
@@ -13,13 +13,17 @@
// limitations under the License.
//! Credential-related data-types and functions
-use crate::{unwrap, PanicReason};
+use crate::{panic, unwrap, PanicReason};
use core::slice;
use np_ffi_core::common::*;
-use np_ffi_core::credentials::credential_book::CredentialBook;
-use np_ffi_core::credentials::credential_slab::CredentialSlab;
-use np_ffi_core::credentials::*;
-use np_ffi_core::deserialize::decrypted_metadata::DecryptedMetadata;
+use np_ffi_core::credentials::{
+ create_credential_book_from_slab, create_credential_slab, deallocate_credential_book,
+ deallocate_credential_slab, AddV0CredentialToSlabResult, AddV1CredentialToSlabResult,
+ CredentialBook, CredentialSlab, MatchedCredential, V0DiscoveryCredential,
+ V1DiscoveryCredential,
+};
+use np_ffi_core::declare_enum_cast;
+use np_ffi_core::deserialize::DecryptedMetadata;
use np_ffi_core::deserialize::{
DecryptMetadataResult, DecryptMetadataResultKind, GetMetadataBufferPartsResult,
GetMetadataBufferPartsResultKind, MetadataBufferParts,
@@ -32,7 +36,61 @@ use np_ffi_core::utils::FfiEnum;
pub extern "C" fn np_ffi_create_credential_book_from_slab(
slab: CredentialSlab,
) -> CreateCredentialBookResult {
- create_credential_book_from_slab(slab)
+ create_credential_book_from_slab(slab).into()
+}
+
+/// Result type for `create_credential_book`
+#[repr(u8)]
+#[allow(missing_docs)]
+pub enum CreateCredentialBookResult {
+ Success(CredentialBook) = 0,
+ InvalidSlabHandle = 2,
+}
+
+//TODO: unwrap allocation errors at the ffi-core layer and remove this, after design has been
+// agreed upon
+impl From<np_ffi_core::credentials::CreateCredentialBookResult> for CreateCredentialBookResult {
+ fn from(value: np_ffi_core::credentials::CreateCredentialBookResult) -> Self {
+ match value {
+ np_ffi_core::credentials::CreateCredentialBookResult::Success(v) => {
+ CreateCredentialBookResult::Success(v)
+ }
+ np_ffi_core::credentials::CreateCredentialBookResult::InvalidSlabHandle => {
+ CreateCredentialBookResult::InvalidSlabHandle
+ }
+ np_ffi_core::credentials::CreateCredentialBookResult::NoSpaceLeft => {
+ panic(PanicReason::ExceededMaxHandleAllocations)
+ }
+ }
+ }
+}
+
+/// Discriminant for `CreateCredentialBookResult`
+#[repr(u8)]
+pub enum CreateCredentialBookResultKind {
+ /// We created a new credential book behind the given handle.
+ /// The associated payload may be obtained via
+ /// `CreateCredentialBookResult#into_success()`.
+ Success = 0,
+ /// The slab that we tried to create a credential-book from
+ /// actually was an invalid handle.
+ InvalidSlabHandle = 1,
+}
+
+impl np_ffi_core::utils::FfiEnum for CreateCredentialBookResult {
+ type Kind = CreateCredentialBookResultKind;
+ fn kind(&self) -> Self::Kind {
+ match self {
+ CreateCredentialBookResult::Success(_) => CreateCredentialBookResultKind::Success,
+ CreateCredentialBookResult::InvalidSlabHandle => {
+ CreateCredentialBookResultKind::InvalidSlabHandle
+ }
+ }
+ }
+}
+
+impl CreateCredentialBookResult {
+ declare_enum_cast! {into_success, Success, CredentialBook}
}
/// Gets the tag of a `CreateCredentialBookResult` tagged enum.
@@ -70,25 +128,8 @@ pub extern "C" fn np_ffi_deallocate_credential_book(
/// Allocates a new credential-slab, returning a handle to the created object
#[no_mangle]
-pub extern "C" fn np_ffi_create_credential_slab() -> CreateCredentialSlabResult {
- create_credential_slab()
-}
-
-/// Gets the tag of a `CreateCredentialSlabResult` tagged enum.
-#[no_mangle]
-pub extern "C" fn np_ffi_CreateCredentialSlabResult_kind(
- result: CreateCredentialSlabResult,
-) -> CreateCredentialSlabResultKind {
- result.kind()
-}
-
-/// Casts a `CreateCredentialSlabResult` to the `SUCCESS` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-#[no_mangle]
-pub extern "C" fn np_ffi_CreateCredentialSlabResult_into_SUCCESS(
- result: CreateCredentialSlabResult,
-) -> CredentialSlab {
- unwrap(result.into_success(), PanicReason::EnumCastFailed)
+pub extern "C" fn np_ffi_create_credential_slab() -> CredentialSlab {
+ unwrap(create_credential_slab().into_success(), PanicReason::ExceededMaxHandleAllocations)
}
/// Representation of a V0 credential that contains additional data to provide back to caller once it
@@ -127,7 +168,7 @@ pub struct FfiMatchedCredential {
pub extern "C" fn np_ffi_CredentialSlab_add_v0_credential(
credential_slab: CredentialSlab,
v0_cred: V0MatchableCredential,
-) -> AddCredentialToSlabResult {
+) -> AddV0CredentialToSlabResult {
#[allow(unsafe_code)]
let metadata_slice = unsafe {
slice::from_raw_parts(
@@ -150,7 +191,7 @@ pub extern "C" fn np_ffi_CredentialSlab_add_v0_credential(
pub extern "C" fn np_ffi_CredentialSlab_add_v1_credential(
credential_slab: CredentialSlab,
v1_cred: V1MatchableCredential,
-) -> AddCredentialToSlabResult {
+) -> AddV1CredentialToSlabResult {
#[allow(unsafe_code)]
let metadata_slice = unsafe {
slice::from_raw_parts(
diff --git a/nearby/presence/np_c_ffi/src/deserialize/mod.rs b/nearby/presence/np_c_ffi/src/deserialize/mod.rs
index 9f2cea8..3faf414 100644
--- a/nearby/presence/np_c_ffi/src/deserialize/mod.rs
+++ b/nearby/presence/np_c_ffi/src/deserialize/mod.rs
@@ -14,7 +14,7 @@
use crate::{unwrap, PanicReason};
use np_ffi_core::common::*;
-use np_ffi_core::credentials::credential_book::CredentialBook;
+use np_ffi_core::credentials::CredentialBook;
use np_ffi_core::deserialize::v0::*;
use np_ffi_core::deserialize::v1::*;
use np_ffi_core::deserialize::*;
diff --git a/nearby/presence/np_c_ffi/src/deserialize/v0.rs b/nearby/presence/np_c_ffi/src/deserialize/v0.rs
index 7a460a2..243f3ff 100644
--- a/nearby/presence/np_c_ffi/src/deserialize/v0.rs
+++ b/nearby/presence/np_c_ffi/src/deserialize/v0.rs
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::{panic, unwrap, PanicReason};
+use crate::{unwrap, PanicReason};
use np_ffi_core::common::DeallocateResult;
-use np_ffi_core::deserialize::v0::v0_payload::V0Payload;
use np_ffi_core::deserialize::v0::*;
use np_ffi_core::deserialize::DecryptMetadataResult;
use np_ffi_core::utils::FfiEnum;
+use np_ffi_core::v0::*;
/// Gets the tag of a `DeserializedV0Advertisement` tagged-union.
#[no_mangle]
@@ -126,50 +126,3 @@ pub extern "C" fn np_ffi_GetV0DEResult_kind(result: GetV0DEResult) -> GetV0DERes
pub extern "C" fn np_ffi_GetV0DEResult_into_SUCCESS(result: GetV0DEResult) -> V0DataElement {
unwrap(result.into_success(), PanicReason::EnumCastFailed)
}
-
-/// Gets the tag of a `V0DataElement` tagged-union.
-#[no_mangle]
-pub extern "C" fn np_ffi_V0DataElement_kind(de: V0DataElement) -> V0DataElementKind {
- de.kind()
-}
-
-/// Casts a `V0DataElement` to the `TxPower` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-#[no_mangle]
-pub extern "C" fn np_ffi_V0DataElement_into_TX_POWER(de: V0DataElement) -> TxPower {
- unwrap(de.into_tx_power(), PanicReason::EnumCastFailed)
-}
-
-/// Casts a `V0DataElement` to the `Actions` variant, panicking in the
-/// case where the passed value is of a different enum variant.
-#[no_mangle]
-pub extern "C" fn np_ffi_V0DataElement_into_ACTIONS(de: V0DataElement) -> V0Actions {
- unwrap(de.into_actions(), PanicReason::EnumCastFailed)
-}
-
-/// Return whether a boolean action type is set in this data element
-#[no_mangle]
-pub extern "C" fn np_ffi_V0Actions_has_action(
- actions: V0Actions,
- action_type: BooleanActionType,
-) -> bool {
- match actions.has_action(&action_type) {
- Ok(b) => b,
- Err(_) => panic(PanicReason::InvalidActionBits),
- }
-}
-
-/// Gets the 4 bit context sync sequence number as a u8 from this data element
-#[no_mangle]
-pub extern "C" fn np_ffi_V0Actions_get_context_sync_sequence_number(actions: V0Actions) -> u8 {
- match actions.get_context_sync_seq_num() {
- Ok(b) => b,
- Err(_) => panic(PanicReason::InvalidActionBits),
- }
-}
-
-/// Return whether a boolean action type is set in this data element
-#[no_mangle]
-pub extern "C" fn np_ffi_V0Actions_as_u32(actions: V0Actions) -> u32 {
- actions.as_u32()
-}
diff --git a/nearby/presence/np_c_ffi/src/deserialize/v1.rs b/nearby/presence/np_c_ffi/src/deserialize/v1.rs
index 598ce9c..68c0cc2 100644
--- a/nearby/presence/np_c_ffi/src/deserialize/v1.rs
+++ b/nearby/presence/np_c_ffi/src/deserialize/v1.rs
@@ -164,17 +164,3 @@ pub extern "C" fn np_ffi_GetV1DEResult_kind(result: GetV1DEResult) -> GetV1DERes
pub extern "C" fn np_ffi_GetV1DEResult_into_SUCCESS(result: GetV1DEResult) -> V1DataElement {
unwrap(result.into_success(), PanicReason::EnumCastFailed)
}
-
-/// Converts a `V1DataElement` to a `GenericV1DataElement` which
-/// only maintains information about the DE's type-code and payload.
-#[no_mangle]
-pub extern "C" fn np_ffi_V1DataElement_to_generic(de: V1DataElement) -> GenericV1DataElement {
- de.to_generic()
-}
-
-/// Extracts the numerical value of the given V1 DE type code as
-/// an unsigned 32-bit integer.
-#[no_mangle]
-pub extern "C" fn np_ffi_V1DEType_to_uint32_t(de_type: V1DEType) -> u32 {
- de_type.to_u32()
-}
diff --git a/nearby/presence/np_c_ffi/src/lib.rs b/nearby/presence/np_c_ffi/src/lib.rs
index 50e74b6..5111aff 100644
--- a/nearby/presence/np_c_ffi/src/lib.rs
+++ b/nearby/presence/np_c_ffi/src/lib.rs
@@ -16,9 +16,13 @@
pub mod credentials;
pub mod deserialize;
+pub mod serialize;
+pub mod v0;
+pub mod v1;
-use lock_adapter::std::RwLock;
+use lock_adapter::stdlib::RwLock;
use lock_adapter::RwLock as _;
+use np_ffi_core::common::{CurrentHandleAllocations, InvalidStackDataStructure};
/// Structure for categorized reasons for why a NP C FFI call may
/// be panicking.
@@ -35,10 +39,18 @@ pub enum PanicReason {
/// The panic handler is used to assert conditions are true to avoid programmer errors.
/// If a failed assert condition is hit, this panic handler is invoked with this reason.
AssertFailed = 1,
- /// Error returned if action bits inside of a V0Actions struct are invalid. If the struct was
- /// created by this deserializer, the bits will always be valid, they are only invalid if
- /// a user reaches in and changes them to something invalid.
- InvalidActionBits = 2,
+ /// Error returned if the bit representation of a supposedly-Rust-constructed
+ /// -and-validated type actually doesn't correspond to the format of the
+ /// data structure expected on the Rust side of the boundary, and performing
+ /// further operations on the structure would yield unintended behavior.
+ /// If this kind of error is being raised, the C code must
+ /// be messing with stack-allocated data structures for this library
+ /// in an entirely unexpected way.
+ InvalidStackDataStructure = 2,
+ /// The maximum amount of allocations per type is `u32::MAX`, this panic handler is invoked
+ /// with this reason when this is exceeded. Clients should never need more than 4 Billions
+ /// handles and would certainly run into other issues before reaching that point
+ ExceededMaxHandleAllocations = 3,
}
/// Structure which maintains information about the panic-handler
@@ -93,6 +105,13 @@ pub(crate) fn panic(reason: PanicReason) -> ! {
PANIC_HANDLER.read().panic(reason)
}
+pub(crate) fn panic_if_invalid<T>(value: Result<T, InvalidStackDataStructure>) -> T {
+ match value {
+ Ok(x) => x,
+ Err(_) => panic(PanicReason::InvalidStackDataStructure),
+ }
+}
+
pub(crate) fn unwrap<T>(value: Option<T>, panic_reason: PanicReason) -> T {
match value {
Some(x) => x,
@@ -126,6 +145,13 @@ pub extern "C" fn np_ffi_global_config_panic_handler(
panic_handler.set_handler(handler)
}
+/// Checks the current count of all outstanding handle allocations, useful for debugging,
+/// logging, and testing
+#[no_mangle]
+pub extern "C" fn np_ffi_global_config_get_current_allocation_count() -> CurrentHandleAllocations {
+ np_ffi_core::common::global_config_get_current_allocation_count()
+}
+
/// Sets an override to the number of shards to employ in the NP FFI's
/// internal handle-maps, which places an upper bound on the number
/// of writing threads which may make progress at any one time
@@ -144,81 +170,3 @@ pub extern "C" fn np_ffi_global_config_panic_handler(
pub extern "C" fn np_ffi_global_config_set_num_shards(num_shards: u8) {
np_ffi_core::common::global_config_set_num_shards(num_shards)
}
-
-/// Sets the maximum number of active handles to credential slabs
-/// which may be active at any one time.
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on credential slabs in constrained-memory environments.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential slabs.
-#[no_mangle]
-pub extern "C" fn np_ffi_global_config_set_max_num_credential_slabs(max_num_credential_slabs: u32) {
- np_ffi_core::common::global_config_set_max_num_credential_slabs(max_num_credential_slabs)
-}
-
-/// Sets the maximum number of active handles to credential books
-/// which may be active at any one time.
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on credential books in constrained-memory environments.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential books.
-#[no_mangle]
-pub extern "C" fn np_ffi_global_config_set_max_num_credential_books(max_num_credential_books: u32) {
- np_ffi_core::common::global_config_set_max_num_credential_books(max_num_credential_books)
-}
-
-/// Sets the maximum number of active handles to deserialized v0
-/// advertisements which may be active at any one time.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on v0 advertisements in constrained-memory environments.
-///
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V0 advertisement.
-#[no_mangle]
-pub extern "C" fn np_ffi_global_config_set_max_num_deserialized_v0_advertisements(
- max_num_deserialized_v0_advertisements: u32,
-) {
- np_ffi_core::common::global_config_set_max_num_deserialized_v0_advertisements(
- max_num_deserialized_v0_advertisements,
- )
-}
-
-/// Sets the maximum number of active handles to deserialized v1
-/// advertisements which may be active at any one time.
-///
-/// Useful for bounding the maximum memory used by the client application
-/// on v1 advertisements in constrained-memory environments.
-///
-/// Default value: Max value.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V1 advertisement.
-#[no_mangle]
-pub extern "C" fn np_ffi_global_config_set_max_num_deserialized_v1_advertisements(
- max_num_deserialized_v1_advertisements: u32,
-) {
- np_ffi_core::common::global_config_set_max_num_deserialized_v1_advertisements(
- max_num_deserialized_v1_advertisements,
- )
-}
diff --git a/nearby/presence/np_c_ffi/src/serialize/mod.rs b/nearby/presence/np_c_ffi/src/serialize/mod.rs
new file mode 100644
index 0000000..da5690a
--- /dev/null
+++ b/nearby/presence/np_c_ffi/src/serialize/mod.rs
@@ -0,0 +1,16 @@
+// 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.
+
+mod v0;
+mod v1;
diff --git a/nearby/presence/np_c_ffi/src/serialize/v0.rs b/nearby/presence/np_c_ffi/src/serialize/v0.rs
new file mode 100644
index 0000000..867c33b
--- /dev/null
+++ b/nearby/presence/np_c_ffi/src/serialize/v0.rs
@@ -0,0 +1,94 @@
+// 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.
+
+//! NP Rust C FFI functionality for V0 advertisement serialization.
+
+use crate::{panic_if_invalid, unwrap, PanicReason};
+use np_ffi_core::common::{ByteBuffer, DeallocateResult, FixedSizeArray};
+use np_ffi_core::credentials::V0BroadcastCredential;
+use np_ffi_core::serialize::v0::*;
+use np_ffi_core::utils::FfiEnum;
+use np_ffi_core::v0::V0DataElement;
+
+/// Attempts to add the given data element to the V0
+/// advertisement builder behind the passed handle.
+///
+/// This method may invoke the panic handler if the passed DE
+/// has an invalid layout, which may indicate that the backing
+/// data on the stack was somehow tampered with in an unintended way.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0AdvertisementBuilder_add_de(
+ adv_builder: V0AdvertisementBuilder,
+ de: V0DataElement,
+) -> AddV0DEResult {
+ panic_if_invalid(adv_builder.add_de(de))
+}
+
+/// Attempts to serialize the contents of the advertisement builder
+/// behind this handle to bytes. Assuming that the handle is valid,
+/// this operation will always result in the contents behind the
+/// advertisement builder handle being deallocated.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0AdvertisementBuilder_into_advertisement(
+ adv_builder: V0AdvertisementBuilder,
+) -> SerializeV0AdvertisementResult {
+ adv_builder.into_advertisement()
+}
+
+/// Attempts to deallocate the v0 advertisement builder behind
+/// the given handle.
+#[no_mangle]
+pub extern "C" fn np_ffi_deallocate_v0_advertisement_builder(
+ adv_builder: V0AdvertisementBuilder,
+) -> DeallocateResult {
+ adv_builder.deallocate()
+}
+
+/// Creates a new V0 advertisement builder for a public advertisement.
+#[no_mangle]
+pub extern "C" fn np_ffi_create_v0_public_advertisement_builder() -> V0AdvertisementBuilder {
+ unwrap(
+ create_v0_public_advertisement_builder().into_success(),
+ PanicReason::ExceededMaxHandleAllocations,
+ )
+}
+
+/// Creates a new V0 advertisement builder for an encrypted advertisement.
+#[no_mangle]
+pub extern "C" fn np_ffi_create_v0_encrypted_advertisement_builder(
+ broadcast_cred: V0BroadcastCredential,
+ salt: FixedSizeArray<2>,
+) -> V0AdvertisementBuilder {
+ unwrap(
+ create_v0_encrypted_advertisement_builder(broadcast_cred, salt).into_success(),
+ PanicReason::ExceededMaxHandleAllocations,
+ )
+}
+
+/// Gets the tag of a `SerializeV0AdvertisementResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_SerializeV0AdvertisementResult_kind(
+ result: SerializeV0AdvertisementResult,
+) -> SerializeV0AdvertisementResultKind {
+ result.kind()
+}
+
+/// Casts a `SerializeV0AdvertisementResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_SerializeV0AdvertisementResult_into_SUCCESS(
+ result: SerializeV0AdvertisementResult,
+) -> ByteBuffer<24> {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
diff --git a/nearby/presence/np_c_ffi/src/serialize/v1.rs b/nearby/presence/np_c_ffi/src/serialize/v1.rs
new file mode 100644
index 0000000..484425b
--- /dev/null
+++ b/nearby/presence/np_c_ffi/src/serialize/v1.rs
@@ -0,0 +1,168 @@
+// 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.
+
+//! NP Rust C FFI functionality for V1 advertisement serialization.
+
+use crate::{unwrap, PanicReason};
+use np_ffi_core::common::{ByteBuffer, FixedSizeArray};
+use np_ffi_core::credentials::V1BroadcastCredential;
+use np_ffi_core::serialize::v1::*;
+use np_ffi_core::serialize::AdvertisementBuilderKind;
+use np_ffi_core::utils::FfiEnum;
+use np_ffi_core::v1::V1VerificationMode;
+
+/// Attempts to create a builder for a new public section within
+/// the advertisement builder behind this handle,
+/// returning a handle to the newly-created section builder if successful.
+///
+/// This method may fail if there is another currently-active
+/// section builder for the same advertisement builder, if the
+/// kind of section being added does not match the advertisement
+/// type (public/encrypted), or if the section would not manage
+/// to fit within the enclosing advertisement.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1AdvertisementBuilder_public_section_builder(
+ adv_builder: V1AdvertisementBuilder,
+) -> CreateV1SectionBuilderResult {
+ adv_builder.public_section_builder()
+}
+
+/// Attempts to create a builder for a new encrypted section within
+/// the advertisement builder behind the given handle,
+/// returning a handle to the newly-created section builder if successful.
+///
+/// The identity details for the new section builder may be specified
+/// via providing the broadcast credential data, the kind of encrypted
+/// identity being broadcast (private/trusted/provisioned), and the
+/// verification mode (MIC/Signature) to be used for the encrypted section.
+///
+/// This method may fail if there is another currently-active
+/// section builder for the same advertisement builder, if the
+/// kind of section being added does not match the advertisement
+/// type (public/encrypted), or if the section would not manage
+/// to fit within the enclosing advertisement.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1AdvertisementBuilder_encrypted_section_builder(
+ adv_builder: V1AdvertisementBuilder,
+ broadcast_cred: V1BroadcastCredential,
+ verification_mode: V1VerificationMode,
+) -> CreateV1SectionBuilderResult {
+ adv_builder.encrypted_section_builder(broadcast_cred, verification_mode)
+}
+
+/// Attempts to serialize the contents of the advertisement builder
+/// behind this handle to bytes. Assuming that the handle is valid,
+/// this operation will always result in the contents behind the
+/// advertisement builder handle being deallocated.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1AdvertisementBuilder_into_advertisement(
+ adv_builder: V1AdvertisementBuilder,
+) -> SerializeV1AdvertisementResult {
+ adv_builder.into_advertisement()
+}
+
+/// Creates a new V1 advertisement builder for the given advertisement
+/// kind (public/encrypted).
+#[no_mangle]
+pub extern "C" fn np_ffi_create_v1_advertisement_builder(
+ kind: AdvertisementBuilderKind,
+) -> V1AdvertisementBuilder {
+ unwrap(
+ create_v1_advertisement_builder(kind).into_success(),
+ PanicReason::ExceededMaxHandleAllocations,
+ )
+}
+
+/// Gets the tag of a `SerializeV1AdvertisementResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_SerializeV1AdvertisementResult_kind(
+ result: SerializeV1AdvertisementResult,
+) -> SerializeV1AdvertisementResultKind {
+ result.kind()
+}
+
+/// Casts a `SerializeV1AdvertisementResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_SerializeV1AdvertisementResult_into_SUCCESS(
+ result: SerializeV1AdvertisementResult,
+) -> ByteBuffer<250> {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
+
+/// Gets the tag of a `CreateV1SectionBuilderResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_CreateV1SectionBuilderResult_kind(
+ result: CreateV1SectionBuilderResult,
+) -> CreateV1SectionBuilderResultKind {
+ result.kind()
+}
+
+/// Casts a `CreateV1SectionBuilderResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_CreateV1SectionBuilderResult_into_SUCCESS(
+ result: CreateV1SectionBuilderResult,
+) -> V1SectionBuilder {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
+
+/// Gets the tag of a `NextV1DE16ByteSaltResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_NextV1DE16ByteSaltResult_kind(
+ result: NextV1DE16ByteSaltResult,
+) -> NextV1DE16ByteSaltResultKind {
+ result.kind()
+}
+
+/// Casts a `NextV1DE16ByteSaltResult` to the `Success` variant,
+/// panicking in the case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_NextV1DE16ByteSaltResult_into_SUCCESS(
+ result: NextV1DE16ByteSaltResult,
+) -> FixedSizeArray<16> {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
+
+/// Adds the section constructed behind the given handle to
+/// a section builder to the containing advertisement it originated from.
+/// After this call, the section builder handle will become invalid.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1SectionBuilder_add_to_advertisement(
+ section_builder: V1SectionBuilder,
+) -> AddV1SectionToAdvertisementResult {
+ section_builder.add_to_advertisement()
+}
+
+/// Attempts to get the derived 16-byte V1 DE salt for the next
+/// DE to be added to the passed section builder. May fail if this
+/// section builder handle is invalid, or if the section
+/// is a public section.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1SectionBuilder_next_de_salt(
+ section_builder: V1SectionBuilder,
+) -> NextV1DE16ByteSaltResult {
+ section_builder.next_de_salt()
+}
+
+/// Attempts to add the given DE to the section builder behind
+/// this handle. The passed DE may have a payload of up to 127
+/// bytes, the maximum for a V1 DE.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1SectionBuilder_add_127_byte_buffer_de(
+ section_builder: V1SectionBuilder,
+ de: V1DE127ByteBuffer,
+) -> AddV1DEResult {
+ section_builder.add_127_byte_buffer_de(de)
+}
diff --git a/nearby/presence/np_c_ffi/src/v0.rs b/nearby/presence/np_c_ffi/src/v0.rs
new file mode 100644
index 0000000..7bcb980
--- /dev/null
+++ b/nearby/presence/np_c_ffi/src/v0.rs
@@ -0,0 +1,140 @@
+// 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.
+
+//! NP Rust C FFI functionality common to V0 ser/deser flows.
+
+use crate::{panic, panic_if_invalid, unwrap, PanicReason};
+use np_ffi_core::serialize::AdvertisementBuilderKind;
+use np_ffi_core::utils::FfiEnum;
+use np_ffi_core::v0::*;
+
+/// Gets the tag of a `V0DataElement` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0DataElement_kind(de: V0DataElement) -> V0DataElementKind {
+ de.kind()
+}
+
+/// Casts a `V0DataElement` to the `TxPower` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0DataElement_into_TX_POWER(de: V0DataElement) -> TxPower {
+ unwrap(de.into_tx_power(), PanicReason::EnumCastFailed)
+}
+
+/// Upcasts a Tx power DE to a generic V0 data-element.
+#[no_mangle]
+pub extern "C" fn np_ffi_TxPower_into_V0DataElement(tx_power: TxPower) -> V0DataElement {
+ V0DataElement::TxPower(tx_power)
+}
+
+/// Casts a `V0DataElement` to the `Actions` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0DataElement_into_ACTIONS(de: V0DataElement) -> V0Actions {
+ unwrap(de.into_actions(), PanicReason::EnumCastFailed)
+}
+
+/// Upcasts a V0 actions DE to a generic V0 data-element.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0Actions_into_V0DataElement(actions: V0Actions) -> V0DataElement {
+ V0DataElement::Actions(actions)
+}
+
+/// Gets the tag of a `BuildTxPowerResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_BuildTxPowerResult_kind(
+ result: BuildTxPowerResult,
+) -> BuildTxPowerResultKind {
+ result.kind()
+}
+
+/// Casts a `BuildTxPowerResult` to the `Success` variant, panicking in the
+/// case where the passed value is of a different enum variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_BuildTxPowerResult_into_SUCCESS(result: BuildTxPowerResult) -> TxPower {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
+
+/// Attempts to construct a new TxPower from
+/// the given signed-byte value.
+#[no_mangle]
+pub extern "C" fn np_ffi_TxPower_build_from_signed_byte(tx_power: i8) -> BuildTxPowerResult {
+ TxPower::build_from_signed_byte(tx_power)
+}
+
+/// Gets the value of the given TxPower as a signed byte.
+#[no_mangle]
+pub extern "C" fn np_ffi_TxPower_as_signed_byte(tx_power: TxPower) -> i8 {
+ tx_power.as_i8()
+}
+
+/// Gets the discriminant of the `SetV0ActionResult` tagged-union.
+#[no_mangle]
+pub extern "C" fn np_ffi_SetV0ActionResult_kind(
+ result: SetV0ActionResult,
+) -> SetV0ActionResultKind {
+ result.kind()
+}
+
+/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Success` variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_SetV0ActionResult_into_SUCCESS(result: SetV0ActionResult) -> V0Actions {
+ unwrap(result.into_success(), PanicReason::EnumCastFailed)
+}
+
+/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Error` variant.
+#[no_mangle]
+pub extern "C" fn np_ffi_SetV0ActionResult_into_ERROR(result: SetV0ActionResult) -> V0Actions {
+ unwrap(result.into_error(), PanicReason::EnumCastFailed)
+}
+
+/// Constructs a new V0 actions DE with no declared boolean
+/// actions and a zeroed context sync sequence number,
+/// where the DE is intended for the given advertisement
+/// kind (plaintext/encrypted).
+#[no_mangle]
+pub extern "C" fn np_ffi_build_new_zeroed_V0Actions(kind: AdvertisementBuilderKind) -> V0Actions {
+ V0Actions::new_zeroed(kind)
+}
+
+/// Return whether a boolean action type is set in this data element
+#[no_mangle]
+pub extern "C" fn np_ffi_V0Actions_has_action(actions: V0Actions, action_type: ActionType) -> bool {
+ match actions.has_action(action_type) {
+ Ok(b) => b,
+ Err(_) => panic(PanicReason::InvalidStackDataStructure),
+ }
+}
+
+/// Attempts to set the given action bit to the given boolean value.
+/// This operation may fail if the requested action bit may not be
+/// set for the kind of containing advertisement (public/encrypted)
+/// that this action DE is intended to belong to. In this case,
+/// the original action bits will be yielded back to the caller,
+/// unaltered.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0Actions_set_action(
+ actions: V0Actions,
+ action_type: ActionType,
+ value: bool,
+) -> SetV0ActionResult {
+ panic_if_invalid(actions.set_action(action_type, value))
+}
+
+/// Returns the representation of the passed `V0Actions` as an unsigned
+/// integer, where the bit-positions correspond to individual actions.
+#[no_mangle]
+pub extern "C" fn np_ffi_V0Actions_as_u32(actions: V0Actions) -> u32 {
+ actions.as_u32()
+}
diff --git a/nearby/presence/np_c_ffi/src/v1.rs b/nearby/presence/np_c_ffi/src/v1.rs
new file mode 100644
index 0000000..87a168e
--- /dev/null
+++ b/nearby/presence/np_c_ffi/src/v1.rs
@@ -0,0 +1,31 @@
+// 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.
+
+//! NP Rust C FFI functionality common to V1 ser/deser flows.
+
+use np_ffi_core::deserialize::v1::*;
+
+/// Converts a `V1DataElement` to a `GenericV1DataElement` which
+/// only maintains information about the DE's type-code and payload.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1DataElement_to_generic(de: V1DataElement) -> GenericV1DataElement {
+ de.to_generic()
+}
+
+/// Extracts the numerical value of the given V1 DE type code as
+/// an unsigned 32-bit integer.
+#[no_mangle]
+pub extern "C" fn np_ffi_V1DEType_to_uint32_t(de_type: V1DEType) -> u32 {
+ de_type.to_u32()
+}
diff --git a/nearby/presence/np_cpp_ffi/CMakeLists.txt b/nearby/presence/np_cpp_ffi/CMakeLists.txt
index 27c9132..7071bbd 100644
--- a/nearby/presence/np_cpp_ffi/CMakeLists.txt
+++ b/nearby/presence/np_cpp_ffi/CMakeLists.txt
@@ -12,14 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# include ABSL third_party dir which will add it to the cmake build tree
-set(ABSL_PROPAGATE_CXX_STD ON)
-add_subdirectory(${THIRD_PARTY_DIR}/abseil-cpp ${THIRD_PARTY_DIR}/abseil-cpp/build)
-
add_library(nearby_protocol nearby_protocol.cc)
target_link_libraries(nearby_protocol
- "${CMAKE_SOURCE_DIR}/np_c_ffi/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}np_c_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ "${NEARBY_ROOT}/target/release/${CMAKE_STATIC_LIBRARY_PREFIX}np_c_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}"
absl::statusor)
target_include_directories(nearby_protocol PUBLIC
@@ -38,11 +34,12 @@ target_include_directories(shared_test_util PRIVATE include/)
target_link_libraries(shared_test_util nearby_protocol absl::statusor)
if (ENABLE_TESTS)
- message(STATUS "Enabling np_cpp tests")
+ message(STATUS "Enabling np_ffi tests")
add_subdirectory(tests)
add_subdirectory(benchmarks)
endif ()
if (ENABLE_FUZZ)
+ message(STATUS "Enabling np_ffi fuzzers")
add_subdirectory(fuzz)
endif ()
diff --git a/nearby/presence/np_cpp_ffi/benchmarks/CMakeLists.txt b/nearby/presence/np_cpp_ffi/benchmarks/CMakeLists.txt
index c7d8343..c3c059a 100644
--- a/nearby/presence/np_cpp_ffi/benchmarks/CMakeLists.txt
+++ b/nearby/presence/np_cpp_ffi/benchmarks/CMakeLists.txt
@@ -12,11 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-add_executable(np_ffi_bench np_ffi_bench.cc)
+add_executable(
+ np_ffi_bench
+ np_cpp_benches.cc
+ np_c_ffi_benches.cc)
target_link_libraries(
np_ffi_bench
nearby_protocol
+ shared_test_util
benchmark::benchmark)
if (UNIX)
diff --git a/nearby/presence/np_cpp_ffi/benchmarks/np_c_ffi_benches.cc b/nearby/presence/np_cpp_ffi/benchmarks/np_c_ffi_benches.cc
new file mode 100644
index 0000000..1822741
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/benchmarks/np_c_ffi_benches.cc
@@ -0,0 +1,58 @@
+// 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.
+
+// Benchmarks measuring the performance of the pure autogenerated C API.
+// This is useful to compare with the C++ benchmarks to understand the overhead
+// incurred by going through the C++ wrapper types instead of directly calling
+// the C API.
+
+#include "benchmark/benchmark.h"
+#include "np_cpp_ffi_functions.h"
+#include "np_cpp_ffi_types.h"
+#include "shared_test_util.h"
+
+void V0PlaintextCApi(benchmark::State &state) {
+ auto num_ciphers = state.range(0);
+ auto slab = np_ffi::internal::np_ffi_create_credential_slab();
+ auto book_result =
+ np_ffi::internal::np_ffi_create_credential_book_from_slab(slab);
+ assert(
+ np_ffi::internal::np_ffi_CreateCredentialBookResult_kind(book_result) ==
+ np_ffi::internal::CreateCredentialBookResultKind::Success);
+ auto book = np_ffi::internal::np_ffi_CreateCredentialBookResult_into_SUCCESS(
+ book_result);
+
+ for ([[maybe_unused]] auto _ : state) {
+ for (int i = 0; i < num_ciphers; i++) {
+ auto result = np_ffi::internal::np_ffi_deserialize_advertisement(
+ {V0AdvMultiDeInternals}, book);
+ assert(np_ffi::internal::np_ffi_DeserializeAdvertisementResult_kind(
+ result) ==
+ np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ [[maybe_unused]] auto deallocate_result =
+ np_ffi::internal::np_ffi_deallocate_deserialize_advertisement_result(
+ result);
+ assert(deallocate_result == np_ffi::internal::DeallocateResult::Success);
+ }
+ }
+
+ [[maybe_unused]] auto deallocate_result =
+ np_ffi::internal::np_ffi_deallocate_credential_book(book);
+ assert(deallocate_result == np_ffi::internal::DeallocateResult::Success);
+}
+
+BENCHMARK(V0PlaintextCApi)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
diff --git a/nearby/presence/np_cpp_ffi/benchmarks/np_cpp_benches.cc b/nearby/presence/np_cpp_ffi/benchmarks/np_cpp_benches.cc
new file mode 100644
index 0000000..392d679
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/benchmarks/np_cpp_benches.cc
@@ -0,0 +1,216 @@
+// 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 "nearby_protocol.h"
+#include "shared_test_util.h"
+
+// needed for running directly against the C API (ie: bypassing the C++ wrapper)
+#include "benchmark/benchmark.h"
+#include "np_cpp_ffi_functions.h"
+#include "np_cpp_ffi_types.h"
+
+nearby_protocol::CredentialBook CreateEmptyCredBook() {
+ nearby_protocol::CredentialSlab cred_slab;
+ nearby_protocol::CredentialBook cred_book(cred_slab);
+ return std::move(cred_book);
+}
+
+void V0Plaintext(benchmark::State &state) {
+ auto cred_book = CreateEmptyCredBook();
+ auto num_advs = state.range(0);
+ for ([[maybe_unused]] auto _ : state) {
+ for (int i = 0; i < num_advs; i++) {
+ auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvPlaintextMultiDe, cred_book);
+ assert(result.GetKind() ==
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
+ }
+ }
+}
+BENCHMARK(V0Plaintext)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
+
+void V1Plaintext(benchmark::State &state) {
+ auto cred_book = CreateEmptyCredBook();
+ auto num_advs = state.range(0);
+ for ([[maybe_unused]] auto _ : state) {
+ for (int i = 0; i < num_advs; i++) {
+ auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V1AdvPlaintext, cred_book);
+ assert(result.GetKind() ==
+ nearby_protocol::DeserializeAdvertisementResultKind::V1);
+ }
+ }
+}
+BENCHMARK(V1Plaintext)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
+
+class V0Encrypted : public benchmark::Fixture {
+ public:
+ std::optional<nearby_protocol::CredentialBook> cred_book_;
+ void SetUp(const ::benchmark::State &state) override {
+ // populate credential book
+ auto num_creds = state.range(0);
+
+ nearby_protocol::CredentialSlab slab;
+ for (int i = 1; i < num_creds; i++) {
+ auto credential = GenerateRandomCredentialV0();
+ slab.AddV0Credential(credential);
+ }
+
+ // now at the end of the list add the matching credential
+ nearby_protocol::MatchedCredentialData match_data(123,
+ V0AdvEncryptedMetadata);
+ std::array<uint8_t, 32> key_seed = {};
+ std::fill_n(key_seed.begin(), 32, 0x11);
+ nearby_protocol::V0MatchableCredential v0_cred(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
+ slab.AddV0Credential(v0_cred);
+
+ nearby_protocol::CredentialBook cred_book(slab);
+ cred_book_ = std::move(cred_book);
+ }
+ void TearDown(const ::benchmark::State &state) override {}
+};
+
+BENCHMARK_DEFINE_F(V0Encrypted, SingleMatchingCredential)
+(benchmark::State &state) {
+ for ([[maybe_unused]] auto _ : state) {
+ // now that the credentials have been loaded attempt to deserialize
+ auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvEncryptedPayload, cred_book_.value());
+ benchmark::DoNotOptimize(result);
+
+ // make sure this succeeded and that we could correctly decrypt the adv
+ assert(result.GetKind() ==
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
+ assert(result.IntoV0().IntoLegible().GetIdentityKind() ==
+ nearby_protocol::DeserializedV0IdentityKind::Decrypted);
+ }
+}
+
+BENCHMARK_REGISTER_F(V0Encrypted, SingleMatchingCredential)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
+
+class V1SigEncryptedSingleSection : public benchmark::Fixture {
+ public:
+ std::optional<nearby_protocol::CredentialBook> cred_book_;
+ void SetUp(const ::benchmark::State &state) override {
+ // populate credential book
+ auto num_creds = state.range(0);
+ nearby_protocol::CredentialSlab slab;
+ for (int i = 1; i < num_creds; i++) {
+ auto credential = GenerateRandomCredentialV1();
+ auto result = slab.AddV1Credential(credential);
+ assert(result.ok());
+ }
+ // now at the end of the list add the matching credential
+ nearby_protocol::MatchedCredentialData match_data(123,
+ V1AdvEncryptedMetadata);
+ nearby_protocol::V1MatchableCredential v1_cred(
+ V1AdvKeySeed, V1AdvExpectedMicExtendedSaltIdentityTokenHmac,
+ V1AdvExpectedSignatureIdentityTokenHmac, V1AdvPublicKey, match_data);
+ auto add_result = slab.AddV1Credential(v1_cred);
+ assert(add_result.ok());
+ nearby_protocol::CredentialBook cred_book(slab);
+ cred_book_ = std::move(cred_book);
+ }
+ void TearDown(const ::benchmark::State &state) override {}
+};
+
+BENCHMARK_DEFINE_F(V1SigEncryptedSingleSection, SingleMatchingCredential)
+(benchmark::State &state) {
+ for ([[maybe_unused]] auto _ : state) {
+ // now that the credentials have been loaded attempt to deserialize
+ auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V1AdvEncrypted, cred_book_.value());
+ benchmark::DoNotOptimize(result);
+
+ // make sure this succeeded and that we could correctly decrypt the adv
+ assert(result.GetKind() ==
+ nearby_protocol::DeserializeAdvertisementResultKind::V1);
+ assert(result.IntoV1().GetNumLegibleSections() == 1);
+ }
+}
+
+BENCHMARK_REGISTER_F(V1SigEncryptedSingleSection, SingleMatchingCredential)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
+
+struct V1CredentialData {
+ uint32_t cred_id;
+ std::array<uint8_t, 32> key_seed;
+ std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac;
+ std::array<uint8_t, 32> expected_signed_metadata_key_hmac;
+ std::array<uint8_t, 32> pub_key;
+ std::array<uint8_t, 500> encrypted_metadata_bytes;
+};
+
+V1CredentialData GenerateData() {
+ return {
+ .cred_id = static_cast<uint32_t>(rand()),
+ .key_seed = create_random_array<32>(),
+ .expected_unsigned_metadata_key_hmac = create_random_array<32>(),
+ .expected_signed_metadata_key_hmac = create_random_array<32>(),
+ .pub_key = create_random_array<32>(),
+ .encrypted_metadata_bytes = create_random_array<500>(),
+ };
+}
+
+class LoadCredentialBook : public benchmark::Fixture {
+ public:
+ std::vector<V1CredentialData> creds_;
+ // generate all the data in setup so the time for generation is not included
+ // in the measurement
+ void SetUp(const ::benchmark::State &state) override {
+ // populate credential book
+ auto num_creds = state.range(0);
+ for (int i = 1; i < num_creds; i++) {
+ auto credential = GenerateData();
+ creds_.push_back(credential);
+ }
+ }
+};
+
+BENCHMARK_DEFINE_F(LoadCredentialBook, SingleMatchingCredential)
+(benchmark::State &state) {
+ for ([[maybe_unused]] auto _ : state) {
+ nearby_protocol::CredentialSlab slab;
+ for (auto cred : creds_) {
+ nearby_protocol::MatchedCredentialData m(cred.cred_id,
+ cred.encrypted_metadata_bytes);
+ nearby_protocol::V1MatchableCredential v1_cred(
+ cred.key_seed, cred.expected_unsigned_metadata_key_hmac,
+ cred.expected_signed_metadata_key_hmac, cred.pub_key, m);
+ auto result = slab.AddV1Credential(v1_cred);
+ assert(result.ok());
+ }
+ nearby_protocol::CredentialBook book(slab);
+ benchmark::DoNotOptimize(book);
+ }
+}
+
+BENCHMARK_REGISTER_F(LoadCredentialBook, SingleMatchingCredential)
+ ->RangeMultiplier(10)
+ ->Range(1, 1000)
+ ->Unit(benchmark::kMicrosecond);
+
+BENCHMARK_MAIN();
diff --git a/nearby/presence/np_cpp_ffi/benchmarks/np_ffi_bench.cc b/nearby/presence/np_cpp_ffi/benchmarks/np_ffi_bench.cc
deleted file mode 100644
index 164bab3..0000000
--- a/nearby/presence/np_cpp_ffi/benchmarks/np_ffi_bench.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 "nearby_protocol.h"
-
-#include "np_cpp_ffi_functions.h"
-#include "np_cpp_ffi_types.h"
-
-#include "benchmark/benchmark.h"
-
-// Internal C struct representation of a v0 payload
-static np_ffi::internal::RawAdvertisementPayload payload{
- {7,
- {
- 0x00, // Adv Header
- 0x03, // Public DE header
- 0x15, 0x05, // Tx Power value 5
- 0x26, 0x00, 0x46, // Length 2 Actions
- }}};
-
-static nearby_protocol::RawAdvertisementPayload
- v0_adv(nearby_protocol::ByteBuffer(payload.bytes));
-
-class NpCppBenchmark : public benchmark::Fixture {
- void SetUp(const ::benchmark::State &state) override {}
-
- void TearDown(const ::benchmark::State &state) override {}
-};
-
-BENCHMARK_DEFINE_F(NpCppBenchmark, V0PlaintextAdvertisement)
-(benchmark::State &state) {
- auto cred_slab = nearby_protocol::CredentialSlab::TryCreate();
- assert(cred_slab.ok());
- auto cred_book = nearby_protocol::CredentialBook::TryCreateFromSlab(cred_slab.value());
- assert(cred_book.ok());
- auto num_ciphers = state.range(0);
-
- for ([[maybe_unused]] auto _ : state) {
- for (int i = 0; i < num_ciphers; i++) {
- auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- v0_adv, cred_book.value());
- assert(result.GetKind() ==
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
- }
- }
-}
-
-BENCHMARK_REGISTER_F(NpCppBenchmark, V0PlaintextAdvertisement)
- ->RangeMultiplier(10)
- ->Range(1, 1000)
- ->Unit(benchmark::kMicrosecond);
-
-class NpCBenchmark : public benchmark::Fixture {
- void SetUp(const ::benchmark::State &state) override {}
-
- void TearDown(const ::benchmark::State &state) override {}
-};
-
-BENCHMARK_DEFINE_F(NpCBenchmark, V0PlaintextAdvertisement)
-(benchmark::State &state) {
- auto num_ciphers = state.range(0);
- auto slab_result = np_ffi::internal::np_ffi_create_credential_slab();
- assert(
- np_ffi::internal::np_ffi_CreateCredentialSlabResult_kind(slab_result) ==
- np_ffi::internal::CreateCredentialSlabResultKind::Success);
- auto slab = np_ffi::internal::np_ffi_CreateCredentialSlabResult_into_SUCCESS(
- slab_result);
-
- auto book_result = np_ffi::internal::np_ffi_create_credential_book_from_slab(slab);
- assert(
- np_ffi::internal::np_ffi_CreateCredentialBookResult_kind(book_result) ==
- np_ffi::internal::CreateCredentialBookResultKind::Success);
- auto book = np_ffi::internal::np_ffi_CreateCredentialBookResult_into_SUCCESS(
- book_result);
-
- for ([[maybe_unused]] auto _ : state) {
- for (int i = 0; i < num_ciphers; i++) {
- auto result =
- np_ffi::internal::np_ffi_deserialize_advertisement({payload}, book);
- assert(np_ffi::internal::np_ffi_DeserializeAdvertisementResult_kind(
- result) ==
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
- auto deallocate_result =
- np_ffi::internal::np_ffi_deallocate_deserialize_advertisement_result(
- result);
- assert(deallocate_result == np_ffi::internal::DeallocateResult::Success);
- }
- }
-
- auto deallocate_result =
- np_ffi::internal::np_ffi_deallocate_credential_book(book);
- assert(deallocate_result == np_ffi::internal::DeallocateResult::Success);
-}
-
-BENCHMARK_REGISTER_F(NpCBenchmark, V0PlaintextAdvertisement)
- ->RangeMultiplier(10)
- ->Range(1, 1000)
- ->Unit(benchmark::kMicrosecond);
-
-BENCHMARK_MAIN();
diff --git a/nearby/presence/np_cpp_ffi/fuzz/CMakeLists.txt b/nearby/presence/np_cpp_ffi/fuzz/CMakeLists.txt
index 0a1c088..e9decf3 100644
--- a/nearby/presence/np_cpp_ffi/fuzz/CMakeLists.txt
+++ b/nearby/presence/np_cpp_ffi/fuzz/CMakeLists.txt
@@ -12,21 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 3.0)
+fuzztest_setup_fuzzing_flags()
-# libfuzzer needs clang
-SET(CMAKE_C_COMPILER "clang")
-SET(CMAKE_CXX_COMPILER "clang++")
+add_executable(
+ deserialization_fuzzer
+ deserialization_fuzzer.cc
+)
-add_compile_definitions("CORPUS_DIR=${CMAKE_CURRENT_SOURCE_DIR}/corpus")
-file(COPY corpus DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
-add_executable(generate_fuzz_corpus generate_fuzz_corpus.cc)
-target_link_libraries(generate_fuzz_corpus nearby_protocol shared_test_util)
+target_link_libraries(
+ deserialization_fuzzer
+ PRIVATE
+ nearby_protocol
+ shared_test_util
+)
-add_executable(fuzzer_np_cpp_deserialize fuzzer_np_cpp_deserialize.cc)
-target_compile_options(fuzzer_np_cpp_deserialize PRIVATE -fsanitize=fuzzer,address)
-target_link_libraries(fuzzer_np_cpp_deserialize nearby_protocol -fsanitize=fuzzer,address)
-
-add_executable(fuzzer_np_cpp_valid_header fuzzer_np_cpp_valid_header.cc)
-target_compile_options(fuzzer_np_cpp_valid_header PRIVATE -fsanitize=fuzzer,address)
-target_link_libraries(fuzzer_np_cpp_valid_header nearby_protocol -fsanitize=fuzzer,address)
+link_fuzztest(deserialization_fuzzer)
+gtest_discover_tests(deserialization_fuzzer)
diff --git a/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvEmpty b/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvEmpty
deleted file mode 100644
index f76dd23..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvEmpty
+++ /dev/null
Binary files differ
diff --git a/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvSimple b/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvSimple
deleted file mode 100644
index fac97f6..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/corpus/V0AdvSimple
+++ /dev/null
Binary files differ
diff --git a/nearby/presence/np_cpp_ffi/fuzz/corpus/V1AdvSimple b/nearby/presence/np_cpp_ffi/fuzz/corpus/V1AdvSimple
deleted file mode 100644
index 4acdf33..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/corpus/V1AdvSimple
+++ /dev/null
@@ -1 +0,0 @@
-  \ No newline at end of file
diff --git a/nearby/presence/np_cpp_ffi/fuzz/deserialization_fuzzer.cc b/nearby/presence/np_cpp_ffi/fuzz/deserialization_fuzzer.cc
new file mode 100644
index 0000000..7108e0a
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/fuzz/deserialization_fuzzer.cc
@@ -0,0 +1,304 @@
+// 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 <array>
+#include <cstdint>
+#include <random>
+#include <span>
+#include <utility>
+#include <vector>
+
+#include "fuzztest/domain_core.h"
+#include "fuzztest/fuzztest.h"
+#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "shared_test_util.h"
+
+// redefine test data as std::vector types since fuzztest does not support
+// template class use in its input domains (ie: std::array<T, N>), and we want
+// to use our test data to seed the fuzzer
+static std::vector<uint8_t> V0AdvEmptyVec(V0AdvEmptyBytes.begin(),
+ V0AdvEmptyBytes.end());
+static std::vector<uint8_t> V1AdvEmptyVec(V1AdvEmptyBytes.begin(),
+ V1AdvEmptyBytes.end());
+static std::vector<uint8_t> V0AdvPlaintextVec(V0AdvPlaintextBytes.begin(),
+ V0AdvPlaintextBytes.end());
+static std::vector<uint8_t> V0AdvPlaintextMultiDeVec(
+ V0AdvPlaintextMultiDeBytes.begin(), V0AdvPlaintextMultiDeBytes.end());
+static std::vector<uint8_t> V1AdvPlaintextVec(V1AdvPlaintextBytes.begin(),
+ V1AdvPlaintextBytes.end());
+static std::vector<uint8_t> V0AdvEncryptedVec(V0AdvEncryptedBytes.begin(),
+ V0AdvEncryptedBytes.end());
+static std::vector<uint8_t> V1AdvEncryptedVec(V1AdvEncryptedBytes.begin(),
+ V1AdvEncryptedBytes.end());
+
+void HandleAdvertisementResult(nearby_protocol::DeserializeAdvertisementResult);
+
+void PlaintextDeserializer(std::span<const uint8_t> adv_bytes) {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
+ auto buffer = nearby_protocol::ByteBuffer<255>::TryFromSpan(adv_bytes);
+ EXPECT_TRUE(buffer.ok());
+
+ nearby_protocol::RawAdvertisementPayload payload(
+ (nearby_protocol::ByteBuffer<255>(*buffer)));
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(payload, book);
+
+ // Since we are seeding with valid data, we can add extra calls into the
+ // result processing APIs to ensure none of the internal asserts are
+ // triggered.
+ HandleAdvertisementResult(std::move(deserialize_result));
+}
+
+FUZZ_TEST(NpCppDeserializationFuzzers, PlaintextDeserializer)
+ .WithDomains(fuzztest::Arbitrary<std::vector<uint8_t>>()
+ .WithMinSize(0)
+ .WithMaxSize(255))
+ .WithSeeds({V0AdvEmptyVec, V1AdvEmptyVec, V0AdvPlaintextVec,
+ V0AdvPlaintextMultiDeVec, V1AdvPlaintextVec, V0AdvEncryptedVec,
+ V1AdvEncryptedVec});
+
+// The data which is automatically generated by the fuzzer
+struct IdentityData {
+ uint32_t credential_id;
+ std::array<uint8_t, 32> key_seed;
+ std::array<uint8_t, 32> legacy_metadata_key_hmac;
+ std::array<uint8_t, 32> expected_unsigned_identity_token_hmac;
+ std::array<uint8_t, 32> expected_signed_identity_token_hmac;
+ std::array<uint8_t, 32> pub_key;
+ std::vector<uint8_t> encrypted_metadata_bytes;
+};
+
+static struct IdentityData V0TestCaseIdentityData {
+ .credential_id = static_cast<uint32_t>(rand()), .key_seed = V0AdvKeySeed,
+ .legacy_metadata_key_hmac = V0AdvLegacyIdentityTokenHmac,
+ .encrypted_metadata_bytes = V0AdvEncryptedMetadata
+};
+
+static struct IdentityData V1TestCaseIdentityData {
+ .credential_id = static_cast<uint32_t>(rand()), .key_seed = V1AdvKeySeed,
+ .expected_unsigned_identity_token_hmac =
+ V1AdvExpectedMicExtendedSaltIdentityTokenHmac,
+ .expected_signed_identity_token_hmac =
+ V1AdvExpectedSignatureIdentityTokenHmac,
+ .pub_key = V1AdvPublicKey, .encrypted_metadata_bytes = V1AdvEncryptedMetadata,
+};
+
+// Now lets try feeding the fuzzer some credential data that can successfully
+// decrypt advertisements to improve its efficiency, and provide extra coverage
+// on on credential/iteration code paths.
+// TODO: Add more interesting credential seed data once we have C++
+// serialization APIs, ie multiple sections with multiple valid credentials
+// and combinations of matching and undecryptable sections etc.
+void DeserializeWithCredentials(std::span<const IdentityData> identities,
+ std::span<const uint8_t> adv_bytes) {
+ nearby_protocol::CredentialSlab slab;
+ // populate book with fuzzer generated credential data
+ for (auto data : identities) {
+ nearby_protocol::MatchedCredentialData match_data(
+ 123, data.encrypted_metadata_bytes);
+ nearby_protocol::V0MatchableCredential v0_cred(
+ data.key_seed, data.legacy_metadata_key_hmac, match_data);
+ // adding v0 credentials is infallible
+ slab.AddV0Credential(v0_cred);
+
+ nearby_protocol::V1MatchableCredential v1_cred(
+ data.key_seed, data.expected_unsigned_identity_token_hmac,
+ data.expected_signed_identity_token_hmac, data.pub_key, match_data);
+ [[maybe_unused]] auto result = slab.AddV1Credential(v1_cred);
+ }
+
+ nearby_protocol::CredentialBook book(slab);
+ auto buffer = nearby_protocol::ByteBuffer<255>::TryFromSpan(adv_bytes);
+ EXPECT_TRUE(buffer.ok());
+
+ nearby_protocol::RawAdvertisementPayload payload(
+ (nearby_protocol::ByteBuffer<255>(*buffer)));
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(payload, book);
+
+ // Since we are seeding with valid data, we can add extra calls into the
+ // result processing APIs to ensure none of the internal asserts are
+ // triggered.
+ HandleAdvertisementResult(std::move(deserialize_result));
+}
+
+std::vector<std::tuple<std::vector<IdentityData>, std::vector<uint8_t>>>
+DeserializeWithCredentialSeedData() {
+ return {
+ {{{V0TestCaseIdentityData, V1TestCaseIdentityData}, V0AdvEncryptedVec},
+ {{V0TestCaseIdentityData, V1TestCaseIdentityData}, V1AdvEncryptedVec}},
+ };
+}
+
+TEST(NpCppDeserializationFuzzers, InvalidPublicKeyInCredential) {
+ std::vector<IdentityData> identities;
+ identities.push_back(
+ {1804289383,
+ {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17},
+ {136, 51, 222, 213, 77, 0, 146, 232, 128, 112, 213,
+ 31, 24, 236, 34, 69, 117, 124, 36, 223, 227, 140,
+ 178, 222, 119, 182, 120, 133, 252, 165, 103, 77},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ fuzztest::ToByteArray("")});
+ identities.push_back({846930886,
+ {49, 67, 99, 30, 202, 232, 151, 75, 150, 80, 204,
+ 28, 72, 37, 14, 129, 88, 6, 129, 81, 249, 235,
+ 37, 35, 3, 212, 151, 109, 149, 25, 145, 57},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {28, 188, 235, 220, 23, 181, 145, 229, 7, 157, 112,
+ 193, 232, 75, 204, 219, 75, 15, 118, 131, 89, 98,
+ 10, 45, 85, 11, 59, 54, 164, 146, 139, 19},
+ {109, 13, 182, 9, 16, 177, 83, 196, 126, 16, 22,
+ 20, 156, 159, 242, 20, 15, 236, 83, 118, 227, 7,
+ 217, 211, 158, 174, 231, 69, 44, 3, 236, 109},
+ fuzztest::ToByteArray("")});
+
+ DeserializeWithCredentials(
+ identities,
+ fuzztest::ToByteArray(
+ " g\221\020\010\255iF\004]"
+ "\256m\267\367\\\323\270\254\360\277u\220\001\276s3\244v\204J\t"
+ "\017+"
+ "\231G\337\213F\312\026\316\023\265nS\256("
+ "VD\016\246\215\353\241\021\257N\033\340\216\365\272\220O."
+ "\224\374\336\246\177]"
+ "\3107\265\357\312\254\213\237\033\324\306\021\205\323g92\321\202"
+ "\312"
+ "N\271F\003\203hV\013\314\375z*\276\007"));
+}
+
+TEST(NpCppDeserializationFuzzers, PlaintextDeserializerRegression) {
+ PlaintextDeserializer(fuzztest::ToByteArray(
+ " 4\221\020\005\255iF\004]"
+ "\256\275m\267\367\\\270\254\360\277u\220\001G\337\213F\312\026\316\023"
+ "\265nS\256(VD\016\243\215\353\241\021\257N\020\340\216\365\272\220O."
+ "\224\374\336\246\177]"
+ "\3107\267\357\312\254\213\237\033\324\306\021\205\323g92\321\202\312N"
+ "\271D\003\203hV\013\314\375z*\276\007"));
+}
+
+FUZZ_TEST(NpCppDeserializationFuzzers, DeserializeWithCredentials)
+ .WithDomains(fuzztest::Arbitrary<std::vector<IdentityData>>()
+ .WithMinSize(0)
+ .WithMaxSize(1000),
+ fuzztest::Arbitrary<std::vector<uint8_t>>()
+ .WithMinSize(0)
+ .WithMaxSize(255))
+ .WithSeeds(DeserializeWithCredentialSeedData);
+
+// Lets encourage the fuzzer to try with a lot of credentials and make sure
+// nothing falls apart. By default the vec ranges are somewhere between 1-20
+// even with setting a max of 1000, so setting a high minimum here to ensure the
+// higher end of credential iteration is hit.
+FUZZ_TEST(NpCppDeserializationFuzzersLotsOfCredentials,
+ DeserializeWithCredentials)
+ .WithDomains(
+ fuzztest::Arbitrary<std::vector<IdentityData>>().WithMinSize(10000),
+ fuzztest::Arbitrary<std::vector<uint8_t>>().WithMinSize(0).WithMaxSize(
+ 255));
+
+// Helpers to trigger result processing code paths.
+void HandleV0Adv(nearby_protocol::DeserializedV0Advertisement);
+void HandleLegibleV0Adv(nearby_protocol::LegibleDeserializedV0Advertisement);
+void HandleV0IdentityKind(nearby_protocol::DeserializedV0IdentityKind);
+void HandleDataElement(nearby_protocol::V0DataElement);
+
+void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement);
+void HandleV1Section(nearby_protocol::DeserializedV1Section);
+void HandleV1DataElement(nearby_protocol::V1DataElement);
+
+void HandleAdvertisementResult(
+ nearby_protocol::DeserializeAdvertisementResult result) {
+ switch (result.GetKind()) {
+ case nearby_protocol::DeserializeAdvertisementResultKind::Error:
+ break;
+ case nearby_protocol::DeserializeAdvertisementResultKind::V0:
+ HandleV0Adv(result.IntoV0());
+ break;
+ case nearby_protocol::DeserializeAdvertisementResultKind::V1:
+ HandleV1Adv(result.IntoV1());
+ break;
+ }
+}
+
+void HandleV0Adv(nearby_protocol::DeserializedV0Advertisement result) {
+ switch (result.GetKind()) {
+ case nearby_protocol::DeserializedV0AdvertisementKind::Legible:
+ HandleLegibleV0Adv(result.IntoLegible());
+ break;
+ case nearby_protocol::DeserializedV0AdvertisementKind::
+ NoMatchingCredentials:
+ break;
+ }
+}
+
+void HandleLegibleV0Adv(
+ nearby_protocol::LegibleDeserializedV0Advertisement legible_adv) {
+ auto num_des = legible_adv.GetNumberOfDataElements();
+ auto payload = legible_adv.IntoPayload();
+ for (int i = 0; i < num_des; i++) {
+ auto de_result = payload.TryGetDataElement(i);
+ if (!de_result.ok()) {
+ return;
+ }
+ HandleDataElement(de_result.value());
+ }
+}
+
+void HandleDataElement(nearby_protocol::V0DataElement de) {
+ switch (de.GetKind()) {
+ case nearby_protocol::V0DataElementKind::TxPower: {
+ [[maybe_unused]] auto tx_power = de.AsTxPower();
+ break;
+ }
+ case nearby_protocol::V0DataElementKind::Actions: {
+ [[maybe_unused]] auto actions = de.AsActions();
+ break;
+ }
+ }
+}
+
+void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement adv) {
+ auto legible_sections = adv.GetNumLegibleSections();
+ [[maybe_unused]] auto encrypted_sections = adv.GetNumUndecryptableSections();
+ for (auto i = 0; i < legible_sections; i++) {
+ auto section_result = adv.TryGetSection(i);
+ if (!section_result.ok()) {
+ return;
+ }
+ HandleV1Section(section_result.value());
+ }
+}
+
+void HandleV1Section(nearby_protocol::DeserializedV1Section section) {
+ auto num_des = section.NumberOfDataElements();
+ for (auto i = 0; i < num_des; i++) {
+ auto de_result = section.TryGetDataElement(i);
+ if (!de_result.ok()) {
+ return;
+ }
+ }
+}
diff --git a/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_deserialize.cc b/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_deserialize.cc
deleted file mode 100644
index 3c409e7..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_deserialize.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 "nearby_protocol.h"
-
-#include <cstdint>
-#include <string>
-
-#include "absl/strings/escaping.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- // won't fit into a FfiByteBuffer<255>
- if (size > 255) {
- return -1;
- }
-
- nearby_protocol::FfiByteBuffer<255> raw_bytes;
- memcpy(&raw_bytes.bytes, data, size);
- raw_bytes.len = size;
-
- nearby_protocol::RawAdvertisementPayload payload(
- (nearby_protocol::ByteBuffer<255>(raw_bytes)));
-
- auto credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- if (!credential_slab.ok()) {
- printf("Error: create Credential slab failed\n");
- __builtin_trap();
- }
-
- auto credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(credential_slab.value());
- if (!credential_book.ok()) {
- printf("Error: create Credential book failed\n");
- __builtin_trap();
- }
-
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- payload, credential_book.value());
-
- return 0;
-}
diff --git a/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_valid_header.cc b/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_valid_header.cc
deleted file mode 100644
index 2475b5e..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/fuzzer_np_cpp_valid_header.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 "nearby_protocol.h"
-
-#include <cstdint>
-
-// Fuzz input data beginning with a valid header
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- // Won't fit into a FfiByteBuffer<255>
- if (size > 255) {
- return -1;
- }
-
- nearby_protocol::FfiByteBuffer<255> raw_bytes;
- memcpy(&raw_bytes.bytes, data, size);
- raw_bytes.len = size;
-
- nearby_protocol::RawAdvertisementPayload payload(
- (nearby_protocol::ByteBuffer<255>(raw_bytes)));
-
- auto credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- if (!credential_slab.ok()) {
- printf("Error: create Credential slab failed\n");
- __builtin_trap();
- }
-
- auto credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(credential_slab.value());
- if (!credential_book.ok()) {
- printf("Error: create Credential book failed\n");
- __builtin_trap();
- }
-
- // Force it to go down the v0 deserialization path
- raw_bytes.bytes[0] = 0x00;
-
- auto v0_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- payload, credential_book.value());
-
- // Force it down the v1 deserialization path
- raw_bytes.bytes[0] = 0x20;
-
- auto v1_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- payload, credential_book.value());
-
- return 0;
-}
diff --git a/nearby/presence/np_cpp_ffi/fuzz/generate_fuzz_corpus.cc b/nearby/presence/np_cpp_ffi/fuzz/generate_fuzz_corpus.cc
deleted file mode 100644
index 9d28f7a..0000000
--- a/nearby/presence/np_cpp_ffi/fuzz/generate_fuzz_corpus.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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
-//
-// 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.
-
-#include "nearby_protocol.h"
-#include "shared_test_util.h"
-
-#include <fstream>
-#include <iostream>
-
-#define STRING(x) #x
-#define XSTRING(x) STRING(x)
-
-void write_corpus_data_file(std::string file_name,
- nearby_protocol::RawAdvertisementPayload payload) {
- // Get the current source directory.
- std::string current_source_dir = XSTRING(CORPUS_DIR);
-
- // Print the current source directory to the console.
- std::cout << "Writing to file: " << current_source_dir << "/" << file_name
- << std::endl;
-
- std::ofstream out(current_source_dir + "/" + file_name,
- std::ios::out | std::ios::binary);
- auto vec_data = payload.buffer_.ToVector();
- out.write(reinterpret_cast<const char *>(vec_data.data()), vec_data.size());
- out.close();
-}
-
-int main() {
- write_corpus_data_file("V0AdvSimple", V0AdvSimple);
- write_corpus_data_file("V1AdvSimple", V1AdvSimple);
- write_corpus_data_file("V0AdvEmpty", V0AdvEmpty);
-}
diff --git a/nearby/presence/np_cpp_ffi/include/nearby_protocol.h b/nearby/presence/np_cpp_ffi/include/nearby_protocol.h
index cc02007..5e064f9 100644
--- a/nearby/presence/np_cpp_ffi/include/nearby_protocol.h
+++ b/nearby/presence/np_cpp_ffi/include/nearby_protocol.h
@@ -15,12 +15,21 @@
#ifndef NEARBY_PRESENCE_NP_CPP_FFI_INCLUDE_NP_PROTOCOL_H_
#define NEARBY_PRESENCE_NP_CPP_FFI_INCLUDE_NP_PROTOCOL_H_
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <span>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
#include "np_cpp_ffi_types.h"
-#include <span>
-
// This namespace provides a C++ API surface to the Rust nearby protocol
// implementation. This is a wrapper over the np_ffi::internal namespace defined
// in the headers np_cpp_ffi_functions.h and np_cpp_ffi_types.h which are
@@ -52,24 +61,33 @@
namespace nearby_protocol {
// Re-exporting cbindgen generated types which are used in the public API
-using np_ffi::internal::AddCredentialToSlabResult;
-using np_ffi::internal::BooleanActionType;
+using np_ffi::internal::ActionType;
+using np_ffi::internal::AddV0CredentialToSlabResult;
+using np_ffi::internal::AddV0DEResult;
+using np_ffi::internal::AddV1CredentialToSlabResult;
+using np_ffi::internal::AdvertisementBuilderKind;
using np_ffi::internal::CreateCredentialBookResultKind;
-using np_ffi::internal::CreateCredentialSlabResultKind;
+using np_ffi::internal::CreateV1SectionBuilderResultKind;
+using np_ffi::internal::CurrentHandleAllocations;
using np_ffi::internal::DeserializeAdvertisementResultKind;
using np_ffi::internal::DeserializedV0AdvertisementKind;
using np_ffi::internal::DeserializedV0IdentityDetails;
using np_ffi::internal::DeserializedV0IdentityKind;
using np_ffi::internal::DeserializedV1IdentityDetails;
using np_ffi::internal::DeserializedV1IdentityKind;
-using np_ffi::internal::EncryptedIdentityType;
using np_ffi::internal::GetV0DEResultKind;
using np_ffi::internal::PanicReason;
-using np_ffi::internal::TxPower;
+using np_ffi::internal::SerializeV0AdvertisementResultKind;
+using np_ffi::internal::SerializeV1AdvertisementResultKind;
using np_ffi::internal::V0DataElementKind;
using np_ffi::internal::V1VerificationMode;
-template <uintptr_t N> using FfiByteBuffer = np_ffi::internal::ByteBuffer<N>;
+const uint8_t MAX_ADV_PAYLOAD_SIZE = 255;
+const uint8_t MAX_V1_DE_PAYLOAD_SIZE = 127;
+const uint8_t KEY_SEED_SIZE = 32;
+const uint8_t HMAC_TAG_SIZE = 32;
+const uint8_t PUBLIC_SIGNING_KEY_SIZE = 32;
+const uint8_t DERIVED_SALT_SIZE = 16;
// All of the types defined in this header
class RawAdvertisementPayload;
@@ -100,11 +118,11 @@ class V1DataElement;
// on memory consumption. See np_ffi_global_config_* functions in
// np_cpp_ffi_functions.h for more info
class GlobalConfig {
-public:
+ public:
// This class provides the static methods needed for global configuration,
// so it does not need to be constructable, cloneable, or assignable.
- GlobalConfig(GlobalConfig const &) = delete;
- void operator=(GlobalConfig const &) = delete;
+ GlobalConfig(const GlobalConfig &) = delete;
+ void operator=(const GlobalConfig &) = delete;
GlobalConfig() = delete;
// Provides a user specified panic handler. This method will only have an
@@ -120,37 +138,17 @@ public:
// np_ffi_global_config_set_num_shards in np_cpp_ffi_functions.h for more info
static void SetNumShards(uint8_t num_shards);
- // Sets the maximum number of active handles to credential slabs which may be
- // active at any one time. See
- // np_ffi_global_config_set_max_num_credential_slabs in np_cpp_ffi_functions.h
- // for more info
- static void SetMaxNumCredentialSlabs(uint32_t max_num_credential_slabs);
-
- // Sets the maximum number of active handles to credential books which may be
- // active at any one time. See
- // np_ffi_global_config_set_max_num_credential_books in np_cpp_ffi_functions.h
- // for more info
- static void SetMaxNumCredentialBooks(uint32_t max_num_credential_books);
-
- // Sets the maximum number of active handles to deserialized v0 advertisements
- // which may be active at any one time. See
- // np_ffi_global_config_set_max_num_deserialized_v0_advertisements for more
- // info.
- static void SetMaxNumDeserializedV0Advertisements(
- uint32_t max_num_deserialized_v0_advertisements);
-
- // Sets the maximum number of active handles to deserialized v1 advertisements
- // which may be active at any one time
- static void SetMaxNumDeserializedV1Advertisements(
- uint32_t max_num_deserialized_v1_advertisements);
+ // Checks the current count of all outstanding handle allocations, useful for
+ // debugging, logging, and testing
+ static CurrentHandleAllocations GetCurrentHandleAllocationCount();
};
// Holds the credentials used in the construction of a credential book
// using CredentialBook::TryCreateFromSlab()
class CredentialSlab {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor or copy-assignment since
+ // this class wraps a handle to externally allocated resources.
CredentialSlab(const CredentialSlab &other) = delete;
CredentialSlab &operator=(const CredentialSlab &other) = delete;
@@ -159,26 +157,23 @@ public:
CredentialSlab(CredentialSlab &&other) noexcept;
CredentialSlab &operator=(CredentialSlab &&other) noexcept;
+ // Creates a new instance of a CredentialSlab, returns the CredentialSlab on
+ // success or a Status code on failure
+ CredentialSlab();
+
// The destructor for a CredentialSlab, this will be called when a
// CredentialSlab instance goes out of scope and will free the underlying
// resources
~CredentialSlab();
- // Creates a new instance of a CredentialSlab, returns the CredentialSlab on
- // success or a Status code on failure
- [[nodiscard]] static absl::StatusOr<CredentialSlab> TryCreate();
-
// Adds a V0 credential to the slab
- [[nodiscard]] absl::Status AddV0Credential(V0MatchableCredential v0_cred);
+ void AddV0Credential(V0MatchableCredential v0_cred);
// Adds a V1 credential to the slab
[[nodiscard]] absl::Status AddV1Credential(V1MatchableCredential v1_cred);
-private:
+ private:
friend class CredentialBook;
- explicit CredentialSlab(np_ffi::internal::CredentialSlab credential_slab)
- : credential_slab_(credential_slab), moved_(false) {}
-
np_ffi::internal::CredentialSlab credential_slab_;
bool moved_;
};
@@ -187,9 +182,10 @@ private:
// This needs to be passed to Deserializer::DeserializeAdvertisement() when
// attempting to deserialize a payload
class CredentialBook {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ CredentialBook() = delete;
CredentialBook(const CredentialBook &other) = delete;
CredentialBook &operator=(const CredentialBook &other) = delete;
@@ -207,14 +203,10 @@ public:
// returning the CredentialBook on success or a Status code on failure.
// The passed credential-slab will be deallocated if this operation
// is successful.
- [[nodiscard]] static absl::StatusOr<CredentialBook>
- TryCreateFromSlab(CredentialSlab &slab);
+ CredentialBook(CredentialSlab &slab);
-private:
+ private:
friend class Deserializer;
- explicit CredentialBook(np_ffi::internal::CredentialBook credential_book)
- : credential_book_(credential_book), moved_(false) {}
-
np_ffi::internal::CredentialBook credential_book_;
bool moved_;
};
@@ -222,21 +214,20 @@ private:
// Holds data associated with a specific credential which will be returned to
// the caller when it is successfully matched with an advertisement.
class MatchedCredentialData {
-public:
+ public:
// Creates matched credential data from a provided credential_id used to
// correlate the data back to its full credential data, and the metadata byte
- // buffer as copied from the given span over bytes. After calling
- // this the bytes are copied into the rust code, so the
- // encrypted_metadata_bytes_buffer can be freed.
+ // buffer as copied from the given span over bytes. The span must be valid
+ // until the corresponding Add_*_Credential is called using this data.
//
// Safety: this is safe if the span is over a valid buffer of bytes. The copy
// from the memory address isn't atomic, so concurrent modification of the
// array from another thread would cause undefined behavior.
- [[nodiscard]] MatchedCredentialData(uint32_t cred_id,
- std::span<uint8_t> metadata_bytes);
+ [[nodiscard]] MatchedCredentialData(
+ uint32_t cred_id, std::span<const uint8_t> encrypted_metadata_bytes);
-private:
- np_ffi::internal::FfiMatchedCredential data_;
+ private:
+ np_ffi::internal::FfiMatchedCredential data_{};
friend class V0MatchableCredential;
friend class V1MatchableCredential;
};
@@ -245,15 +236,15 @@ private:
// advertisements, along with some provided matched data that will be returned
// back to the caller upon a successful credential match.
class V0MatchableCredential {
-public:
+ public:
// Creates a new V0MatchableCredential from a key seed, its calculated hmac
// value and some match data.
[[nodiscard]] V0MatchableCredential(
- std::array<uint8_t, 32> key_seed,
- std::array<uint8_t, 32> legacy_metadata_key_hmac,
+ std::array<uint8_t, KEY_SEED_SIZE> key_seed,
+ std::array<uint8_t, HMAC_TAG_SIZE> legacy_metadata_key_hmac,
MatchedCredentialData matched_credential_data);
-private:
+ private:
friend class CredentialSlab;
np_ffi::internal::V0MatchableCredential internal_{};
};
@@ -262,34 +253,78 @@ private:
// advertisements, along with some provided matched data that will be returned
// back to the caller upon a successful credential match.
class V1MatchableCredential {
-public:
+ public:
+ V1MatchableCredential() = delete;
+
// Creates a new V1MatchableCredential from key material, its calculated hmac
// value and some match data.
[[nodiscard]] V1MatchableCredential(
- std::array<uint8_t, 32> key_seed,
- std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac,
- std::array<uint8_t, 32> expected_signed_metadata_key_hmac,
- std::array<uint8_t, 32> pub_key,
+ std::array<uint8_t, KEY_SEED_SIZE> key_seed,
+ std::array<uint8_t, HMAC_TAG_SIZE> expected_unsigned_metadata_key_hmac,
+ std::array<uint8_t, HMAC_TAG_SIZE> expected_signed_metadata_key_hmac,
+ std::array<uint8_t, PUBLIC_SIGNING_KEY_SIZE> pub_key,
MatchedCredentialData matched_credential_data);
-private:
+ private:
friend class CredentialSlab;
- np_ffi::internal::V1MatchableCredential internal_;
+ np_ffi::internal::V1MatchableCredential internal_{};
};
-// Representation of a buffer of bytes returned from deserialization APIs
-template <size_t N> class ByteBuffer {
-public:
- // Constructor for a fixed length buffer of bytes from its internal struct
- // data representation consisting of a length and array of unint8_t bytes.
- [[nodiscard]] explicit ByteBuffer(FfiByteBuffer<N> internal)
- : internal_(internal) {}
+// Holds the V0 credential data needed to encrypt advertisements.
+class V0BroadcastCredential {
+ public:
+ V0BroadcastCredential() = delete;
+
+ // Creates a new V0Broadcast credential with the given
+ // key seed and identity token.
+ [[nodiscard]] V0BroadcastCredential(std::array<uint8_t, 32> key_seed,
+ std::array<uint8_t, 14> identity_token);
+
+ private:
+ friend class V0AdvertisementBuilder;
+ np_ffi::internal::V0BroadcastCredential internal_;
+};
+
+// Representation of a buffer of bytes returned from and passed to Rust library
+// deserialization APIs. `N` is the max size of the buffer but its actual
+// contents can be up to N in size.
+template <size_t N>
+class ByteBuffer {
+ public:
+ // Constructs a ByteBuffer from an std::array of bytes
+ template <size_t M>
+ [[nodiscard]] constexpr explicit ByteBuffer(std::array<uint8_t, M> data) {
+ static_assert(N >= M);
+ np_ffi::internal::ByteBuffer<N> internal =
+ np_ffi::internal::ByteBuffer<N>();
+ internal.len = M;
+ std::copy(data.begin(), data.end(), internal.bytes);
+ internal_ = internal;
+ }
+
+ // Creates a ByteBuffer from a std::vector<uint8_t> of bytes, returning an
+ // absl::OutOfRangeError in the case where bytes is too large to fit into the
+ // buffer. On success the returned type contains a copy of the provided bytes.
+ [[nodiscard]] static absl::StatusOr<ByteBuffer<N>> TryFromSpan(
+ std::span<const uint8_t> bytes) {
+ if (bytes.size() > N) {
+ return absl::OutOfRangeError(
+ absl::StrFormat("Provided bytes of length %d will not fit into a "
+ "ByteBuffer<N> of size N=%d",
+ bytes.size(), N));
+ }
+ np_ffi::internal::ByteBuffer<N> internal =
+ np_ffi::internal::ByteBuffer<N>();
+ internal.len = bytes.size();
+ std::copy(std::begin(bytes), std::end(bytes), internal.bytes);
+ return ByteBuffer(internal);
+ }
// Creates a ByteBuffer from a absl::string_view of bytes, returning an
// absl::OutOfRangeError in the case where bytes is too large to fit into the
// buffer. On success the returned type contains a copy of the provided bytes.
- [[nodiscard]] static absl::StatusOr<ByteBuffer<N>>
- CopyFrom(absl::string_view bytes) {
+ [[nodiscard]] static absl::StatusOr<ByteBuffer<N>> TryFromString(
+ absl::string_view bytes) {
if (bytes.length() > N) {
return absl::OutOfRangeError(
absl::StrFormat("Provided bytes of length %d will not fit into a "
@@ -305,7 +340,7 @@ public:
// Helper method to convert the ByteBuffer into a vector. The vector will
// contain a copy of the bytes and won't share the underlying buffer.
- [[nodiscard]] std::vector<uint8_t> ToVector() {
+ [[nodiscard]] std::vector<uint8_t> ToVector() const {
std::vector<uint8_t> result(internal_.bytes,
internal_.bytes + internal_.len);
return result;
@@ -314,64 +349,71 @@ public:
// Helper method to convert the ByteBuffer into a std::string. The returned
// string will contain a copy of the bytes and won't share the underlying
// buffer.
- [[nodiscard]] std::string ToString() {
+ [[nodiscard]] std::string ToString() const {
std::string result;
result.assign(internal_.bytes, internal_.bytes + internal_.len);
return result;
}
+ // Constructor for a fixed length buffer of bytes from its internal struct
+ // data representation consisting of a length and array of unint8_t bytes.
+ [[nodiscard]] explicit ByteBuffer(np_ffi::internal::ByteBuffer<N> internal)
+ : internal_(internal) {}
-private:
+ private:
+ friend class V0AdvertisementBuilder;
friend class V1DataElement;
friend class Deserializer;
np_ffi::internal::ByteBuffer<N> internal_;
};
class RawAdvertisementPayload {
-public:
+ public:
// Creates a RawAdvertisementPayload from a ByteBuffer.
- explicit RawAdvertisementPayload(ByteBuffer<255> bytes) : buffer_(bytes) {}
+ explicit constexpr RawAdvertisementPayload(
+ ByteBuffer<MAX_ADV_PAYLOAD_SIZE> bytes)
+ : buffer_(bytes) {}
- ByteBuffer<255> buffer_;
-
-private:
+ private:
+ ByteBuffer<MAX_ADV_PAYLOAD_SIZE> buffer_;
friend class Deserializer;
};
// A global static Deserializer, configured by GlobalConfig and used to
// deserialize advertisement payloads
class Deserializer {
-public:
+ public:
// Attempts to deserialize an advertisement with the given service-data
// payload (presumed to be under the NP service UUID) using credentials pulled
// from the given credential-book. See np_ffi_deserialize_advertisement in
// np_cpp_ffi_functions.h for more info
- [[nodiscard]] static DeserializeAdvertisementResult
- DeserializeAdvertisement(RawAdvertisementPayload &payload,
- const CredentialBook &credential_book);
+ [[nodiscard]] static DeserializeAdvertisementResult DeserializeAdvertisement(
+ const RawAdvertisementPayload &payload,
+ const CredentialBook &credential_book);
};
// The result type returned from Deserializer::DeserializeAdvertisement(). Can
// be used to further process the advertisement and inspect its contents
class DeserializeAdvertisementResult {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ DeserializeAdvertisementResult() = delete;
DeserializeAdvertisementResult(const DeserializeAdvertisementResult &other) =
delete;
- DeserializeAdvertisementResult &
- operator=(const DeserializeAdvertisementResult &other) = delete;
+ DeserializeAdvertisementResult &operator=(
+ const DeserializeAdvertisementResult &other) = delete;
// Move constructor and move assignment operators
DeserializeAdvertisementResult(
DeserializeAdvertisementResult &&other) noexcept;
- DeserializeAdvertisementResult &
- operator=(DeserializeAdvertisementResult &&other) noexcept;
+ DeserializeAdvertisementResult &operator=(
+ DeserializeAdvertisementResult &&other) noexcept;
// Frees the underlying resources of the result.
~DeserializeAdvertisementResult();
// Returns the DeserializeAdvertisementResultKind of the Result
- [[nodiscard]] DeserializeAdvertisementResultKind GetKind();
+ [[nodiscard]] DeserializeAdvertisementResultKind GetKind() const;
// Casts a `DeserializeAdvertisementResult` to the `V0` variant, panicking in
// the case where the passed value is of a different enum variant. This can
@@ -385,7 +427,7 @@ public:
// is no longer valid.
[[nodiscard]] DeserializedV1Advertisement IntoV1();
-private:
+ private:
friend class Deserializer;
explicit DeserializeAdvertisementResult(
np_ffi::internal::DeserializeAdvertisementResult result)
@@ -397,25 +439,26 @@ private:
// A deserialized V0 advertisement payload
class DeserializedV0Advertisement {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ DeserializedV0Advertisement() = delete;
DeserializedV0Advertisement(const DeserializedV0Advertisement &other) =
delete;
- DeserializedV0Advertisement &
- operator=(const DeserializedV0Advertisement &other) = delete;
+ DeserializedV0Advertisement &operator=(
+ const DeserializedV0Advertisement &other) = delete;
// Move constructor and move assignment operators
DeserializedV0Advertisement(DeserializedV0Advertisement &&other) noexcept;
- DeserializedV0Advertisement &
- operator=(DeserializedV0Advertisement &&other) noexcept;
+ DeserializedV0Advertisement &operator=(
+ DeserializedV0Advertisement &&other) noexcept;
// The destructor which will be called when a DeserializedV0Advertisement
// instance goes out of scope, and will free the underlying resources
~DeserializedV0Advertisement();
// Returns the DeserializedV0AdvertisementKind of the advertisement
- [[nodiscard]] DeserializedV0AdvertisementKind GetKind();
+ [[nodiscard]] DeserializedV0AdvertisementKind GetKind() const;
// Casts a `DeserializedV0Advertisement` to the `Legible` variant, panicking
// in the case where the passed value is of a different enum variant.
@@ -423,7 +466,7 @@ public:
// `LegibleDeserializedV0Advertisement`, and this object is no longer valid.
[[nodiscard]] LegibleDeserializedV0Advertisement IntoLegible();
-private:
+ private:
friend class DeserializeAdvertisementResult;
explicit DeserializedV0Advertisement(
np_ffi::internal::DeserializedV0Advertisement v0_advertisement)
@@ -437,19 +480,20 @@ private:
// either plaintext OR have already been decrypted successfully by a matching
// credential in the provided CredentialBook
class LegibleDeserializedV0Advertisement {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ LegibleDeserializedV0Advertisement() = delete;
LegibleDeserializedV0Advertisement(
const LegibleDeserializedV0Advertisement &other) = delete;
- LegibleDeserializedV0Advertisement &
- operator=(const LegibleDeserializedV0Advertisement &other) = delete;
+ LegibleDeserializedV0Advertisement &operator=(
+ const LegibleDeserializedV0Advertisement &other) = delete;
// Move constructor and move assignment operators
LegibleDeserializedV0Advertisement(
LegibleDeserializedV0Advertisement &&other) noexcept;
- LegibleDeserializedV0Advertisement &
- operator=(LegibleDeserializedV0Advertisement &&other) noexcept;
+ LegibleDeserializedV0Advertisement &operator=(
+ LegibleDeserializedV0Advertisement &&other) noexcept;
// The destructor which will be called when a this instance goes out of scope,
// and will free the underlying parent handle.
@@ -457,13 +501,13 @@ public:
// Returns just the kind of identity (public/encrypted)
// associated with the advertisement
- [[nodiscard]] DeserializedV0IdentityKind GetIdentityKind();
+ [[nodiscard]] DeserializedV0IdentityKind GetIdentityKind() const;
// Returns the number of data elements in the advertisement
- [[nodiscard]] uint8_t GetNumberOfDataElements();
+ [[nodiscard]] uint8_t GetNumberOfDataElements() const;
// Returns just the data-element payload of the advertisement
[[nodiscard]] V0Payload IntoPayload();
-private:
+ private:
friend class DeserializedV0Advertisement;
explicit LegibleDeserializedV0Advertisement(
np_ffi::internal::LegibleDeserializedV0Advertisement
@@ -477,9 +521,10 @@ private:
// A data element payload of a Deserialized V0 Advertisement.
class V0Payload {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying parent handle being freed multiple times.
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ V0Payload() = delete;
V0Payload(const V0Payload &other) = delete;
V0Payload &operator=(const V0Payload &other) = delete;
@@ -492,19 +537,20 @@ public:
// Tries to retrieve the data element at the given index, returns the data
// element if it exists otherwise returns an Error status code
- [[nodiscard]] absl::StatusOr<V0DataElement> TryGetDataElement(uint8_t index);
+ [[nodiscard]] absl::StatusOr<V0DataElement> TryGetDataElement(
+ uint8_t index) const;
// Decrypts the metadata of the credential which matched with this
- // advertisement, or returns an error if the metadata key is invalid and unable
- // to successfully decrypt the metadata.
- [[nodiscard]] absl::StatusOr<std::vector<uint8_t>> DecryptMetadata();
+ // advertisement, or returns an error if the metadata key is invalid and
+ // unable to successfully decrypt the metadata.
+ [[nodiscard]] absl::StatusOr<std::vector<uint8_t>> TryDecryptMetadata() const;
// Gets the details of the identity data element of this payload or returns an
// error if the payload does not have an identity (public advertisement)
[[nodiscard]] absl::StatusOr<DeserializedV0IdentityDetails>
- GetIdentityDetails();
+ TryGetIdentityDetails() const;
-private:
+ private:
friend class LegibleDeserializedV0Advertisement;
explicit V0Payload(np_ffi::internal::V0Payload v0_payload)
: v0_payload_(v0_payload), moved_(false) {}
@@ -513,19 +559,44 @@ private:
bool moved_;
};
-// A single deserialized V0 data element
+// A Tx Power [transmission power] between -100dBm and 20dBm
+class TxPower {
+ public:
+ TxPower() = delete;
+
+ // Gets the value of this tx power as a signed byte.
+ [[nodiscard]] int8_t GetAsI8() const;
+
+ // Attempts to construct a tx power with the given value contained
+ // in a signed byte. If the number is not within the representable
+ // range, this method will return an invalid argument error.
+ [[nodiscard]] static absl::StatusOr<TxPower> TryBuildFromI8(int8_t value);
+
+ private:
+ friend class V0DataElement;
+ explicit TxPower(np_ffi::internal::TxPower tx_power) : tx_power_(tx_power) {}
+ np_ffi::internal::TxPower tx_power_;
+};
+
+// A single V0 data element
class V0DataElement {
-public:
+ public:
// Yields the V0DataElementKind of the data element
- [[nodiscard]] V0DataElementKind GetKind();
+ [[nodiscard]] V0DataElementKind GetKind() const;
// Casts the V0DataElement into the TxPower variant, panicking in the case
// where the data element is of a different enum variant
- [[nodiscard]] TxPower AsTxPower();
+ [[nodiscard]] TxPower AsTxPower() const;
// Casts the V0DataElement into the Actions variant, panicking in the case
// where the data element is of a different enum variant
- [[nodiscard]] V0Actions AsActions();
+ [[nodiscard]] V0Actions AsActions() const;
+
+ // Constructs a Tx Power V0 data element
+ explicit V0DataElement(TxPower tx_power);
+ // Constructs an Actions V0 data element
+ explicit V0DataElement(V0Actions actions);
-private:
+ private:
+ friend class V0AdvertisementBuilder;
friend class V0Payload;
explicit V0DataElement(np_ffi::internal::V0DataElement v0_data_element)
: v0_data_element_(v0_data_element) {}
@@ -534,19 +605,28 @@ private:
// A V0 Actions Data Element
class V0Actions {
-public:
+ public:
+ V0Actions() = delete;
+
// Gets the V0 Action bits as represented by a u32 where the last 8 bits are
// always 0 since V0 actions can only hold up to 24 bits.
- [[nodiscard]] uint32_t GetAsU32();
+ [[nodiscard]] uint32_t GetAsU32() const;
/// Return whether a boolean action type is present in this data element
- [[nodiscard]] bool HasAction(BooleanActionType action);
+ [[nodiscard]] bool HasAction(ActionType action) const;
+
+ /// Attempts to set the given action bit to the given boolean value.
+ /// This operation may fail with an invalid argument error
+ /// if the requested action bit may not be set given the encoding
+ /// of the containing advertisement.
+ /// In this case, the action bits will be unaltered by this call.
+ absl::Status TrySetAction(ActionType action, bool value);
- /// Gets the 4 bit context sync sequence number as a uint8_t from this data
- /// element
- [[nodiscard]] uint8_t GetContextSyncSequenceNumber();
+ // Constructs an all-zeroed V0 actions DE for the given advertisement builder
+ // kind.
+ [[nodiscard]] static V0Actions BuildNewZeroed(AdvertisementBuilderKind kind);
-private:
+ private:
friend class V0DataElement;
explicit V0Actions(np_ffi::internal::V0Actions actions) : actions_(actions) {}
np_ffi::internal::V0Actions actions_;
@@ -554,32 +634,33 @@ private:
// A deserialized V1 Advertisement payload
class DeserializedV1Advertisement {
-public:
- // Don't allow copy constructor or copy assignment, since that would result in
- // the underlying handle being freed multiple times
+ public:
+ // Don't allow copy constructor, copy-assignment or default constructor, since
+ // this class wraps a handle to externally allocated resources.
+ DeserializedV1Advertisement() = delete;
DeserializedV1Advertisement(const DeserializedV1Advertisement &other) =
delete;
- DeserializedV1Advertisement &
- operator=(const DeserializedV1Advertisement &other) = delete;
+ DeserializedV1Advertisement &operator=(
+ const DeserializedV1Advertisement &other) = delete;
// Move constructor and move assignment operators
DeserializedV1Advertisement(DeserializedV1Advertisement &&other) noexcept;
- DeserializedV1Advertisement &
- operator=(DeserializedV1Advertisement &&other) noexcept;
+ DeserializedV1Advertisement &operator=(
+ DeserializedV1Advertisement &&other) noexcept;
// Gets the number of legible sections on a deserialized V1 advertisement.
// This is usable as an iteration bound for the section_index of TryGetSection
- [[nodiscard]] uint8_t GetNumLegibleSections();
+ [[nodiscard]] uint8_t GetNumLegibleSections() const;
// Gets the number of sections on a deserialized V1 advertisement which
// were unable to be decrypted with the credentials that the receiver
// possesses
- [[nodiscard]] uint8_t GetNumUndecryptableSections();
+ [[nodiscard]] uint8_t GetNumUndecryptableSections() const;
// Tries to get the section with the given index in a deserialized V1
// advertisement. Returns a error code in the result of an invalid index
- [[nodiscard]] absl::StatusOr<DeserializedV1Section>
- TryGetSection(uint8_t section_index);
+ [[nodiscard]] absl::StatusOr<DeserializedV1Section> TryGetSection(
+ uint8_t section_index) const;
-private:
+ private:
friend class DeserializeAdvertisementResult;
explicit DeserializedV1Advertisement(
np_ffi::internal::DeserializedV1Advertisement v1_advertisement);
@@ -590,33 +671,35 @@ private:
// A Deserialized V1 Section of an advertisement
class DeserializedV1Section {
-public:
+ public:
// Returns the number of data elements present in the section
- [[nodiscard]] uint8_t NumberOfDataElements();
+ [[nodiscard]] uint8_t NumberOfDataElements() const;
// Returns the DeserializedV1IdentityKind of the identity
- [[nodiscard]] DeserializedV1IdentityKind GetIdentityKind();
+ [[nodiscard]] DeserializedV1IdentityKind GetIdentityKind() const;
// Tries to get the data element in the section at the given index
- [[nodiscard]] absl::StatusOr<V1DataElement> TryGetDataElement(uint8_t index);
+ [[nodiscard]] absl::StatusOr<V1DataElement> TryGetDataElement(
+ uint8_t index) const;
// Decrypts the metadata of the credential which matched with this section
- [[nodiscard]] absl::StatusOr<std::vector<uint8_t>> DecryptMetadata();
+ // or returns an error in the case that the metadata could not be decrypted
+ [[nodiscard]] absl::StatusOr<std::vector<uint8_t>> TryDecryptMetadata() const;
// Gets the details of the identity data element of this section or returns an
- // error if the section does not conatin an identity (public section)
+ // error if the section does not contain an identity (public section)
[[nodiscard]] absl::StatusOr<DeserializedV1IdentityDetails>
- GetIdentityDetails();
+ GetIdentityDetails() const;
// Attempts to derive a 16-byte DE salt for a DE in this section with the
// given DE offset. This operation may fail if the passed offset is 255
// (causes overflow) or if the section is leveraging a public identity, and
// hence, doesn't have an associated salt. The offset should come from a
// particular deserialized v1 de via `V1DataElement::GetOffset()`
- [[nodiscard]] absl::StatusOr<std::array<uint8_t, 16>>
- DeriveSaltForOffset(uint8_t offset);
+ [[nodiscard]] absl::StatusOr<std::array<uint8_t, DERIVED_SALT_SIZE>>
+ DeriveSaltForOffset(uint8_t offset) const;
-private:
+ private:
friend class DeserializedV1Advertisement;
explicit DeserializedV1Section(
np_ffi::internal::DeserializedV1Section section,
@@ -631,21 +714,75 @@ private:
// A V1 Data Element
class V1DataElement {
-public:
+ public:
// Yields the unsigned 32-bit integer V1 DE type code
[[nodiscard]] uint32_t GetDataElementTypeCode() const;
// Yields the payload bytes of the data element
- [[nodiscard]] ByteBuffer<127> GetPayload() const;
+ [[nodiscard]] ByteBuffer<MAX_V1_DE_PAYLOAD_SIZE> GetPayload() const;
/// Gets the offset for this V1 data element.
[[nodiscard]] uint8_t GetOffset() const;
-private:
+ private:
friend class DeserializedV1Section;
explicit V1DataElement(np_ffi::internal::V1DataElement v1_data_element)
: v1_data_element_(v1_data_element) {}
np_ffi::internal::V1DataElement v1_data_element_;
};
-} // namespace nearby_protocol
+// A builder for V0 advertisements
+class V0AdvertisementBuilder {
+ public:
+ V0AdvertisementBuilder() = delete;
+ // Don't allow copy constructor or copy assignment, since that would result in
+ // the underlying handle being freed multiple times
+ V0AdvertisementBuilder(const V0AdvertisementBuilder &other) = delete;
+ V0AdvertisementBuilder &operator=(const V0AdvertisementBuilder &other) =
+ delete;
+
+ // Move constructor and move assignment operators
+ V0AdvertisementBuilder(V0AdvertisementBuilder &&other) noexcept;
+ V0AdvertisementBuilder &operator=(V0AdvertisementBuilder &&other) noexcept;
+
+ // Frees the underlying resources of the adv builder.
+ ~V0AdvertisementBuilder();
+
+ // Tries to add the given data element to the advertisement builder.
+ // May fail with:
+ // - An invalid argument code if:
+ // - The adv builder handle is invalid
+ // OR
+ // - The identity type of the adv builder is invalid
+ // for the data element we're attempting to add.
+ // - A resource exhausted error if there's no remaining adv space.
+ absl::Status TryAddDE(V0DataElement de);
+
+ // Attempts to serialize the contents of the advertisement
+ // builder to bytes. This operation will always result in the
+ // contents behind the handle for this instance being deallocated.
+ //
+ // This operation may return an out-of-range error in the case
+ // where the advertisement contents are of a size inappropriate
+ // for LDT encryption in an encrypted V0 advertisement.
+ [[nodiscard]] absl::StatusOr<ByteBuffer<24>> TrySerialize();
+
+ // Creates a new V0 advertisement builder for a public advertisement,
+ // or returns a Status code on failure.
+ [[nodiscard]] static V0AdvertisementBuilder CreatePublic();
+
+ // Creates a new V0 advertisement builder for an encrypted advertisement,
+ // or returns a Status code on failure.
+ [[nodiscard]] static V0AdvertisementBuilder CreateEncrypted(
+ V0BroadcastCredential broadcast_cred, std::array<uint8_t, 2> salt);
+
+ private:
+ explicit V0AdvertisementBuilder(
+ np_ffi::internal::V0AdvertisementBuilder adv_builder)
+ : adv_builder_(adv_builder), moved_(false) {}
+
+ np_ffi::internal::V0AdvertisementBuilder adv_builder_;
+ bool moved_;
+};
+
+} // namespace nearby_protocol
-#endif // NEARBY_PRESENCE_NP_CPP_FFI_INCLUDE_NP_PROTOCOL_H_
+#endif // NEARBY_PRESENCE_NP_CPP_FFI_INCLUDE_NP_PROTOCOL_H_
diff --git a/nearby/presence/np_cpp_ffi/nearby_protocol.cc b/nearby/presence/np_cpp_ffi/nearby_protocol.cc
index c2f8566..510844a 100644
--- a/nearby/presence/np_cpp_ffi/nearby_protocol.cc
+++ b/nearby/presence/np_cpp_ffi/nearby_protocol.cc
@@ -12,29 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "include/nearby_protocol.h"
-
+#include "nearby_protocol.h"
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+#include <span>
+#include <utility>
+#include <vector>
+
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
#include "np_cpp_ffi_functions.h"
-
-#ifdef __FILE_NAME__
-#define __ASSERT_FILE_NAME __FILE_NAME__
-#else /* __FILE_NAME__ */
-#define __ASSERT_FILE_NAME __FILE__
-#endif /* __FILE_NAME__ */
+#include "np_cpp_ffi_types.h"
namespace nearby_protocol {
-static void panic_handler(PanicReason reason);
+void panic_handler(PanicReason reason);
struct PanicHandler {
- void (* handler)(PanicReason);
+ void (*handler)(PanicReason);
bool set_by_client;
};
-static PanicHandler gPanicHandler = PanicHandler{panic_handler, false};
+PanicHandler gPanicHandler = PanicHandler{panic_handler, false};
// C++ layer internal panic handler
-static void panic_handler(PanicReason reason) {
+void panic_handler(PanicReason reason) {
// Give clients a chance to use their own panic handler, but if they don't
// terminate the process we will make sure it happens.
if (gPanicHandler.set_by_client) {
@@ -43,8 +50,8 @@ static void panic_handler(PanicReason reason) {
std::abort();
}
-static void _assert_panic(bool condition, const char* func, const char* file,
- int line) {
+void _assert_panic(bool condition, const char* func, const char* file,
+ int line) {
if (!condition) {
std::cout << "Assert failed: \n function: " << func << "\n file: " << file
<< "\n line: " << line << "\n";
@@ -52,9 +59,9 @@ static void _assert_panic(bool condition, const char* func, const char* file,
}
}
-#define assert_panic(e) _assert_panic(e, __func__, __ASSERT_FILE_NAME, __LINE__)
+#define assert_panic(e) _assert_panic(e, __func__, __FILE__, __LINE__)
-bool GlobalConfig::SetPanicHandler(void (* handler)(PanicReason)) {
+bool GlobalConfig::SetPanicHandler(void (*handler)(PanicReason)) {
if (!gPanicHandler.set_by_client) {
gPanicHandler.handler = handler;
gPanicHandler.set_by_client = true;
@@ -63,50 +70,17 @@ bool GlobalConfig::SetPanicHandler(void (* handler)(PanicReason)) {
return false;
}
-void GlobalConfig::SetNumShards(uint8_t num_shards) {
+void GlobalConfig::SetNumShards(const uint8_t num_shards) {
np_ffi::internal::np_ffi_global_config_set_num_shards(num_shards);
}
-void GlobalConfig::SetMaxNumCredentialSlabs(uint32_t max_num_credential_slabs) {
- np_ffi::internal::np_ffi_global_config_set_max_num_credential_slabs(
- max_num_credential_slabs);
-}
-
-void GlobalConfig::SetMaxNumCredentialBooks(uint32_t max_num_credential_books) {
- np_ffi::internal::np_ffi_global_config_set_max_num_credential_books(
- max_num_credential_books);
+CurrentHandleAllocations GlobalConfig::GetCurrentHandleAllocationCount() {
+ return np_ffi::internal::np_ffi_global_config_get_current_allocation_count();
}
-void GlobalConfig::SetMaxNumDeserializedV0Advertisements(
- uint32_t max_num_deserialized_v0_advertisements) {
- np_ffi::internal::
- np_ffi_global_config_set_max_num_deserialized_v0_advertisements(
- max_num_deserialized_v0_advertisements);
-}
-
-void GlobalConfig::SetMaxNumDeserializedV1Advertisements(
- uint32_t max_num_deserialized_v1_advertisements) {
- np_ffi::internal::
- np_ffi_global_config_set_max_num_deserialized_v1_advertisements(
- max_num_deserialized_v1_advertisements);
-}
-
-absl::StatusOr<CredentialSlab> CredentialSlab::TryCreate() {
- auto result = np_ffi::internal::np_ffi_create_credential_slab();
- auto kind = np_ffi::internal::np_ffi_CreateCredentialSlabResult_kind(result);
-
- switch (kind) {
- case CreateCredentialSlabResultKind::Success: {
- auto slab = CredentialSlab(
- np_ffi::internal::np_ffi_CreateCredentialSlabResult_into_SUCCESS(
- result));
- return slab;
- }
- case CreateCredentialSlabResultKind::NoSpaceLeft: {
- return absl::ResourceExhaustedError(
- "No space left to create credential slab");
- }
- }
+CredentialSlab::CredentialSlab() {
+ this->credential_slab_ = np_ffi::internal::np_ffi_create_credential_slab();
+ this->moved_ = false;
}
CredentialSlab::~CredentialSlab() {
@@ -140,59 +114,46 @@ CredentialSlab& CredentialSlab::operator=(CredentialSlab&& other) noexcept {
return *this;
}
-absl::Status CredentialSlab::AddV0Credential(V0MatchableCredential v0_cred) {
+void CredentialSlab::AddV0Credential(const V0MatchableCredential v0_cred) {
assert_panic(!this->moved_);
auto result = np_ffi::internal::np_ffi_CredentialSlab_add_v0_credential(
this->credential_slab_, v0_cred.internal_);
- switch (result) {
- case AddCredentialToSlabResult::Success: {
- return absl::OkStatus();
- }
- case AddCredentialToSlabResult::InvalidHandle: {
- return absl::InvalidArgumentError(
- "invalid credential slab handle provided");
- }
- }
+ // Add V0 is infallible since the handle is guaranteed to be correct by the
+ // C++ wrapper
+ assert_panic(result == AddV0CredentialToSlabResult::Success);
}
-absl::Status CredentialSlab::AddV1Credential(V1MatchableCredential v1_cred) {
+absl::Status CredentialSlab::AddV1Credential(
+ const V1MatchableCredential v1_cred) {
assert_panic(!this->moved_);
auto result = np_ffi::internal::np_ffi_CredentialSlab_add_v1_credential(
this->credential_slab_, v1_cred.internal_);
switch (result) {
- case AddCredentialToSlabResult::Success: {
+ case AddV1CredentialToSlabResult::Success: {
return absl::OkStatus();
}
- case AddCredentialToSlabResult::InvalidHandle: {
+ case AddV1CredentialToSlabResult::InvalidHandle: {
return absl::InvalidArgumentError(
"invalid credential slab handle provided");
}
+ case AddV1CredentialToSlabResult::InvalidPublicKeyBytes: {
+ return absl::InvalidArgumentError(
+ "Invalid public key bytes in credential");
+ }
}
}
-absl::StatusOr<CredentialBook>
-CredentialBook::TryCreateFromSlab(CredentialSlab& slab) {
+CredentialBook::CredentialBook(CredentialSlab& slab) {
assert_panic(!slab.moved_);
auto result = np_ffi::internal::np_ffi_create_credential_book_from_slab(
slab.credential_slab_);
auto kind = np_ffi::internal::np_ffi_CreateCredentialBookResult_kind(result);
- switch (kind) {
- case CreateCredentialBookResultKind::Success: {
- auto book =
- np_ffi::internal::np_ffi_CreateCredentialBookResult_into_SUCCESS(
- result);
- slab.moved_ = true;
- return CredentialBook(book);
- }
- case CreateCredentialBookResultKind::NoSpaceLeft: {
- return absl::ResourceExhaustedError(
- "No space left to create credential book");
- }
- case CreateCredentialBookResultKind::InvalidSlabHandle: {
- return absl::NotFoundError(
- "The slab referenced by the given handle was not found.");
- }
- }
+ // Handle is guaranteed to be valid by the C++ wrapper
+ assert_panic(kind == CreateCredentialBookResultKind::Success);
+ slab.moved_ = true;
+ this->credential_book_ =
+ np_ffi::internal::np_ffi_CreateCredentialBookResult_into_SUCCESS(result);
+ this->moved_ = false;
}
CredentialBook::~CredentialBook() {
@@ -226,16 +187,17 @@ CredentialBook& CredentialBook::operator=(CredentialBook&& other) noexcept {
return *this;
}
-DeserializeAdvertisementResult
-Deserializer::DeserializeAdvertisement(RawAdvertisementPayload& payload,
- const CredentialBook& credential_book) {
+DeserializeAdvertisementResult Deserializer::DeserializeAdvertisement(
+ const RawAdvertisementPayload& payload,
+ const CredentialBook& credential_book) {
assert_panic(!credential_book.moved_);
auto result = np_ffi::internal::np_ffi_deserialize_advertisement(
{payload.buffer_.internal_}, credential_book.credential_book_);
return DeserializeAdvertisementResult(result);
}
-DeserializeAdvertisementResultKind DeserializeAdvertisementResult::GetKind() {
+DeserializeAdvertisementResultKind DeserializeAdvertisementResult::GetKind()
+ const {
assert_panic(!this->moved_);
return np_ffi::internal::np_ffi_DeserializeAdvertisementResult_kind(result_);
}
@@ -326,7 +288,7 @@ DeserializedV0Advertisement::~DeserializedV0Advertisement() {
}
np_ffi::internal::DeserializedV0AdvertisementKind
-DeserializedV0Advertisement::GetKind() {
+DeserializedV0Advertisement::GetKind() const {
assert_panic(!this->moved_);
return np_ffi::internal::np_ffi_DeserializedV0Advertisement_kind(
v0_advertisement_);
@@ -377,20 +339,20 @@ LegibleDeserializedV0Advertisement::~LegibleDeserializedV0Advertisement() {
}
}
-DeserializedV0IdentityKind
-LegibleDeserializedV0Advertisement::GetIdentityKind() {
+DeserializedV0IdentityKind LegibleDeserializedV0Advertisement::GetIdentityKind()
+ const {
assert_panic(!this->moved_);
auto result = np_ffi::internal::
- np_ffi_LegibleDeserializedV0Advertisement_get_identity_kind(
- legible_v0_advertisement_);
+ np_ffi_LegibleDeserializedV0Advertisement_get_identity_kind(
+ legible_v0_advertisement_);
return result;
}
-uint8_t LegibleDeserializedV0Advertisement::GetNumberOfDataElements() {
+uint8_t LegibleDeserializedV0Advertisement::GetNumberOfDataElements() const {
assert_panic(!this->moved_);
return np_ffi::internal::
- np_ffi_LegibleDeserializedV0Advertisement_get_num_des(
- legible_v0_advertisement_);
+ np_ffi_LegibleDeserializedV0Advertisement_get_num_des(
+ legible_v0_advertisement_);
}
V0Payload LegibleDeserializedV0Advertisement::IntoPayload() {
@@ -431,7 +393,8 @@ V0Payload::~V0Payload() {
}
}
-absl::StatusOr<V0DataElement> V0Payload::TryGetDataElement(uint8_t index) {
+absl::StatusOr<V0DataElement> V0Payload::TryGetDataElement(
+ const uint8_t index) const {
assert_panic(!this->moved_);
auto result = np_ffi::internal::np_ffi_V0Payload_get_de(v0_payload_, index);
auto kind = np_ffi::internal::np_ffi_GetV0DEResult_kind(result);
@@ -446,8 +409,8 @@ absl::StatusOr<V0DataElement> V0Payload::TryGetDataElement(uint8_t index) {
}
}
-static absl::StatusOr<std::vector<uint8_t>>
-MetadataResultToVec(np_ffi::internal::DecryptMetadataResult decrypt_result) {
+absl::StatusOr<std::vector<uint8_t>> MetadataResultToVec(
+ np_ffi::internal::DecryptMetadataResult decrypt_result) {
auto kind =
np_ffi::internal::np_ffi_DecryptMetadataResult_kind(decrypt_result);
switch (kind) {
@@ -461,8 +424,8 @@ MetadataResultToVec(np_ffi::internal::DecryptMetadataResult decrypt_result) {
// The handle is guaranteed to be valid by the C++ wrapper so this should
// never fail
assert_panic(np_ffi::internal::np_ffi_GetMetadataBufferPartsResult_kind(
- parts_result) ==
- np_ffi::internal::GetMetadataBufferPartsResultKind::Success);
+ parts_result) ==
+ np_ffi::internal::GetMetadataBufferPartsResultKind::Success);
auto parts =
np_ffi::internal::np_ffi_GetMetadataBufferPartsResult_into_SUCCESS(
parts_result);
@@ -473,23 +436,26 @@ MetadataResultToVec(np_ffi::internal::DecryptMetadataResult decrypt_result) {
auto deallocate_result =
np_ffi::internal::np_ffi_deallocate_DecryptedMetadata(metadata);
assert_panic(deallocate_result ==
- np_ffi::internal::DeallocateResult::Success);
+ np_ffi::internal::DeallocateResult::Success);
return result;
}
case np_ffi::internal::DecryptMetadataResultKind::Error: {
- return absl::InvalidArgumentError("Invalid V0 payload handle");
+ return absl::InvalidArgumentError(
+ "Decrypt attempt failed, identity is missing or invalid");
}
}
}
-absl::StatusOr<DeserializedV0IdentityDetails> V0Payload::GetIdentityDetails() {
+absl::StatusOr<DeserializedV0IdentityDetails> V0Payload::TryGetIdentityDetails()
+ const {
assert_panic(!this->moved_);
auto result = np_ffi::internal::np_ffi_V0Payload_get_identity_details(
this->v0_payload_);
auto kind = np_ffi::internal::np_ffi_GetV0IdentityDetailsResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV0IdentityDetailsResultKind::Error: {
- return absl::InvalidArgumentError("Invalid handle");
+ return absl::InvalidArgumentError(
+ "Identity details not available for public advertisements");
}
case np_ffi::internal::GetV0IdentityDetailsResultKind::Success: {
return np_ffi::internal::np_ffi_GetV0IdentityDetailsResult_into_SUCCESS(
@@ -498,41 +464,91 @@ absl::StatusOr<DeserializedV0IdentityDetails> V0Payload::GetIdentityDetails() {
}
}
-absl::StatusOr<std::vector<uint8_t>> V0Payload::DecryptMetadata() {
+absl::StatusOr<std::vector<uint8_t>> V0Payload::TryDecryptMetadata() const {
assert_panic(!this->moved_);
auto decrypt_result =
np_ffi::internal::np_ffi_V0Payload_decrypt_metadata(this->v0_payload_);
return MetadataResultToVec(decrypt_result);
}
-V0DataElementKind V0DataElement::GetKind() {
+V0DataElementKind V0DataElement::GetKind() const {
return np_ffi::internal::np_ffi_V0DataElement_kind(v0_data_element_);
}
-TxPower V0DataElement::AsTxPower() {
- return np_ffi::internal::np_ffi_V0DataElement_into_TX_POWER(v0_data_element_);
+TxPower V0DataElement::AsTxPower() const {
+ return TxPower(
+ np_ffi::internal::np_ffi_V0DataElement_into_TX_POWER(v0_data_element_));
}
-V0Actions V0DataElement::AsActions() {
+V0Actions V0DataElement::AsActions() const {
auto internal =
np_ffi::internal::np_ffi_V0DataElement_into_ACTIONS(v0_data_element_);
return V0Actions(internal);
}
-uint32_t V0Actions::GetAsU32() {
+V0DataElement::V0DataElement(TxPower tx_power) {
+ v0_data_element_ =
+ np_ffi::internal::np_ffi_TxPower_into_V0DataElement(tx_power.tx_power_);
+}
+
+V0DataElement::V0DataElement(V0Actions actions) {
+ v0_data_element_ =
+ np_ffi::internal::np_ffi_V0Actions_into_V0DataElement(actions.actions_);
+}
+
+uint32_t V0Actions::GetAsU32() const {
return np_ffi::internal::np_ffi_V0Actions_as_u32(actions_);
}
-bool V0Actions::HasAction(BooleanActionType action) {
+bool V0Actions::HasAction(ActionType action) const {
return np_ffi::internal::np_ffi_V0Actions_has_action(actions_, action);
}
-uint8_t V0Actions::GetContextSyncSequenceNumber() {
- return np_ffi::internal::np_ffi_V0Actions_get_context_sync_sequence_number(
- actions_);
+absl::Status V0Actions::TrySetAction(ActionType action, bool value) {
+ auto result =
+ np_ffi::internal::np_ffi_V0Actions_set_action(actions_, action, value);
+ auto kind = np_ffi::internal::np_ffi_SetV0ActionResult_kind(result);
+ switch (kind) {
+ case np_ffi::internal::SetV0ActionResultKind::Success: {
+ actions_ =
+ np_ffi::internal::np_ffi_SetV0ActionResult_into_SUCCESS(result);
+ return absl::OkStatus();
+ }
+ case np_ffi::internal::SetV0ActionResultKind::Error: {
+ actions_ = np_ffi::internal::np_ffi_SetV0ActionResult_into_ERROR(result);
+ return absl::InvalidArgumentError(
+ "The requested action bit may not be set for the requested adv "
+ "encoding");
+ }
+ }
+}
+
+V0Actions V0Actions::BuildNewZeroed(AdvertisementBuilderKind kind) {
+ auto actions = np_ffi::internal::np_ffi_build_new_zeroed_V0Actions(kind);
+ return V0Actions(actions);
+}
+
+int8_t TxPower::GetAsI8() const {
+ return np_ffi::internal::np_ffi_TxPower_as_signed_byte(tx_power_);
}
-// This is called after all references to the shared_ptr have gone out of scope
+absl::StatusOr<TxPower> TxPower::TryBuildFromI8(int8_t value) {
+ auto result = np_ffi::internal::np_ffi_TxPower_build_from_signed_byte(value);
+ auto kind = np_ffi::internal::np_ffi_BuildTxPowerResult_kind(result);
+ switch (kind) {
+ case np_ffi::internal::BuildTxPowerResultKind::Success: {
+ return TxPower(
+ np_ffi::internal::np_ffi_BuildTxPowerResult_into_SUCCESS(result));
+ }
+ case np_ffi::internal::BuildTxPowerResultKind::OutOfRange: {
+ return absl::InvalidArgumentError(
+ "Could not build a tx power for the requested byte value.");
+ }
+ }
+}
+
+// This is called after all references to the shared_ptr have gone out of
+// scope
auto DeallocateV1Adv(
np_ffi::internal::DeserializedV1Advertisement* v1_advertisement) {
auto result =
@@ -563,22 +579,22 @@ DeserializedV1Advertisement& DeserializedV1Advertisement::operator=(
}
// V1 Stuff
-uint8_t DeserializedV1Advertisement::GetNumLegibleSections() {
+uint8_t DeserializedV1Advertisement::GetNumLegibleSections() const {
assert_panic(this->v1_advertisement_ != nullptr);
return np_ffi::internal::
- np_ffi_DeserializedV1Advertisement_get_num_legible_sections(
- *v1_advertisement_);
+ np_ffi_DeserializedV1Advertisement_get_num_legible_sections(
+ *v1_advertisement_);
}
-uint8_t DeserializedV1Advertisement::GetNumUndecryptableSections() {
+uint8_t DeserializedV1Advertisement::GetNumUndecryptableSections() const {
assert_panic(this->v1_advertisement_ != nullptr);
return np_ffi::internal::
- np_ffi_DeserializedV1Advertisement_get_num_undecryptable_sections(
- *v1_advertisement_);
+ np_ffi_DeserializedV1Advertisement_get_num_undecryptable_sections(
+ *v1_advertisement_);
}
absl::StatusOr<DeserializedV1Section>
-DeserializedV1Advertisement::TryGetSection(uint8_t section_index) {
+DeserializedV1Advertisement::TryGetSection(const uint8_t section_index) const {
assert_panic(this->v1_advertisement_ != nullptr);
auto result =
np_ffi::internal::np_ffi_DeserializedV1Advertisement_get_section(
@@ -596,23 +612,24 @@ DeserializedV1Advertisement::TryGetSection(uint8_t section_index) {
}
}
-uint8_t DeserializedV1Section::NumberOfDataElements() {
+uint8_t DeserializedV1Section::NumberOfDataElements() const {
return np_ffi::internal::np_ffi_DeserializedV1Section_get_num_des(section_);
}
-DeserializedV1IdentityKind DeserializedV1Section::GetIdentityKind() {
+DeserializedV1IdentityKind DeserializedV1Section::GetIdentityKind() const {
return np_ffi::internal::np_ffi_DeserializedV1Section_get_identity_kind(
section_);
}
-absl::StatusOr<V1DataElement>
-DeserializedV1Section::TryGetDataElement(uint8_t index) {
+absl::StatusOr<V1DataElement> DeserializedV1Section::TryGetDataElement(
+ const uint8_t index) const {
auto result =
np_ffi::internal::np_ffi_DeserializedV1Section_get_de(section_, index);
auto kind = np_ffi::internal::np_ffi_GetV1DEResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV1DEResultKind::Error: {
- return absl::OutOfRangeError("Invalid data element index for this section");
+ return absl::OutOfRangeError(
+ "Invalid data element index for this section");
}
case np_ffi::internal::GetV1DEResultKind::Success: {
return V1DataElement(
@@ -621,7 +638,8 @@ DeserializedV1Section::TryGetDataElement(uint8_t index) {
}
}
-absl::StatusOr<std::vector<uint8_t>> DeserializedV1Section::DecryptMetadata() {
+absl::StatusOr<std::vector<uint8_t>> DeserializedV1Section::TryDecryptMetadata()
+ const {
assert_panic(this->owning_v1_advertisement_ != nullptr);
auto decrypt_result =
np_ffi::internal::np_ffi_DeserializedV1Section_decrypt_metadata(
@@ -630,7 +648,7 @@ absl::StatusOr<std::vector<uint8_t>> DeserializedV1Section::DecryptMetadata() {
}
absl::StatusOr<DeserializedV1IdentityDetails>
-DeserializedV1Section::GetIdentityDetails() {
+DeserializedV1Section::GetIdentityDetails() const {
assert_panic(this->owning_v1_advertisement_ != nullptr);
auto result =
np_ffi::internal::np_ffi_DeserializedV1Section_get_identity_details(
@@ -638,7 +656,8 @@ DeserializedV1Section::GetIdentityDetails() {
auto kind = np_ffi::internal::np_ffi_GetV1IdentityDetailsResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV1IdentityDetailsResultKind::Error: {
- return absl::InvalidArgumentError("Invalid handle");
+ return absl::InvalidArgumentError(
+ "Identity details are not available for public advertisements");
}
case np_ffi::internal::GetV1IdentityDetailsResultKind::Success: {
return np_ffi::internal::np_ffi_GetV1IdentityDetailsResult_into_SUCCESS(
@@ -647,19 +666,19 @@ DeserializedV1Section::GetIdentityDetails() {
}
}
-absl::StatusOr<std::array<uint8_t, 16>> DeserializedV1Section::DeriveSaltForOffset(
- uint8_t offset) {
- auto result =
- np_ffi::internal::np_ffi_DeserializedV1Section_derive_16_byte_salt_for_offset(
- this->section_,
- offset);
+absl::StatusOr<std::array<uint8_t, DERIVED_SALT_SIZE>>
+DeserializedV1Section::DeriveSaltForOffset(const uint8_t offset) const {
+ auto result = np_ffi::internal::
+ np_ffi_DeserializedV1Section_derive_16_byte_salt_for_offset(
+ this->section_, offset);
auto kind = np_ffi::internal::np_ffi_GetV1DE16ByteSaltResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV1DE16ByteSaltResultKind::Error: {
return absl::InvalidArgumentError("Failed to derive salt for offset");
}
case np_ffi::internal::GetV1DE16ByteSaltResultKind::Success: {
- auto buffer = np_ffi::internal::np_ffi_GetV1DE16ByteSaltResult_into_SUCCESS(result);
+ auto buffer =
+ np_ffi::internal::np_ffi_GetV1DE16ByteSaltResult_into_SUCCESS(result);
return std::to_array(buffer._0);
}
}
@@ -671,7 +690,7 @@ uint32_t V1DataElement::GetDataElementTypeCode() const {
.de_type);
}
-ByteBuffer<127> V1DataElement::GetPayload() const {
+ByteBuffer<MAX_V1_DE_PAYLOAD_SIZE> V1DataElement::GetPayload() const {
return ByteBuffer(
np_ffi::internal::np_ffi_V1DataElement_to_generic(this->v1_data_element_)
.payload);
@@ -679,44 +698,166 @@ ByteBuffer<127> V1DataElement::GetPayload() const {
uint8_t V1DataElement::GetOffset() const {
return np_ffi::internal::np_ffi_V1DataElement_to_generic(
- this->v1_data_element_)
+ this->v1_data_element_)
.offset;
}
MatchedCredentialData::MatchedCredentialData(
- uint32_t cred_id, std::span<uint8_t> metadata_bytes) {
+ const uint32_t cred_id, std::span<const uint8_t> metadata_bytes) {
this->data_ = {cred_id, metadata_bytes.data(), metadata_bytes.size()};
}
-template<typename T, size_t N>
-static void CopyToRawArray(T (& dest)[N], const std::array<T, N>& src) {
+template <typename T, size_t N>
+void CopyToRawArray(T (&dest)[N], const std::array<T, N>& src) {
memcpy(dest, src.data(), sizeof(T) * N);
}
V0MatchableCredential::V0MatchableCredential(
- std::array<uint8_t, 32> key_seed,
- std::array<uint8_t, 32> legacy_metadata_key_hmac,
- MatchedCredentialData matched_credential_data) {
+ const std::array<uint8_t, 32> key_seed,
+ const std::array<uint8_t, 32> legacy_metadata_key_hmac,
+ const MatchedCredentialData matched_credential_data) {
np_ffi::internal::V0DiscoveryCredential discovery_cred{};
CopyToRawArray(discovery_cred.key_seed, key_seed);
- CopyToRawArray(discovery_cred.legacy_metadata_key_hmac,
- legacy_metadata_key_hmac);
+ CopyToRawArray(discovery_cred.identity_token_hmac, legacy_metadata_key_hmac);
this->internal_ = {discovery_cred, matched_credential_data.data_};
}
V1MatchableCredential::V1MatchableCredential(
- std::array<uint8_t, 32> key_seed,
- std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac,
- std::array<uint8_t, 32> expected_signed_metadata_key_hmac,
- std::array<uint8_t, 32> pub_key,
- MatchedCredentialData matched_credential_data) {
+ const std::array<uint8_t, 32> key_seed,
+ const std::array<uint8_t, 32>
+ expected_mic_extended_salt_identity_token_hmac,
+ const std::array<uint8_t, 32> expected_signature_identity_token_hmac,
+ const std::array<uint8_t, 32> pub_key,
+ const MatchedCredentialData matched_credential_data) {
np_ffi::internal::V1DiscoveryCredential discovery_cred{};
CopyToRawArray(discovery_cred.key_seed, key_seed);
- CopyToRawArray(discovery_cred.expected_unsigned_metadata_key_hmac,
- expected_unsigned_metadata_key_hmac);
- CopyToRawArray(discovery_cred.expected_signed_metadata_key_hmac,
- expected_signed_metadata_key_hmac);
+ CopyToRawArray(discovery_cred.expected_mic_extended_salt_identity_token_hmac,
+ expected_mic_extended_salt_identity_token_hmac);
+ CopyToRawArray(discovery_cred.expected_signature_identity_token_hmac,
+ expected_signature_identity_token_hmac);
CopyToRawArray(discovery_cred.pub_key, pub_key);
this->internal_ = {discovery_cred, matched_credential_data.data_};
}
-} // namespace nearby_protocol
+
+V0BroadcastCredential::V0BroadcastCredential(
+ std::array<uint8_t, 32> key_seed, std::array<uint8_t, 14> identity_token) {
+ CopyToRawArray(internal_.key_seed, key_seed);
+ CopyToRawArray(internal_.identity_token, identity_token);
+}
+
+V0AdvertisementBuilder::~V0AdvertisementBuilder() {
+ if (!this->moved_) {
+ auto result = np_ffi::internal::np_ffi_deallocate_v0_advertisement_builder(
+ adv_builder_);
+ assert_panic(result == np_ffi::internal::DeallocateResult::Success);
+ }
+}
+
+V0AdvertisementBuilder::V0AdvertisementBuilder(
+ V0AdvertisementBuilder&& other) noexcept
+ : adv_builder_(other.adv_builder_), moved_(other.moved_) {
+ other.adv_builder_ = {};
+ other.moved_ = true;
+}
+
+V0AdvertisementBuilder& V0AdvertisementBuilder::operator=(
+ V0AdvertisementBuilder&& other) noexcept {
+ if (this != &other) {
+ if (!this->moved_) {
+ auto result =
+ np_ffi::internal::np_ffi_deallocate_v0_advertisement_builder(
+ this->adv_builder_);
+ assert_panic(result == np_ffi::internal::DeallocateResult::Success);
+ }
+
+ this->adv_builder_ = other.adv_builder_;
+ this->moved_ = other.moved_;
+
+ other.adv_builder_ = {};
+ other.moved_ = true;
+ }
+ return *this;
+}
+
+absl::Status V0AdvertisementBuilder::TryAddDE(V0DataElement de) {
+ assert_panic(!this->moved_);
+ auto result = np_ffi::internal::np_ffi_V0AdvertisementBuilder_add_de(
+ this->adv_builder_, de.v0_data_element_);
+ switch (result) {
+ case AddV0DEResult::Success: {
+ return absl::OkStatus();
+ }
+ case AddV0DEResult::InvalidAdvertisementBuilderHandle: {
+ return absl::InvalidArgumentError(
+ "invalid v0 advertisement builder handle provided");
+ }
+ case AddV0DEResult::InsufficientAdvertisementSpace: {
+ return absl::ResourceExhaustedError(
+ "insufficient advertisement space to add DE");
+ }
+ case AddV0DEResult::InvalidIdentityTypeForDataElement: {
+ return absl::InvalidArgumentError(
+ "the DE may not be added to this advertisement builder due to an "
+ "identity type mismatch");
+ }
+ }
+}
+
+[[nodiscard]] absl::StatusOr<ByteBuffer<24>>
+V0AdvertisementBuilder::TrySerialize() {
+ assert_panic(!this->moved_);
+ auto result =
+ np_ffi::internal::np_ffi_V0AdvertisementBuilder_into_advertisement(
+ this->adv_builder_);
+ auto kind =
+ np_ffi::internal::np_ffi_SerializeV0AdvertisementResult_kind(result);
+ // Regardless of what happens, we've invalidated the original adv builder.
+ this->moved_ = true;
+
+ switch (kind) {
+ case SerializeV0AdvertisementResultKind::Success: {
+ auto bytes =
+ np_ffi::internal::np_ffi_SerializeV0AdvertisementResult_into_SUCCESS(
+ result);
+ return ByteBuffer(bytes);
+ }
+ case SerializeV0AdvertisementResultKind::LdtError: {
+ return absl::OutOfRangeError(
+ "The advertisement contents were not of a proper size for LDT "
+ "encryption");
+ }
+ case SerializeV0AdvertisementResultKind::UnencryptedError: {
+ return absl::OutOfRangeError(
+ "The advertisement contents did not meet the length requirements");
+ }
+ case SerializeV0AdvertisementResultKind::
+ InvalidAdvertisementBuilderHandle: {
+ return absl::InvalidArgumentError(
+ "The advertisement builder handle was invalid");
+ }
+ }
+}
+
+[[nodiscard]] V0AdvertisementBuilder V0AdvertisementBuilder::CreatePublic() {
+ auto result =
+ np_ffi::internal::np_ffi_create_v0_public_advertisement_builder();
+ return V0AdvertisementBuilder(result);
+}
+
+template <uintptr_t N>
+[[nodiscard]] np_ffi::internal::FixedSizeArray<N> ToFFIArray(
+ std::array<uint8_t, N> value) {
+ np_ffi::internal::FixedSizeArray<N> result;
+ std::copy(std::begin(value), std::end(value), result._0);
+ return result;
+}
+
+[[nodiscard]] V0AdvertisementBuilder V0AdvertisementBuilder::CreateEncrypted(
+ V0BroadcastCredential broadcast_cred, std::array<uint8_t, 2> salt) {
+ auto result =
+ np_ffi::internal::np_ffi_create_v0_encrypted_advertisement_builder(
+ broadcast_cred.internal_, ToFFIArray(salt));
+ return V0AdvertisementBuilder(result);
+}
+
+} // namespace nearby_protocol
diff --git a/nearby/presence/np_cpp_ffi/sample/main.cc b/nearby/presence/np_cpp_ffi/sample/main.cc
index 1d273da..8a5c044 100644
--- a/nearby/presence/np_cpp_ffi/sample/main.cc
+++ b/nearby/presence/np_cpp_ffi/sample/main.cc
@@ -12,25 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-
#include <bitset>
#include <iostream>
+#include <string>
+#include <utility>
#include "absl/strings/escaping.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
-static void SamplePanicHandler(nearby_protocol::PanicReason reason);
+void SamplePanicHandler(nearby_protocol::PanicReason reason);
-void HandleAdvertisementResult(nearby_protocol::DeserializeAdvertisementResult);
+void HandleAdvertisementResult(
+ nearby_protocol::DeserializeAdvertisementResult /*result*/);
-void HandleV0Adv(nearby_protocol::DeserializedV0Advertisement);
-void HandleLegibleV0Adv(nearby_protocol::LegibleDeserializedV0Advertisement);
-void HandleV0IdentityKind(nearby_protocol::DeserializedV0IdentityKind);
-void HandleDataElement(nearby_protocol::V0DataElement);
+void HandleV0Adv(nearby_protocol::DeserializedV0Advertisement /*result*/);
+void HandleLegibleV0Adv(
+ nearby_protocol::LegibleDeserializedV0Advertisement /*legible_adv*/);
+void HandleV0IdentityKind(
+ nearby_protocol::DeserializedV0IdentityKind /*identity*/);
+void HandleDataElement(nearby_protocol::V0DataElement /*de*/);
-void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement);
-void HandleV1Section(nearby_protocol::DeserializedV1Section);
-void HandleV1DataElement(nearby_protocol::V1DataElement);
+void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement /*adv*/);
+void HandleV1Section(const nearby_protocol::DeserializedV1Section& /*section*/);
+void HandleV1DataElement(nearby_protocol::V1DataElement /*de*/);
int main() {
auto result =
@@ -46,51 +51,48 @@ int main() {
std::cout << "\n========= Example V0 Adv ==========\n";
std::cout << "Hex bytes: 00031503260046\n\n";
- // Create an empty credential slab and verify that it is successful
- auto cred_slab_result = nearby_protocol::CredentialSlab::TryCreate();
- if (!cred_slab_result.ok()) {
- std::cout << cred_slab_result.status().ToString();
- return -1;
- }
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
- // Create an empty credential book from the empty slab, and verify success.
- auto cred_book_result = nearby_protocol::CredentialBook::TryCreateFromSlab(cred_slab_result.value());
- if (!cred_book_result.ok()) {
- std::cout << cred_book_result.status().ToString();
+ const auto* v0_byte_string =
+ "00" // Adv Header
+ "03" // Public DE header
+ "1503" // Length 1 Tx Power DE with value 3
+ "260046"; // Length 2 Actions
+
+ std::string v0_bytes;
+ if (!absl::HexStringToBytes(v0_byte_string, &v0_bytes)) {
return -1;
}
-
- auto v0_byte_string = "00" // Adv Header
- "03" // Public DE header
- "1503" // Length 1 Tx Power DE with value 3
- "260046"; // Length 2 Actions
-
- auto v0_bytes = absl::HexStringToBytes(v0_byte_string);
- auto v0_buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(v0_bytes);
- nearby_protocol::RawAdvertisementPayload v0_payload(v0_buffer.value());
+ auto v0_buffer = nearby_protocol::ByteBuffer<255>::TryFromString(v0_bytes);
+ nearby_protocol::RawAdvertisementPayload const v0_payload(v0_buffer.value());
// Try to deserialize a V0 payload
auto deserialize_v0_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- v0_payload, cred_book_result.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(v0_payload,
+ credential_book);
HandleAdvertisementResult(std::move(deserialize_v0_result));
std::cout << "\n========= Example V1 Adv ==========\n";
std::cout << "Hex bytes: 20040326004603031505\n\n";
- auto v1_byte_string = "20" // V1 Advertisement header
- "04" // Section Header
- "03" // Public Identity DE header
- "260046";// Length 2 Actions DE
+ const auto* v1_byte_string =
+ "20" // V1 Advertisement header
+ "04" // Section Header
+ "03" // Public Identity DE header
+ "260046"; // Length 2 Actions DE
- auto v1_bytes = absl::HexStringToBytes(v1_byte_string);
- auto v1_buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(v1_bytes);
- nearby_protocol::RawAdvertisementPayload v1_payload(v1_buffer.value());
+ std::string v1_bytes;
+ if (!absl::HexStringToBytes(v1_byte_string, &v1_bytes)) {
+ return -1;
+ }
+ auto v1_buffer = nearby_protocol::ByteBuffer<255>::TryFromString(v1_bytes);
+ nearby_protocol::RawAdvertisementPayload const v1_payload(v1_buffer.value());
// Try to deserialize a V1 payload
auto deserialize_v1_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- v1_payload, cred_book_result.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(v1_payload,
+ credential_book);
HandleAdvertisementResult(std::move(deserialize_v1_result));
std::cout << "\n========= User input sample ==========\n\n";
@@ -99,19 +101,25 @@ int main() {
std::cout << "Enter the hex of the advertisement you would like to parse "
"(see above examples): ";
std::cin >> user_input;
- auto bytes = absl::HexStringToBytes(user_input);
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+ std::string bytes;
+ auto hex_result = absl::HexStringToBytes(user_input, &bytes);
+ if (!hex_result) {
+ std::cout << "Provided string is not valid hex";
+ continue;
+ }
+ auto buffer = nearby_protocol::ByteBuffer<255>::TryFromString(bytes);
if (!buffer.ok()) {
std::cout << "Too many bytes provided, must fit into a max length 255 "
"byte BLE advertisement\n";
continue;
}
- nearby_protocol::RawAdvertisementPayload user_input_payload(buffer.value());
+ nearby_protocol::RawAdvertisementPayload const user_input_payload(
+ buffer.value());
// Try to deserialize user input
auto user_input_result =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- user_input_payload, cred_book_result.value());
+ user_input_payload, credential_book);
HandleAdvertisementResult(std::move(user_input_result));
char choice;
@@ -126,21 +134,24 @@ int main() {
}
}
-static void SamplePanicHandler(nearby_protocol::PanicReason reason) {
+void SamplePanicHandler(nearby_protocol::PanicReason reason) {
std::cout << "Panicking! Reason: ";
switch (reason) {
- case nearby_protocol::PanicReason::EnumCastFailed: {
- std::cout << "EnumCastFailed \n";
- break;
- }
- case nearby_protocol::PanicReason::AssertFailed: {
- std::cout << "AssertFailed \n";
- break;
- }
- case nearby_protocol::PanicReason::InvalidActionBits: {
- std::cout << "InvalidActionBits \n";
- break;
- }
+ case nearby_protocol::PanicReason::EnumCastFailed: {
+ std::cout << "EnumCastFailed \n";
+ break;
+ }
+ case nearby_protocol::PanicReason::AssertFailed: {
+ std::cout << "AssertFailed \n";
+ break;
+ }
+ case nearby_protocol::PanicReason::InvalidStackDataStructure: {
+ std::cout << "InvalidStackDataStructure \n";
+ break;
+ }
+ case np_ffi::internal::PanicReason::ExceededMaxHandleAllocations:
+ std::cout << "ExceededMaxHandleAllocations \n";
+ break;
}
std::abort();
}
@@ -148,29 +159,30 @@ static void SamplePanicHandler(nearby_protocol::PanicReason reason) {
void HandleAdvertisementResult(
nearby_protocol::DeserializeAdvertisementResult result) {
switch (result.GetKind()) {
- case nearby_protocol::DeserializeAdvertisementResultKind::Error:
- std::cout << "Error in deserializing advertisement!\n";
- break;
- case nearby_protocol::DeserializeAdvertisementResultKind::V0:
- std::cout << "Successfully deserialized a V0 advertisement!\n";
- HandleV0Adv(result.IntoV0());
- break;
- case nearby_protocol::DeserializeAdvertisementResultKind::V1:
- std::cout << "Successfully deserialized a V1 advertisement\n";
- HandleV1Adv(result.IntoV1());
- break;
+ case nearby_protocol::DeserializeAdvertisementResultKind::Error:
+ std::cout << "Error in deserializing advertisement!\n";
+ break;
+ case nearby_protocol::DeserializeAdvertisementResultKind::V0:
+ std::cout << "Successfully deserialized a V0 advertisement!\n";
+ HandleV0Adv(result.IntoV0());
+ break;
+ case nearby_protocol::DeserializeAdvertisementResultKind::V1:
+ std::cout << "Successfully deserialized a V1 advertisement\n";
+ HandleV1Adv(result.IntoV1());
+ break;
}
}
void HandleV0Adv(nearby_protocol::DeserializedV0Advertisement result) {
switch (result.GetKind()) {
- case nearby_protocol::DeserializedV0AdvertisementKind::Legible:
- std::cout << "\tThe Advertisement is plaintext \n";
- HandleLegibleV0Adv(result.IntoLegible());
- break;
- case nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials:
- std::cout << "\tNo matching credentials found for this adv\n";
- return;
+ case nearby_protocol::DeserializedV0AdvertisementKind::Legible:
+ std::cout << "\tThe Advertisement is plaintext \n";
+ HandleLegibleV0Adv(result.IntoLegible());
+ break;
+ case nearby_protocol::DeserializedV0AdvertisementKind::
+ NoMatchingCredentials:
+ std::cout << "\tNo matching credentials found for this adv\n";
+ return;
}
}
@@ -179,7 +191,8 @@ void HandleLegibleV0Adv(
HandleV0IdentityKind(legible_adv.GetIdentityKind());
auto num_des = legible_adv.GetNumberOfDataElements();
- std::cout << "\t\tAdv contains " << unsigned(num_des) << " data elements \n";
+ std::cout << "\t\tAdv contains " << static_cast<unsigned>(num_des)
+ << " data elements \n";
auto payload = legible_adv.IntoPayload();
for (int i = 0; i < num_des; i++) {
auto de_result = payload.TryGetDataElement(i);
@@ -192,44 +205,46 @@ void HandleLegibleV0Adv(
}
}
-void HandleV0IdentityKind(nearby_protocol::DeserializedV0IdentityKind identity) {
+void HandleV0IdentityKind(
+ nearby_protocol::DeserializedV0IdentityKind identity) {
switch (identity) {
- case np_ffi::internal::DeserializedV0IdentityKind::Plaintext: {
- std::cout << "\t\tIdentity is Plaintext\n";
- break;
- }
- case np_ffi::internal::DeserializedV0IdentityKind::Decrypted: {
- std::cout << "\t\tIdentity is Encrypted\n";
- break;
- }
+ case np_ffi::internal::DeserializedV0IdentityKind::Plaintext: {
+ std::cout << "\t\tIdentity is Plaintext\n";
+ break;
+ }
+ case np_ffi::internal::DeserializedV0IdentityKind::Decrypted: {
+ std::cout << "\t\tIdentity is Encrypted\n";
+ break;
+ }
}
}
void HandleDataElement(nearby_protocol::V0DataElement de) {
switch (de.GetKind()) {
- case nearby_protocol::V0DataElementKind::TxPower: {
- std::cout << "\t\t\tDE Type is TxPower\n";
- auto tx_power = de.AsTxPower();
- std::cout << "\t\t\tpower: " << int(tx_power.tx_power) << "\n";
- return;
- }
- case nearby_protocol::V0DataElementKind::Actions: {
- std::cout << "\t\t\tDE Type is Actions\n";
- auto actions = de.AsActions();
- std::cout << "\t\t\tactions: " << std::bitset<32>(actions.GetAsU32())
- << "\n";
- return;
- }
+ case nearby_protocol::V0DataElementKind::TxPower: {
+ std::cout << "\t\t\tDE Type is TxPower\n";
+ auto tx_power = de.AsTxPower();
+ std::cout << "\t\t\tpower: " << static_cast<int>(tx_power.GetAsI8())
+ << "\n";
+ return;
+ }
+ case nearby_protocol::V0DataElementKind::Actions: {
+ std::cout << "\t\t\tDE Type is Actions\n";
+ auto actions = de.AsActions();
+ std::cout << "\t\t\tactions: " << std::bitset<32>(actions.GetAsU32())
+ << "\n";
+ return;
+ }
}
}
void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement adv) {
auto legible_sections = adv.GetNumLegibleSections();
- std::cout << "\tAdv has " << unsigned(legible_sections)
+ std::cout << "\tAdv has " << static_cast<unsigned>(legible_sections)
<< " legible sections \n";
auto encrypted_sections = adv.GetNumUndecryptableSections();
- std::cout << "\tAdv has " << unsigned(encrypted_sections)
+ std::cout << "\tAdv has " << static_cast<unsigned>(encrypted_sections)
<< " undecryptable sections\n";
for (auto i = 0; i < legible_sections; i++) {
@@ -243,20 +258,21 @@ void HandleV1Adv(nearby_protocol::DeserializedV1Advertisement adv) {
}
}
-void HandleV1Section(nearby_protocol::DeserializedV1Section section) {
+void HandleV1Section(const nearby_protocol::DeserializedV1Section& section) {
switch (section.GetIdentityKind()) {
- case np_ffi::internal::DeserializedV1IdentityKind::Plaintext: {
- std::cout << "\t\tIdentity is Plaintext\n";
- break;
- }
- case np_ffi::internal::DeserializedV1IdentityKind::Decrypted: {
- std::cout << "\t\tIdentity is Encrypted\n";
- break;
- }
+ case np_ffi::internal::DeserializedV1IdentityKind::Plaintext: {
+ std::cout << "\t\tIdentity is Plaintext\n";
+ break;
+ }
+ case np_ffi::internal::DeserializedV1IdentityKind::Decrypted: {
+ std::cout << "\t\tIdentity is Encrypted\n";
+ break;
+ }
}
auto num_des = section.NumberOfDataElements();
- std::cout << "\t\tSection has " << unsigned(num_des) << " data elements \n";
+ std::cout << "\t\tSection has " << static_cast<unsigned>(num_des)
+ << " data elements \n";
for (auto i = 0; i < num_des; i++) {
auto de_result = section.TryGetDataElement(i);
if (!de_result.ok()) {
@@ -271,7 +287,7 @@ void HandleV1Section(nearby_protocol::DeserializedV1Section section) {
void HandleV1DataElement(nearby_protocol::V1DataElement de) {
std::cout << "\t\t\tData Element type code: "
- << unsigned(de.GetDataElementTypeCode()) << "\n";
+ << static_cast<unsigned>(de.GetDataElementTypeCode()) << "\n";
std::cout << "\t\t\tPayload bytes as hex: "
<< absl::BytesToHexString(de.GetPayload().ToString()) << "\n";
}
diff --git a/nearby/presence/np_cpp_ffi/shared/shared_test_util.cc b/nearby/presence/np_cpp_ffi/shared/shared_test_util.cc
index 67ca828..58e1d20 100644
--- a/nearby/presence/np_cpp_ffi/shared/shared_test_util.cc
+++ b/nearby/presence/np_cpp_ffi/shared/shared_test_util.cc
@@ -12,22 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
+#include "shared_test_util.h"
#include <cstdlib>
-#include <cstddef> // IWYU pragma: keep
+
+#include "nearby_protocol.h"
std::string PanicReasonToString(nearby_protocol::PanicReason reason) {
switch (reason) {
- case nearby_protocol::PanicReason::EnumCastFailed: {
- return "EnumCastFailed";
- }
- case nearby_protocol::PanicReason::AssertFailed: {
- return "AssertFailed";
- }
- case nearby_protocol::PanicReason::InvalidActionBits: {
- return "InvalidActionBits";
- }
+ case nearby_protocol::PanicReason::EnumCastFailed: {
+ return "EnumCastFailed";
+ }
+ case nearby_protocol::PanicReason::AssertFailed: {
+ return "AssertFailed";
+ }
+ case nearby_protocol::PanicReason::InvalidStackDataStructure: {
+ return "InvalidStackDataStructure";
+ }
+ case np_ffi::internal::PanicReason::ExceededMaxHandleAllocations:
+ return "ExceededMaxHandleAllocations";
}
}
@@ -37,17 +40,37 @@ void test_panic_handler(nearby_protocol::PanicReason reason) {
}
std::string generate_hex_string(const size_t length) {
- char *str = new char[length];
+ std::string result;
+ result.reserve(length);
// hexadecimal characters
char hex_characters[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
- size_t i;
- for (i = 0; i < length; i++) {
- str[i] = hex_characters[rand() % 16]; // NOLINT(cert-msc50-cpp)
+
+ for (size_t i = 0; i < length; i++) {
+ result.push_back(hex_characters[rand() % 16]); // NOLINT(cert-msc50-cpp)
}
- str[length] = 0;
- std::string result(str, length);
- delete[] str;
+
return result;
-} \ No newline at end of file
+}
+
+nearby_protocol::V0MatchableCredential GenerateRandomCredentialV0() {
+ auto key_seed = create_random_array<32>();
+ auto legacy_metadata_key_hmac = create_random_array<32>();
+ auto encrypted_metadata_bytes = create_random_array<200>();
+ nearby_protocol::MatchedCredentialData matched_cred(rand(),
+ encrypted_metadata_bytes);
+ return {key_seed, legacy_metadata_key_hmac, matched_cred};
+}
+
+nearby_protocol::V1MatchableCredential GenerateRandomCredentialV1() {
+ auto key_seed = create_random_array<32>();
+ auto expected_unsigned_metadata_key_hmac = create_random_array<32>();
+ auto expected_signed_metadata_key_hmac = create_random_array<32>();
+ auto pub_key = create_random_array<32>();
+ auto encrypted_metadata_bytes = create_random_array<200>();
+ nearby_protocol::MatchedCredentialData matched_cred(rand(),
+ encrypted_metadata_bytes);
+ return {key_seed, expected_unsigned_metadata_key_hmac,
+ expected_signed_metadata_key_hmac, pub_key, matched_cred};
+}
diff --git a/nearby/presence/np_cpp_ffi/shared/shared_test_util.h b/nearby/presence/np_cpp_ffi/shared/shared_test_util.h
index 22d1bb3..83e79a7 100644
--- a/nearby/presence/np_cpp_ffi/shared/shared_test_util.h
+++ b/nearby/presence/np_cpp_ffi/shared/shared_test_util.h
@@ -17,28 +17,128 @@
#include "nearby_protocol.h"
-inline nearby_protocol::RawAdvertisementPayload
- V0AdvEmpty(nearby_protocol::ByteBuffer<255>({2, {0x00, 0x03}}));
-
-inline nearby_protocol::RawAdvertisementPayload
- V0AdvSimple(nearby_protocol::ByteBuffer<255>({
- 4,
- {0x00, // Adv Header
- 0x03, // Public DE header
- 0x15, 0x03} // Length 1 Tx Power DE with value 3
- }));
-
-inline nearby_protocol::RawAdvertisementPayload
- V1AdvSimple(nearby_protocol::ByteBuffer<255>(
- {5,
- {
- 0x20, // V1 Advertisement header
- 0x03, // Section Header
- 0x03, // Public Identity DE header
- 0x15, 0x03 // Length 1 Tx Power DE with value 3
- }}));
+// Plaintext advertisement bytes
+constexpr std::array<uint8_t, 2> V0AdvEmptyBytes{0x00, 0x03};
+constexpr std::array<uint8_t, 2> V1AdvEmptyBytes{0x00, 0x00};
+constexpr std::array<uint8_t, 3> V0AdvPlaintextBytes{0x00, 0x15, 0x03};
+constexpr std::array<uint8_t, 6> V0AdvPlaintextMultiDeBytes{
+ 0x00, 0x15, 0x05, 0x26, 0x40, 0x40,
+};
+constexpr std::array<uint8_t, 5> V1AdvPlaintextBytes{0x20, // Version header
+ 0x00, // format
+ 0x02, // section len
+ 0x15, // Tx power value 3
+ 0x03};
+
+// V0 encrypted advertisement data - ripped out of np_adv/tests/examples_v0.rs
+constexpr std::array<uint8_t, 19> V0AdvEncryptedBytes{
+ 0x04, 0x22, 0x22, 0xD8, 0x22, 0x12, 0xEF, 0x16, 0xDB, 0xF8,
+ 0x72, 0xF2, 0xA3, 0xA7, 0xC0, 0xFA, 0x52, 0x48, 0xEC};
+inline std::vector<uint8_t> V0AdvEncryptedMetadata = {
+ 0x8D, 0xD4, 0x7A, 0x58, 0x47, 0x30, 0x65, 0x89, 0x06, 0x16, 0x04, 0xCA,
+ 0x68, 0xCE, 0xB4, 0x18, 0xA7, 0x40, 0xB8, 0x36, 0xB0, 0x94, 0xB4, 0xC0,
+ 0x6C, 0xAF, 0x7C, 0x4A, 0x3B, 0x68, 0x28, 0x54, 0x8F, 0x36, 0xD5, 0x68,
+ 0x12, 0x6C, 0xC2, 0x63, 0x31, 0x4A, 0x48, 0xE4, 0x3B, 0xB3, 0xCF, 0xD4,
+ 0x10, 0x49, 0x59, 0xE7, 0x2B, 0xDE, 0xEB, 0x78, 0x44, 0x68,
+};
+inline std::string ExpectedV0DecryptedMetadata(
+ R"({"name":"Alice","email":"alice@gmail.com"})");
+constexpr std::array<uint8_t, 32> V0AdvKeySeed = {
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+};
+constexpr std::array<uint8_t, 32> V0AdvLegacyIdentityTokenHmac = {
+ 0x09, 0xFE, 0x9E, 0x81, 0xB7, 0x3E, 0x5E, 0xCC, 0x76, 0x59, 0x57,
+ 0x71, 0xE0, 0x1F, 0xFB, 0x34, 0x38, 0xE7, 0x5F, 0x24, 0xA7, 0x69,
+ 0x56, 0xA0, 0xB8, 0xEA, 0x67, 0xD1, 0x1C, 0x3E, 0x36, 0xFD};
+
+// V1 encrypted advertisement data - ripped out of np_adv/tests/examples_v1.rs
+constexpr std::array<uint8_t, 101> V1AdvEncryptedBytes{
+ 0x20, 0x03, 0x9C, 0xED, 0x67, 0x93, 0x04, 0x6A, 0xBB, 0x1B, 0x1C, 0x40,
+ 0x45, 0x1F, 0x34, 0x6C, 0x03, 0xF3, 0xAA, 0x4F, 0x01, 0x8B, 0x7A, 0x5F,
+ 0x8A, 0x7B, 0x06, 0x29, 0xA4, 0x12, 0x27, 0x12, 0x63, 0xB4, 0x42, 0x76,
+ 0xDE, 0xE9, 0x01, 0x6D, 0xF5, 0x70, 0x1C, 0x09, 0xDF, 0xBE, 0x2E, 0x32,
+ 0xE5, 0x64, 0x8A, 0xDF, 0xB0, 0xB5, 0xE0, 0xC1, 0xD9, 0x76, 0x99, 0x4C,
+ 0x71, 0xFB, 0xB2, 0xBF, 0xA2, 0xB9, 0xC2, 0xEA, 0x95, 0xE6, 0x6B, 0xFD,
+ 0xD7, 0x93, 0x4D, 0xB5, 0x2D, 0xC2, 0x8D, 0x1E, 0x31, 0x32, 0x00, 0x88,
+ 0x38, 0xBA, 0x73, 0x39, 0x5E, 0x23, 0xC3, 0x6C, 0x2D, 0x50, 0x22, 0x5B,
+ 0xB5, 0xF4, 0x9C, 0x96, 0x37};
+constexpr std::array<uint8_t, 32> V1AdvKeySeed = {
+ 0xF1, 0xEF, 0x9E, 0x34, 0xDC, 0x28, 0xBC, 0x37, 0x5B, 0x6E, 0x4A,
+ 0xC4, 0x52, 0xE6, 0x9C, 0xD3, 0x6D, 0xA9, 0xAB, 0x21, 0x5B, 0x02,
+ 0xB9, 0x10, 0x27, 0xC3, 0xA9, 0x53, 0xB5, 0x29, 0x4C, 0x36};
+constexpr std::array<uint8_t, 32>
+ V1AdvExpectedMicExtendedSaltIdentityTokenHmac = {0};
+constexpr std::array<uint8_t, 32> V1AdvExpectedSignatureIdentityTokenHmac = {
+ 0x10, 0x05, 0x45, 0x27, 0x8F, 0xE6, 0x86, 0x5B, 0x51, 0xB0, 0x39,
+ 0xEA, 0xB8, 0xD7, 0x5F, 0x61, 0x41, 0xDD, 0x92, 0x62, 0xDD, 0x1A,
+ 0x9D, 0xDA, 0x98, 0xDA, 0xF2, 0xDC, 0xA9, 0xD2, 0x45, 0x50};
+constexpr std::array<uint8_t, 32> V1AdvPublicKey = {
+ 0x39, 0xA0, 0x74, 0x81, 0x70, 0x46, 0xFF, 0x72, 0x59, 0xC7, 0x78,
+ 0x6C, 0x30, 0x7B, 0xC8, 0x71, 0x26, 0x34, 0xFF, 0x13, 0x61, 0x8C,
+ 0xE6, 0x22, 0x46, 0x62, 0x56, 0xFD, 0xC1, 0x7A, 0x01, 0xAE};
+inline std::vector<uint8_t> V1AdvEncryptedMetadata = {
+ 0x7B, 0xE9, 0x66, 0x00, 0x9E, 0x14, 0x50, 0xDE, 0x96, 0xCB, 0x79,
+ 0x38, 0x93, 0xC5, 0x15, 0xE9, 0xC2, 0x6B, 0xE8, 0x03, 0x9F, 0x6C,
+ 0xCA, 0x94, 0xAD, 0x24, 0x13, 0x27, 0xC1, 0xDE, 0xBC, 0xC2, 0x29,
+ 0x88, 0xC0, 0xA5, 0x3B, 0xCA, 0x98, 0x4A, 0x42, 0xC3, 0xDE, 0xF5,
+ 0x1C, 0xAE, 0xFF, 0xC0, 0x02, 0xD2, 0xD2, 0x97, 0x8B, 0x52, 0x93,
+ 0x71, 0x07, 0x39, 0x87, 0x89, 0xCB, 0xCD, 0x79, 0x0A, 0x19, 0x0E,
+ 0x73, 0xEB, 0x24, 0xFA, 0x8F, 0x4C, 0xA7, 0xF3, 0x95, 0x0B, 0xED,
+ 0xEF, 0x27, 0x49, 0x8D, 0xE8, 0x7B, 0x88, 0x33, 0x16, 0x83, 0xF6,
+ 0xF1, 0xE6, 0x43, 0x22, 0x70, 0x70, 0xFD, 0x9B, 0xA6, 0x52, 0x35,
+ 0x0B, 0xBF, 0xBA, 0x0C, 0x20, 0xA3, 0x0C, 0xE7, 0xC7, 0xD0, 0x70};
+inline std::string ExpectedV1DecryptedMetadata(
+ "{\"uuid\":\"378845e1-2616-420d-86f5-674177a7504d\","
+ "\"display_name\":\"Alice\",\"location\":\"Wonderland\"}");
+
+// Data suitable for use directly through the C API (bypassing the C++ wrapper)
+constexpr np_ffi::internal::RawAdvertisementPayload V0AdvMultiDeInternals{
+ {7, {0x00, 0x03, 0x15, 0x05, 0x26, 0x00, 0x46}}};
+
+// Wrapper types directly usable by C++ API
+constexpr nearby_protocol::ByteBuffer<255> V0AdvEmptyBuffer(V0AdvEmptyBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V0AdvEmpty(V0AdvEmptyBuffer);
+
+constexpr nearby_protocol::ByteBuffer<255> V0AdvPlaintextBuffer(
+ V0AdvPlaintextBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V0AdvPlaintext(
+ V0AdvPlaintextBuffer);
+
+constexpr nearby_protocol::ByteBuffer<255> V0AdvPlaintextMultiDeBuffer(
+ V0AdvPlaintextMultiDeBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V0AdvPlaintextMultiDe(
+ V0AdvPlaintextMultiDeBuffer);
+
+constexpr nearby_protocol::ByteBuffer<255> V1AdvPlaintextBuffer(
+ V1AdvPlaintextBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V1AdvPlaintext(
+ V1AdvPlaintextBuffer);
+
+constexpr nearby_protocol::ByteBuffer<255> V0AdvEncryptedBuffer(
+ V0AdvEncryptedBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V0AdvEncryptedPayload(
+ V0AdvEncryptedBuffer);
+
+constexpr nearby_protocol::ByteBuffer<255> V1AdvEncryptedBuffer(
+ V1AdvEncryptedBytes);
+constexpr nearby_protocol::RawAdvertisementPayload V1AdvEncrypted(
+ V1AdvEncryptedBuffer);
+
void test_panic_handler(nearby_protocol::PanicReason reason);
+nearby_protocol::V0MatchableCredential GenerateRandomCredentialV0();
+
+nearby_protocol::V1MatchableCredential GenerateRandomCredentialV1();
+
+template <uint32_t N>
+std::array<uint8_t, N> create_random_array() {
+ std::array<uint8_t, N> array{};
+ std::generate(array.begin(), array.end(), []() { return rand(); });
+ return array;
+}
+
std::string generate_hex_string(size_t length);
-#endif // NEARBY_PRESENCE_NP_CPP_FFI_TESTS_SHARED_TEST_UTILS_H_
+#endif // NEARBY_PRESENCE_NP_CPP_FFI_TESTS_SHARED_TEST_UTILS_H_
diff --git a/nearby/presence/np_cpp_ffi/tests/CMakeLists.txt b/nearby/presence/np_cpp_ffi/tests/CMakeLists.txt
index 549a072..80fdee0 100644
--- a/nearby/presence/np_cpp_ffi/tests/CMakeLists.txt
+++ b/nearby/presence/np_cpp_ffi/tests/CMakeLists.txt
@@ -20,10 +20,12 @@ add_executable(
deserialize_result_tests.cc
np_cpp_test.h
np_cpp_test.cc
- v0_private_identity_tests.cc
- v0_public_identity_tests.cc
- v1_private_identity_tests.cc
- v1_public_identity_tests.cc
+ v0_encrypted_deserialization_tests.cc
+ v0_encrypted_serialization_tests.cc
+ v0_unencrypted_deserialization_tests.cc
+ v0_unencrypted_serialization_tests.cc
+ v1_encrypted_deserialization_tests.cc
+ v1_unencrypted_deserialization_tests.cc
)
target_link_libraries(
diff --git a/nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc b/nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc
index 7e1a048..e75d77d 100644
--- a/nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/byte_buffer_tests.cc
@@ -12,69 +12,132 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-#include "np_cpp_test.h"
-#include "shared_test_util.h"
+#include <array>
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
#include "absl/strings/escaping.h"
#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
+// NOLINTBEGIN(readability-magic-numbers)
TEST_F(NpCppTest, ByteBufferMaxLength) {
// Each hex byte takes up 2 characters so length 510 string = 255 bytes of hex
auto str_bytes = generate_hex_string(510);
- auto bytes = absl::HexStringToBytes(str_bytes);
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes(str_bytes, &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromString(bytes);
ASSERT_TRUE(buffer.ok());
auto string = buffer.value().ToString();
ASSERT_EQ(bytes, string);
}
+TEST_F(NpCppTest, ByteBufferArrayConstructor) {
+ const std::array<uint8_t, 3> data{1, 2, 3};
+ const nearby_protocol::ByteBuffer<nearby_protocol::MAX_ADV_PAYLOAD_SIZE>
+ buffer(data);
+ const std::vector<uint8_t> expected{1, 2, 3};
+ ASSERT_EQ(expected, buffer.ToVector());
+}
+
+TEST_F(NpCppTest, ByteBufferTryFromSpan) {
+ std::vector<uint8_t> data{1, 2, 3};
+ auto buffer = nearby_protocol::ByteBuffer<3>::TryFromSpan(data);
+ assert(buffer.ok());
+ ASSERT_EQ(data, buffer->ToVector());
+}
+
+TEST_F(NpCppTest, ByteBufferTryFromSpanBufferNotFull) {
+ std::vector<uint8_t> data{1, 2, 3};
+ auto buffer = nearby_protocol::ByteBuffer<100>::TryFromSpan(data);
+ assert(buffer.ok());
+ ASSERT_EQ(data, buffer->ToVector());
+}
+
+TEST_F(NpCppTest, ByteBufferTryFromSpanInvalidLength) {
+ std::vector<uint8_t> data{1, 2, 3};
+ auto buffer = nearby_protocol::ByteBuffer<2>::TryFromSpan(data);
+ ASSERT_FALSE(buffer.ok());
+}
+
+TEST_F(NpCppTest, ByteBufferTryFromSpanArray) {
+ const std::array<uint8_t, 3> data{1, 2, 3};
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromSpan(data);
+ const std::vector<uint8_t> expected{1, 2, 3};
+ ASSERT_EQ(expected, buffer->ToVector());
+}
+
+TEST_F(NpCppTest, ByteBufferTryFromSpanArrayInvalid) {
+ std::array<uint8_t, 3> data{1, 2, 3};
+ auto buffer = nearby_protocol::ByteBuffer<2>::TryFromSpan(data);
+ ASSERT_FALSE(buffer.ok());
+}
+
TEST_F(NpCppTest, ByteBufferInvalidLength) {
// 256 bytes should fail
auto str_bytes = generate_hex_string(512);
- auto bytes = absl::HexStringToBytes(str_bytes);
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes(str_bytes, &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromString(bytes);
ASSERT_FALSE(buffer.ok());
}
TEST_F(NpCppTest, ByteBufferRoundTrip) {
- auto bytes = absl::HexStringToBytes("2003031503");
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes("2003031503", &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromString(bytes);
auto string = buffer.value().ToString();
ASSERT_EQ(bytes, string);
}
TEST_F(NpCppTest, ByteBufferPayloadWrongSize) {
- auto bytes = absl::HexStringToBytes("1111111111111111111111");
- auto buffer = nearby_protocol::ByteBuffer<10>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes("1111111111111111111111", &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<10>::TryFromString(bytes);
ASSERT_FALSE(buffer.ok());
}
TEST_F(NpCppTest, ByteBufferEmptyString) {
- auto bytes = absl::HexStringToBytes("");
- auto buffer = nearby_protocol::ByteBuffer<10>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes("", &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<10>::TryFromString(bytes);
ASSERT_TRUE(buffer.ok());
}
TEST_F(NpCppTest, ByteBufferToVector) {
- auto bytes = absl::HexStringToBytes("1234567890");
- auto buffer = nearby_protocol::ByteBuffer<100>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes("1234567890", &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<100>::TryFromString(bytes);
auto vec = buffer.value().ToVector();
- std::vector<uint8_t> expected{0x12, 0x34, 0x56, 0x78, 0x90};
+ const std::vector<uint8_t> expected{0x12, 0x34, 0x56, 0x78, 0x90};
ASSERT_EQ(vec, expected);
}
TEST_F(NpCppTest, ByteBufferEndToEndPayloadAsString) {
- std::string bytes = absl::HexStringToBytes("2003031503");
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(
+ absl::HexStringToBytes("20" // NP Version Header V1
+ "00" // Format = unencrypted
+ "02" // section length = 2
+ "1503", // tx power value 3
+ &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromString(bytes);
ASSERT_TRUE(buffer.ok());
- nearby_protocol::RawAdvertisementPayload adv(buffer.value());
+ const nearby_protocol::RawAdvertisementPayload adv(buffer.value());
- auto credential_slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto credential_book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(credential_slab)
- .value();
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto str = nearby_protocol::Deserializer::DeserializeAdvertisement(
adv, credential_book)
.IntoV1()
@@ -84,5 +147,9 @@ TEST_F(NpCppTest, ByteBufferEndToEndPayloadAsString) {
.value()
.GetPayload()
.ToString();
- ASSERT_EQ(str, absl::HexStringToBytes("03"));
+
+ std::string expected;
+ ASSERT_TRUE(absl::HexStringToBytes("03", &expected));
+ ASSERT_EQ(str, expected);
}
+// NOLINTEND(readability-magic-numbers)
diff --git a/nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc b/nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc
index af8fc0d..7ead975 100644
--- a/nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/credential_book_tests.cc
@@ -12,94 +12,106 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-#include "shared_test_util.h"
-#include "np_cpp_test.h"
+#include <utility>
+#include "absl/status/status.h"
#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
-TEST_F(NpCppTest, TestSetMaxCredBooks) {
- auto slab1_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab1_result.ok());
- auto book1_result = nearby_protocol::CredentialBook::TryCreateFromSlab(slab1_result.value());
- ASSERT_TRUE(book1_result.ok());
-
- auto slab2_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab2_result.ok());
- auto book2_result = nearby_protocol::CredentialBook::TryCreateFromSlab(slab2_result.value());
- ASSERT_TRUE(book2_result.ok());
-
- auto slab3_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab3_result.ok());
- auto book3_result = nearby_protocol::CredentialBook::TryCreateFromSlab(slab3_result.value());
-
- ASSERT_FALSE(book3_result.ok());
- ASSERT_TRUE(absl::IsResourceExhausted(book3_result.status()));
-}
-
-TEST_F(NpCppTest, TestBookMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+TEST_F(NpCppTest, TestCredBookMoveConstructor) {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvSimple,
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
book);
ASSERT_EQ(deserialize_result.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
// Move the credential book into a new object. Using the new object should
// still result in success
- nearby_protocol::CredentialBook next_book(std::move(book));
+ const nearby_protocol::CredentialBook next_book(std::move(book));
auto deserialize_result_moved =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvSimple,
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
next_book);
ASSERT_EQ(deserialize_result_moved.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
// The old object should now lead to use after moved assert failure
- ASSERT_DEATH([[maybe_unused]] auto failure =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book), // NOLINT(bugprone-use-after-move)
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvPlaintext, book), // NOLINT(bugprone-use-after-move)
+ "");
// moving again should still lead to a use after moved assert failure
- nearby_protocol::CredentialBook another_moved_book(std::move(book));
+ const nearby_protocol::CredentialBook another_moved_book(std::move(book));
ASSERT_DEATH([[maybe_unused]] auto failure =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, another_moved_book),
+ V0AdvPlaintext, another_moved_book),
"");
}
-TEST_F(NpCppTest, TestBookMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+TEST_F(NpCppTest, TestCredBookDestructor) {
+ nearby_protocol::CredentialSlab slab1;
+ auto current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.cred_slab, 1U);
+ nearby_protocol::CredentialBook book1(slab1);
+ current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.cred_book, 1U);
+ ASSERT_EQ(current_allocations.cred_slab, 0U);
+
+ {
+ nearby_protocol::CredentialSlab slab2;
+ nearby_protocol::CredentialBook book2(slab2);
+ current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.cred_book, 2U);
+ }
+
+ // After above RAII class goes out of scope, its de-allocation should be
+ // reflected in the handle allocation count
+ current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.cred_book, 1U);
+}
+
+TEST_F(NpCppTest, TestCredBookMoveAssignment) {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvSimple,
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
book);
ASSERT_EQ(deserialize_result.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
// create a second empty credential book
- auto other_slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto other_book = nearby_protocol::CredentialBook::TryCreateFromSlab(other_slab).value();
+ nearby_protocol::CredentialSlab other_slab;
+ nearby_protocol::CredentialBook other_book(other_slab);
other_book = std::move(book);
// new credential book should still be successful
auto deserialize_result_other =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvSimple,
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
other_book);
ASSERT_EQ(deserialize_result_other.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
// The old object should now lead to use after moved assert failure
- ASSERT_DEATH([[maybe_unused]] auto failure =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book), // NOLINT(bugprone-use-after-move)
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvPlaintext, book), // NOLINT(bugprone-use-after-move)
+ "");
// moving again should still lead to a use after moved assert failure
auto another_moved_book = std::move(book);
ASSERT_DEATH([[maybe_unused]] auto failure =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, another_moved_book),
+ V0AdvPlaintext, another_moved_book),
"");
}
diff --git a/nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc b/nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc
index c8ddb3c..ebaf874 100644
--- a/nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/credential_slab_tests.cc
@@ -12,215 +12,164 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-#include "np_cpp_test.h"
-#include "shared_test_util.h"
+#include <array>
+#include <cstdint>
+#include <span>
+#include <utility>
+#include "absl/status/status.h"
#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_test.h"
-TEST_F(NpCppTest, TestSetMaxCredSlabs) {
- auto slab1_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab1_result.ok());
-
- auto slab2_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab2_result.ok());
-
- auto slab3_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab3_result.ok());
-
- auto slab4_result = nearby_protocol::CredentialSlab::TryCreate();
-
- ASSERT_FALSE(slab4_result.ok());
- ASSERT_TRUE(absl::IsResourceExhausted(slab4_result.status()));
-}
-
+// NOLINTBEGIN(readability-magic-numbers)
TEST_F(NpCppTest, TestSlabMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
+ nearby_protocol::CredentialSlab slab;
// It should be possible to move the slab into a new object
// and use the moved version to successfully construct a
// credential-book.
nearby_protocol::CredentialSlab next_slab(std::move(slab));
+ nearby_protocol::CredentialBook book(next_slab);
- auto maybe_book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(next_slab);
- ASSERT_TRUE(maybe_book.ok());
-
- // Now, both slabs should be moved-out-of, since `TryCreateFromSlab` takes
+ // Now, both slabs should be moved-out-of, since `CreateFromSlab` takes
// ownership. Verify that this is the case, and attempts to re-use the slabs
// result in an assert failure.
- ASSERT_DEATH([[maybe_unused]] auto failure =
- nearby_protocol::CredentialBook::TryCreateFromSlab(
- slab), // NOLINT(bugprone-use-after-move)
+ ASSERT_DEATH([[maybe_unused]] nearby_protocol::CredentialBook failure(
+ slab), // NOLINT(bugprone-use-after-move)
+ "");
+ ASSERT_DEATH([[maybe_unused]] nearby_protocol::CredentialBook failure(
+ next_slab), // NOLINT(bugprone-use-after-move)
"");
- ASSERT_DEATH(
- [[maybe_unused]] auto failure =
- nearby_protocol::CredentialBook::TryCreateFromSlab(next_slab),
- "");
-}
-
-TEST_F(NpCppTest, TestSlabDestructor) {
- {
- auto slab1_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab1_result.ok());
-
- auto slab2_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab2_result.ok());
-
- auto slab3_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab3_result.ok());
-
- auto slab4_result = nearby_protocol::CredentialSlab::TryCreate();
-
- ASSERT_FALSE(slab4_result.ok());
- ASSERT_TRUE(absl::IsResourceExhausted(slab4_result.status()));
- }
-
- // Now that the above variables have gone out of scope we should verify that
- // the destructor succeeded in cleaning up those resources
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
}
TEST_F(NpCppTest, TestSlabMoveAssignment) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
- // create a second slab
- auto other_slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(other_slab_result.ok());
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialSlab other_slab;
// move assignment should override currently assigned slab with new one,
// freeing the existing one.
- auto other_slab = std::move(slab_result.value());
- auto maybe_book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(other_slab);
- ASSERT_TRUE(maybe_book.ok());
+ other_slab = std::move(slab);
+ nearby_protocol::CredentialBook book(other_slab);
// The old object should now lead to use after moved assert failure
- ASSERT_DEATH([[maybe_unused]] auto failure =
- nearby_protocol::CredentialBook::TryCreateFromSlab(
- slab_result.value()), // NOLINT(bugprone-use-after-move)
+ ASSERT_DEATH([[maybe_unused]] nearby_protocol::CredentialBook failure(
+ slab), // NOLINT(bugprone-use-after-move)
"");
// moving again should still lead to a use after moved assert failure
- auto another_moved_book = std::move(slab_result.value());
- ASSERT_DEATH([[maybe_unused]] auto failure =
- nearby_protocol::CredentialBook::TryCreateFromSlab(
- another_moved_book), // NOLINT(bugprone-use-after-move)
+ auto another_moved_book = std::move(slab);
+ ASSERT_DEATH([[maybe_unused]] nearby_protocol::CredentialBook failure(
+ another_moved_book), // NOLINT(bugprone-use-after-move)
"");
}
TEST_F(NpCppTest, TestAddV0Credential) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
+ nearby_protocol::CredentialSlab slab;
uint8_t metadata[] = {1, 2, 3};
- std::span<uint8_t> metadata_span(metadata);
+ const std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
- std::array<uint8_t, 32> key_seed{1, 2, 3};
- std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
+ const nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
+ const std::array<uint8_t, 32> key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
- nearby_protocol::V0MatchableCredential v0_cred(
+ const nearby_protocol::V0MatchableCredential v0_cred(
key_seed, legacy_metadata_key_hmac, match_data);
- auto add_result = slab_result.value().AddV0Credential(v0_cred);
- ASSERT_EQ(add_result, absl::OkStatus());
+ slab.AddV0Credential(v0_cred);
}
TEST_F(NpCppTest, TestAddV0CredentialAfterMoved) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
+ nearby_protocol::CredentialSlab slab;
// creating a book will move the slab
- auto maybe_book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(slab_result.value());
- ASSERT_TRUE(maybe_book.ok());
+ nearby_protocol::CredentialBook book(slab);
uint8_t metadata[] = {1, 2, 3};
- std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
- std::array<uint8_t, 32> key_seed{1, 2, 3};
- std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
- nearby_protocol::V0MatchableCredential v0_cred(
+ const std::span<uint8_t> metadata_span(metadata);
+ const nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
+ const std::array<uint8_t, 32> key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
+ const nearby_protocol::V0MatchableCredential v0_cred(
key_seed, legacy_metadata_key_hmac, match_data);
-
- ASSERT_DEATH([[maybe_unused]] auto add_result =
- slab_result.value().AddV0Credential(v0_cred);
- , "");
+ ASSERT_DEATH(slab.AddV0Credential(v0_cred);, "");
}
TEST_F(NpCppTest, TestAddV1Credential) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
+ nearby_protocol::CredentialSlab slab;
uint8_t metadata[] = {1, 2, 3};
- std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
- std::array<uint8_t, 32> key_seed{1, 2, 3};
- std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> expected_signed_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> pub_key{1, 2, 3};
- nearby_protocol::V1MatchableCredential v1_cred(
+ const std::span<uint8_t> metadata_span(metadata);
+ const nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
+ const std::array<uint8_t, 32> key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac{1, 2, 3};
+ const std::array<uint8_t, 32> expected_signed_metadata_key_hmac{1, 2, 3};
+ const std::array<uint8_t, 32> pub_key{1, 2, 3};
+ const nearby_protocol::V1MatchableCredential v1_cred(
key_seed, expected_unsigned_metadata_key_hmac,
expected_signed_metadata_key_hmac, pub_key, match_data);
- auto add_result = slab_result.value().AddV1Credential(v1_cred);
+ auto add_result = slab.AddV1Credential(v1_cred);
ASSERT_EQ(add_result, absl::OkStatus());
}
TEST_F(NpCppTest, TestAddV1CredentialAfterMoved) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
+ nearby_protocol::CredentialSlab slab;
// creating a book will move the slab
- auto maybe_book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(slab_result.value());
- ASSERT_TRUE(maybe_book.ok());
-
+ nearby_protocol::CredentialBook book(slab);
uint8_t metadata[] = {1, 2, 3};
- std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
- std::array<uint8_t, 32> key_seed{1, 2, 3};
- std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> expected_signed_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> pub_key{1, 2, 3};
- nearby_protocol::V1MatchableCredential v1_cred(
+ const std::span<uint8_t> metadata_span(metadata);
+ const nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
+ const std::array<uint8_t, 32> key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac{1, 2, 3};
+ const std::array<uint8_t, 32> expected_signed_metadata_key_hmac{1, 2, 3};
+ const std::array<uint8_t, 32> pub_key{1, 2, 3};
+ const nearby_protocol::V1MatchableCredential v1_cred(
key_seed, expected_unsigned_metadata_key_hmac,
expected_signed_metadata_key_hmac, pub_key, match_data);
- ASSERT_DEATH([[maybe_unused]] auto add_result =
- slab_result.value().AddV1Credential(v1_cred);
+ ASSERT_DEATH([[maybe_unused]] auto add_result = slab.AddV1Credential(v1_cred);
, "");
}
// make sure the book can be populated with many credentials
TEST_F(NpCppTest, TestAddManyCredentials) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
+ nearby_protocol::CredentialSlab slab;
// Should be able to load the slab up with many credentials
for (int i = 0; i < 500; i++) {
uint8_t metadata[] = {1, 2, 3};
- std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
- std::array<uint8_t, 32> key_seed{1, 2, 3};
- std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
- nearby_protocol::V0MatchableCredential v0_cred(
+ const std::span<uint8_t> metadata_span(metadata);
+ const nearby_protocol::MatchedCredentialData match_data(111, metadata_span);
+ const std::array<uint8_t, 32> key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> legacy_metadata_key_hmac{1, 2, 3};
+ const nearby_protocol::V0MatchableCredential v0_cred(
key_seed, legacy_metadata_key_hmac, match_data);
- auto add_result = slab_result->AddV0Credential(v0_cred);
- ASSERT_EQ(add_result, absl::OkStatus());
-
- std::array<uint8_t, 32> v1_key_seed{1, 2, 3};
- std::array<uint8_t, 32> v1_expected_unsigned_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> v1_expected_signed_metadata_key_hmac{1, 2, 3};
- std::array<uint8_t, 32> v1_pub_key{1, 2, 3};
- nearby_protocol::V1MatchableCredential v1_cred(
+ slab.AddV0Credential(v0_cred);
+
+ const std::array<uint8_t, 32> v1_key_seed{1, 2, 3};
+ const std::array<uint8_t, 32> v1_expected_unsigned_metadata_key_hmac{1, 2,
+ 3};
+ const std::array<uint8_t, 32> v1_expected_signed_metadata_key_hmac{1, 2, 3};
+ const std::array<uint8_t, 32> v1_pub_key{1, 2, 3};
+ const nearby_protocol::V1MatchableCredential v1_cred(
v1_key_seed, v1_expected_unsigned_metadata_key_hmac,
v1_expected_signed_metadata_key_hmac, v1_pub_key, match_data);
- auto add_v1_result = slab_result->AddV1Credential(v1_cred);
+ auto add_v1_result = slab.AddV1Credential(v1_cred);
ASSERT_EQ(add_v1_result, absl::OkStatus());
}
- ASSERT_TRUE(
- nearby_protocol::CredentialBook::TryCreateFromSlab(*slab_result).ok());
+ nearby_protocol::CredentialBook book(slab);
+}
+
+TEST_F(NpCppTest, TestSlabDestructor) {
+ {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialSlab slab2;
+ nearby_protocol::CredentialSlab slab3;
+ auto alloc_count =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(alloc_count.cred_slab, 3U);
+ }
+ auto alloc_count =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(alloc_count.cred_slab, 0U);
}
+// NOLINTEND(readability-magic-numbers) \ No newline at end of file
diff --git a/nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc b/nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc
index 0469933..af83461 100644
--- a/nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/deserialize_result_tests.cc
@@ -12,18 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-#include "shared_test_util.h"
-#include "np_cpp_test.h"
+#include <array>
+#include <cstdint>
+#include <utility>
#include "absl/strings/escaping.h"
#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
TEST_F(NpCppTest, TestResultMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -39,7 +43,7 @@ TEST_F(NpCppTest, TestResultMoveConstructor) {
// trying to use the moved object should result in a use after free which
// triggers an abort
ASSERT_DEATH([[maybe_unused]] auto failure =
- result.IntoV0(), // NOLINT(bugprone-use-after-move
+ result.IntoV0(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH([[maybe_unused]] auto failure = result.GetKind(), "");
@@ -52,22 +56,18 @@ TEST_F(NpCppTest, TestResultMoveConstructor) {
}
TEST_F(NpCppTest, DeserializeFromStringView) {
- auto bytes = absl::HexStringToBytes("00031503");
- auto buffer = nearby_protocol::ByteBuffer<255>::CopyFrom(bytes);
+ std::string bytes;
+ ASSERT_TRUE(absl::HexStringToBytes("001503", &bytes));
+ auto buffer = nearby_protocol::ByteBuffer<
+ nearby_protocol::MAX_ADV_PAYLOAD_SIZE>::TryFromString(bytes);
ASSERT_TRUE(buffer.ok());
- nearby_protocol::RawAdvertisementPayload adv(buffer.value());
-
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ const nearby_protocol::RawAdvertisementPayload adv(buffer.value());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- adv, maybe_credential_book.value());
-
+ nearby_protocol::Deserializer::DeserializeAdvertisement(adv,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
auto v0_adv = deserialize_result.IntoV0();
@@ -76,8 +76,7 @@ TEST_F(NpCppTest, DeserializeFromStringView) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
@@ -89,20 +88,20 @@ TEST_F(NpCppTest, DeserializeFromStringView) {
ASSERT_EQ(de.GetKind(), nearby_protocol::V0DataElementKind::TxPower);
auto tx_power = de.AsTxPower();
- ASSERT_EQ(tx_power.tx_power, 3);
+ ASSERT_EQ(tx_power.GetAsI8(), 3);
}
TEST_F(NpCppTest, TestResultMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
// create a second result
auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(another_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -116,7 +115,7 @@ TEST_F(NpCppTest, TestResultMoveAssignment) {
// original result should now be invalid, using it will trigger a use after
// free abort.
ASSERT_DEATH([[maybe_unused]] auto failure =
- result.IntoV0(), // NOLINT(bugprone-use-after-move)
+ result.IntoV0(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH([[maybe_unused]] auto failure = result.GetKind(), "");
@@ -128,18 +127,14 @@ TEST_F(NpCppTest, TestResultMoveAssignment) {
TEST_F(NpCppTest, TestInvalidPayloadHeader) {
// An invalid header result should result in error
- nearby_protocol::RawAdvertisementPayload InvalidHeaderPayload(
- nearby_protocol::ByteBuffer<255>({1, {0xFF}}));
-
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ const std::array<uint8_t, 1> InvalidHeaderPayloadBytes{0xFF};
+ const nearby_protocol::RawAdvertisementPayload InvalidHeaderPayload(
+ (nearby_protocol::ByteBuffer<255>(InvalidHeaderPayloadBytes)));
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- InvalidHeaderPayload, maybe_credential_book.value());
+ InvalidHeaderPayload, credential_book);
// Errors cannot be casted into further types
ASSERT_EQ(deserialize_result.GetKind(),
@@ -151,15 +146,11 @@ TEST_F(NpCppTest, TestInvalidPayloadHeader) {
}
TEST_F(NpCppTest, TestInvalidV0Cast) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V1);
@@ -169,16 +160,11 @@ TEST_F(NpCppTest, TestInvalidV0Cast) {
TEST_F(NpCppTest, TestInvalidV1Cast) {
// Create an empty credential book and verify that is is successful
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -187,15 +173,11 @@ TEST_F(NpCppTest, TestInvalidV1Cast) {
}
TEST_F(NpCppTest, V0UseResultTwice) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -208,15 +190,11 @@ TEST_F(NpCppTest, V0UseResultTwice) {
}
TEST_F(NpCppTest, V1UseResultTwice) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
@@ -229,15 +207,11 @@ TEST_F(NpCppTest, V1UseResultTwice) {
}
TEST_F(NpCppTest, IntoV0AfterOutOfScope) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -251,15 +225,11 @@ TEST_F(NpCppTest, IntoV0AfterOutOfScope) {
}
TEST_F(NpCppTest, IntoV1AfterOutOfScope) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
@@ -273,15 +243,11 @@ TEST_F(NpCppTest, IntoV1AfterOutOfScope) {
}
TEST_F(NpCppTest, V0ResultKindAfterOutOfScope) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -295,15 +261,11 @@ TEST_F(NpCppTest, V0ResultKindAfterOutOfScope) {
}
TEST_F(NpCppTest, V1ResultKindAfterOutOfScope) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
-
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
diff --git a/nearby/presence/np_cpp_ffi/tests/np_cpp_test.h b/nearby/presence/np_cpp_ffi/tests/np_cpp_test.h
index 1787c35..c8337a5 100644
--- a/nearby/presence/np_cpp_ffi/tests/np_cpp_test.h
+++ b/nearby/presence/np_cpp_ffi/tests/np_cpp_test.h
@@ -15,22 +15,17 @@
#ifndef NEARBY_PRESENCE_NP_CPP_FFI_TESTS_NP_CPP_TEST_H_
#define NEARBY_PRESENCE_NP_CPP_FFI_TESTS_NP_CPP_TEST_H_
+#include "gtest/gtest.h"
#include "nearby_protocol.h"
#include "shared_test_util.h"
-#include "gtest/gtest.h"
-
class NpCppTest : public testing::Test {
-protected:
+ protected:
static void SetUpTestSuite() {
if (!panic_handler_set) {
ASSERT_TRUE(
nearby_protocol::GlobalConfig::SetPanicHandler(test_panic_handler));
panic_handler_set = true;
- nearby_protocol::GlobalConfig::SetMaxNumDeserializedV0Advertisements(2);
- nearby_protocol::GlobalConfig::SetMaxNumDeserializedV1Advertisements(2);
- nearby_protocol::GlobalConfig::SetMaxNumCredentialSlabs(3);
- nearby_protocol::GlobalConfig::SetMaxNumCredentialBooks(2);
} else {
ASSERT_FALSE(
nearby_protocol::GlobalConfig::SetPanicHandler(test_panic_handler));
@@ -39,4 +34,4 @@ protected:
static bool panic_handler_set;
};
-#endif // NEARBY_PRESENCE_NP_CPP_FFI_TESTS_NP_CPP_TEST_H_
+#endif // NEARBY_PRESENCE_NP_CPP_FFI_TESTS_NP_CPP_TEST_H_
diff --git a/nearby/presence/np_cpp_ffi/tests/v0_encrypted_deserialization_tests.cc b/nearby/presence/np_cpp_ffi/tests/v0_encrypted_deserialization_tests.cc
new file mode 100644
index 0000000..bd1f771
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/tests/v0_encrypted_deserialization_tests.cc
@@ -0,0 +1,171 @@
+// 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 <algorithm>
+#include <array>
+#include <cstdint>
+#include <span>
+#include <string>
+
+#include "absl/status/status.h"
+#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
+
+// NOLINTBEGIN(readability-magic-numbers)
+TEST_F(NpCppTest, V0PrivateIdentityDeserializationSimpleCase) {
+ nearby_protocol::CredentialSlab slab;
+ const std::span<uint8_t> metadata_span(V0AdvEncryptedMetadata);
+ const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
+ std::array<uint8_t, 32> key_seed = {};
+ std::fill_n(key_seed.begin(), 32, 0x11);
+ const nearby_protocol::V0MatchableCredential v0_cred(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
+ slab.AddV0Credential(v0_cred);
+ nearby_protocol::CredentialBook book(slab);
+
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvEncryptedPayload, book);
+ ASSERT_EQ(deserialize_result.GetKind(),
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
+
+ auto v0_adv = deserialize_result.IntoV0();
+ auto kind = v0_adv.GetKind();
+ ASSERT_EQ(kind, nearby_protocol::DeserializedV0AdvertisementKind::Legible);
+
+ auto legible_adv = v0_adv.IntoLegible();
+ auto identity_kind = legible_adv.GetIdentityKind();
+ ASSERT_EQ(identity_kind,
+ nearby_protocol::DeserializedV0IdentityKind::Decrypted);
+ ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
+
+ auto payload = legible_adv.IntoPayload();
+ auto de = payload.TryGetDataElement(0);
+ ASSERT_TRUE(de.ok());
+
+ auto metadata = payload.TryDecryptMetadata();
+ ASSERT_TRUE(metadata.ok());
+ ASSERT_EQ(ExpectedV0DecryptedMetadata,
+ std::string(metadata->begin(), metadata->end()));
+
+ auto identity_details = payload.TryGetIdentityDetails();
+ ASSERT_TRUE(identity_details.ok());
+ ASSERT_EQ(identity_details->cred_id, 123u);
+
+ auto de_type = de->GetKind();
+ ASSERT_EQ(de_type, nearby_protocol::V0DataElementKind::TxPower);
+
+ auto tx_power_de = de->AsTxPower();
+ ASSERT_EQ(tx_power_de.GetAsI8(), 3);
+}
+
+nearby_protocol::CredentialBook CreateEmptyCredBook() {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
+ return book;
+}
+
+TEST_F(NpCppTest, V0PrivateIdentityEmptyBook) {
+ auto book = CreateEmptyCredBook();
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvEncryptedPayload, book);
+ ASSERT_EQ(deserialize_result.GetKind(),
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
+
+ auto v0_adv = deserialize_result.IntoV0();
+ ASSERT_EQ(
+ v0_adv.GetKind(),
+ nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
+
+ // Should not be able to actually access contents
+ ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
+}
+
+TEST_F(NpCppTest, V0PrivateIdentityNoMatchingCreds) {
+ nearby_protocol::CredentialSlab slab;
+ uint8_t metadata[] = {0};
+ const std::span<uint8_t> metadata_span(metadata);
+ const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
+ // A randomly picked key seed, does NOT match what was used for the canned adv
+ std::array<uint8_t, 32> key_seed = {};
+ std::fill_n(key_seed.begin(), 31, 0x11);
+ const nearby_protocol::V0MatchableCredential v0_cred(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
+ slab.AddV0Credential(v0_cred);
+
+ nearby_protocol::CredentialBook book(slab);
+
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvEncryptedPayload, book);
+ ASSERT_EQ(deserialize_result.GetKind(),
+ nearby_protocol::DeserializeAdvertisementResultKind::V0);
+
+ auto v0_adv = deserialize_result.IntoV0();
+ ASSERT_EQ(
+ v0_adv.GetKind(),
+ nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
+
+ // Should not be able to actually access contents
+ ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
+}
+
+// Make sure the correct credential is matched out of multiple provided
+TEST_F(NpCppTest, V0PrivateIdentityMultipleCredentials) {
+ nearby_protocol::CredentialSlab slab;
+ const std::span<uint8_t> metadata_span(V0AdvEncryptedMetadata);
+ std::array<uint8_t, 32> key_seed = {};
+ // Non matching credential
+ const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
+ std::fill_n(key_seed.begin(), 32, 0x12);
+ const nearby_protocol::V0MatchableCredential v0_cred(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
+ slab.AddV0Credential(v0_cred);
+
+ // Matching credential
+ const nearby_protocol::MatchedCredentialData match_data2(456, metadata_span);
+ std::fill_n(key_seed.begin(), 32, 0x11);
+ const nearby_protocol::V0MatchableCredential v0_cred2(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data2);
+ slab.AddV0Credential(v0_cred2);
+
+ // Non matching credential
+ const nearby_protocol::MatchedCredentialData match_data3(789, metadata_span);
+ std::fill_n(key_seed.begin(), 32, 0x13);
+ const nearby_protocol::V0MatchableCredential v0_cred3(
+ key_seed, V0AdvLegacyIdentityTokenHmac, match_data3);
+ slab.AddV0Credential(v0_cred3);
+
+ nearby_protocol::CredentialBook book(slab);
+ auto legible_adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V0AdvEncryptedPayload, book)
+ .IntoV0()
+ .IntoLegible();
+ ASSERT_EQ(legible_adv.GetIdentityKind(),
+ nearby_protocol::DeserializedV0IdentityKind::Decrypted);
+ ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
+
+ auto payload = legible_adv.IntoPayload();
+ ASSERT_TRUE(payload.TryGetDataElement(0).ok());
+
+ // Make sure the correct credential matches
+ auto identity_details = payload.TryGetIdentityDetails();
+ ASSERT_TRUE(identity_details.ok());
+ ASSERT_EQ(identity_details->cred_id, 456u);
+}
+// NOLINTEND(readability-magic-numbers)
diff --git a/nearby/presence/np_cpp_ffi/tests/v0_encrypted_serialization_tests.cc b/nearby/presence/np_cpp_ffi/tests/v0_encrypted_serialization_tests.cc
new file mode 100644
index 0000000..def4fb6
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/tests/v0_encrypted_serialization_tests.cc
@@ -0,0 +1,58 @@
+// 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 <algorithm>
+#include <array>
+#include <cstdint>
+
+#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
+
+// NOLINTBEGIN(readability-magic-numbers)
+
+// Corresponds to V0PrivateIdentityDeserializationSimpleCase,
+// which in turn corresponds to np_adv's examples_v0
+TEST_F(NpCppTest, V0PrivateIdentitySerializationSimpleCase) {
+ std::array<uint8_t, 32> key_seed = {};
+ std::fill_n(key_seed.begin(), 32, 0x11);
+
+ std::array<uint8_t, 14> metadata_key = {};
+ std::fill_n(metadata_key.begin(), 14, 0x33);
+
+ auto broadcast_cred =
+ nearby_protocol::V0BroadcastCredential(key_seed, metadata_key);
+
+ std::array<uint8_t, 2> salt = {};
+ std::fill_n(salt.begin(), 2, 0x22);
+
+ auto adv_builder = nearby_protocol::V0AdvertisementBuilder::CreateEncrypted(
+ broadcast_cred, salt);
+
+ auto tx_power = nearby_protocol::TxPower::TryBuildFromI8(3).value();
+ auto de = nearby_protocol::V0DataElement(tx_power);
+
+ ASSERT_TRUE(adv_builder.TryAddDE(de).ok());
+
+ auto serialized_bytes = adv_builder.TrySerialize().value();
+ auto actual = serialized_bytes.ToVector();
+
+ auto expected = V0AdvEncryptedBuffer.ToVector();
+
+ ASSERT_EQ(actual, expected);
+}
+
+// NOLINTEND(readability-magic-numbers)
diff --git a/nearby/presence/np_cpp_ffi/tests/v0_private_identity_tests.cc b/nearby/presence/np_cpp_ffi/tests/v0_private_identity_tests.cc
deleted file mode 100644
index e2a60f2..0000000
--- a/nearby/presence/np_cpp_ffi/tests/v0_private_identity_tests.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// 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 "nearby_protocol.h"
-#include "np_cpp_test.h"
-#include "gtest/gtest.h"
-
-#include <algorithm>
-
-static nearby_protocol::RawAdvertisementPayload
- V0AdvPrivateIdentity(nearby_protocol::ByteBuffer<255>(
- {20,
- {
- 0x00, // Adv Header
- 0x21, // private DE w/ a 2 byte payload
- 0x22, 0x22, // salt
- 0x85, 0xBF, 0xA8, // encrypted de contents, Tx Power with value 3
- 0x83, 0x58, 0x7C, 0x50, 0xCF, 0x98, 0x38,
- 0xA7, 0x8A, 0xC0, 0x1C, 0x96, 0xF9,
- }}));
-
-static uint8_t encrypted_metadata[] = {
- 0x26, 0xC5, 0xEA, 0xD4, 0xED, 0x58, 0xF8, 0xFC, 0xE8, 0xF4, 0xAB, 0x0C,
- 0x93, 0x2B, 0x75, 0xAA, 0x74, 0x39, 0x67, 0xDB, 0x1E, 0xF2, 0x33, 0xB5,
- 0x43, 0xCC, 0x94, 0xAA, 0xA3, 0xBB, 0xB9, 0x4C, 0xBF, 0x57, 0x77, 0xD0,
- 0x43, 0x0C, 0x7F, 0xF7, 0x36, 0x03, 0x29, 0xE0, 0x57, 0xBA, 0x97, 0x7F,
- 0xF2, 0xD1, 0x51, 0xDB, 0xC9, 0x01, 0x47, 0xE7, 0x48, 0x36,
-};
-
-static std::array<uint8_t, 32> legacy_metadata_key_hmac = {
- 0x88, 0x33, 0xDE, 0xD5, 0x4D, 0x00, 0x92, 0xE8, 0x80, 0x70, 0xD5,
- 0x1F, 0x18, 0xEC, 0x22, 0x45, 0x75, 0x7C, 0x24, 0xDF, 0xE3, 0x8C,
- 0xB2, 0xDE, 0x77, 0xB6, 0x78, 0x85, 0xFC, 0xA5, 0x67, 0x4D,
-};
-
-// The canned data in this test was taken from np_adv/tests/examples_v0.rs
-TEST_F(NpCppTest, V0PrivateIdentitySimpleCase) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
- std::span<uint8_t> metadata_span(encrypted_metadata);
- nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
-
- std::array<uint8_t, 32> key_seed = {};
- std::fill_n(key_seed.begin(), 32, 0x11);
-
- nearby_protocol::V0MatchableCredential v0_cred(
- key_seed, legacy_metadata_key_hmac, match_data);
-
- auto add_result = slab_result->AddV0Credential(v0_cred);
- ASSERT_EQ(add_result, absl::OkStatus());
-
- auto book_result =
- nearby_protocol::CredentialBook::TryCreateFromSlab(*slab_result);
- ASSERT_TRUE(book_result.ok());
-
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvPrivateIdentity, *book_result);
- ASSERT_EQ(deserialize_result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
-
- auto v0_adv = deserialize_result.IntoV0();
- auto kind = v0_adv.GetKind();
- ASSERT_EQ(kind, nearby_protocol::DeserializedV0AdvertisementKind::Legible);
-
- auto legible_adv = v0_adv.IntoLegible();
- auto identity_kind = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity_kind,
- nearby_protocol::DeserializedV0IdentityKind::Decrypted);
- ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
-
- auto payload = legible_adv.IntoPayload();
- auto de = payload.TryGetDataElement(0);
- ASSERT_TRUE(de.ok());
-
- auto metadata = payload.DecryptMetadata();
- ASSERT_TRUE(metadata.ok());
- ASSERT_EQ(std::string("{\"name\":\"Alice\",\"email\":\"alice@gmail.com\"}"),
- std::string(metadata->begin(), metadata->end()));
-
- auto identity_details = payload.GetIdentityDetails();
- ASSERT_TRUE(identity_details.ok());
- ASSERT_EQ(identity_details->cred_id, 123);
- ASSERT_EQ(identity_details->identity_type,
- nearby_protocol::EncryptedIdentityType::Private);
-
- auto de_type = de->GetKind();
- ASSERT_EQ(de_type, nearby_protocol::V0DataElementKind::TxPower);
-
- auto tx_power_de = de->AsTxPower();
- ASSERT_EQ(tx_power_de.tx_power, 3);
-}
-
-static nearby_protocol::CredentialBook CreateEmptyCredBook() {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
- return book;
-}
-
-TEST_F(NpCppTest, V0PrivateIdentityEmptyBook) {
- auto book = CreateEmptyCredBook();
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvPrivateIdentity, book);
- ASSERT_EQ(deserialize_result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
-
- auto v0_adv = deserialize_result.IntoV0();
- ASSERT_EQ(
- v0_adv.GetKind(),
- nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
-
- // Should not be able to actually access contents
- ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
-}
-
-TEST_F(NpCppTest, V0PrivateIdentityNoMatchingCreds) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
- uint8_t metadata[] = {0};
- std::span<uint8_t> metadata_span(metadata);
- nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
-
- // A randomly picked key seed, does NOT match what was used for the canned adv
- std::array<uint8_t, 32> key_seed = {};
- std::fill_n(key_seed.begin(), 31, 0x11);
-
- nearby_protocol::V0MatchableCredential v0_cred(
- key_seed, legacy_metadata_key_hmac, match_data);
-
- auto add_result = slab_result->AddV0Credential(v0_cred);
- ASSERT_EQ(add_result, absl::OkStatus());
-
- auto book_result =
- nearby_protocol::CredentialBook::TryCreateFromSlab(*slab_result);
- ASSERT_TRUE(book_result.ok());
-
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvPrivateIdentity, *book_result);
- ASSERT_EQ(deserialize_result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
-
- auto v0_adv = deserialize_result.IntoV0();
- ASSERT_EQ(
- v0_adv.GetKind(),
- nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
-
- // Should not be able to actually access contents
- ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
-}
-
-// Make sure the correct credential is matched out of multiple provided
-TEST_F(NpCppTest, V0PrivateIdentityMultipleCredentials) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- std::span<uint8_t> metadata_span(encrypted_metadata);
- std::array<uint8_t, 32> key_seed = {};
-
- // Non matching credential
- nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
- std::fill_n(key_seed.begin(), 32, 0x12);
- nearby_protocol::V0MatchableCredential v0_cred(
- key_seed, legacy_metadata_key_hmac, match_data);
- ASSERT_TRUE(slab.AddV0Credential(v0_cred).ok());
-
- // Matching credential
- nearby_protocol::MatchedCredentialData match_data2(456, metadata_span);
- std::fill_n(key_seed.begin(), 32, 0x11);
- nearby_protocol::V0MatchableCredential v0_cred2(
- key_seed, legacy_metadata_key_hmac, match_data2);
- ASSERT_TRUE(slab.AddV0Credential(v0_cred2).ok());
-
- // Non matching credential
- nearby_protocol::MatchedCredentialData match_data3(789, metadata_span);
- std::fill_n(key_seed.begin(), 32, 0x13);
- nearby_protocol::V0MatchableCredential v0_cred3(
- key_seed, legacy_metadata_key_hmac, match_data3);
- ASSERT_TRUE(slab.AddV0Credential(v0_cred3).ok());
-
- auto book =
- nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
- auto legible_adv =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvPrivateIdentity, book).IntoV0().IntoLegible();
- ASSERT_EQ(legible_adv.GetIdentityKind(),
- nearby_protocol::DeserializedV0IdentityKind::Decrypted);
- ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
-
- auto payload = legible_adv.IntoPayload();
- ASSERT_TRUE(payload.TryGetDataElement(0).ok());
-
- // Make sure the correct credential matches
- auto identity_details = payload.GetIdentityDetails();
- ASSERT_TRUE(identity_details.ok());
- ASSERT_EQ(identity_details->cred_id, 456);
- ASSERT_EQ(identity_details->identity_type,
- nearby_protocol::EncryptedIdentityType::Private);
-}
diff --git a/nearby/presence/np_cpp_ffi/tests/v0_public_identity_tests.cc b/nearby/presence/np_cpp_ffi/tests/v0_unencrypted_deserialization_tests.cc
index 3ed2d79..42819d6 100644
--- a/nearby/presence/np_cpp_ffi/tests/v0_public_identity_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/v0_unencrypted_deserialization_tests.cc
@@ -12,16 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <array>
+#include <cstdint>
+#include <utility>
+
+#include "absl/status/status.h"
+#include "gtest/gtest.h"
#include "nearby_protocol.h"
-#include "shared_test_util.h"
+#include "np_cpp_ffi_types.h"
#include "np_cpp_test.h"
-#include "gtest/gtest.h"
+#include "shared_test_util.h"
TEST_F(NpCppTest, InvalidCast) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvSimple, book);
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ book);
ASSERT_EQ(deserialize_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
@@ -31,21 +38,13 @@ TEST_F(NpCppTest, InvalidCast) {
"");
}
-TEST_F(NpCppTest, V0SingleDataElementTxPower) {
- nearby_protocol::RawAdvertisementPayload adv(
- nearby_protocol::ByteBuffer<255>({
- 4,
- {0x00, // Adv Header
- 0x03, // Public DE header
- 0x15, 0x03} // Length 1 Tx Power DE with value 3
- }));
-
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab);
- ASSERT_TRUE(maybe_credential_book.ok());
+TEST_F(NpCppTest, V0DeserializeSingleDataElementTxPower) {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook credential_book(slab);
+
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- adv, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -55,8 +54,7 @@ TEST_F(NpCppTest, V0SingleDataElementTxPower) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
@@ -68,25 +66,19 @@ TEST_F(NpCppTest, V0SingleDataElementTxPower) {
ASSERT_EQ(de.GetKind(), nearby_protocol::V0DataElementKind::TxPower);
auto tx_power = de.AsTxPower();
- ASSERT_EQ(tx_power.tx_power, 3);
+ ASSERT_EQ(tx_power.GetAsI8(), 3);
}
TEST_F(NpCppTest, V0LengthOneActionsDataElement) {
- nearby_protocol::RawAdvertisementPayload adv(
- nearby_protocol::ByteBuffer<255>({
- 4,
- {0x00, // Adv Header
- 0x03, // Public DE header
- 0x16, 0x00} // Length 1 Actions DE
- }));
-
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ const std::array<uint8_t, 3> V0AdvPlaintextLengthOneActions{0x00, 0x16, 0x00};
+ const nearby_protocol::RawAdvertisementPayload adv(
+ (nearby_protocol::ByteBuffer<255>(V0AdvPlaintextLengthOneActions)));
+
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- adv, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(adv,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -96,8 +88,7 @@ TEST_F(NpCppTest, V0LengthOneActionsDataElement) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
@@ -113,21 +104,16 @@ TEST_F(NpCppTest, V0LengthOneActionsDataElement) {
}
TEST_F(NpCppTest, V0LengthTwoActionsDataElement) {
- nearby_protocol::RawAdvertisementPayload adv(
- nearby_protocol::ByteBuffer<255>({
- 5,
- {0x00, // Adv Header
- 0x03, // Public DE header
- 0x26, 0xD0, 0x46} // Length 2 Actions DE
- }));
-
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ const std::array<uint8_t, 4> V0AdvPlaintextLengthTwoActions{0x00, 0x26, 0x40,
+ 0x40};
+ const nearby_protocol::RawAdvertisementPayload adv(
+ (nearby_protocol::ByteBuffer<255>(V0AdvPlaintextLengthTwoActions)));
+
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- adv, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(adv,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -137,8 +123,7 @@ TEST_F(NpCppTest, V0LengthTwoActionsDataElement) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
@@ -150,42 +135,24 @@ TEST_F(NpCppTest, V0LengthTwoActionsDataElement) {
ASSERT_EQ(de.GetKind(), nearby_protocol::V0DataElementKind::Actions);
auto actions = de.AsActions();
- ASSERT_EQ(actions.GetAsU32(), 0xD0460000);
+ ASSERT_EQ(actions.GetAsU32(), 0x40400000);
- ASSERT_TRUE(
- actions.HasAction(nearby_protocol::BooleanActionType::NearbyShare));
- ASSERT_TRUE(actions.HasAction(nearby_protocol::BooleanActionType::Finder));
- ASSERT_TRUE(
- actions.HasAction(nearby_protocol::BooleanActionType::FastPairSass));
+ ASSERT_TRUE(actions.HasAction(nearby_protocol::ActionType::CrossDevSdk));
+ ASSERT_TRUE(actions.HasAction(nearby_protocol::ActionType::NearbyShare));
+ ASSERT_FALSE(actions.HasAction(nearby_protocol::ActionType::ActiveUnlock));
ASSERT_FALSE(
- actions.HasAction(nearby_protocol::BooleanActionType::ActiveUnlock));
- ASSERT_FALSE(
- actions.HasAction(nearby_protocol::BooleanActionType::InstantTethering));
- ASSERT_FALSE(actions.HasAction(nearby_protocol::BooleanActionType::PhoneHub));
- ASSERT_FALSE(
- actions.HasAction(nearby_protocol::BooleanActionType::PresenceManager));
-
- ASSERT_EQ(actions.GetContextSyncSequenceNumber(), 0xD);
+ actions.HasAction(nearby_protocol::ActionType::InstantTethering));
+ ASSERT_FALSE(actions.HasAction(nearby_protocol::ActionType::PhoneHub));
}
TEST_F(NpCppTest, V0MultipleDataElements) {
- nearby_protocol::RawAdvertisementPayload adv(nearby_protocol::ByteBuffer<255>(
- {7,
- {
- 0x00, // Adv Header
- 0x03, // Public DE header
- 0x15, 0x05, // Tx Power value 5
- 0x26, 0x00, 0x46, // Length 2 Actions
- }}));
-
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
+
auto deserialize_result =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- adv, maybe_credential_book.value());
+ V0AdvPlaintextMultiDe, credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -195,8 +162,7 @@ TEST_F(NpCppTest, V0MultipleDataElements) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 2);
@@ -208,7 +174,7 @@ TEST_F(NpCppTest, V0MultipleDataElements) {
ASSERT_EQ(first_de.GetKind(), nearby_protocol::V0DataElementKind::TxPower);
auto power = first_de.AsTxPower();
- ASSERT_EQ(power.tx_power, 5);
+ ASSERT_EQ(power.GetAsI8(), 5);
auto second_de_result = payload.TryGetDataElement(1);
ASSERT_TRUE(second_de_result.ok());
@@ -216,41 +182,39 @@ TEST_F(NpCppTest, V0MultipleDataElements) {
ASSERT_EQ(second_de.GetKind(), nearby_protocol::V0DataElementKind::Actions);
auto actions = second_de.AsActions();
- ASSERT_EQ(actions.GetAsU32(), (uint32_t)0x00460000);
- ASSERT_EQ(actions.GetContextSyncSequenceNumber(), (uint8_t)0);
+ ASSERT_EQ(actions.GetAsU32(), (uint32_t)0x40400000);
}
TEST_F(NpCppTest, V0EmptyPayload) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
+
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvEmpty, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvEmpty,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::Error);
}
TEST_F(NpCppTest, TestV0AdvMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto adv = result.IntoV0();
// Now move the adv into a new value, and make sure its still valid
- nearby_protocol::DeserializedV0Advertisement moved_adv(std::move(adv));
+ const nearby_protocol::DeserializedV0Advertisement moved_adv(std::move(adv));
ASSERT_EQ(moved_adv.GetKind(),
np_ffi::internal::DeserializedV0AdvertisementKind::Legible);
// trying to use the moved object should result in a use after free which
// triggers an abort
ASSERT_DEATH([[maybe_unused]] auto failure =
- adv.IntoLegible(), // NOLINT(bugprone-use-after-move
+ adv.IntoLegible(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH([[maybe_unused]] auto failure = adv.GetKind(), "");
@@ -262,17 +226,17 @@ TEST_F(NpCppTest, TestV0AdvMoveConstructor) {
}
TEST_F(NpCppTest, TestV0AdvMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto adv = result.IntoV0();
// create a second result
auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(another_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto adv2 = another_result.IntoV0();
@@ -285,7 +249,7 @@ TEST_F(NpCppTest, TestV0AdvMoveAssignment) {
// original result should now be invalid, using it will trigger a use after
// free abort.
ASSERT_DEATH([[maybe_unused]] auto failure =
- adv.IntoLegible(), // NOLINT(bugprone-use-after-move)
+ adv.IntoLegible(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH([[maybe_unused]] auto failure = adv.GetKind(), "");
@@ -295,57 +259,41 @@ TEST_F(NpCppTest, TestV0AdvMoveAssignment) {
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.GetKind(), "");
}
-static nearby_protocol::DeserializeAdvertisementResult
-CreateAdv(nearby_protocol::CredentialBook &book) {
+nearby_protocol::DeserializeAdvertisementResult CreateAdv(
+ nearby_protocol::CredentialBook &book) {
auto adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
+ assert(adv.GetKind() ==
+ np_ffi::internal::DeserializeAdvertisementResultKind::V0);
return adv;
}
TEST_F(NpCppTest, V0AdvDestructor) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto book_result = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(book_result.ok());
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
{
- auto deserialize_result = CreateAdv(book_result.value());
- auto deserialize_result2 = CreateAdv(book_result.value());
- // Deserialize 2 advertisements, which will take up 2 slots in the handle
- // map
- ASSERT_EQ(deserialize_result.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
- ASSERT_EQ(deserialize_result2.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
-
- // Going over max amount should result in error
- auto deserialize_result3 =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book_result.value());
- ASSERT_EQ(deserialize_result3.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::Error);
+ auto deserialize_result = CreateAdv(book);
+ auto deserialize_result2 = CreateAdv(book);
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 2U);
// Calling IntoV0() should move the underlying resources into the v0
// object when both go out of scope only one should be freed
auto v0_adv = deserialize_result.IntoV0();
}
-
- // Now that the first v0 adv is out of scope, it should be de-allocated which
- // will create room for one more to be created.
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book_result.value());
- ASSERT_EQ(deserialize_result.GetKind(),
- np_ffi::internal::DeserializeAdvertisementResultKind::V0);
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 0U);
}
TEST_F(NpCppTest, V0AdvUseAfterMove) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
+
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -361,25 +309,27 @@ TEST_F(NpCppTest, V0AdvUseAfterMove) {
}
TEST_F(NpCppTest, TestLegibleAdvMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto legible = result.IntoV0().IntoLegible();
// Now move the adv into a new value, and make sure its still valid
- nearby_protocol::LegibleDeserializedV0Advertisement moved(std::move(legible));
+ const nearby_protocol::LegibleDeserializedV0Advertisement moved(
+ std::move(legible));
ASSERT_EQ(moved.GetNumberOfDataElements(), 1);
ASSERT_EQ(moved.GetIdentityKind(),
np_ffi::internal::DeserializedV0IdentityKind::Plaintext);
// trying to use the moved object should result in a use after free which
// triggers an abort
- ASSERT_DEATH([[maybe_unused]] auto failure =
- legible.GetIdentityKind(), // NOLINT(bugprone-use-after-move
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ legible.GetIdentityKind(), // NOLINT(bugprone-use-after-move)
+ "");
ASSERT_DEATH(
[[maybe_unused]] auto failure = legible.GetNumberOfDataElements(), "");
ASSERT_DEATH([[maybe_unused]] auto failure = legible.IntoPayload(), "");
@@ -388,25 +338,26 @@ TEST_F(NpCppTest, TestLegibleAdvMoveConstructor) {
// abort
nearby_protocol::LegibleDeserializedV0Advertisement moved_again(
std::move(legible));
- ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.GetIdentityKind(), "");
- ASSERT_DEATH([[maybe_unused]] auto failure =
- moved_again.GetNumberOfDataElements(),
+ ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.GetIdentityKind(),
"");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure = moved_again.GetNumberOfDataElements(),
+ "");
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.IntoPayload(), "");
}
TEST_F(NpCppTest, TestLegibleAdvMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto legible = result.IntoV0().IntoLegible();
// create a second result
auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(another_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto legible2 = another_result.IntoV0().IntoLegible();
@@ -418,9 +369,10 @@ TEST_F(NpCppTest, TestLegibleAdvMoveAssignment) {
// original result should now be invalid, using it will trigger a use after
// free abort.
- ASSERT_DEATH([[maybe_unused]] auto failure =
- legible.GetIdentityKind(), // NOLINT(bugprone-use-after-move)
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ legible.GetIdentityKind(), // NOLINT(bugprone-use-after-move)
+ "");
ASSERT_DEATH(
[[maybe_unused]] auto failure = legible.GetNumberOfDataElements(), "");
ASSERT_DEATH([[maybe_unused]] auto failure = legible.IntoPayload(), "");
@@ -428,141 +380,107 @@ TEST_F(NpCppTest, TestLegibleAdvMoveAssignment) {
// moving again should still lead to an error
auto moved_again = std::move(legible);
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.IntoPayload(), "");
- ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.GetIdentityKind(), "");
- ASSERT_DEATH([[maybe_unused]] auto failure =
- moved_again.GetNumberOfDataElements(),
+ ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.GetIdentityKind(),
"");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure = moved_again.GetNumberOfDataElements(),
+ "");
}
-nearby_protocol::LegibleDeserializedV0Advertisement
-CreateLegibleAdv(nearby_protocol::CredentialBook &book) {
+nearby_protocol::LegibleDeserializedV0Advertisement CreateLegibleAdv(
+ nearby_protocol::CredentialBook &book) {
auto adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
auto v0_adv = adv.IntoV0();
- return v0_adv.IntoLegible();
+ auto legible = v0_adv.IntoLegible();
+ assert(legible.GetIdentityKind() ==
+ nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ assert(legible.GetNumberOfDataElements() == 1U);
+ return legible;
}
TEST_F(NpCppTest, V0LegibleAdvUseAfterMove) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto legible_adv = CreateLegibleAdv(book);
// Should be able to use the valid legible adv even though its original parent
// is now out of scope.
- ASSERT_EQ(legible_adv.GetIdentityKind(),
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
- ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
[[maybe_unused]] auto payload = legible_adv.IntoPayload();
// now that the legible adv has moved into the payload it should no longer be
// valid
- ASSERT_DEATH([[maybe_unused]] auto failure = legible_adv.GetIdentityKind(), "");
- ASSERT_DEATH([[maybe_unused]] auto failure =
- legible_adv.GetNumberOfDataElements(),
+ ASSERT_DEATH([[maybe_unused]] auto failure = legible_adv.GetIdentityKind(),
"");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure = legible_adv.GetNumberOfDataElements(),
+ "");
ASSERT_DEATH([[maybe_unused]] auto failure = legible_adv.IntoPayload(), "");
}
TEST_F(NpCppTest, LegibleAdvDestructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
{
auto legible_adv = CreateLegibleAdv(book);
auto legible_adv2 = CreateLegibleAdv(book);
-
- // check that legible advs are valid.
- ASSERT_EQ(legible_adv.GetIdentityKind(),
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
- ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
- ASSERT_EQ(legible_adv2.GetIdentityKind(),
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
- ASSERT_EQ(legible_adv2.GetNumberOfDataElements(), 1);
-
- // allocation slots should be full
- ASSERT_EQ(nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book)
- .GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::Error);
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 2U);
}
-
- // Verify the handle was de-allocated when legible adv went out of scope
- auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
- ASSERT_EQ(result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
+ // Verify the handles were de-allocated when legible advs went out of scope
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 0U);
}
-nearby_protocol::V0Payload
-CreatePayload(nearby_protocol::CredentialBook &book) {
+nearby_protocol::V0Payload CreatePayload(
+ nearby_protocol::CredentialBook &book) {
auto legible_adv = CreateLegibleAdv(book);
return legible_adv.IntoPayload();
}
-TEST_F(NpCppTest, V0PayloadDestructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
- {
- auto payload = CreatePayload(book);
- auto payload2 = CreatePayload(book);
-
- // check that payload adv is valid even though its parent is out of scope
- ASSERT_TRUE(payload.TryGetDataElement(0).ok());
- ASSERT_TRUE(payload2.TryGetDataElement(0).ok());
-
- // allocation slots should be full
- ASSERT_EQ(nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book)
- .GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::Error);
- }
-
- // Now that the payload is out of scope its destructor should have been called
- // freeing the parent handle
- auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
- ASSERT_EQ(result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V0);
-}
-
TEST_F(NpCppTest, TestV0PayloadMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto payload = result.IntoV0().IntoLegible().IntoPayload();
// Now move the adv into a new value, and make sure its still valid
- nearby_protocol::V0Payload moved(std::move(payload));
+ const nearby_protocol::V0Payload moved(std::move(payload));
ASSERT_TRUE(moved.TryGetDataElement(0).ok());
ASSERT_TRUE(absl::IsOutOfRange(moved.TryGetDataElement(1).status()));
// trying to use the moved object should result in a use after free which
// triggers an abort
- ASSERT_DEATH([[maybe_unused]] auto failure = payload.TryGetDataElement(
- 0), // NOLINT(bugprone-use-after-move
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ payload.TryGetDataElement( // NOLINT(bugprone-use-after-move)
+ 0),
+ "");
// moving again should still preserve the moved state and also lead to an
// abort
- nearby_protocol::V0Payload moved_again(std::move(payload));
+ const nearby_protocol::V0Payload moved_again(std::move(payload));
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryGetDataElement(0),
"");
}
TEST_F(NpCppTest, TestV0PayloadMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto payload = result.IntoV0().IntoLegible().IntoPayload();
// create a second result
auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, book);
+ V0AdvPlaintext, book);
ASSERT_EQ(another_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V0);
auto payload2 = another_result.IntoV0().IntoLegible().IntoPayload();
@@ -573,9 +491,11 @@ TEST_F(NpCppTest, TestV0PayloadMoveAssignment) {
// original result should now be invalid, using it will trigger a use after
// free abort.
- ASSERT_DEATH([[maybe_unused]] auto failure = payload.TryGetDataElement(
- 0), // NOLINT(bugprone-use-after-move)
- "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure =
+ payload.TryGetDataElement( // NOLINT(bugprone-use-after-move)
+ 0),
+ "");
// moving again should still lead to an error
auto moved_again = std::move(payload);
@@ -583,14 +503,34 @@ TEST_F(NpCppTest, TestV0PayloadMoveAssignment) {
"");
}
+TEST_F(NpCppTest, V0PayloadDestructor) {
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
+ {
+ auto payload = CreatePayload(book);
+ auto payload2 = CreatePayload(book);
+
+ // check that payload adv is valid even though its parent is out of scope
+ ASSERT_TRUE(payload.TryGetDataElement(0).ok());
+ ASSERT_TRUE(payload2.TryGetDataElement(0).ok());
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 2U);
+ }
+
+ // Verify the handle was de-allocated when legible advs went out of scope
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.v0_payload, 0U);
+}
+
TEST_F(NpCppTest, InvalidDataElementCast) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
+
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -599,8 +539,7 @@ TEST_F(NpCppTest, InvalidDataElementCast) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
@@ -615,13 +554,12 @@ TEST_F(NpCppTest, InvalidDataElementCast) {
}
TEST_F(NpCppTest, InvalidDataElementIndex) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
+
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V0AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V0AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V0);
@@ -631,8 +569,7 @@ TEST_F(NpCppTest, InvalidDataElementIndex) {
nearby_protocol::DeserializedV0AdvertisementKind::Legible);
auto legible_adv = v0_adv.IntoLegible();
auto identity = legible_adv.GetIdentityKind();
- ASSERT_EQ(identity,
- nearby_protocol::DeserializedV0IdentityKind::Plaintext);
+ ASSERT_EQ(identity, nearby_protocol::DeserializedV0IdentityKind::Plaintext);
auto num_des = legible_adv.GetNumberOfDataElements();
ASSERT_EQ(num_des, 1);
diff --git a/nearby/presence/np_cpp_ffi/tests/v0_unencrypted_serialization_tests.cc b/nearby/presence/np_cpp_ffi/tests/v0_unencrypted_serialization_tests.cc
new file mode 100644
index 0000000..ca28233
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/tests/v0_unencrypted_serialization_tests.cc
@@ -0,0 +1,170 @@
+// 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 <cstdint>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+
+// NOLINTBEGIN(readability-magic-numbers)
+
+TEST_F(NpCppTest, TxPowerMustBeInRange) {
+ auto out_of_range_result = nearby_protocol::TxPower::TryBuildFromI8(100);
+ ASSERT_FALSE(out_of_range_result.ok());
+}
+
+TEST_F(NpCppTest, V0UnencryptedActionFlavorMustMatch) {
+ auto actions = nearby_protocol::V0Actions::BuildNewZeroed(
+ nearby_protocol::AdvertisementBuilderKind::Public);
+
+ // Try to set an encrypted-only action.
+ auto mismatch_result =
+ actions.TrySetAction(nearby_protocol::ActionType::InstantTethering, true);
+ ASSERT_FALSE(mismatch_result.ok());
+ // Verify that nothing changed about the actions.
+ ASSERT_EQ(actions.GetAsU32(), 0u);
+
+ // Try again, but with a plaintext-compatible action.
+ auto success_result =
+ actions.TrySetAction(nearby_protocol::ActionType::NearbyShare, true);
+ ASSERT_TRUE(success_result.ok());
+ ASSERT_TRUE(actions.HasAction(nearby_protocol::ActionType::NearbyShare));
+}
+
+// Corresponds to V0DeserializeSingleDataElementTxPower
+TEST_F(NpCppTest, V0SerializeSingleDataElementTxPower) {
+ auto adv_builder = nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+
+ auto tx_power = nearby_protocol::TxPower::TryBuildFromI8(3).value();
+ auto de = nearby_protocol::V0DataElement(tx_power);
+
+ auto add_de_result = adv_builder.TryAddDE(de);
+ ASSERT_TRUE(add_de_result.ok());
+
+ auto serialized_bytes = adv_builder.TrySerialize().value();
+ auto actual = serialized_bytes.ToVector();
+
+ const std::vector<uint8_t> expected{
+ 0x00, // Version header
+ 0x15, 0x03 // Length 1 Tx Power DE with value 3
+ };
+ ASSERT_EQ(actual, expected);
+}
+
+// Corresponds to V0DeserializeLengthOneActionsDataElement
+TEST_F(NpCppTest, V0SerializeLengthOneActionsDataElement) {
+ auto adv_builder = nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+ auto actions = nearby_protocol::V0Actions::BuildNewZeroed(
+ nearby_protocol::AdvertisementBuilderKind::Public);
+ auto de = nearby_protocol::V0DataElement(actions);
+
+ auto add_de_result = adv_builder.TryAddDE(de);
+ ASSERT_TRUE(add_de_result.ok());
+
+ auto serialized_bytes = adv_builder.TrySerialize().value();
+ auto actual = serialized_bytes.ToVector();
+
+ const std::vector<uint8_t> expected{
+ 0x00, // Version header
+ 0x16, 0x00 // Length 1 Actions DE
+ };
+
+ ASSERT_EQ(actual, expected);
+}
+
+// Corresponds to V0DeserializeLengthTwoActionsDataElement
+TEST_F(NpCppTest, V0SerializeLengthTwoActionsDataElement) {
+ auto adv_builder = nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+ auto actions = nearby_protocol::V0Actions::BuildNewZeroed(
+ nearby_protocol::AdvertisementBuilderKind::Public);
+
+ ASSERT_TRUE(
+ actions.TrySetAction(nearby_protocol::ActionType::NearbyShare, true)
+ .ok());
+ ASSERT_TRUE(
+ actions.TrySetAction(nearby_protocol::ActionType::CrossDevSdk, true)
+ .ok());
+
+ auto de = nearby_protocol::V0DataElement(actions);
+
+ auto add_de_result = adv_builder.TryAddDE(de);
+ ASSERT_TRUE(add_de_result.ok());
+
+ auto serialized_bytes = adv_builder.TrySerialize().value();
+ auto actual = serialized_bytes.ToVector();
+
+ const std::vector<uint8_t> expected{
+ 0x00, // Version header
+ 0x26, 0x40, 0x40 // Length 2 Actions DE
+ };
+
+ ASSERT_EQ(actual, expected);
+}
+
+// TODO: Reinstate this test.
+// TEST_F(NpCppTest, V0SerializeEmptyPayload) {
+// auto adv_builder =
+// nearby_protocol::V0AdvertisementBuilder::CreatePublic(); auto
+// serialize_result = adv_builder.TrySerialize();
+// ASSERT_FALSE(serialize_result.ok());
+//}
+
+TEST_F(NpCppTest, TestV0AdvBuilderMoveConstructor) {
+ auto adv_builder = nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+ // Move it, and ensure it's still valid.
+ nearby_protocol::V0AdvertisementBuilder moved_adv_builder(
+ std::move(adv_builder));
+
+ auto actions = nearby_protocol::V0Actions::BuildNewZeroed(
+ nearby_protocol::AdvertisementBuilderKind::Public);
+ auto actions_de = nearby_protocol::V0DataElement(actions);
+ ASSERT_TRUE(moved_adv_builder.TryAddDE(actions_de).ok());
+
+ // Trying to use the moved-out-of-object should trigger an abort
+ ASSERT_DEATH([[maybe_unused]] auto failure =
+ adv_builder.TryAddDE( // NOLINT(bugprone-use-after-move)
+ actions_de),
+ "");
+
+ // Moving again should still preserve the moved state and lead to an abort
+ nearby_protocol::V0AdvertisementBuilder moved_again(std::move(adv_builder));
+ ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryAddDE(
+ actions_de) // NOLINT(bugprone-use-after-move)
+ ,
+ "");
+}
+
+TEST_F(NpCppTest, TestV0AdvBuilderDestructor) {
+ {
+ // Get us up to the limit on the number of adv builders
+ auto adv_builder_one =
+ nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+ auto adv_builder_two =
+ nearby_protocol::V0AdvertisementBuilder::CreatePublic();
+ auto current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.v0_advertisement_builder, 2U);
+ // Destructors should run.
+ }
+ // The space from the adv builders should've been reclaimed now.
+ auto current_allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(current_allocations.v0_advertisement_builder, 0U);
+}
+
+// NOLINTEND(readability-magic-numbers)
diff --git a/nearby/presence/np_cpp_ffi/tests/v1_encrypted_deserialization_tests.cc b/nearby/presence/np_cpp_ffi/tests/v1_encrypted_deserialization_tests.cc
new file mode 100644
index 0000000..65b9730
--- /dev/null
+++ b/nearby/presence/np_cpp_ffi/tests/v1_encrypted_deserialization_tests.cc
@@ -0,0 +1,78 @@
+// 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 <array>
+#include <cstdint>
+#include <span>
+#include <vector>
+
+#include "absl/status/status.h"
+#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
+
+TEST_F(NpCppTest, V1PrivateIdentitySimpleCase) {
+ nearby_protocol::CredentialSlab slab;
+ const std::span<uint8_t> metadata_span(V1AdvEncryptedMetadata);
+ const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
+ const nearby_protocol::V1MatchableCredential v1_cred(
+ V1AdvKeySeed, V1AdvExpectedMicExtendedSaltIdentityTokenHmac,
+ V1AdvExpectedSignatureIdentityTokenHmac, V1AdvPublicKey, match_data);
+
+ auto add_result = slab.AddV1Credential(v1_cred);
+ ASSERT_EQ(add_result, absl::OkStatus());
+
+ nearby_protocol::CredentialBook book(slab);
+ auto deserialize_result =
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvEncrypted,
+ book);
+ ASSERT_EQ(deserialize_result.GetKind(),
+ nearby_protocol::DeserializeAdvertisementResultKind::V1);
+
+ auto v1_adv = deserialize_result.IntoV1();
+ ASSERT_EQ(v1_adv.GetNumUndecryptableSections(), 0);
+ ASSERT_EQ(v1_adv.GetNumLegibleSections(), 1);
+
+ auto section = v1_adv.TryGetSection(0);
+ ASSERT_TRUE(section.ok());
+ ASSERT_EQ(section->GetIdentityKind(),
+ nearby_protocol::DeserializedV1IdentityKind::Decrypted);
+ ASSERT_EQ(section->NumberOfDataElements(), 1);
+
+ auto metadata = section->TryDecryptMetadata();
+ ASSERT_TRUE(metadata.ok());
+ ASSERT_EQ(ExpectedV1DecryptedMetadata,
+ std::string(metadata->begin(), metadata->end()));
+
+ auto identity_details = section->GetIdentityDetails();
+ ASSERT_TRUE(identity_details.ok());
+ ASSERT_EQ(identity_details->cred_id, 123U);
+ ASSERT_EQ(identity_details->verification_mode,
+ nearby_protocol::V1VerificationMode::Signature);
+
+ auto de = section->TryGetDataElement(0);
+ ASSERT_TRUE(de.ok());
+ ASSERT_EQ(de->GetDataElementTypeCode(), 5U);
+ ASSERT_EQ(de->GetPayload().ToVector(), std::vector<uint8_t>{7});
+
+ auto offset = de->GetOffset();
+ auto derived_salt = section->DeriveSaltForOffset(offset);
+ ASSERT_TRUE(derived_salt.ok());
+ const std::array<uint8_t, 16> expected = {0xD5, 0x63, 0x47, 0x39, 0x77, 0x84,
+ 0x38, 0xF2, 0x91, 0xBC, 0x24, 0x21,
+ 0xAD, 0x80, 0x88, 0x16};
+ ASSERT_EQ(*derived_salt, expected);
+}
diff --git a/nearby/presence/np_cpp_ffi/tests/v1_private_identity_tests.cc b/nearby/presence/np_cpp_ffi/tests/v1_private_identity_tests.cc
deleted file mode 100644
index 8cd0bd0..0000000
--- a/nearby/presence/np_cpp_ffi/tests/v1_private_identity_tests.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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 "nearby_protocol.h"
-#include "np_cpp_test.h"
-#include "gtest/gtest.h"
-#include <algorithm>
-
-// All canned data output from np_adv/tests/examples_v1.rs
-static nearby_protocol::RawAdvertisementPayload
- V1AdvPrivateIdentity(nearby_protocol::ByteBuffer<255>(
- {105,
- {
- 0x20, 0x67, 0x91, 0x10, 0x08, 0xAD, 0x69, 0x46, 0x04, 0x5D, 0xAE,
- 0x6D, 0xB7, 0xF7, 0x5C, 0xD3, 0xB8, 0xAC, 0xF0, 0xBF, 0x75, 0x90,
- 0x01, 0xBE, 0x73, 0x33, 0xA4, 0x76, 0x84, 0x4A, 0x09, 0x0F, 0x2B,
- 0x99, 0x47, 0xDF, 0x8B, 0x46, 0xCA, 0x16, 0xCE, 0x13, 0xB5, 0x6E,
- 0x53, 0xAE, 0x28, 0x56, 0x44, 0x0E, 0xA6, 0x8D, 0xEB, 0xA1, 0x11,
- 0xAF, 0x4E, 0x1B, 0xE0, 0x8E, 0xF5, 0xBA, 0x90, 0x4F, 0x2E, 0x94,
- 0xFC, 0xDE, 0xA6, 0x7F, 0x5D, 0xC8, 0x37, 0xB7, 0xEF, 0xCA, 0xAC,
- 0x8B, 0x9F, 0x1B, 0xD4, 0xC6, 0x11, 0x85, 0xD3, 0x67, 0x39, 0x32,
- 0xD1, 0x82, 0xCA, 0x4E, 0xB9, 0x46, 0x03, 0x83, 0x68, 0x56, 0x0B,
- 0xCC, 0xFD, 0x7A, 0x2A, 0xBE, 0x07,
- }}));
-
-static std::array<uint8_t, 32> key_seed = {
- 0x31, 0x43, 0x63, 0x1E, 0xCA, 0xE8, 0x97, 0x4B, 0x96, 0x50, 0xCC,
- 0x1C, 0x48, 0x25, 0x0E, 0x81, 0x58, 0x06, 0x81, 0x51, 0xF9, 0xEB,
- 0x25, 0x23, 0x03, 0xD4, 0x97, 0x6D, 0x95, 0x19, 0x91, 0x39,
-};
-
-static std::array<uint8_t, 32> expected_unsigned_metadata_key_hmac = {0};
-
-static std::array<uint8_t, 32> expected_signed_metadata_key_hmac = {
- 0x1C, 0xBC, 0xEB, 0xDC, 0x17, 0xB5, 0x91, 0xE5, 0x07, 0x9D, 0x70,
- 0xC1, 0xE8, 0x4B, 0xCC, 0xDB, 0x4B, 0x0F, 0x76, 0x83, 0x59, 0x62,
- 0x0A, 0x2D, 0x55, 0x0B, 0x3B, 0x36, 0xA4, 0x92, 0x8B, 0x13,
-};
-
-static std::array<uint8_t, 32> public_key = {
- 0x6D, 0x0D, 0xB6, 0x09, 0x10, 0xB1, 0x4E, 0xC4, 0x7E, 0x10, 0x16,
- 0x14, 0x9C, 0x9F, 0xF2, 0x14, 0x0F, 0xEC, 0x53, 0x76, 0xE3, 0x07,
- 0xD9, 0xD3, 0x9E, 0xAE, 0xE7, 0x45, 0x2C, 0x03, 0xEC, 0x6D,
-};
-
-static uint8_t encrypted_metadata[] = {
- 0x09, 0xB8, 0xC6, 0x6B, 0x71, 0x43, 0x55, 0x4C, 0xB9, 0x9D, 0xBF,
- 0xE4, 0xAF, 0x3E, 0xA2, 0x56, 0x0E, 0x6C, 0xBC, 0xDC, 0x3F, 0x3F,
- 0x0D, 0x28, 0xD4, 0x50, 0xA9, 0xEA, 0xC3, 0x60, 0xB0, 0x81, 0x31,
- 0xE2, 0x67, 0xB5, 0xC8, 0x15, 0x0C, 0xCA, 0x0B, 0x9B, 0x2C, 0x80,
- 0xC1, 0xB1, 0xF6, 0x5F, 0xE1, 0x51, 0xF9, 0xE2, 0x23, 0x56, 0xD4,
- 0x0B, 0x89, 0xA7, 0xF3, 0x4D, 0xE8, 0x79, 0x26, 0x44, 0x7E, 0x62,
- 0xDE, 0x53, 0x13, 0x15, 0x3D, 0xFC, 0x04, 0x2E, 0x2D, 0x08, 0x43,
- 0x2E, 0xE1, 0x96, 0xE8, 0x0F, 0xD0, 0xFC, 0xDE, 0x03, 0x86, 0x23,
- 0xB6, 0x98, 0x85, 0x27, 0x67, 0xD8, 0x1D, 0xC3, 0xE2, 0xE0, 0xA4,
- 0x32, 0x1A, 0x5F, 0x51, 0x0B, 0xA8, 0xD8, 0xA7, 0x23, 0xA4, 0x57,
-};
-
-TEST_F(NpCppTest, V1PrivateIdentitySimpleCase) {
- auto slab_result = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(slab_result.ok());
-
- std::span<uint8_t> metadata_span(encrypted_metadata);
- nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
-
- nearby_protocol::V1MatchableCredential v1_cred(
- key_seed, expected_unsigned_metadata_key_hmac,
- expected_signed_metadata_key_hmac, public_key, match_data);
-
- auto add_result = slab_result->AddV1Credential(v1_cred);
- ASSERT_EQ(add_result, absl::OkStatus());
-
- auto book_result =
- nearby_protocol::CredentialBook::TryCreateFromSlab(*slab_result);
- ASSERT_TRUE(book_result.ok());
-
- auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvPrivateIdentity, *book_result);
- ASSERT_EQ(deserialize_result.GetKind(),
- nearby_protocol::DeserializeAdvertisementResultKind::V1);
-
- auto v1_adv = deserialize_result.IntoV1();
- ASSERT_EQ(v1_adv.GetNumUndecryptableSections(), 0);
- ASSERT_EQ(v1_adv.GetNumLegibleSections(), 1);
-
- auto section = v1_adv.TryGetSection(0);
- ASSERT_TRUE(section.ok());
- ASSERT_EQ(section->GetIdentityKind(),
- nearby_protocol::DeserializedV1IdentityKind::Decrypted);
- ASSERT_EQ(section->NumberOfDataElements(), 1);
-
- auto metadata = section->DecryptMetadata();
- ASSERT_TRUE(metadata.ok());
- ASSERT_EQ(
- std::string("{\"uuid\":\"378845e1-2616-420d-86f5-674177a7504d\","
- "\"display_name\":\"Alice\",\"location\":\"Wonderland\"}"),
- std::string(metadata->begin(), metadata->end()));
-
- auto identity_details = section->GetIdentityDetails();
- ASSERT_TRUE(identity_details.ok());
- ASSERT_EQ(identity_details->cred_id, 123);
- ASSERT_EQ(identity_details->verification_mode,
- nearby_protocol::V1VerificationMode::Signature);
- ASSERT_EQ(identity_details->identity_type,
- nearby_protocol::EncryptedIdentityType::Private);
-
- auto de = section->TryGetDataElement(0);
- ASSERT_TRUE(de.ok());
- ASSERT_EQ(de->GetDataElementTypeCode(), 5);
- ASSERT_EQ(de->GetPayload().ToVector(), std::vector<uint8_t>{7});
-
- auto offset = de->GetOffset();
- auto derived_salt = section->DeriveSaltForOffset(offset);
- ASSERT_TRUE(derived_salt.ok());
- std::array<uint8_t, 16> expected =
- {94, 154, 245, 152, 164, 22, 131, 157, 8, 79, 28, 77, 236, 57, 17, 97};
- ASSERT_EQ(*derived_salt, expected);
-} \ No newline at end of file
diff --git a/nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc b/nearby/presence/np_cpp_ffi/tests/v1_unencrypted_deserialization_tests.cc
index aa32f7b..4f50e0c 100644
--- a/nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc
+++ b/nearby/presence/np_cpp_ffi/tests/v1_unencrypted_deserialization_tests.cc
@@ -12,21 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "nearby_protocol.h"
-#include "shared_test_util.h"
-#include "np_cpp_test.h"
+#include <cstdint>
+#include <utility>
+#include <vector>
+#include "absl/status/status.h"
#include "gtest/gtest.h"
+#include "nearby_protocol.h"
+#include "np_cpp_ffi_types.h"
+#include "np_cpp_test.h"
+#include "shared_test_util.h"
TEST_F(NpCppTest, V1SimpleTestCase) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
+ nearby_protocol::CredentialSlab credential_slab;
+ nearby_protocol::CredentialBook credential_book(credential_slab);
auto deserialize_result =
- nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, maybe_credential_book.value());
+ nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvPlaintext,
+ credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V1);
@@ -54,28 +57,28 @@ TEST_F(NpCppTest, V1SimpleTestCase) {
auto payload = de.value().GetPayload();
auto vec = payload.ToVector();
- std::vector<uint8_t> expected{3};
+ const std::vector<uint8_t> expected{3};
ASSERT_EQ(vec, expected);
}
TEST_F(NpCppTest, TestV1AdvMoveConstructor) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, book);
+ V1AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
auto adv = result.IntoV1();
// Now move the adv into a new value, and make sure its still valid
- nearby_protocol::DeserializedV1Advertisement moved_adv(std::move(adv));
+ const nearby_protocol::DeserializedV1Advertisement moved_adv(std::move(adv));
ASSERT_EQ(moved_adv.GetNumLegibleSections(), 1);
// trying to use the moved object should result in a use after free which
// triggers an abort
ASSERT_DEATH(
[[maybe_unused]] auto failure =
- adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move
+ adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH(
[[maybe_unused]] auto failure = adv.GetNumUndecryptableSections(), "");
@@ -83,30 +86,29 @@ TEST_F(NpCppTest, TestV1AdvMoveConstructor) {
// moving again should still preserve the moved state and also lead to an
// abort
- nearby_protocol::DeserializedV1Advertisement moved_again(std::move(adv));
+ const nearby_protocol::DeserializedV1Advertisement moved_again(
+ std::move(adv));
ASSERT_DEATH(
- [[maybe_unused]] auto failure =
- moved_again.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move
+ [[maybe_unused]] auto failure = moved_again.GetNumLegibleSections(), "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure = moved_again.GetNumUndecryptableSections(),
"");
- ASSERT_DEATH([[maybe_unused]] auto failure =
- moved_again.GetNumUndecryptableSections(),
- "");
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryGetSection(0),
"");
}
TEST_F(NpCppTest, TestV1AdvMoveAssignment) {
- auto slab = nearby_protocol::CredentialSlab::TryCreate().value();
- auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value();
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
auto result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, book);
+ V1AdvPlaintext, book);
ASSERT_EQ(result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
auto adv = result.IntoV1();
// create a second result
auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, book);
+ V1AdvPlaintext, book);
ASSERT_EQ(another_result.GetKind(),
np_ffi::internal::DeserializeAdvertisementResultKind::V1);
auto adv2 = another_result.IntoV1();
@@ -119,7 +121,7 @@ TEST_F(NpCppTest, TestV1AdvMoveAssignment) {
// free abort.
ASSERT_DEATH(
[[maybe_unused]] auto failure =
- adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move
+ adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move)
"");
ASSERT_DEATH(
[[maybe_unused]] auto failure = adv.GetNumUndecryptableSections(), "");
@@ -128,71 +130,70 @@ TEST_F(NpCppTest, TestV1AdvMoveAssignment) {
// moving again should still lead to an error
auto moved_again = std::move(adv);
ASSERT_DEATH(
- [[maybe_unused]] auto failure =
- moved_again.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move
+ [[maybe_unused]] auto failure = moved_again.GetNumLegibleSections(), "");
+ ASSERT_DEATH(
+ [[maybe_unused]] auto failure = moved_again.GetNumUndecryptableSections(),
"");
- ASSERT_DEATH([[maybe_unused]] auto failure =
- moved_again.GetNumUndecryptableSections(),
- "");
ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryGetSection(0),
"");
}
-nearby_protocol::DeserializedV1Section
-GetSection(nearby_protocol::CredentialBook &book) {
+nearby_protocol::DeserializedV1Section GetSection(
+ nearby_protocol::CredentialBook &book) {
// Create the adv in this scope, so its de-allocated at the end of this call.
// The section should still be valid
- auto v1_adv =
- nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvSimple, book)
- .IntoV1();
+ auto v1_adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
+ V1AdvPlaintext, book)
+ .IntoV1();
auto section = v1_adv.TryGetSection(0);
return section.value();
}
bool TryDeserializeNewV1Adv(nearby_protocol::CredentialBook &book) {
auto adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvSimple, book);
+ V1AdvPlaintext, book);
return adv.GetKind() ==
np_ffi::internal::DeserializeAdvertisementResultKind::V1;
}
TEST_F(NpCppTest, TestSectionOwnership) {
- auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate();
- ASSERT_TRUE(maybe_credential_slab.ok());
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value());
- ASSERT_TRUE(maybe_credential_book.ok());
-
+ nearby_protocol::CredentialSlab slab;
+ nearby_protocol::CredentialBook book(slab);
{
- auto section = GetSection(maybe_credential_book.value());
+ auto section = GetSection(book);
ASSERT_EQ(section.GetIdentityKind(),
nearby_protocol::DeserializedV1IdentityKind::Plaintext);
ASSERT_EQ(section.NumberOfDataElements(), 1);
ASSERT_TRUE(section.TryGetDataElement(0).ok());
- auto section2 = GetSection(maybe_credential_book.value());
+ auto section2 = GetSection(book);
ASSERT_EQ(section2.GetIdentityKind(),
nearby_protocol::DeserializedV1IdentityKind::Plaintext);
ASSERT_EQ(section2.NumberOfDataElements(), 1);
ASSERT_TRUE(section2.TryGetDataElement(0).ok());
- ASSERT_FALSE(TryDeserializeNewV1Adv(maybe_credential_book.value()));
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.legible_v1_sections, 2U);
}
- // now that the section has gone out of scope, deserializing a new adv should
- // succeed
- ASSERT_TRUE(TryDeserializeNewV1Adv(maybe_credential_book.value()));
+ // now that the section has gone out of scope the allocation should be
+ // released
+ auto allocations =
+ nearby_protocol::GlobalConfig::GetCurrentHandleAllocationCount();
+ ASSERT_EQ(allocations.legible_v1_sections, 0U);
}
/*
* Multiple sections are not supported in plaintext advertisements
* TODO Update the below test to use encrypted sections
TEST(NpCppTest, V1MultipleSections) {
- auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreate();
- ASSERT_TRUE(maybe_credential_book.ok());
+ auto credential_book = nearby_protocol::CredentialBook::Create();
+ ASSERT_TRUE(credential_book.ok());
auto deserialize_result =
nearby_protocol::Deserializer::DeserializeAdvertisement(
- V1AdvMultipleSections, maybe_credential_book.value());
+ V1AdvMultipleSections, credential_book);
ASSERT_EQ(deserialize_result.GetKind(),
nearby_protocol::DeserializeAdvertisementResultKind::V1);
diff --git a/nearby/presence/np_ed25519/src/lib.rs b/nearby/presence/np_ed25519/src/lib.rs
index fe2ab5a..b5123e1 100644
--- a/nearby/presence/np_ed25519/src/lib.rs
+++ b/nearby/presence/np_ed25519/src/lib.rs
@@ -21,101 +21,34 @@
#![no_std]
use array_view::ArrayView;
-use crypto_provider::ed25519::{
- Ed25519Provider, KeyPair as _, PrivateKey, PublicKey as _, RawPrivateKey, RawPrivateKeyPermit,
- RawPublicKey, RawSignature, Signature as _, SignatureError,
-};
-use crypto_provider::CryptoProvider;
+use crypto_provider::ed25519::{Ed25519Provider, PrivateKey, PublicKey, Signature, SignatureError};
use sink::{Sink, SinkWriter};
use tinyvec::ArrayVec;
-/// Convenient type-alias for a crypto-provider's Ed25519 key-pair
-type CpKeyPair<C> = <<C as CryptoProvider>::Ed25519 as Ed25519Provider>::KeyPair;
-
-/// Type-alias for the Ed25519 public key type
-type CpPublicKey<C> = <<C as CryptoProvider>::Ed25519 as Ed25519Provider>::PublicKey;
-
-/// Type-alias for the Ed25519 signature type
-type CpSignature<C> = <<C as CryptoProvider>::Ed25519 as Ed25519Provider>::Signature;
-
/// Maximum length of the combined (context len byte) + (context bytes) + (signing payload)
/// byte-array which an ed25519 signature will be computed over. This is deliberately
/// chosen to be large enough to incorporate an entire v1 adv as the signing payload.
pub const MAX_SIGNATURE_BUFFER_LEN: usize = 512;
-/// Representation of an Ed25519 key-pair using the given
-/// [`CryptoProvider`] to back its implementation.
-/// Contains both the public and secret halves of an
-/// asymmetric key, and so it may be used to
-/// both sign and verify message signatures.
-pub struct KeyPair<C: CryptoProvider>(CpKeyPair<C>);
-
-impl<C: CryptoProvider> KeyPair<C> {
- /// Returns the `KeyPair`'s private key bytes.
- /// This method is only usable in situations where
- /// the caller has permission to handle the raw bytes
- /// of a private key.
- pub fn raw_private_key(&self, permit: &RawPrivateKeyPermit) -> RawPrivateKey {
- self.0.raw_private_key(permit)
- }
-
- /// Builds this key-pair from an array of its private key bytes in the format
- /// yielded by `private_key`.
- /// This method is only usable in situations where
- /// the caller has permission to handle the raw bytes
- /// of a private key.
- pub fn from_raw_private_key(private_key: &RawPrivateKey, permit: &RawPrivateKeyPermit) -> Self {
- Self(CpKeyPair::<C>::from_raw_private_key(private_key, permit))
- }
-
- /// Returns the private key of this key-pair.
- pub fn private_key(&self) -> PrivateKey {
- self.0.private_key()
- }
-
- /// Builds this key-pair from a private key.
- pub fn from_private_key(private_key: &PrivateKey) -> Self {
- Self(CpKeyPair::<C>::from_private_key(private_key))
- }
-
- /// Sign the given message with the given context and
- /// return a digital signature. The message is represented
- /// using a [`SinkWriter`] to allow the caller to construct
- /// the payload to sign without requiring a fully-assembled
- /// payload available as a slice.
- ///
- /// If the message writer writes too much data (greater than 256 bytes),
- /// this will return `None` instead of a valid signature,
- /// and so uses in `np_adv` will use `.expect` on the returned value
- /// to indicate that this length constraint has been considered.
- pub fn sign_with_context<W: SinkWriter<DataType = u8>>(
- &self,
- context: &SignatureContext,
- msg_writer: W,
- ) -> Option<Signature<C>> {
- let mut buffer = context.create_signature_buffer();
- buffer.try_extend_from_writer(msg_writer).map(|_| Signature(self.0.sign(buffer.as_ref())))
- }
-
- /// Gets the public key of this key-pair
- pub fn public(&self) -> PublicKey<C> {
- PublicKey { public_key: self.0.public() }
- }
-
- /// Generates an ed25519 keypair from a CSPRNG
- /// generate is not available in `no-std`
- #[cfg(feature = "std")]
- pub fn generate() -> Self {
- Self(CpKeyPair::<C>::generate())
- }
+/// Sign the given message with the given context and
+/// return a digital signature. The message is represented
+/// using a [`SinkWriter`] to allow the caller to construct
+/// the payload to sign without requiring a fully-assembled
+/// payload available as a slice.
+///
+/// If the message writer writes too much data (greater than 256 bytes),
+/// this will return `None` instead of a valid signature,
+/// and so uses in `np_adv` will use `.expect` on the returned value
+/// to indicate that this length constraint has been considered.
+pub fn sign_with_context<E: Ed25519Provider, W: SinkWriter<DataType = u8>>(
+ private_key: &PrivateKey,
+ context: &SignatureContext,
+ msg_writer: W,
+) -> Option<Signature> {
+ let mut buffer = context.create_signature_buffer();
+ buffer.try_extend_from_writer(msg_writer).map(|_| private_key.sign::<E>(buffer.as_ref()))
}
-/// Error raised when attempting to deserialize a key-pair
-/// from a byte-array, but the bytes do not represent a valid
-/// ed25519 key-pair
-#[derive(Debug)]
-pub struct InvalidKeyPairBytes;
-
/// Errors yielded when attempting to verify an ed25519 signature.
#[derive(Debug, PartialEq, Eq)]
pub enum SignatureVerificationError {
@@ -131,104 +64,38 @@ impl From<SignatureError> for SignatureVerificationError {
}
}
-/// Representation of an Ed25519 public key used for
-/// signature verification.
-pub struct PublicKey<C: CryptoProvider> {
- public_key: CpPublicKey<C>,
-}
-
-impl<C: CryptoProvider> PublicKey<C> {
- /// Constructs a public key for NP adv signature verification
- /// from a public key under the given crypto-provider
- pub fn new(public_key: CpPublicKey<C>) -> Self {
- Self { public_key }
- }
- /// Succeeds if the signature was a valid signature created via the corresponding
- /// keypair to this public key using the given [`SignatureContext`] on the given
- /// message payload. The message payload is represented
- /// using a [`SinkWriter`] to allow the caller to construct
- /// the payload to sign without requiring a fully-assembled
- /// payload available as a slice.
- ///
- /// If the message writer writes too much data (greater than 256 bytes),
- /// this will return `None` instead of a valid signature,
- /// and so uses in `np_adv` will use `.expect` on the returned value
- /// to indicate that this length constraint has been considered.
- pub fn verify_signature_with_context<W: SinkWriter<DataType = u8>>(
- &self,
- context: &SignatureContext,
- msg_writer: W,
- signature: &Signature<C>,
- ) -> Result<(), SignatureVerificationError> {
- let mut buffer = context.create_signature_buffer();
- let maybe_write_success = buffer.try_extend_from_writer(msg_writer);
- match maybe_write_success {
- Some(_) => {
- self.public_key.verify_strict(buffer.as_ref(), &signature.0)?;
- Ok(())
- }
- None => Err(SignatureVerificationError::PayloadTooBig),
+/// Succeeds if the signature was a valid signature created via the corresponding
+/// keypair to this public key using the given [`SignatureContext`] on the given
+/// message payload. The message payload is represented
+/// using a [`SinkWriter`] to allow the caller to construct
+/// the payload to sign without requiring a fully-assembled
+/// payload available as a slice.
+///
+/// If the message writer writes too much data (greater than 256 bytes),
+/// this will return `None` instead of a valid signature,
+/// and so uses in `np_adv` will use `.expect` on the returned value
+/// to indicate that this length constraint has been considered.
+pub fn verify_signature_with_context<E: Ed25519Provider, W: SinkWriter<DataType = u8>>(
+ public_key: &PublicKey,
+ context: &SignatureContext,
+ msg_writer: W,
+ signature: Signature,
+) -> Result<(), SignatureVerificationError> {
+ let mut buffer = context.create_signature_buffer();
+ let maybe_write_success = buffer.try_extend_from_writer(msg_writer);
+ match maybe_write_success {
+ Some(_) => {
+ public_key.verify_strict::<E>(buffer.as_ref(), signature)?;
+ Ok(())
}
- }
-
- /// Builds an ed25519 public key from an array of bytes in
- /// the format yielded by `to_bytes`.
- pub fn from_bytes(bytes: &RawPublicKey) -> Result<Self, InvalidPublicKeyBytes> {
- CpPublicKey::<C>::from_bytes(bytes)
- .map(|public_key| Self { public_key })
- .map_err(|_| InvalidPublicKeyBytes)
- }
-
- /// Yields the bytes of this ed25519 public key
- pub fn to_bytes(&self) -> RawPublicKey {
- self.public_key.to_bytes()
- }
-}
-
-impl<C: CryptoProvider> Clone for PublicKey<C> {
- fn clone(&self) -> Self {
- #[allow(clippy::expect_used)]
- Self::from_bytes(&self.to_bytes()).expect("This should always succeed since self will always contain valid public key bytes, which is verified on creation")
- }
-}
-
-/// Error raised when attempting to deserialize a public key
-/// from a byte-array, but the bytes do not represent a valid
-/// ed25519 public key
-#[derive(Debug)]
-pub struct InvalidPublicKeyBytes;
-
-/// Representation of an Ed25519 message signature,
-/// which can be checked against a [`PublicKey`]
-/// for validity.
-pub struct Signature<C: CryptoProvider>(CpSignature<C>);
-
-impl<C: CryptoProvider> Signature<C> {
- /// Returns a slice of the signature bytes
- pub fn to_bytes(&self) -> RawSignature {
- self.0.to_bytes()
- }
-}
-
-/// Error raised when attempting to construct a [`Signature`]
-/// from a byte-array which is not of the proper length or format.
-#[derive(Debug)]
-pub struct InvalidSignatureBytes;
-
-impl<C: CryptoProvider> TryFrom<&[u8]> for Signature<C> {
- type Error = InvalidSignatureBytes;
- fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
- bytes
- .try_into()
- .map(|sig| Self(CpSignature::<C>::from_bytes(sig)))
- .map_err(|_| InvalidSignatureBytes)
+ None => Err(SignatureVerificationError::PayloadTooBig),
}
}
/// Minimum length (in bytes) for a [`SignatureContext`] (which cannot be empty).
pub const MIN_SIGNATURE_CONTEXT_LEN: usize = 1;
-/// Maximum length (in bytes) for a [`SignatureContext`] (which uses a 8-bit length field).
+/// Maximum length (in bytes) for a [`SignatureContext`] (which uses an 8-bit length field).
pub const MAX_SIGNATURE_CONTEXT_LEN: usize = 255;
/// (Non-empty) context bytes to use in the construction of NP's
diff --git a/nearby/presence/np_ffi_core/Cargo.toml b/nearby/presence/np_ffi_core/Cargo.toml
index 6c9a6f4..7c3c112 100644
--- a/nearby/presence/np_ffi_core/Cargo.toml
+++ b/nearby/presence/np_ffi_core/Cargo.toml
@@ -18,9 +18,10 @@ crypto_provider.workspace = true
crypto_provider_default = { workspace = true, default-features = false }
lock_adapter.workspace = true
lazy_static.workspace = true
+strum.workspace = true
+strum_macros.workspace = true
[features]
default = ["rustcrypto"]
rustcrypto = ["crypto_provider_default/rustcrypto", "crypto_provider_default/std"]
-opensslbssl = ["crypto_provider_default/opensslbssl"]
boringssl = ["crypto_provider_default/boringssl"]
diff --git a/nearby/presence/np_ffi_core/src/common.rs b/nearby/presence/np_ffi_core/src/common.rs
index 5996e80..592e1cd 100644
--- a/nearby/presence/np_ffi_core/src/common.rs
+++ b/nearby/presence/np_ffi_core/src/common.rs
@@ -18,11 +18,10 @@ use array_view::ArrayView;
use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
use handle_map::HandleNotPresentError;
-use lock_adapter::std::{RwLock, RwLockWriteGuard};
+use lock_adapter::stdlib::{RwLock, RwLockWriteGuard};
use lock_adapter::RwLock as _;
-use std::string::String;
-pub(crate) const DEFAULT_MAX_HANDLES: u32 = u32::MAX - 1;
+const MAX_HANDLES: u32 = u32::MAX - 1;
/// Configuration for top-level constants to be used
/// by the rest of the FFI which are independent of
@@ -41,34 +40,6 @@ pub struct CommonConfig {
/// assuming that that call completes successfully.
/// - In all other cases, 16 shards will be used by default.
num_shards: u8,
-
- /// The maximum number of credential slabs which may be active
- /// at any one time. By default, this value will be set to
- /// `u32::MAX - 1`, which is the upper-bound on this value.
- max_num_credential_slabs: u32,
-
- /// The maximum number of credential books which may be active
- /// at any one time. By default, this value will be set to
- /// `u32::MAX - 1`, which is the upper-bound on this value.
- max_num_credential_books: u32,
-
- /// The maximum number of deserialized v0 advertisements
- /// which may be active at any one time. By default, this
- /// value will be set to `u32::MAX - 1`, which is the upper-bound
- /// on this value.
- max_num_deserialized_v0_advertisements: u32,
-
- /// The maximum number of deserialized v1 advertisements
- /// which may be active at any one time. By default, this
- /// value will be set to `u32::MAX - 1`, which is the upper-bound
- /// on this value.
- max_num_deserialized_v1_advertisements: u32,
-
- /// The maximum number of v1 advertisement builders
- /// which may be active at any one time. By default, this
- /// value will be set to `u32::MAX - 1`, which is the upper-bound
- /// on this value.
- max_num_v1_advertisement_builders: u32,
}
impl Default for CommonConfig {
@@ -79,14 +50,7 @@ impl Default for CommonConfig {
impl CommonConfig {
pub(crate) const fn new() -> Self {
- Self {
- num_shards: 0,
- max_num_credential_slabs: DEFAULT_MAX_HANDLES,
- max_num_credential_books: DEFAULT_MAX_HANDLES,
- max_num_deserialized_v0_advertisements: DEFAULT_MAX_HANDLES,
- max_num_deserialized_v1_advertisements: DEFAULT_MAX_HANDLES,
- max_num_v1_advertisement_builders: DEFAULT_MAX_HANDLES,
- }
+ Self { num_shards: 0 }
}
#[cfg(feature = "std")]
pub(crate) fn num_shards(&self) -> u8 {
@@ -107,92 +71,23 @@ impl CommonConfig {
self.num_shards
}
}
- pub(crate) fn max_num_credential_slabs(&self) -> u32 {
- self.max_num_credential_slabs
- }
- pub(crate) fn max_num_credential_books(&self) -> u32 {
- self.max_num_credential_books
- }
- pub(crate) fn max_num_deserialized_v0_advertisements(&self) -> u32 {
- self.max_num_deserialized_v0_advertisements
- }
- pub(crate) fn max_num_deserialized_v1_advertisements(&self) -> u32 {
- self.max_num_deserialized_v1_advertisements
- }
- pub(crate) fn max_num_v1_advertisement_builders(&self) -> u32 {
- self.max_num_v1_advertisement_builders
- }
pub(crate) fn set_num_shards(&mut self, num_shards: u8) {
self.num_shards = num_shards
}
+}
- /// Sets the maximum number of active handles to credential-books
- /// which may be active at any one time.
- /// Max value: `u32::MAX - 1`.
- pub fn set_max_num_credential_books(&mut self, max_num_credential_books: u32) {
- self.max_num_credential_books = DEFAULT_MAX_HANDLES.min(max_num_credential_books)
- }
-
- /// Sets the maximum number of active handles to credential-slabs
- /// which may be active at any one time.
- /// Max value: `u32::MAX - 1`.
- pub fn set_max_num_credential_slabs(&mut self, max_num_credential_slabs: u32) {
- self.max_num_credential_slabs = DEFAULT_MAX_HANDLES.min(max_num_credential_slabs)
- }
-
- /// Sets the maximum number of active handles to deserialized v0
- /// advertisements which may be active at any one time.
- /// Max value: `u32::MAX - 1`.
- pub fn set_max_num_deserialized_v0_advertisements(
- &mut self,
- max_num_deserialized_v0_advertisements: u32,
- ) {
- self.max_num_deserialized_v0_advertisements =
- DEFAULT_MAX_HANDLES.min(max_num_deserialized_v0_advertisements)
- }
-
- /// Sets the maximum number of active handles to deserialized v1
- /// advertisements which may be active at any one time.
- /// Max value: `u32::MAX - 1`.
- pub fn set_max_num_deserialized_v1_advertisements(
- &mut self,
- max_num_deserialized_v1_advertisements: u32,
- ) {
- self.max_num_deserialized_v1_advertisements =
- DEFAULT_MAX_HANDLES.min(max_num_deserialized_v1_advertisements)
- }
- /// Sets the maximum number of active handles to v1 advertisement
- /// builders which may be active at any one time.
- /// Max value: `u32::MAX - 1`.
- pub fn set_max_num_v1_advertisement_builders(
- &mut self,
- max_num_v1_advertisement_builders: u32,
- ) {
- self.max_num_v1_advertisement_builders =
- DEFAULT_MAX_HANDLES.min(max_num_v1_advertisement_builders)
+pub(crate) fn default_handle_map_dimensions() -> handle_map::HandleMapDimensions {
+ handle_map::HandleMapDimensions {
+ num_shards: global_num_shards(),
+ max_active_handles: MAX_HANDLES,
}
}
static COMMON_CONFIG: RwLock<CommonConfig> = RwLock::new(CommonConfig::new());
-pub(crate) fn global_num_shards() -> u8 {
+fn global_num_shards() -> u8 {
COMMON_CONFIG.read().num_shards()
}
-pub(crate) fn global_max_num_credential_slabs() -> u32 {
- COMMON_CONFIG.read().max_num_credential_slabs()
-}
-pub(crate) fn global_max_num_credential_books() -> u32 {
- COMMON_CONFIG.read().max_num_credential_books()
-}
-pub(crate) fn global_max_num_deserialized_v0_advertisements() -> u32 {
- COMMON_CONFIG.read().max_num_deserialized_v0_advertisements()
-}
-pub(crate) fn global_max_num_deserialized_v1_advertisements() -> u32 {
- COMMON_CONFIG.read().max_num_deserialized_v1_advertisements()
-}
-pub(crate) fn global_max_num_v1_advertisement_builders() -> u32 {
- COMMON_CONFIG.read().max_num_v1_advertisement_builders()
-}
/// Sets an override to the number of shards to employ in the NP FFI's
/// internal handle-maps, which places an upper bound on the number
@@ -213,69 +108,43 @@ pub fn global_config_set_num_shards(num_shards: u8) {
config.set_num_shards(num_shards);
}
-/// Sets the maximum number of active handles to credential slabs
-/// which may be active at any one time. Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential slabs.
-pub fn global_config_set_max_num_credential_slabs(max_num_credential_slabs: u32) {
- let mut config = COMMON_CONFIG.write();
- config.set_max_num_credential_slabs(max_num_credential_slabs);
-}
-/// Sets the maximum number of active handles to credential books
-/// which may be active at any one time. Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call utilizing credential books.
-pub fn global_config_set_max_num_credential_books(max_num_credential_books: u32) {
- let mut config = COMMON_CONFIG.write();
- config.set_max_num_credential_books(max_num_credential_books);
-}
-
-/// Sets the maximum number of active handles to deserialized v0
-/// advertisements which may be active at any one time.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V0 advertisement.
-pub fn global_config_set_max_num_deserialized_v0_advertisements(
- max_num_deserialized_v0_advertisements: u32,
-) {
- let mut config = COMMON_CONFIG.write();
- config.set_max_num_deserialized_v0_advertisements(max_num_deserialized_v0_advertisements);
+/// Holds the count of handles currently allocated for each handle type
+#[repr(C)]
+pub struct CurrentHandleAllocations {
+ cred_book: u32,
+ cred_slab: u32,
+ decrypted_metadata: u32,
+ v0_payload: u32,
+ legible_v1_sections: u32,
+ v0_advertisement_builder: u32,
+ v1_advertisement_builder: u32,
}
-/// Sets the maximum number of active handles to deserialized v1
-/// advertisements which may be active at any one time.
-/// Max value: `u32::MAX - 1`.
-///
-/// Setting this value will have no effect if the handle-maps for the
-/// API have already begun being used by the client code, and any
-/// values set will take effect upon the first usage of any API
-/// call which references or returns a deserialized V1 advertisement.
-pub fn global_config_set_max_num_deserialized_v1_advertisements(
- max_num_deserialized_v1_advertisements: u32,
-) {
- let mut config = COMMON_CONFIG.write();
- config.set_max_num_deserialized_v1_advertisements(max_num_deserialized_v1_advertisements);
+/// Returns the count of currently allocated handle types being held by the rust layer. Useful
+/// for debugging, logging, and testing.
+pub fn global_config_get_current_allocation_count() -> CurrentHandleAllocations {
+ CurrentHandleAllocations {
+ cred_book: crate::credentials::credential_book::get_current_allocation_count(),
+ cred_slab: crate::credentials::credential_slab::get_current_allocation_count(),
+ decrypted_metadata: crate::deserialize::decrypted_metadata::get_current_allocation_count(),
+ v0_payload: crate::deserialize::v0::v0_payload::get_current_allocation_count(),
+ legible_v1_sections:
+ crate::deserialize::v1::legible_v1_sections::get_current_allocation_count(),
+ v0_advertisement_builder:
+ crate::serialize::v0::advertisement_builder::get_current_allocation_count(),
+ v1_advertisement_builder:
+ crate::serialize::v1::advertisement_builder::get_current_allocation_count(),
+ }
}
-// API surfaces:
-
/// A result-type enum which tells the caller whether/not a deallocation
/// succeeded or failed due to the requested handle not being present.
#[repr(C)]
pub enum DeallocateResult {
/// The requested handle to deallocate was not present in the map
- NotPresent = 0,
+ NotPresent = 1,
/// The object behind the handle was successfully deallocated
- Success = 1,
+ Success = 2,
}
impl From<Result<(), HandleNotPresentError>> for DeallocateResult {
@@ -319,6 +188,7 @@ pub struct ByteBuffer<const N: usize> {
}
/// A FFI safe wrapper of a fixed size array
+#[derive(Clone)]
#[repr(C)]
pub struct FixedSizeArray<const N: usize>([u8; N]);
@@ -331,6 +201,11 @@ impl<const N: usize> FixedSizeArray<N> {
pub fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
+ /// De-structures this FFI-compatible fixed-size array
+ /// into a bare Rust fixed size array.
+ pub fn into_array(self) -> [u8; N] {
+ self.0
+ }
}
impl<const N: usize> ByteBuffer<N> {
@@ -377,42 +252,15 @@ pub(crate) fn get_global_crypto_rng() -> RwLockWriteGuard<'static, LazyInitCrypt
CRYPTO_RNG.write()
}
-/// The DE type for an encrypted identity
-#[derive(Clone, Copy)]
-#[repr(u8)]
-pub enum EncryptedIdentityType {
- /// Identity for broadcasts to nearby devices with the same
- /// logged-in-account (for some account).
- Private = 1,
- /// Identity for broadcasts to nearby devices which this
- /// device has declared to trust.
- Trusted = 2,
- /// Identity for broadcasts to devices which have been provisioned
- /// offline with this device.
- Provisioned = 4,
-}
-
-impl From<EncryptedIdentityType> for np_adv::de_type::EncryptedIdentityDataElementType {
- fn from(val: EncryptedIdentityType) -> np_adv::de_type::EncryptedIdentityDataElementType {
- use np_adv::de_type::EncryptedIdentityDataElementType;
- match val {
- EncryptedIdentityType::Private => EncryptedIdentityDataElementType::Private,
- EncryptedIdentityType::Trusted => EncryptedIdentityDataElementType::Trusted,
- EncryptedIdentityType::Provisioned => EncryptedIdentityDataElementType::Provisioned,
- }
- }
-}
-
-impl From<np_adv::de_type::EncryptedIdentityDataElementType> for EncryptedIdentityType {
- fn from(value: np_adv::de_type::EncryptedIdentityDataElementType) -> Self {
- use np_adv::de_type::EncryptedIdentityDataElementType;
- match value {
- EncryptedIdentityDataElementType::Private => Self::Private,
- EncryptedIdentityDataElementType::Trusted => Self::Trusted,
- EncryptedIdentityDataElementType::Provisioned => Self::Provisioned,
- }
- }
-}
+/// Error returned if the bit representation of a supposedly-Rust-constructed
+/// -and-validated type actually doesn't correspond to the format of the
+/// data structure expected on the Rust side of the boundary, and performing
+/// further operations on the structure would yield unintended behavior.
+/// If this kind of error is being raised, the foreign lang code must
+/// be messing with stack-allocated data structures for this library
+/// in an entirely unexpected way.
+#[derive(Debug)]
+pub struct InvalidStackDataStructure;
/// Error raised when attempting to cast an enum to
/// one of its variants, but the value is actually
diff --git a/nearby/presence/np_ffi_core/src/credentials.rs b/nearby/presence/np_ffi_core/src/credentials.rs
index c1fc808..1ad303f 100644
--- a/nearby/presence/np_ffi_core/src/credentials.rs
+++ b/nearby/presence/np_ffi_core/src/credentials.rs
@@ -15,32 +15,30 @@
use crate::common::*;
use crate::utils::{FfiEnum, LocksLongerThan};
+use crypto_provider::{ed25519, CryptoProvider};
use crypto_provider_default::CryptoProviderImpl;
-use handle_map::{
- declare_handle_map, HandleLike, HandleMapDimensions, HandleMapFullError,
- HandleMapTryAllocateError,
-};
+use handle_map::{declare_handle_map, HandleLike, HandleMapFullError, HandleMapTryAllocateError};
+use np_adv::extended;
use std::sync::Arc;
+type Ed25519ProviderImpl = <CryptoProviderImpl as CryptoProvider>::Ed25519;
+
/// Cryptographic information about a particular V0 discovery credential
/// necessary to match and decrypt encrypted V0 advertisements.
#[repr(C)]
pub struct V0DiscoveryCredential {
key_seed: [u8; 32],
- legacy_metadata_key_hmac: [u8; 32],
+ identity_token_hmac: [u8; 32],
}
impl V0DiscoveryCredential {
/// Constructs a new V0 discovery credential with the given 32-byte key-seed
/// and the given 32-byte HMAC for the (14-byte) legacy metadata key.
- pub fn new(key_seed: [u8; 32], legacy_metadata_key_hmac: [u8; 32]) -> Self {
- Self { key_seed, legacy_metadata_key_hmac }
+ pub fn new(key_seed: [u8; 32], identity_token_hmac: [u8; 32]) -> Self {
+ Self { key_seed, identity_token_hmac }
}
fn into_internal(self) -> np_adv::credential::v0::V0DiscoveryCredential {
- np_adv::credential::v0::V0DiscoveryCredential::new(
- self.key_seed,
- self.legacy_metadata_key_hmac,
- )
+ np_adv::credential::v0::V0DiscoveryCredential::new(self.key_seed, self.identity_token_hmac)
}
}
@@ -49,8 +47,9 @@ impl V0DiscoveryCredential {
#[repr(C)]
pub struct V1DiscoveryCredential {
key_seed: [u8; 32],
- expected_unsigned_metadata_key_hmac: [u8; 32],
- expected_signed_metadata_key_hmac: [u8; 32],
+ expected_mic_short_salt_identity_token_hmac: [u8; 32],
+ expected_mic_extended_salt_identity_token_hmac: [u8; 32],
+ expected_signature_identity_token_hmac: [u8; 32],
pub_key: [u8; 32],
}
@@ -60,24 +59,30 @@ impl V1DiscoveryCredential {
/// the metadata key, and the given public key for signature verification.
pub fn new(
key_seed: [u8; 32],
- expected_unsigned_metadata_key_hmac: [u8; 32],
- expected_signed_metadata_key_hmac: [u8; 32],
+ expected_mic_short_salt_identity_token_hmac: [u8; 32],
+ expected_mic_extended_salt_identity_token_hmac: [u8; 32],
+ expected_signature_identity_token_hmac: [u8; 32],
pub_key: [u8; 32],
) -> Self {
Self {
key_seed,
- expected_unsigned_metadata_key_hmac,
- expected_signed_metadata_key_hmac,
+ expected_mic_short_salt_identity_token_hmac,
+ expected_mic_extended_salt_identity_token_hmac,
+ expected_signature_identity_token_hmac,
pub_key,
}
}
- fn into_internal(self) -> np_adv::credential::v1::V1DiscoveryCredential {
- np_adv::credential::v1::V1DiscoveryCredential::new(
+ fn into_internal(
+ self,
+ ) -> Result<np_adv::credential::v1::V1DiscoveryCredential, ed25519::InvalidPublicKeyBytes> {
+ let public_key = ed25519::PublicKey::from_bytes::<Ed25519ProviderImpl>(self.pub_key)?;
+ Ok(np_adv::credential::v1::V1DiscoveryCredential::new(
self.key_seed,
- self.expected_unsigned_metadata_key_hmac,
- self.expected_signed_metadata_key_hmac,
- self.pub_key,
- )
+ self.expected_mic_short_salt_identity_token_hmac,
+ self.expected_mic_extended_salt_identity_token_hmac,
+ self.expected_signature_identity_token_hmac,
+ public_key,
+ ))
}
}
@@ -104,8 +109,11 @@ impl MatchedCredential {
/// (some arbitrary `u32` identifier) and encrypted metadata bytes,
/// copied from the given slice.
pub fn new(cred_id: u32, encrypted_metadata_bytes: &[u8]) -> Self {
- let encrypted_metadata_bytes = encrypted_metadata_bytes.to_vec().into_boxed_slice();
- let encrypted_metadata_bytes = Arc::from(encrypted_metadata_bytes);
+ Self::from_arc_bytes(cred_id, encrypted_metadata_bytes.to_vec().into())
+ }
+ /// Constructs a new matched credential from the given match-id
+ /// (some arbitrary `u32` identifier) and encrypted metadata bytes.
+ pub fn from_arc_bytes(cred_id: u32, encrypted_metadata_bytes: Arc<[u8]>) -> Self {
Self { cred_id, encrypted_metadata_bytes }
}
/// Gets the pre-specified numerical identifier for this matched-credential.
@@ -122,7 +130,7 @@ impl PartialEq<MatchedCredential> for MatchedCredential {
impl Eq for MatchedCredential {}
-impl np_adv::credential::MatchedCredential for MatchedCredential {
+impl np_adv::credential::matched::MatchedCredential for MatchedCredential {
type EncryptedMetadata = Arc<[u8]>;
type EncryptedMetadataFetchError = core::convert::Infallible;
fn fetch_encrypted_metadata(&self) -> Result<Arc<[u8]>, core::convert::Infallible> {
@@ -152,9 +160,10 @@ impl CredentialSlabInternals {
discovery_credential: V0DiscoveryCredential,
match_data: MatchedCredential,
) {
- let discovery_credential = discovery_credential.into_internal();
- let matchable_credential =
- np_adv::credential::MatchableCredential { discovery_credential, match_data };
+ let matchable_credential = np_adv::credential::MatchableCredential {
+ discovery_credential: discovery_credential.into_internal(),
+ match_data,
+ };
self.v0_creds.push(matchable_credential);
}
/// Adds the given V1 discovery credential with the given
@@ -164,11 +173,12 @@ impl CredentialSlabInternals {
&mut self,
discovery_credential: V1DiscoveryCredential,
match_data: MatchedCredential,
- ) {
- let discovery_credential = discovery_credential.into_internal();
- let matchable_credential =
- np_adv::credential::MatchableCredential { discovery_credential, match_data };
- self.v1_creds.push(matchable_credential);
+ ) -> Result<(), ed25519::InvalidPublicKeyBytes> {
+ discovery_credential.into_internal().map(|dc| {
+ let matchable_credential =
+ np_adv::credential::MatchableCredential { discovery_credential: dc, match_data };
+ self.v1_creds.push(matchable_credential);
+ })
}
}
@@ -200,64 +210,76 @@ impl From<Result<CredentialSlab, HandleMapFullError>> for CreateCredentialSlabRe
}
}
-/// Result type for trying to add a credential to a credential-slab.
+/// Result type for trying to add a V1 credential to a credential-slab.
#[repr(u8)]
-pub enum AddCredentialToSlabResult {
+pub enum AddV1CredentialToSlabResult {
/// We succeeded in adding the credential to the slab.
Success = 0,
/// The handle to the slab was actually invalid.
InvalidHandle = 1,
+ /// The provided public key bytes do not actually represent a valid "edwards y" format
+ /// or that said compressed point is not actually a point on the curve.
+ InvalidPublicKeyBytes = 2,
}
-declare_handle_map! {
- mod credential_slab {
- #[dimensions = super::get_credential_slab_handle_map_dimensions()]
- type CredentialSlab: HandleLike<Object = super::CredentialSlabInternals>;
- }
+/// Result type for trying to add a V0 credential to a credential-slab.
+#[repr(u8)]
+pub enum AddV0CredentialToSlabResult {
+ /// We succeeded in adding the credential to the slab.
+ Success = 0,
+ /// The handle to the slab was actually invalid.
+ InvalidHandle = 1,
}
-use credential_slab::CredentialSlab;
-fn get_credential_slab_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions {
- num_shards: global_num_shards(),
- max_active_handles: global_max_num_credential_slabs(),
- }
+/// A `#[repr(C)]` handle to a value of type `CredentialSlabInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct CredentialSlab {
+ handle_id: u64,
}
+declare_handle_map!(
+ credential_slab,
+ crate::common::default_handle_map_dimensions(),
+ super::CredentialSlab,
+ super::CredentialSlabInternals
+);
+
impl CredentialSlab {
- /// Adds the given V0 discovery credential with some associated
- /// match-data to this credential slab.
+ /// Adds the given V0 discovery credential with some associated match-data to this credential
+ /// slab. This uses the handle but does not transfer ownership of it.
pub fn add_v0(
&self,
discovery_credential: V0DiscoveryCredential,
match_data: MatchedCredential,
- ) -> AddCredentialToSlabResult {
+ ) -> AddV0CredentialToSlabResult {
match self.get_mut() {
Ok(mut write_guard) => {
write_guard.add_v0(discovery_credential, match_data);
- AddCredentialToSlabResult::Success
+ AddV0CredentialToSlabResult::Success
}
- Err(_) => AddCredentialToSlabResult::InvalidHandle,
+ Err(_) => AddV0CredentialToSlabResult::InvalidHandle,
}
}
- /// Adds the given V1 discovery credential with some associated
- /// match-data to this credential slab.
+ /// Adds the given V1 discovery credential with some associated match-data to this credential
+ /// slab. This uses the handle but does not transfer ownership of it.
pub fn add_v1(
&self,
discovery_credential: V1DiscoveryCredential,
match_data: MatchedCredential,
- ) -> AddCredentialToSlabResult {
+ ) -> AddV1CredentialToSlabResult {
match self.get_mut() {
- Ok(mut write_guard) => {
- write_guard.add_v1(discovery_credential, match_data);
- AddCredentialToSlabResult::Success
- }
- Err(_) => AddCredentialToSlabResult::InvalidHandle,
+ Ok(mut write_guard) => match write_guard.add_v1(discovery_credential, match_data) {
+ Ok(_) => AddV1CredentialToSlabResult::Success,
+ Err(_) => AddV1CredentialToSlabResult::InvalidPublicKeyBytes,
+ },
+ Err(_) => AddV1CredentialToSlabResult::InvalidHandle,
}
}
}
-/// Allocates a new credential-slab, returning a handle to the created object
+/// Allocates a new credential-slab, returning a handle to the created object. The caller is given
+/// ownership of the created handle.
pub fn create_credential_slab() -> CreateCredentialSlabResult {
CredentialSlab::allocate(CredentialSlabInternals::new).into()
}
@@ -291,20 +313,19 @@ impl CredentialBookInternals {
}
}
-fn get_credential_book_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions {
- num_shards: global_num_shards(),
- max_active_handles: global_max_num_credential_books(),
- }
+/// A `#[repr(C)]` handle to a value of type `CredentialBookInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct CredentialBook {
+ handle_id: u64,
}
-declare_handle_map! {
- mod credential_book {
- #[dimensions = super::get_credential_book_handle_map_dimensions()]
- type CredentialBook: HandleLike<Object = super::CredentialBookInternals>;
- }
-}
-pub use credential_book::CredentialBook;
+declare_handle_map!(
+ credential_book,
+ crate::common::default_handle_map_dimensions(),
+ super::CredentialBook,
+ super::CredentialBookInternals
+);
/// Discriminant for `CreateCredentialBookResult`
#[repr(u8)]
@@ -331,7 +352,10 @@ pub enum CreateCredentialBookResult {
impl LocksLongerThan<CredentialSlab> for CredentialBook {}
-/// Allocates a new credential-book, returning a handle to the created object
+/// Allocates a new credential-book, returning a handle to the created object. This takes ownership
+/// of the `credential_slab` handle except in the case where `NoSpaceLeft` is the error returned.
+/// In that case the caller will retain ownership of the slab handle. The caller is given ownership
+/// of the returned credential book handle if present.
pub fn create_credential_book_from_slab(
credential_slab: CredentialSlab,
) -> CreateCredentialBookResult {
@@ -371,22 +395,51 @@ impl CreateCredentialBookResult {
declare_enum_cast! {into_success, Success, CredentialBook}
}
-/// Deallocates a credential-book by its handle
+/// Deallocates a credential-book by its handle. This takes ownership of the credential book
+/// handle.
pub fn deallocate_credential_book(credential_book: CredentialBook) -> DeallocateResult {
credential_book.deallocate().map(|_| ()).into()
}
-/// Deallocates a credential-slab by its handle
+/// Deallocates a credential-slab by its handle. This takes ownership of the credential slab
+/// handle.
pub fn deallocate_credential_slab(credential_slab: CredentialSlab) -> DeallocateResult {
credential_slab.deallocate().map(|_| ()).into()
}
+/// Cryptographic information about a particular V0 broadcast credential
+/// necessary to LDT-encrypt V0 advertisements.
+#[repr(C)]
+pub struct V0BroadcastCredential {
+ key_seed: [u8; 32],
+ identity_token: [u8; 14],
+}
+
+impl V0BroadcastCredential {
+ /// Constructs a new `V0BroadcastCredential` from the given
+ /// key-seed and 14-byte metadata key.
+ ///
+ /// Safety: Since this representation requires transmission
+ /// of the raw bytes of sensitive cryptographic info over FFI,
+ /// foreign-lang code around how this information is maintained
+ /// deserves close scrutiny.
+ pub fn new(key_seed: [u8; 32], identity_token: ldt_np_adv::V0IdentityToken) -> Self {
+ Self { key_seed, identity_token: identity_token.bytes() }
+ }
+ pub(crate) fn into_internal(self) -> np_adv::credential::v0::V0BroadcastCredential {
+ np_adv::credential::v0::V0BroadcastCredential::new(
+ self.key_seed,
+ self.identity_token.into(),
+ )
+ }
+}
+
/// Cryptographic information about a particular V1 broadcast credential
/// necessary to encrypt V1 MIC-verified and signature-verified sections.
#[repr(C)]
pub struct V1BroadcastCredential {
key_seed: [u8; 32],
- metadata_key: [u8; 16],
+ identity_token: [u8; 16],
private_key: [u8; 32],
}
@@ -400,16 +453,18 @@ impl V1BroadcastCredential {
/// sensitive cryptographic info) over FFI, foreign-lang
/// code around how this information is maintained
/// deserves close scrutiny.
- pub fn new(key_seed: [u8; 32], metadata_key: [u8; 16], private_key: [u8; 32]) -> Self {
- Self { key_seed, metadata_key, private_key }
+ pub const fn new(
+ key_seed: [u8; 32],
+ identity_token: extended::V1IdentityToken,
+ private_key: [u8; 32],
+ ) -> Self {
+ Self { key_seed, identity_token: identity_token.into_bytes(), private_key }
}
- pub(crate) fn into_internal(
- self,
- ) -> np_adv::credential::v1::SimpleSignedBroadcastCryptoMaterial {
+ pub(crate) fn into_internal(self) -> np_adv::credential::v1::V1BroadcastCredential {
let permit = crypto_provider::ed25519::RawPrivateKeyPermit::default();
- np_adv::credential::v1::SimpleSignedBroadcastCryptoMaterial::new(
+ np_adv::credential::v1::V1BroadcastCredential::new(
self.key_seed,
- np_adv::MetadataKey(self.metadata_key),
+ self.identity_token.into(),
crypto_provider::ed25519::PrivateKey::from_raw_private_key(self.private_key, &permit),
)
}
diff --git a/nearby/presence/np_ffi_core/src/deserialize/mod.rs b/nearby/presence/np_ffi_core/src/deserialize.rs
index 5c1a891..dffa8d1 100644
--- a/nearby/presence/np_ffi_core/src/deserialize/mod.rs
+++ b/nearby/presence/np_ffi_core/src/deserialize.rs
@@ -14,14 +14,12 @@
//! Core NP Rust FFI structures and methods for advertisement deserialization.
use crate::common::*;
-use crate::credentials::credential_book::CredentialBook;
+use crate::credentials::CredentialBook;
use crate::deserialize::v0::*;
use crate::deserialize::v1::*;
use crate::utils::FfiEnum;
use crypto_provider_default::CryptoProviderImpl;
-use handle_map::{
- declare_handle_map, HandleLike, HandleMapDimensions, HandleMapFullError, HandleNotPresentError,
-};
+use handle_map::{declare_handle_map, HandleLike, HandleMapFullError, HandleNotPresentError};
use np_adv::deserialization_arena;
pub mod v0;
@@ -73,7 +71,8 @@ impl DeserializeAdvertisementResult {
declare_enum_cast! {into_v0, V0, DeserializedV0Advertisement}
declare_enum_cast! {into_v1, V1, DeserializedV1Advertisement}
- /// Deallocates any internal data referenced by a `DeserializeAdvertisementResult`
+ /// Deallocates any internal data referenced by a `DeserializeAdvertisementResult`. This takes
+ /// ownership of any internal handles.
pub fn deallocate(self) -> DeallocateResult {
match self {
DeserializeAdvertisementResult::Error => DeallocateResult::Success,
@@ -133,8 +132,9 @@ fn deserialize_advertisement_from_slice_internal(
}
}
-/// Attempts to deserialize an advertisement with the given payload.
-/// Suitable for langs which have a suitably expressive slice-type.
+/// Attempts to deserialize an advertisement with the given payload. Suitable for langs which have
+/// a suitably expressive slice-type. This uses the given `credential_book` handle but does not
+/// take ownership of it. The caller is given ownership of any handles in the returned structure.
pub fn deserialize_advertisement_from_slice(
adv_payload: &[u8],
credential_book: CredentialBook,
@@ -147,8 +147,10 @@ pub fn deserialize_advertisement_from_slice(
}
}
-/// Attempts to deserialize an advertisement with the given payload.
-/// Suitable for langs which don't have an expressive-enough slice type.
+/// Attempts to deserialize an advertisement with the given payload. Suitable for langs which
+/// don't have an expressive-enough slice type. This uses the given `credential_book` handle but
+/// does not take ownership of it. The caller is given ownership of any handles in the returned
+/// structure.
pub fn deserialize_advertisement(
adv_payload: &RawAdvertisementPayload,
credential_book: CredentialBook,
@@ -206,17 +208,19 @@ pub struct DecryptedMetadataInternals {
decrypted_bytes: Box<[u8]>,
}
-declare_handle_map! {
- mod decrypted_metadata {
- #[dimensions = super::get_decrypted_metadata_handle_map_dimensions()]
- type DecryptedMetadata: HandleLike<Object = super::DecryptedMetadataInternals>;
- }
+/// A `#[repr(C)]` handle to a value of type `DecryptedMetadataInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct DecryptedMetadata {
+ handle_id: u64,
}
-use decrypted_metadata::DecryptedMetadata;
-fn get_decrypted_metadata_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions { num_shards: global_num_shards(), max_active_handles: DEFAULT_MAX_HANDLES }
-}
+declare_handle_map!(
+ decrypted_metadata,
+ crate::common::default_handle_map_dimensions(),
+ super::DecryptedMetadata,
+ super::DecryptedMetadataInternals
+);
/// The pointer and length of the decrypted metadata byte buffer
#[repr(C)]
@@ -265,7 +269,8 @@ fn allocate_decrypted_metadata_handle(metadata: Vec<u8>) -> DecryptMetadataResul
}
impl DecryptedMetadata {
- /// Gets the raw parts, pointer + length representation of the metadata byte buffer
+ /// Gets the raw parts, pointer + length representation of the metadata byte buffer. This uses
+ /// the handle but does not take ownership of it.
pub fn get_metadata_buffer_parts(&self) -> GetMetadataBufferPartsResult {
match self.get() {
Ok(metadata_internals) => {
@@ -279,8 +284,8 @@ impl DecryptedMetadata {
}
}
- /// Frees the underlying decrypted metadata buffer
- pub fn deallocate_metadata(&self) -> DeallocateResult {
+ /// Frees the underlying decrypted metadata buffer. This takes ownership of the handle.
+ pub fn deallocate_metadata(self) -> DeallocateResult {
self.deallocate().map(|_| ()).into()
}
}
diff --git a/nearby/presence/np_ffi_core/src/deserialize/v0.rs b/nearby/presence/np_ffi_core/src/deserialize/v0.rs
index 14214c4..79528a0 100644
--- a/nearby/presence/np_ffi_core/src/deserialize/v0.rs
+++ b/nearby/presence/np_ffi_core/src/deserialize/v0.rs
@@ -14,18 +14,17 @@
//! Core NP Rust FFI structures and methods for v0 advertisement deserialization.
use crate::common::*;
-use crate::credentials::credential_book::CredentialBook;
+use crate::credentials::CredentialBook;
use crate::credentials::MatchedCredential;
use crate::deserialize::{
allocate_decrypted_metadata_handle, DecryptMetadataError, DecryptMetadataResult,
};
use crate::utils::{FfiEnum, LocksLongerThan};
+use crate::v0::V0DataElement;
use crypto_provider_default::CryptoProviderImpl;
-use handle_map::{declare_handle_map, HandleLike, HandleMapDimensions, HandleMapFullError};
-use np_adv::legacy::actions::ActionsDataElement;
-use np_adv::legacy::{data_elements as np_adv_de, Ciphertext, PacketFlavorEnum, Plaintext};
-use np_adv::HasIdentityMatch;
-use std::vec::Vec;
+use handle_map::{declare_handle_map, HandleLike, HandleMapFullError};
+use np_adv::credential::matched::HasIdentityMatch;
+use np_adv::legacy;
/// Discriminant for possible results of V0 advertisement deserialization
#[derive(Clone, Copy)]
@@ -34,12 +33,12 @@ pub enum DeserializedV0AdvertisementKind {
/// The deserialized V0 advertisement was legible.
/// The associated payload may be obtained via
/// `DeserializedV0Advertisement#into_legible`.
- Legible = 0,
+ Legible = 1,
/// The deserialized V0 advertisement is illegible,
/// likely meaning that the receiver does not hold
/// the proper credentials to be able to read
/// the received advertisement.
- NoMatchingCredentials = 1,
+ NoMatchingCredentials = 2,
}
/// Represents a deserialized V0 advertisement
@@ -63,8 +62,9 @@ impl FfiEnum for DeserializedV0Advertisement {
}
impl DeserializedV0Advertisement {
- /// Attempts to deallocate memory utilized internally by this V0 advertisement
- /// (which contains a handle to actual advertisement contents behind-the-scenes).
+ /// Attempts to deallocate memory utilized internally by this V0 advertisement (which contains
+ /// a handle to actual advertisement contents behind-the-scenes). This function takes ownership
+ /// of that internal handle.
pub fn deallocate(self) -> DeallocateResult {
match self {
DeserializedV0Advertisement::Legible(adv) => adv.deallocate(),
@@ -73,25 +73,25 @@ impl DeserializedV0Advertisement {
}
pub(crate) fn allocate_with_contents(
- contents: np_adv::V0AdvertisementContents<
- np_adv::credential::ReferencedMatchedCredential<MatchedCredential>,
+ contents: legacy::V0AdvertisementContents<
+ np_adv::credential::matched::ReferencedMatchedCredential<MatchedCredential>,
>,
) -> Result<Self, DeserializeAdvertisementError> {
match contents {
- np_adv::V0AdvertisementContents::Plaintext(plaintext_contents) => {
+ legacy::V0AdvertisementContents::Plaintext(plaintext_contents) => {
let adv = LegibleDeserializedV0Advertisement::allocate_with_plaintext_contents(
plaintext_contents,
)?;
Ok(Self::Legible(adv))
}
- np_adv::V0AdvertisementContents::Decrypted(decrypted_contents) => {
+ legacy::V0AdvertisementContents::Decrypted(decrypted_contents) => {
let decrypted_contents = decrypted_contents.clone_match_data();
let adv = LegibleDeserializedV0Advertisement::allocate_with_decrypted_contents(
decrypted_contents,
)?;
Ok(Self::Legible(adv))
}
- np_adv::V0AdvertisementContents::NoMatchingCredentials => {
+ legacy::V0AdvertisementContents::NoMatchingCredentials => {
Ok(Self::NoMatchingCredentials)
}
}
@@ -110,7 +110,7 @@ pub struct LegibleDeserializedV0Advertisement {
impl LegibleDeserializedV0Advertisement {
pub(crate) fn allocate_with_plaintext_contents(
- contents: np_adv::legacy::deserialize::PlaintextAdvContents,
+ contents: legacy::deserialize::UnencryptedAdvContents,
) -> Result<Self, DeserializeAdvertisementError> {
let data_elements = contents
.data_elements()
@@ -121,9 +121,9 @@ impl LegibleDeserializedV0Advertisement {
Ok(Self { num_des, payload, identity_kind: DeserializedV0IdentityKind::Plaintext })
}
pub(crate) fn allocate_with_decrypted_contents(
- contents: np_adv::WithMatchedCredential<
+ contents: np_adv::credential::matched::WithMatchedCredential<
MatchedCredential,
- np_adv::legacy::deserialize::DecryptedAdvContents,
+ legacy::deserialize::DecryptedAdvContents,
>,
) -> Result<Self, DeserializeAdvertisementError> {
let data_elements = contents
@@ -134,28 +134,23 @@ impl LegibleDeserializedV0Advertisement {
let num_des = data_elements.len() as u8;
let salt = contents.contents().salt();
- let identity_type = contents.contents().identity_type();
// Reduce the information contained in the contents to just
// the metadata key, since we're done copying over the DEs
// and other data into an FFI-friendly form.
- let match_data = contents.map(|x| x.metadata_key());
+ let match_data = contents.map(|x| x.identity_token());
- let payload = V0Payload::allocate_with_decrypted_contents(
- identity_type,
- salt,
- match_data,
- data_elements,
- )?;
+ let payload = V0Payload::allocate_with_decrypted_contents(salt, match_data, data_elements)?;
Ok(Self { num_des, payload, identity_kind: DeserializedV0IdentityKind::Decrypted })
}
- /// Gets the number of data-elements in this adv's payload
- /// Suitable as an iteration bound for `Self.into_payload().get_de(...)`.
+ /// Gets the number of data-elements in this adv's payload. This number is suitable as an
+ /// iteration bound for `Self.into_payload().get_de(...)`.
pub fn num_des(&self) -> u8 {
self.num_des
}
- /// Destructures this legible advertisement into just the payload
+ /// Get a copy of the payload handle. This does not copy the underlying payload. The copied
+ /// handle shares a lifetime with the payload handle in this struct; it's the same handle.
pub fn payload(&self) -> V0Payload {
self.payload
}
@@ -164,7 +159,8 @@ impl LegibleDeserializedV0Advertisement {
pub fn identity_kind(&self) -> DeserializedV0IdentityKind {
self.identity_kind
}
- /// Deallocates the underlying handle of the payload
+ /// Deallocates the underlying handle of the payload. This function takes ownership of the
+ /// payload handle.
pub fn deallocate(self) -> DeallocateResult {
self.payload.deallocate().map(|_| ()).into()
}
@@ -176,9 +172,9 @@ impl LegibleDeserializedV0Advertisement {
#[repr(u8)]
pub enum DeserializedV0IdentityKind {
/// The deserialized identity was a plaintext identity.
- Plaintext = 0,
+ Plaintext = 1,
/// The deserialized identity was some decrypted identity.
- Decrypted = 1,
+ Decrypted = 2,
}
/// Information about the identity which matched a
@@ -186,13 +182,11 @@ pub enum DeserializedV0IdentityKind {
#[derive(Clone, Copy)]
#[repr(C)]
pub struct DeserializedV0IdentityDetails {
- /// The identity type (private/provisioned/trusted)
- identity_type: EncryptedIdentityType,
/// The ID of the credential which
/// matched the deserialized adv
cred_id: u32,
- /// The 14-byte legacy metadata key
- metadata_key: [u8; 14],
+ /// The 14-byte legacy identity token
+ identity_token: [u8; 14],
/// The 2-byte advertisement salt
salt: [u8; 2],
}
@@ -200,27 +194,19 @@ pub struct DeserializedV0IdentityDetails {
impl DeserializedV0IdentityDetails {
pub(crate) fn new(
cred_id: u32,
- identity_type: np_adv::de_type::EncryptedIdentityDataElementType,
- salt: ldt_np_adv::LegacySalt,
- metadata_key: np_adv::legacy::ShortMetadataKey,
+ salt: ldt_np_adv::V0Salt,
+ identity_token: ldt_np_adv::V0IdentityToken,
) -> Self {
- let metadata_key = metadata_key.0;
- let salt = *salt.bytes();
- let identity_type = identity_type.into();
- Self { identity_type, cred_id, salt, metadata_key }
+ let salt = salt.bytes();
+ Self { cred_id, salt, identity_token: identity_token.bytes() }
}
- /// Returns the ID of the credential which
- /// matched the deserialized adv
+ /// Returns the ID of the credential which matched the deserialized adv
pub fn cred_id(&self) -> u32 {
self.cred_id
}
- /// Returns the identity type (private/provisioned/trusted)
- pub fn identity_type(&self) -> EncryptedIdentityType {
- self.identity_type
- }
/// Returns the 14-byte legacy metadata key
- pub fn metadata_key(&self) -> [u8; 14] {
- self.metadata_key
+ pub fn identity_token(&self) -> [u8; 14] {
+ self.identity_token
}
/// Returns the 2-byte advertisement salt
pub fn salt(&self) -> [u8; 2] {
@@ -276,22 +262,23 @@ pub(crate) struct DeserializedV0IdentityInternals {
/// The metadata key, together with the matched
/// credential and enough information to decrypt
/// the credential metadata, if desired.
- match_data: np_adv::WithMatchedCredential<MatchedCredential, np_adv::legacy::ShortMetadataKey>,
+ match_data: np_adv::credential::matched::WithMatchedCredential<
+ MatchedCredential,
+ ldt_np_adv::V0IdentityToken,
+ >,
}
impl DeserializedV0IdentityInternals {
pub(crate) fn new(
- identity_type: np_adv::de_type::EncryptedIdentityDataElementType,
- salt: ldt_np_adv::LegacySalt,
- match_data: np_adv::WithMatchedCredential<
+ salt: ldt_np_adv::V0Salt,
+ match_data: np_adv::credential::matched::WithMatchedCredential<
MatchedCredential,
- np_adv::legacy::ShortMetadataKey,
+ ldt_np_adv::V0IdentityToken,
>,
) -> Self {
let cred_id = match_data.matched_credential().id();
- let metadata_key = match_data.contents();
- let details =
- DeserializedV0IdentityDetails::new(cred_id, identity_type, salt, *metadata_key);
+ let identity_token = match_data.contents();
+ let details = DeserializedV0IdentityDetails::new(cred_id, salt, *identity_token);
Self { details, match_data }
}
/// Gets the directly-transmissible details about
@@ -343,20 +330,19 @@ impl V0PayloadInternals {
}
}
-fn get_v0_payload_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions {
- num_shards: global_num_shards(),
- max_active_handles: global_max_num_deserialized_v0_advertisements(),
- }
+/// A `#[repr(C)]` handle to a value of type `V0PayloadInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct V0Payload {
+ handle_id: u64,
}
-declare_handle_map! {
- mod v0_payload {
- #[dimensions = super::get_v0_payload_handle_map_dimensions()]
- type V0Payload: HandleLike<Object = super::V0PayloadInternals>;
- }
-}
-use v0_payload::V0Payload;
+declare_handle_map!(
+ v0_payload,
+ crate::common::default_handle_map_dimensions(),
+ super::V0Payload,
+ super::V0PayloadInternals
+);
use super::DeserializeAdvertisementError;
@@ -364,9 +350,7 @@ impl LocksLongerThan<V0Payload> for CredentialBook {}
impl V0Payload {
pub(crate) fn allocate_with_plaintext_data_elements(
- data_elements: Vec<
- np_adv::legacy::deserialize::PlainDataElement<np_adv::legacy::Plaintext>,
- >,
+ data_elements: Vec<legacy::deserialize::DeserializedDataElement<legacy::Plaintext>>,
) -> Result<Self, HandleMapFullError> {
Self::allocate(move || {
let des = data_elements.into_iter().map(V0DataElement::from).collect();
@@ -375,24 +359,21 @@ impl V0Payload {
})
}
pub(crate) fn allocate_with_decrypted_contents(
- identity_type: np_adv::de_type::EncryptedIdentityDataElementType,
- salt: ldt_np_adv::LegacySalt,
- match_data: np_adv::WithMatchedCredential<
+ salt: ldt_np_adv::V0Salt,
+ match_data: np_adv::credential::matched::WithMatchedCredential<
MatchedCredential,
- np_adv::legacy::ShortMetadataKey,
- >,
- data_elements: Vec<
- np_adv::legacy::deserialize::PlainDataElement<np_adv::legacy::Ciphertext>,
+ ldt_np_adv::V0IdentityToken,
>,
+ data_elements: Vec<legacy::deserialize::DeserializedDataElement<legacy::Ciphertext>>,
) -> Result<Self, HandleMapFullError> {
Self::allocate(move || {
let des = data_elements.into_iter().map(V0DataElement::from).collect();
- let identity =
- Some(DeserializedV0IdentityInternals::new(identity_type, salt, match_data));
+ let identity = Some(DeserializedV0IdentityInternals::new(salt, match_data));
V0PayloadInternals { des, identity }
})
}
- /// Gets the data-element with the given index in this v0 adv payload
+ /// Gets the data-element with the given index in this v0 adv payload. This uses the handle but
+ /// does not take ownership of it.
pub fn get_de(&self, index: u8) -> GetV0DEResult {
match self.get() {
Ok(read_guard) => read_guard.get_de(index),
@@ -400,9 +381,9 @@ impl V0Payload {
}
}
- /// Gets the identity details for this V0 payload,
- /// if this payload was associated with an identity
- /// (i.e: non-public advertisements).
+ /// Gets the identity details for this V0 payload, if this payload was associated with an
+ /// identity (i.e: encrypted advertisements). This uses the handle but does not take ownership
+ /// of it.
pub fn get_identity_details(&self) -> GetV0IdentityDetailsResult {
match self.get() {
Ok(read_guard) => read_guard.get_identity_details(),
@@ -410,8 +391,9 @@ impl V0Payload {
}
}
- /// Attempts to decrypt the metadata for the matched
- /// credential for this V0 payload (if any)
+ /// Attempts to decrypt the metadata for the matched credential for this V0 payload (if any).
+ /// This uses the handle but does not take ownership of it. The caller is given ownership of
+ /// the returned `DecryptedMetadata` handle if present.
pub fn decrypt_metadata(&self) -> DecryptMetadataResult {
match self.get() {
Ok(read_guard) => match read_guard.decrypt_metadata() {
@@ -422,7 +404,7 @@ impl V0Payload {
}
}
- /// Deallocates any underlying data held by a V0Payload
+ /// Deallocates any underlying data held by a `V0Payload`. This takes ownership of the handle.
pub fn deallocate_payload(&self) -> DeallocateResult {
self.deallocate().map(|_| ()).into()
}
@@ -464,208 +446,3 @@ impl FfiEnum for GetV0DEResult {
impl GetV0DEResult {
declare_enum_cast! {into_success, Success, V0DataElement}
}
-
-/// Discriminant for `V0DataElement`.
-#[repr(u8)]
-pub enum V0DataElementKind {
- /// A transmission Power (Tx Power) data-element.
- /// The associated payload may be obtained via
- /// `V0DataElement#into_tx_power`.
- TxPower = 0,
- /// The Actions data-element.
- /// The associated payload may be obtained via
- /// `V0DataElement#into_actions`.
- Actions = 1,
-}
-
-/// Representation of a V0 data element.
-#[repr(C)]
-#[allow(missing_docs)]
-#[derive(Clone)]
-pub enum V0DataElement {
- TxPower(TxPower),
- Actions(V0Actions),
-}
-
-impl<F: np_adv::legacy::PacketFlavor> From<np_adv::legacy::deserialize::PlainDataElement<F>>
- for V0DataElement
-{
- fn from(de: np_adv::legacy::deserialize::PlainDataElement<F>) -> Self {
- use np_adv::legacy::deserialize::PlainDataElement;
- match de {
- PlainDataElement::Actions(x) => V0DataElement::Actions(x.into()),
- PlainDataElement::TxPower(x) => V0DataElement::TxPower(x.into()),
- }
- }
-}
-
-impl FfiEnum for V0DataElement {
- type Kind = V0DataElementKind;
- fn kind(&self) -> Self::Kind {
- match self {
- V0DataElement::Actions(_) => V0DataElementKind::Actions,
- V0DataElement::TxPower(_) => V0DataElementKind::TxPower,
- }
- }
-}
-
-impl V0DataElement {
- declare_enum_cast! {into_tx_power, TxPower, TxPower}
- declare_enum_cast! {into_actions, Actions, V0Actions}
-}
-
-/// Representation of a transmission power,
-/// as used for the Tx Power DE in V0 and V1.
-#[derive(Clone)]
-#[repr(C)]
-pub struct TxPower {
- tx_power: i8,
-}
-
-impl TxPower {
- /// Yields this Tx Power value as an i8.
- pub fn as_i8(&self) -> i8 {
- self.tx_power
- }
-}
-
-impl From<np_adv_de::TxPowerDataElement> for TxPower {
- fn from(de: np_adv_de::TxPowerDataElement) -> Self {
- Self { tx_power: de.tx_power_value() }
- }
-}
-
-/// Representation of the Actions DE in V0.
-#[derive(Clone)]
-#[repr(C)]
-pub enum V0Actions {
- /// A set of action bits which were present in a plaintext identity advertisement
- Plaintext(V0ActionBits),
- /// A set of action bits which were present in a encrypted identity advertisement
- Encrypted(V0ActionBits),
-}
-
-impl<F: np_adv::legacy::PacketFlavor> From<np_adv::legacy::actions::ActionsDataElement<F>>
- for V0Actions
-{
- fn from(value: ActionsDataElement<F>) -> Self {
- match F::ENUM_VARIANT {
- PacketFlavorEnum::Plaintext => {
- Self::Plaintext(V0ActionBits { bitfield: value.action.as_u32() })
- }
- PacketFlavorEnum::Ciphertext => {
- Self::Encrypted(V0ActionBits { bitfield: value.action.as_u32() })
- }
- }
- }
-}
-
-#[repr(C)]
-#[derive(Clone)]
-/// The bitfield data of a VOActions data element
-pub struct V0ActionBits {
- bitfield: u32,
-}
-
-#[allow(missing_docs)]
-#[repr(u8)]
-/// The possible boolean action types which can be present in an Actions data element
-pub enum BooleanActionType {
- ActiveUnlock = 8,
- NearbyShare = 9,
- InstantTethering = 10,
- PhoneHub = 11,
- PresenceManager = 12,
- Finder = 13,
- FastPairSass = 14,
-}
-
-impl From<&BooleanActionType> for np_adv::legacy::actions::ActionType {
- fn from(value: &BooleanActionType) -> Self {
- match value {
- BooleanActionType::ActiveUnlock => np_adv::legacy::actions::ActionType::ActiveUnlock,
- BooleanActionType::NearbyShare => np_adv::legacy::actions::ActionType::NearbyShare,
- BooleanActionType::InstantTethering => {
- np_adv::legacy::actions::ActionType::InstantTethering
- }
- BooleanActionType::PhoneHub => np_adv::legacy::actions::ActionType::PhoneHub,
- BooleanActionType::Finder => np_adv::legacy::actions::ActionType::Finder,
- BooleanActionType::FastPairSass => np_adv::legacy::actions::ActionType::FastPairSass,
- BooleanActionType::PresenceManager => {
- np_adv::legacy::actions::ActionType::PresenceManager
- }
- }
- }
-}
-
-/// Error returned if action bits inside of a V0Actions struct are invalid. If the struct was
-/// created by the np_adv deserializer, the bits will always be valid, they are only invalid if a
-/// user reaches in and changes them to something invalid.
-#[derive(Debug)]
-pub struct InvalidActionBits;
-
-impl V0Actions {
- /// Gets the V0 Action bits as represented by a u32 where the last 8 bits are
- /// always 0 since V0 actions can only hold up to 24 bits.
- pub fn as_u32(&self) -> u32 {
- match self {
- V0Actions::Plaintext(bits) => bits.bitfield,
- V0Actions::Encrypted(bits) => bits.bitfield,
- }
- }
-
- /// Return whether a boolean action type is set in this data element
- #[allow(clippy::expect_used)]
- pub fn has_action(&self, action_type: &BooleanActionType) -> Result<bool, InvalidActionBits> {
- match self {
- V0Actions::Plaintext(action_bits) => {
- let bits = np_adv::legacy::actions::ActionBits::<Plaintext>::try_from(
- action_bits.bitfield,
- )
- .map_err(|_| InvalidActionBits)?;
-
- let actions_de = np_adv::legacy::actions::ActionsDataElement::from(bits);
- Ok(actions_de
- .action
- .has_action(&action_type.into())
- .expect("BooleanActionType only has one bit"))
- }
- V0Actions::Encrypted(action_bits) => {
- let bits = np_adv::legacy::actions::ActionBits::<Ciphertext>::try_from(
- action_bits.bitfield,
- )
- .map_err(|_| InvalidActionBits)?;
-
- let actions_de = np_adv::legacy::actions::ActionsDataElement::from(bits);
- Ok(actions_de
- .action
- .has_action(&action_type.into())
- .expect("BooleanActionType only has one bit"))
- }
- }
- }
-
- /// Return the context sequence number from this data element
- #[allow(clippy::expect_used)]
- pub fn get_context_sync_seq_num(&self) -> Result<u8, InvalidActionBits> {
- match self {
- V0Actions::Plaintext(action_bits) => {
- let bits = np_adv::legacy::actions::ActionBits::<Plaintext>::try_from(
- action_bits.bitfield,
- )
- .map_err(|_| InvalidActionBits)?;
-
- let actions_de = np_adv::legacy::actions::ActionsDataElement::from(bits);
- Ok(actions_de.action.context_sync_seq_num().as_u8())
- }
- V0Actions::Encrypted(action_bits) => {
- let bits = np_adv::legacy::actions::ActionBits::<Ciphertext>::try_from(
- action_bits.bitfield,
- )
- .map_err(|_| InvalidActionBits)?;
- let actions_de = np_adv::legacy::actions::ActionsDataElement::from(bits);
- Ok(actions_de.action.context_sync_seq_num().as_u8())
- }
- }
- }
-}
diff --git a/nearby/presence/np_ffi_core/src/deserialize/v1.rs b/nearby/presence/np_ffi_core/src/deserialize/v1.rs
index cb56b33..af54fec 100644
--- a/nearby/presence/np_ffi_core/src/deserialize/v1.rs
+++ b/nearby/presence/np_ffi_core/src/deserialize/v1.rs
@@ -14,26 +14,36 @@
//! Core NP Rust FFI structures and methods for v1 advertisement deserialization.
use super::DeserializeAdvertisementError;
-use crate::common::*;
-use crate::credentials::credential_book::CredentialBook;
-use crate::credentials::MatchedCredential;
-use crate::deserialize::{allocate_decrypted_metadata_handle, DecryptMetadataResult};
-use crate::utils::*;
-use crate::v1::V1VerificationMode;
+use crate::{
+ common::*,
+ credentials::{CredentialBook, MatchedCredential},
+ deserialize::{allocate_decrypted_metadata_handle, DecryptMetadataResult},
+ utils::*,
+ v1::V1VerificationMode,
+};
use array_view::ArrayView;
+use crypto_provider::CryptoProvider;
use crypto_provider_default::CryptoProviderImpl;
-use handle_map::{declare_handle_map, HandleLike, HandleMapDimensions};
-use legible_v1_sections::LegibleV1Sections;
-use np_adv::extended::deserialize::DataElementParseError;
-use np_adv::HasIdentityMatch;
-use std::vec::Vec;
+use handle_map::{declare_handle_map, HandleLike};
+use np_adv::{
+ credential::matched::WithMatchedCredential,
+ extended::{
+ deserialize::{
+ data_element::DataElementParseError, V1AdvertisementContents, V1DeserializedSection,
+ },
+ salt::MultiSalt,
+ },
+};
/// Representation of a deserialized V1 advertisement
#[repr(C)]
pub struct DeserializedV1Advertisement {
- num_legible_sections: u8,
- num_undecryptable_sections: u8,
- legible_sections: LegibleV1Sections,
+ /// The number of legible sections
+ pub num_legible_sections: u8,
+ /// The number of sections that were unable to be decrypted
+ pub num_undecryptable_sections: u8,
+ /// A handle to the set of legible (plain or decrypted) sections
+ pub legible_sections: LegibleV1Sections,
}
impl DeserializedV1Advertisement {
@@ -47,8 +57,9 @@ impl DeserializedV1Advertisement {
self.num_undecryptable_sections
}
- /// Gets the legible section with the given index
- /// (which is bounded in `0..self.num_legible_sections()`)
+ /// Gets the legible section with the given index (which is bounded in
+ /// `0..self.num_legible_sections()`). This uses the internal handle but does not take
+ /// ownership of it.
pub fn get_section(&self, legible_section_index: u8) -> GetV1SectionResult {
match self.legible_sections.get() {
Ok(sections_read_guard) => {
@@ -58,15 +69,16 @@ impl DeserializedV1Advertisement {
}
}
- /// Attempts to deallocate memory utilized internally by this V1 advertisement
- /// (which contains a handle to actual advertisement contents behind-the-scenes).
+ /// Attempts to deallocate memory utilized internally by this V1 advertisement (which contains
+ /// a handle to actual advertisement contents behind-the-scenes). This function takes ownership
+ /// of the internal handle.
pub fn deallocate(self) -> DeallocateResult {
self.legible_sections.deallocate().map(|_| ()).into()
}
pub(crate) fn allocate_with_contents(
- contents: np_adv::V1AdvertisementContents<
- np_adv::credential::ReferencedMatchedCredential<MatchedCredential>,
+ contents: V1AdvertisementContents<
+ np_adv::credential::matched::ReferencedMatchedCredential<MatchedCredential>,
>,
) -> Result<Self, DeserializeAdvertisementError> {
// 16-section limit enforced by np_adv
@@ -119,9 +131,9 @@ impl LegibleV1SectionsInternals {
impl<'adv>
TryFrom<
Vec<
- np_adv::V1DeserializedSection<
+ V1DeserializedSection<
'adv,
- np_adv::credential::ReferencedMatchedCredential<'adv, MatchedCredential>,
+ np_adv::credential::matched::ReferencedMatchedCredential<'adv, MatchedCredential>,
>,
>,
> for LegibleV1SectionsInternals
@@ -130,9 +142,9 @@ impl<'adv>
fn try_from(
contents: Vec<
- np_adv::V1DeserializedSection<
+ V1DeserializedSection<
'adv,
- np_adv::credential::ReferencedMatchedCredential<'adv, MatchedCredential>,
+ np_adv::credential::matched::ReferencedMatchedCredential<'adv, MatchedCredential>,
>,
>,
) -> Result<Self, Self::Error> {
@@ -144,27 +156,27 @@ impl<'adv>
}
}
-fn get_legible_v1_sections_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions {
- num_shards: global_num_shards(),
- max_active_handles: global_max_num_deserialized_v1_advertisements(),
- }
+/// A `#[repr(C)]` handle to a value of type `LegibleV1SectionsInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct LegibleV1Sections {
+ handle_id: u64,
}
-declare_handle_map! {
- mod legible_v1_sections {
- #[dimensions = super::get_legible_v1_sections_handle_map_dimensions()]
- type LegibleV1Sections: HandleLike<Object = super::LegibleV1SectionsInternals>;
- }
-}
+declare_handle_map!(
+ legible_v1_sections,
+ crate::common::default_handle_map_dimensions(),
+ super::LegibleV1Sections,
+ super::LegibleV1SectionsInternals
+);
impl LocksLongerThan<LegibleV1Sections> for CredentialBook {}
impl LegibleV1Sections {
pub(crate) fn allocate_with_contents(
contents: Vec<
- np_adv::V1DeserializedSection<
- np_adv::credential::ReferencedMatchedCredential<MatchedCredential>,
+ V1DeserializedSection<
+ np_adv::credential::matched::ReferencedMatchedCredential<MatchedCredential>,
>,
>,
) -> Result<Self, DeserializeAdvertisementError> {
@@ -172,6 +184,31 @@ impl LegibleV1Sections {
.map_err(|_| DeserializeAdvertisementError)?;
Self::allocate(move || section).map_err(|e| e.into())
}
+
+ /// Gets the legible section with the given index (which is bounded in
+ /// `0..self.num_legible_sections()`). This function uses this handle but does not take
+ /// ownership of it.
+ pub fn get_section(&self, legible_section_index: u8) -> GetV1SectionResult {
+ match self.get() {
+ Ok(sections_read_guard) => {
+ sections_read_guard.get_section(*self, legible_section_index)
+ }
+ Err(_) => GetV1SectionResult::Error,
+ }
+ }
+
+ /// Get a data element by section index and de index. Similar to `get_section().get_de()` but
+ /// will only lock the HandleMap once. This function uses this handle but does not take
+ /// ownership of it.
+ pub fn get_section_de(&self, legible_section_index: u8, de_index: u8) -> GetV1DEResult {
+ let Ok(sections) = self.get() else {
+ return GetV1DEResult::Error;
+ };
+ let Some(section) = sections.get_section_internals(legible_section_index) else {
+ return GetV1DEResult::Error;
+ };
+ section.get_de(de_index)
+ }
}
/// Discriminant for `GetV1SectionResult`
@@ -307,31 +344,33 @@ impl DeserializedV1SectionInternals {
/// passed offset is 255 (causes overflow) or if the section
/// is leveraging a public identity, and hence, doesn't have
/// an associated salt.
- pub(crate) fn derive_16_byte_salt_for_offset(&self, de_offset: u8) -> GetV1DE16ByteSaltResult {
+ pub(crate) fn derive_16_byte_salt_for_offset<C: CryptoProvider>(
+ &self,
+ de_offset: u8,
+ ) -> GetV1DE16ByteSaltResult {
self.identity
.as_ref()
- .and_then(|x| x.derive_16_byte_salt_for_offset(de_offset))
+ .and_then(|x| x.derive_16_byte_salt_for_offset::<C>(de_offset))
.map_or(GetV1DE16ByteSaltResult::Error, GetV1DE16ByteSaltResult::Success)
}
}
impl<'adv>
TryFrom<
- np_adv::V1DeserializedSection<
+ V1DeserializedSection<
'adv,
- np_adv::credential::ReferencedMatchedCredential<'adv, MatchedCredential>,
+ np_adv::credential::matched::ReferencedMatchedCredential<'adv, MatchedCredential>,
>,
> for DeserializedV1SectionInternals
{
type Error = DataElementParseError;
fn try_from(
- section: np_adv::V1DeserializedSection<
- np_adv::credential::ReferencedMatchedCredential<'adv, MatchedCredential>,
+ section: V1DeserializedSection<
+ np_adv::credential::matched::ReferencedMatchedCredential<'adv, MatchedCredential>,
>,
) -> Result<Self, Self::Error> {
use np_adv::extended::deserialize::Section;
- use np_adv::V1DeserializedSection;
match section {
V1DeserializedSection::Plaintext(section) => {
let des = section
@@ -348,19 +387,14 @@ impl<'adv>
.map(|r| r.map(|de| V1DataElement::from(&de)))
.collect::<Result<Vec<_>, _>>()?;
- let identity_type = section.identity_type();
let verification_mode = section.verification_mode();
- let salt = section.salt();
+ let salt = *section.salt();
let match_data = with_matched.clone_match_data();
- let match_data = match_data.map(|x| x.metadata_key());
-
- let identity = Some(DeserializedV1IdentityInternals::new(
- identity_type,
- verification_mode,
- salt,
- match_data,
- ));
+ let match_data = match_data.map(|x| *x.identity_token());
+
+ let identity =
+ Some(DeserializedV1IdentityInternals::new(verification_mode, salt, match_data));
Ok(Self { des, identity })
}
}
@@ -386,26 +420,21 @@ pub(crate) struct DeserializedV1IdentityInternals {
/// The metadata key, together with the matched
/// credential and enough information to decrypt
/// the credential metadata, if desired.
- match_data: np_adv::WithMatchedCredential<MatchedCredential, np_adv::MetadataKey>,
+ match_data: WithMatchedCredential<MatchedCredential, np_adv::extended::V1IdentityToken>,
/// The 16-byte section salt
- salt: np_adv::extended::deserialize::RawV1Salt,
+ salt: MultiSalt,
}
impl DeserializedV1IdentityInternals {
pub(crate) fn new(
- identity_type: np_adv::de_type::EncryptedIdentityDataElementType,
verification_mode: np_adv::extended::deserialize::VerificationMode,
- salt: np_adv::extended::deserialize::RawV1Salt,
- match_data: np_adv::WithMatchedCredential<MatchedCredential, np_adv::MetadataKey>,
+ salt: MultiSalt,
+ match_data: WithMatchedCredential<MatchedCredential, np_adv::extended::V1IdentityToken>,
) -> Self {
let cred_id = match_data.matched_credential().id();
- let metadata_key = match_data.contents();
- let details = DeserializedV1IdentityDetails::new(
- cred_id,
- identity_type,
- verification_mode,
- *metadata_key,
- );
+ let identity_token = match_data.contents();
+ let details =
+ DeserializedV1IdentityDetails::new(cred_id, verification_mode, *identity_token);
Self { details, match_data, salt }
}
/// Gets the directly-transmissible details about
@@ -421,13 +450,18 @@ impl DeserializedV1IdentityInternals {
}
/// For a given data-element offset, derives a 16-byte DE salt
/// for a DE in that position within this section.
- pub(crate) fn derive_16_byte_salt_for_offset(
+ pub(crate) fn derive_16_byte_salt_for_offset<C: CryptoProvider>(
&self,
de_offset: u8,
) -> Option<FixedSizeArray<16>> {
- let section_salt = np_hkdf::v1_salt::V1Salt::<CryptoProviderImpl>::from(self.salt);
let de_offset = np_hkdf::v1_salt::DataElementOffset::from(de_offset);
- section_salt.derive::<16>(Some(de_offset)).map(FixedSizeArray::from_array)
+
+ match self.salt {
+ MultiSalt::Short(_) => None,
+ MultiSalt::Extended(s) => {
+ s.derive::<16, C>(Some(de_offset)).map(FixedSizeArray::from_array)
+ }
+ }
}
}
@@ -476,8 +510,6 @@ impl GetV1IdentityDetailsResult {
#[derive(Clone, Copy)]
#[repr(C)]
pub struct DeserializedV1IdentityDetails {
- /// The identity type (private/provisioned/trusted)
- identity_type: EncryptedIdentityType,
/// The verification mode (MIC/Signature) which
/// was used to verify the decrypted adv contents.
verification_mode: V1VerificationMode,
@@ -485,38 +517,29 @@ pub struct DeserializedV1IdentityDetails {
/// matched the deserialized section.
cred_id: u32,
/// The 16-byte metadata key.
- metadata_key: [u8; 16],
+ identity_token: [u8; 16],
}
impl DeserializedV1IdentityDetails {
pub(crate) fn new(
cred_id: u32,
- identity_type: np_adv::de_type::EncryptedIdentityDataElementType,
verification_mode: np_adv::extended::deserialize::VerificationMode,
- metadata_key: np_adv::MetadataKey,
+ identity_token: np_adv::extended::V1IdentityToken,
) -> Self {
- let metadata_key = metadata_key.0;
- let identity_type = identity_type.into();
let verification_mode = verification_mode.into();
- Self { cred_id, identity_type, verification_mode, metadata_key }
+ Self { cred_id, verification_mode, identity_token: identity_token.into_bytes() }
}
- /// Returns the ID of the credential which
- /// matched the deserialized section.
+ /// Returns the ID of the credential which matched the deserialized section.
pub fn cred_id(&self) -> u32 {
self.cred_id
}
- /// Returns the identity type (private/provisioned/trusted)
- pub fn identity_type(&self) -> EncryptedIdentityType {
- self.identity_type
- }
- /// Returns the verification mode (MIC/Signature)
- /// employed for the decrypted section.
+ /// Returns the verification mode (MIC/Signature) employed for the decrypted section.
pub fn verification_mode(&self) -> V1VerificationMode {
self.verification_mode
}
- /// Returns the 16-byte section metadata key.
- pub fn metadata_key(&self) -> [u8; 16] {
- self.metadata_key
+ /// Returns the 16-byte section identity token.
+ pub fn identity_token(&self) -> [u8; 16] {
+ self.identity_token
}
}
@@ -548,33 +571,31 @@ impl DeserializedV1Section {
GetV1DEResult::Error,
)
}
- /// Attempts to get the details of the identity employed
- /// for the section referenced by this handle. May fail
- /// if the handle is invalid, or if the advertisement
- /// section leverages a public identity.
+ /// Attempts to get the details of the identity employed for the section referenced by this
+ /// handle. May fail if the handle is invalid, or if the advertisement section leverages a
+ /// public identity. This function does not take ownership of the handle.
pub fn get_identity_details(&self) -> GetV1IdentityDetailsResult {
self.apply_to_section_internals(
DeserializedV1SectionInternals::get_identity_details,
GetV1IdentityDetailsResult::Error,
)
}
- /// Attempts to decrypt the metadata for the matched
- /// credential for the V1 section referenced by
- /// this handle (if any).
+ /// Attempts to decrypt the metadata for the matched credential for the V1 section referenced
+ /// by this handle (if any). This uses but does not take ownership of the handle.
pub fn decrypt_metadata(&self) -> DecryptMetadataResult {
self.apply_to_section_internals(
DeserializedV1SectionInternals::decrypt_metadata,
DecryptMetadataResult::Error,
)
}
- /// Attempts to derive a 16-byte DE salt for a DE in this section
- /// with the given DE offset. This operation may fail if the
- /// passed offset is 255 (causes overflow) or if the section
- /// is leveraging a public identity, and hence, doesn't have
- /// an associated salt.
+ /// Attempts to derive a 16-byte DE salt for a DE in this section with the given DE offset.
+ /// This operation may fail if the passed offset is 255 (causes overflow) or if the section is
+ /// leveraging a public identity, and hence, doesn't have an associated salt.
pub fn derive_16_byte_salt_for_offset(&self, de_offset: u8) -> GetV1DE16ByteSaltResult {
self.apply_to_section_internals(
- move |section_ref| section_ref.derive_16_byte_salt_for_offset(de_offset),
+ move |section_ref| {
+ section_ref.derive_16_byte_salt_for_offset::<CryptoProviderImpl>(de_offset)
+ },
GetV1DE16ByteSaltResult::Error,
)
}
@@ -655,8 +676,8 @@ impl V1DataElement {
}
}
-impl<'a> From<&'a np_adv::extended::deserialize::DataElement<'a>> for V1DataElement {
- fn from(de: &'a np_adv::extended::deserialize::DataElement<'a>) -> Self {
+impl<'a> From<&'a np_adv::extended::deserialize::data_element::DataElement<'a>> for V1DataElement {
+ fn from(de: &'a np_adv::extended::deserialize::data_element::DataElement<'a>) -> Self {
let offset = de.offset().as_u8();
let de_type = V1DEType::from(de.de_type());
let contents_as_slice = de.contents();
@@ -692,8 +713,7 @@ impl GenericV1DataElement {
pub fn de_type(&self) -> V1DEType {
self.de_type
}
- /// Destructures this `GenericV1DataElement` into just the
- /// DE payload byte-buffer.
+ /// Destructures this `GenericV1DataElement` into just the DE payload byte-buffer.
pub fn into_payload(self) -> ByteBuffer<127> {
self.payload
}
diff --git a/nearby/presence/np_ffi_core/src/lib.rs b/nearby/presence/np_ffi_core/src/lib.rs
index f3bb7a3..2c03ea5 100644
--- a/nearby/presence/np_ffi_core/src/lib.rs
+++ b/nearby/presence/np_ffi_core/src/lib.rs
@@ -23,4 +23,5 @@ pub mod common;
pub mod credentials;
pub mod deserialize;
pub mod serialize;
+pub mod v0;
pub mod v1;
diff --git a/nearby/presence/np_ffi_core/src/serialize/mod.rs b/nearby/presence/np_ffi_core/src/serialize.rs
index aeb68a0..0aade0a 100644
--- a/nearby/presence/np_ffi_core/src/serialize/mod.rs
+++ b/nearby/presence/np_ffi_core/src/serialize.rs
@@ -13,6 +13,7 @@
// limitations under the License.
//! Core NP Rust FFI structures and methods for advertisement serialization.
+pub mod v0;
pub mod v1;
/// Enum common to V0 and V1 serialization expressing
diff --git a/nearby/presence/np_ffi_core/src/serialize/v0.rs b/nearby/presence/np_ffi_core/src/serialize/v0.rs
new file mode 100644
index 0000000..736925b
--- /dev/null
+++ b/nearby/presence/np_ffi_core/src/serialize/v0.rs
@@ -0,0 +1,275 @@
+// 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.
+
+//! NP Rust FFI structures and methods for V0 advertisement serialization.
+
+use crate::common::*;
+use crate::credentials::V0BroadcastCredential;
+use crate::serialize::AdvertisementBuilderKind;
+use crate::utils::FfiEnum;
+use crate::v0::V0DataElement;
+use crypto_provider_default::CryptoProviderImpl;
+use handle_map::{declare_handle_map, HandleLike, HandleMapFullError};
+use np_adv_dynamic::legacy::BoxedAdvConstructionError;
+
+/// A handle to a builder for V0 advertisements.
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct V0AdvertisementBuilder {
+ kind: AdvertisementBuilderKind,
+ handle: V0AdvertisementBuilderHandle,
+}
+
+impl V0AdvertisementBuilder {
+ /// Gets the kind of advertisement builder (public/encrypted).
+ pub fn kind(&self) -> AdvertisementBuilderKind {
+ self.kind
+ }
+
+ /// Attempts to add the given data element to the V0 advertisement builder behind this handle.
+ /// This function does not take ownership of the handle.
+ pub fn add_de(&self, de: V0DataElement) -> Result<AddV0DEResult, InvalidStackDataStructure> {
+ match self.handle.get_mut() {
+ Ok(mut adv_builder_write_guard) => adv_builder_write_guard.add_de(de),
+ Err(_) => Ok(AddV0DEResult::InvalidAdvertisementBuilderHandle),
+ }
+ }
+ /// Attempts to serialize the contents of the advertisement builder behind this handle to
+ /// bytes. This function takes ownership of the handle.
+ pub fn into_advertisement(self) -> SerializeV0AdvertisementResult {
+ match self.handle.deallocate() {
+ Ok(adv_builder) => adv_builder.into_advertisement(),
+ Err(_) => SerializeV0AdvertisementResult::InvalidAdvertisementBuilderHandle,
+ }
+ }
+ /// Attempts to deallocate the V0 advertisement builder behind this handle. This function takes
+ /// ownership of the handle.
+ pub fn deallocate(self) -> DeallocateResult {
+ self.handle.deallocate().map(|_| ()).into()
+ }
+}
+
+/// Discriminant for `CreateV0AdvertisementBuilderResult`
+#[derive(Copy, Clone)]
+#[repr(u8)]
+pub enum CreateV0AdvertisementBuilderResultKind {
+ /// The attempt to create a new advertisement builder
+ /// failed since there are no more available
+ /// slots for V0 advertisement builders in their handle-map.
+ NoSpaceLeft = 0,
+ /// The attempt succeeded. The wrapped advertisement builder
+ /// may be obtained via
+ /// `CreateV0AdvertisementBuilderResult#into_success`.
+ Success = 1,
+}
+
+/// The result of attempting to create a new V0 advertisement builder.
+#[repr(C)]
+#[allow(missing_docs)]
+pub enum CreateV0AdvertisementBuilderResult {
+ NoSpaceLeft,
+ Success(V0AdvertisementBuilder),
+}
+
+impl From<Result<V0AdvertisementBuilder, HandleMapFullError>>
+ for CreateV0AdvertisementBuilderResult
+{
+ fn from(result: Result<V0AdvertisementBuilder, HandleMapFullError>) -> Self {
+ match result {
+ Ok(builder) => CreateV0AdvertisementBuilderResult::Success(builder),
+ Err(_) => CreateV0AdvertisementBuilderResult::NoSpaceLeft,
+ }
+ }
+}
+
+impl FfiEnum for CreateV0AdvertisementBuilderResult {
+ type Kind = CreateV0AdvertisementBuilderResultKind;
+ fn kind(&self) -> Self::Kind {
+ match self {
+ CreateV0AdvertisementBuilderResult::NoSpaceLeft => {
+ CreateV0AdvertisementBuilderResultKind::NoSpaceLeft
+ }
+ CreateV0AdvertisementBuilderResult::Success(_) => {
+ CreateV0AdvertisementBuilderResultKind::Success
+ }
+ }
+ }
+}
+
+impl CreateV0AdvertisementBuilderResult {
+ declare_enum_cast! {into_success, Success, V0AdvertisementBuilder }
+}
+
+/// Creates a new V0 advertisement builder for a public advertisement. The caller is given
+/// ownership of the created handle.
+pub fn create_v0_public_advertisement_builder() -> CreateV0AdvertisementBuilderResult {
+ V0AdvertisementBuilderHandle::allocate(V0AdvertisementBuilderInternals::new_public)
+ .map(|handle| V0AdvertisementBuilder { kind: AdvertisementBuilderKind::Public, handle })
+ .into()
+}
+
+/// Creates a new V0 advertisement builder for an encrypted advertisement. The caller is given
+/// ownership of the created handle.
+pub fn create_v0_encrypted_advertisement_builder(
+ broadcast_cred: V0BroadcastCredential,
+ salt: FixedSizeArray<2>,
+) -> CreateV0AdvertisementBuilderResult {
+ V0AdvertisementBuilderHandle::allocate(move || {
+ V0AdvertisementBuilderInternals::new_ldt(broadcast_cred, salt.into_array())
+ })
+ .map(|handle| V0AdvertisementBuilder { kind: AdvertisementBuilderKind::Encrypted, handle })
+ .into()
+}
+
+/// Discriminant for `SerializeV0AdvertisementResult`.
+#[repr(u8)]
+pub enum SerializeV0AdvertisementResultKind {
+ /// Serializing the advertisement to bytes was successful.
+ Success = 0,
+ /// The advertisement builder handle was invalid.
+ InvalidAdvertisementBuilderHandle = 1,
+ /// Serializing the advertisement to bytes failed
+ /// because the data in the advertisement wasn't
+ /// of an appropriate size for LDT encryption
+ /// to succeed.
+ LdtError = 2,
+ /// Serializing an unencrypted adv failed because the adv data didn't meet the length
+ /// requirements.
+ UnencryptedError = 3,
+}
+
+/// The result of attempting to serialize the contents
+/// of a V0 advertisement builder to raw bytes.
+#[repr(C)]
+#[allow(missing_docs)]
+pub enum SerializeV0AdvertisementResult {
+ Success(ByteBuffer<24>),
+ InvalidAdvertisementBuilderHandle,
+ LdtError,
+ UnencryptedError,
+}
+
+impl SerializeV0AdvertisementResult {
+ declare_enum_cast! { into_success, Success, ByteBuffer<24> }
+}
+
+impl FfiEnum for SerializeV0AdvertisementResult {
+ type Kind = SerializeV0AdvertisementResultKind;
+ fn kind(&self) -> SerializeV0AdvertisementResultKind {
+ match self {
+ Self::Success(_) => SerializeV0AdvertisementResultKind::Success,
+ Self::InvalidAdvertisementBuilderHandle => {
+ SerializeV0AdvertisementResultKind::InvalidAdvertisementBuilderHandle
+ }
+ Self::LdtError => SerializeV0AdvertisementResultKind::LdtError,
+ Self::UnencryptedError => SerializeV0AdvertisementResultKind::UnencryptedError,
+ }
+ }
+}
+
+/// Internal Rust-side implementation of a V0 advertisement builder.
+pub struct V0AdvertisementBuilderInternals {
+ adv_builder: np_adv_dynamic::legacy::BoxedAdvBuilder<CryptoProviderImpl>,
+}
+
+impl V0AdvertisementBuilderInternals {
+ pub(crate) fn new_public() -> Self {
+ Self::new(np_adv::legacy::serialize::UnencryptedEncoder.into())
+ }
+ pub(crate) fn new_ldt(broadcast_cred: V0BroadcastCredential, salt: [u8; 2]) -> Self {
+ // TODO: What do about salts? Need to prevent re-use fo the same salt,
+ // but have no current rich representation of used salts...
+ let salt = ldt_np_adv::V0Salt::from(salt);
+ let internal_broadcast_cred = broadcast_cred.into_internal();
+ let identity = np_adv::legacy::serialize::LdtEncoder::new(salt, &internal_broadcast_cred);
+ Self::new(identity.into())
+ }
+ fn new(encoder: np_adv_dynamic::legacy::BoxedEncoder<CryptoProviderImpl>) -> Self {
+ let adv_builder =
+ np_adv_dynamic::legacy::BoxedAdvBuilder::<CryptoProviderImpl>::new(encoder);
+ Self { adv_builder }
+ }
+ fn add_de(&mut self, de: V0DataElement) -> Result<AddV0DEResult, InvalidStackDataStructure> {
+ let to_boxed = np_adv_dynamic::legacy::ToBoxedSerializeDataElement::try_from(de)?;
+ use np_adv::legacy::serialize::AddDataElementError;
+ use np_adv_dynamic::legacy::BoxedAddDataElementError;
+ match self.adv_builder.add_data_element(to_boxed) {
+ Ok(_) => Ok(AddV0DEResult::Success),
+ Err(BoxedAddDataElementError::FlavorMismatchError) => {
+ Ok(AddV0DEResult::InvalidIdentityTypeForDataElement)
+ }
+ Err(BoxedAddDataElementError::UnderlyingError(
+ AddDataElementError::InsufficientAdvSpace,
+ )) => Ok(AddV0DEResult::InsufficientAdvertisementSpace),
+ }
+ }
+ fn into_advertisement(self) -> SerializeV0AdvertisementResult {
+ self.adv_builder
+ .into_advertisement()
+ .map(|serialized_bytes| {
+ SerializeV0AdvertisementResult::Success(ByteBuffer::from_array_view(
+ serialized_bytes,
+ ))
+ })
+ .unwrap_or_else(|e| match e {
+ BoxedAdvConstructionError::Ldt(_) => SerializeV0AdvertisementResult::LdtError,
+ BoxedAdvConstructionError::Unencrypted(_) => {
+ SerializeV0AdvertisementResult::UnencryptedError
+ }
+ })
+ }
+}
+
+/// A `#[repr(C)]` handle to a value of type `V0AdvertisementBuilderInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+struct V0AdvertisementBuilderHandle {
+ handle_id: u64,
+}
+
+declare_handle_map!(
+ advertisement_builder,
+ crate::common::default_handle_map_dimensions(),
+ super::V0AdvertisementBuilderHandle,
+ super::V0AdvertisementBuilderInternals
+);
+
+/// Result code for the operation of adding a DE to a V0
+/// advertisement builder.
+#[derive(Clone, Copy)]
+#[repr(u8)]
+pub enum AddV0DEResult {
+ /// The DE was successfully added to the advertisement builder
+ /// behind the given handle.
+ Success = 0,
+ /// The handle for the advertisement builder was invalid.
+ InvalidAdvertisementBuilderHandle = 1,
+ /// There was not enough available space left in the advertisement
+ /// to append the given data element.
+ InsufficientAdvertisementSpace = 2,
+ /// The passed data element is not broadcastable under the
+ /// identity type of the advertisement (public/private).
+ InvalidIdentityTypeForDataElement = 3,
+}
+
+impl From<np_adv_dynamic::legacy::BoxedAddDataElementError> for AddV0DEResult {
+ fn from(err: np_adv_dynamic::legacy::BoxedAddDataElementError) -> Self {
+ use np_adv_dynamic::legacy::BoxedAddDataElementError;
+ match err {
+ BoxedAddDataElementError::UnderlyingError(_) => Self::InsufficientAdvertisementSpace,
+ BoxedAddDataElementError::FlavorMismatchError => {
+ Self::InvalidIdentityTypeForDataElement
+ }
+ }
+ }
+}
diff --git a/nearby/presence/np_ffi_core/src/serialize/v1.rs b/nearby/presence/np_ffi_core/src/serialize/v1.rs
index ccc6ef7..c87446f 100644
--- a/nearby/presence/np_ffi_core/src/serialize/v1.rs
+++ b/nearby/presence/np_ffi_core/src/serialize/v1.rs
@@ -19,9 +19,7 @@ use crate::serialize::AdvertisementBuilderKind;
use crate::utils::FfiEnum;
use crate::v1::V1VerificationMode;
use crypto_provider_default::CryptoProviderImpl;
-use handle_map::{declare_handle_map, HandleLike, HandleMapDimensions, HandleMapFullError};
-use np_adv;
-use np_adv_dynamic;
+use handle_map::{declare_handle_map, HandleLike, HandleMapFullError};
/// A handle to a builder for V1 advertisements.
#[derive(Clone, Copy)]
@@ -32,21 +30,24 @@ pub struct V1AdvertisementBuilder {
}
impl V1AdvertisementBuilder {
- /// Attempts to create a builder for a new public section within
- /// this advertisement, returning a handle to the newly-created
- /// section builder if successful.
+ /// Attempts to create a builder for a new public section within this advertisement, returning
+ /// an owned handle to the newly-created section builder if successful.
///
- /// This method may fail if there is another currently-active
- /// section builder for the same advertisement builder, if the
- /// kind of section being added does not match the advertisement
- /// type (public/encrypted), or if the section would not manage
- /// to fit within the enclosing advertisement.
+ /// This method may fail if there is another currently-active section builder for the same
+ /// advertisement builder, if the kind of section being added does not match the advertisement
+ /// type (public/encrypted), or if the section would not manage to fit within the enclosing
+ /// advertisement.
pub fn public_section_builder(&self) -> CreateV1SectionBuilderResult {
self.section_builder_internals(|internals| internals.public_section_builder())
}
- /// Attempts to create a builder for a new encrypted section within
- /// this advertisement, returning a handle to the newly-created
- /// section builder if successful.
+
+ /// Gets the kind of advertisement builder (public/encrypted)
+ pub fn kind(&self) -> AdvertisementBuilderKind {
+ self.kind
+ }
+
+ /// Attempts to create a builder for a new encrypted section within this advertisement,
+ /// returning an owned handle to the newly-created section builder if successful.
///
/// The identity details for the new section builder may be specified
/// via providing the broadcast credential data, the kind of encrypted
@@ -61,14 +62,24 @@ impl V1AdvertisementBuilder {
pub fn encrypted_section_builder(
&self,
broadcast_cred: V1BroadcastCredential,
- identity_type: EncryptedIdentityType,
verification_mode: V1VerificationMode,
) -> CreateV1SectionBuilderResult {
self.section_builder_internals(move |internals| {
- internals.encrypted_section_builder(broadcast_cred, identity_type, verification_mode)
+ internals.encrypted_section_builder(broadcast_cred, verification_mode)
})
}
+ /// Attempts to serialize the contents of the advertisement builder behind this handle to
+ /// bytes. Assuming that the handle is valid, this operation will always take ownership of the
+ /// handle and result in the contents behind the advertisement builder handle being
+ /// deallocated.
+ pub fn into_advertisement(self) -> SerializeV1AdvertisementResult {
+ match self.handle.deallocate() {
+ Ok(adv_builder) => adv_builder.into_advertisement(),
+ Err(_) => SerializeV1AdvertisementResult::InvalidAdvertisementBuilderHandle,
+ }
+ }
+
fn section_builder_internals(
&self,
builder_supplier: impl FnOnce(
@@ -85,13 +96,12 @@ impl V1AdvertisementBuilder {
Err(e) => e.into(),
}
}
- Err(_) => CreateV1SectionBuilderResult::InvalidAdvBuilderHandle,
+ Err(_) => CreateV1SectionBuilderResult::InvalidAdvertisementBuilderHandle,
}
}
}
/// Discriminant for `CreateV1AdvertisementBuilderResult`
-
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum CreateV1AdvertisementBuilderResultKind {
@@ -152,30 +162,19 @@ pub fn create_v1_advertisement_builder(
.into()
}
-impl V1AdvertisementBuilder {
- /// Gets the kind of advertisement builder (public/encrypted)
- pub fn kind(&self) -> AdvertisementBuilderKind {
- self.kind
- }
-}
-
pub(crate) enum V1AdvertisementBuilderState {
/// Internal state for when we have an active advertisement
/// builder, but no currently-active section builder.
Advertisement(np_adv_dynamic::extended::BoxedAdvBuilder),
/// Internal state for when we have both an active advertisement
/// builder and an active section builder.
- Section(
- np_adv_dynamic::extended::BoxedSectionBuilder<
- np_adv::extended::serialize::AdvBuilder,
- CryptoProviderImpl,
- >,
- ),
+ Section(np_adv_dynamic::extended::BoxedSectionBuilder<np_adv::extended::serialize::AdvBuilder>),
}
/// Internal version of errors which may be raised when
/// attempting to derive a new section builder from an
/// advertisement builder.
+#[derive(Debug, Eq, PartialEq)]
pub(crate) enum SectionBuilderError {
/// We're currently in the middle of building a section.
UnclosedActiveSection,
@@ -207,6 +206,46 @@ impl From<np_adv_dynamic::extended::BoxedAddSectionError> for SectionBuilderErro
}
}
+/// Discriminant for `SerializeV1AdvertisementResult`.
+#[repr(u8)]
+pub enum SerializeV1AdvertisementResultKind {
+ /// Serializing the advertisement to bytes was successful.
+ Success = 0,
+ /// The state of the advertisement builder was invalid
+ /// for the builder to be closed for serialization, likely
+ /// because there was an unclosed section builder.
+ InvalidBuilderState = 1,
+ /// The advertisement builder handle was invalid.
+ InvalidAdvertisementBuilderHandle = 2,
+}
+
+/// The result of attempting to serialize the contents
+/// of a V1 advertisement builder to raw bytes.
+#[repr(C)]
+#[allow(missing_docs, clippy::large_enum_variant)]
+pub enum SerializeV1AdvertisementResult {
+ Success(ByteBuffer<250>),
+ InvalidBuilderState,
+ InvalidAdvertisementBuilderHandle,
+}
+
+impl SerializeV1AdvertisementResult {
+ declare_enum_cast! { into_success, Success, ByteBuffer<250> }
+}
+
+impl FfiEnum for SerializeV1AdvertisementResult {
+ type Kind = SerializeV1AdvertisementResultKind;
+ fn kind(&self) -> SerializeV1AdvertisementResultKind {
+ match self {
+ Self::Success(_) => SerializeV1AdvertisementResultKind::Success,
+ Self::InvalidBuilderState => SerializeV1AdvertisementResultKind::InvalidBuilderState,
+ Self::InvalidAdvertisementBuilderHandle => {
+ SerializeV1AdvertisementResultKind::InvalidAdvertisementBuilderHandle
+ }
+ }
+ }
+}
+
/// Internal, Rust-side implementation of a V1 advertisement builder.
pub struct V1AdvertisementBuilderInternals {
// Note: This is actually always populated from an external
@@ -228,12 +267,12 @@ impl V1AdvertisementBuilderInternals {
/// of the newly-added section builder.
pub(crate) fn section_builder_internal(
&mut self,
- identity: np_adv_dynamic::extended::BoxedIdentity<CryptoProviderImpl>,
+ identity: np_adv_dynamic::extended::BoxedEncoder,
) -> Result<usize, SectionBuilderError> {
let state = self.state.take();
match state {
Some(V1AdvertisementBuilderState::Advertisement(adv_builder)) => {
- match adv_builder.into_section_builder::<CryptoProviderImpl>(identity) {
+ match adv_builder.into_section_builder(identity) {
Ok(section_builder) => {
let section_index = section_builder.section_index();
self.state = Some(V1AdvertisementBuilderState::Section(section_builder));
@@ -256,55 +295,59 @@ impl V1AdvertisementBuilderInternals {
}
pub(crate) fn public_section_builder(&mut self) -> Result<usize, SectionBuilderError> {
- let identity = np_adv_dynamic::extended::BoxedIdentity::PublicIdentity;
+ let identity = np_adv_dynamic::extended::BoxedEncoder::Unencrypted;
self.section_builder_internal(identity)
}
pub(crate) fn encrypted_section_builder(
&mut self,
broadcast_cred: V1BroadcastCredential,
- identity_type: EncryptedIdentityType,
verification_mode: V1VerificationMode,
) -> Result<usize, SectionBuilderError> {
let mut rng = get_global_crypto_rng();
let rng = rng.get_rng();
- let identity_type = identity_type.into();
let internal_broadcast_cred = broadcast_cred.into_internal();
- let identity = match verification_mode {
+ let encoder = match verification_mode {
V1VerificationMode::Mic => {
- let encoder = np_adv::extended::serialize::MicEncryptedSectionEncoder::<
- CryptoProviderImpl,
- >::new_random_salt(
- rng, identity_type, &internal_broadcast_cred
- );
- np_adv_dynamic::extended::BoxedIdentity::MicEncrypted(encoder)
+ let encoder =
+ np_adv::extended::serialize::MicEncryptedSectionEncoder::<_>::new_wrapped_salt::<
+ CryptoProviderImpl,
+ >(rng, &internal_broadcast_cred);
+ np_adv_dynamic::extended::BoxedEncoder::MicEncrypted(encoder)
}
V1VerificationMode::Signature => {
- let encoder = np_adv::extended::serialize::SignedEncryptedSectionEncoder::<
- CryptoProviderImpl,
- >::new_random_salt(
- rng, identity_type, &internal_broadcast_cred
- );
- np_adv_dynamic::extended::BoxedIdentity::SignedEncrypted(encoder)
+ let encoder =
+ np_adv::extended::serialize::SignedEncryptedSectionEncoder::new_random_salt::<
+ CryptoProviderImpl,
+ >(rng, &internal_broadcast_cred);
+ np_adv_dynamic::extended::BoxedEncoder::SignedEncrypted(encoder)
}
};
- self.section_builder_internal(identity)
+ self.section_builder_internal(encoder)
}
-}
-
-fn get_v1_advertisement_builder_handle_map_dimensions() -> HandleMapDimensions {
- HandleMapDimensions {
- num_shards: global_num_shards(),
- max_active_handles: global_max_num_v1_advertisement_builders(),
+ fn into_advertisement(self) -> SerializeV1AdvertisementResult {
+ match self.state {
+ Some(V1AdvertisementBuilderState::Advertisement(adv_builder)) => {
+ let array_view = adv_builder.into_advertisement().into_array_view();
+ SerializeV1AdvertisementResult::Success(ByteBuffer::from_array_view(array_view))
+ }
+ _ => SerializeV1AdvertisementResult::InvalidBuilderState,
+ }
}
}
-declare_handle_map! {
- mod advertisement_builder {
- #[dimensions = super::get_v1_advertisement_builder_handle_map_dimensions()]
- type V1AdvertisementBuilderHandle: HandleLike<Object = super::V1AdvertisementBuilderInternals>;
- }
+/// A `#[repr(C)]` handle to a value of type `V1AdvertisementBuilderInternals`
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Eq)]
+struct V1AdvertisementBuilderHandle {
+ handle_id: u64,
}
-use crate::serialize::v1::advertisement_builder::V1AdvertisementBuilderHandle;
+
+declare_handle_map!(
+ advertisement_builder,
+ crate::common::default_handle_map_dimensions(),
+ super::V1AdvertisementBuilderHandle,
+ super::V1AdvertisementBuilderInternals
+);
/// Discriminant for `CreateV1SectionBuilderResult`
#[derive(Copy, Clone)]
@@ -315,7 +358,7 @@ pub enum CreateV1SectionBuilderResultKind {
/// We're currently in the middle of building a section.
UnclosedActiveSection = 1,
/// The advertisement builder handle was invalid.
- InvalidAdvBuilderHandle = 2,
+ InvalidAdvertisementBuilderHandle = 2,
/// We're attempting to build a section with an identity
/// kind (public/encrypted) which doesn't match the kind
/// for the entire advertisement.
@@ -333,7 +376,7 @@ pub enum CreateV1SectionBuilderResultKind {
pub enum CreateV1SectionBuilderResult {
Success(V1SectionBuilder),
UnclosedActiveSection,
- InvalidAdvBuilderHandle,
+ InvalidAdvertisementBuilderHandle,
IdentityKindMismatch,
NoSpaceLeft,
}
@@ -344,8 +387,8 @@ impl FfiEnum for CreateV1SectionBuilderResult {
match self {
Self::Success(_) => CreateV1SectionBuilderResultKind::Success,
Self::UnclosedActiveSection => CreateV1SectionBuilderResultKind::UnclosedActiveSection,
- Self::InvalidAdvBuilderHandle => {
- CreateV1SectionBuilderResultKind::InvalidAdvBuilderHandle
+ Self::InvalidAdvertisementBuilderHandle => {
+ CreateV1SectionBuilderResultKind::InvalidAdvertisementBuilderHandle
}
Self::IdentityKindMismatch => CreateV1SectionBuilderResultKind::IdentityKindMismatch,
Self::NoSpaceLeft => CreateV1SectionBuilderResultKind::NoSpaceLeft,
@@ -416,12 +459,12 @@ pub enum NextV1DE16ByteSaltResultKind {
/// The result of attempting to get the derived V1 DE
/// 16-byte salt for the next-added DE to the section
/// builder behind the given handle.
-#[derive(Clone, Copy)]
+#[derive(Clone)]
#[repr(C)]
#[allow(missing_docs)]
pub enum NextV1DE16ByteSaltResult {
Error,
- Success([u8; 16]),
+ Success(FixedSizeArray<16>),
}
impl FfiEnum for NextV1DE16ByteSaltResult {
@@ -435,21 +478,18 @@ impl FfiEnum for NextV1DE16ByteSaltResult {
}
impl NextV1DE16ByteSaltResult {
- declare_enum_cast! {into_success, Success, [u8; 16] }
-}
-
-impl From<Option<np_adv::extended::serialize::DeSalt<CryptoProviderImpl>>>
- for NextV1DE16ByteSaltResult
-{
- fn from(maybe_salt: Option<np_adv::extended::serialize::DeSalt<CryptoProviderImpl>>) -> Self {
- match maybe_salt.and_then(|salt| salt.derive::<16>()) {
- Some(salt) => NextV1DE16ByteSaltResult::Success(salt),
+ fn new_from_de_salt(salt: Option<np_adv::extended::serialize::DeSalt>) -> Self {
+ match salt.and_then(|salt| salt.derive::<16, CryptoProviderImpl>()) {
+ Some(salt) => NextV1DE16ByteSaltResult::Success(FixedSizeArray::from_array(salt)),
None => NextV1DE16ByteSaltResult::Error,
}
}
+
+ declare_enum_cast! {into_success, Success, FixedSizeArray<16> }
}
-/// A handle to a builder for V1 sections.
+/// A handle to a builder for V1 sections. This is not a unique handle; it is the same handle as
+/// the advertisement builder the section builder was originated from.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct V1SectionBuilder {
@@ -471,7 +511,8 @@ impl V1SectionBuilder {
// matches the index of the section currently under construction.
let actual_section_index = section_builder.section_index() as u8;
if self.section_index == actual_section_index {
- let updated_adv_builder = section_builder.add_to_advertisement();
+ let updated_adv_builder =
+ section_builder.add_to_advertisement::<CryptoProviderImpl>();
adv_builder.state = Some(V1AdvertisementBuilderState::Advertisement(
updated_adv_builder,
));
@@ -498,7 +539,9 @@ impl V1SectionBuilder {
/// is a public section.
pub fn next_de_salt(&self) -> NextV1DE16ByteSaltResult {
self.try_apply_to_internals(
- |section_builder| section_builder.next_de_salt().into(),
+ |section_builder| {
+ NextV1DE16ByteSaltResult::new_from_de_salt(section_builder.next_de_salt())
+ },
NextV1DE16ByteSaltResult::Error,
)
}
@@ -532,7 +575,6 @@ impl V1SectionBuilder {
func: impl FnOnce(
&mut np_adv_dynamic::extended::BoxedSectionBuilder<
np_adv::extended::serialize::AdvBuilder,
- CryptoProviderImpl,
>,
) -> R,
invalid_handle_error: R,
@@ -587,3 +629,41 @@ impl V1DE127ByteBuffer {
})
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn state_is_advertisement_building(adv_builder_state: &V1AdvertisementBuilderState) -> bool {
+ matches!(adv_builder_state, V1AdvertisementBuilderState::Advertisement(_))
+ }
+
+ #[allow(clippy::expect_used)]
+ #[test]
+ fn test_build_section_fails_with_outstanding_section() {
+ let mut adv_builder =
+ V1AdvertisementBuilderInternals::new(AdvertisementBuilderKind::Encrypted);
+
+ let adv_builder_state =
+ adv_builder.state.as_ref().expect("Adv builder state should be present.");
+ assert!(state_is_advertisement_building(adv_builder_state));
+ let section_index = adv_builder
+ .encrypted_section_builder(empty_broadcast_cred(), V1VerificationMode::Mic)
+ .expect("Should be able to build the first section.");
+ assert_eq!(section_index, 0);
+
+ assert!(adv_builder.state.is_some());
+ let adv_builder_state =
+ adv_builder.state.as_ref().expect("Adv builder state should be present.");
+ assert!(!state_is_advertisement_building(adv_builder_state));
+
+ let double_build_error = adv_builder
+ .encrypted_section_builder(empty_broadcast_cred(), V1VerificationMode::Mic)
+ .expect_err("Shouldn't be able to start a new section builder with an unclosed one.");
+ assert_eq!(double_build_error, SectionBuilderError::UnclosedActiveSection);
+ }
+
+ fn empty_broadcast_cred() -> V1BroadcastCredential {
+ V1BroadcastCredential::new([0; 32], [0; 16].into(), [0; 32])
+ }
+}
diff --git a/nearby/presence/np_ffi_core/src/utils.rs b/nearby/presence/np_ffi_core/src/utils.rs
index b1495b9..4876645 100644
--- a/nearby/presence/np_ffi_core/src/utils.rs
+++ b/nearby/presence/np_ffi_core/src/utils.rs
@@ -17,6 +17,10 @@ use handle_map::HandleLike;
/// Type-level predicate for handle types which uniformly hold a lock
/// for longer than some other handle type in API calls.
+///
+/// Largely an informative marker trait used to indicate the
+/// lock ordering on types.
+#[allow(dead_code)]
pub(crate) trait LocksLongerThan<H: HandleLike>: HandleLike {}
/// Trait which canonicalizes the relationship between FFI
diff --git a/nearby/presence/np_ffi_core/src/v0.rs b/nearby/presence/np_ffi_core/src/v0.rs
new file mode 100644
index 0000000..16b7b21
--- /dev/null
+++ b/nearby/presence/np_ffi_core/src/v0.rs
@@ -0,0 +1,410 @@
+// 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.
+
+//! Common externally-acessible V0 constructs for both of the
+//! serialization+deserialization flows.
+
+use crate::common::InvalidStackDataStructure;
+use crate::serialize::AdvertisementBuilderKind;
+use crate::utils::FfiEnum;
+use np_adv::{
+ legacy::data_elements::actions::ActionsDataElement,
+ legacy::{data_elements as np_adv_de, Ciphertext, PacketFlavorEnum, Plaintext},
+};
+use strum::IntoEnumIterator;
+
+/// Discriminant for `V0DataElement`.
+#[repr(u8)]
+pub enum V0DataElementKind {
+ /// A transmission Power (Tx Power) data-element.
+ /// The associated payload may be obtained via
+ /// `V0DataElement#into_tx_power`.
+ TxPower = 1,
+ /// The Actions data-element.
+ /// The associated payload may be obtained via
+ /// `V0DataElement#into_actions`.
+ Actions = 2,
+}
+
+/// Representation of a V0 data element.
+#[repr(C)]
+#[allow(missing_docs)]
+#[derive(Clone)]
+pub enum V0DataElement {
+ TxPower(TxPower),
+ Actions(V0Actions),
+}
+
+impl TryFrom<V0DataElement> for np_adv_dynamic::legacy::ToBoxedSerializeDataElement {
+ type Error = InvalidStackDataStructure;
+ fn try_from(de: V0DataElement) -> Result<Self, InvalidStackDataStructure> {
+ match de {
+ V0DataElement::TxPower(x) => x.try_into(),
+ V0DataElement::Actions(x) => x.try_into(),
+ }
+ }
+}
+
+impl<F: np_adv::legacy::PacketFlavor> From<np_adv::legacy::deserialize::DeserializedDataElement<F>>
+ for V0DataElement
+{
+ fn from(de: np_adv::legacy::deserialize::DeserializedDataElement<F>) -> Self {
+ use np_adv::legacy::deserialize::DeserializedDataElement;
+ match de {
+ DeserializedDataElement::Actions(x) => V0DataElement::Actions(x.into()),
+ DeserializedDataElement::TxPower(x) => V0DataElement::TxPower(x.into()),
+ }
+ }
+}
+
+impl FfiEnum for V0DataElement {
+ type Kind = V0DataElementKind;
+ fn kind(&self) -> Self::Kind {
+ match self {
+ V0DataElement::Actions(_) => V0DataElementKind::Actions,
+ V0DataElement::TxPower(_) => V0DataElementKind::TxPower,
+ }
+ }
+}
+
+impl V0DataElement {
+ declare_enum_cast! {into_tx_power, TxPower, TxPower}
+ declare_enum_cast! {into_actions, Actions, V0Actions}
+}
+
+/// Discriminant for `BuildTxPowerResult`.
+#[repr(u8)]
+#[derive(Clone, Copy)]
+pub enum BuildTxPowerResultKind {
+ /// The transmission power was outside the
+ /// allowed -100dBm to 20dBm range.
+ OutOfRange = 0,
+ /// The transmission power was in range,
+ /// and so a `TxPower` struct was constructed.
+ Success = 1,
+}
+
+/// Result type for attempting to construct a
+/// Tx Power from a signed byte.
+#[repr(C)]
+#[allow(missing_docs)]
+pub enum BuildTxPowerResult {
+ OutOfRange,
+ Success(TxPower),
+}
+
+impl FfiEnum for BuildTxPowerResult {
+ type Kind = BuildTxPowerResultKind;
+ fn kind(&self) -> Self::Kind {
+ match self {
+ Self::OutOfRange => BuildTxPowerResultKind::OutOfRange,
+ Self::Success(_) => BuildTxPowerResultKind::Success,
+ }
+ }
+}
+
+impl BuildTxPowerResult {
+ declare_enum_cast! {into_success, Success, TxPower}
+}
+
+/// Representation of a transmission power,
+/// as used for the Tx Power DE in V0 and V1.
+#[derive(Clone)]
+#[repr(C)]
+pub struct TxPower {
+ tx_power: i8,
+}
+
+impl TxPower {
+ /// Attempts to construct a new TxPower from the given signed-byte value.
+ pub fn build_from_signed_byte(tx_power: i8) -> BuildTxPowerResult {
+ match np_adv::shared_data::TxPower::try_from(tx_power) {
+ Ok(_) => BuildTxPowerResult::Success(Self { tx_power }),
+ Err(_) => BuildTxPowerResult::OutOfRange,
+ }
+ }
+ /// Yields this Tx Power value as an i8.
+ pub fn as_i8(&self) -> i8 {
+ self.tx_power
+ }
+}
+
+impl From<np_adv_de::tx_power::TxPowerDataElement> for TxPower {
+ fn from(de: np_adv_de::tx_power::TxPowerDataElement) -> Self {
+ Self { tx_power: de.tx_power_value() }
+ }
+}
+
+impl TryFrom<TxPower> for np_adv_dynamic::legacy::ToBoxedSerializeDataElement {
+ type Error = InvalidStackDataStructure;
+ fn try_from(value: TxPower) -> Result<Self, InvalidStackDataStructure> {
+ np_adv::shared_data::TxPower::try_from(value.as_i8())
+ .map_err(|_| InvalidStackDataStructure)
+ .map(|x| x.into())
+ }
+}
+
+/// Representation of the Actions DE in V0.
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub enum V0Actions {
+ /// A set of action bits which were present in a plaintext identity advertisement
+ Plaintext(V0ActionBits),
+ /// A set of action bits which were present in a encrypted identity advertisement
+ Encrypted(V0ActionBits),
+}
+
+impl TryFrom<V0Actions> for np_adv_dynamic::legacy::ToBoxedSerializeDataElement {
+ type Error = InvalidStackDataStructure;
+ fn try_from(value: V0Actions) -> Result<Self, InvalidStackDataStructure> {
+ let boxed_action_bits = np_adv_dynamic::legacy::BoxedActionBits::try_from(value)?;
+ Ok(boxed_action_bits.into())
+ }
+}
+
+impl<F: np_adv::legacy::PacketFlavor> From<ActionsDataElement<F>> for V0Actions {
+ fn from(value: ActionsDataElement<F>) -> Self {
+ match F::ENUM_VARIANT {
+ PacketFlavorEnum::Plaintext => {
+ Self::Plaintext(V0ActionBits { bitfield: value.action.as_u32() })
+ }
+ PacketFlavorEnum::Ciphertext => {
+ Self::Encrypted(V0ActionBits { bitfield: value.action.as_u32() })
+ }
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
+/// The bitfield data of a V0Actions data element
+pub struct V0ActionBits {
+ bitfield: u32,
+}
+
+impl From<u32> for V0ActionBits {
+ fn from(bitfield: u32) -> Self {
+ // No need to validate here. Validation of this struct is done at all places where it is
+ // taken as a parameter. See [`InvalidStackDataStructure`]. Since this struct is
+ // `#[repr(C)]` if rules were enforced here, they could be broken by a foreign language
+ // user.
+ Self { bitfield }
+ }
+}
+
+#[derive(Clone, Copy, strum_macros::EnumIter)]
+#[allow(missing_docs)]
+#[repr(u8)]
+/// The possible boolean action types which can be present in an Actions data element
+pub enum ActionType {
+ CrossDevSdk = 1,
+ CallTransfer = 4,
+ ActiveUnlock = 8,
+ NearbyShare = 9,
+ InstantTethering = 10,
+ PhoneHub = 11,
+}
+
+#[derive(Clone, Copy, Debug)]
+/// The given int is out of range for conversion.
+pub struct TryFromIntError;
+
+impl From<core::num::TryFromIntError> for TryFromIntError {
+ fn from(_: core::num::TryFromIntError) -> Self {
+ Self
+ }
+}
+
+impl TryFrom<u8> for ActionType {
+ type Error = TryFromIntError;
+ fn try_from(n: u8) -> Result<Self, Self::Error> {
+ // cast is safe since it's a repr(u8) unit enum
+ Self::iter().find(|t| *t as u8 == n).ok_or(TryFromIntError)
+ }
+}
+
+impl ActionType {
+ pub(crate) fn as_boxed_action_element(
+ &self,
+ value: bool,
+ ) -> np_adv_dynamic::legacy::ToBoxedActionElement {
+ use np_adv_dynamic::legacy::ToBoxedActionElement;
+ match self {
+ Self::CrossDevSdk => ToBoxedActionElement::CrossDevSdk(value),
+ Self::CallTransfer => ToBoxedActionElement::CallTransfer(value),
+ Self::ActiveUnlock => ToBoxedActionElement::ActiveUnlock(value),
+ Self::NearbyShare => ToBoxedActionElement::NearbyShare(value),
+ Self::InstantTethering => ToBoxedActionElement::InstantTethering(value),
+ Self::PhoneHub => ToBoxedActionElement::PhoneHub(value),
+ }
+ }
+}
+
+impl From<ActionType> for np_adv::legacy::data_elements::actions::ActionType {
+ fn from(value: ActionType) -> Self {
+ match value {
+ ActionType::CrossDevSdk => {
+ np_adv::legacy::data_elements::actions::ActionType::CrossDevSdk
+ }
+ ActionType::CallTransfer => {
+ np_adv::legacy::data_elements::actions::ActionType::CallTransfer
+ }
+ ActionType::ActiveUnlock => {
+ np_adv::legacy::data_elements::actions::ActionType::ActiveUnlock
+ }
+ ActionType::NearbyShare => {
+ np_adv::legacy::data_elements::actions::ActionType::NearbyShare
+ }
+ ActionType::InstantTethering => {
+ np_adv::legacy::data_elements::actions::ActionType::InstantTethering
+ }
+ ActionType::PhoneHub => np_adv::legacy::data_elements::actions::ActionType::PhoneHub,
+ }
+ }
+}
+
+// ensure bidirectional mapping
+impl From<np_adv::legacy::data_elements::actions::ActionType> for ActionType {
+ fn from(value: np_adv_de::actions::ActionType) -> Self {
+ match value {
+ np_adv_de::actions::ActionType::CrossDevSdk => ActionType::CrossDevSdk,
+ np_adv_de::actions::ActionType::CallTransfer => ActionType::CallTransfer,
+ np_adv_de::actions::ActionType::ActiveUnlock => ActionType::ActiveUnlock,
+ np_adv_de::actions::ActionType::NearbyShare => ActionType::NearbyShare,
+ np_adv_de::actions::ActionType::InstantTethering => ActionType::InstantTethering,
+ np_adv_de::actions::ActionType::PhoneHub => ActionType::PhoneHub,
+ }
+ }
+}
+
+impl From<np_adv_dynamic::legacy::BoxedActionBits> for V0Actions {
+ fn from(bits: np_adv_dynamic::legacy::BoxedActionBits) -> Self {
+ use np_adv_dynamic::legacy::BoxedActionBits;
+ match bits {
+ BoxedActionBits::Plaintext(x) => Self::Plaintext(V0ActionBits { bitfield: x.as_u32() }),
+ BoxedActionBits::Ciphertext(x) => {
+ Self::Encrypted(V0ActionBits { bitfield: x.as_u32() })
+ }
+ }
+ }
+}
+
+impl TryFrom<V0Actions> for np_adv_dynamic::legacy::BoxedActionBits {
+ type Error = InvalidStackDataStructure;
+ fn try_from(actions: V0Actions) -> Result<Self, InvalidStackDataStructure> {
+ match actions {
+ V0Actions::Plaintext(action_bits) => {
+ let bits =
+ np_adv::legacy::data_elements::actions::ActionBits::<Plaintext>::try_from(
+ action_bits.bitfield,
+ )
+ .map_err(|_| InvalidStackDataStructure)?;
+ Ok(bits.into())
+ }
+ V0Actions::Encrypted(action_bits) => {
+ let bits =
+ np_adv::legacy::data_elements::actions::ActionBits::<Ciphertext>::try_from(
+ action_bits.bitfield,
+ )
+ .map_err(|_| InvalidStackDataStructure)?;
+ Ok(bits.into())
+ }
+ }
+ }
+}
+
+/// Discriminant for `SetV0ActionResult`.
+#[repr(u8)]
+pub enum SetV0ActionResultKind {
+ /// The attempt to set the action bit failed. The
+ /// action bits were yielded back to the caller,
+ /// unmodified.
+ Error = 0,
+ /// The attempt to set the action bit succeeded.
+ /// The updated action bits were yielded back to the caller.
+ Success = 1,
+}
+
+/// The result of attempting to set a particular action
+/// bit on some `V0Actions`.
+#[repr(C)]
+#[allow(missing_docs)]
+pub enum SetV0ActionResult {
+ Success(V0Actions),
+ Error(V0Actions),
+}
+
+impl FfiEnum for SetV0ActionResult {
+ type Kind = SetV0ActionResultKind;
+ fn kind(&self) -> Self::Kind {
+ match self {
+ Self::Success(_) => SetV0ActionResultKind::Success,
+ Self::Error(_) => SetV0ActionResultKind::Error,
+ }
+ }
+}
+
+impl SetV0ActionResult {
+ declare_enum_cast! { into_success, Success, V0Actions }
+ declare_enum_cast! { into_error, Error, V0Actions }
+}
+
+impl V0Actions {
+ /// Constructs a new V0 actions DE with no declared boolean
+ /// actions and a zeroed context sync sequence number,
+ /// where the DE is intended for the given advertisement
+ /// kind (plaintext/encrypted).
+ pub fn new_zeroed(kind: AdvertisementBuilderKind) -> Self {
+ match kind {
+ AdvertisementBuilderKind::Public => Self::Plaintext(V0ActionBits { bitfield: 0 }),
+ AdvertisementBuilderKind::Encrypted => Self::Encrypted(V0ActionBits { bitfield: 0 }),
+ }
+ }
+
+ /// Gets the V0 Action bits as represented by a u32 where the last 8 bits are
+ /// always 0 since V0 actions can only hold up to 24 bits.
+ pub fn as_u32(&self) -> u32 {
+ match self {
+ V0Actions::Plaintext(bits) => bits.bitfield,
+ V0Actions::Encrypted(bits) => bits.bitfield,
+ }
+ }
+
+ /// Return whether a boolean action type is set in this data element
+ #[allow(clippy::expect_used)]
+ pub fn has_action(&self, action_type: ActionType) -> Result<bool, InvalidStackDataStructure> {
+ let boxed_action_bits = np_adv_dynamic::legacy::BoxedActionBits::try_from(*self)?;
+ let action_type = action_type.into();
+ Ok(boxed_action_bits.has_action(action_type))
+ }
+
+ /// Attempts to set the given action bit to the given boolean value.
+ /// This operation may fail if the requested action bit may not be
+ /// set for the kind of containing advertisement (public/encrypted)
+ /// that this action DE is intended to belong to. In this case,
+ /// the original action bits will be yielded back to the caller,
+ /// unaltered.
+ pub fn set_action(
+ self,
+ action_type: ActionType,
+ value: bool,
+ ) -> Result<SetV0ActionResult, InvalidStackDataStructure> {
+ let mut boxed_action_bits = np_adv_dynamic::legacy::BoxedActionBits::try_from(self)?;
+ let boxed_action_element = action_type.as_boxed_action_element(value);
+ match boxed_action_bits.set_action(boxed_action_element) {
+ Ok(()) => Ok(SetV0ActionResult::Success(boxed_action_bits.into())),
+ Err(_) => Ok(SetV0ActionResult::Error(self)),
+ }
+ }
+}
diff --git a/nearby/presence/np_hkdf/Cargo.toml b/nearby/presence/np_hkdf/Cargo.toml
index 45e40da..cd7fb4c 100644
--- a/nearby/presence/np_hkdf/Cargo.toml
+++ b/nearby/presence/np_hkdf/Cargo.toml
@@ -17,9 +17,10 @@ ldt.workspace = true
xts_aes.workspace = true
[dev-dependencies]
-crypto_provider_default.workspace = true
+crypto_provider_default = { workspace = true, features = ["rustcrypto"] }
rand_ext.workspace = true
test_helper.workspace = true
+test_vector_hkdf.workspace = true
anyhow.workspace = true
criterion.workspace = true
diff --git a/nearby/presence/np_hkdf/benches/np_hkdf.rs b/nearby/presence/np_hkdf/benches/np_hkdf.rs
index bec3b0e..0380d78 100644
--- a/nearby/presence/np_hkdf/benches/np_hkdf.rs
+++ b/nearby/presence/np_hkdf/benches/np_hkdf.rs
@@ -17,6 +17,7 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use crypto_provider::{CryptoProvider, CryptoRng};
use crypto_provider_default::CryptoProviderImpl;
+use np_hkdf::DerivedSectionKeys;
use rand_ext::random_bytes;
pub fn build_np_hkdf(c: &mut Criterion) {
@@ -45,7 +46,7 @@ pub fn build_np_hkdf(c: &mut Criterion) {
.collect::<Vec<_>>();
b.iter(|| {
for hkdf in keys.iter() {
- black_box(hkdf.extended_unsigned_metadata_key_hmac_key());
+ black_box(hkdf.v1_mic_extended_salt_keys().identity_token_hmac_key());
}
});
});
@@ -62,7 +63,7 @@ pub fn build_np_hkdf(c: &mut Criterion) {
.collect::<Vec<_>>();
b.iter(|| {
for hkdf in keys.iter() {
- black_box(np_hkdf::UnsignedSectionKeys::aes_key(hkdf));
+ black_box(hkdf.v1_mic_extended_salt_keys().aes_key());
}
});
});
@@ -79,7 +80,7 @@ pub fn build_np_hkdf(c: &mut Criterion) {
.collect::<Vec<_>>();
b.iter(|| {
for hkdf in keys.iter() {
- black_box(hkdf.legacy_ldt_key());
+ black_box(hkdf.v0_ldt_key());
}
});
});
diff --git a/nearby/presence/np_hkdf/resources/test/hkdf-test-vectors.json b/nearby/presence/np_hkdf/resources/test/hkdf-test-vectors.json
index b4e283c..d0af65f 100644
--- a/nearby/presence/np_hkdf/resources/test/hkdf-test-vectors.json
+++ b/nearby/presence/np_hkdf/resources/test/hkdf-test-vectors.json
@@ -1,2802 +1,3502 @@
[
{
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "99D59E9A0A1761D40F4F28E1D56F4C25",
- "derived_salt_first_section_no_de": "4D02FD0C02250E221A8C63A1A9865AE2",
- "derived_salt_first_section_third_de": "8A72AE14A6EA06DAD91CC5970FBD005F",
- "section_salt": "C561AB4667AA9D7E126E79F060BAD04F"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "05B8575BCA2486B5A1DD5D7D",
- "extended_signed_metadata_key_hmac_key": "072C62C8F3A83F2ED0EEDD3107249160FF2ABEEDBEBA4607EF517A60F6640C7C",
- "extended_signed_section_aes_key": "4DF7DE7DECCF54059C259EC7529D8AF8",
- "extended_unsigned_metadata_key_hmac_key": "DC9FC71D78B822B6763ED1058E77DFCEF41B5F9F4810330AE034F962700EE225",
- "extended_unsigned_section_aes_key": "A4E14FCB637F18E3B908635B67F4695B",
- "extended_unsigned_section_mic_hmac_key": "C456B4C30D6E8F33B2D4010D656E3321ACF572EE09C831A87177B04F0F692AEF",
- "key_seed": "E78C9A018A4B81DD837D9C7E2995B265E3363AAE9E9F7A46D1E0ECC81689D004",
- "legacy_ldt_key": "E584BE2B557549287AAF196A765A0BB7F26F81210FFBA9AFE314ED0A4912BC4098779896121E6F0DAFFB30A70F358854C984611C4C249D48D8793F35512CBCE7",
- "legacy_metadata_key_hmac_key": "EF9805022265A8B11D56B8E9EB2A17307EFC258EA1B8CEF70380BE6A3A3B1F43",
- "legacy_metadata_nonce": "2ED7B79A45C428DFB747460B"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "202A",
- "expanded_salt": "BBB2F537324B844F10631A119EB7C1C0"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "EFB7E58C4EF1CE656C9D2691CD46880E",
- "legacy_metadata_key": "E36847D19B3DB1715E6542D66205"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "3B9EB63E2B808E95384B37049EC52296",
- "derived_salt_first_section_no_de": "DA32C8270314D33E521BD6D455CEBAED",
- "derived_salt_first_section_third_de": "FED4AB32F733BBD3A1F6CC3568925182",
- "section_salt": "E6F154A2B223214012758A37E5EEEF10"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "ABA8038F9AF71FC6C1DA0AA4",
- "extended_signed_metadata_key_hmac_key": "D65DA42911CD5ED334C530F869DB03C6614CA35E6FA866D9E38E69C777ABB6DA",
- "extended_signed_section_aes_key": "A017DA593FF63BDF6FE6F77ECFD2AB5E",
- "extended_unsigned_metadata_key_hmac_key": "A38246B6BD7F50873ACB4C04E0EC64FC189F64055D297E0965D98EEE19173A10",
- "extended_unsigned_section_aes_key": "6727FBCBDC7B6C29F3ED05346661ADD6",
- "extended_unsigned_section_mic_hmac_key": "E5DC924147B60D7F39EAA86AD504DB3C37230DBF79EDAB9005150135443864BF",
- "key_seed": "80FCB0995D122213A13491854547AE8DC1F9DA0FBCDC425EF8CAE2F1621B5123",
- "legacy_ldt_key": "791FFF186FAB641481FA4F9CED1FA84BE86FD44118214C4D911C7FED6E72367DD7E7D516CA45EBA6F39140D735EAE911C9FD41FF64AA5A1D6FAB6945EF95ACC7",
- "legacy_metadata_key_hmac_key": "FB0D2011320B53ADC656F21ADAC39599A84660CC06E01E6BF71FA3A13EC7017F",
- "legacy_metadata_nonce": "65E4371B55813FF7B1EF282B"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "8527",
- "expanded_salt": "41DF3C96FD61381D21C6B33C4ABF109B"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D3CFD17D054FAEBD7E7FC121915090B3",
- "legacy_metadata_key": "788B30E87219D982203B007557BE"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "29F63E30C4CA477654EA633EF851EF2C",
- "derived_salt_first_section_no_de": "9F1DA62A3038226B6E1A0B7BA3AE6735",
- "derived_salt_first_section_third_de": "078A761182B0E4C9FAB615B1B5BD76F3",
- "section_salt": "3EFE885D2597608370E56E69A0EBBE08"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "3F20992295F10AD806832D05",
- "extended_signed_metadata_key_hmac_key": "74273A7D5F63F7E8F319716489804EF7B0693EE94831B24B94DEC7916B3A7E75",
- "extended_signed_section_aes_key": "95C76B3AB159ECC6AA7AF3806E065EC7",
- "extended_unsigned_metadata_key_hmac_key": "91ACB7139211ABCEEFD27C3371D8E8E3DA4AA1EF62DE05331A6A97671E4C1E13",
- "extended_unsigned_section_aes_key": "A6A6E1AB38E8D1E1734D8E6F2ED72F55",
- "extended_unsigned_section_mic_hmac_key": "81DF7CFC39442A2A065D795A1B836FE11A1E9EDA04DDF5C206A6C5E35DB37442",
- "key_seed": "49F89927FDFEE5496504B4A130919BA8967C66E28BEAD4525DFEFCC704A18423",
- "legacy_ldt_key": "C298669D7FFAE75E0DF93574FBCB1FF2ED135A0211256FCD6942981B832FBE35AD444D1678697DAF07F5D8A9E117CC86C3E57BB6BDB8689DF9CF969F097E68BA",
- "legacy_metadata_key_hmac_key": "AF3EBA58151897927BE02FD78E68AAF90675CD8D556800B736752426ECD48764",
- "legacy_metadata_nonce": "BED3836FD96FD34EB7FC9983"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "BE30",
- "expanded_salt": "66BC953964F357EE08DD1C7668A79D6A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "8C16CCF3C80E07746B1F8471932A1FE5",
- "legacy_metadata_key": "74135EB8B0F379AAA4D4478ADE7F"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "82AD47824247F00924ECF0A43621BC57",
- "derived_salt_first_section_no_de": "C737B65B994BF8CD872CA41BDB8A53A7",
- "derived_salt_first_section_third_de": "9BB8BB55E1DE5129A43AC0EA937B4430",
- "section_salt": "72C9E759C172DA23B71FB6B0C6ED8CC7"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "80921E0D404179D9F04DC155",
- "extended_signed_metadata_key_hmac_key": "B9B1F73D7FCFD25EB6A62B788032C71104926922C436A137B95A46D7B63C5EE6",
- "extended_signed_section_aes_key": "85C1D9D14D09C0722DCFF12643CF2669",
- "extended_unsigned_metadata_key_hmac_key": "F89C26264B27E1A265C60D69A20AE73222CE9E2F68E0F1D71C6DEF936C4092D0",
- "extended_unsigned_section_aes_key": "43639BFCEBDF4EE61629156E04F92EA0",
- "extended_unsigned_section_mic_hmac_key": "AF81B5A56EC2D2541E46AB2F9F583A48155A2F9BB272372E8064E446BE8A182A",
- "key_seed": "286E2029CF579A26495BE93926BC663732C46DE57049C1A5E2BEBFE03A12A096",
- "legacy_ldt_key": "ED36084F2492B19D07D5A09D174C16A01B8AFEAF27C86EC145CEAD08C8BE67A80BCFF79C40F7E63019B81821A715DFEFCA273F467A176C61D7A024BC245A6B8E",
- "legacy_metadata_key_hmac_key": "2A48789FF8B93282B4D483566E9FF4DFB65AF5FBB869BAEF6C408465A310879D",
- "legacy_metadata_nonce": "6803BD4BD4D435930449C17E"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "3353",
- "expanded_salt": "C86C20A42866236AB1CD9F1E815DDFD5"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "95E24D5EA5EBA3152427BF48A3781BDC",
- "legacy_metadata_key": "4FE2300F2CA3C469959DC0A5510D"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "98C14D785DD885F3D039C8F84EB65B81",
- "derived_salt_first_section_no_de": "94C66E08758D83DCE457073C6B911483",
- "derived_salt_first_section_third_de": "1BAED8E606422F18BC5CCD3F649BAEE6",
- "section_salt": "9D82CCB568AEFB50C4D1061D29220A63"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "05B2831B07DF537F173ED291",
- "extended_signed_metadata_key_hmac_key": "D120FC54257B1EA765E2D210C6F77D5066404601BBAC598725BDE993CCA9D90B",
- "extended_signed_section_aes_key": "52605A8345524539B05A4DD5DD7A51EC",
- "extended_unsigned_metadata_key_hmac_key": "ED44D698082772261DB4F47F37999E5474523A75A5F046A671B9138086A31B7A",
- "extended_unsigned_section_aes_key": "8A0EC8AE2F2177300A418614507F0F27",
- "extended_unsigned_section_mic_hmac_key": "E7456EDF9F5B5F614FDF8C88BF45B897307E2A48405FE3DC0F4B6966E9693C04",
- "key_seed": "4F1E079363BF2CF5C475F0D927C36B81FBEC8B4F323A0417184414914AC95ADB",
- "legacy_ldt_key": "BCB0EFC03494AD2260CE8925A140E58FA12FF5C6D59B467D6C4C6F616D0DEE6212DF667F5144F29E6DB4F04443EC2143A429F49189D4B96B077469D12FB609B7",
- "legacy_metadata_key_hmac_key": "E43D59616850DA473A9820F0F4215FB23E0BCBFF91360EC9A8DCB2166DD360FF",
- "legacy_metadata_nonce": "EDE3166B65C4FFCE477B0344"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "D3B5",
- "expanded_salt": "75DF7B4DAE71EAA2531A2A66BD67CC34"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "24921B2F2ADDC07DE0E4818DF0FA218D",
- "legacy_metadata_key": "F36505BC7D272E0A61E6F825CBCD"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "A188BBEE6CBAB5C972EE985C21ABF21E",
- "derived_salt_first_section_no_de": "5170EA5075FD2D3346430FE8781E352C",
- "derived_salt_first_section_third_de": "A7280620B2E6907C765DB1B005C56485",
- "section_salt": "C362D9DEEAB32835AADB2713E86AA3BE"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "BD6393FDA5A002CF968AD7F9",
- "extended_signed_metadata_key_hmac_key": "6CAFF8DE3681C4445926AF1CB615B8A7EA39687BD24597384002F0EF1BFE7FC2",
- "extended_signed_section_aes_key": "03A107EEEDE319EC3C14B287533F26F9",
- "extended_unsigned_metadata_key_hmac_key": "48107D08007213F545238626291ADF3963F71D64A7E42D859B77F5B5FED3DEDB",
- "extended_unsigned_section_aes_key": "918832BE7D5E3E5DCB8D6FFCFC53324C",
- "extended_unsigned_section_mic_hmac_key": "A0E2D0EE71984DD82D3AC1BDDD030913D4BC9BD276E71E2BEDB57290B0AD652B",
- "key_seed": "7B1FB28E5884B2B7DEEDC2620A87E729C1AA5E3810C56F59FAAE375BA22750D8",
- "legacy_ldt_key": "00A9B6FD99AF13743AA3B6E31381E4321EF15F21D4DF1D8B904307896ABB7ACE185526619BDE388E462847F178F32439245D8A4AD45AA26759DAFB751B6BB544",
- "legacy_metadata_key_hmac_key": "27F5E15D51C393501B5C9AC3254A8FADDE756110C8E8A952DE2FD58AB3EFD16A",
- "legacy_metadata_nonce": "DEC66637548279AB556A1219"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "781C",
- "expanded_salt": "28C257CC0BDEFCDC63D28B14D38A5E9B"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "DD89372C6BC8038EF866314AE0015DBB",
- "legacy_metadata_key": "D0D0C08326310877A07002234539"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "425882E16247B61965C2CB122571CFCF",
- "derived_salt_first_section_no_de": "0C8429B057889FF103029651B0178DB1",
- "derived_salt_first_section_third_de": "61F70C6EA361790E715295EB500A9DF6",
- "section_salt": "2BE5976B6054DC8EC9B517B03FA25754"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "22E652B9D05090C3CD17A386",
- "extended_signed_metadata_key_hmac_key": "B1F52377B751B3CD5456DF79607FF00F47388F2063BE559A151B7B9985030D9A",
- "extended_signed_section_aes_key": "6C6A2C0C4FB7B10E71D4B9C90DCF97D4",
- "extended_unsigned_metadata_key_hmac_key": "AE15A2095E41AFC7E33ED5A4F1210E36BC8B08761DCA1A50C8AAAF4D18804096",
- "extended_unsigned_section_aes_key": "FF93EDCD2458BD330CB8F6461CB5F3FE",
- "extended_unsigned_section_mic_hmac_key": "2ED5F7C30A3EBF854A6EC62863D9C22CA14BB8B3EE34C2E4CA48AA1972E6D74D",
- "key_seed": "674EAC48402573CBF8D9C71F862F2F773330F1C8777B86D6C1C054DCBDD7F5BF",
- "legacy_ldt_key": "C98FED8E0671B3B73E31019FACA33127F2EAE11BBC8D6D503E7C4C36DCDF42F8711EAFAD6E64AE2EDB6D2870203B64EF74388AA0FDFDEC9372AE06E4B14639BD",
- "legacy_metadata_key_hmac_key": "C39A23027BA99068BB113712449125BE8B4E891C92B9B822EF14FEEFF64D01F3",
- "legacy_metadata_nonce": "03759271308F135FCD00566D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "F14E",
- "expanded_salt": "1F35B6CAACCB4DABC88F014F186FD58A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "4DBA128B48257E51906815A44EBB31C8",
- "legacy_metadata_key": "1BCB5E77E87246FB145B53599415"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C210EEC7E5F37ED5DD585CA78E4F461C",
- "derived_salt_first_section_no_de": "512F88EC4D2C1D98155A79C50766881E",
- "derived_salt_first_section_third_de": "5C51EAFD14CCB470D455818FC233951D",
- "section_salt": "1F6F7DCED1EAB1B9AC53C24BF29D9E74"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "6EAE4DC82AB5941A1E09FEF9",
- "extended_signed_metadata_key_hmac_key": "8646A00AC8922FCCC259807B3B9EAEC556701927DC03ACADCB1DE1517F2C6C3B",
- "extended_signed_section_aes_key": "DA63146BE1A81A806C6DFADB9076E6C8",
- "extended_unsigned_metadata_key_hmac_key": "2F437D2C9BD771D02A87C0E17CB053958F62DC13559413C871FC01B4E5FB496E",
- "extended_unsigned_section_aes_key": "9366D940C998995D7846B28F0FCA05E1",
- "extended_unsigned_section_mic_hmac_key": "092BC3A92351F4673A37BFEC4BC62F8FA042EE9E5ACF391B2668142015570658",
- "key_seed": "6028F5FEE8F66DC80D4F1C4155D7DCF9495C4D98DD481AB2BC30C9FDF0672A2E",
- "legacy_ldt_key": "AC718CAC29033FF1FF300BC44B99BFD97F5419AE42BD79837E19D52C115C01FE32F0B2AA678D756B088BDD276CF6402B729A69F2689FFF6A035B5C9B6363A49C",
- "legacy_metadata_key_hmac_key": "B0A90F0DBC1ABA5AEE0F4A8CABD5764EBC83F3BD618656BDA509E594A91E4D52",
- "legacy_metadata_nonce": "4788CA94F7A0AB258486D3F7"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "18BD",
- "expanded_salt": "1702E72B0270FAB301ECFAE901FEB45F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "ED1208D4B3435736B92075B4E2DFBA3D",
- "legacy_metadata_key": "AF7F068F3FD3FEF1B9ECA66F33A0"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "B27EF32036E2AD671536F7CDFCF3D8D4",
- "derived_salt_first_section_no_de": "3841B50190E59B72F7F47281ED980317",
- "derived_salt_first_section_third_de": "1658D434AD2BD8190467E009476C1F7B",
- "section_salt": "F9172022012C774D058C8383D2D4235F"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "F7BFDC47005FE9892DD1A940",
- "extended_signed_metadata_key_hmac_key": "9864300E87DD5F34284AA47C00381B36C69813423B6BFCB14250715BAFF34259",
- "extended_signed_section_aes_key": "93C04B6BA7CF6F4A9B27615C900086B0",
- "extended_unsigned_metadata_key_hmac_key": "4CF4F78468301DC365A2C27BF4D544CE525F3CACDB471868FFCFF896D896155C",
- "extended_unsigned_section_aes_key": "908CC6D593CD9401D47CB850BF4812F9",
- "extended_unsigned_section_mic_hmac_key": "68283A8DDFC70B5B523E8ADB8DD98C209DD458140E3ED6C61509D4259DA8D4BE",
- "key_seed": "F04F58F4C6158F4E05EABEADADC3453F3A75FC3B6D331B45FD5589D0B16D5F1C",
- "legacy_ldt_key": "AEC307B3A752EB1C5FDFC64843A93ABF5D2674A9505C736D131B1C84BB89A17D09CAC89BEFB1274B56262CAB56F04EB013A4475B518170C321AF4DFEB3F3CF27",
- "legacy_metadata_key_hmac_key": "2C16FE1F32E5077BBB9C659C55BD9A77600FCA5D45FCE0430127514E513973A5",
- "legacy_metadata_nonce": "628F79EC288BDD800A4ED6BF"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "94A0",
- "expanded_salt": "9201A2F2DAB3488533230CD580588267"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "735ACB0A5B5A47743F22EAAD1F64F8BB",
- "legacy_metadata_key": "1DD0B9A032ADAB96501E851CD707"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "64C97FC6CB9A499116614733309E473D",
- "derived_salt_first_section_no_de": "3B2B9FCD5DEAEE859EFE8B7C2C8FF150",
- "derived_salt_first_section_third_de": "38999F9FDE0BB4A02621675A265C0F53",
- "section_salt": "E152E9CA82C846268793A13AC2CFEE01"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "0FAE226D0C037417DF2CC8F1",
- "extended_signed_metadata_key_hmac_key": "B03AF5D25B64EA34DEA4A04B30E234D0C45D0844AD3D76E9D4BDF72B9E1634EF",
- "extended_signed_section_aes_key": "419A9B17073BB3A7DEA566D14B322675",
- "extended_unsigned_metadata_key_hmac_key": "8CD58449D0AF3398E3649F977A8FBC55573464F4E25818E8ED94230A270E5B42",
- "extended_unsigned_section_aes_key": "52CFA465829A0AF17FCD496C302E7094",
- "extended_unsigned_section_mic_hmac_key": "B098BCE7ECBE5DC667C7DCD99B186B3294C442783741A2AF02973B9C1CEC3E7A",
- "key_seed": "26005EBE2B54878D7D51E8AE0A133F601F845706CFFE22EF5406E848D743CDBD",
- "legacy_ldt_key": "86F94EB0B3514972F54E4B072694BE295FACB1C9B1CFFEC97F7AEEE7E7A4B2EEF8D83CF3F46A1046553F0FBA739B512BEB70E8294AB3A8E9D354DC15904F8FE4",
- "legacy_metadata_key_hmac_key": "6C5F27B8758F150413A0E723AD2C87A89FC8E0922D6AFC9C4BEE7D640564F20E",
- "legacy_metadata_nonce": "C9E22F8D09D4F4593A61FE7C"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "35EE",
- "expanded_salt": "6DD6FC15DC3871D1664A44C78A886FC4"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D1B46D2631F70EEDEB29AA47D4437686",
- "legacy_metadata_key": "1416021C29E743088B02B41B571E"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "9651CD6607E54363129153CA5315FB86",
- "derived_salt_first_section_no_de": "0A54495999A555463622F3875F8B0589",
- "derived_salt_first_section_third_de": "E47744FCFD5DC037621555A11E000988",
- "section_salt": "5EECCF54ED89546D031A0103EDB17A2E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "57F6D756297E1693FB8A1D4A",
- "extended_signed_metadata_key_hmac_key": "1A7B18552F2818F7B17106C0D32337D33F69903604CFA6807DA5DCF2746108E3",
- "extended_signed_section_aes_key": "194961312A320FBF060414DB8650ED9A",
- "extended_unsigned_metadata_key_hmac_key": "25B117B4EE587290C4F7CEC17115E104FF96E7EFED13033C1DD4705BAFF3694A",
- "extended_unsigned_section_aes_key": "B5E64E57E00D022C4A1ED7F1841B5A1D",
- "extended_unsigned_section_mic_hmac_key": "D499BB4DA43B7ECCB3499AC1B5B0E251AEC407EBCA917F0EB08838BD618476DD",
- "key_seed": "D3457A18BF634AD2166223C38B4A1BD74C66DCCE809D410CAD1218F56EA363D4",
- "legacy_ldt_key": "D32BB668B2AA256B27339F45F228672FD51BCD73C3C0C044E9A9E27E282D867BF2A7ABDE2300452BDBE49B79C3457F65F38186A59D9B88FD5164365212DAB6C6",
- "legacy_metadata_key_hmac_key": "10A19D2EEA33F510D969E3A7036D1F288079A6D242EA2B1376DBEBB02F49C503",
- "legacy_metadata_nonce": "CA9A9DBF70527FBBDD94E59D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "00CA",
- "expanded_salt": "B2D541DDC7E007FD5D9B394E66C33319"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "0A4F31037E77231B0B51C8A447E3E329",
- "legacy_metadata_key": "03E5B8D922677CE5DC011BAFFBEF"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "9B1DCFE8149C1EBD905A5F2B71341C05",
- "derived_salt_first_section_no_de": "BEF89573FEA45BEE4E9BF988824904F6",
- "derived_salt_first_section_third_de": "41E32C74EDC315E7929DDA7FBC91CC8E",
- "section_salt": "EBF3C70C17A01679A563A39FA46D7F0C"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "605D86FAD007BC4EA0878430",
- "extended_signed_metadata_key_hmac_key": "EBA52456957CA17961D098C55159D6D79C3451E5738468586D4187B15300ED2D",
- "extended_signed_section_aes_key": "76FD6B925AA863C06D42FBEC0F29B98C",
- "extended_unsigned_metadata_key_hmac_key": "C80E7E9DE0E1357E95AEBABEA46C14C4065D8FB1B4B4CF755413B3F5EBD930C7",
- "extended_unsigned_section_aes_key": "AF6EB46E7DE399B15CBBB1F54BA7436A",
- "extended_unsigned_section_mic_hmac_key": "0F3EB356450F0A6C99BCBA4D69899631CCB0E18D5CAAFBF844D61B741EA44E9C",
- "key_seed": "3652F27504B90685287D9F9EFC800244A4F250F153B825F00389A5578D50F9D5",
- "legacy_ldt_key": "656543A5C4CA235799BFA3EDEF3734AA57830F3EB0D4BC94BC42A9E4265D0DA8838B9E69414F07E0F933784DD054194E660F604F345EFBCD694C2F466499747F",
- "legacy_metadata_key_hmac_key": "836A63241862CFE7B29FD00B05A9438D293E05E460C0E77C56804461803DCCDA",
- "legacy_metadata_nonce": "E188B583B00F2910B16EF19F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "E5D8",
- "expanded_salt": "FBEED7B8E11129FBB42F282F988B1A81"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "95124B323D4373E93FD74091B97406D6",
- "legacy_metadata_key": "CE875009453430A68CDB21A04D5F"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "A04BF6A2FF522EFB9682A288C93BB656",
- "derived_salt_first_section_no_de": "57DC6F81CE5B7432540EB145659C56D1",
- "derived_salt_first_section_third_de": "769504709A8FCC5EAC8927039CE9DA64",
- "section_salt": "B10E4B3856910D59B98435355E69AB25"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "C0FC2A8AD5C0AD828ACD91F5",
- "extended_signed_metadata_key_hmac_key": "720F677655EB635563DE99FA07E045D7074C1E099401341E7A7A3C93B55BAD55",
- "extended_signed_section_aes_key": "BDE744442E32EBA45FCC5C6340342AE9",
- "extended_unsigned_metadata_key_hmac_key": "1B380539C060707E986587B52E0EFB9EBC7907F939467741D385A3A706137078",
- "extended_unsigned_section_aes_key": "AD4E22885C75C1767DDD55943AA675C9",
- "extended_unsigned_section_mic_hmac_key": "3D1170B39B5766B83A74425A1CECFDD73786EDBDC4943C1063D29609AA6281DF",
- "key_seed": "E05713CE94A34C790D245E5340F0034B7FCE8C470639AACFB649E351C4517996",
- "legacy_ldt_key": "B77B168EB6924B7DAF554027BF77FEC4C5B0D5FFD370AA0D8A2D6AC2BAB0C678DF858B7B28A143BB4AD12E7D9CAD3B51D939E23C0AE1289797078334530D8BAE",
- "legacy_metadata_key_hmac_key": "B564B6695F774376499A95B28B11591EFBDD492948B9840B7207949154A46510",
- "legacy_metadata_nonce": "4DDA74813EC3FDD85ECF79A6"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "F388",
- "expanded_salt": "8967E476B2B0068E17A1B71FCFCBDFF1"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "E36AFC309B6E668C2C3A0CE5FAC3DBD3",
- "legacy_metadata_key": "8A97CFB9BF30ECCFA0EFD7E11022"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D5B0B8A104592ED2AA6605FAD6E2B786",
- "derived_salt_first_section_no_de": "546BD228DA5EC1C6706BBD0B6512260F",
- "derived_salt_first_section_third_de": "D9093EABE9731CFE5CD5EDC03B3593B7",
- "section_salt": "625AC46C5387C640952FD435DCE7BF8F"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "256918D6714CA183AEA76E3A",
- "extended_signed_metadata_key_hmac_key": "44E27B5CF5EB7F40E301D513BFCC0E7AD1D064268ECED1C93E08521C2DA9CDAB",
- "extended_signed_section_aes_key": "C717E7186766C821588610DDA234BD1A",
- "extended_unsigned_metadata_key_hmac_key": "5BBC3B99F800486E7D1ABF0998E8553CF827B4CB79D556CFC43954397909EFBA",
- "extended_unsigned_section_aes_key": "49E46036FD7EEDF2E316C8E3A2C83E18",
- "extended_unsigned_section_mic_hmac_key": "9EF8F3A9C044C579691C59EE221859361ED13B4C588E1576C019CBB83411A0C4",
- "key_seed": "E2633861C773DE669266B36268FD535E3B04A5269F5BA3B58DD1B2B2800141AF",
- "legacy_ldt_key": "B68B9BFB869949766927D96D8E11A8F7AE6B4D0CE4AD11FFEB56CCDE74B4329315EF8BDE16F5B89B6A05373EBDB09ED7272D20F51ABFABF50C901FF4A5B6D45B",
- "legacy_metadata_key_hmac_key": "B20510C6C750BFE0991CA3CD6CA3A6D1132A09CD845BDC3C2E006CFA4243682C",
- "legacy_metadata_nonce": "F82A5657110463EB4993D5EE"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "98AA",
- "expanded_salt": "13661848812A9F40B2C9550857E3ABF4"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "521F75308E4F3ACBA82DA74134C46309",
- "legacy_metadata_key": "4F767CCD14102B29ED949CE30218"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "DE24781BCD7E2BD9F39DBD8EDF8EE2E8",
- "derived_salt_first_section_no_de": "647E6F36D4F8529748EC831811ECEE59",
- "derived_salt_first_section_third_de": "A755924F3874F3E5661E8AA0F3F62173",
- "section_salt": "5A6632D4602C01565447BD6939610E7D"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "1280F2BF6B120289C45DC96B",
- "extended_signed_metadata_key_hmac_key": "6D058C55D5B2CBB0B4BBBD51028C0B973F469A1B8E3DAC59D52A1886D088F125",
- "extended_signed_section_aes_key": "37E713DAE40FD31E2F92C329CAAFEBF8",
- "extended_unsigned_metadata_key_hmac_key": "1A20B4BFE3EB4EDADE909358ACEBF1C020E9539BA5140BC2EF986EBEEEAB45AE",
- "extended_unsigned_section_aes_key": "3F872A127339C6C6C511AA00604C411D",
- "extended_unsigned_section_mic_hmac_key": "A837546D57AB36B017645E740D6631016E14E5B16DBF71E058DEC61F5F8AF1A9",
- "key_seed": "02FED3D1E3307A9FCE2B11203249FDC09CF979ACD85DF62359860EDCE2DC5507",
- "legacy_ldt_key": "B4D501B6B7DD28A54A49E3F57F99C782285B30CD69203E5AF7F838CC4A0380DF6EC89D1D67113E4517C6EE916460017B655F5A4AC373AE8FD68410DF230BB138",
- "legacy_metadata_key_hmac_key": "E1707BBBB1337ED59704AF606EA54550074F5B3D5C0310738C04128D634A8558",
- "legacy_metadata_nonce": "4DB188779B676BC7B70F234B"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "3B69",
- "expanded_salt": "A05E1016967C2E7DA79688AF74615B4F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "FA9ABBC8316622DC2A9843BA0097E0DE",
- "legacy_metadata_key": "AE83451CAC8181606BE17AC715C4"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "40ECE473568BE946121A394FE60B8737",
- "derived_salt_first_section_no_de": "7548394C226D05F10C9B557BD0359040",
- "derived_salt_first_section_third_de": "2E8189954D8068F3CB284740CE552CCD",
- "section_salt": "B3A517BB5CA6D1627B9A0255B31CFE31"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "CB9E33EEDAA33993FC4B5318",
- "extended_signed_metadata_key_hmac_key": "08AD406C9CCDB3892CFF81B5FDABB9ED3B08A24FFE60FBA487A9DE2EAB871A26",
- "extended_signed_section_aes_key": "973BF0F1F7B463EB9A97E1681BD1D3DF",
- "extended_unsigned_metadata_key_hmac_key": "E1DABB2A2F8D3CB975196C9BF900491D463BBEE01E408B3E595E718EBD1AA2AE",
- "extended_unsigned_section_aes_key": "CB15F4F517DBD310BCD5FEA2DFEBBF26",
- "extended_unsigned_section_mic_hmac_key": "865316C4BD1F483DF2FB1F819AFD6798B26344E9CB7D5F33C0FE5AD5C8DBC1E0",
- "key_seed": "4129B6D0A4B84BA1F7241CCC11F9C75EDCB74E50DAEDA9B94E7E5EAFD418921F",
- "legacy_ldt_key": "A3322720422B4E51C75B1C66F3BD3DF06DE13496B38FBA0BEBC4CE11B12238F3C779A2136C2B616F5E680A9A708E5E2CCC3F8AE9F0047AEA0B1AEA088C823EC2",
- "legacy_metadata_key_hmac_key": "43C5B9A88F6818DCEA6F93D49466F31BFFD5A4EBEC3C2ECF5A872BE86F5B99F6",
- "legacy_metadata_nonce": "A3CAF797ABC475FB19F5B602"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "AF5C",
- "expanded_salt": "C7F68B27D565702CF382B680B8E7055F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "1CC170AD6BC9799CB87FECFEB7FB593B",
- "legacy_metadata_key": "4D860E0531136A82B22D80EED522"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "EB90E68FE9C38FF5A956B2DA2D44D399",
- "derived_salt_first_section_no_de": "014EA160B58368629BA76FF16A844341",
- "derived_salt_first_section_third_de": "9ABC5ED7EF8973C8FF865B6174CF18D8",
- "section_salt": "04CDB186B08FB26AF67486FA439CA9AA"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "69EFD440262ABCAD6340712C",
- "extended_signed_metadata_key_hmac_key": "ABE74AB6340DB962F20CC9D40EAD220DB2E644547F110AAE1AFA59E98ACA5073",
- "extended_signed_section_aes_key": "C30E2EE7462A487197359E2B1E6B592F",
- "extended_unsigned_metadata_key_hmac_key": "46BC94A1996B114BB3EDFF2EE8ECA2A897EEC62704CB2EDDFFD5B97330E770D4",
- "extended_unsigned_section_aes_key": "F3ADC71F3D1948E5609C740FE8DC5DFD",
- "extended_unsigned_section_mic_hmac_key": "45F4745792A7129CD8864CDFB715B7047356DF99F7A3ECDFA4F1191C2EEF39DA",
- "key_seed": "8D228D34A11D8C6E89BEAD97C32CF1CDEB83128EDE806AB12AC1C315104A12C4",
- "legacy_ldt_key": "58B087E71D5AFBE1B2C9D40770425BF2F950EC54A80BD266A8C3DC184F4FCE7F6799BC221FA5FE4025EA898632E2F3D3C8A983E9468B99AC033002779395CEB0",
- "legacy_metadata_key_hmac_key": "79C5E3C3D6BBCB4FD9BE972683D273484578E592AB7808B1A2DBCB6A0AF0EB20",
- "legacy_metadata_nonce": "22C6BF85F720FB130D698F43"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "AA36",
- "expanded_salt": "1DCEFB9DA72BA3A4AEF988EA5C803E39"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "60989D8A1EB13AE51250E2698F544BD0",
- "legacy_metadata_key": "E9B69DC6D89A0FB49D43B34F5311"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "64555F0FD7574CDB19BA389CDFBC543B",
- "derived_salt_first_section_no_de": "3E0E5C26DD09AA19522AE9FF60E299B5",
- "derived_salt_first_section_third_de": "2177B3044D79C03B816CD8E8433C5B3B",
- "section_salt": "BFE9AF6A7740CD26E60E7C5A8AB281C0"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "8F2CC361A133B662D60E70B4",
- "extended_signed_metadata_key_hmac_key": "14F28363041B1AC420116ADBE5E862E36C4F209C68D784AAF659003123931F20",
- "extended_signed_section_aes_key": "F68813A0A51D3A7D6460C05109EF1730",
- "extended_unsigned_metadata_key_hmac_key": "6AC0B8555E39508D3F72BA8984E530E59A42777BEB16A2A6CFC760345AB6AB13",
- "extended_unsigned_section_aes_key": "F3DF15F42B2DCD3617C60847F88EC279",
- "extended_unsigned_section_mic_hmac_key": "149F3635D7BB841DE87493388AF27E75F0D5C374DF9108C5865EB3F1B631AD1A",
- "key_seed": "0D4D259D5D0E5D7C9B2A569A1C17D389E618B782D1BCE04F8484035492CE11C4",
- "legacy_ldt_key": "E1628A30487D83BB90ED7B5643AE314CD9FD98C9679F37C25D922DFAA0FFA66999FDBEFC099EAC5250C6CBCBA2314085DBDEBC4341A2074226D3E92773B1946A",
- "legacy_metadata_key_hmac_key": "9549B17906EDCEC2E747744703EF977F5236528197E55617F93755C860CBD0B5",
- "legacy_metadata_nonce": "BAA28085EE97A8DF527A5594"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "57EB",
- "expanded_salt": "D275F5AB0B47DB46096D6A2ECDF58D52"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "F3B453CA100ED3E10C91E12A7481F4CB",
- "legacy_metadata_key": "859FCE97618BF2DB58D184DC53DE"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "74F425482431EB42FF996BAC1A227F0F",
- "derived_salt_first_section_no_de": "CAC0DBDE04AB7B70FBF8A40E18814286",
- "derived_salt_first_section_third_de": "B751EC2415541106D79351A34AA5D2DC",
- "section_salt": "4B0BF5D2EE37C72845CD0776F7AAA512"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "183FB3B68B7A48FFF0C161AC",
- "extended_signed_metadata_key_hmac_key": "50027ADA2FF20DD6132B1729D7CDDF3D6619EC2F0B676D68946B199C65EDF004",
- "extended_signed_section_aes_key": "2C4916F70427AB1247D581CDEF656639",
- "extended_unsigned_metadata_key_hmac_key": "211294989AB217BBC4794503C433B7B886612E2D9A8B824B0EDD590F2DEC8B7B",
- "extended_unsigned_section_aes_key": "FEB3354D18E5ADA3E7684F96EDB719DB",
- "extended_unsigned_section_mic_hmac_key": "144845A3ED634D768F0F4E4BCEED5E9F23D77A033D67FDBE6F1BA225FA0A71A1",
- "key_seed": "2B4907289260929651D6339AE8157C6F509BF34AA7E2672B5C671837C62A0363",
- "legacy_ldt_key": "2A1BDC158660033902E9EC6F47BCF81C99EF5AE759CB03352320324BEACAC4D62F816CA1A190BCC28A276838F565FA5F41E2A7BA8574FA77D61F2A83DCDF665B",
- "legacy_metadata_key_hmac_key": "1266E50907BFA5ED5990F295F10B1562D4780775A3CC95F2F5D7DD9912644961",
- "legacy_metadata_nonce": "27B1A368FC746D389CAB7604"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2CF1",
- "expanded_salt": "2D9360CAD492BF9B3F8BA5659FBFD479"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "B04A6E310A7D824C2ECBAC27C078CF20",
- "legacy_metadata_key": "2E262ABE8F4651CE3875F82BBF18"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "A36E49ABD02685DAC38CE1D19D0B8B9E",
- "derived_salt_first_section_no_de": "D531C60F8CA7C63115E838F71519894F",
- "derived_salt_first_section_third_de": "722AD6D5D32103BE533568A2C3903320",
- "section_salt": "581234FE7E1189244C5C61BAFDA5DDB4"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "45E5E1444674572E775B8224",
- "extended_signed_metadata_key_hmac_key": "E0B347400DE60F9FA04DA4ADBAF3B6BD04C644F6793CE46F85CB71479ECF3EF9",
- "extended_signed_section_aes_key": "B6DDDDAF922C963512160E75225D09F4",
- "extended_unsigned_metadata_key_hmac_key": "AF0BE49B0E816D8F7712328C5F4E6ECC82DDC48892B3BDE3F1C4C01E5FA03136",
- "extended_unsigned_section_aes_key": "848215F6E61B20D5928039AD45AD2132",
- "extended_unsigned_section_mic_hmac_key": "8B905A2A15AD9CF4FB406828D832C9A035D4230C0F539D7647C55022232A9FE8",
- "key_seed": "32DD54629DB08642CDD3D8FADA206AAC7283C4CA3E2A8C555AD8DD6598720562",
- "legacy_ldt_key": "4274705A9EB207FFA0F1D42694C47173DAB548F1255772A438CB64BC9A03E80C50DC01E2F201BE9A1FF32E40C9008B4EAF1242A11CA3C0B4D398419369228C8C",
- "legacy_metadata_key_hmac_key": "EDE5263B245DA34B73AD72B20E1D07CDC64A814F65676AD59F056B31D3525B34",
- "legacy_metadata_nonce": "AE685D297E2D64B79DC9C2B7"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "8CA2",
- "expanded_salt": "49637910997ECD98BC7F3190BAB36A4C"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "BF435149C0B6A7FA723E18855A5D02B2",
- "legacy_metadata_key": "96FD3B89B68B0B14A3781DDF9538"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "DCBBEE3140866817D5B3E64BF6AFD60F",
- "derived_salt_first_section_no_de": "C7DBA60E81BB4A0F806B82F9DD4DE170",
- "derived_salt_first_section_third_de": "00C8B3CA67C7C566A850C3E17B7E3A29",
- "section_salt": "80FC0A629CE7F0CD7B603F171F162D24"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "CA66CE6D69EA86A41AB0F413",
- "extended_signed_metadata_key_hmac_key": "6EA8DF938647F825C60C6251F0CC1CD82FC642A0E254EF2620A746F46C9E1258",
- "extended_signed_section_aes_key": "0F0B94A88E78E605C74B5B91AE62BFFD",
- "extended_unsigned_metadata_key_hmac_key": "6C5D462BCD86343B68C4435D5B1EF6CF9AFB3C38F226AA84B7ADE93CDB23E83A",
- "extended_unsigned_section_aes_key": "E2C02DADB79D7CBFEA71F94C4A65575D",
- "extended_unsigned_section_mic_hmac_key": "38350921EF19BA63EA5D6A5511230EA652628101961EA4504A597C5FE4510591",
- "key_seed": "3836F8FDE174BAA5BFCE8F199CD45AF774C245312F90939B6D6FF51892F5C549",
- "legacy_ldt_key": "EC34EF3B3714001DD85534A5D3600A70645B612F7E8937362E43C683149F6F5621C3E2F700EC3E9E40AE468116316DB52F85746E6B9856FECFD94BA6BA852AF9",
- "legacy_metadata_key_hmac_key": "7B2DE270684F7A3872B5752AACE00BDA88CA3D832833432EF1FCEA8D04523E59",
- "legacy_metadata_nonce": "5A9EC7E213B30C88FB1F32BC"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "EE17",
- "expanded_salt": "D206579E8B5DA9132DBF4D1582A846E5"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "BECFD5FC4083874524BD1E5A11A15CEF",
- "legacy_metadata_key": "FD47DB9B922B170C9332494805DB"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "BE32AD26A190F96FC445AABBCB1CE959",
- "derived_salt_first_section_no_de": "8F061686BF5B1411A332C523C4E0A209",
- "derived_salt_first_section_third_de": "232C9AB5D992F3411339C60540915063",
- "section_salt": "8C2DCAFB7C90877729124D34A7D5B6E5"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "23CDFE5E54488821F6ED0A27",
- "extended_signed_metadata_key_hmac_key": "2B262B746F258E0AE1CECEDC1C761535AB94C83536FB700A8C005F7DD418C388",
- "extended_signed_section_aes_key": "DBAABCE45273B37FD68B63B6957E5785",
- "extended_unsigned_metadata_key_hmac_key": "E177B64123EFE628A6268D943BB7824EFF52212CACF2E3F59C07E165E4F16637",
- "extended_unsigned_section_aes_key": "B085C6252DC18DCD41D7F83A28071565",
- "extended_unsigned_section_mic_hmac_key": "32CD283375EF7007BA71BA8540A8AA91A05AFD714FE80809A9F92F0754F3CC72",
- "key_seed": "2E489B259C0566C778FA0ED37E2E7FA41DF3A664CAF4EF875A4427EDB479BB23",
- "legacy_ldt_key": "68682B202007B1B9DDA6871451170B1B093C2A051C7C5416E71313ADC01B5F61C9E849A9C2C1CECC480F8658C6A649F195EAC21EC41749E4E9034894B1A13462",
- "legacy_metadata_key_hmac_key": "9B6569331C5F5BC18C8444EDE38A946F59FF525D71C9DD3A0C0AF93BD799EF34",
- "legacy_metadata_nonce": "A6A810AA0DCBD8FB7C957713"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "76E3",
- "expanded_salt": "DB8C04B9A21DCCEC75C4D2C7806F57AE"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "0243B20CDF5D6EC2B5F40DE90BD517C6",
- "legacy_metadata_key": "10D3F1C4B9422B343140B77FC230"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "CC2F52EBC86DB28E36451CDAF13079E4",
- "derived_salt_first_section_no_de": "DF2CF0AF9608449FBD2545BEBE111B51",
- "derived_salt_first_section_third_de": "0B60FF977CD4A5D900642F660C496EC8",
- "section_salt": "3D36E649B2617F943C57E5845043BD7B"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "92124C3375F66E88EFE35C53",
- "extended_signed_metadata_key_hmac_key": "A0D58D77AF063A719AF9FF4EE9073C16B9BE7624AAB46951032E2DCA7E58F9A9",
- "extended_signed_section_aes_key": "2B11051C494B15EFF095B1CE27731780",
- "extended_unsigned_metadata_key_hmac_key": "0DAC827E8E114BE7A5377C68A902C3F9F9ADAA3799DCAB115B4402D6986B6693",
- "extended_unsigned_section_aes_key": "9EBE28389C5D4037FE9CE66E5815318A",
- "extended_unsigned_section_mic_hmac_key": "575A04282694E59058B0B62D8EE68F9F97063EB4CAADBBBBDD49CCD58C00AF3A",
- "key_seed": "0A188883B6CA017E98A98E6F25D090AD8B59432D5978D9B54F41A7E4F60BD880",
- "legacy_ldt_key": "C393CA2F2A769B0C37F6F394C806FAB5E6D73AE829B7AD0AA58351D65A8436D09F67C076069BE57AE561CFEC65DF13F31A2D78C583835335B9E79D42667884E6",
- "legacy_metadata_key_hmac_key": "CC4DDD317D155D714F0BCDCF55F7C7596B9593B5A331561D1E075D63605F1311",
- "legacy_metadata_nonce": "9D15BA91B10DA670512B7F69"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "0786",
- "expanded_salt": "90BF5725A647F3877EACDFE93F00743A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "44412FD614B0F95EB598CBD223F560A3",
- "legacy_metadata_key": "3A127741C99A09FD4F7416C678B9"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "BF6F7B9731537CD65957FE062847164E",
- "derived_salt_first_section_no_de": "7A4C1F1972B35CB2F1D8ED706210BF86",
- "derived_salt_first_section_third_de": "86D64154463B1BA93C139DDB0476F29E",
- "section_salt": "006BC21D03AFA7BD1316E76B52AF72AA"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "460BECD309A3EE6B35175031",
- "extended_signed_metadata_key_hmac_key": "63CB2E1C16F5B94BFD5DCF725B322E2EC4CFED49BECD757FA4A5066524875C15",
- "extended_signed_section_aes_key": "7D3E000289F97FEAC66DBA48492A985E",
- "extended_unsigned_metadata_key_hmac_key": "3C9232DEF5692ECB5F753CF1CE5AE15F1E251881D947B0EF726D86720C1E03A4",
- "extended_unsigned_section_aes_key": "A2FCCB33B71B1A8D807DC1D9241584D2",
- "extended_unsigned_section_mic_hmac_key": "52C00EB623D242318A865DAD8FB76A775F6D5D80F5CF030CED9777F6B704E9B8",
- "key_seed": "B48D65795DEEF4190966FEA215BB96F6052507BF909CB2DD5345E9FDEDF321CC",
- "legacy_ldt_key": "22F49B6998414150E646326B75F7AC83CF5DF705B33C582310A963116845F5E00B2937634AA8338AF18E9B45EC6C892708924A0868051A44ED4561D9D091F47F",
- "legacy_metadata_key_hmac_key": "8A28B3F414B387807148BB37C2C74977C2755E41863DAAC7B15E3B7C006A5E6A",
- "legacy_metadata_nonce": "1CD3B2E498B4D30985B1E11A"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2619",
- "expanded_salt": "11CD75FA9ED0CC386D81040E5E28BD5A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "6F0D67269728308DBCBB1DF1D485512C",
- "legacy_metadata_key": "F3FA997825C9B8CE27114093994F"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C4394DDD7E50753EA4F6A380BEAA6D75",
- "derived_salt_first_section_no_de": "9FBAB23311FF8DC91ED5581625BE5C31",
- "derived_salt_first_section_third_de": "7EA2A3C3E08970ED0ADDDA2EE28989E3",
- "section_salt": "F7802897A51C9CC8CB4F39237AA5AF75"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "32EBBA46F34FE6447FCB9F03",
- "extended_signed_metadata_key_hmac_key": "9D457FEC0DED032FCA7C4663788C3413D985458D3B7DD7C77CA808CEC7A7EE23",
- "extended_signed_section_aes_key": "C89264716F9ED0AD1A591D4E7B535537",
- "extended_unsigned_metadata_key_hmac_key": "A478F927217CE04B52D69110C6FC26C773B68C9CF862C586474F498B38AF736A",
- "extended_unsigned_section_aes_key": "726704CD26B963222D3ACE2E8510FDA8",
- "extended_unsigned_section_mic_hmac_key": "6912E3F7E93AA50850A908EBEAC4595C5542BD274247902C4EEE48E9EE5C55DD",
- "key_seed": "880B555B9AA8600F636A51A179B7E8F577425885545DF12D1CD6E01C87D3FE92",
- "legacy_ldt_key": "AFD7043040B31C0F86D1CF833660C533AA297AA161B8D2EFEA77BD0B1A1A2FBE3A194A52BF2950CC1E307695D750E818EB6CF2161FC3C1A0AB54B647FF9275F0",
- "legacy_metadata_key_hmac_key": "CDAC9BFD8382DDBB3941D3051353EFCD37015CA03452C66273EECBEFA22E03E5",
- "legacy_metadata_nonce": "C80E0C617C7A3CB8D2863481"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7165",
- "expanded_salt": "C7DAAE6B6635A8AB95D2300CB6416269"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "42BCC04B27A64629343177218F57BE0A",
- "legacy_metadata_key": "A876ABB90315F25712F38499B85C"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "0F6D736CE65D5C65A3B2D6559F5FD402",
- "derived_salt_first_section_no_de": "554244AF344CA2C83F253966F6102027",
- "derived_salt_first_section_third_de": "13F1B8E4B07D0A51B509F878A71C50A0",
- "section_salt": "FA523DAC59FFB86119FFC29D753AA473"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "2DF7FDECC381703DE06DFC8B",
- "extended_signed_metadata_key_hmac_key": "002E77DA262FAF5BEFB7668D09710373FD69821DC3F563320202DFC6F7F8DAFF",
- "extended_signed_section_aes_key": "A9B5C0BC08AFE740B6FD1E6BA8220E53",
- "extended_unsigned_metadata_key_hmac_key": "2FB80909E593CEDE519FA19B034FFC6D189E0B772B0C4FC686C3732C82B34F19",
- "extended_unsigned_section_aes_key": "E8D6F9C80CCF633B9F37574DBC38ECCA",
- "extended_unsigned_section_mic_hmac_key": "4A3E71A87ED54DFECD1FC9EDC09371D329E8B231A189D072F827863C3377FD7F",
- "key_seed": "B641968304F3D65286618FE936844A883932A98F172FAEB1CF5DC6E77007488D",
- "legacy_ldt_key": "9D925DBD151593EAC40F2C7FEA7BE2EC81891FE87971CF1C7F38369BDB8B12EBA067EEA5BCDDC36E5D8430CC67C9F8C85C272E868D75404E64A087FFAB92D7CA",
- "legacy_metadata_key_hmac_key": "F8AA867BD12B81AE663E62C650E705DD1F2A1D9ABE38A99A2E1D51EF7E2DA26A",
- "legacy_metadata_nonce": "46D5A1760D44590DCE76FCE6"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "587E",
- "expanded_salt": "D3CDEC97B00233FD542022C2EB5F3848"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "0D01ADC26CDE59CB3350AC0374ADD752",
- "legacy_metadata_key": "F9664E87F9E82683417A6C69FC6A"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D2B338926A1201F6CD659AC639B1862F",
- "derived_salt_first_section_no_de": "B3E7AA07BD4FAFB10015CD6C196E067C",
- "derived_salt_first_section_third_de": "4D84FFA3D9A34766CCBD37DF356A9FFC",
- "section_salt": "1D99919B07153CBA8C4D3311A118B9FC"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "F8495F6B16683501AE5B19E7",
- "extended_signed_metadata_key_hmac_key": "75B5C62C60C3019BC2D9D4CD91CCAA2E76D33EDC43AD13384123F3B5D52D67C0",
- "extended_signed_section_aes_key": "BCC8DB06C53733E8F793BD7D64DBF46E",
- "extended_unsigned_metadata_key_hmac_key": "A90E9E7F829DDFB44D1C10AD1BC1BF08401781B8C22FCE5DE73AC6DC0AC66BEB",
- "extended_unsigned_section_aes_key": "9F6E49E8CAD1919314298C3A354FC392",
- "extended_unsigned_section_mic_hmac_key": "C316406D229A27AF3CB3C13E906287EF8B5036B658FE824A076C8B6E74D2B885",
- "key_seed": "BEB2E5288A42FD7AC9E4BE6D4998F32CA5AD102DD6BBF21D9A63E92ECE14F7C8",
- "legacy_ldt_key": "7B180A8344D1E4A7E154BDE1DFD16888E3778686A35DCDB75485EF2A93762E0932D6D79EA0826E5ABAF79DEC504B7D539C6324CFF9B7D4C1F19B60B65D3B9BCD",
- "legacy_metadata_key_hmac_key": "BE281084F50E511096BF52D7FAA5AE64949796EFAD2615C4FD16495016C5CDE1",
- "legacy_metadata_nonce": "42ED5DFB6ABF8FC2CA75DDB4"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "9288",
- "expanded_salt": "EB04D1DB34235FE2814ABE28338AF6BD"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "E1478A4ABBA0D34E1DBB8440636BA1DE",
- "legacy_metadata_key": "3B2669DBE04D22E4146856F24964"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "2315A6A6A255AFDF9CB9BC23D7481C70",
- "derived_salt_first_section_no_de": "2F871D368ECA88997CA4EA877F8BCDA1",
- "derived_salt_first_section_third_de": "F4D547600C7C3CC1ECEB4D83C821D191",
- "section_salt": "D82414D60C56BC7571AC11EA22FD95A1"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "3225229E97DE8EF6EF3738A4",
- "extended_signed_metadata_key_hmac_key": "8F2D19779DE3D0BD45A93F9D546C7D70BA7D24A3039FC10FBED142099A7E48B0",
- "extended_signed_section_aes_key": "552CF2D3F72D8AD6AE4613521D744069",
- "extended_unsigned_metadata_key_hmac_key": "4DD906B20F0F537A4759DEC498B3F5F35A26A850F458B7AF9D140304C138DA3D",
- "extended_unsigned_section_aes_key": "E915FB586132C17710BDDBBC7BE734D3",
- "extended_unsigned_section_mic_hmac_key": "00FAB34E3EF9BABCC38BB24476583539C41F2C0CA69FBCD21C278742108158B2",
- "key_seed": "B835493E7A34BA1C0ED885CF78EB30CED4203067CFB0E3501CF1509C44A10EA4",
- "legacy_ldt_key": "63DDFA294943D9D30A1B8A911EF3C9643719AF8B1E30F6CC7FE9EA490E1F5544D22A65721399122A0A6324F215CC2FB178447E5D9F7F54FC326B994C27B257BB",
- "legacy_metadata_key_hmac_key": "15C70495ED3FD7EF63650611395B8BD9D6015DEDFE41685077911059081639BC",
- "legacy_metadata_nonce": "BBE949BBD59C4F963E7E2821"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "54C1",
- "expanded_salt": "0DB76FBA8F6AC46D1C0E4D3BF4F9760B"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "6815ACAD17F576FCFAC31D7CA348B9C7",
- "legacy_metadata_key": "D56BC285FCBC28F14904C110D022"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "A63D90F8D31E70B5F12FA49567853940",
- "derived_salt_first_section_no_de": "DBA2B7268B2EDFCE658C2DF7D1F50E18",
- "derived_salt_first_section_third_de": "923531B496A572D8E6C45ECDC3598D78",
- "section_salt": "228003CED4DE76F9E2E12998C3ACF2ED"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "9D7BBE2671E7D6C30CD6F810",
- "extended_signed_metadata_key_hmac_key": "33EB25BFFFC7B15197FAEB32C928CF5A128D01D00735C3EF7727F1F761F51BAE",
- "extended_signed_section_aes_key": "7D5EE6F4E07F8C5F07E258ECD20D4D34",
- "extended_unsigned_metadata_key_hmac_key": "792E4F635AD3FD8AA5054F8EC58AADF6BDF7471EDF9EAA2445C944C3C10B6463",
- "extended_unsigned_section_aes_key": "9DDB1E227FD6E4F9FA7D29BB7A5A1C4F",
- "extended_unsigned_section_mic_hmac_key": "9611D448338D20F3C6A6464C9CBE3841CD703E6FCBEBAC5EB44D3F5F5D6997B4",
- "key_seed": "D116B27178BB5F9D9979CBAA97159E4D4410DE3D26CE2AC3ABA7BDAB63A6B85B",
- "legacy_ldt_key": "5628DCC812A21B82C0619D613EE0E4B67082C89E316D23EA3409563EB8E297377F472FF25C4A0A70B2889BB27293873724B8C0E94A83D9EE2E080D3A5CFE0429",
- "legacy_metadata_key_hmac_key": "76D7B1B4B3E7432884C9A49F46FF26F1DCE8D583344AFDC7A6635254EEB5CFA7",
- "legacy_metadata_nonce": "3C2CA3B55509876DACCE58B2"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "A386",
- "expanded_salt": "F59E3504B2B86D465989D0F5B5F04E7A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D4522DEB87180CBAD14338BCF3B1107E",
- "legacy_metadata_key": "F1A6EEEAEFD437330DFB706FBC43"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "06C173FF92776658E2DB2394907E31C7",
- "derived_salt_first_section_no_de": "CC2D079DF426A5359DB15CF4DF6C894D",
- "derived_salt_first_section_third_de": "5FD567F78807129F25151725F939CA7A",
- "section_salt": "375DB6FAE577F7F2BBB1483161B62D98"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "4DB0F75206E7B33C55CD1A87",
- "extended_signed_metadata_key_hmac_key": "F01DA0E7048DC47AF21AE6E1E00705711F397C80E4E5872FD484CB2A353EA84B",
- "extended_signed_section_aes_key": "EA0D9B928C271079D8DE740792217A2E",
- "extended_unsigned_metadata_key_hmac_key": "0FE25C53F513D8C4079663AD26D3EFB76C9E53403A32CF3DD1AC5C4F0B46D401",
- "extended_unsigned_section_aes_key": "BEFF54630EB0851BABD6C9080B3650AB",
- "extended_unsigned_section_mic_hmac_key": "41E49DFF047BB3D9DFEBB5D86CA2FED61CCA22A8DA4AFE08010B4B2E026605DC",
- "key_seed": "8E94D64DA399A2EF9428419B72C2D6B96EBD83470CC5894564DC624BCAB5F437",
- "legacy_ldt_key": "2B802CC087114906FA80A9C68E0991C1D99CAE898EF25F2EF7FEC84E4B8F194AA4608F022C7912B8879BADAF1689140CB37BD15C4646BE36C61CDE4199AD27B3",
- "legacy_metadata_key_hmac_key": "290F16A7EF5A15726241870605899132979F304FC452B6E7D3CB80822AE3DA7F",
- "legacy_metadata_nonce": "9FDD6FDAE7D43E1937EFD1B8"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "1161",
- "expanded_salt": "CAFA25E3F8E00053BC3825E8FF5D5078"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D918D076ABA54A6B7FB5406522616208",
- "legacy_metadata_key": "6C7A1A6D9A337FD3FE62B2E2ADF9"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D2C405851BBC1268709BCA5E92ACB57B",
- "derived_salt_first_section_no_de": "8F84A4AB6444AFD08FE7110D0D16C74D",
- "derived_salt_first_section_third_de": "4C3C84632D69672E8921C5067A7DFB56",
- "section_salt": "5D950CB5E7D9F44E9429359415FED1B4"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "F061EE619FB13FE95DE267E8",
- "extended_signed_metadata_key_hmac_key": "F276A731C51D5936687E7F908F88224BA28BDC2D6A4F94999765822DEE917D6B",
- "extended_signed_section_aes_key": "CD9E5F7C922F58A56A17CB8F62B9DD09",
- "extended_unsigned_metadata_key_hmac_key": "174295A2B19CD4F9A821895D098CC63CB4CF17AC16CA7BD0DABF7136C2D3D194",
- "extended_unsigned_section_aes_key": "1CEC9AA427A98480A6642003700F4A5A",
- "extended_unsigned_section_mic_hmac_key": "6780C7E76F1A85B3E31A1382505FE21BA04AAFE268C9810C626E72C9203C638E",
- "key_seed": "234DD6BBDADEA172BB97EA68E22A0B0321F8DBD65EAAAA38F95940D73770F35A",
- "legacy_ldt_key": "7E7C646B51F1867F6D7CEA56F2AC7EE80DE9D9DE2015E9CBD7525ABD0FA05656CAEFE120EEEF521CEB7D9E296555CF8A249862D97F0D3FCAEDE9A4E8C309092E",
- "legacy_metadata_key_hmac_key": "1DA50172EAFA031A15FADA0313BA770324BC8A0D1223FD5EBC127A331459F2B2",
- "legacy_metadata_nonce": "74C72A883D6BA2CFB5F68830"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "F836",
- "expanded_salt": "F8809BFDD69EE831A7686D8359BBBAE4"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "A97B037072AC4D59472E20AE1C8688CE",
- "legacy_metadata_key": "4E18A6F5EEDEDFAE9AEE43A53094"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "146332F0DF9B6701D5F6ED9173B966D7",
- "derived_salt_first_section_no_de": "CA5CEB6D8BA41402859B0706E603C25D",
- "derived_salt_first_section_third_de": "E93B2C310878FED27F89298CA9F77731",
- "section_salt": "EB9DA18BDB815DBF4BF9906E8AAFB491"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "588AB130BE0197CBF1E240AB",
- "extended_signed_metadata_key_hmac_key": "948A762DFB558385CDAE56420D2AF863F8AD6ACB9EC442775C20F1D12793D08A",
- "extended_signed_section_aes_key": "FDFA11ABDAC005CD0C6DBAFE22CB84F5",
- "extended_unsigned_metadata_key_hmac_key": "A8ABEFCD7AF7D09F7862E825FC5D641A23CF32210676F1CB8AFD375F180DE059",
- "extended_unsigned_section_aes_key": "895814EEFA0514080381B2466C5560DF",
- "extended_unsigned_section_mic_hmac_key": "770CD91393852E19BB1A5878B8BDA5E4B9AF9A0640856804C470EDE355DB0914",
- "key_seed": "519521C296DA4C8A13A47835506AA306C9782F3F1C946D061616CA248E64CD9E",
- "legacy_ldt_key": "84406D27E7717B520A082163CE7DF98BCC0261E8342C105F210C31FDE6B5521547E51414E67D00BDDDB57046564FD491A88E4C5CB913D28FDA7C972EA21A9DA0",
- "legacy_metadata_key_hmac_key": "24032DA88D3510F18FEAF898A414BCCC55EF1E56350D07B6A4AAAC85AD09C863",
- "legacy_metadata_nonce": "F0392AFD52B25E66D0D16B50"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "AF9B",
- "expanded_salt": "488FC6BDA553D9894C6C397E009D56F9"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "AF67A28D0088401BE912DFF010C7CD2B",
- "legacy_metadata_key": "0A0692A83815A72C28C2E1A0C324"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "B57FD4C4A95B5FA80E77FB0A4342B558",
- "derived_salt_first_section_no_de": "804C7287DBC4705759D1543D3BB19796",
- "derived_salt_first_section_third_de": "185B5BE5742AF28DA4D9BA8FFDC8E609",
- "section_salt": "1D6723044D269740F2E422789242AD4A"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E4EDFA97754C39393AEEF09A",
- "extended_signed_metadata_key_hmac_key": "AE6C660ACBE3D637F9D01CFB4EA927FF4B1DEB1446EB096688BCB54F5C1A5389",
- "extended_signed_section_aes_key": "DC58AF65EDAB2BDB393DDD7033F781CD",
- "extended_unsigned_metadata_key_hmac_key": "578C17FC68D03B2A9FFA8352C4ECD9D15DE2F97B5500DB4A9FEE70A93E28AD2D",
- "extended_unsigned_section_aes_key": "573CC36574396A27D5CD12DE72470637",
- "extended_unsigned_section_mic_hmac_key": "9D8CFA87DB083EF2FC4C495E6A7E3F8483C608A186AC9EFB6C22144B4A654034",
- "key_seed": "A34102D098DBC12FBAAFAC0DE0F0959450DF888C7323AF55CF04B976E6B9152C",
- "legacy_ldt_key": "78065CCC471C92F1328DF45AF7180DCF3073A56F599B861706DB9691DEE1580AAC1FBE1215CF24AF403A0BEA04E27C87E91E24DE63CB61C35576326B32A50F97",
- "legacy_metadata_key_hmac_key": "E8B03892D17EFBAAFC23A96ABEF538A2AC1B34A9A76E5C32E70D67CA73491EFB",
- "legacy_metadata_nonce": "889DB55C293C1227BCFA48AB"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "4644",
- "expanded_salt": "8E7143D60063DC6AFF6A285C0CAED64A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "B61F6E359C97537CC9B30A51581DCAE4",
- "legacy_metadata_key": "D3E6FF7D90D25CD472C672173992"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "0CA731695CA701A5DA7CA3F15898E7B4",
- "derived_salt_first_section_no_de": "C576F3146312E1744C5AAB5553880FD8",
- "derived_salt_first_section_third_de": "39E3A93EEE518127370FD04B92CA2506",
- "section_salt": "DC536229ABCC11D225875AFE64B192BF"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "D28B1E59115D3A1862CA1F90",
- "extended_signed_metadata_key_hmac_key": "59A3E079DC5F8697219BEB4ED10CBD2BE60551E59B9FC30296574304026D05D2",
- "extended_signed_section_aes_key": "15491B6EF07D98836A01228ED8225758",
- "extended_unsigned_metadata_key_hmac_key": "ED9C566500737283B6CBE3288D119DC773E50C22A2736E0F95F6EF4BD583C67A",
- "extended_unsigned_section_aes_key": "FE8FBBDB0EEEED2024B35F30E49E06B8",
- "extended_unsigned_section_mic_hmac_key": "24EAB7D66302B766B2BFE287A784673467022D56E7A4706B3EE7BAE1A04787FB",
- "key_seed": "09A152AA290EC4BF418AFB60B3F66BE866078A5F59FC3BB39728DC80EFDDC5A1",
- "legacy_ldt_key": "E3265FA3C650A2F0DAF5CBE890CE5430807AD6C7E423858F4D8A47DACD39BD87C5439DC6D952CF87DBD0840736D5FFDF0EB5FE2661A9141B2CB3C8B28DBB7F77",
- "legacy_metadata_key_hmac_key": "6497FF0A4F742EBD8C908673D696FFA289C2C1DB64434ED082F9D2C7D8862196",
- "legacy_metadata_nonce": "21BEB33970139E57B2BB897A"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "DD89",
- "expanded_salt": "0F01369801DE549FC4946F13D754CCE9"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "EA4CA525B09663EBCABF017A6AF3FE89",
- "legacy_metadata_key": "0D4C5F0560894C41FA9951DF6EE3"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "621132026D7F9CCCF26A682B7761183E",
- "derived_salt_first_section_no_de": "24DAE7CEF38D92425B0C2C94B88566BC",
- "derived_salt_first_section_third_de": "813BBB1469B4319669B8093FC8FBAA15",
- "section_salt": "42D31FE0C4495AB88C2CC34728DF59B9"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "99E72102DE2485A8CD026DCF",
- "extended_signed_metadata_key_hmac_key": "49534D2085653D32DCBD06492CE860375D41A3D91C5517D98759257E6D22D46F",
- "extended_signed_section_aes_key": "F7091AD2941314A7934D2C74D2D2CB35",
- "extended_unsigned_metadata_key_hmac_key": "A0BA2094C1CBDD22854EB846FA4DDEC387B0C1E13A7BB833C6E7110ADA47F6AC",
- "extended_unsigned_section_aes_key": "ED03585313F4DCE95E765913E100E591",
- "extended_unsigned_section_mic_hmac_key": "EC361DD6B444EAED4BF342CA6479319B2FA391062D6E627A50F40730EFC50B5B",
- "key_seed": "154EB89F568C5D04EDC4AB0A61DD783D0EBF04437A188B2175B495C8D5019655",
- "legacy_ldt_key": "171DEF9D37747E6F9D6BBABE17B2F7E049608D67518DE48445AD0FD1901F6016C95AEFBE451AE7E256541B8307A16A7E0B7D259219DC81D4985EAA3FDB743E44",
- "legacy_metadata_key_hmac_key": "9BC8F5BF79FD354DAE71DE2CA4B91AAC36D6A875D3287D721D3EDB4AF52AB3C5",
- "legacy_metadata_nonce": "A5C09B3E1E02FC388CE5D124"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "42AF",
- "expanded_salt": "D2BB747C495DD8231531B9149C9C866F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "7831F6B9B71D322F74FA91734B8C193C",
- "legacy_metadata_key": "6C33C973C499174E058F63F0D59B"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "3D772AF59FA77F172C0C61E75864316A",
- "derived_salt_first_section_no_de": "45BDC255A9DC922C4D816CE216609E29",
- "derived_salt_first_section_third_de": "C7256E328AFE8C6ADAA9007494408E01",
- "section_salt": "3AA898649E58CC9FB5D7CC5FC9B26C7D"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "EAA31B86CCF3CA56AE358D43",
- "extended_signed_metadata_key_hmac_key": "52DFF69B372CDF7A4E4844CFF34AFF3B97EAEFC323FD0BFEE409062D8D283ABA",
- "extended_signed_section_aes_key": "51AE16500538B6819A646EB9AD330FF4",
- "extended_unsigned_metadata_key_hmac_key": "8772D7EFEF2CA10A882DE8F73A4F5949575BF58E5293FEA863ACBABFC7E12EAA",
- "extended_unsigned_section_aes_key": "70847AF7A37D9C84957AABC667F6F066",
- "extended_unsigned_section_mic_hmac_key": "5E659C4B61ED807910D78AEB440F13CA494228B7F0332854B2D54C984254BFFD",
- "key_seed": "314E89C6DD5D18FE4B824727DFD96F2844000FE144F0BB3AB004B4A8584DEA1C",
- "legacy_ldt_key": "4E0F8B2D2B62F991AC23EEE229F133DF03674A412318DAE3B7D31B1EB3F5FC1394FBF81FE0CC0088C08624C058F8A4F5069A6B7DCFB26B2C24F59FE8999EADD6",
- "legacy_metadata_key_hmac_key": "F3595FCB9F437ED53C7BB6D2A52EB890BCA1D8B823722383D76830B50E58086F",
- "legacy_metadata_nonce": "BE5139909CF99938E465B5F3"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "E9D7",
- "expanded_salt": "8143B10A7353AFD1884BD8652E38C1A1"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "22B61200D9EEC2A81E8FAC74ADF6F9E6",
- "legacy_metadata_key": "6EBCAA307ED2B72FFD2CD6F249C5"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "9D4357DFBE20C028112104A515ACC3E2",
- "derived_salt_first_section_no_de": "A23C5D2DB650AD57227C15A86F1BF40E",
- "derived_salt_first_section_third_de": "7A4B1899973D71DDCB4F92E1665072B3",
- "section_salt": "68C6FD12C8C56CB58DF60455A0FE7AD1"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "76EEC201AB36A236EC186625",
- "extended_signed_metadata_key_hmac_key": "A0F331B488ED78B4190BB62063B6A66CDA7A3503E1CBC08368E39565C307C062",
- "extended_signed_section_aes_key": "BC854924304C1F14181F985F2A7875E0",
- "extended_unsigned_metadata_key_hmac_key": "0A298E55442FA855F3EF35E748D52E1EABBB0FA1B3E17D24957F964F413A76B5",
- "extended_unsigned_section_aes_key": "6ACFA834A2FA81A1A4A7D6DB9988078F",
- "extended_unsigned_section_mic_hmac_key": "B34EFE5E312B504B811E32330C120106154D5303F431DED9FB1FC845C71CE193",
- "key_seed": "FFE98778134B058DDA1C17F3B368FF6DE1C9FCE69BF5AC63C133177E707AB259",
- "legacy_ldt_key": "976F3552251D50BB5E6B10A291ECA51F7E5C0C62F13035B55420530F464364C74CB41036BB8294CA2A438F946EEF622071841005B6D804412959092ACDE0A22F",
- "legacy_metadata_key_hmac_key": "1278970FF627F1F077A0AF1C370317EAA0CCC33843B47DCD94C59A908069A70A",
- "legacy_metadata_nonce": "23C0DB064837D54FF3883DFC"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "F2D0",
- "expanded_salt": "BF636415E72B8974D9CEA57DFBD9713C"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "869D047A3EFED540B16C867918B5CA06",
- "legacy_metadata_key": "D6C78751DF42B853DCB42F723B6D"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "F6AF11DAE90B198388EA1D778C10CA4A",
- "derived_salt_first_section_no_de": "3AEC2DD5E0D29A9EE0DE8B6C00DB2285",
- "derived_salt_first_section_third_de": "29C1901D0646729360364695E47F59AA",
- "section_salt": "B0955AB7ADF6FD11F1AAECB1A777A329"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E1CD4A0A0F44E1B9EBDC99E4",
- "extended_signed_metadata_key_hmac_key": "B2EFABA87A2E8BCC4ADB9CA2C94B425E824A0B9E9ADE39C000E7AFC3D4084D8C",
- "extended_signed_section_aes_key": "A59CFDB9BAB8A6774B67B80F1D5EB576",
- "extended_unsigned_metadata_key_hmac_key": "E975F5B3AF3C931B94F7D7ABD332BA9AF8C40F822BFBE93685714E49FA34BE81",
- "extended_unsigned_section_aes_key": "B9E68CEA1E1836ADA1C2B6F72F19814E",
- "extended_unsigned_section_mic_hmac_key": "9054020C39D0AC975FA1446386B282FBA102D3B13B94E06751182223E8BACD20",
- "key_seed": "92CC48D1E46FD37FD8D92063C275E5601F7956B1D79EB4DA6406989177F795E6",
- "legacy_ldt_key": "79873B89C6801423B759014737AD82E8774EFC2648416703942B31D831438D9C7AE96912B7CE48F10A5A81222BFD11E7BA68188FF8A68594ACCC5F3EFD183376",
- "legacy_metadata_key_hmac_key": "DB7883B5FC9939D08A478BA41CBC8D205359391813FF7AA1B1CE8E5446835005",
- "legacy_metadata_nonce": "CAD17CB88CBB262FA2648FAA"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2760",
- "expanded_salt": "ACE0FB227A299B29532B691723192E4C"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "CECFCF062962713BF67A2C253C34C430",
- "legacy_metadata_key": "514B537E9F65528BB70C726EAB75"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "711E72342E2DF4D9DB3E21CB79E15B1A",
- "derived_salt_first_section_no_de": "4AF7B282B09493FE2AB824CE11CF5A3D",
- "derived_salt_first_section_third_de": "BDECA0D713545F2C06E92ECFD90F32FA",
- "section_salt": "5A7297E0F00FB0AE50DB911EA8320E32"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "53C12B415D361B1E7CFD2BE9",
- "extended_signed_metadata_key_hmac_key": "1A903300F25E61572D66E6F92E4F20526EFB141748AC018547F164847EC33029",
- "extended_signed_section_aes_key": "8EDD20D6C52E46FDB3005E2F11D40E78",
- "extended_unsigned_metadata_key_hmac_key": "51AC4D0DCC343FB2A8442E497D086767A0F904FD8FF0C2F5C1C3C7F462E2690D",
- "extended_unsigned_section_aes_key": "DDD633E7ABBC286E409104446AACE0F7",
- "extended_unsigned_section_mic_hmac_key": "57061A968056E7ED330F1C8F65242B18335B0203B3AE5F863F861FBA07155CFE",
- "key_seed": "9E095A9E979E0556C03FE1276821A0905A530027A4E48B445FF150DA40A47BC5",
- "legacy_ldt_key": "74EDD1187CF248366FADC5DD69BB431EDB9FB39621221F62A67FED5CB3D0129EE8B5526BEEC86BC1CA0193239184A23D70D901B12F89079E1560A25AC839F6FE",
- "legacy_metadata_key_hmac_key": "5B34A6319FD27843706A8E1A7A1E779200E3D9BE8DA1246CC5E32D88DE816486",
- "legacy_metadata_nonce": "F23109B82D2099F6F94B4C88"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "FE58",
- "expanded_salt": "9C7EA9924564F03D6340019D4BCBBA47"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "439B31109FE781639C510638CD037A12",
- "legacy_metadata_key": "1F22EFEAA64F55866D64968A732A"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "F1CA484DCFEEEAF8652F00199C50A97F",
- "derived_salt_first_section_no_de": "9F52A5DAA201CD3307BC80F9A3FF5A64",
- "derived_salt_first_section_third_de": "BCC55DC7AD531D04D24F88CD03FC9947",
- "section_salt": "96E68F69CE0AF1CA5947D950AC03167C"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "790DA0B3358A34B85EAC7667",
- "extended_signed_metadata_key_hmac_key": "8CA9AA70936AFBCBABF150D6E5B27AB91974D4B039CCE5C1F3AD7CD09B124F08",
- "extended_signed_section_aes_key": "9B148D55787368596D67A8536F89214E",
- "extended_unsigned_metadata_key_hmac_key": "2497B036129D2F25F43E6838495CA54DA3E39DFBD80906C945F1C536CA8B54F3",
- "extended_unsigned_section_aes_key": "680EB9CE125DA2B614C1768023E69C8D",
- "extended_unsigned_section_mic_hmac_key": "4FDA73846885210F5E42B57D32C559C5C176B4FC17A5DE755E9832F7473A6615",
- "key_seed": "1C21EF77FDCFE2F77ADC1687CCB48A85C71A6D53E8BBF9C445F9A81E44C96010",
- "legacy_ldt_key": "65D36DD12CFA1D5985EBD4547CEE55D85A439A6879A390A114E8265B52DDC19071E346DE0F8AF67D8D91B506399043DE945F3B61F0698D58E80543BCD6FB57AF",
- "legacy_metadata_key_hmac_key": "7D96F6A20DDE772C03F269C6B5D1851A569C300D5B0277B7AAEF6EB9C71C884A",
- "legacy_metadata_nonce": "3E4300FD8F982F491BD335EC"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "9CC4",
- "expanded_salt": "61B568A967985A5611EF9256E29E9894"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D477CF6201CC1CADBA21370D16760F8F",
- "legacy_metadata_key": "50841355894155E171A91BD507A7"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "DCA35224242C81D062E2D7806C58D0B2",
- "derived_salt_first_section_no_de": "54EF44DB16594004E554658EFA470231",
- "derived_salt_first_section_third_de": "001814C42510FCD65262A3B4CC145933",
- "section_salt": "B601766283CBAE3A4CE5C7DFF2A0DA74"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "A15525217C62F032E6D54151",
- "extended_signed_metadata_key_hmac_key": "298E19377343EA2CA328F5BFA39DC8517F1C426BDA2171E0A09208C39BA50145",
- "extended_signed_section_aes_key": "2167A0F9007EB1A8EFED8341491C5B68",
- "extended_unsigned_metadata_key_hmac_key": "2219E955FC16E04FEF31B79E0C620133CC4BFE2CD2CB6FDFB756DD88FDBC0799",
- "extended_unsigned_section_aes_key": "1F7AE997F2B6D9AE904158DDF91C7A62",
- "extended_unsigned_section_mic_hmac_key": "4D3627566109F030079FC771DED6D567F556A1FB703A89C51FB76C2B59FC5443",
- "key_seed": "121462ED1B16BC8682D880878916CDB81CD7E7556FEEBA1FE22210D2949F0931",
- "legacy_ldt_key": "0EF6436C70F2797E08DCAE6D368C1C3EE7B8578572EA873C8B7C185D8CD1616FB0F33F4632618E4A60B9B6F9FBFD7D34655A50C444995C7059C93DD28AF58176",
- "legacy_metadata_key_hmac_key": "184A3999BCF8CC12D37D4013D7822C64A11CE426267A0271C1ED53E7E8DB1000",
- "legacy_metadata_nonce": "78C1769887FDE04453C81658"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "296A",
- "expanded_salt": "F44EA8B30FD9F999BC7E31C8130892C3"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "4299BCBB2412A71215EDFBFE1F8176E7",
- "legacy_metadata_key": "07C4A089310EACCA1B3BA2D4EA94"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "F3CAEB25DC97A317A38C99E7F1438E1F",
- "derived_salt_first_section_no_de": "EC4686E3C2F9A5AF8934C8EADAFAEB6D",
- "derived_salt_first_section_third_de": "921DBFBA6B75D60A97443F20A6AE5779",
- "section_salt": "F3A5EA6D8CC24F111F84B17EA038A2FC"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "944F676AE58D1738571A6988",
- "extended_signed_metadata_key_hmac_key": "D5642BD297591472FEDD16557F86D9FC98701FC19BB83E24A87EE5D31314CCF7",
- "extended_signed_section_aes_key": "B2FE576CBF190EFF36B7DDF428D08806",
- "extended_unsigned_metadata_key_hmac_key": "80E4277B7C98DE76783580F99D7AFFBD0C939069E129FCD2A451DE2A4DFB347C",
- "extended_unsigned_section_aes_key": "84AF72363AC42837703E0233DA58AF15",
- "extended_unsigned_section_mic_hmac_key": "309CEADE18269614513CC150680E07E79A395BFD00966021D074AA51D5DBB0B3",
- "key_seed": "174C6D54B1B0CC84774E8FB9339AC57933CFEC2D78A57F66268A2ED648C79D54",
- "legacy_ldt_key": "FEFDC3138EC8C0F7CC34C171A43E9AEEBB4A0FE5EAADC607A9D6600D8B9B54D207A2BC90D0B38DD989EB57AEE3A21F11DFA1C22F8DEEFCBB84F14DE16706CB5E",
- "legacy_metadata_key_hmac_key": "181967500164E896A23C22E206E00208E0A82CBF97B839DA87F9C3EC5759F1EB",
- "legacy_metadata_nonce": "0688E75E1B921F995491EB07"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "BEB5",
- "expanded_salt": "C401AFC676735287424E9F7F0DF237B2"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "8AB09C04AC42D4F4E123FC884885C595",
- "legacy_metadata_key": "191530A2A7F75BBDFD7777601AE1"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "99D022786E9CC9AB870AC2FF57DA80EB",
- "derived_salt_first_section_no_de": "01E17F91C55F51BD79A72463BC8493F8",
- "derived_salt_first_section_third_de": "AE2DCB3E34AB81BF22F460D7546376F0",
- "section_salt": "3E1F652AE28F8335D7B15864E9F7CCF5"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "F3ABE0F91D65A95957CF2AD7",
- "extended_signed_metadata_key_hmac_key": "0F4E56038ABF9ACAA73EC95395B337124A89ACC20399E1DBAB7F8F73182BC107",
- "extended_signed_section_aes_key": "13B7FEAF3CD5ABF9905CDA55AFDDEFF4",
- "extended_unsigned_metadata_key_hmac_key": "B42A14360C1128B0B4AA1D99E89B32F4D13D2C8A191EC5E58DB841EDDC4ABF76",
- "extended_unsigned_section_aes_key": "3AE1FBA492CE6D8854923EEAC2AB8A17",
- "extended_unsigned_section_mic_hmac_key": "9FF77BD8BF275AB41652950CE40976102A641CE5CBCF346A9E755281FC0259B3",
- "key_seed": "9864ECFD656E7B608A63883FBEC4F62E8E6F7A3590114C39E036AEC87BECBE41",
- "legacy_ldt_key": "8FC7B079C4225368931B03C4814EAB6DC02175EF1873B1A224CFD39B9CD99814417A884A2FDB9D324747F55A9BF7758B22C2C3113D06ADC373B0A47E925FADF3",
- "legacy_metadata_key_hmac_key": "493B6E99413B5E07771053F536EEB8DBF169B4DE6E78EE341E1627C5055200B9",
- "legacy_metadata_nonce": "B4245B6A65DA3B698B64B9B1"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "8C5F",
- "expanded_salt": "1E634D3633DB16B5698B53B1FAC7318A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "ABACBBEA70871DA67332DAD622F9877E",
- "legacy_metadata_key": "711C81AF55689C9F41F26EC0B3D9"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D42F8611248F16803F100880FD2C40A8",
- "derived_salt_first_section_no_de": "0AFD085C634D64812B22120E6EA087A2",
- "derived_salt_first_section_third_de": "0530E299A7CECDA05EF000FCBD461AE6",
- "section_salt": "1025402C2B74145C70E2CA2E518A83C4"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "37CAFFB8E8BC64931F3190F3",
- "extended_signed_metadata_key_hmac_key": "15D89B2AEEBF854A0BE65C186885E4AAAB903E312CF27B67F8881FACB082B7D6",
- "extended_signed_section_aes_key": "640271AF293235DD4592A0FD12EDCDBB",
- "extended_unsigned_metadata_key_hmac_key": "3E5D5FBA4B63F41DD8B5F42C1A285DA8C0AACD5AE96891BF9BE94BA7F2A3422E",
- "extended_unsigned_section_aes_key": "573C4B8052EF1CB1BFCE2EE02A21FDDB",
- "extended_unsigned_section_mic_hmac_key": "269360FAD76012F1BFB9B46E48CCB4A4484C959B46AAF666E7E99BB571D02DBF",
- "key_seed": "AED5B53B0E0A4A8E7A00B1DFCC03428D99E7B07CC6B90A2A226DAC3C51C53300",
- "legacy_ldt_key": "80B93319EEC4CB0E43E07CE1DCC54AFA5143E3E0688297837BE19921550E3903AC441802CF7816C959C8BB5B5F650C294379767E8A13821F0BD4CD0164748355",
- "legacy_metadata_key_hmac_key": "AD90B2CF579CA71E41CE8EED3E8D2EDBE74BC6B3E090C298B3027E2071E1D707",
- "legacy_metadata_nonce": "28C25CA1937E414689922A89"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5CD7",
- "expanded_salt": "3479EE965DA3C29D12C79B83F87DE36A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "EBB365F56DD11C290CF18ABAAA208F68",
- "legacy_metadata_key": "798BB2405B1E4C58708885C8C64C"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "E06D761A8CA571BF0B0F44BECE8D84E5",
- "derived_salt_first_section_no_de": "F4FA7DA6B4BEB32FB8D61AD5529221DB",
- "derived_salt_first_section_third_de": "C8B3BAE8D808A3E4CACFDF99B9006801",
- "section_salt": "44829BD9245724BB422CDF85FE06575A"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "3E8E5771EC037DFE9655CF21",
- "extended_signed_metadata_key_hmac_key": "FB1E172D8BDC30C0686494050F0545AA14AC4CEB4B80178D1A60BA91F52E4220",
- "extended_signed_section_aes_key": "CCCCAB2218464982259AC1F9E1C883C9",
- "extended_unsigned_metadata_key_hmac_key": "A165FBA7AE751FB806EB71B517C107108ADE8AD83CAF2270CCBB500A16D6E8B8",
- "extended_unsigned_section_aes_key": "939BC65E829C365A53FA76DEC5CCAF72",
- "extended_unsigned_section_mic_hmac_key": "F517D42A409DECE9A73326D2D83073F5354D5FA6E18E361C8F5C322DF0DE2074",
- "key_seed": "AFBF0717AAE34C12160C6699E875BC497324201A00F28BB689E72FF81EA02083",
- "legacy_ldt_key": "64701C13AAFD18BD719961E5168794D660F2B303265D8164B3F42DA11DC1689AF643525BD5674FD39E4EDA98217D04C0F72188D4290C1820C3E7DD999E5C26A2",
- "legacy_metadata_key_hmac_key": "3228A4757D856906247B16A2E70ACBA3E2B3A556B48C3F34188605EF76C36EEC",
- "legacy_metadata_nonce": "5E989D42F47971FBB6D02CA2"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "B7BF",
- "expanded_salt": "B08300567B79FF302A5C7E88AA9FD54B"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "D98863233D54488599DDB89774AEE330",
- "legacy_metadata_key": "0077F1879D872A287071D462AF20"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "CAB00A6159E6DE851D7E64435197DBFA",
- "derived_salt_first_section_no_de": "9D33AA17D4672886D95B8040F714E99A",
- "derived_salt_first_section_third_de": "F000BFD919B6C082652650B4A5C5E1A1",
- "section_salt": "11D3A895308F443C74723FE45C9AD464"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "9594966607D85F389214AE63",
- "extended_signed_metadata_key_hmac_key": "FA1A0A53C819972F4E4F9DC3557D7E48EF74FD16FD1B4E6E343EC2DB2CAC2812",
- "extended_signed_section_aes_key": "03570780D11AF5A85038B03FF4DD0700",
- "extended_unsigned_metadata_key_hmac_key": "7379F3362DF6C3204A4B334B8AE60369493FF4E5296C5A7AF2485881940F6170",
- "extended_unsigned_section_aes_key": "2DF64D6C5F0843468AA52DFAA6A587CD",
- "extended_unsigned_section_mic_hmac_key": "6259F5119F8B9D77E2DEB23DC41A54DDE67742AD520F225E83E67E98C44DE6A0",
- "key_seed": "5EA0EF5C2E1E60B1741DAD421FC11EE78391D9598D143B5DAC4FB07091847EA3",
- "legacy_ldt_key": "A2D8CD41763E0C7F5A24C05FEA4BBF9C05B50338FAD3B877F69A81768FA01BB0CC9704C1A8DCA929025CCC8F6E80507FD74D140BC8D56EFE9E201F2C34077DDB",
- "legacy_metadata_key_hmac_key": "B5CCC3B2437D3D659C4CDFDF7B0EF920A5ECABFBF75DC6C36CE47E946F35CB9E",
- "legacy_metadata_nonce": "745E3B9CDE832DE4EE67847F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "81EB",
- "expanded_salt": "400E2A436293377A368189866BF5A615"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "C0B5A3D9B7E8EB4D8A68F6AA158D0C90",
- "legacy_metadata_key": "8E9165673AEFCC49B33E4535E0AF"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "0FCF0C13F89FFAFF9CF2EBB9C74238B2",
- "derived_salt_first_section_no_de": "D1375663E1B57A43DD17E6FFAFC17279",
- "derived_salt_first_section_third_de": "2EFF6AC282F726CA937B8B9AEED2B9FA",
- "section_salt": "76B2FF4BF7A1754AA61E2FDD6C88FC30"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "5706AFC8EE2B6341CC4D3B05",
- "extended_signed_metadata_key_hmac_key": "D790D59CCEEEA5A0C804429344D35C3AC9A515A9CFF7E10043125388CF5D326C",
- "extended_signed_section_aes_key": "E23DF3CEBC1F83A569DDC05DE27DCA19",
- "extended_unsigned_metadata_key_hmac_key": "A396B34DBF66E482B53D2B79DABD00F098E1E5240D45C3805F2386A1237B06ED",
- "extended_unsigned_section_aes_key": "03D99FA28322A9506C3CB7B9F51F4542",
- "extended_unsigned_section_mic_hmac_key": "E495765950E61B023CB6E2686ED4DC4189CA56F915CB3AF877B15ADE845EF31A",
- "key_seed": "206C196A03EB7DE2525B6C27E478552CD3B1904D4D89D3785D51C02B8F1D9B36",
- "legacy_ldt_key": "71534CC9368B8B599431DDAE5F62200DDFBDF8009248436F92636CF214F43E85CE80EC8703B78FC26503F6DD3634526B7301D8DDF45339A3B63C64838A09734A",
- "legacy_metadata_key_hmac_key": "3158EF75327E4F117A5ABAB3EF29954CF76B7249C74DC50CB8D1EE4027F70CD2",
- "legacy_metadata_nonce": "704A450B927CC83483CB5210"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "4E36",
- "expanded_salt": "D96E799C1F673C3AB5621DE38FB7D9FE"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "DC4C0824F5965E110BE7C9036B6043D2",
- "legacy_metadata_key": "D2DE6C51A1B2F0CC740A0433BA0C"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D735F933C91F70E6703FA277DD9D6B07",
- "derived_salt_first_section_no_de": "A1216FDE48D4E7CF716EBA6304B0E002",
- "derived_salt_first_section_third_de": "6C6F84F7B0ADB3DC95733154462DC464",
- "section_salt": "EE077330D38FA4E741EEB2A423C44E16"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E8591F5F7A4A9BEEFD11704A",
- "extended_signed_metadata_key_hmac_key": "0D06ED71FA2DAF112A89EBA86E42961C0CCF5F114C9D5414221ACAB16493615A",
- "extended_signed_section_aes_key": "5DCDDA469454FEB3C2EA71021F93C392",
- "extended_unsigned_metadata_key_hmac_key": "770A74886ECB2E13C09DA386048A1FFDD32F184821CFABF97C591F2F1AF593D9",
- "extended_unsigned_section_aes_key": "74093EBAD21C75C9FB6496AB55D71D10",
- "extended_unsigned_section_mic_hmac_key": "528D1D684E3DBB6A55B3C74B76F12E3BF88F622796E111436F8436F9C68BD7AB",
- "key_seed": "CB62878D769D49414CD07AB82DD01A567BD320BCDFE120E137EA6D24FD754A31",
- "legacy_ldt_key": "526A62E198AF94F8E1C97AD51BCAD021ADE8BE68CBD16DA8FEDA9186141099AB4D1FB09B3C45E06217A50F20143C6669E024A5FF127311B46024E981A8F79C80",
- "legacy_metadata_key_hmac_key": "C3FEF82D19D4198A12825C7B81D92F92A27E04C0D512FC07D2C144C48DF39A9A",
- "legacy_metadata_nonce": "6A2FC44C5DCC8ECE690470BB"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "4B93",
- "expanded_salt": "0618681E330AA95ABCF5908C7D80266E"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "176853A104A7E84FB244044ADB23E60B",
- "legacy_metadata_key": "AD1ADA1E3F33D44DBAD9D68546F8"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "1A605E7282BBB65E768BA802674316E4",
- "derived_salt_first_section_no_de": "46EDD6B928BC45D5349843C3DA660A46",
- "derived_salt_first_section_third_de": "23866A17B31C30E4B6BFCE65FF9EF2DD",
- "section_salt": "CF0811E9E51806ED2EC869D2DCF7C3DD"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "D1031370C1491071F4D7C54A",
- "extended_signed_metadata_key_hmac_key": "E27E04EEE22E36C87CA16C6AD7D5ADD10776EF643CE1D9CE30EB22D00A30FD59",
- "extended_signed_section_aes_key": "15D907F25E7808AB08BECD25DC12BB17",
- "extended_unsigned_metadata_key_hmac_key": "F3F714D219EEE49D4F2BBDEA6245570148A513989BDB07C72D940C8F6174A6C5",
- "extended_unsigned_section_aes_key": "3449B21771EA3B2B1B246A73B031C67C",
- "extended_unsigned_section_mic_hmac_key": "7AA8030A85FF64635D6B913A1E96D58EE649BD9E29A27F24A2EE429AADF5B6C5",
- "key_seed": "FF255729FEA933CDB4EFEC5E38D382C2B8166FC1F61099FAB8E0DD472A1EA192",
- "legacy_ldt_key": "95B5891E32CDD742FEFDF510C32937F19926BA8A2FF7568AA3A2049E4AC468620FB72DD2E0720EEDC69ABE700AAAD9077345CBC40B410C01F03D7B0B34EBF852",
- "legacy_metadata_key_hmac_key": "B76F11E187F71D17D2A8038BBDA38DA7F6090E2CEDCF324D4DEBA899F9D39985",
- "legacy_metadata_nonce": "72FE7AB45734E2C87AE34B96"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "3CF9",
- "expanded_salt": "469C89FF0AFE6B7AEA5A94E8E5D413EF"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "34C8733D5598224EBE7E0F468AC42AE0",
- "legacy_metadata_key": "B4EBC9A698A9F67B3360AB444B65"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "6C0B7CAAB6B77D7E69927BEC4CF9857D",
- "derived_salt_first_section_no_de": "E85B82E53864343FE2E11C3BBA921BE8",
- "derived_salt_first_section_third_de": "B5C9E52B81072C158A44DA3D0F1B863C",
- "section_salt": "55F816AB16A494DA8DB45539F30C615E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "9F3A841BC948F67E6F6C1394",
- "extended_signed_metadata_key_hmac_key": "1741C9FEFE5F3C189A06E18FF55693BAD6F850740AE5EE91CF0CE7E1A6A48D65",
- "extended_signed_section_aes_key": "6624413BF4F1665423E6AFC7E48F6DBA",
- "extended_unsigned_metadata_key_hmac_key": "79009162ED60569C88E211D09543E5612C1D5A590B8277C44F5F86A3C1ED26FD",
- "extended_unsigned_section_aes_key": "4AF8134B5774E0DA661D4D74424BDC8D",
- "extended_unsigned_section_mic_hmac_key": "FC55078A316070CD61B23304D7E0A076490E3425F2257503D1FA3B13F806B8DD",
- "key_seed": "17D52F8EE6C17DAA338290F9E0D08F91C9BE1AB1DEA910D487309BBB09F67F0F",
- "legacy_ldt_key": "F01C06D770236831C55B3A10BC648812125B0A8F65367DE7AD83E48F6EB6C2151F09F83B933B2339BD08E36DB74780BE1F435F035DE643D28CE067AF88D4E30A",
- "legacy_metadata_key_hmac_key": "4BC9A35B25DA286883594B8258037CCBA46F26A76CF3D16DA66B79A5AA645FBF",
- "legacy_metadata_nonce": "BAC048C167A5890EA8D5D060"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "651A",
- "expanded_salt": "D9C1AB2EA41BDCC8839A83CF4EFFBEA8"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "ECB322FC63A5B136F19A39403AB4A3FF",
- "legacy_metadata_key": "0224F2C3F01DF3961A9DDB33D33F"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "9BCC1DE1FB74CC1CD16D0B4200B04D30",
- "derived_salt_first_section_no_de": "9ECDB554F3EF801381DB9373B9886BFB",
- "derived_salt_first_section_third_de": "B898A171766659C0B6CFD5A54D7D3ED6",
- "section_salt": "12120586C731008F58E2EBE90F2D9FD7"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "43EC170E0B76202475557760",
- "extended_signed_metadata_key_hmac_key": "99B0F78F43A68D4F6367ED11338BD73DA00CAD40BCC917DC0E10CD1D3B8225FC",
- "extended_signed_section_aes_key": "FDB4A65AC4DB43107994369895BB7340",
- "extended_unsigned_metadata_key_hmac_key": "A4E32E714DBCC3AF4BB2054620ED0E26B05A00235AA46DE36E87DD1C33ED4B02",
- "extended_unsigned_section_aes_key": "3A50203C921E126E8D1B0A31660E025D",
- "extended_unsigned_section_mic_hmac_key": "F722C6EA33D7F8257B668A6A48AD451E90292DA2B5C5A2565383AABB3B75B158",
- "key_seed": "DB33ED53F748F16D4C44A0D7256951E46737473A2ABEA4FF1A66166072D198A4",
- "legacy_ldt_key": "4679142868B7A72EAE5D275C6077F84BF4A2AEF5A6B638925752B30C9A43F356CEBD1000C540CD5103F5FCF620E11FEE9900D951667026D68770E1CC9F37F9B7",
- "legacy_metadata_key_hmac_key": "B81CE82EC7918F849BD209F9CBE4F6232FCC22FE773D96A7823468BD9FE6F6BF",
- "legacy_metadata_nonce": "4DEC4087D83773E0A57AD6DC"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "C854",
- "expanded_salt": "7F509331897315561AE87E8E465731D5"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "445F1AC997B6F6258C04D6612730F576",
- "legacy_metadata_key": "5A0395FCA63385D863B94C161830"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C5D4701E3941FA12EBDFE7EAF8D1103D",
- "derived_salt_first_section_no_de": "CA9740A690C83B28BB8EB6C99A28471B",
- "derived_salt_first_section_third_de": "0C2ACC54B8EB3433574E87CC03090508",
- "section_salt": "1420CFC23918397B5B0743A7BD1D33DE"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "2AE39BFE66BFF7F3685B7FFC",
- "extended_signed_metadata_key_hmac_key": "1E5B00AADD20BEF97BB6CA33F97C20661F041FF73DB72D33787C374028FBDAB5",
- "extended_signed_section_aes_key": "59A55BB848376BB2A1F2212E954743C4",
- "extended_unsigned_metadata_key_hmac_key": "A33A337FC8BF0C5C435B46121BE28F5D119617D044C990ECDC61A36F8EF60808",
- "extended_unsigned_section_aes_key": "4B6F0EA5C9C9A1DBC1203B0B5AA1D81C",
- "extended_unsigned_section_mic_hmac_key": "D5B603436CA006324D83AE5020DAC7BD98F9E05EF3E94BA41F63558E2282FED2",
- "key_seed": "0982F189CB2F763A17D3D68430CA8DE5C22D6B44C21881CF76473C21F4CF573F",
- "legacy_ldt_key": "C61EEED8BF13DC405DFB8C57232F66381B7FF78CDFD4DA1FFB6737565E5419E98EB38C237064656DB9BC31611F4C47864D54DEB96CEE29F4BE9BFA8CA257D036",
- "legacy_metadata_key_hmac_key": "DB9E4BF67F914548B813C071B42B37A486B1564DEB98D90CF8B4A020DB9A2702",
- "legacy_metadata_nonce": "3BBD17F0F4C43E279C69A7E0"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "065F",
- "expanded_salt": "1360903389867A3F865080EE99218A93"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "13D9CD7AB4481EC78AAE713AC7F7A534",
- "legacy_metadata_key": "13A49EE19095CFD061978BE2DA07"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "5809826FE4C41311D0DF8490071E4BA5",
- "derived_salt_first_section_no_de": "B10FE9FE08BB71AAEF17701E3805E337",
- "derived_salt_first_section_third_de": "5C8C4CFD85E659D2CCC0A735E4C14C44",
- "section_salt": "C1290354344488D39DD88998567BFA1E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "A0A936CA136E8ECA670708EB",
- "extended_signed_metadata_key_hmac_key": "27200867B9446FAEC18E4B472C0C2A43D8180753607B42B678184CC5CA3B1AB1",
- "extended_signed_section_aes_key": "2214D4050FEBA4E4C18543FD920D15C4",
- "extended_unsigned_metadata_key_hmac_key": "51EE6B49F353568E055B06CFB717A8A467DEE6D90A6D5B325052DFFA15564C6E",
- "extended_unsigned_section_aes_key": "6F162714F3BDA65324EBBC4B328CD0CE",
- "extended_unsigned_section_mic_hmac_key": "DA51358ED2AA0916325399E9A2B0244D1791A1C5D600AFD8A351BBCADBE616EA",
- "key_seed": "8EDCDDAE0F2742D381A7E56284E6804AC68080F872F6A587DE4DADC5B589A4A5",
- "legacy_ldt_key": "6AC852D94DAFB8C18917A6406D3E8364125F01B03D1EC583FD20E5F9B71DD579B807D3874C4B3AB0FD9582F505E558C98F3E96F609636AAEAB90E9DE51703CA8",
- "legacy_metadata_key_hmac_key": "89D14E7C13E4B33BDA2B0A70AFC4376FC82BC5E8B6D028F1C91D0E9159F9D549",
- "legacy_metadata_nonce": "CDD93F6D02D83D0685DF0729"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5E81",
- "expanded_salt": "A1D53BE4EC3D0418587BD370BEFC413A"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "39B757F61E136408F7D8CD58DBAE1A89",
- "legacy_metadata_key": "F58C1AE45F74112200878EB16AD2"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "4B9D669E994848CF832475821E5BA9A0",
- "derived_salt_first_section_no_de": "B0DD4242F201361D92B775C5F192C979",
- "derived_salt_first_section_third_de": "E5A6AE615AE988C06CEAB18846B5F659",
- "section_salt": "33CC65E1EC1CE33B169733DC3096B450"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "DDBF503438D36104DA4B319D",
- "extended_signed_metadata_key_hmac_key": "DB2C6A4EEBCA496FE06C311A8A26AB0C208E2785ACC33A02AEB4ABC1FFC8E5BB",
- "extended_signed_section_aes_key": "8E5E7C2C79A489BA786B7FBA6B85383B",
- "extended_unsigned_metadata_key_hmac_key": "803D250E88446724C7192F9BBBB5F1E4EBA342D5391DC8CB8FF53349D4E8DB67",
- "extended_unsigned_section_aes_key": "58C6E7AFDBC57C0482C6E611EF1A346E",
- "extended_unsigned_section_mic_hmac_key": "D704D0EC34F6D775C575D3C09AE34A5CC1926C88E59A4DDE6A8B5E0FAC2AD3F0",
- "key_seed": "EFBE104969A3580E48A63285BFA56DB95CAF3C81137B5DEDA8BBC0ACC12C658E",
- "legacy_ldt_key": "382BC725B508E73E5616B110C92CD8F55CEAF87EB9E0E5BC372150AD9BEE1F1647F3944E3171519B94249A3A789D472C9961FD675653927D1DFE345FF3266358",
- "legacy_metadata_key_hmac_key": "8D6251503286E357F6EC394CC68446A36BD0C62D50F20FAC6C258B3DF1FACC4D",
- "legacy_metadata_nonce": "A19B0D2A97B7F3B3CC296F97"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5FC9",
- "expanded_salt": "C69D7BCD94B23FBD8E2AC68B96330BF5"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "6AFDFA46631667385F2C5D764E5301C7",
- "legacy_metadata_key": "062743EDE5C56F5130998BADF2D0"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "58552F903E39FAD1B6FF06B7E55835B0",
- "derived_salt_first_section_no_de": "586199F442C8473B9690A6AEAC36A405",
- "derived_salt_first_section_third_de": "B69365658EE47B79809645ACBD160173",
- "section_salt": "D08A6947309047818E4529E4CC80F9E2"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "1C2BD072C9330CB6D3807B9F",
- "extended_signed_metadata_key_hmac_key": "7EB76208F558DB04B0ED9C741F7F4146AD323ED5A9676708F3C2718FCF61DD5D",
- "extended_signed_section_aes_key": "9E043B7A0F1D242100D98F88D77180D1",
- "extended_unsigned_metadata_key_hmac_key": "4D6397EEC391828BA27EA7E0F01DCB8350A081577CC0DF9FA3C244CACA923EC5",
- "extended_unsigned_section_aes_key": "13D8B05613887623BFC72CB4BD57D0DD",
- "extended_unsigned_section_mic_hmac_key": "249A8EFEEF21C7597AB5EAAABA00536ADD7F2D57CDB1C7F81914946748922B30",
- "key_seed": "C952629EA0AAF16EDF450AB792C0FDF454B3748F14F8228CA39B3AC3D733BCC8",
- "legacy_ldt_key": "7D90190372B6EB72DE892F159FD90C723D0B30CD1F97D7A6C15536C8766335AF62DD0BFD8FCB33CF808EA9A8565EA8AEE60D03B9A21849C7473B5E653DD58E94",
- "legacy_metadata_key_hmac_key": "C02E17C17A1E010FB5F8B34E104B6F4B83C3697CE3878896D9C1D8E12128F28A",
- "legacy_metadata_nonce": "D2834CF3DD852C5D65EF47AF"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "79A5",
- "expanded_salt": "18FB4E698A2B0F8FEEAE8D6571217051"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "359493D5139411922367E5C050162264",
- "legacy_metadata_key": "579718BBEB70558182C85652E2FB"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "81083ED8ADE4D6E6EBFEC991A837AC97",
- "derived_salt_first_section_no_de": "8BDCE6C08C41DDB5EF3990EE1962965F",
- "derived_salt_first_section_third_de": "6451CAC1C77CDD02F6339AC8F5011935",
- "section_salt": "19E1A6466DF15274E28FD2AA96C01BB0"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "C47EAAC92D0E2BC76D5B7168",
- "extended_signed_metadata_key_hmac_key": "8666FC7A47A63BAB78216CE4225E819D8680DB8C6F79F3FFBFB8B573C0A35C95",
- "extended_signed_section_aes_key": "E4CFAEF9DAA97426A0F6776ABBDD0615",
- "extended_unsigned_metadata_key_hmac_key": "18B3DA3C8736739FBD9D203493BC7697E47EC2072DE351475F332A989CCE2600",
- "extended_unsigned_section_aes_key": "3732E014F15539C1999F6486B7933A43",
- "extended_unsigned_section_mic_hmac_key": "F0ABA5CC299B1D3C210774DA1B065BCBB877A0991EED7C34E1DF5B318D1D5C25",
- "key_seed": "E49335220345649BE4C6AD75B3EDE2A49A9CD22D291764E90510826835CA3528",
- "legacy_ldt_key": "637CA1A46B169B80D0833678505E3FBEBDDCD42C7D297E78EC5DD6CE1F8007914742F09396A5439592568445117436BBF0B8A4075BE65843259B28A49C8C4A3F",
- "legacy_metadata_key_hmac_key": "1780831E70950E84CEDBB6D08591E5867DB33D64B9AEFC60C1D29D3F4BD0DB6A",
- "legacy_metadata_nonce": "4FE56B42C34913314149EAD3"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7369",
- "expanded_salt": "7B7D59EA9882AC8D8E5B95F11ED6773B"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "20D2CA28DAD44F40276871C7B8AD6D1A",
- "legacy_metadata_key": "AD5DBAB68501DADA871E6CE6EFF0"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C27C4FA03E43A46EADAC3A827A6ABDA1",
- "derived_salt_first_section_no_de": "28B6CEF526584124B03720FC4A65188B",
- "derived_salt_first_section_third_de": "76B42830B3813795F19CF07B6EFD17C8",
- "section_salt": "3DAC056F62D259B969B815D08DA79507"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "8BC4D291417DA2637FDCA948",
- "extended_signed_metadata_key_hmac_key": "69305759C5CF4AD06490F51BF9305543E835A219F53EA84F39ABF714F6B2F855",
- "extended_signed_section_aes_key": "69E4C6301882A5494C10231DD82FD9AB",
- "extended_unsigned_metadata_key_hmac_key": "F6F45381D06AD669756F4BC421495F60F02FAA2FFD3ACF9FAE6755CE54AEEA0C",
- "extended_unsigned_section_aes_key": "744A7950D65D03AEEF5AF17C36AC3954",
- "extended_unsigned_section_mic_hmac_key": "AF012F292628BFCB7421B4A846361AD4829FB93FD766A014A5D846B7F471F5A8",
- "key_seed": "B46750D2A75BDF9960E825289F24D8A1C777C4481FDE9E1E38F72A3DF7B29AEA",
- "legacy_ldt_key": "7C689AF4CE7D769DEC4BE41DE5651B9C87F76D988C90DF4A5263859159CF855DCEFEA5B0047F450AE9033FE5E3C4D96D0B81DA5D52C94487C481C11BC5204A71",
- "legacy_metadata_key_hmac_key": "4EFEB0DFFB5E37BF0BE1373A4917078FE2F54EAAC0E22CD049D3A84F79CD5BCA",
- "legacy_metadata_nonce": "0185B0580338EA6BD57D801E"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "4456",
- "expanded_salt": "4C0B15F195F4E9506FD3BF692C8A81A9"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "F7B19B1F77FDDDA49AD637F92F559434",
- "legacy_metadata_key": "71C96FDFE7539BAA0A52B6F4C1ED"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "DB0238E42DD58FFCEF52697A6B60EEAC",
- "derived_salt_first_section_no_de": "76B8797D8220B4F7D3F2994F57AF40F6",
- "derived_salt_first_section_third_de": "8FEFF73B163E9ECBF0B75743237146C2",
- "section_salt": "3FF3074E6E32C3A1282DA7E7486FD5D2"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "8E1A231A33610A9B3F78D046",
- "extended_signed_metadata_key_hmac_key": "724CBBC4F7B44408327A62B1EF12BBC451732406FE77B1F7E6F5EB125D47F69D",
- "extended_signed_section_aes_key": "EADDEDCCE98E6DC2145C48C5648052A8",
- "extended_unsigned_metadata_key_hmac_key": "9519CC0F24A2DB8D534B9233E863D1105711E79E84DFBE17E13DC3D6C1332D2A",
- "extended_unsigned_section_aes_key": "80C1210F4F306D881C7ED5568A78D643",
- "extended_unsigned_section_mic_hmac_key": "590362F05927596F04EEE3633FD526DA7C17FBA4A4489DC1B09F33FA2A84DACC",
- "key_seed": "D83D79192D3A1490BB2DF4F72686E8E351F5F354BBEDB83B389DBC94D0DECC6F",
- "legacy_ldt_key": "F6CC44D2FB8A497FDEF4D8505BF8954C1673F7AA74279938FF60D74F2D56E5E590B1EA7E71EEE7A14782FB6E5DDF856402DE2F388BC7A6BE7808C6B02D6AF3CF",
- "legacy_metadata_key_hmac_key": "8EC62082A556856D8D9622063340E8B7A649CBB82193EE3FF1980DB7918A74C8",
- "legacy_metadata_nonce": "0AE81376D41C4A66A58C9E15"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7538",
- "expanded_salt": "9C0EAC987D64D64324502964CE4260AD"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "809FF61B6778348B260BFB91DB789913",
- "legacy_metadata_key": "BBCFBE39DF3BDF239B25E14976A5"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "86485E5604FA2EF6F8EAF42DF4CE0CF1",
- "derived_salt_first_section_no_de": "5506D594D6DEBDF6AA3FF103EF018765",
- "derived_salt_first_section_third_de": "DE2468D8B660E2757D9D80315450D573",
- "section_salt": "C7321D6A2F9877CB0FF99B9B11D34309"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "D7D49880F809AFFDCF2AB7BF",
- "extended_signed_metadata_key_hmac_key": "89280461B4D2102D3F829CBBDA32CD75F01579E2B25E8C2F01F3983804A7B5D1",
- "extended_signed_section_aes_key": "9B42E858D2ED7439F951403533CAF3F0",
- "extended_unsigned_metadata_key_hmac_key": "509A8BF8096E9A547D14F27284C20D7EAFDA6C9D8D0946EF81D4611DE00F22DC",
- "extended_unsigned_section_aes_key": "88F058A2EAD74A4BAED5F99136508DAD",
- "extended_unsigned_section_mic_hmac_key": "3729770DD90FEFA7253F53F87244C928CDE14CF5D2D5513D8EB3C1889C34AAA0",
- "key_seed": "96B3E4E23374C3162E94B1701F6720E0D0918AAAF10FA0E7FCBC4D7059C824D7",
- "legacy_ldt_key": "4B0AB9E1C8CDE2F1B55EE0EA4A331B8B923E34AF5DADC5F18971111F45D41BDDC7E9A9F7D28F94AC71F50DFE5AAD7FA7B85884169FE0099175073100CE1DA9C7",
- "legacy_metadata_key_hmac_key": "5FE8C268D4DFCFCC91F4B7820BA679D26A54C8FF0F3063EB856BE84FF4AED8F9",
- "legacy_metadata_nonce": "D885F819DB614904DEF77E09"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "3881",
- "expanded_salt": "839E06D9CAFECE9EB910ECA73E7B7041"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "C4ABC2194181D14624AFE1B545E87B95",
- "legacy_metadata_key": "2F8C7737B5E98216C6358DFD1163"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "A662F512F68A331133401EA5EB2A2A66",
- "derived_salt_first_section_no_de": "BFE2EA19A0984DEE6BE7EB90DC2FC58E",
- "derived_salt_first_section_third_de": "92E3744D86B5ED21D50C726A66ED36B5",
- "section_salt": "55DA08E873B5664E175650BAAA9A8021"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "8E7098BA5E6A64E0F97746AD",
- "extended_signed_metadata_key_hmac_key": "D8C3614062B4B68DFDEC328EE588C257CB5D8378F33F514181FFBAABF9C18A2C",
- "extended_signed_section_aes_key": "9215527DA83060DC2F32E39048ECD4FB",
- "extended_unsigned_metadata_key_hmac_key": "345516B0AFF7928137B9AF940CB13EBC734F9015540C713C0C813AD136BCAA09",
- "extended_unsigned_section_aes_key": "C563004B3236B38E9C02BC6817B9B199",
- "extended_unsigned_section_mic_hmac_key": "2F4A9499095C511768D57BEC00A3EC265E9384BC9A12B0F9956791D8617BBE3C",
- "key_seed": "4678C5DAC152DF06265640453E53177D237E72FD58E1B784C692D95363B3DB30",
- "legacy_ldt_key": "08D4D021EC845DCE579783FAA377F1B8E20A75CD4768D18DF0326F314A181C17CBB821F0033C970B8A7448E208FA06025A855D25DC38775E44917DC51CF267CE",
- "legacy_metadata_key_hmac_key": "0D31EE249C7FFA7A827E90EA8C20D70CF22F5DD8DE8BA331A5B05B3831435C36",
- "legacy_metadata_nonce": "DA5011061FF4017D38381053"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7C72",
- "expanded_salt": "7F599F5A3FA8CA8046C80BD2F8D43377"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "77B1D1B130E78CD88DB0FB2D439722A5",
- "legacy_metadata_key": "0FA76D2A99B2E693B6D358C41D42"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "532346C01C3D5C6488233523F1239853",
- "derived_salt_first_section_no_de": "00FA8A3468172AA618AA22518A04AB90",
- "derived_salt_first_section_third_de": "1B2BBA5F893D87824BD4D36EB568ADE3",
- "section_salt": "F3BADB4D93D44B2C83651C4D977BDA85"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "AC7F3D2E8F0CA67D9E3286FB",
- "extended_signed_metadata_key_hmac_key": "09F574FCD463AC6C36B8E3444B5C205D4E7F34FEE2C50F4C9D8F4E21F3F08E8D",
- "extended_signed_section_aes_key": "03929B8C9D55DE8A2DB331F3A458C5A0",
- "extended_unsigned_metadata_key_hmac_key": "41CB06A6ACA499582A97E506954CF3346E10922C6816893088E920400C15724A",
- "extended_unsigned_section_aes_key": "8586ADD0A300F594781EC6A91F7525DC",
- "extended_unsigned_section_mic_hmac_key": "0A104999429CBD6CC254840DEC399C70F9A64F4BD4B9EA572861F44280311D1C",
- "key_seed": "5EA22F37C2895A5ECBEF49AA18F9BEF14E2221E8AD6B73C48B500059C0920563",
- "legacy_ldt_key": "2CF083240697097DB14CCE7EC06542F2D8CA93DBF4404BF733A67BE123A7D577A4ACEAA6EAFF9BE5B73FAB9E48AAA93D63779D8FAA7044C24D1DF6E6415540D4",
- "legacy_metadata_key_hmac_key": "5DF6ED321FFE805FD33A7A17CE8CB8348532798C604F3878892D3A6B1D12E4D0",
- "legacy_metadata_nonce": "E9872F6F6C5595E82DE87409"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2D24",
- "expanded_salt": "09935DB3B8781070715F440E27D5CD90"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "7B9525E023AE6563A1938D713276A250",
- "legacy_metadata_key": "E95212B84FBB8BD181401FB77BCE"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "F4A7A1A0A42EE2C34BB44EE7CB7FDF50",
- "derived_salt_first_section_no_de": "F13440BC0A2B7911039742C57654D2B6",
- "derived_salt_first_section_third_de": "AE1A8F016C73B5BA485C27D9F21C4379",
- "section_salt": "B7C7FD8E1C40228B71165C00DF490496"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "62E90AEC398397F92486725B",
- "extended_signed_metadata_key_hmac_key": "512490244C6AFB22B8E1FF0AE15B1BD9BF61B02C20FDF18AFCC28704FAA04B11",
- "extended_signed_section_aes_key": "C650084EAA3E35460C65A6D5A3BC056F",
- "extended_unsigned_metadata_key_hmac_key": "969259ED1CC21D9DC198921204BD98F1B60D51E52758EF03EA42A088FC33AA99",
- "extended_unsigned_section_aes_key": "A12E741FBEE73C341789F4A2E217E568",
- "extended_unsigned_section_mic_hmac_key": "C11625C0E356394FA499EA6E7606CD7ED016364FC8913C2590CD04E6B7101C33",
- "key_seed": "9FE70D5318CEACFFBC1C0BF66168E2404D67AC342B36AFAC5306F65AB75D4BD1",
- "legacy_ldt_key": "07DB2360A6FF579827C73C33947D3432F0D2D44282C3055447C79C732A3DA4CFCA3423D87D080259F2056D9EEF0AD03D874AA6D3767019608486CCCE1CB34CAD",
- "legacy_metadata_key_hmac_key": "B8EF43182F6E8159601E63E474DA30B6A0A18FAC8D37BA25207395990F75CA70",
- "legacy_metadata_nonce": "B8E730D17A2B71DFD2113E80"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7141",
- "expanded_salt": "9E8C5C44E412C2E5D54FB423AB48102F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "1FC5EA826AA0C33800219591A2856184",
- "legacy_metadata_key": "DBEE14EB39323EE9CC4B341C3A00"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "BA4492E8755975045094D06AC8930F50",
- "derived_salt_first_section_no_de": "20B8815C2C7788BE334D8D945AFD59DC",
- "derived_salt_first_section_third_de": "2E567F8F25DF8D06C7DF61A05811F7F1",
- "section_salt": "627BA43CFCB6B9FD6C4676C1102635CF"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "D1FE7EF66BC90F8B53E64538",
- "extended_signed_metadata_key_hmac_key": "1484C6E96375DD5B4314600D12BCADC5063E1C865D64C8390CFF60E52E6FC0A1",
- "extended_signed_section_aes_key": "CF4880570B17863BCC0B17D263BD563F",
- "extended_unsigned_metadata_key_hmac_key": "E3CF564D084FEC04FC96B6CD5A23B288D49F360B326005698B6B1CBD8B8860A9",
- "extended_unsigned_section_aes_key": "6193B4A238BE3240C7E4D53E7708EE8B",
- "extended_unsigned_section_mic_hmac_key": "45CC2AFD5BB72392874172AC5C059E871BD6E9C46D977E6D0F7510B817B180B4",
- "key_seed": "B237A0FC008DF51F15EA3E1789FC834923556B61A7BD30664EA06BE6C40169D2",
- "legacy_ldt_key": "FEE50CF8496A24EB1A216C0FDBED6CB9559099E8650BEC22C2DEF7ED4E490A9CFF5E21C40572A40AA9F5FC3E9C60F60CA60C257D08155849CADCEE76FC869202",
- "legacy_metadata_key_hmac_key": "8E854A8DB7B847B84862757EDC73881609F0CF90A99DBD82571C204B040B5D54",
- "legacy_metadata_nonce": "F58512DCB899E1F857C3394D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "770E",
- "expanded_salt": "7A1A3782A82F1E40CCBD5330A84750E7"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "C8C682033DA60D93756D23338D6427BC",
- "legacy_metadata_key": "E12C6EE466A1ED61753B30E6BD6C"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "B20A3B57F64EFC41D079734A14A3D576",
- "derived_salt_first_section_no_de": "09B542C88D08F276B29C0E1A2A424246",
- "derived_salt_first_section_third_de": "962AC562D09F20F714EB885E729D4C3E",
- "section_salt": "53F5CD677966C5D1E3EC25D1089BDFF2"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "BE6106BCD5D7388E53C26ECA",
- "extended_signed_metadata_key_hmac_key": "0D98105D990B688F91C10BC27885E635B1DBDBF2DAE215EE49E04C06E33DAFEE",
- "extended_signed_section_aes_key": "7A3A2341DB494F1D5AB346E54EA49729",
- "extended_unsigned_metadata_key_hmac_key": "C6C0836CC438960704071E2EC71EC18219A7CA336E314C9DF1FD5F5848803C07",
- "extended_unsigned_section_aes_key": "C00032E500DD04C16176DE5EF45466F9",
- "extended_unsigned_section_mic_hmac_key": "2B813176336A7A645826F95F3763A536ED2EDC15EF25C87FAE32C3766114323F",
- "key_seed": "BFF3192023AF42A5D4B3D12DC34350E7F41E214B25501A7FE0ADD19497A48276",
- "legacy_ldt_key": "37E2DFCFDEFECB1FC486B6B26670AA37D3BE7E106E0C2CB5AFD9CCB1130EE7899A3D38CAF15142CD3A06DFC2A39D34503F7826EE517F9232DCC7CB1931855028",
- "legacy_metadata_key_hmac_key": "5771D06F65AFD121908E4750EF2EBA0E9C385839E6987F30161FBCF88F49A974",
- "legacy_metadata_nonce": "20448FEFB69E2643D7932CAA"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "524B",
- "expanded_salt": "F0B23D5EB99A02DF9E8A7D6F8B8A1A3D"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "C6B9DB92F2818C6B57A3E386BD44B236",
- "legacy_metadata_key": "A4C003398DEF995E0CF5457DF3A0"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "EB8E676E9E53A4828200A25942EBA2CF",
- "derived_salt_first_section_no_de": "A342A8CFFBD87DA2F95D1C72CB0EEA36",
- "derived_salt_first_section_third_de": "6F049F5664239C49D76286B8218D64B1",
- "section_salt": "8096BBCFC6AE0C6CA7A17D5623929518"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "586425C6E1CAAE439F588912",
- "extended_signed_metadata_key_hmac_key": "FD0CA08040BB854BDF7414DA7ECF4733A094644B4FE3473C04F787DBEF6E53E1",
- "extended_signed_section_aes_key": "E4FA3E811B0C7263CCE2CD60500587A4",
- "extended_unsigned_metadata_key_hmac_key": "6E6DA7DC5B6F17C7B6C8B37E9B8E82D09DA5C4300DB8C601CDBB258161A8701C",
- "extended_unsigned_section_aes_key": "3E0E93D5EA50FC6420B0331F2D30EE07",
- "extended_unsigned_section_mic_hmac_key": "78F44EA95AED2D816672A0EB7BC16B8DA13DC285CC903E63BB844BF6499949D4",
- "key_seed": "66E4BFB8633C10BDD7B8C2E5653E014BC1E652D809487B1810DBF79515ED66F9",
- "legacy_ldt_key": "D53EDC7BDDEF9CD6FFA5C7DCE7FCFC6A4653412B7F690454201BB6536FCD2EB04A090D3C252375FD703D87869AF7F6CC60EB7F381896396662C472C5B1626A81",
- "legacy_metadata_key_hmac_key": "466B32DC5CCF02949C092E5AA5AB321CA35E339CA8F6483FB1F9F6F0C7E6A438",
- "legacy_metadata_nonce": "BFF9144266F9BC3527CB8C46"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "CCB6",
- "expanded_salt": "0F9B6162C8CDBC3092573D85B26DBC37"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "AEB39B7A005D27F8DA9FAB9AD80D220E",
- "legacy_metadata_key": "A52FF0A8837236A5D3DDA03BA23E"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "FC6812BA03F06BEFD59BF0F949D8F449",
- "derived_salt_first_section_no_de": "2DCB709ACE9617A6119BD2CC960EED9E",
- "derived_salt_first_section_third_de": "FE06376C4AE96023D51C6C8475072558",
- "section_salt": "2F808BAF3FE99E6E84B565038CA90BC9"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "D8C89D6886078AF21EE678DB",
- "extended_signed_metadata_key_hmac_key": "FCE0422748BD4D4082B66F25B06DD3056E9D37C135CF212CE1C8631FEA94F864",
- "extended_signed_section_aes_key": "9EB35E1816D04630AECA453BC64A8FE8",
- "extended_unsigned_metadata_key_hmac_key": "D161E19CB3638E925E028602B7928D6889C776062DF66A33C97F2C45890C0581",
- "extended_unsigned_section_aes_key": "A7AB3B735821FB8F59F63A8E8DE3F3F8",
- "extended_unsigned_section_mic_hmac_key": "CEAD2B2095603CC58A1C5DDE0A5ECBC2FC960840DE6A463E9893C97409B0437A",
- "key_seed": "3538A99DC75533C5A301539C166BD8A6476AF6F5F52A73382441681781283A4B",
- "legacy_ldt_key": "32360EC7E4FE0B3C5FE27E236639D62C5C81BEE8397B320688087B4D4009B10E6C15B6057CCE1BC1B8F8732606E730BA172746D8CBD34DEECF911CBFB9712B15",
- "legacy_metadata_key_hmac_key": "90A819E29083F6DF7FD2C7E9EC4A872CF4887CA8D964984E49C4CCC292EB8938",
- "legacy_metadata_nonce": "0982939640FCC0CEE8551409"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7975",
- "expanded_salt": "AE096CF053C4F4A17ADB41DF4AF79D01"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "EA6B4A31500F98886521EBCEC6ECAAC5",
- "legacy_metadata_key": "70A44BF295A6510C039A031BCB04"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "0818451F633193982BFEBBD61988FF62",
- "derived_salt_first_section_no_de": "48ED1DF2C5BBF94DB0DADE30C0BE21C6",
- "derived_salt_first_section_third_de": "633611AFE0697A6F36BC5B76E685391E",
- "section_salt": "AAFCF56E0A0F6A8F76E2BC44E54F2B78"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "30696C2FFD88091165B93256",
- "extended_signed_metadata_key_hmac_key": "346B7958CA1259BB7197FDCA84B718A41AF9049D2DE6B472B64B19102D4240CF",
- "extended_signed_section_aes_key": "854ADA9753D9A82E94E5D6ADBB22873E",
- "extended_unsigned_metadata_key_hmac_key": "29D905607B3ABF4E2CD261EE4E67C19EF36F41311A61CAADB60C95FC468FB72D",
- "extended_unsigned_section_aes_key": "DD5329454006EC3BD37FE3520810CD98",
- "extended_unsigned_section_mic_hmac_key": "E4077D45CDDD895F5577A11D2FE9CB3BE65242D5DFEDAC87471C76038605741C",
- "key_seed": "3719ACB4884750708757D20A58648804B8B7A614C176AEF7DFA6E0A5BB9CD5A0",
- "legacy_ldt_key": "88CAEB0E79177042908D16AF2ED4025D95448A76E901A4B6195F405E5210A6889324B3DB121508D411A012499EDAEFF35A280BFCD32B35B2DC773AAFFAC9DC35",
- "legacy_metadata_key_hmac_key": "A358646C1D338EC123E72FBCAF4BF615844764F91F8F2BD9811CDFCEF5FC2548",
- "legacy_metadata_nonce": "EB2B57119D7662AFA40BC448"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7BC6",
- "expanded_salt": "F81E9EC1C91B1007FF2A32D72FB6483C"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "36BB3E66C0820FC418EB2F1B873BDDA5",
- "legacy_metadata_key": "89981C312BA536E82EC3B1090CA5"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "218AB6D163ADEB31634B1DED52E56326",
- "derived_salt_first_section_no_de": "0F4F42636DBC8ADE1DF3383E6E8C80F1",
- "derived_salt_first_section_third_de": "B667CEF8B176732FD56AFE83BFAA7611",
- "section_salt": "D884E95FCD3A29F4E951A3C64D43C020"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "497081ADD0EAAD948AC3D743",
- "extended_signed_metadata_key_hmac_key": "4CF4E05DA1B0EF538CA84515202E1AFC845E94A236C672F091D7998A1AFD0D24",
- "extended_signed_section_aes_key": "7DF8CEF6BFDA7D1944BC5F5105BD003D",
- "extended_unsigned_metadata_key_hmac_key": "4892A9FD8A1080F06D299D8DF2FBD1382E5F31E32FDE1B974ED1958AD7348C08",
- "extended_unsigned_section_aes_key": "608194400C0D4390A12891645FEE4EA1",
- "extended_unsigned_section_mic_hmac_key": "8B3B932C61B0B9E2FF883B13791EAF9EBBE382E4539242DEEFAF03C6930FEE9C",
- "key_seed": "871B0FD2D15F8C5EA49B610C544D0F957884876C614228083A414F8A441A2D30",
- "legacy_ldt_key": "D41A6CF8C5BB99BB8FE8B33F341FAD33AF603E980B6C2FF70B6F0BC0080F655141D0421932F573706664085752947678D4F106E1FA71E8E584445BCE7ABBA35D",
- "legacy_metadata_key_hmac_key": "99D2C4B908B8FF9151F30A4B7ADD9590BF85EBD4D086560B32A20AFB529CC524",
- "legacy_metadata_nonce": "60B88352445ED074EA447690"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "BFDF",
- "expanded_salt": "AFDBB3A928B41B9C72F3CC9C21437B63"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "4F832379A70733EB481C98C287573D51",
- "legacy_metadata_key": "9C8893A6DB94328439157550279E"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "1F3AC1292A3E34943F65ACBD5A5D5F71",
- "derived_salt_first_section_no_de": "6162875F35A6B9B20C0F81C8CC9BC0D6",
- "derived_salt_first_section_third_de": "EF5A3849BB1526EFEF254214AE714CD9",
- "section_salt": "4058BBC28C1E874801AB570EAA0B1EB6"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "213546D6654AD76E62DDABF6",
- "extended_signed_metadata_key_hmac_key": "359FCC4FB2576B773E11B61937E190FD0D9249EFE348AAABF18EEB331373BF66",
- "extended_signed_section_aes_key": "48FEA76F4BA226E1880B3D8245125AEE",
- "extended_unsigned_metadata_key_hmac_key": "59118D794BC59C9D1F4A6008E3AFB9FDBBC9F874C1F6C25812ADB75AD7744314",
- "extended_unsigned_section_aes_key": "F55C149FB252D0744AAC781C04E87251",
- "extended_unsigned_section_mic_hmac_key": "6A6C6DD45298CE923C01E0CCE68519E1C6E2C494F0E9476E596539DCB30423FA",
- "key_seed": "7B65E45190EA159343E5562D63AE83ECF4B15DA7506706FBFAE25DC607D88720",
- "legacy_ldt_key": "7801EA9A9FE16C5554116B72463EF63DE1565CA8AAF6DC1025FE6AF53C4B798AB15609774385FC25FDDDC4D28E57A2661ABDD074638A10C7C9CD7E852CCBB9A8",
- "legacy_metadata_key_hmac_key": "3787DCAE0CC30E049935477D8562D380B9DB021BA494FD1ADD9925DBC8864A85",
- "legacy_metadata_nonce": "902CCFD130ACF873A78F9481"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "9A70",
- "expanded_salt": "4ECBEE3BBC2B85F39E379254D7163227"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "AD4B09305929D4A277BBB2D3227B54BF",
- "legacy_metadata_key": "ACA208D4C92030B19114C73F8399"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "34BCFCB74C32AAE99B97D24A839C4533",
- "derived_salt_first_section_no_de": "C6C751B4257933CCE05AD7C336B3F17B",
- "derived_salt_first_section_third_de": "292892273B46FB6C99FA4BC3C44708BD",
- "section_salt": "74F5AC8F69F601C07AB4AC92E9F51C3F"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "3564E475886853F7BF5EC55A",
- "extended_signed_metadata_key_hmac_key": "35A5FF3F932BDC655A9FD8AAEA36E25ED917C509A42F3337E3E3E89F2DDBCD0D",
- "extended_signed_section_aes_key": "470C528EF53B704C515C58A17EDF6C86",
- "extended_unsigned_metadata_key_hmac_key": "4144AFA9B5D527A9D1E05AA282A7C1D00DF51E79CFE93D7578043A5191C8D1A7",
- "extended_unsigned_section_aes_key": "C32F8F9706900F0FCFEE149D120CAAB5",
- "extended_unsigned_section_mic_hmac_key": "7D1D483580DA73C3322F088E3D2A24FE640A9F818CBD72842D288364A1937286",
- "key_seed": "A8590C79753059E9873CB4F0BEEECD1B43071D76BDD4A1E07809FFA0B89AD5E6",
- "legacy_ldt_key": "82D25B8271ABE1D6262F09DA005D99BB6046EC6BB387800B4E2E01993998867FBBD487C65E0BCDCECBDD89E1EA23ACDE697862E2D9B644963625BE8BAC4E3F99",
- "legacy_metadata_key_hmac_key": "C574697B87A56EA447BD202BFD3D960E2393119A5AA4BD270CEB0E37B719BF16",
- "legacy_metadata_nonce": "1CFD6A666E8F405C39D9E1AA"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5685",
- "expanded_salt": "8AF7ACB0C156A5882E64105535A8521F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "9B9FEE02950DC453BFB4EF3C1CCF4811",
- "legacy_metadata_key": "B2C2A05B519CF20021C9996DF808"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "89CF340356F2E40A23A033F98DDF7D28",
- "derived_salt_first_section_no_de": "853D5F3E410E67A666A9E41F86BD4EFD",
- "derived_salt_first_section_third_de": "DE0B861151059E218B754C32B123C147",
- "section_salt": "226836AA61CC797529A81307D64EA301"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "285561F74E853C3208B51748",
- "extended_signed_metadata_key_hmac_key": "32C03F14E9AA9082E4A87375B53543103A6B8B041922778BFA9C083D5E1F39B2",
- "extended_signed_section_aes_key": "A0BE8DF66519E26A80CA4C1D84958150",
- "extended_unsigned_metadata_key_hmac_key": "98CB9A09F93AB43D229C1D1699E998BB21DCC535128B4F3EBA93939CB2806199",
- "extended_unsigned_section_aes_key": "C579BE805B3801B4680EC72CF6F4C888",
- "extended_unsigned_section_mic_hmac_key": "DAE01D0E3D8A08A8B3BB00A48BC81E8C6B730133EC90A03326189F2E43A1B0A2",
- "key_seed": "82B0C4B354909A4A05C43CFD728804FD58C9A339362576865378D1B92A3DC3FF",
- "legacy_ldt_key": "A939DFBDC50FBF27637C0B2AE4357D4403A5E3956373BD17CB8C589657517E79D1EB900F634E3F41092E4E25787C6161D2D18EE09A13A35A354A449AB8292BCC",
- "legacy_metadata_key_hmac_key": "4D32558AF034F2AC2E63AB36256B842852598D49ADC8E2F244C8AC13DA1E9D04",
- "legacy_metadata_nonce": "F00120FCD5FFEC079D2CA173"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "6C58",
- "expanded_salt": "92EC631F08ABD78DC8552A2484D568F2"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "04443FC782143B5B62BFFB6F4E0EFE8C",
- "legacy_metadata_key": "F011C17EDC3FB4095C9ED4BFCEF6"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "7104EDAF3D39ACA85F0DE66FB8A0E6A4",
- "derived_salt_first_section_no_de": "297FC2DCC22C9793610FD3504DBAAA3B",
- "derived_salt_first_section_third_de": "CF455558C8C67E5AB573C79AC356B02D",
- "section_salt": "19421ECBB444B94A369F1684DA6E87F6"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "C1BCED6F35A78F0FB40F698B",
- "extended_signed_metadata_key_hmac_key": "30BB3C9AA11570317B0551F667CAB16554C72400B318F99E70FCDBE24138CBB9",
- "extended_signed_section_aes_key": "A32C24E09D4ADAAE24CA1944697B961A",
- "extended_unsigned_metadata_key_hmac_key": "4B5F583F19BB6D221E6105E55B45F9A2CEA17CCE179B03BEB99A9C50147CD2FD",
- "extended_unsigned_section_aes_key": "5F97AE24166CBFAF9BFE96EC213142C9",
- "extended_unsigned_section_mic_hmac_key": "C7AE5C3B45B8FA9AD2EB92D39CCF3D67C9F10BCFB44BDC747EEFF84FDEAFF921",
- "key_seed": "ADBFB02FB9DFC75BD74516C628285096F2C4350DEA65D4616BB4DD30DF2C8907",
- "legacy_ldt_key": "9CD5AFBB5CDB94FBF0A51B07C7B8C0CDE7EC9E8985D40CCB6E2EA21EBBA409B9D5E2123BA5EFB45000FB0660EC063274F4E112324037D7548F4CC9DD2B00A9EC",
- "legacy_metadata_key_hmac_key": "CE65891EF8F79F286A62705AAB9FFDB3CC49FDDC42F084BC06D11A4B7C254403",
- "legacy_metadata_nonce": "5630BBB459F3C2FF04480607"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "6716",
- "expanded_salt": "7EC07D3176C5ABCB3731A38D7CACE699"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "97CCAE1E7A2BB5319834306D940B4798",
- "legacy_metadata_key": "736A5584FB8EF29D722171B0E133"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "AD388BD4C9CA419A983A50DE70B96E87",
- "derived_salt_first_section_no_de": "ABACFA97695D2FBA00E7D5F2BB322165",
- "derived_salt_first_section_third_de": "C3BDDC19E7A1D453F8BE2B85958C2B6A",
- "section_salt": "522FF617F4877D7FCCB569597903DD05"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "2D02434C5257433FC62E157D",
- "extended_signed_metadata_key_hmac_key": "BC06E2ECDF44C4E749F07AA9FFDAE6786156382DEB38214C23ADF9676273F058",
- "extended_signed_section_aes_key": "277CC3A4FBD6FA8A0433813C35AE03E0",
- "extended_unsigned_metadata_key_hmac_key": "A93DCADBFDB56157B57CE0FB27845AB3B14072BB8F51AD430251D5FE431E4862",
- "extended_unsigned_section_aes_key": "01AACC054CCC1E4C69A30F5BDB083DF6",
- "extended_unsigned_section_mic_hmac_key": "ABD3E647D57721A8AFD6CE354E65FA9717FE273B3D3002C9EF116E3060EE49CA",
- "key_seed": "04A09B2901EA8F73BF4503081DA2B2F1C701C8FB2E6D0727229AAF18E618D6B2",
- "legacy_ldt_key": "F728279808DAA6957480F08D9A71EAFCDCA22F6D8BB646A1B55174997DF3C161D95E50BDC84F2AF897D97319D86D6CF1F4D29755B2A4BD4C896188B493579F69",
- "legacy_metadata_key_hmac_key": "93F7B7662855DC419AEA47D99180AABAA42DE340259E5875C60E90DF9600F419",
- "legacy_metadata_nonce": "D451E840855973EBCD5CB21E"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "4BE1",
- "expanded_salt": "76209392CCAC5FB22D8EEAFAEDD20ECC"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "2EAFE79FB0028DEEAAABCC1ACE7F7B08",
- "legacy_metadata_key": "1B9CE163FB544E4B189C5F2B72E1"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "2F0D5E19F15AD52B54C40021FEE0F9E1",
- "derived_salt_first_section_no_de": "7826CEB8C46C4FE75DFAEB56973BC3BD",
- "derived_salt_first_section_third_de": "CAC8343515178DAE36FD923FEBD8452D",
- "section_salt": "CDBB37DFF788530779D089D6EDD732F5"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "71177ECD2A4AF37C9608B3A8",
- "extended_signed_metadata_key_hmac_key": "B1ABA8C85AFC6DF1FA37250E164F40BD88ACBEA2E74A12437E13C3E0640C1FD6",
- "extended_signed_section_aes_key": "FD479476C02CE97482D3AC90876BBD75",
- "extended_unsigned_metadata_key_hmac_key": "01D6F430855496FE82A98334CEBD234A31BEBEFC900AEBE86C89ADDA184F1510",
- "extended_unsigned_section_aes_key": "7B66F349E92928431F7499B1609BD60B",
- "extended_unsigned_section_mic_hmac_key": "AB9676BE62D30988CB70A5A7F958E73B2DB6765CB2B06F06F37D462A930FCE4C",
- "key_seed": "7C6A118C1331C9276169A367E049962899C7A2E20444F9F964D83FEE4B0C46A8",
- "legacy_ldt_key": "A0C190B05BC945FE38E1C117D1AB06FE7DA9C46D74F76974CFD558344964054B05EE748E0F8F17D6A3AD995B129EC83F5A803F9FDE0098551020356E59CBE674",
- "legacy_metadata_key_hmac_key": "C12FF27071B70A96145919151789D0C4311B5CE896C010D49431A78FF933393A",
- "legacy_metadata_nonce": "F388B3284F9C4983BAC29498"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "B1F7",
- "expanded_salt": "7DD107544AA52412D36D5AC0C65E8A86"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "B6A84A4591AA5C4115D0D47E9D475DD1",
- "legacy_metadata_key": "66D7DAC60B00990F01D618D929E7"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C03F4007F1E7180EC871FE12519F98B2",
- "derived_salt_first_section_no_de": "A76C0BBEFDC804F829DEF65EA3F51C90",
- "derived_salt_first_section_third_de": "A4DF26763162B19617B24D357C4E7EC3",
- "section_salt": "4D555178782275479BAEBFCD147C9C61"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E4E6C206BDD5477A4894F465",
- "extended_signed_metadata_key_hmac_key": "9274B9E3806FFB99E2D096597B8716E0949486FF30BA7A1FAB01FB5D143E5E30",
- "extended_signed_section_aes_key": "5E09FB429564270B1E01C0C12064457F",
- "extended_unsigned_metadata_key_hmac_key": "AE2B21B4DD683EEA3815374C1E606EFE81B3012A20C244F3EF44E4B126C1B060",
- "extended_unsigned_section_aes_key": "4FC383A9EB6FC92D4E550C0869BA7424",
- "extended_unsigned_section_mic_hmac_key": "A2D2F07EE970FFA7030BC81DB05D87AD7A1CF60E45A0F607F7F7D6CE64E7FE1E",
- "key_seed": "06E34312B7BA188C16BF9EC455B7C3DB7BFF273ED7E671DCA6218923F6315EAC",
- "legacy_ldt_key": "9A779C0695146D84379F839C1B01410A77838D4627A16D697AD8BA062BAF892C0518FF10250348929DD369E8A6B0D41076A485B48287E01F9D28F76A7AA93C25",
- "legacy_metadata_key_hmac_key": "802F06CF894D4A44E91C384CD4CA11282E443D9E44D9A038715A3CC889DDCB19",
- "legacy_metadata_nonce": "0918753240B432ADA508D2A0"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "B28E",
- "expanded_salt": "27122881802D23D4B730928B317AD649"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "A60426318C060F541DED5C1F7AFA6E87",
- "legacy_metadata_key": "4EE9FB0C014E5C8DEC62CDCE3A54"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "C9264AB98A5CBEC98A59B436301C9456",
- "derived_salt_first_section_no_de": "75AA3B31D990FA958C0BAB07C316137C",
- "derived_salt_first_section_third_de": "20F8C6AA4C641C3EBAC513410853A637",
- "section_salt": "63056BE924D9AF7A4E1EDFB78F8FFD42"
- },
"key_seed_hkdf": {
- "extended_metadata_nonce": "641A9E897828B9CAD7C16FF8",
- "extended_signed_metadata_key_hmac_key": "690679062F05D8BAC47BA64D13F91029084631B9FD39696B64702B533283C8F1",
- "extended_signed_section_aes_key": "A521430F5CF09B5073A2EE5DCA704962",
- "extended_unsigned_metadata_key_hmac_key": "2685C8CB006301455AA48F317D812AFA9F36FC071A692A7E21F411CA4B203E26",
- "extended_unsigned_section_aes_key": "ADE5DC26FA3ECD51A6B4BE7B2EA0C70A",
- "extended_unsigned_section_mic_hmac_key": "D8AE4269C81599401F6DE7805A5DD401BBEAFCE68BCF3245E315940130C041C5",
- "key_seed": "41ECB16B981741F3FE1EC685A601EA8FB5F3B26ABAEC70294805339C90A8AD71",
- "legacy_ldt_key": "8A6B4B8EFAF5DE8701684F7470183A4046FBFEE965E61D4219E09F95280D43B895BC9FE4B39499C927FF0541F067C95D98377D139CA23D19AD7B729F75207BD2",
- "legacy_metadata_key_hmac_key": "D9A2131A2E99553E598BAACC299C5E40E3051A4E4244F3FB8705FEACE0CAB3AB",
- "legacy_metadata_nonce": "862DF488A461D0EFA780FC19"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7CE1",
- "expanded_salt": "72F031CD4FB7AB7A03423FBF04BA2A9E"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "07EDA657E63FC8F6737B5B3F4A0A8C81",
- "legacy_metadata_key": "F141D580CA3325C5FC485E552438"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D9498F72764DFB0266F773788284BCC9",
- "derived_salt_first_section_no_de": "2736F330B0FC8CE3AC39558F48513039",
- "derived_salt_first_section_third_de": "2B485FFF58AC337F216B01885F0A1FEB",
- "section_salt": "482DFB90D8B4501C8089AD97750EC132"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "F1FA2EBDE91BEFEFDFC7CF00",
- "extended_signed_metadata_key_hmac_key": "B1DF6DF11C98D5BE667BC5CE8B91321CC5498F9149B0217D48BA9C6E81BE9074",
- "extended_signed_section_aes_key": "D63F841B59C4398735CCE79146AADC3F",
- "extended_unsigned_metadata_key_hmac_key": "37A581DC364BB86DDC2AA8F8A1B939A7A92BBA83CA3697408D1CDED5699A4243",
- "extended_unsigned_section_aes_key": "20A1EA0E7454FEFBFF4DA2BB4DF6CD8D",
- "extended_unsigned_section_mic_hmac_key": "2842AAA512670388A45EC3DF52356B28AE1F7C3CEA324BE4847E9D8AF578A5DE",
- "key_seed": "37399B354FF258D23A87941C4E9A348D851C5CAB79E1DB345BB2568841ADE7B7",
- "legacy_ldt_key": "070759E454B3EBE99755C4C8C6FF67BB9DEA89D49A2CB68E02D3A4E66F12D1F97862F8A8B8664CD80A6F17EE9372170908F47B70681CCD6673019505E4130542",
- "legacy_metadata_key_hmac_key": "535D5A54192D3E58EFB23C815A099924B2602137D8E12F6279A24077E232C3EA",
- "legacy_metadata_nonce": "04B9108D0FB4A41EB17D754A"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "D6EB",
- "expanded_salt": "83EB2FECC0F1C19A6EF7FB30E945C103"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "60C52A4D9245D6E8D49DB7FE7FDA5C43",
- "legacy_metadata_key": "4E2117A0CED10CE233750FBAB835"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "849B406AC1383E3333C4526823350AC8",
- "derived_salt_first_section_no_de": "F2657BBB7FB8879E98F9D4EE55343AA4",
- "derived_salt_first_section_third_de": "9025C1E15E5668F1144640D7C2CB7F63",
- "section_salt": "971929C83FBFB8552FAC4316895F82EF"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "BAB6E78DEE99392F09D6A045",
- "extended_signed_metadata_key_hmac_key": "FE88421ABA3A3E0DA9E519243749AB2B28586480DB9B59C41F7E4AB17A9459CF",
- "extended_signed_section_aes_key": "EB1F668BACAD4DE4555036C8B9F21D9F",
- "extended_unsigned_metadata_key_hmac_key": "F7016A22618D636539DD37221EB7BA8BE8764707AB9DEBA695FAE93546E1E777",
- "extended_unsigned_section_aes_key": "7AF856E9EA5F3AC6EBF2DA80EC065050",
- "extended_unsigned_section_mic_hmac_key": "17738046ED5E72F0C379D08FE6A815CDF72CB1B8BA2C675DD013872E7B0DD185",
- "key_seed": "185AF89CD890AD6F7C0F9DE8228DB8A92AE25DEF3BE510289663D4C196FC2CDD",
- "legacy_ldt_key": "3659A65B725059278CB5ACD34B73F32EC5D8D267C15E567BD4EEE489618EFA62D03DF9A8C77D3B407F107927AEB771EC613320B1DAE7A295FC49AC8E1B274F8A",
- "legacy_metadata_key_hmac_key": "5F10B1A7CCA2F40E32B00738583CA2604312F1D9648EB375995EF725438B6B5B",
- "legacy_metadata_nonce": "EE05CC8759A360B9699FFD9F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "7FEA",
- "expanded_salt": "C7E9D2070465A796CB27EA5E81D7B5C9"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "E4AB233100D9D776DEBA1949426DC104",
- "legacy_metadata_key": "C5E5885E8041F9A0E290D0174FF0"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "582878C554E5BFF92A4C26C50BBC2B27",
- "derived_salt_first_section_no_de": "C9FA9274CB4C3F6F03BB7F2AA5D70A11",
- "derived_salt_first_section_third_de": "582276B5F71F65E87B883C86DEC83349",
- "section_salt": "2DA2B6676B05EADBBA2AC2C7A1B91E5B"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "1516355E155E481A2C1BC292",
- "extended_signed_metadata_key_hmac_key": "A96AB799DBBF000DBD6429124DF1AB94AD26BA8EA3CFA2BD3685D18F74AB95B5",
- "extended_signed_section_aes_key": "2EA7AA6081C6055A50D2BA83F7650ECE",
- "extended_unsigned_metadata_key_hmac_key": "54D6DE3AB30E06638AF867C79CA8F291499A6A912964EDAE3FFF06D75D6734FE",
- "extended_unsigned_section_aes_key": "FCF1C0C04D383C2B440E91142D5F8DF3",
- "extended_unsigned_section_mic_hmac_key": "617A0B559B6C31312C6DB59956560DB2200B0DA19132085BB51EEC4662365BEC",
- "key_seed": "BEE55110B49523CA92D9CD1921A3A3556D3DAE9E7D2DC1DCF809A7F744D744FB",
- "legacy_ldt_key": "3050E135E4A609B600FA94D673AD60C6800F860CEB26E0C080669174F4967FC877241054D94C945CFC4F511404AAB3941EF5337E49A3C0357DDCFBEE6D0FF178",
- "legacy_metadata_key_hmac_key": "D4CD2F5513409E9C08796B367D68ED86E7F8AA1D73B3BC80E310A6A89FBB5AF1",
- "legacy_metadata_nonce": "69BBF34C4C06F9098ED5822C"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "E41C",
- "expanded_salt": "F90A3A5A7E184026B2412B7981E6E4EA"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "7CBB4317E53C77A6EAF04270340C8E74",
- "legacy_metadata_key": "290406B8E4F3FDD69F77100C25F8"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "09C85DC366B0A127E44BC3EB55F1B69F",
- "derived_salt_first_section_no_de": "8E806978646803E71CF5A89A993EBD15",
- "derived_salt_first_section_third_de": "A79CB0BE50F815A706B75686E8AF95A8",
- "section_salt": "BDC5C3A2FDEFF52154DBEE9B2DC99272"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "38347176312E7BF0CFC150F5",
- "extended_signed_metadata_key_hmac_key": "AF37F8DDF621E95E9DF9E960D7C3C3B204CF5F660E33015C0F76E1FFBF793255",
- "extended_signed_section_aes_key": "DDCE8B724FCB835C5769FC12FBBBCFA1",
- "extended_unsigned_metadata_key_hmac_key": "2A31672AF767AD1C20F69A40FC0C39E82760A88CF7FC32AC562B4334A3BB6FE1",
- "extended_unsigned_section_aes_key": "A6DA0A55C2DF68D9A268E2E7D5DFA910",
- "extended_unsigned_section_mic_hmac_key": "842AC63178D49573C9A294B11B23053A8D7D032E2092A7B090B18C3B4B1B0D41",
- "key_seed": "5507520DCBC7FB26D474314F10DE9CA600A29F7EA2B4EE3FCBA75A79812410EB",
- "legacy_ldt_key": "13FAD5A042A94E5BB18ACB097E8D9AC9BC3212ECECCAE8B3F0877B28BE475A00F055E916510D5E37B70EBFFC6E20281A98E960BB875B6CA04DC4A4D791D728D4",
- "legacy_metadata_key_hmac_key": "D208CCF899D7738EFA94AF2F50D71E96A850ABD8DEA1E731513BF959E52245D8",
- "legacy_metadata_nonce": "55869FF688A156A9AD67F4B0"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5D87",
- "expanded_salt": "6CD22F42846D18DEB8B16AEC28055646"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "67C50D4BE0C807CC777A451E55290706",
- "legacy_metadata_key": "CC56E75A8BB54C3CE1EE9DAC6855"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "724B63781CDFD0DE57D682E929C0F1AC",
- "derived_salt_first_section_no_de": "DA6C22EBBD2E4FC58307D725E7001E18",
- "derived_salt_first_section_third_de": "70E96C64C5013DDA87D8750BFC734CCF",
- "section_salt": "60922665EAA6734D3AC84D0BC6B8173E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "6195C05F850120907C37E671",
- "extended_signed_metadata_key_hmac_key": "C197E6E017FDECD561EA88AD8CBF7F9826B17CC993E15803C2B770DB98803F71",
- "extended_signed_section_aes_key": "0400A8E1E5D2A6D93FE2DA13E109D10A",
- "extended_unsigned_metadata_key_hmac_key": "DA4F587EA32EE460D0605AEFB2A3D4916137A0D27FE142D2BA315CFE40A7CF7E",
- "extended_unsigned_section_aes_key": "97F44ECF5B72FCAA7730A06BC7E21466",
- "extended_unsigned_section_mic_hmac_key": "1B2815943A5DAE1D4823E8B146AA3CABB59017B2D01E9DDA7731933E77354459",
- "key_seed": "933CC9ED79D768475F2C50D65DD35E354AEC0ACDDBB1DB7A406B16A967262F95",
- "legacy_ldt_key": "B3C8DB885F6949E585C9B9CFB8292A2E1D16DFAEB0D8B4CB859362AF85EEB78F55C676BAED4ED82FE690EB5A52DC194E3C09037367E0AF6C012DC33AFE024750",
- "legacy_metadata_key_hmac_key": "68B1BDFFCEC2A954A0C61C07BA65A3028BB117945F0D405BFF859719E90C603F",
- "legacy_metadata_nonce": "9368E6A9BFD9CA79ED0FCC4D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2C1F",
- "expanded_salt": "764B370D8ED153B4D9AF7326FD7E3131"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "6B947A303D99A9874028683C7663E5AE",
- "legacy_metadata_key": "95E95ADB8AAC112E502641BB3974"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "699F64EEEE0A421370D20D1E656D8EF1",
- "derived_salt_first_section_no_de": "0B9CC994DEB1CBEE31334AAE82BB01C6",
- "derived_salt_first_section_third_de": "E883BA14BB1E9C1CF2CA544507A8E26D",
- "section_salt": "93EC27FD11A0710A12D837043C9CB895"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "8C118284D7A96BF2A60C1239",
- "extended_signed_metadata_key_hmac_key": "C6CE919C79E1CB055C77D1213E9266D95C8B828D32E93F77A8EA73EA48C6CD20",
- "extended_signed_section_aes_key": "6E770DC0F1C276CE1DCFB138E8005EC3",
- "extended_unsigned_metadata_key_hmac_key": "2582C714334AAEE935486705696B9196C27A4EC495CB0E59C8601CD60831022D",
- "extended_unsigned_section_aes_key": "255034A404E961637FCF4CE1CA72B44F",
- "extended_unsigned_section_mic_hmac_key": "4216782A51DCB1997224685E06185109FEF99FA3354038A49FAE4F0E0076FEE7",
- "key_seed": "562111357842DD6AD71E95C6B9DC635ADE5E2EC3A2E29A242117147A0148705A",
- "legacy_ldt_key": "D258BC177A33B5E2256475FDC9F84AD78F8B4886EB8781B4F1926716A6BA6D527D75D2953CC4037044B14107A91B292A45DD46ECEA653A1D086283EAB5607FC1",
- "legacy_metadata_key_hmac_key": "8BBC6480F67E0BB2AE62AEFBB16D97BFD4C37618E34B1982B29BA56B34FDB466",
- "legacy_metadata_nonce": "3EA11851CAC5F5608CCCE44F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "1C18",
- "expanded_salt": "A58037650FF49441923278D15FE312D6"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "96B7834CD34C6EE7027864BC6CC410FF",
- "legacy_metadata_key": "B8CD0EC6CBB33A4601A522200869"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "B091260FEC73EE7A8D70201F9D464F83",
- "derived_salt_first_section_no_de": "EE1D6CE31F19649C24841A7F6533AF34",
- "derived_salt_first_section_third_de": "14FD75BF7AD5B802CE6725D9A4C2EAC9",
- "section_salt": "CC587F388F406FC90B64C0AF1000419C"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "0F1F6DDCDD98D829428F0551",
- "extended_signed_metadata_key_hmac_key": "6BDD30B0682F92D8E01A1483C3B21887F0053B3E99435388C6DD41037EB51AEB",
- "extended_signed_section_aes_key": "3F4604AD3B2C106C10BA72C3ECE5AE49",
- "extended_unsigned_metadata_key_hmac_key": "874627B363F91A534891A9285E0DF0EDD15DC79E3E48A165B0984D4521ACAD7B",
- "extended_unsigned_section_aes_key": "B103A43F35DC81696985B85943FC9F7C",
- "extended_unsigned_section_mic_hmac_key": "4983A837EC95679DFBB7BBC1EDA6839C351059CF76E3465FCB7150E2C9DAA555",
- "key_seed": "67E041F864141E3F2D046910D9F966739B5C393ACC320E68C5DA6017D4599DC7",
- "legacy_ldt_key": "D8BB8E5985E39A4E64C54FCBDE74D1D5D3E27781C34AC260999F4FF0C06B0E1AE7A0E6D4099F9BF71BCEF921B24C85751314574F394891E49C8001FF56806572",
- "legacy_metadata_key_hmac_key": "2BE0A55DA15AA8323C56AB17C946C6A4E539560BA87A85C656BD1EF2326300BF",
- "legacy_metadata_nonce": "6E488DABE0EF2C8F5EDEE07B"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "246C",
- "expanded_salt": "A04B4F4D54258A3481BC4E119A6A2B62"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "9DF4EB64B8D5D2959CFD9D092BC37B17",
- "legacy_metadata_key": "5505114A304DFA404B9258AB6AF7"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "92F14175B1DFC4CE170902636E42713E",
- "derived_salt_first_section_no_de": "4156C04BB9AE6EFA9DEC3233CD5A305A",
- "derived_salt_first_section_third_de": "3C58FB419F0BD045E235ADC4352676DA",
- "section_salt": "FCC5C8C0A905123991DB1963CA187342"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E6CB1D645A1C322DD231C530",
- "extended_signed_metadata_key_hmac_key": "6541D917FFD4EBE53C09BF098B18DADAAA8DFF5ACBB1356BB3E1439EAE91E399",
- "extended_signed_section_aes_key": "A5C69E0BB040A4ED7AEA8D202D1AC1B6",
- "extended_unsigned_metadata_key_hmac_key": "0F3C39ABFB77F95C5B015829511A821DC453306953B33D12A1D0BA5F2E48F3DE",
- "extended_unsigned_section_aes_key": "F73B279C87F7D8145D53BCE3FBE49FA2",
- "extended_unsigned_section_mic_hmac_key": "C386709CED7BF9873F36D764C601B3DB06FFF096993FE59E2C2E7A2E06C83ECE",
- "key_seed": "66BD6221C1E30871D422B67F060C9E22800A834DF098843BFC648B76E54ED908",
- "legacy_ldt_key": "79204103FD0DC36158434265D60D9D4A7CDF2569D1A855CC1C0A5616298C41E07A25577E028C13A4C517D2BEBCFC6F2198710BE7573B7C0C70E73BFF28C9710F",
- "legacy_metadata_key_hmac_key": "FDE5E6233F81A1DA995A94969207DA3CF835C672B2C4A5F65D36AE45B2A5D2A1",
- "legacy_metadata_nonce": "57EA5DBE1D8D34591922A866"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "AE61",
- "expanded_salt": "EE04115499CE6C19FB6BB2610257A5FC"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "45FE6BCBC3E86F2B10458F44DBC73647",
- "legacy_metadata_key": "D9B336A4E52CB722943FFD9CF784"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "6919D48644FFCB351097E0A7F63BAD7C",
- "derived_salt_first_section_no_de": "B40EEC7CA7711C443BC6131AE1209711",
- "derived_salt_first_section_third_de": "EE87CC5CE451FACAC62DD63C70F53BB3",
- "section_salt": "E9C2AB1A142AAD88D5B3E8ECE861F46C"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "1F7415759E6AF70ED5ECFB8B",
- "extended_signed_metadata_key_hmac_key": "4C52B8B27F4405B995784DA1A19800280D7790F02E1A4ED718AFF3B9D2CFB632",
- "extended_signed_section_aes_key": "E39A23C3DE620D184AD6717B9441B453",
- "extended_unsigned_metadata_key_hmac_key": "D97C790467145FC66B8962922BE7163D01E72398E58A7381E94E52205A99C49B",
- "extended_unsigned_section_aes_key": "FB9F25B845153CD75A97C8FCDA32A6B9",
- "extended_unsigned_section_mic_hmac_key": "7F291513A23A7AA803A1CD8DBA7A9DE24180EE1580B31E3AE689EF51851EF266",
- "key_seed": "C76E4012BA6DAE4B2CC7DE0FD6A60790E7E69183D4C894EEB2C14F55F691D200",
- "legacy_ldt_key": "02D0233B56EB07765A584139A7791E9E338698C5C16A32B89973A921DCE26B483E7322D354F8D597A48A67818E7697686C9416CE10A2FD5B5A153A80EF0C3DD7",
- "legacy_metadata_key_hmac_key": "D3BFBF4AEF2B0EAA29B8C0A4A5A8E140C9861C55AE77939A9100863458F73A48",
- "legacy_metadata_nonce": "3DB25905270EA45BDE8B2C78"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "C0DC",
- "expanded_salt": "51AFDF06C286189BE2A38DF2AC5C157F"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "DBFD6CB8BEF948E30034942C217AB49F",
- "legacy_metadata_key": "A6572C02A89BFC53CE24AFE726A5"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "F0C2D07232D5E955E8C82CD835B56E1C",
- "derived_salt_first_section_no_de": "1F34BDC3807F158859A6FACC33B76BA6",
- "derived_salt_first_section_third_de": "8B547F100FE1EAD817E8DD7AC7FA6D7D",
- "section_salt": "E887AFFFEBC6CAEA000CD7B2843AD21E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "817052592ED2AC889E53F3DB",
- "extended_signed_metadata_key_hmac_key": "ED836D0F732D1051DD4E7DAE505FFB670CA6717F7BC287E0C8957EEAA6AAB9EC",
- "extended_signed_section_aes_key": "03D31EED691F220ED807A0A3699D01E5",
- "extended_unsigned_metadata_key_hmac_key": "0C304D6EA35B6602646FC0E6951EFF09249712E42E8AA6BD995666AC29E774B6",
- "extended_unsigned_section_aes_key": "8507DF1A8D34390EE03C10C29C16E20C",
- "extended_unsigned_section_mic_hmac_key": "857FA3CEE51F9018367961FF82F30041D43DB1F1916BF067396EE7DEEE08B063",
- "key_seed": "F7E47754ED974913367ECC4B4DE2B1E66D9C8EF36BC36875111231A421A1F892",
- "legacy_ldt_key": "DF739460333EED047E4700C6D43763208D6F7B8994CD36AFA6C3B725124BD68F50A5DF542D16780F8FAA64C919F4E1321752C2473BF44843012F49CCD2BDC43F",
- "legacy_metadata_key_hmac_key": "7BC61FACD5C01C6F0B24B38004BD8CC5BD00215D9270D8621919266CFC7CC1F5",
- "legacy_metadata_nonce": "23DE6EA7BB73D686CA04432D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "FD97",
- "expanded_salt": "AB621F612EC9F1DBF995C1CE7610A3F4"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "7E59495C2E31ACF37A8A82914D67A3C2",
- "legacy_metadata_key": "FD95D8D7F1234F29C61B73586E50"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "B1FFFDB5149EB2C1E55818C9AC278F22",
- "derived_salt_first_section_no_de": "9FF7BA7CA2D7A64907CAD503C9D9E931",
- "derived_salt_first_section_third_de": "E05CE47FEAAB471BDAAEEFE326144F87",
- "section_salt": "05FD6AD5FB6ECEF67187AB22628D83F5"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "656ECAFAD9D02F5C53D1499C",
- "extended_signed_metadata_key_hmac_key": "3C07733D5EADB798C0F0A085711E7980D5437BC8D9003F2E6D32EB1E997D8D08",
- "extended_signed_section_aes_key": "D49EF1EFFE0236EA082EF79C6BEF496E",
- "extended_unsigned_metadata_key_hmac_key": "BBAF91442DABA83EAEA9AA3C6312972672AB20FE962605FDD01FD709F832D562",
- "extended_unsigned_section_aes_key": "D472A600CD6F77F233D6274917328EDE",
- "extended_unsigned_section_mic_hmac_key": "62A45AFFBCAE257E682BCB364B77F8FFFEF9088BB8DE260FAA6E622088E44A43",
- "key_seed": "744EE5E68214D686A678E2F964A33C054EBF0155354CEEEC0EE77448F6E156F1",
- "legacy_ldt_key": "A3F256081813BAEF903C9DC155AAAA8F7D8443726E1DB42695632D36BA9932E0A70D568A10CC1631D1CCB86AABA44B82CE08A65EB31C466C4E41728A11429BA0",
- "legacy_metadata_key_hmac_key": "33EADD4558505A6805581DC7E514C624670C824B489D63F54500E7AE348184E4",
- "legacy_metadata_nonce": "33283F73B1E3EBA32C5D862D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5987",
- "expanded_salt": "BDA17AF3C8D8E8E7627742B3AB2075B6"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "F9BFA683C1B856991A2C5CA893D71050",
- "legacy_metadata_key": "DCE4D724E5161B46AC54E4C18A08"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "DB22BC19A27CCC15E51A0A1B950857F7",
- "derived_salt_first_section_no_de": "547CC56DC0A5507125082C68C053D5D5",
- "derived_salt_first_section_third_de": "DFBAFDA1CF3AA59B26FE011EA450B823",
- "section_salt": "078A2C255BB03030F52965D13B0AA53D"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "1020F8C375AC5BF5D3DAC380",
- "extended_signed_metadata_key_hmac_key": "98F6FD73D248D52E1338E6F37EF4BE53160EB68C57687BBD5F4C4AE7F2C5A6CD",
- "extended_signed_section_aes_key": "63B0CB478D4E5F38F454521A785B5DA1",
- "extended_unsigned_metadata_key_hmac_key": "77A743C542941356A1DB8D8F3031439401B82F1B7A6C5BDA68152C1232603CE9",
- "extended_unsigned_section_aes_key": "B743EB7D63164D30EEA5F452F4ECB6EF",
- "extended_unsigned_section_mic_hmac_key": "F34F5FED159362C0CFCE08702216F77B7BC9BD6739D7B7A6BE022F69E119A011",
- "key_seed": "8D8B909F903746E317D2FAD7B81C44E14C2BC911BF57505FD21E657BDE7B9448",
- "legacy_ldt_key": "B95B352CC7A616CFCEF94F140DB1FFF6C96699456B53E22EF2A92C189C8ACF71B15996E5592651FDB0B9EF482E3D3A77F69C43381BFA3FBEB77EF3FF3508C4F6",
- "legacy_metadata_key_hmac_key": "0FA59F92E4D45EA6F7CE221654D40FD7F04723C271B02CF2E6FE7D2F38B1F9C8",
- "legacy_metadata_nonce": "B8CE49F04135E2EFADD82878"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "E04C",
- "expanded_salt": "C09ED0239B32A0C2BE3A0EE440CCBE42"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "3FEE720404CE1EA1B1D761262F6E2C09",
- "legacy_metadata_key": "5D81EB7355CC5ED9A8979ACB3DC3"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "0062A464AD7B46EC51A8083B2F34410E",
- "derived_salt_first_section_no_de": "08E8417B389B48DF971A62A738A28A1A",
- "derived_salt_first_section_third_de": "A475206446E694B5751C5E3CAD225454",
- "section_salt": "F2F39B46ED2763C2D2471485E6EAE97F"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "9D465DB8703FD644B14B99E1",
- "extended_signed_metadata_key_hmac_key": "14BA9DEE1626741059F8B6D426CF83FCE010C26124E5AC9D66925D3B89EE2BB1",
- "extended_signed_section_aes_key": "591995C12F75A6D28673E9BA651BF099",
- "extended_unsigned_metadata_key_hmac_key": "7BCCE36CAE2D834C397513EA6C8F90026A1108A856285F9106B38319EFC9FF9C",
- "extended_unsigned_section_aes_key": "A5A156C9EC17E50D3D4D5DABB63CCBA7",
- "extended_unsigned_section_mic_hmac_key": "EBCEE2B687E58DD608CA3BE824C5465BB325FF602E30DAEBB2F2544DAABEF580",
- "key_seed": "6EF7F1684C5C353B4ECDB1EEFDC10C34CF78B9E60D067EC7DB769595F8914CD8",
- "legacy_ldt_key": "8251C9BC73D421AE9345E27335D84A03BB706EE9A2ED41A90D3E7BE66B3EEE9D98ADDF2958DD85B21FF1BF5CB06DD1B7180781BC89EA0AC6B31E0DFA8B6F49BA",
- "legacy_metadata_key_hmac_key": "177B5056A2BF6ADE707EC448CE3825FC7F4EEFBF6118F58BAFB9504B461FB3C0",
- "legacy_metadata_nonce": "989E60F047E8D4BD15075FDA"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "0E4A",
- "expanded_salt": "45841BEF518D55BC872449D35B69D3D3"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "07BE6AE936B1ED68B3823A6893702467",
- "legacy_metadata_key": "0C15537A85CACDC26F26019ED439"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "3DE9D56F37147C866D25DF4D1EC6E854",
- "derived_salt_first_section_no_de": "2FDE5B60AFED59C1CF366A514FBBACA3",
- "derived_salt_first_section_third_de": "AF10E5F3A5DF61DE19420E75E55D12BD",
- "section_salt": "ED4025D9A2CBE10CAA5B8A1ABA910BE4"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "6F59318B12B620600E40892E",
- "extended_signed_metadata_key_hmac_key": "383DEB0C8AA51D119AF01606930A19F42C253BA8AB6A6CA730F7F0DA67F6526B",
- "extended_signed_section_aes_key": "8E2158CCE463C86814C3A923EB66BAAC",
- "extended_unsigned_metadata_key_hmac_key": "551F2045C860E1A7B7B0E190ABB6A51447E9DBE9009AFC46FECD25331E4AA414",
- "extended_unsigned_section_aes_key": "8AEF9D42C27067B232BEA8242FE93F3D",
- "extended_unsigned_section_mic_hmac_key": "788130EA49F3BC5C2D9FEBA9C9758A4B268A0FB16C2B844A4F28E03E7549D602",
- "key_seed": "0C692A79213891396CD3B92C3FAC2DA33EB0491272E59411E1CCBAD01F1CC663",
- "legacy_ldt_key": "AEBD9A429EF5E38A23C12F825C269950D231BBC7548115E198C7BE64B096B6FA6C11CB120803241FFDE8A78BACF27CE5545DFE3E896F598CB5EA715115B9EE56",
- "legacy_metadata_key_hmac_key": "D68DC293B640E8E6E0E60DAA01B744FB59FC2EF5868D8856EBDB39772A510E5A",
- "legacy_metadata_nonce": "EC688179F89D775E64394EC6"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "BD8B",
- "expanded_salt": "F3078BA520F2080B927ADF89CF273A18"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "DDACF0C5D556F78DE46253E77A85ACFF",
- "legacy_metadata_key": "9732F406F870342BEE8B0A914078"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "EB86DD1685C8017EAACF542B7A32C154",
- "derived_salt_first_section_no_de": "2E1D91452B6BE755CA6D1A510B786F95",
- "derived_salt_first_section_third_de": "3F6795CB4E05C03486FBAD12D98543FF",
- "section_salt": "700111649D792ABCC1E004978C637E0E"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E3A2F71B15300A7232927D5B",
- "extended_signed_metadata_key_hmac_key": "688536A171F65ED7AF6DBE841968025720997891374D0E30EAD96C2DBA1C6CD8",
- "extended_signed_section_aes_key": "72B7CD1147CAD43C239D0637C9192967",
- "extended_unsigned_metadata_key_hmac_key": "22EFB24D7DEE84A07643AFF3D11A0EF56D818466C43882E3170027DE0CBEF920",
- "extended_unsigned_section_aes_key": "C38BC169874FB5551DEA99A853A3242C",
- "extended_unsigned_section_mic_hmac_key": "28F8743A05F77BB067BE29BB714EF5208532383125EB35317F6C9B464E65159B",
- "key_seed": "8062D40BA07D2331C15DB4F4992D45A4C500350EB2B4DE00BF5EBBCE396A96E7",
- "legacy_ldt_key": "4ABC6C92EEAAA16D277812A851D8A1334846D9FDA1DCCAEEA24927F74765F37C48FB6297F88982234DA5B576A6FA5EA69D11972104350CC3CD20932799E3EFDC",
- "legacy_metadata_key_hmac_key": "30121B3A3B523BCD071DECE2F469E96D24EBD5B83CA941EAF7F038010A70A1B1",
- "legacy_metadata_nonce": "873248D5319D71CF756CD8B6"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2D7F",
- "expanded_salt": "3C48F27B1F13EE4BD87F817785EF7703"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "50979493AC77E7C48BABD922BBBF9775",
- "legacy_metadata_key": "EC8D649AF82B50E56F7E5F2C1426"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "D262A02E3A58DF486E345BEC4A2B5D4F",
- "derived_salt_first_section_no_de": "9E106096FF44973E527F2F7CBBB68275",
- "derived_salt_first_section_third_de": "F9B9F4D9CBCB69C7A00DA254229D4BF3",
- "section_salt": "4496838ABE23AA21C0CA736114A37BD6"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "786176FCFF3231D1572CA808",
- "extended_signed_metadata_key_hmac_key": "18CE44A7087E1E3FEDAA6248262F697E1BAC68F878815DDF44A330BFF19A43ED",
- "extended_signed_section_aes_key": "AC9B94AC20F1D81E1D1DEC0684E36297",
- "extended_unsigned_metadata_key_hmac_key": "47C8F715E8E2E9F67B1C376E2D726A60D30D1B8033E2D78B7EA3D1DD55BA23FE",
- "extended_unsigned_section_aes_key": "0C40C4BA4105CE4F2CBE9C8DE5F01123",
- "extended_unsigned_section_mic_hmac_key": "6D9373A7A34B9072FA386B06725B4BEF851EEEE601907991C5D2D51500356F2E",
- "key_seed": "EA366AAA629102AB6B62305B92BFF85C878A1E7536C2057444C989AA68370138",
- "legacy_ldt_key": "4FEC3FF94C7E7BBB8A7ADB496EE01056B702AD1EFE5458E94FD0D9436EE976CB367F12FF19A31166D2E7541C7C71C1B3BF25E532B08D80A456A1FF04A6C79503",
- "legacy_metadata_key_hmac_key": "EF0679E429D9B23036DBE7B8AB08AD5B02C236DC8C2D526EF3E0E840E1FAE6FE",
- "legacy_metadata_nonce": "B90108EF65B54923459A2B9F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "5203",
- "expanded_salt": "A3A47B0B38AB2899441F905548251625"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "BB0BAE62AFF2FE5A6E20B8D581A272DE",
- "legacy_metadata_key": "DF9B54563110C3D424C36C7A0B12"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "9794C1A08CF2F8E1E64FC53A89C81798",
- "derived_salt_first_section_no_de": "899E09BEA7E181371FC7DB3E064B93BC",
- "derived_salt_first_section_third_de": "BDA3B1732F5E0E7F2D0E8F3EA79402FD",
- "section_salt": "82CF94C9A74170CDB84C8132E0A9AA25"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "9E2E62CFF064E5688C2B785E",
- "extended_signed_metadata_key_hmac_key": "397D11E6EE958656F2674EF69001146BEE0F972C497C92C71914B90F908228F7",
- "extended_signed_section_aes_key": "C5AB5145752AA16E3C65C6EFE561EC9C",
- "extended_unsigned_metadata_key_hmac_key": "EAB5C3F841C81AE3394987D3AE876D5043778BB711A191C36BBCCEF42CA3FF6A",
- "extended_unsigned_section_aes_key": "E9B70118BF8A4D58A758F1B3FA1661AC",
- "extended_unsigned_section_mic_hmac_key": "B3E6D61C78A8867BDD3F33404218279D13F6F89059671DED0E8D4EE34C7FB5D2",
- "key_seed": "F61539C310341BFDA73F7D9504502B785A27BD555E2A4B80BCE329AB213522D0",
- "legacy_ldt_key": "2D427E218733944B5F784EBE48E0DA05A515BE4D4D6C56FF79E36661F2DDDD8D6ACEB11FBB0F7C9DFA18EABF0BB2FA96F093F0D599DBFE357265DC5A6C860ECB",
- "legacy_metadata_key_hmac_key": "53DB1506A87A258744C9B065C1B6D0C39395EFA8F0E6C543415506BFD6252FE0",
- "legacy_metadata_nonce": "D3B81B8D52920BB3D47EC5BD"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "2037",
- "expanded_salt": "E1430F688FBB46C8F6067E50A1F4B296"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "1D4C9F7C2CE767CDAAF1F2E2CC9E56D4",
- "legacy_metadata_key": "8A521A8E6FD14285498B5DEC2A79"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "4363CB3C7259246F4B123095550EE704",
- "derived_salt_first_section_no_de": "6E95B9CFB044108DE5EABDDD098667A4",
- "derived_salt_first_section_third_de": "F4441684E3A1C584AE218220C5823D63",
- "section_salt": "4FB82CF0A6F46347DE465EF01BEF9DC7"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "7F8B9AF9663AE92297910F2F",
- "extended_signed_metadata_key_hmac_key": "12328EBBAC73837BAC2D4B82D2EB0943C41F11DEA46B6562C1992B49F91D78F4",
- "extended_signed_section_aes_key": "DB11AC0C3FBD6B105EB4ECF65440F2BF",
- "extended_unsigned_metadata_key_hmac_key": "D8A37BEB7EC0DB54ABEA9C4A05616090ADE42C3C255949698690C5D38D683627",
- "extended_unsigned_section_aes_key": "AF42DDA012ADF8A795EE4A7B15DAA081",
- "extended_unsigned_section_mic_hmac_key": "48EA765212AD49D3527D56554149629C969AE888F1D681DEAFE78CB0F0EAF658",
- "key_seed": "E615EDD2FD82BB47855C4BE869BFC649E0BD0EF7A15EB0C8F99E5884156711DB",
- "legacy_ldt_key": "EBC006F8343DAC70202A8ACA714C41EDCFBC6B5A5E6756DE2687A2A2B02068CF3317F3083E0DC3D626BCA08DFC188F1FA131B90679899618782C58CE2D3416E5",
- "legacy_metadata_key_hmac_key": "F50BB9D2761D9FF880911989A82C2B844E21D7F4AFEAEA1CDB5F8BEB417F1EE0",
- "legacy_metadata_nonce": "9152D3FCAB6D25F3EB847E41"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "889B",
- "expanded_salt": "7FBF8613F21C47797F4814D1939629E4"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "B10610105C6FB841987ED5DA28B1A8FA",
- "legacy_metadata_key": "82558AF0C2A123C0577AD47FDDD9"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "BF63189D3C53D46BC6D15EA10B4AB4E0",
- "derived_salt_first_section_no_de": "C2D485579DD258D6806CF6E345E0EC22",
- "derived_salt_first_section_third_de": "1CCCCF350FD11768168AC0C94F598931",
- "section_salt": "3EE85997BA02AB4A6620B2CE05469FE2"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "6743665EF1F2534A7EB969AF",
- "extended_signed_metadata_key_hmac_key": "355F49A98438F06E21D1501BF501ECCE624C206CC9F9430B0AFBC30041DA605A",
- "extended_signed_section_aes_key": "CDD0694A18EF582345EA7C785F928EBD",
- "extended_unsigned_metadata_key_hmac_key": "C82654B0FE5E9E50821806DDDD7F8114A79E9C2DA232C557A4B0AC98A514CEC3",
- "extended_unsigned_section_aes_key": "E45A101D48BEBF02D446F97609EAFEC2",
- "extended_unsigned_section_mic_hmac_key": "CE08A1DD793049E727DA51A8E6BA3B0AF1563D9DA40474FB335199037BFA7CAB",
- "key_seed": "E396273E0432224E384CF4CA199547E73E985A3E7886102E0B9ABE911ADBDECC",
- "legacy_ldt_key": "78E0EF38C80C61C0B907FF322D047C00664B19B5C704E3698E30B4860EED1814AA25097D7437E972007C5B923DB8D3708B312420EB1708817353D5D3345D40B6",
- "legacy_metadata_key_hmac_key": "7266C9A1D0B38E92E975FE7E9E16436F7C596C62A99DCEDC01B26D65651917B9",
- "legacy_metadata_nonce": "9CB20BBE3E11C360C90F4433"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "F44E",
- "expanded_salt": "CC8D7F5AAE254573F1775BD42817E483"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "A5CEB053C9960AF550E753C41D78D146",
- "legacy_metadata_key": "E9E844761B0DA4549C8136A68534"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "73E81E7AD1FD560A8492C57B58F0EF4B",
- "derived_salt_first_section_no_de": "52C7E3EED057E22BEE798D1EF0AA09F8",
- "derived_salt_first_section_third_de": "075B795823F03E6D0877E58125F3BA2B",
- "section_salt": "600FE29E6B140E51AFEFA00BB3C72EAF"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "34D8405F3BEFA5DA663ABD38",
- "extended_signed_metadata_key_hmac_key": "A773F7699265B7BAC958E1EBFBA32B1C7B20B10F09DE32FE9F57ADD3190D6037",
- "extended_signed_section_aes_key": "3648115AE3CE58377A3CBEF0B3BB2911",
- "extended_unsigned_metadata_key_hmac_key": "64CBB1F7D08A526D5FF00C9C55C3B3F050B64DFEA5D2EEA4B1B5978632552635",
- "extended_unsigned_section_aes_key": "380C378C2656B11DDBE2DB9BC188C2CB",
- "extended_unsigned_section_mic_hmac_key": "2606D0A2E28E00E248C1A72D6441575A6737ED0E291F510F3C683E333F6E7860",
- "key_seed": "FF0CA47221553F08490BF23140D052CEC0055B8B4BF7F1217F20E3325C1A14CD",
- "legacy_ldt_key": "6CF901B6EF11F104077A3C8FC9DFCD406FFC0A9DEDA5BD1F373D61DF23C020BE603D604C67E2D6C8050AE464EC3F7DC3D6D90732E2E3935C339C5C4BCCD2EB0F",
- "legacy_metadata_key_hmac_key": "42AB1CF389132FF5895D75FC9695AE07CEB1C228FD9590FDB49A07F612F11F56",
- "legacy_metadata_nonce": "2F0439B0E875A3BFBC685D90"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "355E",
- "expanded_salt": "E6423E380E5D5970BE91AE9CCFCF0636"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "2E0A709E2856F0807AE68B785B51F0D1",
- "legacy_metadata_key": "26A21171AC7983950B900C2F2979"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "40D2F105E8C926AB9D7F7DA89596F555",
- "derived_salt_first_section_no_de": "33440FBB64C6BAB6453F7F9A050FFEB5",
- "derived_salt_first_section_third_de": "21899A6B8657F7ACB1048C1F683BAC29",
- "section_salt": "7B7751AF729D27E3E4C2384D7DB8BEB7"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "0155A616ECEC864B00282442",
- "extended_signed_metadata_key_hmac_key": "A824088645C02D59479DC7A74318CC5E07654B61F06478C67CF046E7B85BB252",
- "extended_signed_section_aes_key": "D8D511E9F1CBC39FEA821CEC36BF13CF",
- "extended_unsigned_metadata_key_hmac_key": "7AA177254B5A06EA9EBAF174490B4117DB213D894B3CFF4F877E4CD83BFAF8C4",
- "extended_unsigned_section_aes_key": "E902E759E6DEC479968A81B77B94257A",
- "extended_unsigned_section_mic_hmac_key": "CB6FEBD1421C381E3110CF4D3AB26B66DD581D0E0D56675314B389BF26D80231",
- "key_seed": "476578AA15A168B1AA7A31A35118008730FB1557A71CB1FB4B49A71103F8900F",
- "legacy_ldt_key": "EE0CC526127D2D552A052880C0903B85898507C0247F4635F50B0E4A7F00DF2B96CF572DFF31ADB922932C4A119DE3EC06FCCA823709A090BCD3E4F6E3C89B8D",
- "legacy_metadata_key_hmac_key": "65FA3562C23D80DAA78FF2CAC8C6D283D75C674079FAA21E9381E66DDB977AB4",
- "legacy_metadata_nonce": "9CC3630D7C3686BE3ACFB38E"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "9909",
- "expanded_salt": "AB6B101F206D124E8B55520349C8F4DC"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "DF7EC5214955F4A2666598DBCBC1337B",
- "legacy_metadata_key": "B37A8ED8D672D20361D8F3D51AAB"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "CAF806EE61C9F98C033B6CE648B0A9AA",
- "derived_salt_first_section_no_de": "7656E7E7B214432B15B30F17901A592C",
- "derived_salt_first_section_third_de": "DAAF85C2FF8DCA2EEAB6524A94EB001A",
- "section_salt": "DB0B46A3A5A38945744BC413851D8452"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "0598BCB940F7E46AEB02391A",
- "extended_signed_metadata_key_hmac_key": "4B37B033B3911F061486FDD312F423269F345C5EC9D6EE4C9E427B2E2D584159",
- "extended_signed_section_aes_key": "E28193D56E706173061F6890E557F96A",
- "extended_unsigned_metadata_key_hmac_key": "4817CC85BC549519BEDA10D2257EDADE178B2AA9A710C462DD1190727B9E2E14",
- "extended_unsigned_section_aes_key": "197FE5273519A250224BC5E582F599AE",
- "extended_unsigned_section_mic_hmac_key": "E2B6BD73DD9018FC0D73C63574CDB10E27D5B84386958EB961B30AED26BD5303",
- "key_seed": "2E84B9175D2AF64DCF5592A6CE6A600430F36D1E326268C8628A0790CB832637",
- "legacy_ldt_key": "78BF29E2890F20C2359FFD32E20DD90972C660DEE7626DFB2FD89DA4DF2AD34B146973BF7FBC08E477F18199F3861A089BC32F247BDE835A7E34D4242241830C",
- "legacy_metadata_key_hmac_key": "6F73D2A56EC7A166FF4965BD10FF5BD53225F9E598E9835120D4D3ECE29839B1",
- "legacy_metadata_nonce": "6643257603952C875B40D527"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "0518",
- "expanded_salt": "F5CB5C30716D50337E3597A008774306"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "C7437CB6E1910745E1D5F85217DE6C3B",
- "legacy_metadata_key": "836B4F0F57011DEE3EF79471A08A"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "509E424CBCC5964DC827CD736417FDA6",
- "derived_salt_first_section_no_de": "8269B8D8C65B9F7519F17EA1B501DCF2",
- "derived_salt_first_section_third_de": "313C4472E5BF2EC6F08F8E407433E2D5",
- "section_salt": "0C98C48D64771BD607BEE3CFA873E048"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "44F203FA2E7FC2E7DE0985A6",
- "extended_signed_metadata_key_hmac_key": "077688F727BAADA52A42D5F4C5DE0FB10028190F68A2950BD1B622A8810A4F84",
- "extended_signed_section_aes_key": "74959A95D5FE867B35646442EE2367F0",
- "extended_unsigned_metadata_key_hmac_key": "6F5E34C56135FDACC90EDD77AB27D40C583689FDA915AD2B3E053FB287A9B7C9",
- "extended_unsigned_section_aes_key": "BFBA8DDD3768E1475F6C2C8167DE2ED7",
- "extended_unsigned_section_mic_hmac_key": "7723F9AA8F4694412A19AAF981149B03F332C2CA84EE7A7EA30F0A6CFFE8DF5F",
- "key_seed": "C2F7D2B6C8A814B76198CC2838B787E70BE404B7F30C2D3300F00657FF15D4D7",
- "legacy_ldt_key": "A675CA45BBA982D8027F96AB8E65B2B267F317805A8E92547DE9B59FF68D1D5D0464197908115D84F1699DF1321671D201AD42918AEDB938A32D4C9145505949",
- "legacy_metadata_key_hmac_key": "C8B1A0EA176953817E25A5C2DD984AAA997A0841FD5795EBD596F8954490995D",
- "legacy_metadata_nonce": "811CF06428436C54CFFBF02F"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "FB05",
- "expanded_salt": "5E11580A3CE991235E9CC3C7F2ADF285"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "3226C766C11C315F46A2173286D56880",
- "legacy_metadata_key": "A3B88B75A089E3D23A9DEE562FCC"
- }
- },
- {
- "extended_section_salt_hkdf": {
- "derived_salt_first_section_first_de": "BD4BA99CDFEEFD741D662D819B4D14F8",
- "derived_salt_first_section_no_de": "64FB9A93030B0365D875001B3E96C350",
- "derived_salt_first_section_third_de": "6A3C091F49BF86800AE97AE1E7E45328",
- "section_salt": "E48DDB9A0AB7F195FC4CE1EECE95C905"
- },
- "key_seed_hkdf": {
- "extended_metadata_nonce": "E3B03E7EC1C59A97088C54F1",
- "extended_signed_metadata_key_hmac_key": "827D30C971E64E75A26047C6288B4709D814C9BE9CC7F46572BB9B343D49A1FC",
- "extended_signed_section_aes_key": "31F40B5580260656F90D47F58C6FFE3E",
- "extended_unsigned_metadata_key_hmac_key": "EEF0C2830B30035F6EC56904F132AEFB4098A88951CC33286939CB9789AD1638",
- "extended_unsigned_section_aes_key": "A60216A1AC950D161D157EDD08C98073",
- "extended_unsigned_section_mic_hmac_key": "8AADFDEEA0DF6A71D95D3570846F53A4FEC594274282DD4BD227C4BD64FF98AF",
- "key_seed": "0BE1EE39610085A3BA277EBBEAD2872369707174526F23FFC67AA8BA962ABB1F",
- "legacy_ldt_key": "8D4922931521FB95569442172FAC2118E396C92702DAFC1DC3CB9E205C0E3ED7896179B06D1A0B9528B936E2F85B6FFC741F8654016FD47107333BD247E96EA5",
- "legacy_metadata_key_hmac_key": "FAE1B3B936C6756EFD9AEBCA751389891DACDEE3EAFD3A808D0797F0C128F544",
- "legacy_metadata_nonce": "094573CD360778668C292C9D"
- },
- "legacy_adv_salt_hkdf": {
- "adv_salt": "3E9E",
- "expanded_salt": "D7A319F27E248AB5CA95967784D6AF77"
- },
- "legacy_metadata_key_hkdf": {
- "expanded_key": "15896E896566D60C3810FAADC94A05CE",
- "legacy_metadata_key": "C08895650105CE9C165A9BCA08D8"
+ "key_seed": "C73539A8BBF0270B0F15AC17442D664D0599FD63A6C9B913E1A4FDE3FD445229",
+ "v0_identity_token_hmac_key": "3EDE3135EFBB36DAA573469C4154DD3801D7A1A9DBF909EC9589C0F290395E09",
+ "v0_ldt_key": "FA79263B28CC411B6EF1D07A13D99E021D16E85C31963C86CA6413466F05F4ADC05EF9EAE5986F2C36525B366D88A05AC51CF105B09C98469341A6EC6E37C553",
+ "v0_metadata_nonce": "8A2952BCB4BB1A5131595884",
+ "v1_metadata_nonce": "2F68AE0A2D4A63436948F8A3",
+ "v1_mic_extended_salt_aes_key": "3C6AB7573EB60372377088D37FA71F28",
+ "v1_mic_extended_salt_identity_token_hmac_key": "AEAA5C7B9BEBC7ED47ACEEF2B4B15C957C7F18333DF05371CC5194928E4A75E1",
+ "v1_mic_extended_salt_mic_hmac_key": "77FAC801B7F4BFB45B66493109E5D2B8A1811046FE1B26FDD4911DFE83F22AE6",
+ "v1_mic_short_salt_aes_key": "6A4EA007544EB1F1F4FC3A09733A7636",
+ "v1_mic_short_salt_identity_token_hmac_key": "24CCCA1794C5267D0F31BFFD05933A3056DC866AE5CCC812D0BE992E741E3C70",
+ "v1_mic_short_salt_mic_hmac_key": "900CCE3E377FBF1A075F5FB96B2A670981624069DFCF8A99FF3CCB73AEDEC153",
+ "v1_signature_identity_token_hmac_key": "8C707D9DCB8C7965EF0DFB90C8781312135C0A8AD10388B939082947B0EEC5CF",
+ "v1_signature_section_aes_key": "EDB08293628753CF3BE7C28A65FF1A9D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "F0EB",
+ "expanded_salt": "5267CC24373508BDD9CC45FE1BBFF13F"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "DC3DF85D25399054C997ABA4D0550C72",
+ "v0_identity_token": "84C66824B29BA5741EC22F1D3E77"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8579",
+ "short_salt_nonce": "38C673E98F69BE47A67CD13D"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "DA0DEC97DD1B417639F5BABAD8F3EA65",
+ "derived_salt_nonce": "3D412EFE82132F641657B86BBB145803",
+ "derived_salt_third_de": "2F1011C59BF1CC8A1870CB124E8C2753",
+ "section_extended_salt": "C88D4D9DF5287AE88CC991A84CDEDAA4"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "3938C7007A29B73F1EE49941B99A569D154FF1CFA6B67701E84BA14D303E1414",
+ "v0_identity_token_hmac_key": "A1F9362118EFA8F8C10597C11D8E3351A8803C2832961916C4057DC6CB48DCFC",
+ "v0_ldt_key": "895E703E6017716499E617F2915C4655D25840D38CCA27E32941FDD82AA3FC2C2CB3B7F29444E96F7539B50951822CC56C137287A863FAF9709AFDF470392155",
+ "v0_metadata_nonce": "33920520D06381D8CB88C56A",
+ "v1_metadata_nonce": "D2AC980FCF2027E5C5317F6D",
+ "v1_mic_extended_salt_aes_key": "3DBE8FC106A237FBA6DDACA6EF045882",
+ "v1_mic_extended_salt_identity_token_hmac_key": "7FCEB04961C81354ECB3B8C933C0E57441EE02244615DC091690D34B85730038",
+ "v1_mic_extended_salt_mic_hmac_key": "B97F39D53AA3497347DC3D7DDB5F6399C3EC78A97844A4B1B6CA33D62A5610CF",
+ "v1_mic_short_salt_aes_key": "BD67C930144A6D49052DDD3100DEAC8C",
+ "v1_mic_short_salt_identity_token_hmac_key": "83741493B76DCB32684A90514D76E06AEFA48BF6CCA7E5FD88F62A21457D6B7C",
+ "v1_mic_short_salt_mic_hmac_key": "9C2C874DBFFA6A5DB88D8FAB3BC2E6B8453452A666407A970AB09586A729F64B",
+ "v1_signature_identity_token_hmac_key": "CE915CC5776983A0FA0D9952A2DB5B9362C413351C147E7A060161B94F668AE6",
+ "v1_signature_section_aes_key": "F5E624240876543285520E1E8E74F795"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "11F3",
+ "expanded_salt": "08286FAACBAC794BF268D0733E82E545"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "96661B2739A97E383181D6025942488A",
+ "v0_identity_token": "DFB8131F26DD0C193982BBDCB69B"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "4218",
+ "short_salt_nonce": "F43CD28A64290DCCB5ED553A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "2A5D5B1EE6E62646232D1ABECBF33804",
+ "derived_salt_nonce": "2890730B9A82A68AF81B88B2880E0CCB",
+ "derived_salt_third_de": "C493E8AB86C2BD5B5B7EA619D2E0E92F",
+ "section_extended_salt": "3BC347425EE1B8962BF6D5D340D53C9D"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "520437E77A58A99A75D71BEABD7D787B8C570335DE0E1D9C0EDA2659EBA786E8",
+ "v0_identity_token_hmac_key": "CD255D8326E90A105F6CE79A2CD291A2775D414DF5E1BB2C5AB1FD2AD76BB6E3",
+ "v0_ldt_key": "279DD7CCD679EA8406C1682148A1312BED0A0DB6414809A23079125258011134C5574FBEE4BF9E1B74E1F5D0F911B52B902B0009D0BB7100CBE9872648E3DA5E",
+ "v0_metadata_nonce": "6F23E1EB5657CCE8961D23DC",
+ "v1_metadata_nonce": "B745A0F923AA18DE10CC11E5",
+ "v1_mic_extended_salt_aes_key": "8274C309B074B3A1D80E0D77AECF4897",
+ "v1_mic_extended_salt_identity_token_hmac_key": "443DDC3EB2D51ACBD8C79ED2B732946408FE79CC0336A21C5AB774B2373864C1",
+ "v1_mic_extended_salt_mic_hmac_key": "972931866621E2B8DD7FB76ABB8797C18B26C74974ED471F501102645DC76ECC",
+ "v1_mic_short_salt_aes_key": "E240E070654F3794C276D799CB23D5CE",
+ "v1_mic_short_salt_identity_token_hmac_key": "9AA904713C1F1146CEACD567C6BC4BC7B84F92660426D1FD633A42ECD3D4196D",
+ "v1_mic_short_salt_mic_hmac_key": "648A1D4915934BE8EA5C24CF747E2A17A2CEF1E655D98B0877F3B1DCF04441B9",
+ "v1_signature_identity_token_hmac_key": "2B3210B9D391E4D2CDA95368B8B66572975348748C382588AAF4664E2EFFC2D4",
+ "v1_signature_section_aes_key": "9FC3EB118E5472E3D0E1806BC8EEB6C4"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BC01",
+ "expanded_salt": "1945A447FF4F02934C6381466192FA3A"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "1AB857638876426CA721C616DE5BF65C",
+ "v0_identity_token": "F996D02678003CD71CE17004C2D7"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "FDD7",
+ "short_salt_nonce": "E6CDA2BF1E867E1C76A878A7"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "8A985AC6265F3067E13ABAA6218D6758",
+ "derived_salt_nonce": "DA89867F71A70412D2B00D8DA0454838",
+ "derived_salt_third_de": "A36B229A20A2A972401A843F84FA8D33",
+ "section_extended_salt": "967D99CE3EE6D79AE98B8037056760B9"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "94830D89A2B314388EF7B63C3C3F1D9C5558F07B1ABFF28FC336FB5F41079FA9",
+ "v0_identity_token_hmac_key": "727F82E28FC3F96E5BFE00A479C96FD8419921516CA1ABC2FD42C373FE9E328B",
+ "v0_ldt_key": "64A40560C4ABFF49B54A893522F75B2DB2A21BE79B44E7F9CAC3AD0E8E5FAB91BAFA76B2264EA081EE92DD94B6B0AD11295BACC6D44C9B7224E975542FE837C5",
+ "v0_metadata_nonce": "E1FFED6F1FBE0A7086DB29FD",
+ "v1_metadata_nonce": "1E765544661B31503FB0CC04",
+ "v1_mic_extended_salt_aes_key": "B3773653274143AD72C95F3C01A71D4C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "811D7EE92ECC15D14A2EB005C17F072BB331834EFE623F0E2EF5E042672995AD",
+ "v1_mic_extended_salt_mic_hmac_key": "025D81497467CE23085944DB9AD50A5B8BBEF3F5036E9750A8EE3801CEA18EB9",
+ "v1_mic_short_salt_aes_key": "10F24F181454ED4663CC803642768DAF",
+ "v1_mic_short_salt_identity_token_hmac_key": "6B42C12D243ABBB7F2236EAFFE0C1A8B1654E25E3CF6416677D3462DF7402062",
+ "v1_mic_short_salt_mic_hmac_key": "52EECEDEEF2758E036A9748E8BF06287F8C6E70CCDB6017C9961A97E64B26FD4",
+ "v1_signature_identity_token_hmac_key": "591CE684D72DA16E9168381A2A8167F409E83662AF6713F3F68D8B753DA3174B",
+ "v1_signature_section_aes_key": "240792A759473821A1D8CBF99AE54AA4"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "480A",
+ "expanded_salt": "73CA056DC334741E6E6567853BE9AC0E"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "C68D9064D5CBC769AA2ABBB035248851",
+ "v0_identity_token": "0CF9B87C144D6D444DBC98D3307A"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "A5A8",
+ "short_salt_nonce": "20358E029A4BA3EF97796505"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "002B67A8C992EAEBCA8259FEC28289A4",
+ "derived_salt_nonce": "F202A0CB1EE7D8FCC9BABB9EB6304EF5",
+ "derived_salt_third_de": "F44C487244901DE5D96ABFD481BAC4CB",
+ "section_extended_salt": "69167A8D033BBB5E257E729AE62ED6E7"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "98EB553FA5F60CCA72B5C7DD2C98E4FF839C728EEDA1A5B78C182CB94C58C714",
+ "v0_identity_token_hmac_key": "5D87D3A84F06E24BFE1E22E7E5FFEADABF6D583587B2615DC39117568E1C958D",
+ "v0_ldt_key": "C676CF2C50219632BF484FBCDBC3B6ED9BAF0114B03B7EDB3B4F6A8A3C977F07A72B19F74C71F800B65FBDB5147EDB38AFAF849B82BB7F9717DF1C1ED206F534",
+ "v0_metadata_nonce": "824779F6CC15BF01C3BDB03C",
+ "v1_metadata_nonce": "79B82382BAE70FE9F2C3EEEC",
+ "v1_mic_extended_salt_aes_key": "A1DFA7F844D8357A3E0E554770F26517",
+ "v1_mic_extended_salt_identity_token_hmac_key": "EBBE559CBF3D41AF04F599C3AC66A57C14A7983BB59805520E0F26BECAFB04FD",
+ "v1_mic_extended_salt_mic_hmac_key": "3B571385F9A85C437D7A0FDEF9193B643FB30A82C94FF4BEF03499E8FF8DE773",
+ "v1_mic_short_salt_aes_key": "7945B907207E26989E99CF22D75C5134",
+ "v1_mic_short_salt_identity_token_hmac_key": "F4C50FCBF4772A730A1A962A61DBA99993BC4E1FC823B09C591889A07B0848EF",
+ "v1_mic_short_salt_mic_hmac_key": "5BB027194D3274626B9F12F33EDF3894F48C74EC8643E979171F311AE56C6196",
+ "v1_signature_identity_token_hmac_key": "4606A5AE3B1A042E620FAE09883B0E2B60F2CBA0F55243C9E82BE0BCBA64AA4C",
+ "v1_signature_section_aes_key": "62ED38EF19133F282C78AD3BE7493419"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D77E",
+ "expanded_salt": "7224B61774E1B0F193E6E2B9C6828D47"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "40D0E2FF3CC0401794857BA46D4018D6",
+ "v0_identity_token": "2D00EC3B8F0F5E82C0FDF2ABEFE0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "DE54",
+ "short_salt_nonce": "FCF5569BBB730792EAC492EB"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "FDBF480AFE38C1A3B518C9E4E37DF73B",
+ "derived_salt_nonce": "D0AB883D19A80B9A9B0F71FCB3BA9C4D",
+ "derived_salt_third_de": "559EF43087D81A97644A1564939C902D",
+ "section_extended_salt": "7D6E587DCCB086EE382CDA8ECA378555"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CE5928B1C8F46246E5C922C80DD9558FA8AF4F213E21AFB8A99B0FEAEB9B56DB",
+ "v0_identity_token_hmac_key": "0899E9BB8C98AFAA6AC98097F66B0342806FDD2B90676D2C20107CD6947BD3AD",
+ "v0_ldt_key": "4134C4E3F15361F79134E2FCF5ECB398EE7E4ECB43A839622859BA72CAF476732ECD67EE3B354236EB64ADD7C0D2E0CCAB5E051D12792F39B8846616BF4A84DE",
+ "v0_metadata_nonce": "8566A1CC7A91F6A022B999E5",
+ "v1_metadata_nonce": "396A0AA737EA6C93E27FE7DA",
+ "v1_mic_extended_salt_aes_key": "800E76656036F4A04879808F114BAE67",
+ "v1_mic_extended_salt_identity_token_hmac_key": "FE24751061A9F50086411F85352EFF5B5DF0E1247998A203B33CC609EB63AB50",
+ "v1_mic_extended_salt_mic_hmac_key": "F095007E76CB193DA11718890BE7D735C9B57DD99C85E597893E9A51DD15A93E",
+ "v1_mic_short_salt_aes_key": "52A881282D67F6ADE798591223985FF8",
+ "v1_mic_short_salt_identity_token_hmac_key": "60CDFB8EDEB884516A7A3D8501E3357AFD42A77CD5FE6578D2F5957FDA03F5CB",
+ "v1_mic_short_salt_mic_hmac_key": "8555D441A574D3375E50F9A450022F4A982E8D580982908C7B6D81C628312968",
+ "v1_signature_identity_token_hmac_key": "E850671925AB258049D3E3A4822FD1C78A4D80F556FB92EB7D7B5DA01F5CE641",
+ "v1_signature_section_aes_key": "8A1ACA177E160A79924EB4D2C9435F98"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "AFB1",
+ "expanded_salt": "6D35C770B1F09DC2DEE7453C22EC018C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "23A208FB72F76B27842D0EF4590681EF",
+ "v0_identity_token": "3080D30C82A0F6AB7A5FA83675C0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "96AC",
+ "short_salt_nonce": "9BF830CCD7DB20F7A3115702"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "668E2A14D9B304AC23D0F56CDFE0726A",
+ "derived_salt_nonce": "866E7A3B3D3F0A094F8FF58C221754BE",
+ "derived_salt_third_de": "137E0CE6D82B8DE9AFDFBE0DEB447B33",
+ "section_extended_salt": "4AC4230A5F3B911F69A07DCE728586E4"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "A036E6CC7FC866CA0BE5B4C017CF177396E403F7D5CA8F94C6FF9DA7C010299C",
+ "v0_identity_token_hmac_key": "D85A9EF927E02B5A0ECEF8B1949846AEC6D7FFD049A465288F8BE406E63EEBEB",
+ "v0_ldt_key": "C95083F599D7D994F72142C844822652EC9C914F132AFB2CDA4C7BA88B4235A76CA1BC44FD42CAFFAA7A553BB74E93F30E4E873DD1348F99D0125577D06274F8",
+ "v0_metadata_nonce": "23D7F03405EED43619F8A02B",
+ "v1_metadata_nonce": "ADB6676920779A3F6D24F542",
+ "v1_mic_extended_salt_aes_key": "B3A11A9DDB232EC9634B28EB5DD002D7",
+ "v1_mic_extended_salt_identity_token_hmac_key": "E9E49F8A8FE50E066C83BAF02D9277BBAC5EC629D16FD5B02F90E04EF76E682E",
+ "v1_mic_extended_salt_mic_hmac_key": "0E5A3BCD461378A07659FBBD5E22AD8A658D3871FDA1B94111F5F468298A8D74",
+ "v1_mic_short_salt_aes_key": "C3B2251C9ECEBABBF766D5185B5F18AB",
+ "v1_mic_short_salt_identity_token_hmac_key": "ADF35872686CF343B3CCAC85D02789B9AE1F9D30A8DDCFF90EB87B17232F928C",
+ "v1_mic_short_salt_mic_hmac_key": "EE54C5BB9C1BFE150A389B0A87E4181694721FA52C7DFAD2012375D95356CDCF",
+ "v1_signature_identity_token_hmac_key": "D1E4984F45D313CD9FFBC84344861B3E4695CD514BED3150C16533E8D342CDE1",
+ "v1_signature_section_aes_key": "15EB95365271D866D98BD422014205B1"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "9BCE",
+ "expanded_salt": "CAB8E837BB60A1FDF5F164F1930B0E8D"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "42C1EF92D5E71149BCCC7B3B2237410F",
+ "v0_identity_token": "C3B8624C9BA609C1BDCEA9CF373C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8466",
+ "short_salt_nonce": "AEFEF9A66BCC84F652A6B6F8"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "62CA3E3C25D90BC9601B292D3DBAF36B",
+ "derived_salt_nonce": "DDFA02449C05C95B5D958B876CA189DE",
+ "derived_salt_third_de": "40EAA779A52CE6249681C6C2A6E33839",
+ "section_extended_salt": "9054B345A1B790A68CFF7CFC52D75525"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "71B63EB56B07CBC9322E666347CEA44BC4FC6344696D7D5F879E2B2538C6C0DA",
+ "v0_identity_token_hmac_key": "CD3092A8E4B648FD3DC6C80A449FB248F05934A116A775F6C70A9D5FD07E5A0F",
+ "v0_ldt_key": "3C2138F65AC20985A4BC677B4CF36F9D09B316E25506AAFFC407E2B72468B6BC71961D5958D4846793392C7389053BB7C248BC6E47269E9619098FB55D38E254",
+ "v0_metadata_nonce": "459816206C609FE86EBA6D7F",
+ "v1_metadata_nonce": "14B7E15A016D8BC3849BDE28",
+ "v1_mic_extended_salt_aes_key": "C6B3C93BB0063BB443EB0A4AC6EE4BF8",
+ "v1_mic_extended_salt_identity_token_hmac_key": "0D189A29519293EA6995D6658527ADEDF51CFDD500F4E602BEDC242740308898",
+ "v1_mic_extended_salt_mic_hmac_key": "2D65B2CD24E315B3B60237770E5F14AEE994E718C023B32BBAE93F00A49160CE",
+ "v1_mic_short_salt_aes_key": "C886A50B76F6FA70D653F47D58E32DB5",
+ "v1_mic_short_salt_identity_token_hmac_key": "73D1231C70DF32D46609A2BCC11E0F1C09298F772ED3C1ED61F3473F6B0D109E",
+ "v1_mic_short_salt_mic_hmac_key": "8BA22F5A56E0C7D945A43286C432875B2A8BA4D340B71FDB32A5078BACF81D05",
+ "v1_signature_identity_token_hmac_key": "8F3E043B38AD640DDB32F836B000FEB140E293FEFFE22B048DABCC6AD0D77EB8",
+ "v1_signature_section_aes_key": "F0B1C0499D7F735D789BF19C6B27BDA0"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "02DD",
+ "expanded_salt": "0559A2DDCA64BD2AC3BFB68B58D8D33C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "64E3B4DD353BD25E6A6DB0C693D3A38C",
+ "v0_identity_token": "615B490B1C2BD88CB66FDB5020B0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "C0A1",
+ "short_salt_nonce": "FC5A9CD5C30AE35F2439A989"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "C7C542850D51FC65A3748B637D4BF2B6",
+ "derived_salt_nonce": "E7BC6A195FD35BBBBD36890C84DFD6BF",
+ "derived_salt_third_de": "08B163B3C00BCF2302E50BCD54DE256C",
+ "section_extended_salt": "B045F1FC3AA558F7DB3436B43FE3703D"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "4E0E7EA2FD1505C0917AF77650AF066B4CA785C71E94EADFF9179A700B871B99",
+ "v0_identity_token_hmac_key": "F03B77CA61C2E4F3CAFEB1ACC40A5B6EC7DC91E4EA5A453603A31C7C15398FDD",
+ "v0_ldt_key": "E2F5B9301BDB44BDFDDEF6A186AED98E40E044EE0246823157ED03BEA1BDC2416BA43B7579E762141DB967AA5AE4D3A7B29E2DE79225CF58976B1D0A848253F9",
+ "v0_metadata_nonce": "E40E15488FD763B95BE80EEA",
+ "v1_metadata_nonce": "E27F419A42791059D8ECD258",
+ "v1_mic_extended_salt_aes_key": "DA459644331D2AB5BBFA36F4D7FF3C3C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "9435C376887ED2BDBE06AE6E216B20F3A5F513D5C73CF7A464FB00C96AF42156",
+ "v1_mic_extended_salt_mic_hmac_key": "EBA1ADD68E7A7175C6EA4BAC7C9DA02408DA8B42B079CE25883E286BE7D027F0",
+ "v1_mic_short_salt_aes_key": "B4FBAAC9FB28B31447917346BF960A6A",
+ "v1_mic_short_salt_identity_token_hmac_key": "8261D61215141838D5F9BE7B561917B4BE89A7CD558403E146FD5F9FDB232308",
+ "v1_mic_short_salt_mic_hmac_key": "776E5708C049603DE6CD23D46F5867BD4CFCBD68865DA033F76284C02248C5FE",
+ "v1_signature_identity_token_hmac_key": "8A10585EE8E9DE84E26A0284C4C0AADD7726DC54FCE6FB2196C6314661B8D765",
+ "v1_signature_section_aes_key": "1324A78CBC23F567A880B1975F0ED40C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "10EE",
+ "expanded_salt": "FD6A9A6E112D7D76ADDC2D8BD40B7E29"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "A0879258EB4E46C9AD228B720035C301",
+ "v0_identity_token": "2CBAAAF3C96B0F18CDB02D332249"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "61F0",
+ "short_salt_nonce": "615C3235852E9D1CD0063CE4"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "6272F7C2A41C3A15288E20DF6298EAD9",
+ "derived_salt_nonce": "E2F217DE0828333D9F49E122636431EA",
+ "derived_salt_third_de": "74DF8645F7FFB751482B84D2B291D3DA",
+ "section_extended_salt": "189063CFAF8E1915CCF88CB306E65B16"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "0C4BF3FFE9CB060E30C97ADD9DC99E4AA2E6EB6AEC723BF8BDAD409051D3BD37",
+ "v0_identity_token_hmac_key": "ABFB8A91549E636D07DFB7E57A817C9C2891AA6E626E38A3EE063248CE912F86",
+ "v0_ldt_key": "93A179BDCCA21151352CEF07195B0D8F8B7018E75078A0E1B99F7E4A0D239CC08059CA82EF69848E5E3894885A4EA80B7B664005BC6C1EAE6B93094FFD2129BF",
+ "v0_metadata_nonce": "78FF83DFB55958CAC1F5983C",
+ "v1_metadata_nonce": "7FB9A6EDE0C5D91DF8E567A7",
+ "v1_mic_extended_salt_aes_key": "090D4308933E3CECCC986F09A37CF87F",
+ "v1_mic_extended_salt_identity_token_hmac_key": "5A8BC4F150492B66307B1DDB38AE19E594AAA280FEC8EC9E79F4B1E3DEFFA525",
+ "v1_mic_extended_salt_mic_hmac_key": "1F8DCC645A797A805CF72D23FD6DCF3243735737BE0E11870614BD547C56D3D7",
+ "v1_mic_short_salt_aes_key": "E49F8D00B07699825E9F82D7A668F8D3",
+ "v1_mic_short_salt_identity_token_hmac_key": "9AFBB83B9CE4C2A0A1F865B4386E87BB31273D46BC1F5C272D1F2F098F46C579",
+ "v1_mic_short_salt_mic_hmac_key": "A68EDA18BF3D5CE9CFB3EEC57922F0E4EE0DA69C36F353C9302976ACA66CEF6E",
+ "v1_signature_identity_token_hmac_key": "55602CC889D8C5B0C8E2F37149831B6C97DB377B2168A8A06BC667C8D017AA29",
+ "v1_signature_section_aes_key": "9EC0098FC8386B2260A44033CAF969FF"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "FAF0",
+ "expanded_salt": "349DD2805CAD12CBD795101D47403486"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "901F6D216BEBF74D2D0E46E033634FBE",
+ "v0_identity_token": "B297A12E68BF33DB8ADA62316B4F"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "44F8",
+ "short_salt_nonce": "BA72171618BC1AE229E46B79"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F3B0AFF9A87AD9F157FCB595A0400440",
+ "derived_salt_nonce": "58B7445E6B36BA40A10BA36B5C1E2EE2",
+ "derived_salt_third_de": "087236B6E0C93C6153A061CE6A145D2A",
+ "section_extended_salt": "E574B5E9485189F792010872C55A1A16"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "ECE5B0557E2B77C7267F12D916A058AE7A989E2EB7E3DDA012EE4615DA3E072B",
+ "v0_identity_token_hmac_key": "51A45AC67195344FA0FF0F6B45A555E0113EF7A976E1371C38ABC1092A739AA4",
+ "v0_ldt_key": "0C857A8818273B2087858DC361082FD28F1A526DC3C8C17524294AE9C4B4369FE678F3D1ACF4AAFC6D2CAAF5E9E20EFBB5CBB6E4D42BBA520D244762E3569B15",
+ "v0_metadata_nonce": "2397ED85E3AA65D707364D55",
+ "v1_metadata_nonce": "81FE5070C63D916C065E8960",
+ "v1_mic_extended_salt_aes_key": "02F8434EA7ED25A95997308A704DBEAF",
+ "v1_mic_extended_salt_identity_token_hmac_key": "DC250FE0C182459E9502568122871806C76721D8EC15EA858823C6943A22FAF1",
+ "v1_mic_extended_salt_mic_hmac_key": "C073CA0A8FBFA53DE6D573FF2C4DC981C8567DCD41674F666A9B6F2A3E5DDBB8",
+ "v1_mic_short_salt_aes_key": "3CA3A347F198B2771543DFDA16EBF066",
+ "v1_mic_short_salt_identity_token_hmac_key": "526F4A2BADF226817B6CFBECAC622C76ECB29F08D94E76A19E0E5AA47E60BCC6",
+ "v1_mic_short_salt_mic_hmac_key": "B1BFA6EB1CF610F7ABAB39846A4096A201400C96FF365FA28DC17E21A10B4843",
+ "v1_signature_identity_token_hmac_key": "CDB40BBD6E8C6F09EACB8C49F6620036AF9EDADBE2C4DDDF4F1576BD16E60D97",
+ "v1_signature_section_aes_key": "89D7606A0A0A3BD01ECC6C5753B73976"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "9F8F",
+ "expanded_salt": "C440F5F693A391089F493578A3246EE4"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "08286E0B99391DA30EC2274DBB00E849",
+ "v0_identity_token": "D00DCF154C31C752B929FAF666BD"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "E02D",
+ "short_salt_nonce": "622C675E322ED508F3D36C63"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "18DACA43407EBFAC3F779E06A67455F9",
+ "derived_salt_nonce": "F82E736F62D198165C6D347EA4E39C6E",
+ "derived_salt_third_de": "23619B13FF4E31FCACFD529756674E09",
+ "section_extended_salt": "BEE23DC5EBEB75C788B766ACEFA64377"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "9E694C7731B4C8C077DE1E5233B3F6E8E47E436D920D8C4E4BEA39FEF681978E",
+ "v0_identity_token_hmac_key": "1A6329E5D9948D1DA2B988FF7A1A703222A085894926BD27AA92BCFF19563469",
+ "v0_ldt_key": "D79115F0BBD9AD968C1F99C08A1F6EE03997499BD1549F66CD1603B40B18FE15CB61057F6ACFFE7DF23628AA5D7A7E6A1AB3022ED735A0EEA7B025FC16897D6B",
+ "v0_metadata_nonce": "60D20D161EE6B97FCEE5E2DD",
+ "v1_metadata_nonce": "42876252FC40CC971CD39A6E",
+ "v1_mic_extended_salt_aes_key": "584DD6D94E5DB46E5EDC4BE2B854368C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "0E71CD49557CD6C9CD914B1624E2880188F8ABDB142E546C4D04570FA606E3AD",
+ "v1_mic_extended_salt_mic_hmac_key": "07863900E27135BC852442C80BFCBA09FE418A460F91DCF30F88F194F2B15DE5",
+ "v1_mic_short_salt_aes_key": "E0DA5AA00A18AB165C15005E75A02F7E",
+ "v1_mic_short_salt_identity_token_hmac_key": "C6870BECE7AC586F61563E3FA8F460728218E93644B40E0DDDC621A01042FCC0",
+ "v1_mic_short_salt_mic_hmac_key": "CCBA93DACA9023B7633E5408DAD5EFF1FBE3A00E9F76E9AC8507DE5E651A5FD4",
+ "v1_signature_identity_token_hmac_key": "E6A09F1A28C2DE26841044AAAC67C4CEDF963992767C960796E204BBA6B61432",
+ "v1_signature_section_aes_key": "F610CCD8C43EF4D6E738CCD0C1C24C09"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "1B22",
+ "expanded_salt": "95D2C439CAE94171D8F64ECC4D79CED2"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D5D6FD18F488483BED09863555AD3BA3",
+ "v0_identity_token": "3C7E4793630A8229E8D7E2337E04"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B898",
+ "short_salt_nonce": "D983D29159D24108F06DB7D3"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "67BC64977B228888CC5CD6466E3112A2",
+ "derived_salt_nonce": "44279BC1027CA9D501947166840CF2AE",
+ "derived_salt_third_de": "D656A3294C7E089F94ACF3FDFE93D463",
+ "section_extended_salt": "D482C2A6D420C5F6993527865FD38E45"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CE2C5489AE9BBD4E63911BB5D51B8EDC726A6F30557C012A8DD37206DCC4DA0B",
+ "v0_identity_token_hmac_key": "8BCA9E29B97BD9610DFBEB35DF02261C16A3A6E7AF8EE60C45E7A8EC00057F6A",
+ "v0_ldt_key": "51A6880BFA961E52F8961CD397D3905AB3EF02B6431394390C330CB0480AEF3B48F6D02CCB8E7496985B802F13254AE6747E5AE585C8D0D390E81A17406199C0",
+ "v0_metadata_nonce": "0AACCDF41FBF33135BFE11E8",
+ "v1_metadata_nonce": "04411E15C45DB0FB941F1B09",
+ "v1_mic_extended_salt_aes_key": "31E9CF730E31A1A56C75624790869DC6",
+ "v1_mic_extended_salt_identity_token_hmac_key": "400E94EEFE9F40AC2761E04EF84D4C9A5506AF2BCA87F1FFC3C41DB0CE42EF6F",
+ "v1_mic_extended_salt_mic_hmac_key": "35AC887D2973BF40F73476F789E095A220919AF1C4A308A20C4B72957A6F0847",
+ "v1_mic_short_salt_aes_key": "18A8B80F7FFE5B3818837D04BAF23FC8",
+ "v1_mic_short_salt_identity_token_hmac_key": "5CD8B34230B6BDED50B42E1EAF30F46136432AA2599F66A4F7AEE7442E974BA5",
+ "v1_mic_short_salt_mic_hmac_key": "91AC6D599B6D5EDDF95472D946A8C60292896C395DF3216FE6B0297BF0FBC890",
+ "v1_signature_identity_token_hmac_key": "848F82B20E686C242A2D7F1933E0CD872DBBDF1E7B436856F19424BD47078DD3",
+ "v1_signature_section_aes_key": "7A88551E0D0B4C248BD88C7214423C1F"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "7DAA",
+ "expanded_salt": "8B186389B95F08E844499318AF2CC0B0"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "558D0863258D8230FD3C931CD2EDBF7A",
+ "v0_identity_token": "2713C2F2B47DFA957381C10C2649"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "A20B",
+ "short_salt_nonce": "412810F614DD5448E7BA6171"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F613A207D445ED2EC7CBE2A5787EFE60",
+ "derived_salt_nonce": "92A3862125E69F44E8E6087DD72828B6",
+ "derived_salt_third_de": "54C805F3DE7A3652271EBD5E097A9D95",
+ "section_extended_salt": "8D5F11C001A419648067D4A1966B0EED"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C79A63177DA5F9CABC80DA27464F9407A50F686B9253CD8D6CE16A2FAAD90DC3",
+ "v0_identity_token_hmac_key": "154DA7DA9EDCA6AB3B336D1BBF3A3DFC2B959C76BB3DC530DC336469A22EE49A",
+ "v0_ldt_key": "AA7A2CD44C71098E3F94A8B0155650502F257681BDC8B856C7B2AF5B1136D96F86089FF3719296C183DF56484D0A688308536BE2EEF9FC667E15BDC4D3BB0279",
+ "v0_metadata_nonce": "2FB6567C04443950D5F10C82",
+ "v1_metadata_nonce": "A847F747EFE0FA2F8596B2BD",
+ "v1_mic_extended_salt_aes_key": "855D9EB68E68D7AAEB46C71C66FC1BC0",
+ "v1_mic_extended_salt_identity_token_hmac_key": "4FDCB83D8EF4C5AACFF25300FADB3816408CF671D9874FC3CAFD8ED6755B3C0B",
+ "v1_mic_extended_salt_mic_hmac_key": "CD6FA52AA997B94740B8645D647103C671B5795BC46F1E12B7AEFC7067641D96",
+ "v1_mic_short_salt_aes_key": "6B695E1C8FB3DFDF4C1964B4B3424A03",
+ "v1_mic_short_salt_identity_token_hmac_key": "900252ED6385B4E457CE563A5E5FC4BD39784EA4BC64958349E7CD427A68493C",
+ "v1_mic_short_salt_mic_hmac_key": "72DDECC2AB00222B3C70A9B343664B901614F01CD2E7033934DEC4077D6EC14B",
+ "v1_signature_identity_token_hmac_key": "05CB39213C947B9C4D82F311372A1780E4BB4AFE8480747841B0A681FF092A0D",
+ "v1_signature_section_aes_key": "E130CCBF8595EEFA23A6925AAD6E394C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C2FA",
+ "expanded_salt": "5B94F9CB6A7867A0D27C9CBDF4B0EA73"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "7EEAF724D0D00C551EFB2985D1E28519",
+ "v0_identity_token": "FF3A952F373296C0F260CAADD55D"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "6B11",
+ "short_salt_nonce": "9DCF2866433ED70F26A6DCE4"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "8882901B8F1F333196F1B78FC5D012C1",
+ "derived_salt_nonce": "EE7A39E6A119642C002E260A972369EC",
+ "derived_salt_third_de": "20B064790320BEDAC44CE80C37B4FCC4",
+ "section_extended_salt": "1E7F5C402A5D4994A8188E52A0AD2D72"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1C745DE11ADD00D3CA19D37B5CAB3D60F5F86659B1848A11D3059872B376BB15",
+ "v0_identity_token_hmac_key": "E08EA49AC02F69DCAA441DFF1DA7DE2181202DBC15F006244458C2431E4DBF90",
+ "v0_ldt_key": "2E91782584FF49C855E1B842594481C6DB3496D21E19EE85CC8A1FEA83FB52D68CA22FF441DD68F2EAE28636AB143D3A03392847E766C70737357B2EDAF35D8A",
+ "v0_metadata_nonce": "36DF9D6DD2D171BAC182D212",
+ "v1_metadata_nonce": "0AC3126A538404024CBDE6E8",
+ "v1_mic_extended_salt_aes_key": "7DA766C835B14E1AD6352D8956C0B606",
+ "v1_mic_extended_salt_identity_token_hmac_key": "3830C1826FF962656DF74B541087104929EA9096D1632516E560208BAFF950A5",
+ "v1_mic_extended_salt_mic_hmac_key": "A88A2984350349201CBA4531C95928DD34D2536CDC6958D6EB77A992AE1A3815",
+ "v1_mic_short_salt_aes_key": "ADD9E7D962DD812FBEF7D19E09E5C6E4",
+ "v1_mic_short_salt_identity_token_hmac_key": "44B9B99CF2B3A3514BF22123387F8D45F2197C71348B8FC3EE885A875AE10451",
+ "v1_mic_short_salt_mic_hmac_key": "62EAB192B0DD022F91733FB357D7DD912C94EBCB45B91F04AA5C0C9A9E7A85BE",
+ "v1_signature_identity_token_hmac_key": "A427FEC4ED745D0353E0B24CA11D69CE4FFC5117FA26F906B2ED023AE806B854",
+ "v1_signature_section_aes_key": "6A4CA8910A38C31640CD06D2045E2D0C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "0834",
+ "expanded_salt": "A708695452CF14D8E469B91F26BC7E3C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D57B964F7DC6F9BA1061A25550D8693D",
+ "v0_identity_token": "F3AA301AA094B20B2B0E7A02BB81"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "766E",
+ "short_salt_nonce": "FAE06666F8180F410474F3F9"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F6BF0314DB3A1C1330A8E6E9A2CE5E7A",
+ "derived_salt_nonce": "7D5985FCF0EC057383CF3BAC7B113A43",
+ "derived_salt_third_de": "84F6F682DE9C87BDD9AABFFCDC14A822",
+ "section_extended_salt": "CEE571EA0F50EC647161523CBC93367E"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C767661E4DAD8FDF897BA00727A98FEFB87AC252BC0975BFFF3FC4AE3844FA89",
+ "v0_identity_token_hmac_key": "652640BD7236CFF84A9E87D57775FA4A81F7BEBAE501AF8B64AEDC0C844102E5",
+ "v0_ldt_key": "3EE26E3AD6244AB6720D572EB4AFA66A6B4F474E911DD9795E9903BBD90B8D2ED94C2F7EE7CDD0D66B9B092D40F0AD1E3EF53D2D959ABA9EDF561A9F7E3AD675",
+ "v0_metadata_nonce": "4A57C7D89DA48A086131D3C0",
+ "v1_metadata_nonce": "4746E50ED394092187E13D8B",
+ "v1_mic_extended_salt_aes_key": "B487D5205DBE5C0CF663BEDA55163823",
+ "v1_mic_extended_salt_identity_token_hmac_key": "114B6C0BEBA4663ED08D6757606B528F7C3256EF2BE148F7BF75F6DC401BFEF8",
+ "v1_mic_extended_salt_mic_hmac_key": "BF34BAC8C099EFDD3BF41C051675CDEC259C27786E50CD326FFD409AC8ED6026",
+ "v1_mic_short_salt_aes_key": "F3482440016A1E6CA2E1C79EF3B9F3B2",
+ "v1_mic_short_salt_identity_token_hmac_key": "BBB7762E694FF6DC4CA9F31A537094364495BADCCB73FC69327C86D8A84FDBC7",
+ "v1_mic_short_salt_mic_hmac_key": "E35BD2293E90BD3AC97E98C2983EAA7B7F106AC55B3D88D332539F928CDB8E09",
+ "v1_signature_identity_token_hmac_key": "7F9ED591367A0EB8A4F23D145BA75249FD5842B59E8CF8C8BB9E69E942E555AF",
+ "v1_signature_section_aes_key": "955D996A026288A647EA707B0A33C9EB"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "B490",
+ "expanded_salt": "F5A6423790B75B0A73E26647F83E003F"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "1143418D5D928DC46A5764F53E7065FF",
+ "v0_identity_token": "5A6EB28E3F9F076AAF47F1AD6F52"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "5B71",
+ "short_salt_nonce": "446675E4C5503E587A7ECD0E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "CB1D2C8F670DE3E029FA9F91D0FC1494",
+ "derived_salt_nonce": "F82D6616C9669EC7708B6C085A45E8F8",
+ "derived_salt_third_de": "8ACC53A66823593B9F10479985B6D9B0",
+ "section_extended_salt": "839CE97E9C32C0C81368ED8F8057FC02"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F8D48367C0C15E86ABD63D96C632504F7ED68866436F6CF694D7926BFDB460E6",
+ "v0_identity_token_hmac_key": "02840A91CA2DB99828CA95C4A6102EB14D28554B01ACF4EDB70A8CFAFD0ABF1D",
+ "v0_ldt_key": "DDFB10BC34B1A507695E663B936379D7F8F5E3A58960B0D54D286752784414F4AC7E3D86F480BBE83F3D43F99E45E2787A57D234D26C43881BA12BDA5B8A84F7",
+ "v0_metadata_nonce": "31DF1F26F5C80D57D312E8FF",
+ "v1_metadata_nonce": "EF1FE145CA3643D332ED685A",
+ "v1_mic_extended_salt_aes_key": "681A2CB23B847D46E355E0625988C8DF",
+ "v1_mic_extended_salt_identity_token_hmac_key": "CD02ED35449659F983FB2070D2D353311FD04A1529DF128F097FB28447898FF9",
+ "v1_mic_extended_salt_mic_hmac_key": "26B0F39B6880F40FBB6D006D3FDF20FA75D61FE70A21AA279295303AEEAAE57C",
+ "v1_mic_short_salt_aes_key": "A0082298B9261FA98FF77171F7FC6D35",
+ "v1_mic_short_salt_identity_token_hmac_key": "DA9EEED06B73B51582DBB749CAE10B30A072B4CFFA13B3055BBB0DCFAE423D7C",
+ "v1_mic_short_salt_mic_hmac_key": "28D6FDBDB521166652ABA223A3FB626DAFB5E5600D72B7EEBCE1A95E1E62CBAA",
+ "v1_signature_identity_token_hmac_key": "6A82842B2EA2C3C17C26B2867FDCFDC4733F67D4486CB92E1436B282A2E63AED",
+ "v1_signature_section_aes_key": "066127DEAD9D2611AFCC7B6216F8F180"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "3820",
+ "expanded_salt": "ADCD23D7DD53599418BFA63474D69B5B"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D886612612F2CF8F0C8D2FEC71A2FF37",
+ "v0_identity_token": "63DA95A649039DDE7129B93519E8"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9A3F",
+ "short_salt_nonce": "7D16B77869830EE92A4EBFC5"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "659B8A721546530DA9795AF4F85F3172",
+ "derived_salt_nonce": "C86E1DF850ABF4050CFF5069AF064842",
+ "derived_salt_third_de": "5409D2E3012D6087942D9C6A9AD01055",
+ "section_extended_salt": "618434E133FE816E6B612F6CA5057231"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1908DD830FC3A7EE0E0FE2B559BC1DF6B5C80F9576452FCA38995CED1EF3D9DF",
+ "v0_identity_token_hmac_key": "3CEB70A041FC1EA8969A7FE0ED5C0B26919747CE6E32793B7928D14934CF1921",
+ "v0_ldt_key": "82B1C998FD20CB2053674D3BE231763B9B4445B16D39E23C054985F315717C2D842817F74EE526D4F3CB50FA7CCEB30C3DA0B5DF9D39B19A8E51917E56905CBF",
+ "v0_metadata_nonce": "DE3382B2F3E85062C9C945E0",
+ "v1_metadata_nonce": "73FC91F971F797CF852BD47C",
+ "v1_mic_extended_salt_aes_key": "7479E783DF7D3F949C85D44150538152",
+ "v1_mic_extended_salt_identity_token_hmac_key": "4E8FB9F60DC947E7E6ECCD42D235842453C070432703EC381BC44F65F17A944B",
+ "v1_mic_extended_salt_mic_hmac_key": "081D31934C99EB52072EC7ED6D5DB9B238E8E9E6A1E66F612C3A53CE664895E5",
+ "v1_mic_short_salt_aes_key": "87B5CFFAF5E8BF3F76F901E8A8167EE1",
+ "v1_mic_short_salt_identity_token_hmac_key": "02926351AC11AB30159026DE19F8860825CDDEA95AE3B4054564EE4F42AAB436",
+ "v1_mic_short_salt_mic_hmac_key": "E7B62E504AF1F2EF99A86EB37FB14AB5642FCAA0EAD4BB0636D65A41B455A876",
+ "v1_signature_identity_token_hmac_key": "8E1E4E0D0082011E31322CF3CCF5CB6DD94F041C529255A3E96215C2EA887B86",
+ "v1_signature_section_aes_key": "113BDF8FDEB7FDDC45EB8D0CBFAA35DD"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "34D8",
+ "expanded_salt": "E1726AEE6C32008D70E77FA3CA10A3D5"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "9FA9C4CEEB36C5D01308572338AA4DBC",
+ "v0_identity_token": "4468295C7F2D6B52CCB9519B5C18"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "51A7",
+ "short_salt_nonce": "B61ACE6DA49F07333D36D94E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "B2DB55B0EE6A19591335FD4A004AED74",
+ "derived_salt_nonce": "A18DB7BB4DEB0BAC4C300C1DFF08300B",
+ "derived_salt_third_de": "65FE8535564AE2CFB9D3D19CD5F1DF30",
+ "section_extended_salt": "FC87C8E278F6CF79DFA952B70D3804CD"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "D9C3778AA9B5E3B681176C33F23D930EECF65E3B03F57383173FF1C961C43632",
+ "v0_identity_token_hmac_key": "6D9F5B36A298BC2BB69628BE19C027B5B82EA49BBF39938CA796BFFBA80BDD6D",
+ "v0_ldt_key": "515D7D78685E974EFEC733637B866911EC2DA076275B073B53B8474C52B4EF97A0BB4BE23CEDD04EDD320BE099E42C17690B9FE34543D0BC56F10E706185C735",
+ "v0_metadata_nonce": "294F93F189066B9962BE5F28",
+ "v1_metadata_nonce": "7C2775AFCE63CDF40320A5D7",
+ "v1_mic_extended_salt_aes_key": "3083165096C985AFD9634D7C8C27B241",
+ "v1_mic_extended_salt_identity_token_hmac_key": "072CD33806FF7BC19C06232406E694417FC54B2A5CFB07F7F6B8E9F41B05CA5E",
+ "v1_mic_extended_salt_mic_hmac_key": "6787832FCFCE8782338608C8F35419AC877A130B4AA7866A3C7CB22ABD67179D",
+ "v1_mic_short_salt_aes_key": "A3798AC54A640D75DE9460BFF32D5A5E",
+ "v1_mic_short_salt_identity_token_hmac_key": "43DADD838D1B76E2EAE5A94FB1B839173FBD84CA47BC35CC2AA508D9D3516823",
+ "v1_mic_short_salt_mic_hmac_key": "F92977DD9EBAA721832F6E5D0CED0E29F940847AB0FB87494F323EC770EAF6F3",
+ "v1_signature_identity_token_hmac_key": "28A9E655ECBB19E0C72E389AF86D18CC1DD99B837CA39F80EFBEF46562ED30DC",
+ "v1_signature_section_aes_key": "5882688026AFC05D0A53C691D3C205AF"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BB77",
+ "expanded_salt": "5EEC79CBDE9B59FB7CFA09BBD4C21F6A"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "9C80752325978A05003338C9AA98CA51",
+ "v0_identity_token": "CDCED4F23EC9AEAF9254F5851E9F"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B8FC",
+ "short_salt_nonce": "C4625EB21060C7AC6EA7734A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "2040080121468E2437D7C4AF1AB57CBF",
+ "derived_salt_nonce": "ED3C0CD523D93752269A7AE558DA70D1",
+ "derived_salt_third_de": "7EF0A5B6DB0312484B90580CC5CCDBF6",
+ "section_extended_salt": "DD49906314C2165F3AA4887C7C2CBDE9"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "BDB42D1F4E1C41E35B00D54D726D90A18D9EDF326C5A95792C6A8BCB47F3D8DC",
+ "v0_identity_token_hmac_key": "4DF296ADF1A25ACA84D578855464E8A91903FB5FB2925D4F7AA4EEB667C3F514",
+ "v0_ldt_key": "A34CB3B18ED974E8C932C3F776D8D640D044E8EB23395507EF2E27143DE60549E44A2CCFB545900C84020984F1CA4ACE171E2150CF3E37CEA49128423E96EB6D",
+ "v0_metadata_nonce": "4007F919792DE5E3D9E35D6E",
+ "v1_metadata_nonce": "E95F4B6766CCD3571F404E51",
+ "v1_mic_extended_salt_aes_key": "5355412E0561A0BC09520C23F88E33AB",
+ "v1_mic_extended_salt_identity_token_hmac_key": "8324D08430C2B565D5E4E3FD00068564C096FCEFEAF026A714033726242A6EB5",
+ "v1_mic_extended_salt_mic_hmac_key": "80025D8E9667BD088B5F9D297EEB6AE6323204DED5D6A5823E28896F58D703A4",
+ "v1_mic_short_salt_aes_key": "3FB967135677C8DDDA512EE813CB7143",
+ "v1_mic_short_salt_identity_token_hmac_key": "E9A7AF77D3A9368BF553BCA5721EA1F9981877501C5D999B437FCCF1E92086EA",
+ "v1_mic_short_salt_mic_hmac_key": "7A93B87E26BF91DFE19D314D0D1E50B85CCE0BCB90AA127706A328F927092721",
+ "v1_signature_identity_token_hmac_key": "39062B01DFC854FE594F8D6542FA644CD5C969E6F227511F4865D974CC6DEC2A",
+ "v1_signature_section_aes_key": "4B1167F08673796EC85DAFE62137B809"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "F252",
+ "expanded_salt": "EA39B41EE8AE4A6EA4EEA497AEA49449"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "53559C87298B9802AA805237D5652703",
+ "v0_identity_token": "CEFBB6A76E7EF5CDA4D26ED815C7"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9E68",
+ "short_salt_nonce": "0956F02109DC68655CB62A5E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "93BD8DE56900BCEDD84B9A1978AA94EE",
+ "derived_salt_nonce": "66881A93AE754517DC4D61AD12F5E742",
+ "derived_salt_third_de": "BBFD5FCD7F36BA90D88A9A092F8ECA29",
+ "section_extended_salt": "4D1E91C6292D4A910828E53CA3F09EE3"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "3B47B274E1880F0D735A3A461608C79800450B43A7CF5144AC1106AEBAC9826A",
+ "v0_identity_token_hmac_key": "A45E22C2CEA0F70D106AB51893CA33D0DF68701EAD7AAACD3D5A9942FC5F0DFB",
+ "v0_ldt_key": "FEA32307FE627BC3C5D33D748ED4A00AD9002CA2B10EB72F85BDF82F0275B9583B73FC02ABEC26E891AFB24C340EFE8EA4C27E7C4D28FE44ADA6BF10E899F561",
+ "v0_metadata_nonce": "6E5B371C46E3D16E4D5A66BF",
+ "v1_metadata_nonce": "7F261DF35ACEEDAA4B576F1A",
+ "v1_mic_extended_salt_aes_key": "BC74140188830CF38B8C241095BEB16C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "385EE3B943000B9ADE0DEB825876F9F56EEECB6A72A0FFE15FA2FA958B1AD6F9",
+ "v1_mic_extended_salt_mic_hmac_key": "4B68A5067578BC2F7618F8B47F1FB64F3D304FFAE521225A895555BA5D8D9340",
+ "v1_mic_short_salt_aes_key": "DE089E6F3B702F1BA314CACA9E7F2788",
+ "v1_mic_short_salt_identity_token_hmac_key": "B2B5C5D2DA5C6FF0E1AF067248893051884AC530852A1EDD47CB494FAFFE06A1",
+ "v1_mic_short_salt_mic_hmac_key": "0263DBCBE0F69B101A639B2CF16346841E5ED159FAC9DCE93F92019A207D5819",
+ "v1_signature_identity_token_hmac_key": "E9F139462C5CF1CCB22E216ADB16B13C04206D39DABAFAAD83C342010BDCDD78",
+ "v1_signature_section_aes_key": "2DDFA0C2E734D9A8698821320CF1FE8D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "3D53",
+ "expanded_salt": "5D92CE2F393EB11F68AE3399C3C6AA13"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "6541E71B9A62F202963E4C541DBE6DE1",
+ "v0_identity_token": "1E65BA9B2D61AF735D60781F99F2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3F94",
+ "short_salt_nonce": "85714E38445BE9A4C2D012CF"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "A7C1B418774DF806054C029FA82533F7",
+ "derived_salt_nonce": "4919EFBFB04402814AB0C6A805820947",
+ "derived_salt_third_de": "C55544C75B968C2EAAD88699050D4362",
+ "section_extended_salt": "2BE31AA1F7D93AB925E36C8E96D2FCC3"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F13F7BA40A43DFB17FB31FA4EE756C48B9FD924F19EF3A86CA524B838A4ABF88",
+ "v0_identity_token_hmac_key": "280DA0042A5A21602B1D11DCAD91AC32691973312481855D05C221E4B3CD4B20",
+ "v0_ldt_key": "AF35739784D80E88F6AA2948111E905B95DE18AACEF41358A1A1C99D9C95BC67D5A62523FAA0E929AA7F83479F1A5D30FBB8E349A04A085F5AB28562B3BBC681",
+ "v0_metadata_nonce": "0A9504BB121E12DE3E8BFEFA",
+ "v1_metadata_nonce": "C63F427096971F1752F6221F",
+ "v1_mic_extended_salt_aes_key": "01EC1263EDE7F6EA26031C28ED8E6EC3",
+ "v1_mic_extended_salt_identity_token_hmac_key": "58C76F2F174E8B026E32BA4A09896898E39A21A4B4C6AFB5CBFFDD3F17217686",
+ "v1_mic_extended_salt_mic_hmac_key": "59DD79D819E0C6E50E4189CC394B7FDE1D1AF17E29C9EEC63727F64430A1DE9A",
+ "v1_mic_short_salt_aes_key": "AD577ED2A071A7EA5BE2DBE3D9440CAE",
+ "v1_mic_short_salt_identity_token_hmac_key": "E6A27A0F3EA35DA104296F11B2D3D7104DCDD066FDD3930D2A8B4370C0497F27",
+ "v1_mic_short_salt_mic_hmac_key": "F5D81846C62C536E3D6B19F3A33F6DAB14C708EA183E6D598DABD4D567DB2C21",
+ "v1_signature_identity_token_hmac_key": "03BD502076C9F2CA53775BB46DB7D0120297DCE95C9D455EBF0D5C588A31FCA7",
+ "v1_signature_section_aes_key": "8559B5ADD92D397DE221F606DA353EB6"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "5B56",
+ "expanded_salt": "0F102F204F31D295E3B9FF1956F387E2"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D6CDB0E747062077D2AAAD00D039B656",
+ "v0_identity_token": "EE348B9FE43A8F854A90FD246EA3"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "F5EC",
+ "short_salt_nonce": "A1FC444CC695E3DA1BB17AF0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "04AB6D4EDA19FC328F24C74CAC5C5DD8",
+ "derived_salt_nonce": "9331647748783F90E401965AC5B87106",
+ "derived_salt_third_de": "42CC023EEE82C7E84914B2E8190BF169",
+ "section_extended_salt": "B877CD0EC34F48EF8AA9E00297D82C64"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "B6400810BB927EFD733610B7E06F0D73DF1AE94274346CE0AB15CF95EC2A074D",
+ "v0_identity_token_hmac_key": "663D9BFAC9D198A1874C1AF13E986B22D94CEA5DB82FB8CC26DB95BCAA78C363",
+ "v0_ldt_key": "52C970B142592DF27DE130EF7C1D51F6BF2D191E046FF815A1C340AD8A10CC7D1C7A917F1989706C7E1AF8749BF7C2E97388BAFFF56EFB7DCDCEDDC3DFE1B42F",
+ "v0_metadata_nonce": "1340C3F2C220EAB0864590BC",
+ "v1_metadata_nonce": "739B0EB3925CD78302454F25",
+ "v1_mic_extended_salt_aes_key": "983C9CBDDD7F5D76D9D501819218974B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "A07289F3FCFB896BDE3289DD42B12D30C2440FA3A556DD58F7C87C305CFFA533",
+ "v1_mic_extended_salt_mic_hmac_key": "41DE5A06B3108EFDAFD5B8072E5438D0D411EC26C46C2EF62742D31E7601442D",
+ "v1_mic_short_salt_aes_key": "2A3B1E230B36FCC470FD65299A7EDA9E",
+ "v1_mic_short_salt_identity_token_hmac_key": "CCA9DE895F08980C2709A0FD4CF1B835E915BEB5E5BF192D5D30AC918E100C75",
+ "v1_mic_short_salt_mic_hmac_key": "80139B754D19E3896A1E1A5025DD04FC8E699B879484D8294A77EDF648E5643B",
+ "v1_signature_identity_token_hmac_key": "C6D68149007593DD02EE8790467405844C978F9352DDF2545C813022497DA7D1",
+ "v1_signature_section_aes_key": "738E9ABCFB9D5461E3F8E249C5BED287"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "77F7",
+ "expanded_salt": "999BAACA7F0F4EC499FB4984FAD96C5A"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "0800A0075D6EBBB3D36CC9E504DD12C2",
+ "v0_identity_token": "4F53F51F11499E9B94A03C1A12F6"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "FCB0",
+ "short_salt_nonce": "7B035FDE619F1DC6DDC82276"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "CF464723DEB71D8CB55827A0DF0D10F2",
+ "derived_salt_nonce": "5DB21C018408C6854005F5854F4FC0DD",
+ "derived_salt_third_de": "4F8C68AF4DFC9F31706823CEC2CFC31F",
+ "section_extended_salt": "F6F7A20A1113FA0CBADEE03D8737309C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F100C4BBC5B202507F057930DF27C5920882EA60BC5A770D33793133CF247746",
+ "v0_identity_token_hmac_key": "473297E18614DEF67B65E9C7857176A793754ACAA1530102AA81A082D58F7D02",
+ "v0_ldt_key": "1BB3499572A9AAD2C719A8961D95A1040DEE023D5933CBF52938A2A4880C5339C7EBB4F54DBD9697FF470A5F50171C223707B568E48CC4287DD309A855912E11",
+ "v0_metadata_nonce": "FC4F23D0384FCF4830D1E499",
+ "v1_metadata_nonce": "0AAD6D64DE1D90C577F60248",
+ "v1_mic_extended_salt_aes_key": "17A86CACFCE67DCCCF875B0AEA29A5D8",
+ "v1_mic_extended_salt_identity_token_hmac_key": "93DCD02530F3C29DB62667D5FF2FF8C5EC81341A7F642C0BAAF3D16B82E051CF",
+ "v1_mic_extended_salt_mic_hmac_key": "020BF714AFCC97E16CFED3A9CEE5490B0C72B649DADCB7F0D31E1B9EFEBC048D",
+ "v1_mic_short_salt_aes_key": "C82D0BB3858BCF0818755B90B87467AD",
+ "v1_mic_short_salt_identity_token_hmac_key": "99700748DF89599EC8CD6A0464EC084651BD335DD8D8D82956E405D0994F2325",
+ "v1_mic_short_salt_mic_hmac_key": "FC3B070CECBABBF42ADE9193735C6D66322A12A1C3703C59194B823E5BC460E7",
+ "v1_signature_identity_token_hmac_key": "700DC0F4F8D9AC2B6A190EC7D041F0E6143C99CBB4C39C83419C5CB2382504CB",
+ "v1_signature_section_aes_key": "1D268051F9FCA0FD696862C2DD230F97"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "0739",
+ "expanded_salt": "57E814971788FDBAEFD41AE890DA236E"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "07F23FA7ECDCFFFFC98A7B46B0382C69",
+ "v0_identity_token": "92DEBCB60F3BB1E5D5D3BE1FBED2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9A12",
+ "short_salt_nonce": "BADA73EFD61495DD37336600"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "22820FA9A35165D2ABF6C7C256681574",
+ "derived_salt_nonce": "67DC58AD06F080D8A671163E36A4F0F1",
+ "derived_salt_third_de": "B5DE19F288B57D8338FCB5134D7FE17D",
+ "section_extended_salt": "14C2765287EFFFE0153EF93894134505"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "D0E768CF45FC018A6C3B9B78634E0D8ECCA218220BAB479F14327CBE273AACD8",
+ "v0_identity_token_hmac_key": "7706A0543B4EB81B1555D989161EF86F617DFE7A93F87EC62D239709DCE3F2BD",
+ "v0_ldt_key": "8B3422872ED8BA90E9378F20B5C066846358D7238979499D2E32DC657C359C0511BDA2624B8F7F1C6BD93C08A7DA716035D720DEBE02AC0A3F9E0CDFC8B979FD",
+ "v0_metadata_nonce": "69E6E6255195E8ABF8C191DA",
+ "v1_metadata_nonce": "2A6B45C6C1A4B8B0AFECD887",
+ "v1_mic_extended_salt_aes_key": "DFD9F7A823818E211715841828D9EDC2",
+ "v1_mic_extended_salt_identity_token_hmac_key": "AD329A4E049CA3B4F621DAF087A88ECC5B318AC36D92EB3604ED1FD7AC997DD2",
+ "v1_mic_extended_salt_mic_hmac_key": "C4C4E9B64AFC367473E38D66B110403284C3C03AE00F1BBADC230C93D5D97BB7",
+ "v1_mic_short_salt_aes_key": "7365641B35E3A6A5863106192EE1E1D1",
+ "v1_mic_short_salt_identity_token_hmac_key": "F4DB33EC5EB13864F6B46DCDAFA9399E0B5F17C111D275C9BD906FC46D45D38B",
+ "v1_mic_short_salt_mic_hmac_key": "107A3B99DFA9D082BA9C5A52D066F0517EB0448B4CD3CE2671D6E191E2E2ED08",
+ "v1_signature_identity_token_hmac_key": "67E13E77F909D2E4A54AF23DF1319098A1CF63EC9D69ADBE1C1993CDA198AD7A",
+ "v1_signature_section_aes_key": "0CCE0847357476165E32DAB0D93660A5"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D429",
+ "expanded_salt": "B293DDC05C6AE00B98174666AC83A92B"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "4AA95B37D4A63A1DC834AE394C30EFB2",
+ "v0_identity_token": "B650B408B882856F757A55FC2AB6"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B35D",
+ "short_salt_nonce": "38893FBF7D1BEE182635466F"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "70EF8C20670E91B0201666736D87FFF0",
+ "derived_salt_nonce": "135C24DF13767FF03E133BB99D20B0F6",
+ "derived_salt_third_de": "3B537B5FF5AE9AB51B076C50F88DF467",
+ "section_extended_salt": "BE300446F843EC41349FC25CBE09D972"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E81B91F6D8C1095C1D42F68DE4CEC8D0976A6491F8AC899966A121D0A6F17A43",
+ "v0_identity_token_hmac_key": "75C08671B8EC4C5FEB972AA4F02FBC725BF42263C5693DB01E9C94ACFBC4460E",
+ "v0_ldt_key": "F53EF38DB4429D264B4C0EE8EC671327060BDE5C340F0CAB7EBD0E9C3BC8F7C4A9B49C0CF4A535DB8717F8E308D28FCA5D9ED92D0EB555C3C810C07558772A33",
+ "v0_metadata_nonce": "7AD4B6D7845B86851A7B4953",
+ "v1_metadata_nonce": "1AD2218AB0B01CCB1181D201",
+ "v1_mic_extended_salt_aes_key": "5BAF591B371061B32B72C8E1E56B8B56",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1EDCEDD0EDC416E7D8DFC2E2CFDFECF6002080DDAE2C1E13AD0E517561621ABC",
+ "v1_mic_extended_salt_mic_hmac_key": "3041D70D7B869284630A49C8272CAA14F3BA2826BAD8EB8EF3FB2CCBEA2AC1F4",
+ "v1_mic_short_salt_aes_key": "24B3475C2818DD82B2B861890B521CA6",
+ "v1_mic_short_salt_identity_token_hmac_key": "17C3C1FEE32642EBAAF0B4D9F769346394FE12D0EF967535CA1AC7C9EDA28770",
+ "v1_mic_short_salt_mic_hmac_key": "020D702CD9F9FA8D8D4214F4C2E326DCA16E782AB23DB36CD4A846B36312605B",
+ "v1_signature_identity_token_hmac_key": "CBCD66F3A1395C1C119396056A69180BF48BFE314DC331E78E6B81C06A897168",
+ "v1_signature_section_aes_key": "7630A756E997DD3EE511628239C2EB42"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BD6A",
+ "expanded_salt": "CC3CFE649FCEF543F9D77FC2D14F7DD1"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F3212F08D87FA7C44FCDA7E2C4A0F0C4",
+ "v0_identity_token": "ED93E5F3F71967B749570A37D16E"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "22FD",
+ "short_salt_nonce": "32484DC7B135A80C39081760"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "78CE8B13F129273503E1536058A43149",
+ "derived_salt_nonce": "C7F3873BDD429C39E5560D733BD3AFCC",
+ "derived_salt_third_de": "9795B0AC7799E44E875429A7A24B1547",
+ "section_extended_salt": "F86AB59158954445BC6366F8E823155F"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "711FC606359D4A42B851EBE5E51877DB08F075A7D54C7F3EA2D1FD4D1CAE4844",
+ "v0_identity_token_hmac_key": "673BFCEA7A139058558C1767A4466B9CA9EEEE6AD126C437828F22B5C2A7AB8B",
+ "v0_ldt_key": "4073B6432E80244E5311E22C3E2FA74C303C98CAC85945E276DD8D77D31D6AA6C3E89897D3271C35CB5A4A4D3D744D92934926FBC81CC264DB701F5DF56F5911",
+ "v0_metadata_nonce": "3CFA4E242A06A8E43E7EB43F",
+ "v1_metadata_nonce": "98FDBD9939089072019C5C42",
+ "v1_mic_extended_salt_aes_key": "FF33518D26448E2D4DFA5A67B3B21474",
+ "v1_mic_extended_salt_identity_token_hmac_key": "3142FEDB54903B750D43E984D94D5501BDF361B27994737A0A77A22E87C2778E",
+ "v1_mic_extended_salt_mic_hmac_key": "110D45543242D23BD5896052CB4EA44B9DA4AD1B6D6E4D5D795D7F23262FBEA6",
+ "v1_mic_short_salt_aes_key": "DB686DB1702E76B6A2E835D249E0143B",
+ "v1_mic_short_salt_identity_token_hmac_key": "4BC8DCD602C7894832F1CEC3D1C715B9EA2DA59AAD81D50108E4CEF6404A92E5",
+ "v1_mic_short_salt_mic_hmac_key": "BA49A19BBC61BB50BEC6F2C102E4D099DF3D204E3C5CD6C7CEFF4F22B62B5804",
+ "v1_signature_identity_token_hmac_key": "685A096405A541B4BA786E24DA79E8780FCD448563352CEDF12A7746A7808D75",
+ "v1_signature_section_aes_key": "737D543B38D9BC756BA6BF8D0E345839"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "6328",
+ "expanded_salt": "C41E3A15A684898BD69AB353CF9403D1"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "C248C7A2DF1596ECF285CD70F0B8FF6B",
+ "v0_identity_token": "880A532423DC3D24F9B01EB74747"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "703C",
+ "short_salt_nonce": "C2533EAB891577CD94E07FDA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "DD5E5F7DB850DB95FD63F5F6097094CA",
+ "derived_salt_nonce": "40BF0CC82087F3D8EE4E1070EE4E0D91",
+ "derived_salt_third_de": "D14D7004CA8C8776275296A563487325",
+ "section_extended_salt": "B774D26C0DA92679B9F85BA62EF47501"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "60A9A540CBADC6792695C2F83BFF8862F8345D9E52B8356398F78EA5EC5649FF",
+ "v0_identity_token_hmac_key": "1F216C2E0B900D0689FAC04FA32ACCA32D420E041AC5CAC6651CEC29ADF20FE0",
+ "v0_ldt_key": "ADFA524EC6DB187734F14812267DD46299AFF92C96CAC67AD898E0C2B51B00BA007A8C226C06BF0A711669687830D4E6A7C8A7E9AF8FA427A91A461D7BA38D77",
+ "v0_metadata_nonce": "51DCDFFCDEAA8FB85DF5D077",
+ "v1_metadata_nonce": "B9DE8526EBA518CADE736887",
+ "v1_mic_extended_salt_aes_key": "BC00D162975B27283A910929DB17F7D6",
+ "v1_mic_extended_salt_identity_token_hmac_key": "D9D2FA28386C9FCB05171F063FC464630CE1CC52CD47B6B235814B77695DA0FF",
+ "v1_mic_extended_salt_mic_hmac_key": "55BD72D9FE9ECD40946E57894549E0B468E0A62E2BEC97FD744FAE68C45783A7",
+ "v1_mic_short_salt_aes_key": "8240C926DD7C8887AB1D99C10D994BD1",
+ "v1_mic_short_salt_identity_token_hmac_key": "01F8D73775C16E0B2165023A3FBDF31F2FAB14F9269B26E0397D9F75105CB4A3",
+ "v1_mic_short_salt_mic_hmac_key": "4DE142833A00DC99C9A98AB93893AC000BE38083B7F31F3FB112E93B32B7F3E2",
+ "v1_signature_identity_token_hmac_key": "2D31AA445FED272EF8CC6C8BD869D30F1F7E2D3D013BC179AD19ECB59DBDA3D8",
+ "v1_signature_section_aes_key": "4548FC98A94CEB5037232B78069656F1"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BB38",
+ "expanded_salt": "DD8BEE6CB4F2F732966A4334D98A6A6F"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "58EDE47F3974330EECF1A2E5AC5659BF",
+ "v0_identity_token": "0848F6E9EEA846D61D0BD7F3145E"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "DBCD",
+ "short_salt_nonce": "8DC07DE237C5C0973E1F142A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "53F10F9CA5E77717F922663B49169B24",
+ "derived_salt_nonce": "4947E98A773F91E71B31C94603FE2A27",
+ "derived_salt_third_de": "82576C8D1063FA9B9CFE825EC4BC8D44",
+ "section_extended_salt": "71D1DA2128B0D32EDA53591B8B1E2214"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "DEC336D867DC86E9DA91F93D9F113D8A99EC2AEEFA5DD7076B98CCA93B775711",
+ "v0_identity_token_hmac_key": "36AFC7B183AF0C8815E337171C0F2B1ED7E3CC03C462D8360D86A9FBE61F763D",
+ "v0_ldt_key": "9A045E5092D0802835C2D77F9AE24B0C6572E27E10734AD0D7472C087E5A5BB1D94FA44F1094BF3C77640E483C4798C744602EA06658E401F3DD13DB5E9F2978",
+ "v0_metadata_nonce": "02E64EE4D3783A3B84279BCD",
+ "v1_metadata_nonce": "3BEB93AF74FF27D9CB898AB6",
+ "v1_mic_extended_salt_aes_key": "A981814F6939740E0FE916C93350E687",
+ "v1_mic_extended_salt_identity_token_hmac_key": "11CAE48A1DEE7B9BF057D721989DD4D6EC5E3BC7057B572EAB0EC91EC246C51A",
+ "v1_mic_extended_salt_mic_hmac_key": "2827D2973DA029745965B868ED9634EB7394D442143E79E72CD09BBC9F59F0FA",
+ "v1_mic_short_salt_aes_key": "5013ADB5508464143F2D2A96C807E459",
+ "v1_mic_short_salt_identity_token_hmac_key": "859EAD154B93576E407471495FD37A54193F9CFEE0078342EF48F677E2A20AEE",
+ "v1_mic_short_salt_mic_hmac_key": "2C5C56B063989DD245791D8398E146A585C4F91C8C29240814E606C0AF4CB6C3",
+ "v1_signature_identity_token_hmac_key": "A7A0CF65D8121AD48101E5A10512CC09F6B50FC64142A030188B6ACA57EE2219",
+ "v1_signature_section_aes_key": "2AD28911FAA0C9D0FD4295ACB09823F2"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C6E5",
+ "expanded_salt": "77DF9D9647500CC9FD17BDB3F4E68BE9"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "920EA91C74EF23E1607E7112BD9F5783",
+ "v0_identity_token": "190E0DD127CCE7E0A7B69779408D"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "BB49",
+ "short_salt_nonce": "063DDF6B3AE8F83186DF04FA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "64F5ECC15737A6BD0CD7148884A7389B",
+ "derived_salt_nonce": "FF7ACEE09C30922CC4367ACD2014FBE9",
+ "derived_salt_third_de": "A4B5B9D6F05A84BC5AA915AC954CA94C",
+ "section_extended_salt": "2D31BE7AB1A84EDF74D9B66B6DF3E7D4"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "D91552CA6C061EA51B80DDEA22465FDC3B0254D5F3D78F066E085A2711FE31FB",
+ "v0_identity_token_hmac_key": "2C3247978B974787D1F1037BF6C69B2F65B26B74DDD33F83EB397BE7E17B5FC5",
+ "v0_ldt_key": "2FFE770039FC6E6C2CCBA99EAEB23A3788FDEC93C54EA11CEC0E3CF8158FD17614CEDD82122608FC93B4831F1FB8AFCB724FA79F5F8013395D0B20273BC895BA",
+ "v0_metadata_nonce": "681F0C626EEB0EF9102F02CA",
+ "v1_metadata_nonce": "ED7B5E3B33DD153551E7EDFE",
+ "v1_mic_extended_salt_aes_key": "6E2FB2E25A3DE00492B7D00564EE4B9A",
+ "v1_mic_extended_salt_identity_token_hmac_key": "6FA4C0C757B012B5475EE27B9ECB13D0DEB28B11E050E62084099848AECABED0",
+ "v1_mic_extended_salt_mic_hmac_key": "5F0411676B1FA1C17C08568A88BB477DA9C2016560888D6D791D342CA8C9B812",
+ "v1_mic_short_salt_aes_key": "AC6C5BDDE8C655C7354206D748065E45",
+ "v1_mic_short_salt_identity_token_hmac_key": "7F04F2F8BAA4D0F564D291E17E00A4EA547A33D22C144608D6CA64D048571502",
+ "v1_mic_short_salt_mic_hmac_key": "6E2F84D1A9BE9234BBD6F8138068B7520B8E056B1B0949EEA5B720972DDA5D5E",
+ "v1_signature_identity_token_hmac_key": "983863BD77F0A3A79443DE302AD320F51EDACD4E735385260CD8703414AC897A",
+ "v1_signature_section_aes_key": "E62E81BBD49561DD9C20FDD414C1BF8A"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C20B",
+ "expanded_salt": "20C6AC9CF63183FE2C3578F69D5E81CD"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "4E76651BCC3F7AFDEC8631FB3156CA56",
+ "v0_identity_token": "70DE62B41AE48BFBED5AEF89B4B2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "FF14",
+ "short_salt_nonce": "9EC52904170660BFC9946FD0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "D3DFF59C7AEA3C8E820B92E76B80ED03",
+ "derived_salt_nonce": "16DE3412C96734F65C24B77E6A597BAA",
+ "derived_salt_third_de": "73FC3E0306353363F7AA4F8910C1F86F",
+ "section_extended_salt": "F0181D6CC67C40620D61C0377D06627A"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "D6B3A8F4CD3E869B904A4B1F0E34AC2F37509D40592A3884C3E69067632ACCEF",
+ "v0_identity_token_hmac_key": "D27AD5EC8129C043262F5A6F48B2B1737A5DDB08C6205D7D7CDF0FD8BF9D87B8",
+ "v0_ldt_key": "3B685DC172EFD153B0C6875F3E52B565A97993C96DC3FDB476E47A0945AE33B11B47AB78301330A079D7E68E6F89925EA528BED0EE437053FA1C0CCF9C294059",
+ "v0_metadata_nonce": "D3F45B2A2A8330C89A0D5A8C",
+ "v1_metadata_nonce": "3FD567346D88B78F94C5369F",
+ "v1_mic_extended_salt_aes_key": "E01D5674316E8357CB925409DAC3BE13",
+ "v1_mic_extended_salt_identity_token_hmac_key": "26EA66B124B9E03456EC07CEF36D6A24F1CB985CCE9F8285DA4139547D71B341",
+ "v1_mic_extended_salt_mic_hmac_key": "9EB1CD357FA7BB0AB5B17E95661DB20F30A9AF2DE76F06CDC6FF19D4B533A15F",
+ "v1_mic_short_salt_aes_key": "949AE776AA4D9F7B80E23D25EC3F0CB9",
+ "v1_mic_short_salt_identity_token_hmac_key": "58B69B49CF4DB03F5784823D95C94E868AFE1B1AE547131F32A0410CA8B4C205",
+ "v1_mic_short_salt_mic_hmac_key": "166A695C761FE5D1C0CA5577CDAE59BADC4D6B34ED6A02FF8C7C5B9F9D829D34",
+ "v1_signature_identity_token_hmac_key": "B8A5017381D6CA6EC9A1CB4676F00BA3F3F345BCA33C348CB7CE60AF1A9A7279",
+ "v1_signature_section_aes_key": "8BF7B8345F2B0BE8DB7CBE7E96D9E3AC"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "30D1",
+ "expanded_salt": "F75AF6269831BE87E645A48C8F2731FF"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "8057B45E2557983E5B173883A75396DC",
+ "v0_identity_token": "963C9D4D52A09EC1EC5BE7FCE09C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "AA48",
+ "short_salt_nonce": "3BE65DEA17A00BF9D49A1C38"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "2B99B7DBFD1AD40DBE93E10E259A6188",
+ "derived_salt_nonce": "FA549B59FBB527C1422799C1749F0304",
+ "derived_salt_third_de": "7570E91C96332E0248AB19ED32AE2A31",
+ "section_extended_salt": "0F3D3F0272988D59B1F3B1C6189E7E89"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CD466940D42BCF990370FCB55B63201CDA22DCA5BBCE0CF1DDCAE350E8B085E1",
+ "v0_identity_token_hmac_key": "683039034AA4C0DCEE3755EA41EA4A3DE983519B99FB961E8E8ED53FB4A96483",
+ "v0_ldt_key": "4FD74D82D4A29FE1254412C2A8FC74CDE4A10F3646E3CE11A4B34FBF18D8FC0B50597225A7BDC05FBF9791050298EE47ECED684F9404BC82CAA00471CB18C07C",
+ "v0_metadata_nonce": "B15E214FCECA2AF6263F0071",
+ "v1_metadata_nonce": "2B41C0A066C4E06435814541",
+ "v1_mic_extended_salt_aes_key": "849E8DED91FA247EC22FCE659E4458BB",
+ "v1_mic_extended_salt_identity_token_hmac_key": "6709E5FCA4295FD242F0EA72816B18EC308677791291539D458CF0C1BB3F2F09",
+ "v1_mic_extended_salt_mic_hmac_key": "A0CB3B5F81BF78216E18957A46B0DC4E38570FE1C69B1D6E06D29C3E2D56C5CC",
+ "v1_mic_short_salt_aes_key": "A67440D7A821523A84FCA1633161125E",
+ "v1_mic_short_salt_identity_token_hmac_key": "7DB92F89448C4D4059E48D199C36ACC879F0E450B0D8EECABBEC8C387B6A160F",
+ "v1_mic_short_salt_mic_hmac_key": "5378B75FE4E4A8505FAA231CA43CB0DFC1BFB53D07FFA2FC61391214AF21D293",
+ "v1_signature_identity_token_hmac_key": "31F296D8BBC8E6C8D877190FF808746B522B781F5D98E234DE608194E60A928D",
+ "v1_signature_section_aes_key": "C1E5CF90392F864D15390E483F08562E"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "82B1",
+ "expanded_salt": "1BE40D25CD9776534A2DDB5611A72A24"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "902BF2B1A996C43B041F9B420BC96648",
+ "v0_identity_token": "E51F72D506023394F7291D484052"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0C5F",
+ "short_salt_nonce": "408CD97C38B4878C593CA9FF"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "2CB4C2F731719080646D748288FD8A09",
+ "derived_salt_nonce": "C65251DDEEE83B1C0C7B1B6417EBFAA3",
+ "derived_salt_third_de": "E3ADDE6C9B9124A4ABDC4026178DCBAF",
+ "section_extended_salt": "20638EE0EBF0D34A51A53EF7563C15E3"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "BDBD1DD888D7FDCF43BF9D7F6674ACFF1DF2E2C660FBC745E43313739FAC437B",
+ "v0_identity_token_hmac_key": "FA13440C9B6024C2DABA4BA5D15F00E2366B7846D588199DCB58B38C1C6E9922",
+ "v0_ldt_key": "BE949780CD96A922B71160362959CE07376AED81979109E62E5BBB877A85E6C4EC0414697132AF7771485206B9BE8672D947996AB8878E479DDB3A29AE2C2373",
+ "v0_metadata_nonce": "7D5D37D4DC2C957A04376DA3",
+ "v1_metadata_nonce": "6131D2EB386B29CC1F335147",
+ "v1_mic_extended_salt_aes_key": "04B76123C0DA3C10F84D5303240799FD",
+ "v1_mic_extended_salt_identity_token_hmac_key": "536A471425BF8B929C332DD55423F010A15B4290CD453E78E4D53EE35E285E96",
+ "v1_mic_extended_salt_mic_hmac_key": "B151727B25FF7630AACE3803BCB85CB942EA1638E45F1DFD70663D8B8143A6FD",
+ "v1_mic_short_salt_aes_key": "266FAADB0647BF79A759C9F747F0236B",
+ "v1_mic_short_salt_identity_token_hmac_key": "F4C7A6A7F8F6FE6C77AB0A95A7A716966C7828BF5E7D1A7204984823639ECB20",
+ "v1_mic_short_salt_mic_hmac_key": "3EEF8D8F921DEBFC0B38B2C969488FC7EEAD618EEF189F0D6EE427539133095F",
+ "v1_signature_identity_token_hmac_key": "0B4E8908F5113876B22700FD9505474EBC4FAF369F850F6FEAB2CFFC8C218857",
+ "v1_signature_section_aes_key": "BAD090C852284E25461B7152B1B4D5D5"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "3345",
+ "expanded_salt": "F64A0AF0402F5ABC4D541C1DD1FA7C89"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D6DA7B5AE8C730D4E0C56F0D2F3C033B",
+ "v0_identity_token": "155B071F6DBF3F06763299B0DA91"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8534",
+ "short_salt_nonce": "7F613AC000317D4C02D5D869"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "C9C285BA4E31877EB2B2E031CFEA0B30",
+ "derived_salt_nonce": "35A6A82C0B520C126652A1376AD58DF4",
+ "derived_salt_third_de": "2EEC85204A794C280C774C8F2C037204",
+ "section_extended_salt": "EC6182A82E58AD95A9EDCACA06791FF7"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "307F26401920ABF523527895C6DD0F6BF4B20773505B1BE846B0D048F5A6FA87",
+ "v0_identity_token_hmac_key": "17B4D37D0642C6716EB50B800D65C3410F8A04F34927CDF15275E645C59D45FE",
+ "v0_ldt_key": "09BF32231643E1E288D213670302BAB93CE75A5733953005A01478F7A1B8740B5B08277F5A62B3C82F55AA5417E71E5FADC2AFF385B8683DB86832B0735ACC01",
+ "v0_metadata_nonce": "615BD483D3F879E35D3CA43C",
+ "v1_metadata_nonce": "147E38826C4682E5AA5E1678",
+ "v1_mic_extended_salt_aes_key": "2212A788DC4EE1ED998A958A0E4733A3",
+ "v1_mic_extended_salt_identity_token_hmac_key": "D28E7D6BDAD5F4C6B2A9FF58DA57133DC92F4C34F60DC107528B423361DF5493",
+ "v1_mic_extended_salt_mic_hmac_key": "95EE789B7EE2D188C993872CD7F7928AADCBDB063EF37B9BF4A1E42FE48BF27A",
+ "v1_mic_short_salt_aes_key": "FC2D104399AED84B2E04C6EC5B1D6434",
+ "v1_mic_short_salt_identity_token_hmac_key": "C378873BBA5D9686626014ADB68EA7DE71CC905C6212AF0D8659D6D6FF2D364B",
+ "v1_mic_short_salt_mic_hmac_key": "954651192C31CDDB288CB209E9644C9BF38566DAA16B828AB8BA51B40760C5DA",
+ "v1_signature_identity_token_hmac_key": "77C78656128EDC316410216D4A7ABF39E9A83F5C975B4C0672F4FBA61C855342",
+ "v1_signature_section_aes_key": "AF94A29FB78A0FE335FEC5E8B5C8DB93"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "5094",
+ "expanded_salt": "D74D67EAD97A17C8E712DAFC65DFF5FC"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "79BAFF7725786B619730FB1B5E660879",
+ "v0_identity_token": "03829BDD7852E472F79492371156"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "F32C",
+ "short_salt_nonce": "EF90714317133008CC791097"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "FC45A7467A362CB4A7BD1B51717012AF",
+ "derived_salt_nonce": "DBDD7802D5F950078856A9182E623962",
+ "derived_salt_third_de": "3C2970E4D337BA8D15FB3CEB02305027",
+ "section_extended_salt": "6C61349ED1E575BEE8632E0704C63FA0"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "0E57BC7F84E2B88D3E6E6DD1550544428123BDCE8087A273CEF083D508E9CBEE",
+ "v0_identity_token_hmac_key": "07AC05011C6C5798F10523C178095F30D09C5970D295290BA1C149A8296F0087",
+ "v0_ldt_key": "991B35604C8E261E12252B7EB4A4B5E7AA5D1E282346E35ABC119F740B72263B25F5CD970591A5A691C44930A6D53D17EDE0E6279C0811AD7F95BA846959125E",
+ "v0_metadata_nonce": "662688EA68FB63CBED7727B4",
+ "v1_metadata_nonce": "C34766435CAA1EA79616B2DC",
+ "v1_mic_extended_salt_aes_key": "D6A8080BBF67B2A5F31F50CC3F065D98",
+ "v1_mic_extended_salt_identity_token_hmac_key": "0F61BEE5E9E628D2E6AE6BA85FEDE8644C0F7A67913C12DBB7A9A2CC0F8003C4",
+ "v1_mic_extended_salt_mic_hmac_key": "54034D6726FE5EB1B3ABE64CFDA9F59B27363AE3E31134381439AD97E9D102CF",
+ "v1_mic_short_salt_aes_key": "563BE2F028CCAFACB90F495AB1C6E90D",
+ "v1_mic_short_salt_identity_token_hmac_key": "179DC9E04EF5284CDB8226A46355E771C618934D46052339E580CFA4A1042921",
+ "v1_mic_short_salt_mic_hmac_key": "65238FBDB477D87AA79E6BF2FEFE763D26C95FC2BE480C007318A1FE0A2B2F87",
+ "v1_signature_identity_token_hmac_key": "8548488B07F32D86F41B584DACC3FAA5D1FBE99B85CA152CA358C585D27E8C05",
+ "v1_signature_section_aes_key": "649A99512E6B524CD6AAFB9349EEC4AD"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BD68",
+ "expanded_salt": "332DA8CBB87E4B90D053E1463E6E25C6"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "889AA04ADC0A6867A691A37458CCA261",
+ "v0_identity_token": "CA3D2CDE92558D49C685F9B8DFDA"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "002E",
+ "short_salt_nonce": "268B4FA03588CAAD663128E5"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "3BB392471E3DC9FD55124F895C7715FB",
+ "derived_salt_nonce": "D55F2D27065CEC26BA6A3CDA4A99420C",
+ "derived_salt_third_de": "F0C487B8010500EC28E1E162C3ECDA7C",
+ "section_extended_salt": "B6B17B39F5C7EED0037906B686AD650C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "625636745F59A39E26742EB6DF2271730742517E40EB51C3959C5D2F4D70A530",
+ "v0_identity_token_hmac_key": "0C8AC8EF01326F2AD11E8858B69A43B5F4B6B47BC544439D191CD8D31B5B857C",
+ "v0_ldt_key": "0DE470CD371D7AE3F4866BD032BACAA9D7C6704BB978CA8F8C5BAFAE165B410130422C2B4E224A89F436752B8132056C26E1ED10ECE94DF85D223933ACC7E554",
+ "v0_metadata_nonce": "5FC268D65631597D5ACF7E03",
+ "v1_metadata_nonce": "75061912973730B3C8F98A6C",
+ "v1_mic_extended_salt_aes_key": "5F0F57E6CD52CCCCA1454153370C730B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "C7E773D20038E16FA0BDC823C470DEDF88C831B8D9E57B833BF5AEF29F3609D3",
+ "v1_mic_extended_salt_mic_hmac_key": "88229AC78E07751043236D0963BC121E2A4EB6489D0C19008E3210F57277CD90",
+ "v1_mic_short_salt_aes_key": "8C3C9A5E608DDD8195590F70B852C9EF",
+ "v1_mic_short_salt_identity_token_hmac_key": "9D1C4285C18AA6B490C11557CAD4A909ADC0711EB5F0FE493D0A837B84DB9E1F",
+ "v1_mic_short_salt_mic_hmac_key": "95550CE1FF69EAAF1BA1E8AE6560F29F2E068D0C8C78EEA78A6BB8A898B09C83",
+ "v1_signature_identity_token_hmac_key": "3893648367F0710E2E1FD4608C7A7892DF05A40CE1DA124C99F7483016B2A9AC",
+ "v1_signature_section_aes_key": "9E4A0F1FD50A640743596D58FDAB2A8C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "A14A",
+ "expanded_salt": "6EB825B90A6FA254A206AE337AB5519C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F32FE88F6A32C1FB8D6A7936DB0D701D",
+ "v0_identity_token": "4D181E23F8727578CDDFFE6C0807"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B4F7",
+ "short_salt_nonce": "689506D55DA43C98229E35E8"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "6C28C3ABDE8FFDA08F9953CB6B24320F",
+ "derived_salt_nonce": "410E75A3CA41E3C125C11FBB5FEF5698",
+ "derived_salt_third_de": "7A39A6831FE1C42FD179D229AB3BA997",
+ "section_extended_salt": "50BAC8BFC5B415D834FB0E214FD0A435"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "19CC012CC9001734B8364F869F1A509B73FA8136E244B9D3B748729B34A79FC1",
+ "v0_identity_token_hmac_key": "91126F93E7F6C136D0C45B2F4ADB05E90FB2820050C1AE0661268F615D656B50",
+ "v0_ldt_key": "65E151200435492E2E08BF9BD546BB5E874D98423E143068353AA241C017C996E11ED54A21A0E0271119A64E347B1F3D2A677F102025296C9AD99FAE60526944",
+ "v0_metadata_nonce": "AF7153D5E3454D574F3AC87A",
+ "v1_metadata_nonce": "B95A9D3509FB843EDCDE7C30",
+ "v1_mic_extended_salt_aes_key": "858513A0BD8CA526CB01C37D872CC17F",
+ "v1_mic_extended_salt_identity_token_hmac_key": "93C55B03439CB5070EB21AE8A4CA9BBA65F3B5455639ABEF55BA06D9DE5D097B",
+ "v1_mic_extended_salt_mic_hmac_key": "F62B10BBE49EDB6710E99F12D0A7A5C4F76E05158905098D3B7E7221675057A4",
+ "v1_mic_short_salt_aes_key": "12A98E8CAE6329555EEB63400A56D627",
+ "v1_mic_short_salt_identity_token_hmac_key": "401BF4799CB21A9277D3F643D51C5C2E5D574E53F20D5A4D6039BF8501B4B9A4",
+ "v1_mic_short_salt_mic_hmac_key": "77937075451137DA6E774BA77C5A25B51896BD85429245EB45FDF8D84D40ECD1",
+ "v1_signature_identity_token_hmac_key": "2A938DF61D8F4FC208BB76E2C1509AD85C880079F1C194287CAECE0AB03EFD25",
+ "v1_signature_section_aes_key": "305B71CD7CC16B254D7DB937EED3E384"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "CE71",
+ "expanded_salt": "52C4B782535F782334FC24FA40F001D6"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "17C531BAE241B406BB2922009FAD2294",
+ "v0_identity_token": "A612CAE0C2C60B0847C95556DC4A"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "F217",
+ "short_salt_nonce": "C7B4FA588C9333953524A7CA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "DE16277E7CEC4B1FACAA17BC54474A8E",
+ "derived_salt_nonce": "D4FF5F07C589D8138D2FDB2A24BC0C89",
+ "derived_salt_third_de": "D53C34584D2EA2FCF446979A19CD7EB4",
+ "section_extended_salt": "F946C81199DE69612EB07197BC151E2C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E145E4CDA18D67961C0286D0377554B146858D4D83365D406199928CDCAC0C89",
+ "v0_identity_token_hmac_key": "51094471DCCA8C3E1DE0075F09137AC7CC16A0A1C593EA16B01D21BA8BD2212A",
+ "v0_ldt_key": "4F2A178BCDA7D33A469327F1DD4A936F3690E9D6AC48FC69A30639833AB409641F30296928E25A32598936D1FC872A8356984FD3ACA78AAB96DE6EB2C8B15AD9",
+ "v0_metadata_nonce": "D8B9FC255A175733AEB21289",
+ "v1_metadata_nonce": "3B1A920FC87B0CD4DB45FE58",
+ "v1_mic_extended_salt_aes_key": "284E68D89D1634B46CFB893C4DFACE25",
+ "v1_mic_extended_salt_identity_token_hmac_key": "A53C4B56D2E8C308D2DC7D1A730F16059C8F352AB43350EDB6BC9FF0E8D5C8C6",
+ "v1_mic_extended_salt_mic_hmac_key": "4E98FDB0A10DECFF15DD50201B666FD37DECD7714DC39375807CA551EA4566B2",
+ "v1_mic_short_salt_aes_key": "FC0DABBB4752FEC56777FB109C1FCF70",
+ "v1_mic_short_salt_identity_token_hmac_key": "26B67259B23EE7FF7732B63D29FB88C6EFF6B2963742314E7EE443D062D577FE",
+ "v1_mic_short_salt_mic_hmac_key": "494B430E241D388B8E15EAC8B79FB531D8202019A03F171A70FEF735DEA4A839",
+ "v1_signature_identity_token_hmac_key": "1BB63967B26B3A8182DB6E45CE90217C48F7C7289049669114F2F60D59A4982D",
+ "v1_signature_section_aes_key": "C12D865CE3C3B92E3D86E11D31C4B7D0"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "AA4B",
+ "expanded_salt": "055DB6E3745BDA470CE4F4C132880845"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F594F0C71C5C1FE594655C37747429C4",
+ "v0_identity_token": "B4C958171BC3890DBE38F108DAAA"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "97AE",
+ "short_salt_nonce": "C9FDD6FB248C1AB3CFF1BEF9"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "90549FA7AC9880D8007E17CDEE74FE89",
+ "derived_salt_nonce": "55FB1B0D6681696C15F559A6A0B817BD",
+ "derived_salt_third_de": "DA0D6A896BC2718BAD6B2582B3EE79C7",
+ "section_extended_salt": "1FCA0AE82AE6340C91647C5564742C84"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E4B6ED39E885C5F41D6F4D90C81C4087346E365A3E18278A7CDCA536C7229ADE",
+ "v0_identity_token_hmac_key": "482AFD56528CDADE549636FDABCE9587455323DF5F6BB2F9FD0C66F14F2FA4B4",
+ "v0_ldt_key": "0789774D2056B6A5EA53D55137B61BAE5C313FEB8BF68E3DE555EA01964B54A6F0E1E481429DE7D2BE8FEFD3C16C438EA167C6910C457F1C189251F54A01436E",
+ "v0_metadata_nonce": "F497EF21C812E0A4ACC14FC3",
+ "v1_metadata_nonce": "F1738F20E3B5B10D3E328511",
+ "v1_mic_extended_salt_aes_key": "1E4783B23CC12AF94BCC9642958C53D5",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1AB2BDD7562FEF156CE157BDE824FAC8C927861B7DD1CBAA2D26DAD763A1EB90",
+ "v1_mic_extended_salt_mic_hmac_key": "46ECCA964CC3D606C16840222CB68074FE307938809FC97EA68C5E9EAC01E754",
+ "v1_mic_short_salt_aes_key": "A4EB5E86AF11AB3A4F8D70BA2D37784A",
+ "v1_mic_short_salt_identity_token_hmac_key": "32E95A4CFC685F4F3987F8D89C13B33C43E5F8BA1A1C76518975667B7EDD5A98",
+ "v1_mic_short_salt_mic_hmac_key": "80179BE73B86A9D0AFF72833F594BCF83905914646F4DB288EC11F875F1591BB",
+ "v1_signature_identity_token_hmac_key": "94A64B97AA4C3A474CFD819BA6FC161F2E2865B1E2B08B041CA219490F786F6A",
+ "v1_signature_section_aes_key": "8025F8AA3FC09DC5EF67F59C63D81FDB"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "28B7",
+ "expanded_salt": "6A3253C12DC5A5A9C9F2BB5FF84575A3"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "942E2707FA20651603FB9BCD1483D57E",
+ "v0_identity_token": "79F541A8D757F44FB52031C6EF7E"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "1299",
+ "short_salt_nonce": "911ACEFB50B97795D2A96537"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "5BAA0ED9252F176221DE2D9E287C731A",
+ "derived_salt_nonce": "220F098C6ADCF4E24B6762E4CA4DC7A6",
+ "derived_salt_third_de": "FDB6D13DB24556E6A1E926CA5080B20E",
+ "section_extended_salt": "C10AF6288A750A0C71B7FBB3057BBAA2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F93748CF451F971291D31EB2D25948BF10687D3F3955D5A6EB6BAB4510E003E8",
+ "v0_identity_token_hmac_key": "BA87E890F118FF9516B6054C89212CBA85D3413E236865E71CC939AF0A48D26B",
+ "v0_ldt_key": "7D6E7092EF91CE57885E3F7250DC889064C9B657A8BEECC800EE8DA3A5E508D22CDBF4C8164CAD7EF9067CE25B1A51693998A3FCC4974B80AA26D0A08FC1ECEA",
+ "v0_metadata_nonce": "CBE2FDBF7E222F39257C4697",
+ "v1_metadata_nonce": "37181E07F73F64E6D39549D9",
+ "v1_mic_extended_salt_aes_key": "442BB1C9309855CC0C81B319AC4942BE",
+ "v1_mic_extended_salt_identity_token_hmac_key": "905919A49E80A3F5DC2471AC9CEB9588AE9266DBDF346F9FEB05980466A24A48",
+ "v1_mic_extended_salt_mic_hmac_key": "1BE4DF51E2A244F17793D9C3D1EE2DDC9FC992BFBE378C828DBD1D3121F4D9EC",
+ "v1_mic_short_salt_aes_key": "FDB274DA8F75B1DA00CEAAD2BDD6BD06",
+ "v1_mic_short_salt_identity_token_hmac_key": "750DFF2B2046595041B400945833A3434B39D98C23975040C6192F66959E40B7",
+ "v1_mic_short_salt_mic_hmac_key": "19F78A8FE548117BA40809FD8F602F2FB9A57F6EFE01756A93A81A6BBEA0BEF6",
+ "v1_signature_identity_token_hmac_key": "48FAF93A1F41C85646B0204CCEA6C145E7CEB69BA38F3FCF3979E4F9A34747BC",
+ "v1_signature_section_aes_key": "34324281067F3278984109B434594C84"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "9021",
+ "expanded_salt": "024D17ED3BC1DD62FFC281DBA42F6CE9"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "2CA6D8809D9CC54B426A5D631F5DD5D2",
+ "v0_identity_token": "C17929AECBB954C19B7D9FFAB41E"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "F2BD",
+ "short_salt_nonce": "760FE743C18D50BC5915DEAA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "66980E111A8AA401E3B96E7E0EA44FF5",
+ "derived_salt_nonce": "51074A20BC98469D5E302D454A661CF1",
+ "derived_salt_third_de": "0A7723EEBC848E10D5573084A5AA9326",
+ "section_extended_salt": "3CDABDF68AAB76BA4AD395BEB668D405"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "6BE4BD51107BCB90669934994487DFFD384C30A08A130DCF058DFA9CAE77D7B2",
+ "v0_identity_token_hmac_key": "36DB5DF09F5706F43F19A6A6A6DB9EFACE7C0945BE5CCD6FD9B41E514D3ADF6E",
+ "v0_ldt_key": "6B1D1F8670DF12FAE850EFB556A52E80AF256644C657442BFF5B6A8535C0532CA642511E2EF35C9BBF583F051594656F4D9EA1C8639710F51033600488B3C5D7",
+ "v0_metadata_nonce": "E64647D6D6428CA9356F587B",
+ "v1_metadata_nonce": "9446C5C7C84F3592D1BBDB63",
+ "v1_mic_extended_salt_aes_key": "A466870E3E012FD1D47AD9AD1A70BB00",
+ "v1_mic_extended_salt_identity_token_hmac_key": "303A9851761A21D1B8F8428FA5EEFE4311C10CE0BB62E0C846D336C829B626B1",
+ "v1_mic_extended_salt_mic_hmac_key": "4EFE91D05602871EF06FEE7A9B2DB2ABF8FDA8093467E2B7E5437176D24885AF",
+ "v1_mic_short_salt_aes_key": "6465CF64ACF1F01D2D5D9D1441B2E4B9",
+ "v1_mic_short_salt_identity_token_hmac_key": "F5129A6C3923C228366A93A12BA8287B1C2CDA1A6CFDEC305C7FB224D92EDE7B",
+ "v1_mic_short_salt_mic_hmac_key": "30876F2D82145F3754EBD7CAF699A3BA64458F0846C9E6047485B5C209F65C1F",
+ "v1_signature_identity_token_hmac_key": "AD8B825C5A010150B5F2AF5A3FF073A3EE199654BBBB073E4D902FE4D0AC5A48",
+ "v1_signature_section_aes_key": "611B58E120CDE3E26F834932C36566DD"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "3CA1",
+ "expanded_salt": "8DDD8654D5EF2D402D1BD89677B3B2F7"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "33A6954AA51AC176229053887D832EB7",
+ "v0_identity_token": "45694EE6AB26F4B895349E87F727"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "D982",
+ "short_salt_nonce": "72163DAF1F557C67B89BA7B0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "84D7B207BC3AC861E317C4427A2F3301",
+ "derived_salt_nonce": "498C9B6F78B4E5F68FCBDFA5FAD87C0B",
+ "derived_salt_third_de": "363C6DADFC2F7B20DB94885929867F1F",
+ "section_extended_salt": "9435272D1BBC6EA6FB74B94D6AEB5AF9"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "9A5DF1DDC5B966E46275F11196A5FD20AC8C785438892A20AF9CC19D1F024234",
+ "v0_identity_token_hmac_key": "0CC4D92F3CB8D258086F2FFAE0D3C00CA5D091666B506967365A20BAFDC8075D",
+ "v0_ldt_key": "B002ED5E3E3A89138132968C513DCCCCE3505AC181845BF28BED504BCAEAD1B9992A869C9FFE5869AD40AD9088B6B3B3C0C84152A15A65861B9AA5E1C15B0A48",
+ "v0_metadata_nonce": "A71E83B5E9FAE0461B560352",
+ "v1_metadata_nonce": "D68843EB7043254F1F786CB9",
+ "v1_mic_extended_salt_aes_key": "4A32421BC387873521C5DAC5DD9BB2EC",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1043596317963E0FA7B386319B95A23EC6E2B8BDFC510F98C2D55472FD479CA5",
+ "v1_mic_extended_salt_mic_hmac_key": "D619E81CC454D9988BAEE3126A279B2E06E91555B79E736D3A148BC5562B7640",
+ "v1_mic_short_salt_aes_key": "7F710EBA3B7926655AB09CBE0B907506",
+ "v1_mic_short_salt_identity_token_hmac_key": "CD64A6D97487DFA1AB1893D5E00117807F598A2AE118654996BC1E3DE8F8B61A",
+ "v1_mic_short_salt_mic_hmac_key": "3C5F8ED49E7B095E21F3DFC00E92C34A6291E6E445FB181EB5612FB45389BC9B",
+ "v1_signature_identity_token_hmac_key": "FD265D72D87FBB7503D2B532DF0F03F916FB41D82758D1A6BD1E71AF1C3C99E8",
+ "v1_signature_section_aes_key": "C715D287A1C5131332DE38C844EC32D9"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "38BA",
+ "expanded_salt": "BE558E77E1C1CB6D3B412593604D212E"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "3249439E945688E53E2D09CECF669801",
+ "v0_identity_token": "262E2E4C531A2756323900C354C5"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "1C05",
+ "short_salt_nonce": "F93616C2AEC28E78FF0B5D0C"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "8F505CBB29A4CC1CD037D1864D15141C",
+ "derived_salt_nonce": "03A12AB647E4834E3E507F1F6EF20F1A",
+ "derived_salt_third_de": "654F8A7CD26F23E82163007DD25029B9",
+ "section_extended_salt": "AD43FF79BFF583BED9ECAA14CDDA4B4A"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "FD4AA335CD6FE01E9BDD45FE11B306293BBECB92F1D2CAD39CBD1AF43ABCDA60",
+ "v0_identity_token_hmac_key": "406B8E5E105F55217B0687BA83B5DDA39C541DA4D53015D7E9CB83DD8A6A307F",
+ "v0_ldt_key": "F5F2E863B32E3B216EB59D37C1CAF3761D6BBE6A089ADE286390690C0C1DA5AD5CB3B647D9CD210ED63267C98C2893D17988B8A1D03845AE170E737CC20D0185",
+ "v0_metadata_nonce": "64FB1137553FADBA3814DD0D",
+ "v1_metadata_nonce": "1DA66804A1577592B5D88534",
+ "v1_mic_extended_salt_aes_key": "204CE842E93EDBEA97BBF662EF60C006",
+ "v1_mic_extended_salt_identity_token_hmac_key": "FE3DE77C3C83956B52F85C4A6284B97BC69E2D238A185F2AC7AD7E3A042D7883",
+ "v1_mic_extended_salt_mic_hmac_key": "208EA31DA316646310DAFE2A4036E5A1556E80020D8EE582DCD9CB6DC475B625",
+ "v1_mic_short_salt_aes_key": "0B308555FC29F102CF5AF79AA5C5D85C",
+ "v1_mic_short_salt_identity_token_hmac_key": "5F89875055E105BD96055508E440A6A6B44AC0F867D642FF95EBF249D2A28BD8",
+ "v1_mic_short_salt_mic_hmac_key": "54F0E228A0E4761F1694BC2717794E2C79BC9CCA99A0B368A370A83750468223",
+ "v1_signature_identity_token_hmac_key": "5838D84FFD60A23225B059EFE52D7FFE71CDFDB599826D8BBCF2E254FA5B72A7",
+ "v1_signature_section_aes_key": "0BA6F0BE32E0E8AF932B27A38BFF678C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "1D76",
+ "expanded_salt": "03BD30CAD853D018A141F8DEF1F37112"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "9355E90CA1E607F24358C2898E658346",
+ "v0_identity_token": "636CFD6764F2586AAD40ADD23774"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "DAC9",
+ "short_salt_nonce": "ACF0BFA6CF9267C79BF71814"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "588B14F40986244A6E6E11B59DBE6004",
+ "derived_salt_nonce": "8F4780C654ACC3FDC454F59459EE4806",
+ "derived_salt_third_de": "433266A654D8821576954A6122E18ED5",
+ "section_extended_salt": "5D5394D0EF11A3C4C83A1B3F4DD1340D"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "8385E64B2E3EF21FAA2E01F9A7E3681B17C7DBE0498B3A9DB7CB25E9D62EB6ED",
+ "v0_identity_token_hmac_key": "AB4C142CE9F73CAB064D3533B1980B1B4B88B98AED58171986D28966A127F45E",
+ "v0_ldt_key": "8978107F05DBC75203A1D8B09C2B3C3508207EAB51AB43312FA2D6AA912DA366F050FB8EE7A1AEC265D08F47EE1C299B4B8E526A62EE1CD529294A0F9166B135",
+ "v0_metadata_nonce": "48551A9BF3E51223B4FA83A2",
+ "v1_metadata_nonce": "DEEED21180C62518A729ECFA",
+ "v1_mic_extended_salt_aes_key": "CDD92FF2299C64640DD4DDE767B8447C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "475944CC40A29812841D147B2F1B8E6FA3B1960083DB50C373F1D032C05C32D7",
+ "v1_mic_extended_salt_mic_hmac_key": "2ED15F9F067294394BA5F7EB2F554553CB932E33A8C10E6AC3434FF1A7F8DD2F",
+ "v1_mic_short_salt_aes_key": "CA73989C086C73B114AC605A79A0F8F2",
+ "v1_mic_short_salt_identity_token_hmac_key": "63269C17F98AA0029E06EA1B749D8DB6C28ED916906DD28F1A3A8C94E31DACF9",
+ "v1_mic_short_salt_mic_hmac_key": "AD1C3A30332FA34408CA62A9C6B9A5263932EEE57829C1195DC74127B1C88671",
+ "v1_signature_identity_token_hmac_key": "99B0BDB55C04EAEBA66E40815CA346C596D848044A16F8A8CD1E8F22E4B11F97",
+ "v1_signature_section_aes_key": "5F2B10AD3A8C1803B080A1F99239B66C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D451",
+ "expanded_salt": "B73C8091A1D606893FFCE4BA8DD96D80"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "3A1461B8D59E8F9AAC4DE97877E97A56",
+ "v0_identity_token": "2377F0BE5EACC04FA6679BFD6DC0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "7A24",
+ "short_salt_nonce": "D13C30E6D309831E754A8B5D"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "22A24B673F12E4066B1058549ACB431A",
+ "derived_salt_nonce": "EEF802FFAEBD8AF451F5275934E2F8ED",
+ "derived_salt_third_de": "136F8970074C895F2195791B5636A000",
+ "section_extended_salt": "18B6A2DB75BA6F6C2CF40473B7673D48"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "B5F5FD3809B1E2287363B843688B8F263B36F22A818CE6D653AD2E202D4C2029",
+ "v0_identity_token_hmac_key": "8FE854C9FCB565B6E74C28EE13B9740B3F0A76F1BEB869A6EBBB7DE4999F69D2",
+ "v0_ldt_key": "F3B0B3A99C8AE9E6C111C2378C15396404E32B7278E5B3B5514251EAB2FECE631528F1EFE06CFFCD192C2D3483D00760C4D5F3809D32B29ECF4E1A9D9422F6AD",
+ "v0_metadata_nonce": "820F6CC121CECB5D770CBE5D",
+ "v1_metadata_nonce": "371063E1C363EE10DD07C754",
+ "v1_mic_extended_salt_aes_key": "78C14BE8C5AC8D740024768A2B59F13D",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B0CD0B70103C233E66D37E621EE40A04873D917A70D2E647FBA106399AFF720A",
+ "v1_mic_extended_salt_mic_hmac_key": "1FDF6A45C585A0F1B30CB767AD84410A2B95628635124F63C05F092918768D6E",
+ "v1_mic_short_salt_aes_key": "2C30551B0B248E7AA0C567A9F1F588A2",
+ "v1_mic_short_salt_identity_token_hmac_key": "CE516307270755B243FF272BB9A38EDA69BA0E04771E1675B5CFF1218637CC36",
+ "v1_mic_short_salt_mic_hmac_key": "BA808DDB430868DEF3BAA9FA53D9FF19BDA2559876360F87DEC0B4D04E6B482B",
+ "v1_signature_identity_token_hmac_key": "B90E66D1CC33DB3DEED3F867C42569514764A2E4E26D6E65A5009D3C39EF0BB0",
+ "v1_signature_section_aes_key": "5E4075E092E92885446D7D362B52D788"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "E077",
+ "expanded_salt": "A6B67A4794E7CE03C296D02ABC551D86"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "108E348B0D134F66511A75D575F3A1D7",
+ "v0_identity_token": "E79958E8FF15C1F5B7857F2BFD5D"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "735B",
+ "short_salt_nonce": "808310562C7E7A9F797FE241"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "D063EED8AE6DA992FACCD9BEAEFF9D60",
+ "derived_salt_nonce": "49FB1F75B6A395722D25D76BF3B5CA35",
+ "derived_salt_third_de": "86575CCD43CFD910F9103697669DFE08",
+ "section_extended_salt": "AB63F5E51D36B4C5CC9C302876BB2C37"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "11BC6308D6F1B051F733F9ADD041E90BEE2B19725633988B416F1EEED3C1EA8E",
+ "v0_identity_token_hmac_key": "7DFBD6E8C3D38FFA86D57F9984A91D79F0092F15DDB133C99A35C23C1EB7FF6E",
+ "v0_ldt_key": "15B76645533D06841647A3079A81C60F862CDBF49BD259DB3AAEFC7909B8CC14E44E63E04410434E541C99A00017A1D91A1D48F3960CD19460B17FF720252727",
+ "v0_metadata_nonce": "134D3F0E1599C745191BB287",
+ "v1_metadata_nonce": "7E2895642ECB18F17843FFF5",
+ "v1_mic_extended_salt_aes_key": "E75A52D878873874712BF3D7BB5419E7",
+ "v1_mic_extended_salt_identity_token_hmac_key": "A61F230BA907B4C754FBB42BCEADAA92221444FC88FCCB9B1ADF04AF88035D27",
+ "v1_mic_extended_salt_mic_hmac_key": "57EEBAEC158DD1DC90F3B1D8884CACB5FA32322E4E7C4EE21AA0EB175232498E",
+ "v1_mic_short_salt_aes_key": "CB4C2ECD3F7058A3FF10FBA90939B090",
+ "v1_mic_short_salt_identity_token_hmac_key": "A09E42551B882B1E6FDC075FB2A379332C66F91C3FD2DE496E16AC3C57FB2F88",
+ "v1_mic_short_salt_mic_hmac_key": "4746E3679A6D724E53E049DB091AF90619DAB91369DBD18204E346B2BD69FD6E",
+ "v1_signature_identity_token_hmac_key": "6944BE9FD3E6F9FE05843758B8185862A8112941E10615767A7E41A76E6B1136",
+ "v1_signature_section_aes_key": "4A4A874A9EA2E43F5A9F76E7B2C20283"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "4B85",
+ "expanded_salt": "7E6520C25AD0706CF1B053B159BAB155"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "356B301E5F432F5AC986BD0E0803812D",
+ "v0_identity_token": "05038424718B35F01CEDDA0AE654"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "E1E7",
+ "short_salt_nonce": "224F4CDE51A4C3379B542B1E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "4CED096908CA26C394EC58083D07668B",
+ "derived_salt_nonce": "0676D12F882BBE0106CA0BB3138F0BB9",
+ "derived_salt_third_de": "5A1A19BD6F8C55822C6B51538206B166",
+ "section_extended_salt": "59D1E9BDA1B9BBC808157A8EFA1D6BC2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "32E24295D7ED86DD0F048F5AFB62251E5BBA5FF34E2C191F8E89277E93DB4200",
+ "v0_identity_token_hmac_key": "4056DFA3904F3DB84F85315807A1ED8AC4B03A0FB300BB64C244FD377F8B8350",
+ "v0_ldt_key": "D4F8368C22558EE72891F005C5DD4B62C2AE562147C7E7A6B1041E2B8387160CE1DDACFFC1EE0725DBACACF79A6C1AB7F16DD15DCAC3EE96DA0EF70C03CFB261",
+ "v0_metadata_nonce": "5BD37F029FDDCF34D94D9723",
+ "v1_metadata_nonce": "9AEA4508424F0408F12D3F83",
+ "v1_mic_extended_salt_aes_key": "4FA46CB81F16D1973C228D94A26B316F",
+ "v1_mic_extended_salt_identity_token_hmac_key": "A0D1CED918D2A3D702E2D1E81211247FABC8E74E28614FF12B86DA38FE49804E",
+ "v1_mic_extended_salt_mic_hmac_key": "6C6BB48C73B078F00191FCD9E5A6F9E51540963C3B11B242DBC6B8C4EF5DC396",
+ "v1_mic_short_salt_aes_key": "A75EB826BBE44DA0B11FB0E93B06F661",
+ "v1_mic_short_salt_identity_token_hmac_key": "3848F69057BE12FF81A53754431C32DFAE36155AB7069ADB0C59A441F3459C68",
+ "v1_mic_short_salt_mic_hmac_key": "96EF80B80CB868F76C623029EBBC45793B78D584F43D955930C74EACF1256885",
+ "v1_signature_identity_token_hmac_key": "1FC9D1ECDBC54491BE8F60F7663EF74B551FC5734620463D55E6A561A2AF6945",
+ "v1_signature_section_aes_key": "72EEC64698FBD42D3A53F84EFB88EC3A"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "B65D",
+ "expanded_salt": "ED9F26FC67AD4BEDFCA31BE3DD4E2173"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F432735228DB941C89598E37EC4ECF1A",
+ "v0_identity_token": "70AB53CC636AF05080929153F78F"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3309",
+ "short_salt_nonce": "3701F88A64084BBC60178848"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "7A718CFDEDF904C7A72BD13FD5DFDF47",
+ "derived_salt_nonce": "53C9C943AFE5BE0EF3EEE3859B536A4B",
+ "derived_salt_third_de": "42726C30FDF62DBDA0074E6FAE969CEA",
+ "section_extended_salt": "45E80FFC36670147E8D2CFBA526EFD42"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "229032F519800B9A2527068EDE2BB34852628ADCAAC3F20CD72E93B01D4AD9C3",
+ "v0_identity_token_hmac_key": "0D3D137BE4B1478340EF1FDB8FD01B917B72FD783151505E1A7D8782F9A53342",
+ "v0_ldt_key": "AA6E607B24892A16693EEB60F05AA306B2513F8D65E8A43BE6B9C135C2E6E8EFDDE759A13EBE077CC2D84785514D6DC55FD8D3BE9D075003C7BE9D7299ED9F8C",
+ "v0_metadata_nonce": "026E8C93F32AF7A8BEC2E014",
+ "v1_metadata_nonce": "E3A33A83F8DDF01A20423453",
+ "v1_mic_extended_salt_aes_key": "E4F8998F78966160243FFC98073E27EE",
+ "v1_mic_extended_salt_identity_token_hmac_key": "47BC89710BF706CED760412959675300B62B997402FA5BA1969251B22903874A",
+ "v1_mic_extended_salt_mic_hmac_key": "A0C758A7EF5B92B5CB0EB64F5406F63C03CD395DF2D2806661023CDD29A92735",
+ "v1_mic_short_salt_aes_key": "85F922D62800B1716710D7347534F076",
+ "v1_mic_short_salt_identity_token_hmac_key": "734B82605001AA6C8380F8D020D3B66D6CC5BF6D841CB54417FF633566EE42E4",
+ "v1_mic_short_salt_mic_hmac_key": "97851B6E5D32EDF9858D3261BEC3E9B6D821475F73C248EE1C82C5482C780A1D",
+ "v1_signature_identity_token_hmac_key": "0A209406D33340C3CB0052E913F1E9790029DA31184175D8D8E18795251EA194",
+ "v1_signature_section_aes_key": "C9385776AA1D74BC77CD1A7985329E16"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "7A7D",
+ "expanded_salt": "30C981ECC7042DDBD123DB6271F25438"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "4975149498F7972EE91550E2838FAA5C",
+ "v0_identity_token": "64357B751F939F46CB00C2E34301"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0595",
+ "short_salt_nonce": "0C3874DC89E7793DA6562C3B"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "854BB53F1FFAA03F8E4A4F89B36FC75A",
+ "derived_salt_nonce": "2B61315A2A80409D20DD3567EC8612E6",
+ "derived_salt_third_de": "68CFF39B8B60522BB864F55909F6A07B",
+ "section_extended_salt": "BE6DFEB3BC734140F9F2E7A2C514782A"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "926F979CD91828BAD536CFF2B68D1F78CA1D888D07A16717CFBDFB2A4305AF16",
+ "v0_identity_token_hmac_key": "7FEFAC357C80BE62792DDB094471D7595330063D23661E657B48A65185877295",
+ "v0_ldt_key": "CD2E40F2D80EFA65F2C34DB94F64FE799CCB5FEBAE1696FC8141E379FAC4E829F2EAE5D3E4512A03DFA0F00130117CE5A95EE9BF1AC6419618E8B023A2C65575",
+ "v0_metadata_nonce": "826FF1F5574134B44DB2629D",
+ "v1_metadata_nonce": "5524D245AEACC28113B5B37B",
+ "v1_mic_extended_salt_aes_key": "DA21A963D42360531123F21E0B1009D5",
+ "v1_mic_extended_salt_identity_token_hmac_key": "99E686E750515E72D124F70E05EC0A1191378885CCC98D827A8707457DAE7B62",
+ "v1_mic_extended_salt_mic_hmac_key": "BAEDA9CCDD8780DA6D122D777249B462D43E267A60C8AC821B6E49E52FF6E497",
+ "v1_mic_short_salt_aes_key": "B078CE6C132D1D5F03C7011CD1D1B739",
+ "v1_mic_short_salt_identity_token_hmac_key": "B2A42460F29197AA8F08367283175BDB97DDCF5716EE7F011EF7D7765336425A",
+ "v1_mic_short_salt_mic_hmac_key": "C774F2182514364F7FD446D14E545C6B94DAA8292BD09286B5A06320DF0E6E31",
+ "v1_signature_identity_token_hmac_key": "C41617580CDF1D4C81AE49774535BA6A622C319F6F02466905A13F6DFC34D354",
+ "v1_signature_section_aes_key": "F438355B1434789B8BA63BFA2FDB4DF4"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "F67E",
+ "expanded_salt": "67407A62A7D1A972E818EA6D50A4B82C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "6BB8FA3FCB7F68A676918B7E274282CE",
+ "v0_identity_token": "A5520A470B231F19B9459DEAC5AD"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B6FC",
+ "short_salt_nonce": "9A22E33E298A3D2F813E947A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "BB326463B805B3B120DF3A3C1EA440E5",
+ "derived_salt_nonce": "6D533671722212A5B388B94F462B66B0",
+ "derived_salt_third_de": "FCCD3C04B6AD3FBB94F5196EE5E5CB39",
+ "section_extended_salt": "E9E85B2DD811EFE01DB44C34D96245D7"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1E886D86767B2D1CA915B5FC93342EBC806AD6514B0A6FE3BA86837E7C9BB251",
+ "v0_identity_token_hmac_key": "78C9838980927982C90BD31EBBFAEB6437E8C80E9815601BA8DB01AEB8D5C7D5",
+ "v0_ldt_key": "FB4EDFC50836341EF3902AB6838562C0AF614BA3D1D1DA817E78A98EE70517F060C059EB79126CD944E1DA5E9F577A3F82A096769D58A28909EF177697D31106",
+ "v0_metadata_nonce": "FBF4B4DBF353419687387277",
+ "v1_metadata_nonce": "08E00B2CCC92CE1C0E6E3384",
+ "v1_mic_extended_salt_aes_key": "00EE827633E2295F9CBF0C880DFE4CB2",
+ "v1_mic_extended_salt_identity_token_hmac_key": "985DC19EB9D9B8F3921B82AEB1F324C0DEDFCCE99871D5A65D1978C05B2DA1EB",
+ "v1_mic_extended_salt_mic_hmac_key": "DDF3D0BF099CD0A4AFC96E682BA82414775B21F69F7604CC4EEC3A70AD9F1909",
+ "v1_mic_short_salt_aes_key": "10D98E2BA375142D53279A7C8BAA18C9",
+ "v1_mic_short_salt_identity_token_hmac_key": "A3DC4E64B719FC69E60F600ECD6A6C61A1E2DBB03C936A716CDD23BA486BE5DD",
+ "v1_mic_short_salt_mic_hmac_key": "56FBCE7F9800AE9985C591692672ADDD87F9E97DAD409DC33A428C2DAE66D4B1",
+ "v1_signature_identity_token_hmac_key": "F5E639C319E632569E882D9426505E71A1E283584F4DA0CB23BE6792F4708F19",
+ "v1_signature_section_aes_key": "74554872D23253B364539E0DF37FD1B5"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "2C27",
+ "expanded_salt": "FFEC190578D4675D3E8F3B255B665B09"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "1AF203A4134F84A95EC2A465E61E6FC3",
+ "v0_identity_token": "B43A2C7B5909178A9FA4A81A3AF4"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "EBB5",
+ "short_salt_nonce": "9967714E945DD4F451DCD5D2"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "263AC32CE6FA4D0E5F00671D461C4082",
+ "derived_salt_nonce": "D5216F638FB5E3148C23E3568B02DED0",
+ "derived_salt_third_de": "F5E3DBC571628A18F0832B3A78BB144D",
+ "section_extended_salt": "50AAE9055970B5F6A79554148AFF1C67"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E6B40DA9CA1C23164262097414042F425448D4A63997DF8AF14FD97078365506",
+ "v0_identity_token_hmac_key": "9A47EAB582881AAA20B3E09F318008A01C2978ACD715BE8470399821D44B22A3",
+ "v0_ldt_key": "A83EE2141E4896FDF7E0E50F47162919E6837B02A778BE6C77EF84F06425231C7E6F66A403BDE3AB706D394392F8B215E2E1B6F8B135E7FFE487F8EEA553D5C3",
+ "v0_metadata_nonce": "78FA2208BF4A129F35882DA6",
+ "v1_metadata_nonce": "74E88D1A4199CAB29AFD006E",
+ "v1_mic_extended_salt_aes_key": "0B080F62AE2FBAA92991B9381E5BFBCE",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B3AD5C680CB808670B08AE7B3136A329CA755AA266086020CB13F5445D3AB90F",
+ "v1_mic_extended_salt_mic_hmac_key": "3D035169BBBADA723E634DCF0E203D7D0F85ABAA4DADC4C33D1DB14908C31D1B",
+ "v1_mic_short_salt_aes_key": "54AF93FD026428575900009294AF21DA",
+ "v1_mic_short_salt_identity_token_hmac_key": "B4F6A45A822954C251F04E5F54CCAC07FAD0826B5C323F4A9D2755E0E184893F",
+ "v1_mic_short_salt_mic_hmac_key": "6A8B6CAA0F30C013A40BE4535FA727FE47A832C4BAE0878E72ECE9DAC538807D",
+ "v1_signature_identity_token_hmac_key": "2EBBD9FA35E24808B06361017D2ED29263F9BD857595AEFC4336740485D3AA41",
+ "v1_signature_section_aes_key": "44C1F00F21E21DE548332224F191B56A"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "8C48",
+ "expanded_salt": "92DA955A90A7A181E9A744C7F64FCFB1"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "C60CB21C78BAFD9ED8A08E18C3DC9C1C",
+ "v0_identity_token": "B08BC761A0A1F9C72DCAC3168AF6"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8561",
+ "short_salt_nonce": "A8A5A0D023F982987C6C2912"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "731880CCE113A561F779D98EC3BED041",
+ "derived_salt_nonce": "1C3A582B0B0E6461B150A1559F122B76",
+ "derived_salt_third_de": "374E30A969CBB37DFDDE376E217E4427",
+ "section_extended_salt": "FD6B1023E870A6908EDA3CD8067004BC"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "B800FA4783D4EC4D80AAD9A805AD0F9CD1C26BAD38FC5655A8755A7768505014",
+ "v0_identity_token_hmac_key": "F1DD45F4F5C19D4344F7CB0C04F4EF5E5BF8B417A11E3140006A4F4CA2060652",
+ "v0_ldt_key": "B185F3EF5EDFE2F2B722A0DCB9904AB533A12585B6A3AA897FBCBD3B435BDA5EAA9E5A76C95D64C993C36687807C1DBC5846E9A9C2C386129FE9DA39AB237788",
+ "v0_metadata_nonce": "6EB8B910DC2F0094CAA873C3",
+ "v1_metadata_nonce": "600080C27BA115C7317BD754",
+ "v1_mic_extended_salt_aes_key": "B16E94AC636F789C62A35DE4F974319B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "47E5B25A33520F10E5FEFD1DA06E0908B671CAE8CAB54C5B40BE9541C5E18E97",
+ "v1_mic_extended_salt_mic_hmac_key": "3CED276A31CCFB412EF3E22B0E048907CD73A2BF39955B7C73EFB295689469A5",
+ "v1_mic_short_salt_aes_key": "9DCD2E8874EE2E6A092618AFAF397D20",
+ "v1_mic_short_salt_identity_token_hmac_key": "284F83827CAC37A22DC0CC2A3F10BDAC8A0E3859218C5DD5FF1F6277268FAD3D",
+ "v1_mic_short_salt_mic_hmac_key": "77FAA24269AE6A5A4B61569DCAF8AA75B155C8D483F32AA26ADDAC49C3AFB3EC",
+ "v1_signature_identity_token_hmac_key": "FF533E6454F471C4D5AE1CBE51A085082147480E06881A193CA0375D30305247",
+ "v1_signature_section_aes_key": "E0AA39A3E2D60041A8956A6B8A3FE4E4"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "BB3E",
+ "expanded_salt": "930D14EDDC1B681C49C2B315D3E89E16"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F498977D3CD6C519A4BF36C1C10A2272",
+ "v0_identity_token": "3B0DA1390CC2F8F53F5812FE80B2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "468A",
+ "short_salt_nonce": "147C2526D096E43BFB972E05"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "0E396FA0163DD119AF3097362E838146",
+ "derived_salt_nonce": "6B87889DA7443CA9F8D9526ED9C86B14",
+ "derived_salt_third_de": "9E91F27B911BF1CF6CBE13CF1BF43338",
+ "section_extended_salt": "72B71CE5E6A3534C17A0A3BDE29FBE0B"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "3E847398512F2295877A52FC6693C509A77D284B831AC46D17A35463141BB380",
+ "v0_identity_token_hmac_key": "9608CC1C06C3CF935FA9AD9576F7B0699C01190CA821A8BAEB3C196168DB7282",
+ "v0_ldt_key": "68803069E994A0549B92D48777B90B4ACAA691CB67EFD7407273A731C15E8DAD6705780FEB3F9776F22AE3313277E8A393EDAE23802EF457506152A082F9B2DE",
+ "v0_metadata_nonce": "575FF3DD58EABC3013DC3FDB",
+ "v1_metadata_nonce": "DF4C249AEAF7B8651989EE33",
+ "v1_mic_extended_salt_aes_key": "E7AD78F689F894E6415BA5A7538A6B8F",
+ "v1_mic_extended_salt_identity_token_hmac_key": "BB2FA7C1AF13564D37339BF793F69588259FE5F5744165C9DA3A2DCC31BC4DDF",
+ "v1_mic_extended_salt_mic_hmac_key": "A2B891CA3E764C78518ECB419C76EB9696F5B5489B7DAA59246A775C175AE8CB",
+ "v1_mic_short_salt_aes_key": "F511DCF5E5239F6F001CCEA3582BC561",
+ "v1_mic_short_salt_identity_token_hmac_key": "22C4B6CB1135E483F7703A06BC9F71BE65CC7901215DD30047F86ADAAFFF2216",
+ "v1_mic_short_salt_mic_hmac_key": "14D1B893A3947846911168A2AD7BF475D5B10B3AED3E16EB13B82A6AE9E3D5ED",
+ "v1_signature_identity_token_hmac_key": "2818C76B7C6BBC90069219FD3C9B3630A35582813A71627B00D6C255DE831655",
+ "v1_signature_section_aes_key": "AC76472156646E7D1F1E7DEB26409B8F"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "08A7",
+ "expanded_salt": "F848BC5C8A9B08E012A03B3A142F90E4"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "395560A60B904BDE2A963527473696C2",
+ "v0_identity_token": "8C8B58E7FACCD45E79BF08405433"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "D46A",
+ "short_salt_nonce": "E74FA992910E3A0F20733446"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "BE63ECA3139C3A520E562C416E4BD42A",
+ "derived_salt_nonce": "77699741250F48BC8D6C3C275C7129B9",
+ "derived_salt_third_de": "2D57D9556AF4D0076136D20FDBBBE600",
+ "section_extended_salt": "CF0DCBFE60B56E6199A39F86BA47CCEE"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F4FE47350546180E8E5343E508933EAE003797A3CDE161DEC844E9BD0EBE8361",
+ "v0_identity_token_hmac_key": "472974F3E94D84F6C1BF3D2F805DA381AA033B333B012F16F8EBCE6264E8B028",
+ "v0_ldt_key": "515D9B38BF19EBAD10149CC42317B96796B74284F7EA8C15E4F163A37C8FE16FF756F76AC6C460A513CDC0738886B0D2E472525762810A86D84D0CB8CAA23226",
+ "v0_metadata_nonce": "C7DD8B64D78078D2F303EA8C",
+ "v1_metadata_nonce": "817FBD157903FEB877409931",
+ "v1_mic_extended_salt_aes_key": "A9CAB585445FE1CEDBC7A2B8F1C83C25",
+ "v1_mic_extended_salt_identity_token_hmac_key": "D5BC4A745CBEDC33F297CFDA6D1BD14C8DCE74F9AC6CBC8D5EB1D96A5DFEDA3C",
+ "v1_mic_extended_salt_mic_hmac_key": "8E377E6E535A84940C721E088559D3AABA4F448464DCE43227B446E8DE373E01",
+ "v1_mic_short_salt_aes_key": "0CDBB34EE71BF6F99ED10A8DDB0A3D2C",
+ "v1_mic_short_salt_identity_token_hmac_key": "C3A22D602232DF672FEC71BA616D49C882E9F6140379629A38DCA2DDD8BFB394",
+ "v1_mic_short_salt_mic_hmac_key": "CE5169D9EC16AF2D039574A47BD1B892A57AB874A214BDE3C9F078CC527F9EA1",
+ "v1_signature_identity_token_hmac_key": "4DF918930A3D2DC8871481B4FEB538331D57759E6F0A9407A06D15CF05809EE2",
+ "v1_signature_section_aes_key": "756B3BC24AB2B332F46A02620630465D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "8F23",
+ "expanded_salt": "473F3FA8970C09B7EDBBF7736DED37D8"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "DB6746C617AAD634961C3A864D996DEF",
+ "v0_identity_token": "EB699C1CF261CA6323DA7797BBE2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "BF2E",
+ "short_salt_nonce": "EC8FC7EE9EF97564C0478CFD"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "5DC4750A1046E2318D30B4B2612F4DDA",
+ "derived_salt_nonce": "AC3C59C2FB8EBABD7150FD5B35F87323",
+ "derived_salt_third_de": "12C1E5CB114FA19F099E4E49C729B365",
+ "section_extended_salt": "2F130A2F720D4DA91B4C0AAC8B3F2F1F"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C299CC5A114DD4BA0600008349117F85F67333E87C01E772726CA97BA744365A",
+ "v0_identity_token_hmac_key": "86E6D0B6D73CFF4FC2EE2E16D4807D9BE50279BD23514BE123CD273C514451C3",
+ "v0_ldt_key": "1F8AB48896AB2E840310BE0A100EF4CCC8C54576C9C78EC9F433E152CF15D763F766E235198AA702E4BE714D605B773B4E1A6877EC85C2623CAA01C5A9BF8F61",
+ "v0_metadata_nonce": "440BC42EEED871404EAC99D5",
+ "v1_metadata_nonce": "7D8330F7E71F245D8C020753",
+ "v1_mic_extended_salt_aes_key": "45AD1594A7C622CE770C2D754E5F57B0",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1C7636E375A0BD3ED90FFE231977CDFAA8E392C6A77890BE59C4D9877719194B",
+ "v1_mic_extended_salt_mic_hmac_key": "F4C3B085E1887428A07A2EF526B4C54AABDC6A596864674297BD7225FC2BA7AA",
+ "v1_mic_short_salt_aes_key": "19FFFA58D00FE48FC03D4D5D6ABC1D4E",
+ "v1_mic_short_salt_identity_token_hmac_key": "31D79DD4EDB7BE05562955557ADD32358760D9AE327656F563DF31311AD4D2DA",
+ "v1_mic_short_salt_mic_hmac_key": "38846B9D18CEF86540E5F2D2C94E791B1756EB5BB3EEB9D28EF5E60B32D33C8F",
+ "v1_signature_identity_token_hmac_key": "2C78F12CB4F9F423FD2143027E04BEFC493FBE189AC118EC4E5BF6E2E2BC6328",
+ "v1_signature_section_aes_key": "B8E3B89FE6CB6F9983469499A29084BA"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "7AF8",
+ "expanded_salt": "D672F8F7DC19AE5A881214BC736A76D7"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "BEB747A470A9DA803D1BAF126C3EC943",
+ "v0_identity_token": "5A0CEE752584C7D960B4992E05F4"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "56AB",
+ "short_salt_nonce": "D61316F899E53429A2D50DB3"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "70972284567C448B649644F5B6EAB7EB",
+ "derived_salt_nonce": "CBF23EE5038C1D5C1D3CB7B1BF408DDF",
+ "derived_salt_third_de": "D99B02CA713BA66DC867CC60D2500875",
+ "section_extended_salt": "4C5CD144852DF461550C19312FDE138C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "BF2CD3D625C9ABEB44B0789D4BBF5A7BD4BE3A4B5A19DF04E103369C8FBD4F2D",
+ "v0_identity_token_hmac_key": "81950F013B4A13F7EF5B5D0B291C6EE4B1C62F911F3AD01F30B37699AE21BAE7",
+ "v0_ldt_key": "64489F1C234BBFE2217683F96A98B35E5BA4F4515DC6449EC5A711F4248D637F79AF342661904FA8B60DFF457BC879ADA4AC1CF5E73646F201E07594E58C316B",
+ "v0_metadata_nonce": "E48B58BEAD817E906CB7BE7F",
+ "v1_metadata_nonce": "89D0D8C13576F46B74195B51",
+ "v1_mic_extended_salt_aes_key": "CB093E649CF4ED1BA952819C983B0A49",
+ "v1_mic_extended_salt_identity_token_hmac_key": "F8D27C142C1879957C7B0FEABA93097D1AB2F1FE6CE2B4A780EF3B7E12A7A270",
+ "v1_mic_extended_salt_mic_hmac_key": "726C6770FD205CD85F732FED55421A4DB1D7F861E028AE144E883FA88128E099",
+ "v1_mic_short_salt_aes_key": "0CF33F93B242A4095821CFF75ECB9A95",
+ "v1_mic_short_salt_identity_token_hmac_key": "A0E1E2FADA968696B8A421D348021783D41BF5B92A8A61CBABAA3A605706FD70",
+ "v1_mic_short_salt_mic_hmac_key": "32774F6FC589A6A0F3C57D3A3FBDEAAA8C94CE31BC1BE2E71A770C29A365E8C1",
+ "v1_signature_identity_token_hmac_key": "3FA4A5EE8D7CB441D33519D371B615733E82CD99CE5DF704B4BEFFF525B5D484",
+ "v1_signature_section_aes_key": "A69439EEE9E503DC46CDDB7220E6C1BF"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "DBA9",
+ "expanded_salt": "D67693A7826F8BD42315C68A72C5FF35"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "EAAB13D180BC7816E235F2D5CCE25C5F",
+ "v0_identity_token": "953C70D3F668A9BF305EA11FA5A5"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9443",
+ "short_salt_nonce": "EFDA8286D9A7A9B08A098C9E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "932952F0056579BD3532A369D60A6F70",
+ "derived_salt_nonce": "0F8B66EE0EF87D7B6BE39BF707378448",
+ "derived_salt_third_de": "DED92B09B5BC920A8AECE3DB8C7AA0C1",
+ "section_extended_salt": "CDA0859A2285EADBE17556BD28F0D67F"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C759E0D5EFFC5ACB780EE1FF77B2B82808A4418F5103FCDE125ACBDA1CE010C4",
+ "v0_identity_token_hmac_key": "894B0D42B56405F75E28594CAA888EFFE173A6399B892C4AD6DBE49A197E3522",
+ "v0_ldt_key": "8DC248F5B78A21E5F1178157EFA2933ED5A57FAD965560FCB039FB41271AB5CC26FE160E3FB179E5DC04C15E51EFD2A13F4E861F3E85889457C8ACB0CE8FA4E0",
+ "v0_metadata_nonce": "988562C19FAF889DA9390D3A",
+ "v1_metadata_nonce": "1EDCB2F7F9D00FCCE80BEBE6",
+ "v1_mic_extended_salt_aes_key": "159A387D0884959C1E2EB955EBCE035C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "5646920E0104AB7CB77AB3391A61FF420129C1F499B13CA122DA6C77A3BA7728",
+ "v1_mic_extended_salt_mic_hmac_key": "2B2F8575D91F2B3964DAB5721DDED08B8C12AE5C0B984DEF3363994729661130",
+ "v1_mic_short_salt_aes_key": "EDE131CD4C8D0F1251E92C3A3BFF7BE0",
+ "v1_mic_short_salt_identity_token_hmac_key": "DF5823CB7AFD4442A6BC99342B13B9A94343570D487F47F99B15B41131FDC291",
+ "v1_mic_short_salt_mic_hmac_key": "729CDAF9889B1465960C519EA7C5A2D93ECDCF08A252047125284A6A4AFB8423",
+ "v1_signature_identity_token_hmac_key": "DFD3C298F8D8AA5091667EA7DA56C1749259021B5D046E18FCF11515606605EC",
+ "v1_signature_section_aes_key": "1F0821DA6799721FF225950245DC62A2"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "4BF9",
+ "expanded_salt": "F27CC32AEDDAFE2FC02FC67785977931"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "F857C81818AD95DAA7A218B71493D27D",
+ "v0_identity_token": "1CC5F7109208CCEF51918F37A789"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0E95",
+ "short_salt_nonce": "8D12E132EB3558CB5A2A1A0F"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "A568C7960F41860E4CD438B7E09DA45C",
+ "derived_salt_nonce": "82003458C32B5E1408B98668BAFCC9C4",
+ "derived_salt_third_de": "BC2E3F5E799FF967924D4C31E7A8A0C7",
+ "section_extended_salt": "CCC4AE71E0147BB16F2EBCCDB9FE31A1"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "398915BD66C14A84D4FDCD43C8F1DE6C8CF2BC38022B46C3628F3180D0D9C479",
+ "v0_identity_token_hmac_key": "91447A689F29B11D432DB5A28780ADEA084956BCA2F39040C5DC583036935EDA",
+ "v0_ldt_key": "B7DCF4BDF2590C365200462F2740B1A25108D174F2DD489D0B3AD0D60DA354E884A5FF038167D780A855C04B5991F37554BEB0D5D199C35F929601B38ECE4C0D",
+ "v0_metadata_nonce": "BEFC1162FFC2D7B05AE4721C",
+ "v1_metadata_nonce": "ABBEE58AA1A5C5902A66CDEA",
+ "v1_mic_extended_salt_aes_key": "49D90757E91DE84386B7606327779E1E",
+ "v1_mic_extended_salt_identity_token_hmac_key": "F2E067C282FAA0C1EB289976ADF992BC5C4774E0830E9D90F195259A859FD06B",
+ "v1_mic_extended_salt_mic_hmac_key": "905E498FA9444EFC1C23D87B1A48DFF08CD0F71199F5D4A33B0A8D9C03B687FA",
+ "v1_mic_short_salt_aes_key": "D023099AA0859DBB1547E3736DA4D22F",
+ "v1_mic_short_salt_identity_token_hmac_key": "9446AD8F40DE7801AE8C05F4198221C4545836FAFADCFB6A9F6B6811C17320C8",
+ "v1_mic_short_salt_mic_hmac_key": "2F437832F6F6055F3D9FC22E1FF89071C579F9261B200B1289E40BD1987FCE62",
+ "v1_signature_identity_token_hmac_key": "08DEBDA02FDB8250E3B6DD38CB14E6423F414733847634154DA243A0A48709CF",
+ "v1_signature_section_aes_key": "5AE2258B089A53E623FDE10A849660B9"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "45BD",
+ "expanded_salt": "3028028A24AC94FF0DB3D424F09D8E32"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "FA406BC38B6852DBA58B830C9669BA49",
+ "v0_identity_token": "D2E0463D56277A2CF9CC5BA5F85B"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9C48",
+ "short_salt_nonce": "DBC275D67654EFB6ECE3CB2A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F1C91B43A17919A92B1A663CD5214050",
+ "derived_salt_nonce": "07D78BAAB0539B291E17C946F94AD5A3",
+ "derived_salt_third_de": "9E1D2E450EAA994518580BE3F95163D4",
+ "section_extended_salt": "98646141DF3AFB3FFBD4DA56C170AC50"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "935ED1A8B2E5DA1FF777F1F0245CCE37F8BC20FF306A0A82C3F0F318E953DE3F",
+ "v0_identity_token_hmac_key": "5E33B312FFE3E016F7D8B319B7ED4CA72CA25755D32773210E5B758F75732BAE",
+ "v0_ldt_key": "B9BC506239E428193E0ADAE2705D1C5F3F75E502C45DEB393A07D095C2E1E58616548BE47F73AE0056007FEECF9D19DF78F8CBD0F0B4012BCD1E8CF45FE79506",
+ "v0_metadata_nonce": "F225F715CB7E592925BDFFBE",
+ "v1_metadata_nonce": "C07B2E089AEDCFE7E94CBEC0",
+ "v1_mic_extended_salt_aes_key": "E07FDEA905AAD3D0579B42F50705BFD1",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B016136199E5127F95390815C77AAC735A585A8861CB2805543352971D62951B",
+ "v1_mic_extended_salt_mic_hmac_key": "87FA6DA8F450D40085241D55E17EE0F1FAB9B4C51841663CF13DF7D84A03684A",
+ "v1_mic_short_salt_aes_key": "603CDFF82688718D13120372589636A4",
+ "v1_mic_short_salt_identity_token_hmac_key": "743FE98375D1C4D41B02AA9A636A92837AB4C5A588664CECF00E216ABDA17DBE",
+ "v1_mic_short_salt_mic_hmac_key": "1C67FC0FE2E06FE973DD46D4DB0D72A651376F61C8CEF15002F2FB511C05C303",
+ "v1_signature_identity_token_hmac_key": "58B127F990B55B164990917F1C23B485F3EC847DA2E27E0D541FC6F7AD437BBC",
+ "v1_signature_section_aes_key": "33F90FC36D254B78F3D0A1CCE47CDF2F"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "CEF6",
+ "expanded_salt": "889CF5AB8E18277DE8AB9CD2FEBA35D0"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "59B3F16B05BBE9202E78B12ACBB65F9E",
+ "v0_identity_token": "51B2C41F6AF7AEE74DCE977FFA71"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "E664",
+ "short_salt_nonce": "5DE9BC53D47908F83224673A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "4AEE99434AD2D226A375264CBAE0497D",
+ "derived_salt_nonce": "0F201B1E244712F3AE2B7C5DE056DE63",
+ "derived_salt_third_de": "282638440E3212C29F5E8654C6B8B9FA",
+ "section_extended_salt": "1A80A34BAC43864CB5BCFF4547F1B88A"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C0459E6013DD6B77DAC1CAEF84BC43BE04C7E171D5725375C5EC7BFD0A37DC68",
+ "v0_identity_token_hmac_key": "97B9B1371244C00038A4E32022D32B3A550BFA6611BACD1D56030D8B2EA37452",
+ "v0_ldt_key": "A23B8AE89920C1ABFC2A0994DDD4E3E8EA83B9FEA70F81461E5D51D5BB372C674E9D3CD59D5273D9D719EDEB749BF6CD1AD077DCC1E969D5E1715F91E23E8310",
+ "v0_metadata_nonce": "8A33A7C387BBCC7505C32AEA",
+ "v1_metadata_nonce": "A4DC2C766352C27F845EFAE5",
+ "v1_mic_extended_salt_aes_key": "90A5BFF37C46AC0B5CFDEB75FE20980F",
+ "v1_mic_extended_salt_identity_token_hmac_key": "99E8E1414155D0B5B79390615E2F9F80B2F519C00944C01C19450B4AFAA90601",
+ "v1_mic_extended_salt_mic_hmac_key": "20C74AAE9D32359A0C9353267458581B4AFE60606060B16060591CB96AC68F97",
+ "v1_mic_short_salt_aes_key": "11381F1734226C3C2911C7D1280E55C9",
+ "v1_mic_short_salt_identity_token_hmac_key": "A4E6D4F2475E98ACB5E95D518DEA87E90B1EB7D9D2F5AA1456C609CD5B5351AF",
+ "v1_mic_short_salt_mic_hmac_key": "AF6150F86F8AC3AE7BA32219E7B92B158E866EF8CEB36BCEDF6DB456CBBC94BD",
+ "v1_signature_identity_token_hmac_key": "6D27EB4BE29E556CE5A41BB89648D91314A73D60FE884CAE79BDC811115CF08B",
+ "v1_signature_section_aes_key": "E5C1080FA68F5EBDD6F3D063BBE0EFD7"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "DAD4",
+ "expanded_salt": "122911634C8C923FDF8CBCAFEEB31E6D"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "7B8A759E2B26F88A93F80FF05C5E5793",
+ "v0_identity_token": "F01DFBEDB49F8E2DF56B2A9FF832"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "31AB",
+ "short_salt_nonce": "D7A09F5405418C63649804EA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "C94F9B608026089CA2BF81CE363295F7",
+ "derived_salt_nonce": "302455E6682F71E2A813211487A3026B",
+ "derived_salt_third_de": "C289C64BE651B24E7365D79679EFCC46",
+ "section_extended_salt": "BFB748C26DD77BA9F8C82E7572B14608"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "FFD07DB5B2DC2ADB24E0EDABBF6089E579704E7935A4D1B185F6AB6F4ED93B71",
+ "v0_identity_token_hmac_key": "263FFE0A653F56E30861B534D9826FA459972D6142542CAE3B67B6CB478EBAF8",
+ "v0_ldt_key": "1D85D884D12A065DD61C71B3BE3818E116346E0C9619B89960ACC88F9B8875544B682771AA2BC5ACAB33F0BFAB45F8449A236FCB9EC64688A5F7F00BB7799C3B",
+ "v0_metadata_nonce": "B8421CB3EE4D1BA5FB006128",
+ "v1_metadata_nonce": "E5CD8BD69CB8D261B5AACA5E",
+ "v1_mic_extended_salt_aes_key": "9C22E81DEA2F0837A050CB2A78907AE5",
+ "v1_mic_extended_salt_identity_token_hmac_key": "6EB2EAE0D24668E4FAAD66C88E59CAF50ACD2F932EB11DB1DD2E5FBF93C04FC5",
+ "v1_mic_extended_salt_mic_hmac_key": "EF9D7AC607E5B37BB21B16409556162C6EBD3DD89144F19365698FB34E06A2B1",
+ "v1_mic_short_salt_aes_key": "1DFE937349A0968CEA77801B8B51E743",
+ "v1_mic_short_salt_identity_token_hmac_key": "9D1C138B75F9D255E62CC8806D36727DF5877CD831CF6CBFA9AA1D631D032F32",
+ "v1_mic_short_salt_mic_hmac_key": "9D1EFDC00D17243D29DF77EAD25DD34EE1E10E420B047D7C147769A1EC149AF7",
+ "v1_signature_identity_token_hmac_key": "E07194FE1E11686C87A325E511C7DB7DABA3B631878CBBC2018B70F5D75B843F",
+ "v1_signature_section_aes_key": "34EF3FADD1EA265EA5DB45B3335862B5"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D65B",
+ "expanded_salt": "47443B86F1FEAEEEA75EC5C4CCED0A59"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "BF1DA5BA126DF4B125488BBEB78B025F",
+ "v0_identity_token": "A684A924CCF85EAE5A0C7FA404D0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "D4C2",
+ "short_salt_nonce": "14E6E257738D5C3F8EA61A99"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "37DF3ED46159C7B50B7648454A8E3F6E",
+ "derived_salt_nonce": "B19C63BCBC2C5466B7CDD1DD160BC813",
+ "derived_salt_third_de": "7A52A770AC31BA84A31ABFA410398E39",
+ "section_extended_salt": "02017844CC8940E3F95FE27ABF392FDA"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "5D8DED0DBEF3082DF7666EE9C6413D7099C5D57CBCB7572519AD55596351058B",
+ "v0_identity_token_hmac_key": "1787E7BC8CD40D4E2156FDEB481F2D100EBE29515F26D88E7C5B47E4B4CE3398",
+ "v0_ldt_key": "907FE054670C2DDE42021BA1CD61ED49199E6A532044A55A3C842F0761A1A7EE4D9EC192745D3117D05D6BA4199C38435678A38F09FB91A28B80012A2E494299",
+ "v0_metadata_nonce": "149C72A3CFC258042CBC296C",
+ "v1_metadata_nonce": "61D13728AAD32435EA7F2C17",
+ "v1_mic_extended_salt_aes_key": "8F7D7FBB86A7B76027622311BD4FC4FB",
+ "v1_mic_extended_salt_identity_token_hmac_key": "E6D3AF59926AE7CA978F7CE621BBEFC1830CF8E20DB29B4748F97936CBF9DE32",
+ "v1_mic_extended_salt_mic_hmac_key": "23736395522DF94359771CA21DE0EAD1E27AE0833A8C02ED4407DA7BC71BB971",
+ "v1_mic_short_salt_aes_key": "917D6DC510048504D748A1251EAC8BBC",
+ "v1_mic_short_salt_identity_token_hmac_key": "D247C289A7F7C16473E7A8E5F737B2F60F1F281359A2E0E5976CA13E33D0BE48",
+ "v1_mic_short_salt_mic_hmac_key": "D917D8FE9CE653BC8AB3109DB07377B95CD9A0E02028432ECF3B71F933AFB548",
+ "v1_signature_identity_token_hmac_key": "A9E65F92433276507487CCFB1318EA841496C7C1DED9B963D843F56035BF2889",
+ "v1_signature_section_aes_key": "714014241942077D480CBEBA5C7FDA16"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "41D7",
+ "expanded_salt": "D7715923CE771A66E2F806CCB655CE28"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "3E342AEB8310CBDAB633C0FFC9B0ECB7",
+ "v0_identity_token": "E3D4CE4C1ED84B51283AEED98978"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "E61A",
+ "short_salt_nonce": "2B7D6083221050162AD11C2B"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "1479B6AE3A8F99CC6A421B7654E82B65",
+ "derived_salt_nonce": "DE3F081731C6B7E3B2155922FCFBA033",
+ "derived_salt_third_de": "B0BF305855ED8EE892A1574BBC35F1CE",
+ "section_extended_salt": "4949EB4D92049664AA78BA61AD0A159F"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "529A341BF82608D457E6225E80308FBA0A33945C52B8C711AE8D114F2719090A",
+ "v0_identity_token_hmac_key": "BDF73B8718898BB90871292D9819BDE09EC1C7039512896A7168500FD62B7E32",
+ "v0_ldt_key": "3A0805FC96D98923886D637A955144BA4018728882E7D8B47059A2D7C87FDC0E5F36536B7C494EE81D0857FF5ABEC9FEA4737ADF10F87B5A93618379B3A33CB6",
+ "v0_metadata_nonce": "2F655577FE85379259570525",
+ "v1_metadata_nonce": "589FA32CE6FF284F20D05590",
+ "v1_mic_extended_salt_aes_key": "E7CE9469B47ABF36531D71015AED7CA7",
+ "v1_mic_extended_salt_identity_token_hmac_key": "37433BA485D9F7F18D29122C494E7049754ABACAF6BEA52CED98716B8AA737B8",
+ "v1_mic_extended_salt_mic_hmac_key": "8A46B4B1543041B78B3EB07A68F4228B439E5AB139DAD332660482C7FE902FB4",
+ "v1_mic_short_salt_aes_key": "C5613A5B5FE8DC12550878B35E58E2DA",
+ "v1_mic_short_salt_identity_token_hmac_key": "A6C66389A16F81596893F988F31B3C3EDC871378DF687B6F92C069FEC3763C56",
+ "v1_mic_short_salt_mic_hmac_key": "A309E0EBD1838289BE98D58062298A7BF81743511FFE526162CD57C1A5DA7CD4",
+ "v1_signature_identity_token_hmac_key": "2727662B707BBB86574B63B085950181C10A66E95E365BD5E4BE2BD42CFFCD23",
+ "v1_signature_section_aes_key": "61539D6CB1E73FC4C5234E1F505EFE83"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C590",
+ "expanded_salt": "9155D976B94C493E5068E87CE6DC2B07"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "EF3AFA04327F12137EC7ED24952AE0C6",
+ "v0_identity_token": "E78783E55CF00CB3C377D47D739D"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "FEC4",
+ "short_salt_nonce": "A58A3AB41FB65068E3B2BE23"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "982466B94926A293CAFAD0D8DDB5E2A0",
+ "derived_salt_nonce": "9C14D11F87D3E49D71426882A36B793E",
+ "derived_salt_third_de": "53024AF2F7BEFA7D22D9F057CB75B285",
+ "section_extended_salt": "DCA57C5D334B5501EFA2C6C6CA66AC4E"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "77E25A3C9C6D94331B883F22A24EBE4009485DF2EB38AD4D3AD3EE445035AE92",
+ "v0_identity_token_hmac_key": "814E06DF65361B28EEA39EEEA07163115D3015BCA846A3897604B932A07DE31D",
+ "v0_ldt_key": "0559FC378F7A5013C179B9F39D31D5FF8E2E3DD8885228CFC0867D8661D89D035B8D787CC943CBC72AD6E0AA1E215290757A79E3C46D1CA406868F088022F14C",
+ "v0_metadata_nonce": "A636A4C45168D316F30E5416",
+ "v1_metadata_nonce": "EF9A34E9881450F2E1CE9D69",
+ "v1_mic_extended_salt_aes_key": "20E1180F0D29E99EA3461791BCDA9C57",
+ "v1_mic_extended_salt_identity_token_hmac_key": "76967879840F98B5327C103B6E439BB538F0D219F61EF65C7140C8008ED69F10",
+ "v1_mic_extended_salt_mic_hmac_key": "7B8ACCDD365A02C8E2DC4D3DA7CCE6D9B7F5C4EBD65A6513DC9992B9CBD1BEAA",
+ "v1_mic_short_salt_aes_key": "531F84D2E14CC3266E44ECBD6D6DFD96",
+ "v1_mic_short_salt_identity_token_hmac_key": "03B61A2222358A41D08AFD8F242C1905994D315F544DBE92DE9243EA46F0CDEC",
+ "v1_mic_short_salt_mic_hmac_key": "362E7C04F2606012DE5DC59BB8DD1F3B5F5EFE66F6C9427FABD1E5C8F4D2F76A",
+ "v1_signature_identity_token_hmac_key": "C8F25EC50826357C319A9AE60C043945C9A8013FAC0E2F2C623E22977E9B76C3",
+ "v1_signature_section_aes_key": "E2BDA03CF3781A80500F8ECA73C1A84E"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "A7B3",
+ "expanded_salt": "D041484B84E924130D68F058E9FB45C6"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "C3B32F82777B1C5EB860364BA7248ED1",
+ "v0_identity_token": "B809A4E6EFB05572D6474DBFF0E2"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "BCC4",
+ "short_salt_nonce": "C5FBF8210A55A6176527E35A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "4F8C73FA3C662FC6516B4E7D3333B663",
+ "derived_salt_nonce": "01D90834B89356931A7C575478271A43",
+ "derived_salt_third_de": "DF71CC3039A2C9EBE8792C639573245B",
+ "section_extended_salt": "E667569C7C35342D78598CE967DDD6EF"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "629137005F03D848FBC9A663FD4545698B82FC1A2A894DF9C41541A1B1B5B3D4",
+ "v0_identity_token_hmac_key": "46F120A4DF532721806D5D778D2C9E9178BD14D80F458D24001DCA4A22401CAC",
+ "v0_ldt_key": "07BF125D6472987365CF8DE0A31DAE3465F2005BED97016523AD98141CF4D4F68F6E5C193CE86F391474C6597827C371656D4339266E84202A174C5402C49386",
+ "v0_metadata_nonce": "ABF5B2E7D958BFF79882AEB8",
+ "v1_metadata_nonce": "86216A34350E9C1E045AD632",
+ "v1_mic_extended_salt_aes_key": "18B12EBCF7ECB1DFC20C7867D9B6207A",
+ "v1_mic_extended_salt_identity_token_hmac_key": "468A41138CBC76A60F8E1D472BB33152A67B9EDA3B7E79B9EADA3A3720FB3C8D",
+ "v1_mic_extended_salt_mic_hmac_key": "D980A878C750F1AE2C25A21C6045C8EECD81A0B45F400F10EEFB4222DCAE79BC",
+ "v1_mic_short_salt_aes_key": "EC807E84AF935FDCF6210EAFC261FC8F",
+ "v1_mic_short_salt_identity_token_hmac_key": "3683F211CF4FF6728E509372C732404FFD7A49EB6E2A9E011D8A2730A2766488",
+ "v1_mic_short_salt_mic_hmac_key": "ED63CB5202AEA05D6A666A9CF66AA76A0D10E6803A7F0A13C6303FC5D149B326",
+ "v1_signature_identity_token_hmac_key": "B1CB9EEB37699A13A225BDF36102A6E80610AA9A97B8A6B320E772FFDC6B5972",
+ "v1_signature_section_aes_key": "58C40319B83E496188B699111FB9A659"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "B8C1",
+ "expanded_salt": "1E42061F10934A6380306B3CE306CB35"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "5E342014C14C891E73C9AE86FD46D131",
+ "v0_identity_token": "AE279658E230EA4A84493249656C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3780",
+ "short_salt_nonce": "1BEE1C6648B348133DCF4E1F"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "E4EC66F0E365A49CAC1266A28F307798",
+ "derived_salt_nonce": "7478C715C11452249E821EA57A9832A4",
+ "derived_salt_third_de": "1A1F76CB9C0358FB86E217487B860855",
+ "section_extended_salt": "3E351E1A8DEEF7C30011566EF72CCF33"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "AB3AA3128FFAD716B58E523B678189AA0FC39C9D84F627EBF5D1A742E6B35918",
+ "v0_identity_token_hmac_key": "C24032686F78556724A111E743306F7B583E9369B80AF08B1A680A04FF46B3D4",
+ "v0_ldt_key": "65DD7D59DBF3F853296D96F35BF0C350740D0223DD2629A952FCC2B5349B49A3D5E6D41EC120AFDA492F331FB573F122930A98F506B1F9E34AB7D1F38F6E9461",
+ "v0_metadata_nonce": "9432AAEA580486B80C2CEE67",
+ "v1_metadata_nonce": "9682BC001611E3C0271E96CC",
+ "v1_mic_extended_salt_aes_key": "AA2EC2476363A9127ADF96E354A3694B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "05BE6AB4AD1FCC92C52883DB0FFD4369D472910C0E8417C551AB834962059472",
+ "v1_mic_extended_salt_mic_hmac_key": "378010DBE79B40985A0AEA35F7BDF9791E87ECEE34DB04D82084DEFA57ADB601",
+ "v1_mic_short_salt_aes_key": "15EAD484945F798DA57C65107009E5CA",
+ "v1_mic_short_salt_identity_token_hmac_key": "8B9F442893494B0D663B669AEEB2DB66D489B58FACDCFAE8D583019C16E72BEC",
+ "v1_mic_short_salt_mic_hmac_key": "B4EE0EBCBE390C849D864EFB7FBAEAC67932631186C729F76F3CA91BBC7680E9",
+ "v1_signature_identity_token_hmac_key": "A1673B9103B2253E455B8AAA8C2AE84DDD02BFEA7D69E68FE5D120E0B5E57B80",
+ "v1_signature_section_aes_key": "F7CABAA4EBF642DB0BCFA3C0C3EEA99B"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "B20E",
+ "expanded_salt": "0E708DF23FF58C2D7F3F2D38017496BE"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "23472C27E2F659A4AB1A428AF3018C91",
+ "v0_identity_token": "9F3043710CA07FA18EB47719FEAF"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "1FEA",
+ "short_salt_nonce": "9DFE98ABABD5693077D90FFF"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "013B34285047C393204A70E0056B0308",
+ "derived_salt_nonce": "BF792D32CBA8F57028F7EB5BF225CB6F",
+ "derived_salt_third_de": "208228C6462B7671161768D2DE2FF375",
+ "section_extended_salt": "973ACE22CDA6F8F49B74ED9878CF3437"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "96DC23CC175FA4AD9D019AD2697C766174387A431AAC413879F1E58A990EDF3F",
+ "v0_identity_token_hmac_key": "B816783CD9584B43744F9090F8190EFB73C065D80C55D42C5B0FB3E703BF3A3B",
+ "v0_ldt_key": "9A9E7488F70951A6BB0E9E73D4671A1B12B0C5EBB1A59D81258FE4FE80987B67AF2679B36873998CD5236433AA9FB12EFC52E66BC013B86583255FBD10C5C7D2",
+ "v0_metadata_nonce": "1ABAE096CF985C4732EE035D",
+ "v1_metadata_nonce": "7E7DB680E724225C9D1F1C26",
+ "v1_mic_extended_salt_aes_key": "A8C561D529E333D9B72002E0BEE43630",
+ "v1_mic_extended_salt_identity_token_hmac_key": "F45A244E0C64DF9AFF0CDACC2871DA35EE197C565CB47314A2158E944E0DBFAA",
+ "v1_mic_extended_salt_mic_hmac_key": "43950758403417002A184DDBC4991FFC5F0B2BC9CC8D2302784D6B59163546BF",
+ "v1_mic_short_salt_aes_key": "DC18AEDB7EF362A00A8A050D44860877",
+ "v1_mic_short_salt_identity_token_hmac_key": "CFB49BD705D54AC75EC449E1BC2D84B405FA970C728BCB004884DB70AB4E9C0D",
+ "v1_mic_short_salt_mic_hmac_key": "2D9C3E637E1E387EDDD22E586AC029A5FE0FE380502E1F9B1070869806EDA0F9",
+ "v1_signature_identity_token_hmac_key": "D8AC46D57D8F97D333705D9E37582923CC64EB9269692E044CB6F42B6EC7A1D3",
+ "v1_signature_section_aes_key": "3408666AFBFBA0F7C6B1956FF696A7BE"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "697D",
+ "expanded_salt": "87DD6D19A23B02C55F35861FD900852E"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "B893C7D62C8D5D6C4D27F2F2E89A9388",
+ "v0_identity_token": "1173E9D7D4E23D4FA3AE5FED5C4B"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8D74",
+ "short_salt_nonce": "A07118DCA162260AE3431760"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "E64BA2437291F00276F06A9686145AA7",
+ "derived_salt_nonce": "0CAC865313B2A15A5080ADFB9217E5C8",
+ "derived_salt_third_de": "6FD2414155FFA0177A9F6417B607C3FD",
+ "section_extended_salt": "AC9AD659EA00A4265C647D5B46D4EB70"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1658D40CA1FAC8A4C15A8EE96A25434C631C2E3D2D710C74DBEDFF18D12C08A7",
+ "v0_identity_token_hmac_key": "396915CF17C3C5A9369928620FC934DF1A64641D9C46449026D74E47E3AF559B",
+ "v0_ldt_key": "6214EFCAA3542FEA0E81A3A5BFBF077E1CF90222DAB3DA4826218DDF8A41A28A2F09C2D2F75E50C24C0DD402BDB343D4B647A94819D3455A69D5B613EE36B90E",
+ "v0_metadata_nonce": "0DAB2F8A9B3C8741A7B7B27C",
+ "v1_metadata_nonce": "C22D7E7354F6A505678AA3B7",
+ "v1_mic_extended_salt_aes_key": "C6A465F79147E737D969FC5873DBF96B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "32379AE42B10574F8D7934F0D75E7CB0EC82A6C7E5F626BD8DE737C3F8964F8A",
+ "v1_mic_extended_salt_mic_hmac_key": "9B25D3914B0CDDBDF5B73F2F95BEDBCFAAE65289D6649696D91C0BCC8926B619",
+ "v1_mic_short_salt_aes_key": "39C321D60F6E9871C6F0E5F08021894B",
+ "v1_mic_short_salt_identity_token_hmac_key": "67F7D65051D4339DCFD118B55233214FDF6A4D22104C123490267C0A68029A37",
+ "v1_mic_short_salt_mic_hmac_key": "97B7E56E79C9F0E05ADE70F6E85B0104B08150A1BB253451FEE37A02AB2F607E",
+ "v1_signature_identity_token_hmac_key": "019A2FF53B587F6B45139C744973D4BE7F6BAD418625181AC3F0404CE042F125",
+ "v1_signature_section_aes_key": "FBAF3E389EB39C82A87E36BF26459FEE"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C489",
+ "expanded_salt": "830448B54A2F8FE3CF891DC67A61FE6C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "C97A235E30AD867BD583C5465BAE98C6",
+ "v0_identity_token": "C9F646361843A0AA277C1786D452"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0043",
+ "short_salt_nonce": "5E4D5C6D9A148F2E2695D39F"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "EC8C3C7B3A563015AD914D065F065C42",
+ "derived_salt_nonce": "40842C94F4F5046882D39A1F353F5174",
+ "derived_salt_third_de": "CF99D9895D39ED5AEB35E4596C63B4FE",
+ "section_extended_salt": "FC4A1004C457DF7D85788332C3ABF9FE"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "8F5CACEFF8E195DC29A6418D15E42C22D93BC3893EC740FBE9DF3BC36A6E87C5",
+ "v0_identity_token_hmac_key": "B74E9A4B1A1967E5F37362FA6109362D3A93F2EB4D4488D938EBEAA0519B82F7",
+ "v0_ldt_key": "2961475C355C92A682E1AD7A0B545BA5F91B8D1C97396C77DFFE2CEFB7DFC564A8816469472B28611021D03424545C54FD68C87BB3513EB5B1E7B96614965D25",
+ "v0_metadata_nonce": "060B128C71924E5F35403978",
+ "v1_metadata_nonce": "0CAC86A9E31724738CB16769",
+ "v1_mic_extended_salt_aes_key": "A16666440709AF7D91C3FC11C0F40BF5",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B54A57DC9F832214FB383DA4123ED089B16C28480D4097DC57F108272C0E53E4",
+ "v1_mic_extended_salt_mic_hmac_key": "73766408361E3A670635EEB7C9FF70A72116819F94576737C06FE78910063502",
+ "v1_mic_short_salt_aes_key": "0C8A3C2D081449F4F263E11730F59385",
+ "v1_mic_short_salt_identity_token_hmac_key": "E46EEBE36262EF589672F67E20DBBE24DC18B863DDF4CF9D8330DCFA3CFAA3B2",
+ "v1_mic_short_salt_mic_hmac_key": "5CE78E09F37386D4554DFC39B22E4AAF28F812D335BD372583B7C3F1A1552B9C",
+ "v1_signature_identity_token_hmac_key": "B947D986D221E4C06CF27FD3352674D5DE51FF5B14885E36074D363B286B28F1",
+ "v1_signature_section_aes_key": "49A0920DE44EA33D0E2FDD6217492837"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "28F7",
+ "expanded_salt": "6CF0800012002D2E48A3A5A8AC857378"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "A0BE87B5DEAEC03D93A1BC9C10DD28AA",
+ "v0_identity_token": "412DACDC38349059C26766C5F8AA"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "29B9",
+ "short_salt_nonce": "17F243E45941156F9CB40E66"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "A2D63A55BABCFB0F636B0D3621C4CF0E",
+ "derived_salt_nonce": "7DA7DEB96787A854B3B02CD1D3D90BBC",
+ "derived_salt_third_de": "4A653154FF6C376DD0EB5CE64FEA70A1",
+ "section_extended_salt": "8B2303C4EE99348E3B5B34EAF99E29E6"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CB59F22A81FE55D0C5BC1B5D22D4212A811CD1138477D21FEBE17C5E217C87A5",
+ "v0_identity_token_hmac_key": "3BE67C6ED8D821E5C74A7E68A7C5B570362975613E1F974DB855546D0151E3D6",
+ "v0_ldt_key": "9F6C8A4BCB91447656C00ECAEFF72A01A2EA4B66450A3F70B0D1FBBFE70ADCCB4F69D8DF956F44CA877515D21ECADCDB425DFEBF5A3D7025F1D7603E05750A29",
+ "v0_metadata_nonce": "D7E7D92A0A0A19575DAAFB88",
+ "v1_metadata_nonce": "B51766263DA243F02A43D0D5",
+ "v1_mic_extended_salt_aes_key": "37DE33735A25248A6557BF1A68031161",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1AF94FDE53770179094074B778B0F0F9C4F093C33FBE149C6D597CB20762B36E",
+ "v1_mic_extended_salt_mic_hmac_key": "CAB44B647CEF4A189CF3B89428DFCF4D8D7EF74AA05252D4E2D1473472B17E29",
+ "v1_mic_short_salt_aes_key": "480B8E97EC00901A06850E0746BADF25",
+ "v1_mic_short_salt_identity_token_hmac_key": "6CDF2DF6C49DDB32051C172679F731F040549742B92758445712E5380DB052EE",
+ "v1_mic_short_salt_mic_hmac_key": "751622D2D36222D292DB1FA835FAC4676610C27FE961AC28B6F19EDE4FE6D233",
+ "v1_signature_identity_token_hmac_key": "DB49365A1148EFA93B856ADE848B15DC81143FFED26E29811ED4B400D3C3D880",
+ "v1_signature_section_aes_key": "8376773D764F42C0C02209207DE4AE80"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "FF69",
+ "expanded_salt": "C45C95D99B373A3ACE8CD7D1889F0013"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "47F9BAB879C0FA2AA98428A7FDDC7463",
+ "v0_identity_token": "CD1F7F15A691D8D7C30C42CAF69C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "C115",
+ "short_salt_nonce": "78A4DF6F4645BF6868D3B8C0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "557438A8D86570CB0179CC69F8B1653F",
+ "derived_salt_nonce": "4BB982A676DCF6715DBA55A5DA00D25A",
+ "derived_salt_third_de": "F250FD05CF2307636F60750CE5E9B323",
+ "section_extended_salt": "941E0C341EB666240EDAAD47239DABD6"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "ED908C5A4DCEE6429570F2DF17607E087EAD24F213D1A11EBBE62128AD2CBE07",
+ "v0_identity_token_hmac_key": "6C7B5EBBDD2DA8F1C411A367D3049C91B8C3B1CA6BEE58BD5979CC4A7AD3CC55",
+ "v0_ldt_key": "AF41A2C1CF19A7036CBDD5BE73C1F4C6D035A3FD205588931348B680B8826EE4A9915E6697DB8F4EDE0751DD746CD52A4A1A3C682B515A736F8407717A0F8ECA",
+ "v0_metadata_nonce": "AC353D32F3A9AA176DDA755C",
+ "v1_metadata_nonce": "F5D1D9471B14EA7BF02C3E61",
+ "v1_mic_extended_salt_aes_key": "9094F93C7C363EC83C62938E55F34A45",
+ "v1_mic_extended_salt_identity_token_hmac_key": "CBC3A7ED9BD82335329FC83EAEBC6C57A17D41A94C9E57F5C53EAFA29E3E6FBB",
+ "v1_mic_extended_salt_mic_hmac_key": "C8C2EBA26F834A9E3C96C2B7E4F697D1A180FC8F854A6169710120DB29BF0C0F",
+ "v1_mic_short_salt_aes_key": "CA6577851C9BC850A88F485732FB4C52",
+ "v1_mic_short_salt_identity_token_hmac_key": "EB2B6628523226BE853EC1A2A23C8B8F210B1C4B40EDA72435F65BFEE3AA066D",
+ "v1_mic_short_salt_mic_hmac_key": "D17C34BC36306CB1AEC52A7125B0E7D6C9A50F4B9DAC6015BBB9D6E933E7A2DF",
+ "v1_signature_identity_token_hmac_key": "1527905BF57561A93D2EE2509172BFB08BEB8D1456D17B0227C3EC621766B850",
+ "v1_signature_section_aes_key": "4EACAFCBAEC4739EC7726C78BC27BEA1"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "581F",
+ "expanded_salt": "A5DD61D8ECA1EBCE4C322C8E080C9AE8"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "8EEA2717A9052AFE66226349118182DA",
+ "v0_identity_token": "9675B523AB5F81A7ABF9903D9C7D"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "BA45",
+ "short_salt_nonce": "BDAD50E1174C4F1A4011335B"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "C92C5055A19F1B8A0FD1F07705B454DA",
+ "derived_salt_nonce": "C2603BFA63695C6D3CF9F8C294217640",
+ "derived_salt_third_de": "C3509C601D0F373B0875B6B1F7FC7D9D",
+ "section_extended_salt": "782DBF528A022F527A00408A045CEDE2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "3F7B6F2BBEA10535F2EB1830A466A58D1976838B2F56929C5632DB1D35DB9FA5",
+ "v0_identity_token_hmac_key": "84CAA04B2BEACAC2481CB59E58F2F8D2750130791DB02F906ABBE8AA778F8DF1",
+ "v0_ldt_key": "EFBA37A2FD32D2AD2C89489B2ADD958DC689B71CB85FDC132708BEAA5E450FD34F585CF0C40386715ECC9B1F334EABB5C6E9D071A0FD98DD752170F898DB0DCC",
+ "v0_metadata_nonce": "FAAAE5DFA198AF0DB586D4F0",
+ "v1_metadata_nonce": "1200358F9DF02A61AD1B3720",
+ "v1_mic_extended_salt_aes_key": "444C1136B55AFB20194F8485CDBAB199",
+ "v1_mic_extended_salt_identity_token_hmac_key": "DADAC9D5D6272025A43765625864D677B563A0EC550ACBF1D42D1F1C89C3ACF4",
+ "v1_mic_extended_salt_mic_hmac_key": "15F1121625072AE546BE7E9A17CAF4C7D85F084CB0BEA894495F1CC37E97E60F",
+ "v1_mic_short_salt_aes_key": "6452C325F1DF8A9E0D4B6D4D9EA59A7C",
+ "v1_mic_short_salt_identity_token_hmac_key": "4397BF6738AC22CFF3C4272C046F488139107476E2566FE66C789E240A624803",
+ "v1_mic_short_salt_mic_hmac_key": "A7FD1087175D5FD000D3FB744CA35120E232C54DC167B776F42B9EB5A8453079",
+ "v1_signature_identity_token_hmac_key": "368BFF1160B108CE21133C215812D25D36FF6669B72C4B88BACA2D31A597C8A7",
+ "v1_signature_section_aes_key": "351F043D8B6435E5E73684B10F79471B"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "DE49",
+ "expanded_salt": "FECD5D5E1E04B1C52AE646C5D47B1B26"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "573FB84EA56E4DF16BB17C0281D245AD",
+ "v0_identity_token": "EFD9C7521556995E1E091848A8B0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3FC4",
+ "short_salt_nonce": "68CB8DB099FC125FE4E2AAC3"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "9DDDB28462DBFCA74F63FC476FFE3D46",
+ "derived_salt_nonce": "85989FA93A8C9A85A7DA598529479045",
+ "derived_salt_third_de": "FF1A21F20BCB2A86AFF9A29CB42A3C46",
+ "section_extended_salt": "FA9DB8C9A1376BA0265420D4B0588C21"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E21B543EBF98DEE5174CD576F4F719ECDBF30F15BF7635A11749DD647EAB06C0",
+ "v0_identity_token_hmac_key": "6889E19D6A9AEEFA4E19A699E0FC8A813B709CE5BBA105C8FD6C6100833F8985",
+ "v0_ldt_key": "2EF57271E0BD7D977086265C78C8D0A529D5E70A3855DC650EBF338DF0F914394CF7DC5368B46E8F8E921D9D69A00BC04B2ADC01CBA954190669D1D4DD3B4C03",
+ "v0_metadata_nonce": "9D1D2B472358E5E253B9A79C",
+ "v1_metadata_nonce": "6F6E74240EC260B896F73EED",
+ "v1_mic_extended_salt_aes_key": "10A906B13EFDF85CA05741262EDAD70B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B77608559C639713B7E58B631DA3706B1D1E90F95871D4CDAC3F65436195946D",
+ "v1_mic_extended_salt_mic_hmac_key": "3A3BDEEC0AC9D04A2EC9E03D8B32BB48BF7EFACEBC4D946D8FF6B814D5661234",
+ "v1_mic_short_salt_aes_key": "6914FF089524DD20681F6A250A3C2BC0",
+ "v1_mic_short_salt_identity_token_hmac_key": "0B75CD46D539DECA8A7D14F4F7ECF2F1A2618FE449722CECC2816B5D674EACB2",
+ "v1_mic_short_salt_mic_hmac_key": "19D33DE899A50CE211E3BA3727669A6470EE3F52B17AC200E5FCD6FDFD000D5B",
+ "v1_signature_identity_token_hmac_key": "324954DBD6C28C2DB4C1918C3C1964FADFCD0DC2CD5F3E1F8EF870DE57059F5A",
+ "v1_signature_section_aes_key": "78F98654143E5EA976DC7EF3080C4E99"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "42AC",
+ "expanded_salt": "1D31BB4D6407E99C1009B34ECA9488B8"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "96D5FFEA8F177301FB6C714E41DC89CF",
+ "v0_identity_token": "66F176D3B94C02ECD0D4FFB70273"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3884",
+ "short_salt_nonce": "6C06CC0653B5BFD0AF6DEEC2"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F7684DEFAC951359A02D3C3478964CA4",
+ "derived_salt_nonce": "89DD24B2821B57501E07BF8913BA5B23",
+ "derived_salt_third_de": "381D3B6413BE8703AFFB0D17B38D372B",
+ "section_extended_salt": "58A07B28332F5BEE07B5B2B6501DE060"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "37FDF4CA1BB248C94ED307E5E1764EC0165EA1E981CDC24D6EB13DAC7605CF9F",
+ "v0_identity_token_hmac_key": "07BE3BF8E93F634BCC23B83B7B417DDCB274E250306265BF7FC4A968273B5FEB",
+ "v0_ldt_key": "60FFD2A67E1C4ADCE2D76A3DC22C0C019DE651E563B3DB348BC297BCBA807FC85647F2769B793C77DCE750B36B20070A8C3F9AD83B5A2387C4EB56A9E3FAA6B0",
+ "v0_metadata_nonce": "29107E6A280BFBEAEA342EE9",
+ "v1_metadata_nonce": "FF7F2C8E68DE7F6D85C495AB",
+ "v1_mic_extended_salt_aes_key": "8B784FB1DED40B601E99C37E0D5AF873",
+ "v1_mic_extended_salt_identity_token_hmac_key": "DB2CAF59508F29C763E7C9474B976D98146DE1A82043081750B96E64D8D54DD7",
+ "v1_mic_extended_salt_mic_hmac_key": "FAD94CC0F43729C896A4B38B6FC314A30A6235336FB9144857F74DBA62446C43",
+ "v1_mic_short_salt_aes_key": "DA65AAFCBBF298770D7E4C20E8ED4015",
+ "v1_mic_short_salt_identity_token_hmac_key": "A67A0798A0395495824110A9ADE3520DC3E80110046C46C31AE59B133A31D8AD",
+ "v1_mic_short_salt_mic_hmac_key": "A2BDDA2BF237949C6F6C25D8A5138966D2E2778FDA5692C61CC8DD0B5CE06CCF",
+ "v1_signature_identity_token_hmac_key": "E046453AB6F68FEDB7A960170A2827B28037DDC8DA1E7F73D3CC8C83A15EE813",
+ "v1_signature_section_aes_key": "445F1E3B3AA663DDEFE1E5C0F2AB972C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "9EA1",
+ "expanded_salt": "5A3B5015E1D58841D0A30728A25F4604"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "830783B4EC92685F1E440371840B7E1B",
+ "v0_identity_token": "AB8F48A84D5F7B02FCA0E0D197C9"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "AAC4",
+ "short_salt_nonce": "BAB0729453AC44CB60695F7A"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "FF510969FFE54C346C277BCD12314A23",
+ "derived_salt_nonce": "C858D33D065BE6BE321F09A182E4E0B5",
+ "derived_salt_third_de": "8C972C1345CF4B88552917A6C0AA0132",
+ "section_extended_salt": "947F9A9E1AAC92228E70B97E686092B2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "BF78AE44C8BFD059E8A47A00B4678650360D0BFDD8D58821722ABC1B78FA6E5C",
+ "v0_identity_token_hmac_key": "E185FF7397CBB44FA99048A46EBB22C624BC1E3A21F2ECEDED91686440919752",
+ "v0_ldt_key": "6FF4D69DC4CC5D5CF17589ED7EA6FF8843D4785FB5AAF89B8989E5C9EADF8B915CF0F2A2974240C8A7C49B571986E4BFC93F3B9F9D809A69FD89DA0C470E91E6",
+ "v0_metadata_nonce": "F25EBDA155405BEA86941F45",
+ "v1_metadata_nonce": "7787AB19C65497386A035A57",
+ "v1_mic_extended_salt_aes_key": "68A1F6E9E2E703728795CF51AB018597",
+ "v1_mic_extended_salt_identity_token_hmac_key": "A93B60B9DB23C48E2128EE8A0C982FE2256BAFE463F51C99E1FF0D6A5036EAF3",
+ "v1_mic_extended_salt_mic_hmac_key": "BF3E481EEB971717B448D4EDB765F2C9291C3165A8C021742E3B33D84474772C",
+ "v1_mic_short_salt_aes_key": "C30DBBFFD2A16E98895BD9EC2D7E724C",
+ "v1_mic_short_salt_identity_token_hmac_key": "B0B97E8EF4DCD33E40356CB2D6D7359517FCE3FFC7B8DBD4D73FAE87CE0D0CB5",
+ "v1_mic_short_salt_mic_hmac_key": "7AA526E8ACBE888A47E7F042DA3751FBF8988294D8286208122C55C2322D5F25",
+ "v1_signature_identity_token_hmac_key": "5EA50122D84E384D7C4B2105A182BEEC7A4D8CBE266B54C51D70F2186CC821C4",
+ "v1_signature_section_aes_key": "E9E31EFF10C7F9F2634BDB89CBB407CF"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C543",
+ "expanded_salt": "4C4AC44FEA185B78FB54A3A2749DC65D"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D5E805DA2CFD12C67BBC380449E48324",
+ "v0_identity_token": "095409BFC1116FCCCD80F1ED602B"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9D8B",
+ "short_salt_nonce": "FC8A1484820906156C195098"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "E4CC4A82D88EA39A5187A28FBDD40F3D",
+ "derived_salt_nonce": "B5807E2B08DE99DC9EA01E9478282DDF",
+ "derived_salt_third_de": "E3CC102DB32458B2EAFEEBB6113DCEC2",
+ "section_extended_salt": "2E250B90A61C0F513340D930EA6571E4"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C458B31EB8502A483EEE8D5A804249BEFC113FA503018A2E65E91AE51F661839",
+ "v0_identity_token_hmac_key": "7681A1EA463DDD1FF1B10F87A8FBFB4C2069594DDD3B552C097154307BABD2FC",
+ "v0_ldt_key": "39C6E02DAA80BA8207A150BDA0241C3650F128706F413B9094997C661F0B722AEBD00042675F9BBF574A105505866B688EB115AEC0DA430BBB3AF5AA2B3B082E",
+ "v0_metadata_nonce": "6CDDAB688C8E27055A4C7735",
+ "v1_metadata_nonce": "E6B46B1329265F0BC3647652",
+ "v1_mic_extended_salt_aes_key": "5EEE9AB4B0A14122DA37583240569EEA",
+ "v1_mic_extended_salt_identity_token_hmac_key": "F0721E6BFC42BC07755E5838705139246B39637F18E9D6DDF8EB76E8E7BA64C5",
+ "v1_mic_extended_salt_mic_hmac_key": "D115FE4B3ED3D6FF3C457411F89EEC573FB6B4FF074844250F10D923416A951F",
+ "v1_mic_short_salt_aes_key": "10F209765DD1E2848DC419C4268771A6",
+ "v1_mic_short_salt_identity_token_hmac_key": "9FD5A74F6EC544AB29AF7CDF130FEAB9D22B37A4178E7A4C7703DCCE6AEAF4C7",
+ "v1_mic_short_salt_mic_hmac_key": "DB1E2E8F93CB7D9891CBC951DDF02E89B0E77F646EDB9BB4A33F936F7A04F693",
+ "v1_signature_identity_token_hmac_key": "419EA078DEA8DE15D57ED34A497920F671D83425B204F2C364CA506B2A4FFAE9",
+ "v1_signature_section_aes_key": "519EA77C6FFACDF488BC05BD1E45C56D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C2F8",
+ "expanded_salt": "D20BB79365E7FCB7B41D40D18B29D56C"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "5436E96BB1FA5BEA3F61CCF4D1334D7B",
+ "v0_identity_token": "01395F4809126DDA6EDB05CBF274"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "D382",
+ "short_salt_nonce": "AE407828507152FA369D8AF9"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "93A5A6F16A869EFF9F4147B3BFEE2779",
+ "derived_salt_nonce": "51BA87FE075BF338688B780493445A1F",
+ "derived_salt_third_de": "534680E817F3E8366D19AA564ECC2ECC",
+ "section_extended_salt": "58FE62A2B35E250EC7A5F7885357E659"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CAD145B4C4E7B40281586C90415BCE0B1D259E400C12A4558F848D4DB3FF6022",
+ "v0_identity_token_hmac_key": "094878A6B8D94529F33F759B6470003F5EC5D9E9D12D76C245E2E839E98C855B",
+ "v0_ldt_key": "23B0AA6A58D05FA25ADAB4395B948F2718CE48537875D2E68DDDFB38690D96B9A36913007ECF4A030BA7E00E96A7DA7BCE138FEB92FA1A4569F867EC2D881E18",
+ "v0_metadata_nonce": "CBB1C6591A06FBEF5D13C1BC",
+ "v1_metadata_nonce": "B3406DFBE1D1320184D9721C",
+ "v1_mic_extended_salt_aes_key": "0A47274588CCF8ED3772C654A76F7558",
+ "v1_mic_extended_salt_identity_token_hmac_key": "70FCDED0EA67404EF350C5167978234B681BA624C27334896364FDD77C4CCCBD",
+ "v1_mic_extended_salt_mic_hmac_key": "4EA92D6148AA2F61D283E1DB8AE6EE1066893C4A898BA503145CE493F2AD5400",
+ "v1_mic_short_salt_aes_key": "83F56E946E80C574D9A6C89975DEF2DB",
+ "v1_mic_short_salt_identity_token_hmac_key": "5CA60D709F88F9D07556B4A6E6A4CDE9DF1DBD280BABA39BE47A13FE90E5E27D",
+ "v1_mic_short_salt_mic_hmac_key": "33E1065D5BA0349E161E41D873B194379EEF0D2DEE466805D72BBE01F6349F2E",
+ "v1_signature_identity_token_hmac_key": "58A6E794B4593108761562A3C74CA4EDD345EFAA08F35E661B97FF113C24B6A6",
+ "v1_signature_section_aes_key": "1DCC7FBD666A58BD52FB5EB65A63251D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "94D8",
+ "expanded_salt": "0F9CFE35B1EB9C140FD004A84FF23100"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "FAB1FAE5BB91A22DAE1792117AAAF36A",
+ "v0_identity_token": "2A341B1B61F1ACFB5D74DA044867"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "7A1C",
+ "short_salt_nonce": "E006CD94A4539C0185D8A480"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "28AFE5F7B2249029B8C64188C46E8EA6",
+ "derived_salt_nonce": "72B2C14A669C5CA1684D7E4751793E2F",
+ "derived_salt_third_de": "93DA04162B18AEE23A3056DD6B53B447",
+ "section_extended_salt": "E3D5BA66BFF1542BB9E864F1718972EE"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "4ACA5648232134F2F67CAF1F73A747C79F05C5433006D6B0499E41C99CC7EDC5",
+ "v0_identity_token_hmac_key": "E5BFAB30F0CDC766E0A2CCAF2748F1C2D3A4C61F807EF3065AA632C1E031849C",
+ "v0_ldt_key": "8E8A67DCD76DB26CA1F35044302978C4981B6934A03F8431C737D66529E88C752B6B85C8585C3C4F5D321DA0C8297BB6112CC63878C69ED84C97EDAB95AA5BD5",
+ "v0_metadata_nonce": "6457431AEFBF8D2360A0892F",
+ "v1_metadata_nonce": "2307C5893275080E5C6B7A5F",
+ "v1_mic_extended_salt_aes_key": "49F7F9AF2E1AAE200CA362CCB2D8DA5C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "DDF91ACE824007F30BD268501F411F2926B578F675DA58158B12ED67C29DA6DF",
+ "v1_mic_extended_salt_mic_hmac_key": "5D68D65D0C1926E664FB9DABDEC88B84A1151479045FF66BD520E496DA11BDE1",
+ "v1_mic_short_salt_aes_key": "4201A2259722BA7647492CD28EEC1AEF",
+ "v1_mic_short_salt_identity_token_hmac_key": "B827390AAFDFFE4121E501DD5AB0F63FE99812B0AA19EE5D3CCE8371BA8D8565",
+ "v1_mic_short_salt_mic_hmac_key": "14E7069440F3314D316424A4C05B14781FB8057BF555056B4DCC1CCC01CEA5F6",
+ "v1_signature_identity_token_hmac_key": "CEF4CC2BC66B6DA8CDE0BDC33CDB0544A482E693D0AE8E4776D2C50EB3141EDA",
+ "v1_signature_section_aes_key": "26D03E938464532CBED815DE327C0E53"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "5883",
+ "expanded_salt": "107D3AF4F533B1415860BB88500FF30E"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "B5D43495932EA4AAC04D597D47F3E1A5",
+ "v0_identity_token": "CDE1002866DA5EB5F1B93AE8604E"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3F19",
+ "short_salt_nonce": "725F8B5D5A48F5BF15805851"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "ECE9232AEB13F080BBA9110F115C1C06",
+ "derived_salt_nonce": "B067DB848C67AB62F7D9647AEF6350DD",
+ "derived_salt_third_de": "0E171CFAF26BE107633093C5FBE09795",
+ "section_extended_salt": "98564150CD7F85177E2FBCD32D1991AB"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1BE63378AB9D94C9624BF8AA13D32159AE60185DE029F75CC5ED057DA75B5859",
+ "v0_identity_token_hmac_key": "ABD803C6A6A5FC17BE165B565C5258A7B696BACA67F122314BAC5133D26927D4",
+ "v0_ldt_key": "458D845951F3C72999AD0D892B41AB1ADC8F1D257085F5305EB498CDB702BB32272353D4BF359DC7C0BC7348DE5CF83F92F099854742015D1703501620249349",
+ "v0_metadata_nonce": "DC8B506C111B985C7CE1A61E",
+ "v1_metadata_nonce": "D086A5209230EB1289F25BEB",
+ "v1_mic_extended_salt_aes_key": "8A8CD0757997B9A09368E004C13A5907",
+ "v1_mic_extended_salt_identity_token_hmac_key": "9F5E33BB0AADE8FA3B3EFC1C0ED59446D9F5D7078CA6B5A268B4FCCC24F7EEB8",
+ "v1_mic_extended_salt_mic_hmac_key": "7175D3D814EC85A2D0425C56E3AE38B7380FFF95C51104BAA187095753BA574C",
+ "v1_mic_short_salt_aes_key": "50628611E98D88D30CF256444B776072",
+ "v1_mic_short_salt_identity_token_hmac_key": "D8347CF2051CCCE1900812130C256F539172A7937BB9F024C101C61BD11C0767",
+ "v1_mic_short_salt_mic_hmac_key": "46D08AF025C2B6D0B27D54ACC927D0FB0CE944D38A5611BB15DC7FB71864D468",
+ "v1_signature_identity_token_hmac_key": "8B4C710326841E386DB89A9E34140A3129F740253121E150E59F86AC03B7BE9A",
+ "v1_signature_section_aes_key": "F72965CB64E9365256119F29F5355A04"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D584",
+ "expanded_salt": "93356D355D4FE32E21F4945687F768BA"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "087F0BC622E59911C61FEC7AC6D5CE8B",
+ "v0_identity_token": "D8D6DE28153FB1F87CD75FBA7F61"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "B578",
+ "short_salt_nonce": "011AB27EBDDCF76BECAC83E1"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "9E43D77377463D53AC57DFA860AC64F2",
+ "derived_salt_nonce": "CDABCA09C3FE20F0BFD2F0855C16709B",
+ "derived_salt_third_de": "2A7BB2161625A9FA4C944A03780FE0F7",
+ "section_extended_salt": "C3AD1D6CF13D0ED5D4B52933E4BE9923"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "EF9F19EA27A76CE0EEE32D179274DFC21FF9ADB2DF7A94905F796FC6AB976867",
+ "v0_identity_token_hmac_key": "9B83E478395DEC9B396443937B6E51290E28FFDE2449CC2987C2C75AA91E8BF9",
+ "v0_ldt_key": "FE74DCBB424B6F9D9D31F31CB047176E2CE8B3565149201F01ABA127DA935BA97351D6536ECF0AE1C5E1A73B5E651338E7290BEDC98056E369372A5AB036C8B4",
+ "v0_metadata_nonce": "238DC3B985343E54213B4F84",
+ "v1_metadata_nonce": "830717981E766A8D5EF618DC",
+ "v1_mic_extended_salt_aes_key": "D99AE5B345134E9EB7FD31344806ABC5",
+ "v1_mic_extended_salt_identity_token_hmac_key": "FBDDFC1B6102418E55B29C6B1F5C2A6D5E7CF796272E8D4CDB8A212FC5844487",
+ "v1_mic_extended_salt_mic_hmac_key": "279FD3C9459F9752565AC221A02805DCB2860DEE54FC5FB6787F3ED26C327463",
+ "v1_mic_short_salt_aes_key": "9A62AE0DDB8B45D2E6B1A5C34576D29B",
+ "v1_mic_short_salt_identity_token_hmac_key": "D0FBCE82CFCE356C430CB45A87CAB367C0F43F2D512F996854A1E0CF1AA230F8",
+ "v1_mic_short_salt_mic_hmac_key": "35DD70B190738EE311AD7A9169E9831C6DE663A038BC30F744B73686264D868E",
+ "v1_signature_identity_token_hmac_key": "57683A7ECCAF59E1233B5972B29A681EFB5C5CCC7841A59F200562F43B604955",
+ "v1_signature_section_aes_key": "3992116A5B3CB5E2909EBA148CA3D0C0"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "3484",
+ "expanded_salt": "0D2B068736CA05A30FB77F4CB162D6E5"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "0FA4D93D5FB8710DD7B74B82030EFAC3",
+ "v0_identity_token": "DD024CDC610F1298061F59286313"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "A665",
+ "short_salt_nonce": "D060E783D2A0CE06655119EC"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "2B2E1D1168C638E5F96A01EFE95E9198",
+ "derived_salt_nonce": "42F31D89F5FF91B8CC141B2555261E94",
+ "derived_salt_third_de": "9ECC9D55DFF824E87A7C10427EDB7D26",
+ "section_extended_salt": "9CF4B88393E26CA09669F2A24F0893F2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "81BE1F6A11DF23604652C9BE0BB40A5082107EFCD943A13F4804E11C55B0EE76",
+ "v0_identity_token_hmac_key": "B7C2F66D0712E43B3D7A791F1D6B33AEB5FDED682B54F2FDD1E616C5D6ED1AFC",
+ "v0_ldt_key": "6D3F8AA49C7749B49D6F62AC6AF4A9EE6BE43A50C64D7D9C3C17A21F67BAB89B4CCDA8BDE1AB1E5A287DA1427E1F92F43B78BA2CF12F151EEF68B5FDA962C89F",
+ "v0_metadata_nonce": "1E59D995D9364D1F4F601502",
+ "v1_metadata_nonce": "B55540E50C46A2FD3AA6EE54",
+ "v1_mic_extended_salt_aes_key": "C99342BBECF0C67F095FC1ED24C4C4C3",
+ "v1_mic_extended_salt_identity_token_hmac_key": "98A3EB8EE5B99369FDA984BE76A1F05FD7D51DF6D0983C572437CB40B87B5C48",
+ "v1_mic_extended_salt_mic_hmac_key": "1FFDBECE1FB5B98AC89B7AC112608F8E7705C1C98F2434DEE5529232CFA16BC7",
+ "v1_mic_short_salt_aes_key": "3A7608329B686BEEA3B22FE3358B1310",
+ "v1_mic_short_salt_identity_token_hmac_key": "4B4C530D8FD05FB35D04618172CC0CB522F1DB01D91665941DD62B9179642D3D",
+ "v1_mic_short_salt_mic_hmac_key": "386F86CA17343F3A66426BD8B626682D9F4AFDF77AB93AB964FAA3708E9100F2",
+ "v1_signature_identity_token_hmac_key": "9D9FBDEAEFA4D07C54302BDC107B47530E461D428A4DCBA4C20B4339053FFBF1",
+ "v1_signature_section_aes_key": "D8BB6D91F80D467B55F348501483688A"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "1CE3",
+ "expanded_salt": "25EAC881DD2DFD7EFA2973BDB0A3FB23"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "1B3976E6D6E9297D465A6E9EE67559E2",
+ "v0_identity_token": "4CAE44FCA940D2B49B1CDF558260"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0891",
+ "short_salt_nonce": "F4BD7CB2CE01511C1F18A53E"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "541E5A0A4D7EBD30C3366C4628971F0A",
+ "derived_salt_nonce": "6D0DE80696F619D2B4CBA1D9DD0B7DE2",
+ "derived_salt_third_de": "DC761244E373DB2F195ADA9CCB849BF0",
+ "section_extended_salt": "829E9AC22DC10ACB10F1FE7EFE014CDF"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "C33B62DDC31FF779AD1F6D2383226D28789EB3B9BC4F28290975ED6587DA0B4D",
+ "v0_identity_token_hmac_key": "36C816C3AB161BC5691D657590CC8E7D4CED85CFE8A075357B94A00F30E3ED47",
+ "v0_ldt_key": "57E32F4A953427F5D8E6F1DDB9BC9F8A7A770D439E2D9B793033EC74211A8F34938E1FC524EA70C9895DD9872742F13FC22A817FADE748B3F5F0D6D28867098E",
+ "v0_metadata_nonce": "2A4C6A38F60B328CB449D269",
+ "v1_metadata_nonce": "4823300500BAB300C14A290C",
+ "v1_mic_extended_salt_aes_key": "30306339F33123C69725052DBC3DF985",
+ "v1_mic_extended_salt_identity_token_hmac_key": "50B0F5BE869B43E70BC61D249AC48A64E1FDBED45F239E545952CBBACA13171C",
+ "v1_mic_extended_salt_mic_hmac_key": "EBB43E51498E6753A1877E2C996330A2DF880E41887DDDED4FE7FF6D144CF4DA",
+ "v1_mic_short_salt_aes_key": "40119DA2ADBBF3E491019863938942E3",
+ "v1_mic_short_salt_identity_token_hmac_key": "9E82B5C1E723F1B578FE9A8519819B4A5B0D0F6DDAD0147E78BF48F778A38CA0",
+ "v1_mic_short_salt_mic_hmac_key": "2EA118DF0241382FDA2AA66599346986048260DACC8B1CA8EB6AF745224DB3FE",
+ "v1_signature_identity_token_hmac_key": "F31EB8FBF7E0170E352059413B935E7ADC5C8262D97DE0D81CEBF1176D270352",
+ "v1_signature_section_aes_key": "E780DDAB066C5FC692736EBE821C6FF8"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "8118",
+ "expanded_salt": "B259AFC30A1526F524AB7D176239D332"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "FD4028D3275272ABF95084312992FC6D",
+ "v0_identity_token": "95C1A38B5345AF2731967010E3D5"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8F6D",
+ "short_salt_nonce": "E9582F01D2CBE7A7F61C39E8"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "47A9E3DDC054A4E93C11018129263A61",
+ "derived_salt_nonce": "04023B2ED6EDFD2654E91BB8604CFCB9",
+ "derived_salt_third_de": "FE7BEE522D169D527312F2EA7DCDCC1A",
+ "section_extended_salt": "F9696D41F224F85BF8A5CDB62C171144"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "57C3D798D37A8A013CFA9E360748AFBFDAE3BA89F545869122CD051E58331DD4",
+ "v0_identity_token_hmac_key": "7A85D2EB46CD2EA1373599BC94D8CBC6C6678296E3173CA3DDE74D4A80B1ED3B",
+ "v0_ldt_key": "86EDCA697E60EC4CA150BEC73AE0E8CD8F0A0E76F481E409CBEC6BDD93540BFE80C610C0782CE4600CA45E7DAE40FFE3143A18AC11124C233C484C92C8AEAA36",
+ "v0_metadata_nonce": "5068C44E8025E74D61C784E5",
+ "v1_metadata_nonce": "4228B89FA232A8DB0B5B0C25",
+ "v1_mic_extended_salt_aes_key": "743E02E60C3F633F37B073684C5A42A8",
+ "v1_mic_extended_salt_identity_token_hmac_key": "6A38862A238FEA6BBBB4FB72CE602404A26EA0F64D50FDD1D8C088B50AAD16A2",
+ "v1_mic_extended_salt_mic_hmac_key": "B87017DB360AD3F66B74E6F8779C485573CECE93A9B058E9197E08DE19DC233E",
+ "v1_mic_short_salt_aes_key": "C1802BB67FA9966A675459E93BB18E7C",
+ "v1_mic_short_salt_identity_token_hmac_key": "B9BF21CAEA29FDC085FBDD4D26DF28FE548C1B945952FCA25799D13999C1CD30",
+ "v1_mic_short_salt_mic_hmac_key": "9CBC02F56E1DE42FA95DABD085E014E5B1FAC3282A37B23D497F49DA81EF42A2",
+ "v1_signature_identity_token_hmac_key": "F556B76B0E1EE952A87246820380A53ADFC7928AE9A497F3CDEDCC72CB15F2F3",
+ "v1_signature_section_aes_key": "419C27C2E8899D21456C8586BB234079"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "218D",
+ "expanded_salt": "05D34EDFC849A67164C828BBDC95248B"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "ABFE5A0FCD29C9FAC689AF6254F6A4AF",
+ "v0_identity_token": "9C4C49A50D448BB7C98961277E16"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "614C",
+ "short_salt_nonce": "B726D470FB3C62E5AEE6F3AB"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "AFBAA77C37E2F2E4C4BEBD7A7A40E8E8",
+ "derived_salt_nonce": "666C9A35AA6DA090BEE448E331D2201D",
+ "derived_salt_third_de": "89EBB1D894E43156911A709CE348F664",
+ "section_extended_salt": "606E4773F79F85943AD21CE692D8F5BC"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "28F45CDB8E3C5D060AEB3B400E9CADDBE8BC5635375D1B847A0CBCF3F6959E36",
+ "v0_identity_token_hmac_key": "DA584FB27301FAAFA8DBC3A3055B7DB704AA5FA842C4BFE9DCC8402CCBD6B230",
+ "v0_ldt_key": "382BE0817D6EFE8CEFFE2AC75029ED0FB52EA917CD74DEC4146FDCEC8AAB0E40B9D7E540D4E6808C4FB6D3F7A4470D9E9C276746A9BD0E7B7A64D5E7483EE281",
+ "v0_metadata_nonce": "4250F2C00B4540833D26C980",
+ "v1_metadata_nonce": "57EFEB1654A4C124C9B1EF4C",
+ "v1_mic_extended_salt_aes_key": "52562FE1226DFFB4025D2D34C17CABD6",
+ "v1_mic_extended_salt_identity_token_hmac_key": "63DCF0E160424B71FA8769F159F20224F2C36DB2C285EA191EFE891784526290",
+ "v1_mic_extended_salt_mic_hmac_key": "1EF4654DD267EF8ABF0C7B6401F0A108AB7FF39D11593C1CB836C1345312F92B",
+ "v1_mic_short_salt_aes_key": "F7906C1B9382A8AA9E30D58ED937126F",
+ "v1_mic_short_salt_identity_token_hmac_key": "F26237F030DABB04BCCDAB8B927C86C6C5853C2608C39FC574283140E7CD3D65",
+ "v1_mic_short_salt_mic_hmac_key": "387BAD7E4C92B13271493360484B2AD24C8C1DE146CB4AAFD8CB2F9046E57058",
+ "v1_signature_identity_token_hmac_key": "E31153728A02DCA8CA2D2F697F0772E77A92C4483B7CB99E61542B79FCDDA123",
+ "v1_signature_section_aes_key": "AA93AC9530BC4E822430C4A79A898D03"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "2914",
+ "expanded_salt": "8AD51A4D7D8C14145E398607CAFD6008"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "4D70AC76CAF34E091C8D4A6C59C7E2C6",
+ "v0_identity_token": "DEDA6A2C50578DF5DC97C211B9D4"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9051",
+ "short_salt_nonce": "9B0F55835CCBB056C630C3D6"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "5B7A957680DBE5A18F6D47490EBF2839",
+ "derived_salt_nonce": "FA772F27245390D3125821597FB8D0F9",
+ "derived_salt_third_de": "62B187FEFED14F6E4B292E06BC94A19B",
+ "section_extended_salt": "157D4AD5BC9A70486F2E15EFFBA52500"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "39518BAA6A95173EE46FF390762FCB1F60E9B6A2B8C44DF4133289F2984E1033",
+ "v0_identity_token_hmac_key": "964C1DFEA2AAB348F63FA5CEFA9D994DE2C16C5F0EE6D684F2144436331055E6",
+ "v0_ldt_key": "697FE42DCA3F0390137D789BA209E5D2D31EEA10CDB038D2D17445738293359543EE36DAFDCC214738B0C4976144CAF1C885CB26C2C749CACEC8E0A2B9B558A3",
+ "v0_metadata_nonce": "0D22B7BD15D4EDB6CBFD899F",
+ "v1_metadata_nonce": "BF4DCF73602F6ED1AC6E3B0A",
+ "v1_mic_extended_salt_aes_key": "DDF87B5AD37C73133F051E19D73958BE",
+ "v1_mic_extended_salt_identity_token_hmac_key": "8C1943E117152BD3550B99EEF815EF9B533501B7CEA6277BF6BEE4A3A76DC7F9",
+ "v1_mic_extended_salt_mic_hmac_key": "5CE6F847C64DEAA632CBDA32769F18763E757E80B1746AAB191F638E0833C32E",
+ "v1_mic_short_salt_aes_key": "0544AFBF786E3F4C01EC50AB2AD04DA2",
+ "v1_mic_short_salt_identity_token_hmac_key": "A1DB27DB83EE9FD2C756C67CC8FB993286CDAA5895E7C3012E540F32D46EC046",
+ "v1_mic_short_salt_mic_hmac_key": "000B1436329CFB45BFAEF8BD5A0DB872D2951E54FF56BEAEFE4063407BB02F5C",
+ "v1_signature_identity_token_hmac_key": "A768835197F34ED548D340389920D4128507BE77BC0E13556EF41E95C34CEC3F",
+ "v1_signature_section_aes_key": "D23318460ABBDFF8B79B7B7977564BCB"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "5EC8",
+ "expanded_salt": "DBB2415837D9360B31C4C27B45D98643"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "48D5A14CE83B030F33DE6D9767913D1E",
+ "v0_identity_token": "5A4832D02E177FF842083118FFC5"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "3F81",
+ "short_salt_nonce": "0D5A7220B52241C711F8A7B7"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "7A4EC90B70FA9ACC4A37F691C8A62363",
+ "derived_salt_nonce": "90646E267796BB4D06D9DA6332CFC0B8",
+ "derived_salt_third_de": "C76CC4B946155D059264B51412240813",
+ "section_extended_salt": "8B7B2570D21C35A39687CB7725B1D8DC"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "AA2716AF54865437571682DC3C6FE92AA8722F322CA961BBBC7459CE841F960E",
+ "v0_identity_token_hmac_key": "4AD019A61785FEB251708EE927933E062B348CCA84968642EE881FD2D7B5B69B",
+ "v0_ldt_key": "BC65180931BE080985DE03CB0FA3604413E3660D30399A600F5A723A97FFBB64FAE25464CEE6D153A4572EF1F8AE483C95E1159CDFDB9BC338C29D0F7E28B1FF",
+ "v0_metadata_nonce": "262FEDCEAB01B2888C2F284E",
+ "v1_metadata_nonce": "D948EED446410C58F2B5473E",
+ "v1_mic_extended_salt_aes_key": "4D9FB04B417FE0C515441BBB5A24D4DD",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B8CACDDA4B647401AFFA0E64C79A3D60E321CAF15EE406665740F9C4DD5CD6AB",
+ "v1_mic_extended_salt_mic_hmac_key": "D6BF2E0C532A2297799A495F52F5830C47E8D121B07A7600A12ED6DBB6CD1167",
+ "v1_mic_short_salt_aes_key": "8C05F37E25BBE33BFAD40E3BFFB4EFC1",
+ "v1_mic_short_salt_identity_token_hmac_key": "5E3DC31AF514DBE21286E86009435844BD96CC31F501B48E0CDCFCE0032D42AA",
+ "v1_mic_short_salt_mic_hmac_key": "41C70F6FE4E862553196A69B4B66E32B15384159A6865464EB50824E1AC399DB",
+ "v1_signature_identity_token_hmac_key": "7885A9B7E84FB130334AD9AB8BFF1643B3D33D68DE2CD208977656EB5CADA2EE",
+ "v1_signature_section_aes_key": "D559EC95E7D9D905C43582B528204FE6"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D1C8",
+ "expanded_salt": "ECCA8A1F9E8E75DCF570C5D713300889"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "4A7142998A8FC059C0EAFB18E6939785",
+ "v0_identity_token": "BFB0CE297F64B3AB7557113C54AF"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "EE43",
+ "short_salt_nonce": "FC424C642B26FDAE820AF1AB"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "F352BAC3D04AAB1663A78964ACD27F3D",
+ "derived_salt_nonce": "BEB93BCF36574D428781A04841770194",
+ "derived_salt_third_de": "21E4F9FB37F092DD846235297297FBED",
+ "section_extended_salt": "A20F1A436E3CD07AF356935EA412F986"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "EE6C12A309C3D379106949857A2CB8736DBF31E30D519B8CA103DE0C67D702BB",
+ "v0_identity_token_hmac_key": "FC9E1DCF166C57CEA1D88205FA013353A8A5C92919224E4CC4C05E4EFD81BF78",
+ "v0_ldt_key": "7898406C1F2E86046C179E417C18B2C78414A95C5E1993271CB5E731F13D0A05B8F31E71A81B9A0A323C4841EACEAEFBE026CF0BEA6DE5661A2B671E4F89F786",
+ "v0_metadata_nonce": "4DB6DBED980D2BE700FC04FC",
+ "v1_metadata_nonce": "78FC55E3F54D576A0EA7DFE6",
+ "v1_mic_extended_salt_aes_key": "45C0F33938366922940EFE7E7097C261",
+ "v1_mic_extended_salt_identity_token_hmac_key": "7697143041920B2E9561C1414E72CC0E55FE65C46E13952EA0BECD995799D52B",
+ "v1_mic_extended_salt_mic_hmac_key": "DD85470E8F3EDAF23FE25157B8FBD1A7C241E7B1C31EC2A198F345D750D57A32",
+ "v1_mic_short_salt_aes_key": "88A8BC6F73692B9E4BA3D932F34A1C12",
+ "v1_mic_short_salt_identity_token_hmac_key": "06E05118607B678C75BE26876B469D29C7E039EA5BF642B2339CA4D30EFF432F",
+ "v1_mic_short_salt_mic_hmac_key": "B24E520B572C5A64C652D5F7E95A58FD937569779213CD79DD435503B05F8678",
+ "v1_signature_identity_token_hmac_key": "F75DDF545736C151BD76F0AF6D952DF525D7F53F0393F42346B6DE51D410F6F8",
+ "v1_signature_section_aes_key": "972451D672CCDB9E7CA5D68C7CA291CD"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "AA55",
+ "expanded_salt": "A2A7A96222BBB587E385B4B0438837C3"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "D181D62BE2814F8A4515CEE9F98CB16D",
+ "v0_identity_token": "82AAD91558602B7E975108E4C1A8"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "1692",
+ "short_salt_nonce": "41FC0F8BC4B6ADD56E767CA0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "8CA3B5B9AD5A244C7C81A4CECDFBA881",
+ "derived_salt_nonce": "B19D427E9CB92F7F2D1F433BBFC1C484",
+ "derived_salt_third_de": "5EE54CE1EE6359617F847ACF515237C4",
+ "section_extended_salt": "05FE726BE045EDBE53C924C94DCC01FF"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "04CB72E32403D848909CD752FB1728D044B0B922E11933AF485BA6667BDA8095",
+ "v0_identity_token_hmac_key": "AE509065FAB5D2F92D5879A79367774D0DD1E299592700BAEEFF59BB38EF0F7C",
+ "v0_ldt_key": "EB2A03CFB458D8EFDC34F5A1C295CE89A7E4C16EB0A310EB29FFB22C058BC8EDC12679CBB59184A1DAC8914A3266B7DA4A9A18DBC463DDF0F1188E6A1D937317",
+ "v0_metadata_nonce": "F8C6BD75CBFD3563E67C738A",
+ "v1_metadata_nonce": "868F99953CEB467B28C252A1",
+ "v1_mic_extended_salt_aes_key": "8DCD6EB583FC8D6A09D0A6E4887C0CB7",
+ "v1_mic_extended_salt_identity_token_hmac_key": "D379FCA209D85EE044A08DC891E4F0E54A46346D5E6E47B28C213ADF81246750",
+ "v1_mic_extended_salt_mic_hmac_key": "F7F9A514455AE831234376BDFBC64A3639D7E2C4274851EBCB7EFB14D3392FD7",
+ "v1_mic_short_salt_aes_key": "2385AEC92C92345F560C4D292D3C4C98",
+ "v1_mic_short_salt_identity_token_hmac_key": "45B7159DC874A72B0F232DB37EEABFC00B801453BBE78B57A5C08B2FB8AE626A",
+ "v1_mic_short_salt_mic_hmac_key": "0352B8CEE18F5D2A75B5D055806611BEF436A2F2172447236E6C929B41C00FF5",
+ "v1_signature_identity_token_hmac_key": "789B7C2BBEA40F1E9D8C35CA4F6A80734F4A0EC11973F49EEA988DAC0EF10877",
+ "v1_signature_section_aes_key": "9AE1BC3E1532FC968486276BE96AEB6C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "0733",
+ "expanded_salt": "5F072B4BB16C2439CF35176A4E208D43"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "DAE265F7391FF6871E5BF1A60EE33F1B",
+ "v0_identity_token": "29E46351DACECB436710E7BE3CFF"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "89B6",
+ "short_salt_nonce": "4B223F4BE10514D1B8407002"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "4BF6F87B0CD12A0AE66AB6C80C976E33",
+ "derived_salt_nonce": "3AFAF9158C6986EC11F22D14ECD21D29",
+ "derived_salt_third_de": "EF28C13335BB6321FAB46EF2A859DD58",
+ "section_extended_salt": "0DB9FC8CF99C093927DFE9CC092C008D"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "278BA457B88F328447ACC1E6A4E14BE7A62A44CABF28330D6DC044050DF55085",
+ "v0_identity_token_hmac_key": "6503711E003223721BC7A3412B7387FA2BBA963EB581D1D60B5A17BA0E7C4B8E",
+ "v0_ldt_key": "B6FC809AA5F0DBD46A75F6639594D74B5831293824AB4A9922997A3B3A1E6B12111084BE521B3A486E16DBE1AC0FCB346AE16FEC6B80E3560419AA616CE4984F",
+ "v0_metadata_nonce": "67CABDAF41792AED8A72A868",
+ "v1_metadata_nonce": "8B6B23B4E69766931BE22DEC",
+ "v1_mic_extended_salt_aes_key": "9C86645E9BCE74A1EC73AADCD665154B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "1632B567AC6144C41081C91C3F5BAD0B560F59602E39FD0B6207BB5DECF7D734",
+ "v1_mic_extended_salt_mic_hmac_key": "8CB11E1B229A46BF2620483B959201465A44A31F6FB9E675539B7F27439C8B0E",
+ "v1_mic_short_salt_aes_key": "2C9851D5CD39BB2E1FEC593F79F23085",
+ "v1_mic_short_salt_identity_token_hmac_key": "70315F0D044A3F478184A76892BB4204A5CC1E4542CDA99595196323C0770B31",
+ "v1_mic_short_salt_mic_hmac_key": "FCAD5AB2AF31EC2C2649B9DEFFCCA9865B74E332E81474E8FBD7356D33F88DE6",
+ "v1_signature_identity_token_hmac_key": "80F9B9285D8DBF0666839F92E2D2752EF249FCB127503BFF41A629DFFAA1CB45",
+ "v1_signature_section_aes_key": "B519FDA43EE7B072ACB8A855A0820016"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "0F09",
+ "expanded_salt": "8ADD04F894BD7DED3AA47EC0A5AA2F98"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "CFEBF4005115348238072AB6881A36EA",
+ "v0_identity_token": "818BBE9BBAD25F7622319DA42806"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "EE7F",
+ "short_salt_nonce": "C2DA1EC8766C69498CB6EB47"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "E732FDC269D45C4213635D2D35B4A8C1",
+ "derived_salt_nonce": "FF25222D3D493186CBEA2C203733BA86",
+ "derived_salt_third_de": "02BD9E3B04444BF78D059BB4336D1D14",
+ "section_extended_salt": "BF79E23A91CD05105EDB13CCE3CB6B16"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "477C882082527F23F504FBEFD21A679EF0409EA198BC392C5113DEA2755DF924",
+ "v0_identity_token_hmac_key": "196C59DDFB9139C0DDBC7FAB56AA600DFDA39EFE683DB66529002A7E383EFC64",
+ "v0_ldt_key": "A1F7AFF1BC0D85F14DB34C40A82A0DBD75179F7F164958602E6859D281A872EB7C979F1D09C29D1D5F0C89805473B7FD28B5269E52B220AFFAE81C77619FFC7A",
+ "v0_metadata_nonce": "FA10FEE70CFECEF59CC0E0E0",
+ "v1_metadata_nonce": "1E02CDDF1094116A322052F1",
+ "v1_mic_extended_salt_aes_key": "3FC29BAF9D68FBF0312A6642360E7BD1",
+ "v1_mic_extended_salt_identity_token_hmac_key": "C4F0AEC099DEEB16FCAA31731CE8C3C4B480EADEE65EA59DADA666BF558DD945",
+ "v1_mic_extended_salt_mic_hmac_key": "73494C1A3BF1D355985E61D009736941FFB39A3251D915D7EB3E555E887117BA",
+ "v1_mic_short_salt_aes_key": "622187A9DC8AF81E033888DDFE504F77",
+ "v1_mic_short_salt_identity_token_hmac_key": "0BD43C55C16C95BDA2A6DFF39A9FCAE21CDF87DE842C35694698B2B53D1FDFAE",
+ "v1_mic_short_salt_mic_hmac_key": "9900746A6567048FAC292563E40333B948F5D3EDA89BB8D8E5B159441D5EECE6",
+ "v1_signature_identity_token_hmac_key": "9A2793927FD494FB1AFB2EB7F7B91319A231EC88B1A22B3E42293FC1EE81E388",
+ "v1_signature_section_aes_key": "0F5A12959E5210EC994C97724D3E2A96"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "2B8A",
+ "expanded_salt": "F4FA10F6983E9EC4A7F916E5FE7191FD"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "427F95E0A764088384200A097E6AC5CF",
+ "v0_identity_token": "FC6827BE9D955A04B5D4DF33849C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "8EBE",
+ "short_salt_nonce": "2183C1252F128A480A53CCDF"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "1033FF7BE57DFD280D3F1AAF407831C0",
+ "derived_salt_nonce": "E6D9C880D2182F448A6615F7FE10BE69",
+ "derived_salt_third_de": "63A9C49B9F470EA354637612725729A0",
+ "section_extended_salt": "9AFB8618127F357D0060618E781CA599"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "CCB8E6B8AD20D8B150E8FC97A098B6DDD7C1997701EA879CA64182B22FA55503",
+ "v0_identity_token_hmac_key": "E1BE3B3F12B2A2182B49983B8068BA6FA9FB3DE509D671816BBE008523818F8D",
+ "v0_ldt_key": "0F2B30FB50E701F0DB08D85F0CD7328E577CFF43EDB6B223928CB2258BCF1E394E58FECB9596D2AC6B8D43947C4D175BEB95548F21301E1F1F733934393A7360",
+ "v0_metadata_nonce": "942ADD1379EE90A6DED3B65D",
+ "v1_metadata_nonce": "4CEE030F946DF65BBB885DDE",
+ "v1_mic_extended_salt_aes_key": "A1BED5A13B44D10460EEAFB4412EE475",
+ "v1_mic_extended_salt_identity_token_hmac_key": "19675B5C73515ED298ECA658901F187D321A83C935A15C4D4A4844DC48BF077F",
+ "v1_mic_extended_salt_mic_hmac_key": "5D193196A34E4437DB7034795266C7C62DA3605D9F5818C2D433292E610A3762",
+ "v1_mic_short_salt_aes_key": "B29FFF8F001C4726749A2FE7047A82D1",
+ "v1_mic_short_salt_identity_token_hmac_key": "F1A90E829ED67B49C445D7DEBDAFC88E3BCF1974F0ED1EB9643730BF6EB3B90D",
+ "v1_mic_short_salt_mic_hmac_key": "BAB6DA7601191FDEB4344FAA163E818C9BF9B1D5B0AB1EE8D9F4A1C1D30A86E7",
+ "v1_signature_identity_token_hmac_key": "8C6832DB6955803AB934B98378B7F81F3710C65947A8B2C6132525B163F62CD6",
+ "v1_signature_section_aes_key": "8916CE7332C1F924DCC17E68D999EE7D"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "C270",
+ "expanded_salt": "3CD8235D88B0B4D1A0236DCCD0F5629F"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "8DBCA7616260D0E347D3984DCAD03372",
+ "v0_identity_token": "D02797D4E963A7B9806E5EFE0FA0"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "C61C",
+ "short_salt_nonce": "7803F0E069FF172CCF47AA05"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "6D93C32275239B6A82508FEFDFEC112A",
+ "derived_salt_nonce": "D2C45BD5079FE6B2D69E4F5EA192CE07",
+ "derived_salt_third_de": "2CF3FE0C1E6689361B50D2B558FCA09B",
+ "section_extended_salt": "23FF70E4526E9961792744D2C7534BFE"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "9617CCA86C2DE55751298C2F0652DA17D9C461672AF0B25F4440ED17F9A17768",
+ "v0_identity_token_hmac_key": "C4FF34211E8D5C43FBAF8D6653A8AF5FA760F13459000F70082B9D143F3975BD",
+ "v0_ldt_key": "9A118827A019C5EFD3FC97CCC3B10F74C15D56126669EABE07317EC7A02B7B0BF2021383D3F48DDAFC1AEEF5AC930304BE2C85128AE2DF0F6F679B8D48E5CCCD",
+ "v0_metadata_nonce": "A9A2B6059169FBBB81991A3D",
+ "v1_metadata_nonce": "F6B42D5761F30BA937AB8B7C",
+ "v1_mic_extended_salt_aes_key": "328DB3BB74879515324035839561552B",
+ "v1_mic_extended_salt_identity_token_hmac_key": "36243F4E25B1548560477EF30CEB9A785C49D244832564BA262596735ED2DC1D",
+ "v1_mic_extended_salt_mic_hmac_key": "693EB813C40F33650699205BD038EC0D09989F8BA0A6B50741EC8FE1211DFDFE",
+ "v1_mic_short_salt_aes_key": "ADCB2F8D667D5DBABAACD28F72C2E11D",
+ "v1_mic_short_salt_identity_token_hmac_key": "0501458FF851D1C3C83C1BB65F55495E75C24778AA9B8FF0488FFB7F119B574E",
+ "v1_mic_short_salt_mic_hmac_key": "2ABF2E7A68FC09E88AC1122710BC7DD9F57FB8E150F699D5DC0DA5A560C76044",
+ "v1_signature_identity_token_hmac_key": "A267DB5025D3F87D12966C3853FB9449AE1FC4B654428CFAD44AB3AF6020D572",
+ "v1_signature_section_aes_key": "9E6F27E4E0118B8507146871CCF84E2B"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "81AB",
+ "expanded_salt": "F19E33C05E6D989BAB7EDE336BDC01BC"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "68B06A0E1A66F6B996474EE0B282718A",
+ "v0_identity_token": "F60E36A8E0605B46D6A05871C90C"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "A80C",
+ "short_salt_nonce": "8F039D3FA934BC8560918D45"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "FC34E69B7FA34B4341D2D33D5D591D46",
+ "derived_salt_nonce": "9BF73251EFD5E11020390188ADFF72C6",
+ "derived_salt_third_de": "C80634B6E96C0D7EA25C5C47F7389B01",
+ "section_extended_salt": "DF9DAD95D8384321FED7873DFC750B66"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "E465DD783C41093B0A855D11D3D65C141C01A27D0522D7049AC8D92CBEB9D232",
+ "v0_identity_token_hmac_key": "9700E177127FBFC6271A4E7ADE829E5D6BC19901DE311C66F0D5283475241C23",
+ "v0_ldt_key": "FF929D036F9D8713CCAFD13A9A8E3EB1368F904BB28C3A5B16155D440245F2F736A885306539CE9DAE5E8E1E6915738FE2300523831F2FB284A858D968ACF2EB",
+ "v0_metadata_nonce": "113FB8326CCC81FE306E3722",
+ "v1_metadata_nonce": "A1B0C6917739A95F4E36EF34",
+ "v1_mic_extended_salt_aes_key": "FD52721D70BAA377D20F679583CBB776",
+ "v1_mic_extended_salt_identity_token_hmac_key": "C384F651302B7D322F5E3F8A2694A49DF03034C0A13C0A827250DE10E9708B01",
+ "v1_mic_extended_salt_mic_hmac_key": "DD1077C4A05C4701B7EE34561CCC9D4D46C80E522414CC1053A2A3C3F918E24E",
+ "v1_mic_short_salt_aes_key": "EBDF2DEB57C82EC7633A337346495321",
+ "v1_mic_short_salt_identity_token_hmac_key": "B5A4831B58E71C5EDF3206D25CD378D2E569EC32E8E10E173C82527AF7DE59E5",
+ "v1_mic_short_salt_mic_hmac_key": "FD94C8A62DD00C251DAD6ED9DC459E1C06C2E625C24D3EA902122BE1B1EAFC13",
+ "v1_signature_identity_token_hmac_key": "40BACB42A697D9B7322FFC8196CCE5ADCA84758196F9211572C51D1E96683536",
+ "v1_signature_section_aes_key": "ECC4297E2036A147E17C48550B32C9C6"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "D77E",
+ "expanded_salt": "7224B61774E1B0F193E6E2B9C6828D47"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "29AF30ED417C4F170B58DABA018BCB99",
+ "v0_identity_token": "F0663FB846121698C69430BACA77"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "0C83",
+ "short_salt_nonce": "DFDD3C550621ED62C9452D36"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "CF6F2269AE6601323D59347A6B698B6E",
+ "derived_salt_nonce": "8E899705639BD06B26439FA131EE2A2C",
+ "derived_salt_third_de": "B00A28308187B862E7F971387CA44CC4",
+ "section_extended_salt": "B543154433E370E6D7A97B46A73F5652"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "882D400EB39A85F33D277BF925D7ED0E552D94A12BD15AD17F7151FE69E775F0",
+ "v0_identity_token_hmac_key": "1A0D3CFA718CBBDB2B330D38803A1BF03DD759B1EF1C9C0FDEA869012F89958A",
+ "v0_ldt_key": "9AF4D1867CF679CC66E3E874AF8056FAC8173B2287DB6CA871D6C3AADA33F936E281AFC6C09E0DBD9E16B067623763A66F0E5584028C36300D972D39E0C1C71E",
+ "v0_metadata_nonce": "96CCAE0B699F6A861C2FD9ED",
+ "v1_metadata_nonce": "475822C913CF03C67FDB558D",
+ "v1_mic_extended_salt_aes_key": "566FC52F26306B98BD4F702D783CFE18",
+ "v1_mic_extended_salt_identity_token_hmac_key": "B9E518A687FB1E222F2131F9D730493C7BB78E92002CF782FD30C75272E24B92",
+ "v1_mic_extended_salt_mic_hmac_key": "893E8AFB307BF4C011CDA36140152CF892F2356DCB8B87AB8D3B0CEFAE7D23CB",
+ "v1_mic_short_salt_aes_key": "33EB408FAD37D1FF76A27B2CF7D421F8",
+ "v1_mic_short_salt_identity_token_hmac_key": "9EEE04B64C468770682AF45F96D7DCA1D6EF53D4C592A2AE7A172A0DEBF10E21",
+ "v1_mic_short_salt_mic_hmac_key": "74655FA0D30D1E2DF0DA9747A3966C9111693B8E00704DC61D2156009D9F26BD",
+ "v1_signature_identity_token_hmac_key": "801294C7CA501C3BF20F57BA2B0E2FA09F13722B3655F625AE8E17C8A79B1154",
+ "v1_signature_section_aes_key": "44D3F5A168DD048901D7FDA07952634C"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "ADEB",
+ "expanded_salt": "E005DF91854CE6AB6186D3C976110C49"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "8032E7A696CC593BA7863159E0C0EA10",
+ "v0_identity_token": "460240DEB4C8813AA5815BB6E5A9"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "4039",
+ "short_salt_nonce": "A4E6F88E3225FACE356BFDA4"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "3885509BA1045121AE5CED396AA039EA",
+ "derived_salt_nonce": "679DF301EEF3F51C43FFC1701A184685",
+ "derived_salt_third_de": "441CDFC937345A037284C3E35698448A",
+ "section_extended_salt": "B43C581ACFC8A74540852A7DC924867C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "408039A7989CE0B9DF3D3BF66AC9400458A14B524EA03CE24C783D7CEEA6130E",
+ "v0_identity_token_hmac_key": "09DB35D01A5476F41E66061C7420136EA7100245C979987C91111DAFDF5122E3",
+ "v0_ldt_key": "24A79BBB1033112612B3F710B6A9052548CB75772ED0AB03613B84EA77989879032C8026AE28C45D46E71E19261F454C7E0C2A48C8813CBA0D00A986340B31ED",
+ "v0_metadata_nonce": "7D489586FA49BE4CA0B5A333",
+ "v1_metadata_nonce": "F89E50CC26C5A4185A97A407",
+ "v1_mic_extended_salt_aes_key": "4A8884EFFAEFC7981A95DF8A76C68D0C",
+ "v1_mic_extended_salt_identity_token_hmac_key": "5712CAD3673FCB0E83E0BB52AF7D23E84C89D79F9526757F2B5070CA9D9DF81C",
+ "v1_mic_extended_salt_mic_hmac_key": "DB771C4FBA0936936876181EDB642A4C3C018561845F35B3D0DC07D7EE4840F6",
+ "v1_mic_short_salt_aes_key": "AF688DBBE5AE004BAD0D5E49B6F7D234",
+ "v1_mic_short_salt_identity_token_hmac_key": "F09E67D34142371B649BC5A06BF027125CAC81971B962F469FB2BAAF1F077B1C",
+ "v1_mic_short_salt_mic_hmac_key": "DCE2001156BB5C30969FA012D8FE16DB5C599574CC46B61FBA232AE2B184C1F9",
+ "v1_signature_identity_token_hmac_key": "9E7CA4743B0670FB181CDA233640CBADE4A81E38D4EB4F4BE6188B5548EDC765",
+ "v1_signature_section_aes_key": "2523471EBF1ED605399CD39AF0B624B0"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "16D1",
+ "expanded_salt": "24288A2ADBC8574BB7225B2CADBA1F3D"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "B21803E7F32A51D47B439095F1229E51",
+ "v0_identity_token": "6D2145A353E43D90B1487ECD9D20"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "C1E9",
+ "short_salt_nonce": "483CBFACEC1D1468DBCD4FDA"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "03E5070187884CD433FBD176EA5E4A63",
+ "derived_salt_nonce": "D116BF3B37136C23AB77038C81C6FD87",
+ "derived_salt_third_de": "2ADBC8DF751DBB23172BBC87F1E6E77E",
+ "section_extended_salt": "87CA5497D5CE54D75C0B0DBD6CF07B39"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "1AC9F5AC2ED4C99D2B535AC5304F8D481EC6147B39605BFA2B6E21D18006000B",
+ "v0_identity_token_hmac_key": "B2AB4B284B6CC602FB0403C154FBD19C18FBAC377AB971A35577010F8B0A3A97",
+ "v0_ldt_key": "4A4DAA2BB754E3E1ED2F473A3B31BA19A2165F0720AFE06EB6B712EB1A2940B8733E71DFFC3854A831CE0E9B8A74A19DF080B11A1FD42FBE7215D1797DBC2736",
+ "v0_metadata_nonce": "E5ADB3574A0A35ABE1027CF9",
+ "v1_metadata_nonce": "8F9855477699C38B115C7A54",
+ "v1_mic_extended_salt_aes_key": "D3B77010859F05271F05F26D1251E8D0",
+ "v1_mic_extended_salt_identity_token_hmac_key": "5379903CC277C6CA08E17E7EA2A91185F7FB5F9CB75960271AD3089E9F6F4F97",
+ "v1_mic_extended_salt_mic_hmac_key": "4FDE5BCD4A8CD9B8B0212BCA23A7A9EA49D7C039EBC90AABFECD864F594C5203",
+ "v1_mic_short_salt_aes_key": "8D5372501B32F7A568349C722CB0F695",
+ "v1_mic_short_salt_identity_token_hmac_key": "596A1BE90D3806E242B88A5CCE32BC8A2C4FAE2E17BF48B06AEAAD2C5E122032",
+ "v1_mic_short_salt_mic_hmac_key": "B00D35A3F49F08FBDAFDABB7ECA0A04297850A433A6D11C9FF8F6819F8C39C2B",
+ "v1_signature_identity_token_hmac_key": "7509D7C29027BC944390DD51AD6F3804D429C3EFBBFE24AD1AFF25FF40C6A8DE",
+ "v1_signature_section_aes_key": "EC1FA7F03A5E90DBABFFF5EC2495AB5E"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "9F21",
+ "expanded_salt": "349E3311FFFF93BE6AC7D0D53D1E36DE"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "212FD419A877090C52821F501D62FF97",
+ "v0_identity_token": "A9ED25A283E0E58F7B127E2B62D6"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "BD70",
+ "short_salt_nonce": "02C4AC240A3874E831DF38DB"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "FB3EA084403FA66ECB1C15F9D0AC8396",
+ "derived_salt_nonce": "4443A4454CF2F491410423CD5F2AE9D0",
+ "derived_salt_third_de": "90A8D37E587090B7E6D636C6F8D27114",
+ "section_extended_salt": "38DA154EAF77D994EBBF3CD6FFDE825C"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "2D9D38BCDA9C2958227BE553C14CEFCF378D5CDCAB880EBF3C43635E07AAFF5A",
+ "v0_identity_token_hmac_key": "EBD73117325BEECE3A05DB2A1D6323AF7F499E652C61C9008A87A4E47F50EFCE",
+ "v0_ldt_key": "E28854F65892C5A1D6B92902F6142BA14CD3A74AB95356AA70DA22B3A9193E092B2FA17EBA2B76A08307491C7244789B00075B721AF6C8494D9DA1B3C9CA8F8B",
+ "v0_metadata_nonce": "9C3813ADD5746412C3214F51",
+ "v1_metadata_nonce": "6FBC21A602E1E1FB10B5F4EB",
+ "v1_mic_extended_salt_aes_key": "6EB09E856A0915BA60B3869F321981B4",
+ "v1_mic_extended_salt_identity_token_hmac_key": "35A04FCBA5B752C97D20158C3C55761C1E6723629BD40C2CD5F28007B14936C5",
+ "v1_mic_extended_salt_mic_hmac_key": "5F5436261C25D3E5FA446D513B409D5A0C4C27297CBE9F4EE741749154019E21",
+ "v1_mic_short_salt_aes_key": "B03494A82C3848A67453FB367532112C",
+ "v1_mic_short_salt_identity_token_hmac_key": "59D6749A1D6AFA4DB973AEAF088FCC0E7BE7D859A2814D641799BB1590496924",
+ "v1_mic_short_salt_mic_hmac_key": "D3B73C61E28AB288C60D7240B501A074C29A5E328D9BBD8716566B83AB1217A3",
+ "v1_signature_identity_token_hmac_key": "F85D6CA0DA816F073831FDDF3A0E0FCA9C888FB820762CCD6477DAFB90547E8F",
+ "v1_signature_section_aes_key": "807F93D9C345DC3AB3D98D43D6FBEAB9"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "765B",
+ "expanded_salt": "5866D7FC7A27D3A92AB155D7F28348EA"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "20C0754D69BC2EA57AE634C03D92D592",
+ "v0_identity_token": "1A1CAE87957F48BB52D07E0172B6"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "607E",
+ "short_salt_nonce": "8B511172378BCB1BF0CB674C"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "1E962EC586FE218A8F3A736BA5677B7E",
+ "derived_salt_nonce": "7399E4535A366989EF412F3EA0F8CE45",
+ "derived_salt_third_de": "46F2B7D99127C01B68C8B7C8A45CD479",
+ "section_extended_salt": "6BC0DFA6EBFA267952CB7305F05AD8F2"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "34F2CDC71D38A430F36FA88F159AC2B053B1F339189D0570B68B238E86173239",
+ "v0_identity_token_hmac_key": "A7724517771962916DFCAAB84400F05865EA15F998EAC81740AE037A413C5425",
+ "v0_ldt_key": "6F267EC51E8018E9D3CEBF01617BA6E893F01E474BD9710272CA31FF1F61237270BCA8F39E6EEB155E95F2BFE393840EEB26079AB1E03C83FCE12CE52719BAB9",
+ "v0_metadata_nonce": "CE68A8C49765C41C38B3F0A5",
+ "v1_metadata_nonce": "27710531902EA355D240D622",
+ "v1_mic_extended_salt_aes_key": "79E4DBA1E056E59BDCB9BD65A7A805B6",
+ "v1_mic_extended_salt_identity_token_hmac_key": "8968D34F626250221E226A66FB2E76A4216E3F825745B3605B3F053863EDBFE1",
+ "v1_mic_extended_salt_mic_hmac_key": "CDD5D25349B3AB7D4885AD124A050704116A5911CE5F379BE998CC7E92DE01AB",
+ "v1_mic_short_salt_aes_key": "405DCC958551CDD1EC90C4A91D1B87AE",
+ "v1_mic_short_salt_identity_token_hmac_key": "D06923425C4A028710861654BBFACA9F2FB6B3488B70E9C3C1898152A8DAFA6E",
+ "v1_mic_short_salt_mic_hmac_key": "421A413608C4344BF7A0E250324337C9ED374636D38D2B35969B6EF434D0D30F",
+ "v1_signature_identity_token_hmac_key": "D4FADAACB47CC260DEEDB1BBD56131D4FAB54270ACBBFAE975D77079A8554E53",
+ "v1_signature_section_aes_key": "1F5F9803F64C4A6DCF4BFB0C4FDC800A"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "CDFF",
+ "expanded_salt": "9F61F76DC1CE3B702DC66772A87A2774"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "B6A7CF0DA707E09E2A9FD05FB28802D6",
+ "v0_identity_token": "028D2AD4E48B79A63C3D6038F453"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "9D69",
+ "short_salt_nonce": "1B68E2C018314F5C61591D06"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "443DBEF6EA8FBB7E1AED17C651902D8F",
+ "derived_salt_nonce": "C832DD69A51C4466CC7E4C8FF2C8D830",
+ "derived_salt_third_de": "996A7355DADC94B04ED4DD5BFF713D10",
+ "section_extended_salt": "86042432C5C8BFA2ADFEF07E52F76CE1"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "41CAB11A50B05B768F94CB737A55F0431C37058077CAC227BA33DEAFB13AC126",
+ "v0_identity_token_hmac_key": "225746B890970F0BA658FD31807704E4792B04142B643292E73897700DF3F7B2",
+ "v0_ldt_key": "83A452F3DB32B0C30BBCE0188F8674597B16F074155312C4AA50D3543E4F5CBD5F38A3742D0626B532DA9BAABA6976CEFF3F95BD8DC6D30AA945DF8A2ABAEF9B",
+ "v0_metadata_nonce": "FD6F822707B0AA6F1DA28329",
+ "v1_metadata_nonce": "EBC62567E6EDFBDA6FB864E1",
+ "v1_mic_extended_salt_aes_key": "4605C732B31CA709A146D42D49F56964",
+ "v1_mic_extended_salt_identity_token_hmac_key": "D67C18D39A016F3578F5B36CEDF74FF42AB2D33063004D81223709D34B35B1B3",
+ "v1_mic_extended_salt_mic_hmac_key": "2F7EFAC31BC19C6414DBFE1E151CA5A9BB2D7FF23816E50DB8D3DBCEF0F651D6",
+ "v1_mic_short_salt_aes_key": "72EED4197BDD9429F3B227EEEF8D9003",
+ "v1_mic_short_salt_identity_token_hmac_key": "060C6B4E277154EF8E2AACD29FA7FD561D89EE1B55FE75804AC900B2A14FC6AC",
+ "v1_mic_short_salt_mic_hmac_key": "9E5E30433992ECC1D0E897740DE7380195AD9D393B172626A04EB4EC1540441D",
+ "v1_signature_identity_token_hmac_key": "6F8D65A2FDF4A76C612A1CE055862D4E1F3BC758FA9DEA8171281F387C89E89F",
+ "v1_signature_section_aes_key": "9E1A2442E091482C1AD358CB46EBB449"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "6BC4",
+ "expanded_salt": "BCDD2CBC57578E5CE0B7D53841FFC877"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "0D231BE24C14382ED04D1AD9E6C9C876",
+ "v0_identity_token": "A8027285D444310F6180141C6DAF"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "1304",
+ "short_salt_nonce": "B1B266BC940E1CB4C0DDB7C6"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "EC10AA256E69F3BFC61E03E02DAC5572",
+ "derived_salt_nonce": "C5CD7C8AF453AA0A2E0CFB92B4DEC297",
+ "derived_salt_third_de": "E72061FB97353A6B46800EAEA02E86A2",
+ "section_extended_salt": "DC5E1856188626F6FCAF7DEBCD91F83B"
+ }
+ },
+ {
+ "key_seed_hkdf": {
+ "key_seed": "F9929BC72706329A1D56A0DDE98F41F0C23A4F3316703FC756E1035BD146961E",
+ "v0_identity_token_hmac_key": "C312A8A15CBF165D135B8934881F7F717ECD9F3EDE6592A73550F7EA63C14083",
+ "v0_ldt_key": "4BF1CFF058BEED01FA792506A058C94F0FCAEEC2559D16E7E0EB7C458EFD3E11D6BF3E549227B264AFEF830BD7924C54249B25BCC59B4CDD207122936033FDA0",
+ "v0_metadata_nonce": "B75EDD27FB344C7096F27C89",
+ "v1_metadata_nonce": "90EDA9020339C51BA2763873",
+ "v1_mic_extended_salt_aes_key": "1FA685333412CFBE2D673D839419BDA8",
+ "v1_mic_extended_salt_identity_token_hmac_key": "ED7A20A29073B5B95209AD0CCEC01A27BDD3A5A12DA9489518AB24E2307D2632",
+ "v1_mic_extended_salt_mic_hmac_key": "2F8F91E46219709D1389613489A418FA8D806A1FB9D9519D0C5D677D55883E5F",
+ "v1_mic_short_salt_aes_key": "B8A40538DB14E9CCE0157DF49441CDAC",
+ "v1_mic_short_salt_identity_token_hmac_key": "08569465F0C66A011A7D4FFF67B0FC97690ECE6868E62DF94767E7E9436467D1",
+ "v1_mic_short_salt_mic_hmac_key": "19D0469CCCA27EE200930615C3D35C27ABE9AAB808752DA5D205E4003A617543",
+ "v1_signature_identity_token_hmac_key": "FCBBD61A230D9BE84D5E57E4DE4C641F3F9733867290614BE54F33E381EAF517",
+ "v1_signature_section_aes_key": "39C03BE4FCCB838D975F0B10F2F27FA6"
+ },
+ "v0_adv_salt_hkdf": {
+ "adv_salt": "DF27",
+ "expanded_salt": "BB3B8A09918621D2F9AE81B329D4F096"
+ },
+ "v0_identity_token_hkdf": {
+ "expanded_key": "72DE095B1A0271E0042F668244A1255B",
+ "v0_identity_token": "ADFE0051B256B9778548300C4F17"
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": "2816",
+ "short_salt_nonce": "7DB3F25CD050360CEB4DC7D0"
+ },
+ "v1_section_extended_salt_hkdf": {
+ "derived_salt_first_de": "ADACCCB5226C9A33368DCA3CDB62BBA1",
+ "derived_salt_nonce": "00AA84F4608746BEC8A17749584F7229",
+ "derived_salt_third_de": "C925E34CF796B07300BFDA0B91172D86",
+ "section_extended_salt": "65D6AA69B72031C537A1EBD7D1F16B7F"
}
}
-] \ No newline at end of file
+]
diff --git a/nearby/presence/np_hkdf/src/lib.rs b/nearby/presence/np_hkdf/src/lib.rs
index 8201f38..bf82169 100644
--- a/nearby/presence/np_hkdf/src/lib.rs
+++ b/nearby/presence/np_hkdf/src/lib.rs
@@ -22,30 +22,29 @@
#[cfg(feature = "std")]
extern crate std;
-use core::marker;
-use crypto_provider::{aes::Aes128Key, hkdf::Hkdf, hmac::Hmac, CryptoProvider};
+use crypto_provider::aead::Aead;
+use crypto_provider::{aes, aes::Aes128Key, hkdf::Hkdf, hmac::Hmac, CryptoProvider};
pub mod v1_salt;
/// A wrapper around the common NP usage of HMAC-SHA256.
///
/// These are generally derived via HKDF, but could be used for any HMAC-SHA256 key.
-#[derive(Debug)]
-pub struct NpHmacSha256Key<C: CryptoProvider> {
+#[derive(Clone, Debug)]
+pub struct NpHmacSha256Key {
/// Nearby Presence uses 32-byte HMAC keys.
///
/// Inside the HMAC algorithm they will be padded to 64 bytes.
key: [u8; 32],
- c_phantom: marker::PhantomData<C>,
}
-impl<C: CryptoProvider> NpHmacSha256Key<C> {
+impl NpHmacSha256Key {
/// Build a fresh HMAC instance.
///
/// Since each HMAC is modified as data is fed to it, HMACs should not be reused.
///
/// See also [Self::calculate_hmac] for simple use cases.
- pub fn build_hmac(&self) -> C::HmacSha256 {
+ pub fn build_hmac<C: CryptoProvider>(&self) -> C::HmacSha256 {
C::HmacSha256::new_from_key(self.key)
}
@@ -57,8 +56,8 @@ impl<C: CryptoProvider> NpHmacSha256Key<C> {
/// Build an HMAC, update it with the provided `data`, and finalize it, returning the resulting
/// MAC. This is convenient for one-and-done HMAC usage rather than incrementally accumulating
/// the final MAC.
- pub fn calculate_hmac(&self, data: &[u8]) -> [u8; 32] {
- let mut hmac = self.build_hmac();
+ pub fn calculate_hmac<C: CryptoProvider>(&self, data: &[u8]) -> [u8; 32] {
+ let mut hmac = self.build_hmac::<C>();
hmac.update(data);
hmac.finalize()
}
@@ -67,26 +66,20 @@ impl<C: CryptoProvider> NpHmacSha256Key<C> {
///
/// This is convenient for one-and-done HMAC usage rather than incrementally accumulating
/// the final MAC.
- pub fn verify_hmac(
+ pub fn verify_hmac<C: CryptoProvider>(
&self,
data: &[u8],
expected_mac: [u8; 32],
) -> Result<(), crypto_provider::hmac::MacError> {
- let mut hmac = self.build_hmac();
+ let mut hmac = self.build_hmac::<C>();
hmac.update(data);
hmac.verify(expected_mac)
}
}
-impl<C: CryptoProvider> From<[u8; 32]> for NpHmacSha256Key<C> {
+impl From<[u8; 32]> for NpHmacSha256Key {
fn from(key: [u8; 32]) -> Self {
- Self { key, c_phantom: Default::default() }
- }
-}
-
-impl<C: CryptoProvider> Clone for NpHmacSha256Key<C> {
- fn clone(&self) -> Self {
- Self { key: self.key, c_phantom: Default::default() }
+ Self { key }
}
}
@@ -106,84 +99,142 @@ impl<C: CryptoProvider> NpKeySeedHkdf<C> {
/// LDT key used to decrypt a legacy advertisement
#[allow(clippy::expect_used)]
- pub fn legacy_ldt_key(&self) -> ldt::LdtKey<xts_aes::XtsAes128Key> {
+ pub fn v0_ldt_key(&self) -> ldt::LdtKey<xts_aes::XtsAes128Key> {
ldt::LdtKey::from_concatenated(
- &self.hkdf.derive_array(b"Legacy LDT key").expect("LDT key is a valid length"),
+ &self.hkdf.derive_array(b"V0 LDT key").expect("LDT key is a valid length"),
)
}
- /// HMAC key used when verifying the raw metadata key extracted from an advertisement
- pub fn legacy_metadata_key_hmac_key(&self) -> NpHmacSha256Key<C> {
- self.hkdf.derive_hmac_sha256_key(b"Legacy metadata key verification HMAC key")
+ /// HMAC key used when verifying the raw identity token extracted from an advertisement
+ pub fn v0_identity_token_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"V0 Identity token verification HMAC key")
}
/// AES-GCM nonce used when decrypting metadata
#[allow(clippy::expect_used)]
- pub fn legacy_metadata_nonce(&self) -> [u8; 12] {
- self.hkdf.derive_array(b"Legacy Metadata Nonce").expect("Nonce is a valid length")
+ pub fn v0_metadata_nonce(&self) -> <C::Aes128Gcm as Aead>::Nonce {
+ self.hkdf.derive_array(b"V0 Metadata nonce").expect("Nonce is a valid length")
}
/// AES-GCM nonce used when decrypting metadata.
///
/// Shared between signed and unsigned since they use the same credential.
#[allow(clippy::expect_used)]
- pub fn extended_metadata_nonce(&self) -> [u8; 12] {
- self.hkdf.derive_array(b"Metadata Nonce").expect("Nonce is a valid length")
+ pub fn v1_metadata_nonce(&self) -> <C::Aes128Gcm as Aead>::Nonce {
+ self.hkdf.derive_array(b"V1 Metadata nonce").expect("Nonce is a valid length")
}
- /// HMAC key used when verifying the raw metadata key extracted from an advertisement
- pub fn extended_unsigned_metadata_key_hmac_key(&self) -> NpHmacSha256Key<C> {
- self.hkdf.derive_hmac_sha256_key(b"Unsigned Section metadata key HMAC key")
+ /// Derived keys for MIC short salt sections
+ pub fn v1_mic_short_salt_keys(&self) -> MicShortSaltSectionKeys<'_, C> {
+ MicShortSaltSectionKeys { hkdf: &self.hkdf }
}
- /// HMAC key used when verifying the raw metadata key extracted from an extended signed advertisement
- #[allow(clippy::expect_used)]
- pub fn extended_signed_metadata_key_hmac_key(&self) -> NpHmacSha256Key<C> {
- self.hkdf.derive_hmac_sha256_key(b"Signed Section metadata key HMAC key")
+ /// Derived keys for MIC extended salt sections
+ pub fn v1_mic_extended_salt_keys(&self) -> MicExtendedSaltSectionKeys<'_, C> {
+ MicExtendedSaltSectionKeys { hkdf: &self.hkdf }
}
- /// AES128 key used when decrypting an extended signed section
- #[allow(clippy::expect_used)]
- pub fn extended_signed_section_aes_key(&self) -> Aes128Key {
- self.hkdf.derive_aes128_key(b"Signed Section AES key")
+ /// Derived keys for MIC signature sections
+ pub fn v1_signature_keys(&self) -> SignatureSectionKeys<'_, C> {
+ SignatureSectionKeys { hkdf: &self.hkdf }
+ }
+}
+
+/// Derived keys for MIC short salt sections
+pub struct MicShortSaltSectionKeys<'a, C: CryptoProvider> {
+ hkdf: &'a NpHkdf<C>,
+}
+
+impl<'a, C: CryptoProvider> MicShortSaltSectionKeys<'a, C> {
+ /// HMAC-SHA256 key used when verifying a section's ciphertext
+ pub fn mic_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"MIC Section short salt HMAC key")
+ }
+}
+
+impl<'a, C: CryptoProvider> DerivedSectionKeys<C> for MicShortSaltSectionKeys<'a, C> {
+ fn aes_key(&self) -> Aes128Key {
+ self.hkdf.derive_aes128_key(b"MIC Section short salt AES key")
+ }
+
+ fn identity_token_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"MIC Section short salt identity token HMAC key")
}
}
-impl<C: CryptoProvider> UnsignedSectionKeys<C> for NpKeySeedHkdf<C> {
+/// Derived keys for MIC extended salt sections
+pub struct MicExtendedSaltSectionKeys<'a, C: CryptoProvider> {
+ hkdf: &'a NpHkdf<C>,
+}
+
+impl<'a, C: CryptoProvider> MicExtendedSaltSectionKeys<'a, C> {
+ /// HMAC-SHA256 key used when verifying a section's ciphertext
+ pub fn mic_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"MIC Section extended salt HMAC key")
+ }
+}
+
+impl<'a, C: CryptoProvider> DerivedSectionKeys<C> for MicExtendedSaltSectionKeys<'a, C> {
+ fn aes_key(&self) -> Aes128Key {
+ self.hkdf.derive_aes128_key(b"MIC Section extended salt AES key")
+ }
+
+ fn identity_token_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"MIC Section extended salt identity token HMAC key")
+ }
+}
+
+/// Derived keys for Signature sections
+pub struct SignatureSectionKeys<'a, C: CryptoProvider> {
+ hkdf: &'a NpHkdf<C>,
+}
+
+impl<'a, C: CryptoProvider> DerivedSectionKeys<C> for SignatureSectionKeys<'a, C> {
fn aes_key(&self) -> Aes128Key {
- self.hkdf.derive_aes128_key(b"Unsigned Section AES key")
+ self.hkdf.derive_aes128_key(b"Signature Section AES key")
}
- fn hmac_key(&self) -> NpHmacSha256Key<C> {
- self.hkdf.derive_hmac_sha256_key(b"Unsigned Section HMAC key")
+ fn identity_token_hmac_key(&self) -> NpHmacSha256Key {
+ self.hkdf.derive_hmac_sha256_key(b"Signature Section identity token HMAC key")
}
}
-/// Derived keys for V1 MIC (unsigned) sections
-pub trait UnsignedSectionKeys<C: CryptoProvider> {
- /// AES128 key used when decrypting an extended unsigned section
+/// Derived keys for encrypted V1 sections
+pub trait DerivedSectionKeys<C: CryptoProvider> {
+ /// AES128 key used when encrypting a section's ciphertext
fn aes_key(&self) -> Aes128Key;
- /// HMAC-SHA256 key used when verifying an extended unsigned section
- fn hmac_key(&self) -> NpHmacSha256Key<C>;
+ /// HMAC-SHA256 key used when verifying a section's plaintext identity token
+ fn identity_token_hmac_key(&self) -> NpHmacSha256Key;
}
/// Expand a legacy salt into the expanded salt used with XOR padding in LDT.
#[allow(clippy::expect_used)]
-pub fn legacy_ldt_expanded_salt<const B: usize, C: CryptoProvider>(salt: &[u8; 2]) -> [u8; B] {
- simple_np_hkdf_expand::<B, C>(salt, b"Legacy LDT salt pad")
- // the padded salt is the tweak size of a tweakable block cipher, which shouldn't be
- // anywhere close to the max HKDF size (255 * 32)
+pub fn v0_ldt_expanded_salt<C: CryptoProvider>(salt: &[u8; 2]) -> [u8; aes::BLOCK_SIZE] {
+ simple_np_hkdf_expand::<{ aes::BLOCK_SIZE }, C>(salt, b"V0 LDT salt pad")
+ // XTS tweak size is the block cipher's block size
.expect("Tweak size is a valid HKDF size")
}
-/// Expand a legacy (short) raw metadata key into an AES128 key.
+/// Expand a v0 identity token into an AES128 metadata key.
#[allow(clippy::expect_used)]
-pub fn legacy_metadata_expanded_key<C: CryptoProvider>(raw_metadata_key: &[u8; 14]) -> [u8; 16] {
- simple_np_hkdf_expand::<16, C>(raw_metadata_key, b"Legacy metadata key expansion")
+pub fn v0_metadata_expanded_key<C: CryptoProvider>(identity_token: &[u8; 14]) -> [u8; 16] {
+ simple_np_hkdf_expand::<16, C>(identity_token, b"V0 Metadata key expansion")
.expect("AES128 key is a valid HKDF size")
}
+/// Expand an extended MIC section's short salt into an AES-CTR nonce.
+#[allow(clippy::expect_used)]
+pub fn extended_mic_section_short_salt_nonce<C: CryptoProvider>(
+ salt: [u8; 2],
+) -> aes::ctr::AesCtrNonce {
+ simple_np_hkdf_expand::<{ aes::ctr::AES_CTR_NONCE_LEN }, C>(
+ salt.as_slice(),
+ b"MIC Section short salt nonce",
+ )
+ .expect("AES-CTR nonce is a valid HKDF size")
+}
+
/// Build an HKDF using the NP HKDF salt, calculate output, and discard the HKDF.
/// If using the NP key seed as IKM, see [NpKeySeedHkdf] instead.
///
@@ -198,12 +249,12 @@ fn simple_np_hkdf_expand<const N: usize, C: CryptoProvider>(
}
/// Construct an HKDF with the Nearby Presence salt and provided `ikm`
-pub fn np_salt_hkdf<C: CryptoProvider>(ikm: &[u8]) -> C::HkdfSha256 {
+fn np_salt_hkdf<C: CryptoProvider>(ikm: &[u8]) -> C::HkdfSha256 {
C::HkdfSha256::new(Some(NP_HKDF_SALT), ikm)
}
/// NP-flavored HKDF operations for common derived output types
-pub struct NpHkdf<C: CryptoProvider> {
+struct NpHkdf<C: CryptoProvider> {
hkdf: C::HkdfSha256,
}
@@ -222,7 +273,7 @@ impl<C: CryptoProvider> NpHkdf<C> {
/// Derive an HMAC-SHA256 key using the provided `info`
#[allow(clippy::expect_used)]
- pub fn derive_hmac_sha256_key(&self, info: &[u8]) -> NpHmacSha256Key<C> {
+ pub fn derive_hmac_sha256_key(&self, info: &[u8]) -> NpHmacSha256Key {
self.derive_array(info).expect("HMAC-SHA256 keys are a valid length").into()
}
/// Derive an AES-128 key using the provided `info`
diff --git a/nearby/presence/np_hkdf/src/v1_salt.rs b/nearby/presence/np_hkdf/src/v1_salt.rs
index 94e6855..cfa1f51 100644
--- a/nearby/presence/np_hkdf/src/v1_salt.rs
+++ b/nearby/presence/np_hkdf/src/v1_salt.rs
@@ -14,45 +14,44 @@
//! Salt used in a V1 advertisement.
use crate::np_salt_hkdf;
-use core::fmt;
-use crypto_provider::hkdf::Hkdf;
-use crypto_provider::CryptoProvider;
+use crypto_provider::{hkdf::Hkdf, CryptoProvider, CryptoRng, FromCryptoRng};
+
+/// Length of a V1 extended salt
+pub const EXTENDED_SALT_LEN: usize = 16;
/// Salt optionally included in V1 advertisement header.
///
/// The salt is never used directly; rather, a derived salt should be extracted as needed for any
/// section or DE that requires it.
-#[derive(Clone)]
-pub struct V1Salt<C>
-where
- C: CryptoProvider,
-{
- // kept around for Eq and Debug impl, should not be exposed
- data: [u8; 16],
- hkdf: C::HkdfSha256,
+#[derive(Clone, Copy, PartialEq, Debug, Eq)]
+pub struct ExtendedV1Salt {
+ data: [u8; EXTENDED_SALT_LEN],
}
-impl<C: CryptoProvider> V1Salt<C> {
- /// Derive a salt for a particular section and DE, if applicable.
+impl ExtendedV1Salt {
+ /// Derive a salt for a particular DE, if applicable.
///
/// Returns none if the requested size is larger than HKDF allows or if offset arithmetic
/// overflows.
- pub fn derive<const N: usize>(&self, de: Option<DataElementOffset>) -> Option<[u8; N]> {
+ pub fn derive<const N: usize, C: CryptoProvider>(
+ &self,
+ de: Option<DataElementOffset>,
+ ) -> Option<[u8; N]> {
+ let hkdf = np_salt_hkdf::<C>(&self.data);
let mut arr = [0_u8; N];
// 0-based offsets -> 1-based indices w/ 0 indicating not present
- self.hkdf
- .expand_multi_info(
- &[
- b"V1 derived salt",
- &de.and_then(|d| d.offset.checked_add(1))
- .map(|o| o.into())
- .unwrap_or(0_u32)
- .to_be_bytes(),
- ],
- &mut arr,
- )
- .map(|_| arr)
- .ok()
+ hkdf.expand_multi_info(
+ &[
+ b"V1 derived salt",
+ &de.and_then(|d| d.offset.checked_add(1))
+ .map(|o| o.into())
+ .unwrap_or(0_u32)
+ .to_be_bytes(),
+ ],
+ &mut arr,
+ )
+ .map(|_| arr)
+ .ok()
}
/// Returns the salt bytes as a slice
@@ -61,38 +60,29 @@ impl<C: CryptoProvider> V1Salt<C> {
}
/// Returns the salt bytes as an array
- pub fn into_array(self) -> [u8; 16] {
+ pub fn into_array(self) -> [u8; EXTENDED_SALT_LEN] {
self.data
}
/// Returns the salt bytes as a reference to an array
- pub fn as_array_ref(&self) -> &[u8; 16] {
+ pub fn bytes(&self) -> &[u8; EXTENDED_SALT_LEN] {
&self.data
}
}
-impl<C: CryptoProvider> From<[u8; 16]> for V1Salt<C> {
- fn from(arr: [u8; 16]) -> Self {
- Self { data: arr, hkdf: np_salt_hkdf::<C>(&arr) }
+impl From<[u8; EXTENDED_SALT_LEN]> for ExtendedV1Salt {
+ fn from(arr: [u8; EXTENDED_SALT_LEN]) -> Self {
+ Self { data: arr }
}
}
-impl<C: CryptoProvider> PartialEq<Self> for V1Salt<C> {
- fn eq(&self, other: &Self) -> bool {
- // no need to compare hkdf (which it doesn't allow anyway)
- self.data == other.data
- }
-}
-
-impl<C: CryptoProvider> Eq for V1Salt<C> {}
-
-impl<C: CryptoProvider> fmt::Debug for V1Salt<C> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.data.fmt(f)
+impl FromCryptoRng for ExtendedV1Salt {
+ fn new_random<R: CryptoRng>(rng: &mut R) -> Self {
+ rng.gen::<[u8; EXTENDED_SALT_LEN]>().into()
}
}
-/// Offset of a data element in its containing section, used with [V1Salt].
+/// Offset of a data element in its containing section, used with [ExtendedV1Salt].
#[derive(PartialEq, Eq, Debug, Clone, Copy, PartialOrd, Ord)]
pub struct DataElementOffset {
/// 0-based offset of the DE in the advertisement
diff --git a/nearby/presence/np_hkdf/tests/hmac.rs b/nearby/presence/np_hkdf/tests/hmac.rs
index 4ebef5a..9cb0357 100644
--- a/nearby/presence/np_hkdf/tests/hmac.rs
+++ b/nearby/presence/np_hkdf/tests/hmac.rs
@@ -21,11 +21,11 @@ fn verify_hmac_correct_mac() {
let data = &[1_u8; 32];
let hmac_key = [2; 32];
- let hmac = NpHmacSha256Key::<CryptoProviderImpl>::from(hmac_key);
+ let hmac = NpHmacSha256Key::from(hmac_key);
- let mac = hmac.calculate_hmac(data);
+ let mac = hmac.calculate_hmac::<CryptoProviderImpl>(data);
- assert_eq!(Ok(()), hmac.verify_hmac(data, mac));
+ assert_eq!(Ok(()), hmac.verify_hmac::<CryptoProviderImpl>(data, mac));
}
#[test]
@@ -33,10 +33,10 @@ fn verify_hmac_incorrect_mac() {
let data = &[1_u8; 32];
let hmac_key = [2; 32];
- let hmac = NpHmacSha256Key::<CryptoProviderImpl>::from(hmac_key);
+ let hmac = NpHmacSha256Key::from(hmac_key);
- let _mac = hmac.calculate_hmac(data);
+ let _mac = hmac.calculate_hmac::<CryptoProviderImpl>(data);
// wrong mac
- assert_eq!(Err(MacError), hmac.verify_hmac(data, [0xFF; 32]));
+ assert_eq!(Err(MacError), hmac.verify_hmac::<CryptoProviderImpl>(data, [0xFF; 32]));
}
diff --git a/nearby/presence/np_hkdf/tests/test_vectors.rs b/nearby/presence/np_hkdf/tests/test_vectors.rs
index 175e73e..a00e747 100644
--- a/nearby/presence/np_hkdf/tests/test_vectors.rs
+++ b/nearby/presence/np_hkdf/tests/test_vectors.rs
@@ -17,12 +17,11 @@
use anyhow::anyhow;
use crypto_provider::aes::AesKey;
use crypto_provider_default::CryptoProviderImpl;
-use np_hkdf::{v1_salt::V1Salt, *};
-use rand::Rng as _;
-use rand_ext::seeded_rng;
+use np_hkdf::{v1_salt::ExtendedV1Salt, *};
use serde_json::json;
use std::{fs, io::Read as _};
use test_helper::extract_key_array;
+use test_vector_hkdf::TestVectorHkdf;
#[test]
fn hkdf_test_vectors() -> Result<(), anyhow::Error> {
@@ -42,76 +41,97 @@ fn hkdf_test_vectors() -> Result<(), anyhow::Error> {
let key_seed = extract_key_array::<32>(group, "key_seed");
let hkdf = NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
assert_eq!(
- extract_key_array::<64>(group, "legacy_ldt_key"),
- hkdf.legacy_ldt_key().as_concatenated()
+ extract_key_array::<64>(group, "v0_ldt_key"),
+ hkdf.v0_ldt_key().as_concatenated()
);
assert_eq!(
- &extract_key_array::<32>(group, "legacy_metadata_key_hmac_key"),
- hkdf.legacy_metadata_key_hmac_key().as_bytes()
+ &extract_key_array::<32>(group, "v0_identity_token_hmac_key"),
+ hkdf.v0_identity_token_hmac_key().as_bytes()
);
assert_eq!(
- extract_key_array::<12>(group, "legacy_metadata_nonce"),
- hkdf.legacy_metadata_nonce()
+ extract_key_array::<12>(group, "v0_metadata_nonce"),
+ hkdf.v0_metadata_nonce()
);
assert_eq!(
- extract_key_array::<12>(group, "extended_metadata_nonce"),
- hkdf.extended_metadata_nonce()
+ extract_key_array::<12>(group, "v1_metadata_nonce"),
+ hkdf.v1_metadata_nonce()
);
assert_eq!(
- &extract_key_array::<32>(group, "extended_unsigned_metadata_key_hmac_key"),
- hkdf.extended_unsigned_metadata_key_hmac_key().as_bytes()
+ &extract_key_array::<32>(group, "v1_mic_short_salt_identity_token_hmac_key"),
+ hkdf.v1_mic_short_salt_keys().identity_token_hmac_key().as_bytes()
);
assert_eq!(
- extract_key_array::<16>(group, "extended_unsigned_section_aes_key"),
- *UnsignedSectionKeys::aes_key(&hkdf).as_array()
+ extract_key_array::<16>(group, "v1_mic_short_salt_aes_key"),
+ *hkdf.v1_mic_short_salt_keys().aes_key().as_array()
);
assert_eq!(
- &extract_key_array::<32>(group, "extended_unsigned_section_mic_hmac_key"),
- UnsignedSectionKeys::hmac_key(&hkdf).as_bytes()
+ &extract_key_array::<32>(group, "v1_mic_short_salt_mic_hmac_key"),
+ hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes()
);
assert_eq!(
- &extract_key_array::<32>(group, "extended_signed_metadata_key_hmac_key"),
- hkdf.extended_signed_metadata_key_hmac_key().as_bytes()
+ &extract_key_array::<32>(group, "v1_mic_extended_salt_identity_token_hmac_key"),
+ hkdf.v1_mic_extended_salt_keys().identity_token_hmac_key().as_bytes()
);
assert_eq!(
- extract_key_array::<16>(group, "extended_signed_section_aes_key"),
- *hkdf.extended_signed_section_aes_key().as_array()
+ extract_key_array::<16>(group, "v1_mic_extended_salt_aes_key"),
+ *hkdf.v1_mic_extended_salt_keys().aes_key().as_array()
+ );
+ assert_eq!(
+ &extract_key_array::<32>(group, "v1_mic_extended_salt_mic_hmac_key"),
+ hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes()
+ );
+ assert_eq!(
+ &extract_key_array::<32>(group, "v1_signature_identity_token_hmac_key"),
+ hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes()
+ );
+ assert_eq!(
+ extract_key_array::<16>(group, "v1_signature_section_aes_key"),
+ *hkdf.v1_signature_keys().aes_key().as_array()
);
}
{
- let group = &tc["legacy_adv_salt_hkdf"];
+ let group = &tc["v0_adv_salt_hkdf"];
let ikm = extract_key_array::<2>(group, "adv_salt");
assert_eq!(
extract_key_array::<16>(group, "expanded_salt"),
- legacy_ldt_expanded_salt::<16, CryptoProviderImpl>(&ikm)
+ v0_ldt_expanded_salt::<CryptoProviderImpl>(&ikm)
)
}
{
- let group = &tc["legacy_metadata_key_hkdf"];
- let ikm = extract_key_array::<14>(group, "legacy_metadata_key");
+ let group = &tc["v0_identity_token_hkdf"];
+ let ikm = extract_key_array::<14>(group, "v0_identity_token");
assert_eq!(
extract_key_array::<16>(group, "expanded_key"),
- legacy_metadata_expanded_key::<CryptoProviderImpl>(&ikm)
+ v0_metadata_expanded_key::<CryptoProviderImpl>(&ikm)
)
}
{
- let group = &tc["extended_section_salt_hkdf"];
- let ikm = extract_key_array::<16>(group, "section_salt");
- let salt = V1Salt::<CryptoProviderImpl>::from(ikm);
+ let group = &tc["v1_section_extended_salt_hkdf"];
+ let ikm = extract_key_array::<16>(group, "section_extended_salt");
+ let salt = ExtendedV1Salt::from(ikm);
+ assert_eq!(
+ extract_key_array::<16>(group, "derived_salt_nonce"),
+ salt.derive::<16, CryptoProviderImpl>(None).unwrap(),
+ );
assert_eq!(
- extract_key_array::<16>(group, "derived_salt_first_section_no_de"),
- salt.derive(None).unwrap(),
+ extract_key_array::<16>(group, "derived_salt_first_de"),
+ salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap(),
);
assert_eq!(
- extract_key_array::<16>(group, "derived_salt_first_section_first_de"),
- salt.derive(Some(0.into())).unwrap(),
+ extract_key_array::<16>(group, "derived_salt_third_de"),
+ salt.derive::<16, CryptoProviderImpl>(Some(2.into())).unwrap(),
);
+ }
+
+ {
+ let group = &tc["v1_mic_section_short_salt_hkdf"];
+ let ikm = extract_key_array::<2>(group, "section_short_salt");
assert_eq!(
- extract_key_array::<16>(group, "derived_salt_first_section_third_de"),
- salt.derive(Some(2.into())).unwrap(),
+ extract_key_array::<12>(group, "short_salt_nonce"),
+ extended_mic_section_short_salt_nonce::<CryptoProviderImpl>(ikm),
);
}
}
@@ -121,53 +141,70 @@ fn hkdf_test_vectors() -> Result<(), anyhow::Error> {
// disable unless you want to print out a new set of test vectors
#[ignore]
+#[allow(clippy::panic)]
#[test]
fn gen_test_vectors() {
- let mut rng = seeded_rng();
-
let mut array = Vec::<serde_json::Value>::new();
- for _ in 0..100 {
- let key_seed: [u8; 32] = rng.gen();
- let legacy_adv_salt: [u8; 2] = rng.gen();
- let legacy_metadata_key: [u8; 14] = rng.gen();
- let adv_salt_bytes: [u8; 16] = rng.gen();
- let extended_adv_salt = V1Salt::<CryptoProviderImpl>::from(adv_salt_bytes);
+ for i in 0_u32..100 {
+ // build "random" things in a repeatable way so future changes don't
+ // rebuild unrelated things, with some /dev/random thrown in for good measure
+ let test_vector_seed_hkdf = TestVectorHkdf::<CryptoProviderImpl>::new(
+ "NP HKDF test vectors pb4qoNqM9aL/ezSC2FU5EQzu8JJoJ25B+rLqbU5kVN8",
+ &i.to_be_bytes(),
+ );
+
+ let key_seed: [u8; 32] = test_vector_seed_hkdf.derive_array("key seed");
+ let v0_adv_salt: [u8; 2] = test_vector_seed_hkdf.derive_array("legacy adv salt");
+ let v0_identity_token: [u8; 14] = test_vector_seed_hkdf.derive_array("v0 identity token");
+ let extended_salt_bytes: [u8; 16] =
+ test_vector_seed_hkdf.derive_array("v1 section extended salt");
+ let v1_mic_short_salt: [u8; 2] =
+ test_vector_seed_hkdf.derive_array("v1 mic section short salt");
+ let v1_extended_salt = ExtendedV1Salt::from(extended_salt_bytes);
let key_seed_hkdf = NpKeySeedHkdf::<CryptoProviderImpl>::new(&key_seed);
array
.push(json!({
"key_seed_hkdf": {
"key_seed": hex::encode_upper(key_seed),
- "legacy_ldt_key": hex::encode_upper(key_seed_hkdf.legacy_ldt_key().as_concatenated()),
- "legacy_metadata_key_hmac_key":
- hex::encode_upper(key_seed_hkdf.legacy_metadata_key_hmac_key().as_bytes()),
- "legacy_metadata_nonce": hex::encode_upper(key_seed_hkdf.legacy_metadata_nonce()),
- "extended_metadata_nonce": hex::encode_upper(key_seed_hkdf.extended_metadata_nonce()),
- "extended_unsigned_metadata_key_hmac_key": hex::encode_upper(key_seed_hkdf.extended_unsigned_metadata_key_hmac_key().as_bytes()),
- "extended_unsigned_section_aes_key": hex::encode_upper(UnsignedSectionKeys::<CryptoProviderImpl>::aes_key(&key_seed_hkdf).as_array()),
- "extended_unsigned_section_mic_hmac_key": hex::encode_upper(UnsignedSectionKeys::<CryptoProviderImpl>::hmac_key(&key_seed_hkdf).as_bytes()),
- "extended_signed_metadata_key_hmac_key": hex::encode_upper(key_seed_hkdf.extended_signed_metadata_key_hmac_key().as_bytes()),
- "extended_signed_section_aes_key": hex::encode_upper(key_seed_hkdf.extended_signed_section_aes_key().as_array()),
+ "v0_ldt_key": hex::encode_upper(key_seed_hkdf.v0_ldt_key().as_concatenated()),
+ "v0_identity_token_hmac_key":
+ hex::encode_upper(key_seed_hkdf.v0_identity_token_hmac_key().as_bytes()),
+ "v0_metadata_nonce": hex::encode_upper(key_seed_hkdf.v0_metadata_nonce()),
+ "v1_metadata_nonce": hex::encode_upper(key_seed_hkdf.v1_metadata_nonce()),
+ "v1_mic_short_salt_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().identity_token_hmac_key().as_bytes()),
+ "v1_mic_short_salt_aes_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().aes_key().as_array()),
+ "v1_mic_short_salt_mic_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_short_salt_keys().mic_hmac_key().as_bytes()),
+ "v1_mic_extended_salt_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().identity_token_hmac_key().as_bytes()),
+ "v1_mic_extended_salt_aes_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().aes_key().as_array()),
+ "v1_mic_extended_salt_mic_hmac_key": hex::encode_upper(key_seed_hkdf.v1_mic_extended_salt_keys().mic_hmac_key().as_bytes()),
+ "v1_signature_identity_token_hmac_key": hex::encode_upper(key_seed_hkdf.v1_signature_keys().identity_token_hmac_key().as_bytes()),
+ "v1_signature_section_aes_key": hex::encode_upper(key_seed_hkdf.v1_signature_keys().aes_key().as_array()),
},
- "legacy_adv_salt_hkdf": {
- "adv_salt": hex::encode_upper(legacy_adv_salt),
- "expanded_salt": hex::encode_upper(legacy_ldt_expanded_salt::<16, CryptoProviderImpl>(&legacy_adv_salt))
+ "v0_adv_salt_hkdf": {
+ "adv_salt": hex::encode_upper(v0_adv_salt),
+ "expanded_salt": hex::encode_upper(v0_ldt_expanded_salt::<CryptoProviderImpl>(&v0_adv_salt))
},
- "legacy_metadata_key_hkdf": {
- "legacy_metadata_key": hex::encode_upper(legacy_metadata_key),
+ "v0_identity_token_hkdf": {
+ "v0_identity_token": hex::encode_upper(v0_identity_token),
"expanded_key":
- hex::encode_upper(legacy_metadata_expanded_key::<CryptoProviderImpl>(&legacy_metadata_key))
+ hex::encode_upper(v0_metadata_expanded_key::<CryptoProviderImpl>(&v0_identity_token))
},
- "extended_section_salt_hkdf": {
- "section_salt": hex::encode_upper(adv_salt_bytes),
+ "v1_section_extended_salt_hkdf": {
+ "section_extended_salt": hex::encode_upper(v1_extended_salt.bytes()),
// 0-based offsets -> 1-based indexing
- "derived_salt_first_section_no_de": hex::encode_upper(extended_adv_salt.derive::<16>(None).unwrap()),
- "derived_salt_first_section_first_de": hex::encode_upper(extended_adv_salt.derive::<16>(Some(0.into())).unwrap()),
- "derived_salt_first_section_third_de": hex::encode_upper(extended_adv_salt.derive::<16>(Some(2.into())).unwrap()),
+ "derived_salt_nonce": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(None).unwrap()),
+ "derived_salt_first_de": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(Some(0.into())).unwrap()),
+ "derived_salt_third_de": hex::encode_upper(v1_extended_salt.derive::<16, CryptoProviderImpl>(Some(2.into())).unwrap()),
+ },
+ "v1_mic_section_short_salt_hkdf": {
+ "section_short_salt": hex::encode_upper(v1_mic_short_salt),
+ "short_salt_nonce": hex::encode_upper(extended_mic_section_short_salt_nonce::<CryptoProviderImpl>(v1_mic_short_salt)),
}
}));
}
println!("{}", serde_json::ser::to_string_pretty(&array).unwrap());
+ panic!("Don't leave this test enabled. Meanwhile, enjoy the text output above.");
}
diff --git a/nearby/presence/np_java_ffi/.gitignore b/nearby/presence/np_java_ffi/.gitignore
new file mode 100644
index 0000000..cafbf51
--- /dev/null
+++ b/nearby/presence/np_java_ffi/.gitignore
@@ -0,0 +1,8 @@
+# Ignore Gradle project-specific cache directory
+/.gradle
+
+# Ignore Gradle build output directory
+/build
+
+# Ignore IDEA dir
+/.idea
diff --git a/nearby/presence/np_java_ffi/Cargo.toml b/nearby/presence/np_java_ffi/Cargo.toml
new file mode 100644
index 0000000..556b481
--- /dev/null
+++ b/nearby/presence/np_java_ffi/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "np_java_ffi"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
+handle_map.workspace = true
+np_adv.workspace = true
+np_ffi_core.workspace = true
+pourover.workspace = true
+pourover_macro.workspace = true
+crypto_provider_default.workspace = true # for setting features from cmdline
+
+jni.workspace = true
+
+[lib]
+# JNI wants a .so or equivalent
+crate-type = ["cdylib"]
diff --git a/nearby/presence/np_java_ffi/build.gradle.kts b/nearby/presence/np_java_ffi/build.gradle.kts
new file mode 100644
index 0000000..69d73c4
--- /dev/null
+++ b/nearby/presence/np_java_ffi/build.gradle.kts
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+plugins {
+ `java-library`
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation("androidx.annotation:annotation:1.6.0")
+
+ // JUnit Test Support
+ testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
+ testImplementation("com.google.truth:truth:1.1.4")
+ testImplementation("org.mockito:mockito-core:5.+")
+ testImplementation("org.mockito:mockito-junit-jupiter:5.+")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
+}
+
+// Flattened directory layout
+sourceSets {
+ main {
+ java {
+ setSrcDirs(listOf("java"))
+ }
+ }
+ test {
+ java {
+ setSrcDirs(listOf("test"))
+ }
+ }
+}
+
+tasks.test {
+ useJUnitPlatform()
+ jvmArgs = mutableListOf("-Djava.library.path=$projectDir/../../target/debug")
+}
diff --git a/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.jar b/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..943f0cb
--- /dev/null
+++ b/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.properties b/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f398c33
--- /dev/null
+++ b/nearby/presence/np_java_ffi/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
+networkTimeout=10000
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/nearby/presence/np_java_ffi/gradlew b/nearby/presence/np_java_ffi/gradlew
new file mode 100755
index 0000000..79a61d4
--- /dev/null
+++ b/nearby/presence/np_java_ffi/gradlew
@@ -0,0 +1,244 @@
+#!/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##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# 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"'
+
+# 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
+ which java >/dev/null 2>&1 || 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
+
+# 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=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=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
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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" "$@"
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializationException.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializationException.java
new file mode 100644
index 0000000..68db2c9
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializationException.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+/** Base class for exceptions that can occur during deserialization. */
+public abstract class DeserializationException extends Exception {
+
+ private DeserializationException(String message) {
+ super(message);
+ }
+
+ public static final class InvalidHeaderException extends DeserializationException {
+ public InvalidHeaderException() {
+ super("Invalid advertisement header");
+ }
+ }
+
+ public static final class InvalidFormatException extends DeserializationException {
+ public InvalidFormatException() {
+ super("Invalid advertisement format");
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializeResult.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializeResult.java
new file mode 100644
index 0000000..865df41
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializeResult.java
@@ -0,0 +1,122 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+import java.lang.annotation.Retention;
+
+/**
+ * A result of calling {@link NpAdv#deserializeAdvertisement}. This represents either an error
+ * condition or successfully deserialized advertisement.
+ *
+ * <p>Note: A successfully deserialized advertisement may still not be legible for cryptographic
+ * reasons. That condition is reported on the advertisement object itself since a V1 advertisement
+ * may be partially legible (some sections are legible, not all).
+ */
+public final class DeserializeResult implements AutoCloseable {
+
+ @IntDef({
+ Kind.UNKNOWN_ERROR,
+ Kind.V0_ADVERTISEMENT,
+ Kind.V1_ADVERTISEMENT,
+ })
+ @Retention(SOURCE)
+ public @interface Kind {
+ public static final int UNKNOWN_ERROR = -1;
+
+ public static final int V0_ADVERTISEMENT = 1;
+ public static final int V1_ADVERTISEMENT = 2;
+ }
+
+ /** Checks if a {@link Kind} represents and error or not. */
+ public static boolean isErrorKind(@Kind int kind) {
+ return kind <= 0;
+ }
+
+ private final @Kind int kind;
+ private final @Nullable DeserializedAdvertisement advertisement;
+
+ /** Create a DeserializeResult containing an error code */
+ /* package */ DeserializeResult(@Kind int errorKind) {
+ if (!isErrorKind(errorKind)) {
+ throw new IllegalArgumentException(
+ "Cannot create empty DeserializeResult with non-error kind");
+ }
+ this.kind = errorKind;
+ this.advertisement = null;
+ }
+
+ /** Create a DeserializeResult containing a V0 advertisement */
+ /* package */ DeserializeResult(DeserializedV0Advertisement advertisement) {
+ this.kind = Kind.V0_ADVERTISEMENT;
+ this.advertisement = advertisement;
+ }
+
+ /** Create a DeserializeResult containing a V1 advertisement */
+ /* package */ DeserializeResult(DeserializedV1Advertisement advertisement) {
+ this.kind = Kind.V1_ADVERTISEMENT;
+ this.advertisement = advertisement;
+ }
+
+ /** Gets the kind of this result. */
+ @Kind
+ public int getKind() {
+ return kind;
+ }
+
+ /** Check if this result is an error result. */
+ public boolean isError() {
+ return isErrorKind(kind);
+ }
+
+ /**
+ * Gets the contained V0 advertisement if present.
+ *
+ * @return the contained V0 advertisement or {@code null} if not present
+ */
+ @Nullable
+ public DeserializedV0Advertisement getAsV0() {
+ if (this.kind != Kind.V0_ADVERTISEMENT) {
+ return null;
+ }
+ return (DeserializedV0Advertisement) this.advertisement;
+ }
+
+ /**
+ * Gets the contained V1 advertisement if present.
+ *
+ * @return the contained V1 advertisement or {@code null} if not present
+ */
+ @Nullable
+ public DeserializedV1Advertisement getAsV1() {
+ if (this.kind != Kind.V1_ADVERTISEMENT) {
+ return null;
+ }
+ return (DeserializedV1Advertisement) this.advertisement;
+ }
+
+ /** Closes the contained advertisement if it exists. */
+ @Override
+ public void close() {
+ if (this.advertisement != null) {
+ this.advertisement.close();
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedAdvertisement.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedAdvertisement.java
new file mode 100644
index 0000000..2058d8c
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedAdvertisement.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+/** A base class to provide a common type to V0 and V1 advertisements. */
+public abstract class DeserializedAdvertisement implements AutoCloseable {
+
+ /* package */ DeserializedAdvertisement() {}
+
+ // Assert that {@code close()} will not throw checked exceptions.
+ @Override
+ public abstract void close();
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV0Advertisement.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV0Advertisement.java
new file mode 100644
index 0000000..e4a0688
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV0Advertisement.java
@@ -0,0 +1,155 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import androidx.annotation.Nullable;
+import java.util.Iterator;
+
+/**
+ * A deserialized V0 advertisement. This class is backed by native data behind the {@link V0Payload}
+ * handle. If this class is closed then the underlying handle will be closed too. Methods on this
+ * class should not be called if {@link #close()} has already been called.
+ */
+public final class DeserializedV0Advertisement extends DeserializedAdvertisement {
+
+ public static boolean isLegibleIdentity(@IdentityKind int identity) {
+ return identity > 0;
+ }
+
+ private final int numDataElements;
+ private final @Nullable V0Payload payload;
+ private final @IdentityKind int identity;
+
+ /** Create an illegible instance with the given error identity. */
+ /* package */ DeserializedV0Advertisement(@IdentityKind int illegibleIdentity) {
+ if (isLegibleIdentity(illegibleIdentity)) {
+ throw new IllegalArgumentException(
+ "Cannot create empty DeserializedV0Advertisement with a legible identity");
+ }
+ this.numDataElements = 0;
+ this.payload = null;
+ this.identity = illegibleIdentity;
+ }
+
+ /** Create a legible instance with the given information. */
+ /* package */ DeserializedV0Advertisement(
+ int numDataElements, V0Payload payload, @IdentityKind int identity) {
+ this.numDataElements = numDataElements;
+ this.payload = payload;
+ this.identity = identity;
+ }
+
+ /**
+ * Create a legible instance with the given information. Payload is specified as a raw handle id.
+ * This is a helper to be called from native code to avoid needing to construct {@code V0Payload}
+ * on the native side.
+ */
+ /* package */ DeserializedV0Advertisement(
+ int numDataElements, long payload, @IdentityKind int identity) {
+ this(numDataElements, new V0Payload(payload), identity);
+ }
+
+ /** Check if this advertisement is legible */
+ public boolean isLegible() {
+ return isLegibleIdentity(this.identity);
+ }
+
+ /** Throws {@code IllegalStateException} if this advertisement is not legible. */
+ private void ensureLegible(String action) {
+ if (!isLegible()) {
+ throw new IllegalStateException(
+ String.format("Cannot %s for non-legible advertisement", action));
+ }
+ }
+
+ /**
+ * Gets the identity for this advertisement.
+ *
+ * @throws IllegalStateException if the advertisement is not legible ({@link #isLegible()}).
+ */
+ @IdentityKind
+ public int getIdentity() {
+ ensureLegible("get identity");
+ return this.identity;
+ }
+
+ /**
+ * Gets the number of data elements in this advertisement.
+ *
+ * @throws IllegalStateException if the advertisement is not legible ({@link #isLegible()}).
+ */
+ public int getDataElementCount() {
+ ensureLegible("get data element count");
+ return this.numDataElements;
+ }
+
+ /**
+ * Gets the data element at the given {@code index} in this advertisement.
+ *
+ * @param index The data element's index in the advertisement
+ * @throws IllegalStateException if the advertisement is not legible ({@link #isLegible()}).
+ * @throws IndexOutOfBoundsException if the index is invalid
+ * @return The data element at {@code index}
+ */
+ public V0DataElement getDataElement(int index) {
+ ensureLegible("get data element");
+ return payload.getDataElement(index);
+ }
+
+ /** Gets all the data elements for iteration. */
+ public Iterable<V0DataElement> getDataElements() {
+ return () -> new DataElementIterator(payload, numDataElements);
+ }
+
+ /** Visits all the data elements with the given visitor. */
+ public void visitDataElements(V0DataElement.Visitor v) {
+ for (V0DataElement de : getDataElements()) {
+ de.visit(v);
+ }
+ }
+
+ /** Iterator instance for data elements in DeserializedV0Advertisement. */
+ private static final class DataElementIterator implements Iterator<V0DataElement> {
+ private final V0Payload payload;
+ private final int numDataElements;
+
+ private int position = 0;
+
+ public DataElementIterator(V0Payload payload, int numDataElements) {
+ this.payload = payload;
+ this.numDataElements = numDataElements;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return position < (numDataElements - 1);
+ }
+
+ @Override
+ public V0DataElement next() {
+ return payload.getDataElement(position++);
+ }
+ }
+
+ /** Closes the payload handle if this advertisement is legible. */
+ @Override
+ public void close() {
+ if (this.payload != null) {
+ this.payload.close();
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Advertisement.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Advertisement.java
new file mode 100644
index 0000000..d1ecdcd
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Advertisement.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import java.util.Iterator;
+
+/**
+ * A deserialized V0 advertisement. This class is backed by native data behind the {@link
+ * LegibleV1Sections} handle. If this class is closed then the underlying handle will be closed too.
+ * Methods on this class should not be called if {@link #close()} has already been called.
+ */
+public final class DeserializedV1Advertisement extends DeserializedAdvertisement {
+
+ private final int numLegibleSections;
+ private final int numUndecryptableSections;
+ private final LegibleV1Sections legibleSections;
+
+ /** Create a legible instance with the given information. */
+ /* package */ DeserializedV1Advertisement(
+ int numLegibleSections, int numUndecryptableSections, LegibleV1Sections legibleSections) {
+ this.numLegibleSections = numLegibleSections;
+ this.numUndecryptableSections = numUndecryptableSections;
+ this.legibleSections = legibleSections;
+ }
+
+ /** Get the number of legible sections in this advertisement */
+ public int getNumLegibleSections() {
+ return numLegibleSections;
+ }
+
+ /** Get the number of undecryptable sections in this advertisement */
+ public int getNumUndecryptableSections() {
+ return numUndecryptableSections;
+ }
+
+ /**
+ * Gets the section at the given {@code index} in this advertisement. {@code index} only counts
+ * legible sections.
+ *
+ * @param index The section's index in the advertisement
+ * @throws IndexOutOfBoundsException if the index is invalid
+ * @return The section at {@code index}
+ */
+ public DeserializedV1Section getSection(int index) {
+ return legibleSections.getSection(index);
+ }
+
+ /** Get an iterable of this advertisement's legible sections. */
+ public Iterable<DeserializedV1Section> getSections() {
+ return () -> new SectionIterator(numLegibleSections, legibleSections);
+ }
+
+ /** Iterator instance for sections in DeserializedV1Advertisement. */
+ private static final class SectionIterator implements Iterator<DeserializedV1Section> {
+ private final LegibleV1Sections legibleSections;
+ private final int numSections;
+
+ private int position = 0;
+
+ public SectionIterator(int numSections, LegibleV1Sections legibleSections) {
+ this.numSections = numSections;
+ this.legibleSections = legibleSections;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return position < (numSections - 1);
+ }
+
+ @Override
+ public DeserializedV1Section next() {
+ return legibleSections.getSection(position++);
+ }
+ }
+
+ /** Closes the legible sections handle if it exists. */
+ @Override
+ public void close() {
+ if (this.legibleSections != null) {
+ this.legibleSections.close();
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Section.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Section.java
new file mode 100644
index 0000000..1667366
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/DeserializedV1Section.java
@@ -0,0 +1,95 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import java.util.Iterator;
+
+public final class DeserializedV1Section {
+ private final LegibleV1Sections legibleSections;
+ private final int legibleSectionsIndex;
+ private final int numDataElements;
+ private final @IdentityKind int identityTag;
+
+ /* package */ DeserializedV1Section(
+ LegibleV1Sections legibleSections,
+ int legibleSectionsIndex,
+ int numDataElements,
+ @IdentityKind int identityTag) {
+ this.legibleSections = legibleSections;
+ this.legibleSectionsIndex = legibleSectionsIndex;
+ this.numDataElements = numDataElements;
+ this.identityTag = identityTag;
+ }
+
+ /** Gets the identity kind for this section. */
+ @IdentityKind
+ public int getIdentityKind() {
+ return this.identityTag;
+ }
+
+ /** Gets the number of data elements in this section. */
+ public int getDataElementCount() {
+ return this.numDataElements;
+ }
+
+ /**
+ * Gets the data element at the given {@code index} in this advertisement.
+ *
+ * @throws IllegalStateException if the advertisement is not legible ({@link #isLegible()}).
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public V1DataElement getDataElement(int index) {
+ return legibleSections.getSectionDataElement(this.legibleSectionsIndex, index);
+ }
+
+ /** Gets all the data elements for iteration. */
+ public Iterable<V1DataElement> getDataElements() {
+ return () -> new DataElementIterator(legibleSections, legibleSectionsIndex, numDataElements);
+ }
+
+ /** Visits all the data elements with the given visitor. */
+ public void visitDataElements(V1DataElement.Visitor v) {
+ for (V1DataElement de : getDataElements()) {
+ de.visit(v);
+ }
+ }
+
+ private static final class DataElementIterator implements Iterator<V1DataElement> {
+ private final LegibleV1Sections legibleSections;
+ private final int legibleSectionsIndex;
+ private final int numDataElements;
+
+ private int position = 0;
+
+ public DataElementIterator(
+ LegibleV1Sections legibleSections, int legibleSectionsIndex, int numDataElements) {
+ this.legibleSections = legibleSections;
+ this.legibleSectionsIndex = legibleSectionsIndex;
+ this.numDataElements = numDataElements;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return position < (numDataElements - 1);
+ }
+
+ @Override
+ public V1DataElement next() {
+ return legibleSections.getSectionDataElement(legibleSectionsIndex, position++);
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/Handle.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/Handle.java
new file mode 100644
index 0000000..a200358
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/Handle.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+/**
+ * A handle to a natively-allocated object. This class should be subclassed in order to provide a
+ * type for the native object. This class does not control the lifetime of the native object. See
+ * {@link OwnedHandle} for a variant that allows Java to deallocate the native object.
+ *
+ * <p>This may be a handle to an object that has already been deallocated. In that case, any native
+ * uses of this handle should throw {@link Handle.InvalidHandleException}.
+ */
+public abstract class Handle {
+
+ /** Thrown when an invalid handle is used */
+ public static final class InvalidHandleException extends Exception {
+ public InvalidHandleException() {
+ super("The given handle is no longer valid");
+ }
+ }
+
+ protected final long handleId;
+
+ protected Handle(long handleId) {
+ this.handleId = handleId;
+ }
+
+ public long getId() {
+ return handleId;
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/IdentityKind.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/IdentityKind.java
new file mode 100644
index 0000000..9b69851
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/IdentityKind.java
@@ -0,0 +1,43 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.IntDef;
+import java.lang.annotation.Retention;
+
+/**
+ * The kind of identity that was discovered for a decrypted advertisement. Values greater than
+ * {@code 0} are legible. Values less than {@code 0} are not.
+ */
+@IntDef({
+ IdentityKind.NO_MATCHING_CREDENTIALS,
+ IdentityKind.PLAINTEXT,
+ IdentityKind.DECRYPTED,
+})
+@Retention(SOURCE)
+public @interface IdentityKind {
+ /** An encrypted identity that we do not have a credential for. */
+ public static final int NO_MATCHING_CREDENTIALS = -1;
+
+ /** A plaintext identity. */
+ public static final int PLAINTEXT = 1;
+
+ /** An encrypted identity that we have a credential for. */
+ public static final int DECRYPTED = 2;
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/LegibleV1Sections.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/LegibleV1Sections.java
new file mode 100644
index 0000000..5175ce6
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/LegibleV1Sections.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import androidx.annotation.Nullable;
+import java.lang.ref.Cleaner;
+
+/** Internal handle for a V1 deserialized advertisement. */
+public final class LegibleV1Sections extends OwnedHandle {
+
+ static {
+ System.loadLibrary(NpAdv.LIBRARY_NAME);
+ }
+
+ /**
+ * Create a LegibleV1Sections handle from the raw handle id. This will use the default cleaner
+ * form {@code NpAdv#getCleaner()}. This is expected to be called from native code.
+ */
+ /* package-visible */ LegibleV1Sections(long handleId) {
+ this(handleId, NpAdv.getCleaner());
+ }
+
+ /** Create a LegibleV1Sections handle from the raw handle id. */
+ /* package-visible */ LegibleV1Sections(long handleId, Cleaner cleaner) {
+ super(handleId, cleaner, LegibleV1Sections::deallocate);
+ }
+
+ /**
+ * Get the section at the given index.
+ *
+ * @param index The section's index in the advertisement
+ * @throws IndexOutOfBoundsException if the given index is out of range for this advertisement
+ * @return The section at that index
+ */
+ public DeserializedV1Section getSection(int index) {
+ DeserializedV1Section section = nativeGetSection(index);
+ if (section == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return section;
+ }
+
+ /**
+ * Get the data element from a specific section.
+ *
+ * @param sectionIndex The section's index in the advertisement. This only counts legible sections
+ * @param deIndex The data element's index in the section
+ * @throws IndexOutOfBoundsException if either index is out of range for this advertisement
+ * @return The data element found at {@code deIndex} in the section at {@code sectionIndex}
+ */
+ public V1DataElement getSectionDataElement(int sectionIndex, int deIndex) {
+ V1DataElement de = nativeGetSectionDataElement(sectionIndex, deIndex);
+ if (de == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return de;
+ }
+
+ @Nullable
+ private native DeserializedV1Section nativeGetSection(int index);
+
+ @Nullable
+ private native V1DataElement nativeGetSectionDataElement(int sectionIndex, int deIndex);
+
+ private static native void deallocate(long handleId);
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/NpAdv.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/NpAdv.java
new file mode 100644
index 0000000..21abb89
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/NpAdv.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import androidx.annotation.Nullable;
+import com.google.android.nearby.presence.rust.credential.CredentialBook;
+import java.lang.ref.Cleaner;
+
+/**
+ * The main entrypoint to the library.
+ *
+ * <p>On Android call {@link #setCleaner} with a {@code SystemCleaner} instance before any other
+ * method to avoid creating a new cleaner thread.
+ *
+ * <h3>Supported Features:</h3>
+ *
+ * <ul>
+ * <li>Deserialize advertisements: {@link #deserializeAdvertisement}
+ * </ul>
+ */
+public final class NpAdv {
+
+ public static final String LIBRARY_NAME = "np_java_ffi";
+
+ static {
+ System.loadLibrary(LIBRARY_NAME);
+ }
+
+ private static @Nullable Cleaner CLEANER = null;
+
+ /**
+ * Deserialize a Nearby Presence advertisement from its service data bytes.
+ *
+ * @param serviceData The service data bytes. Must have length&lt;256.
+ * @param credentialBook The credential book to use to decrypt.
+ * @return A result containing the advertisement if it was able to be deserialized.
+ */
+ public static <M extends CredentialBook.MatchedMetadata>
+ DeserializeResult deserializeAdvertisement(
+ byte[] serviceData, CredentialBook<M> credentialBook) {
+ DeserializeResult result = nativeDeserializeAdvertisement(serviceData, credentialBook.getId());
+ if (result == null) {
+ result = new DeserializeResult(DeserializeResult.Kind.UNKNOWN_ERROR);
+ }
+ return result;
+ }
+
+ /**
+ * Get the currently configured cleaner. If a cleaner is not configured, a new one will be created
+ * via the {@link Cleaner#create()} factory function.
+ */
+ public static synchronized Cleaner getCleaner() {
+ if (CLEANER == null) {
+ CLEANER = Cleaner.create();
+ }
+ return CLEANER;
+ }
+
+ /**
+ * Configure a {@link Cleaner} to be used by this library. This cleaner will be used to ensure
+ * that {@link OwnedHandle} instances are properly freed. Since each {@code Cleaner} instance
+ * requires its own thread; this can be used to share a {@code Cleaner} instance to reduce the
+ * number of threads used.
+ *
+ * <p>On Android the {@code SystemCleaner} should be provided.
+ */
+ @Nullable
+ public static synchronized Cleaner setCleaner(Cleaner cleaner) {
+ Cleaner old = CLEANER;
+ CLEANER = cleaner;
+ return old;
+ }
+
+ @Nullable
+ private static native DeserializeResult nativeDeserializeAdvertisement(
+ byte[] serviceData, long credentialBook);
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/OwnedHandle.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/OwnedHandle.java
new file mode 100644
index 0000000..c505f81
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/OwnedHandle.java
@@ -0,0 +1,129 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import androidx.annotation.Nullable;
+import java.lang.ref.Cleaner;
+
+/**
+ * A handle to natively-allocated object with lifetime control. This is a {@code Handle} that also
+ * supports deallocating the native object.
+ *
+ * <p>Users should call {@link OwnedHandle#close()} when finished with this handle to free the
+ * native resources. This can be automatically done when using try-with-resources. If neither are
+ * use the handle will still be closed when it is garbage collected.
+ */
+public abstract class OwnedHandle extends Handle implements AutoCloseable {
+
+ /**
+ * A destructor to be called when this {@link OwnedHandle} is no longer used.
+ *
+ * <p>This MUST not hold a reference to the {@link OwnedHandle} instance. Do not implement this on
+ * your subclass; however, it may be implemented by a method reference to a static method.
+ */
+ public interface Destructor {
+ void deallocate(long handleId);
+ }
+
+ /** Thrown when a new handle cannot be allocated due to lack of space */
+ public static final class NoSpaceLeftException extends RuntimeException {
+ public NoSpaceLeftException() {
+ super("No space remaining in the associated HandleMap");
+ }
+ }
+
+ private final CleanupAction cleanupAction;
+
+ /**
+ * Create a new instance and register it with the given cleaner.
+ *
+ * @param handleId The handle's id
+ * @param cleaner The cleaner thread to register with for GC cleanup
+ * @param destructor The destructor to run when this handle is closed
+ */
+ protected OwnedHandle(long handleId, Cleaner cleaner, Destructor destructor) {
+ super(handleId);
+ this.cleanupAction = new CleanupAction(handleId, destructor);
+
+ cleaner.register(this, this.cleanupAction);
+ }
+
+ /** Leak this handle. The associated native object will not be deallocated. */
+ protected final void leak() {
+ this.cleanupAction.leak();
+ }
+
+ /** Implement AutoCloseable for try-with-resources support */
+ @Override
+ public final void close() {
+ this.cleanupAction.cleanupFromCloseable();
+ }
+
+ /**
+ * A {@link Runnable} to be given to the associated {@link Cleaner} to clean up a handle. This
+ * MUST not hold a reference to the {@link OwnedHandle} that it is associated with.
+ */
+ private static final class CleanupAction implements Runnable {
+ private final long handleId;
+ private @Nullable Destructor destructor;
+ private boolean freed = false;
+
+ public CleanupAction(long handleId, Destructor destructor) {
+ this.handleId = handleId;
+ this.destructor = destructor;
+ }
+
+ /** Skip performing cleanup and leak the object instead */
+ private void leak() {
+ this.destructor = null;
+ }
+
+ /**
+ * Deallocate the handle using the given {@link Destructor}.
+ *
+ * <p>The Destructor will only be called once, and future calls to this method will return
+ * {@code false}.
+ *
+ * @return {@code true} if the destructor was called.
+ */
+ private boolean deallocate() {
+ if (this.destructor != null) {
+ this.destructor.deallocate(this.handleId);
+ this.destructor = null;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Perform the cleanup action. This is separate from {@link #run()} so that we can track if the
+ * handle was manually closed or if it was cleaned up via the {@link Cleaner}.
+ */
+ public void cleanupFromCloseable() {
+ if (!deallocate()) {
+ // FUTURE: log that OwnedHandle#close() was called multiple times.
+ }
+ }
+
+ @Override
+ public void run() {
+ if (deallocate()) {
+ // FUTURE: log that OwnedHandle#close() was not called.
+ }
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0DataElement.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0DataElement.java
new file mode 100644
index 0000000..4575f5a
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0DataElement.java
@@ -0,0 +1,114 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.IntDef;
+import java.lang.annotation.Retention;
+
+/** Base class for V0 data element types. */
+public abstract class V0DataElement {
+
+ /**
+ * A visitor interface that can be used while iterating data elements in an advertisement to avoid
+ * checking {@code instanceof} on every one.
+ */
+ public interface Visitor {
+ default void visitTxPower(TxPower txPower) {}
+
+ default void visitV0Actions(V0Actions v0Actions) {}
+ }
+
+ // All subclasses should be in this file
+ private V0DataElement() {}
+
+ /** Visit this advertisement with the given visitor. */
+ public abstract void visit(Visitor v);
+
+ /** Contains the TxPower information. See the spec for more information. */
+ public static final class TxPower extends V0DataElement {
+ private final int txPower;
+
+ public TxPower(int txPower) {
+ this.txPower = txPower;
+ }
+
+ public int getTxPower() {
+ return txPower;
+ }
+
+ public void visit(Visitor v) {
+ v.visitTxPower(this);
+ }
+ }
+
+ /** Marker annotation/enum for V0 action values. */
+ @IntDef({
+ V0ActionType.CROSS_DEV_SDK,
+ V0ActionType.CALL_TRANSFER,
+ V0ActionType.ACTIVE_UNLOCK,
+ V0ActionType.NEARBY_SHARE,
+ V0ActionType.INSTANT_TETHERING,
+ V0ActionType.PHONE_HUB,
+ })
+ @Retention(SOURCE)
+ public @interface V0ActionType {
+ // NOTE: Copied from `np_ffi_core::v0::BooleanActionType`.
+ public static final int CROSS_DEV_SDK = 1;
+ public static final int CALL_TRANSFER = 4;
+ public static final int ACTIVE_UNLOCK = 8;
+ public static final int NEARBY_SHARE = 9;
+ public static final int INSTANT_TETHERING = 10;
+ public static final int PHONE_HUB = 11;
+ }
+
+ /** The Actions data element. See the spec for more information. */
+ public static final class V0Actions extends V0DataElement {
+ static {
+ System.loadLibrary(NpAdv.LIBRARY_NAME);
+ }
+
+ private final @IdentityKind int identityKind;
+ private final int actionBits;
+
+ public V0Actions(@IdentityKind int identityKind, int actionBits) {
+ this.identityKind = identityKind;
+ this.actionBits = actionBits;
+ }
+
+ @IdentityKind
+ public int getIdentityKind() {
+ return identityKind;
+ }
+
+ public int getActionBits() {
+ return actionBits;
+ }
+
+ /** Checks if this Actions DE contains the given action. */
+ public boolean hasAction(@V0ActionType int action) {
+ return nativeHasAction(identityKind, actionBits, action);
+ }
+
+ public void visit(Visitor v) {
+ v.visitV0Actions(this);
+ }
+
+ private static native boolean nativeHasAction(int identityKind, int actionBits, int action);
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0Payload.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0Payload.java
new file mode 100644
index 0000000..722f37c
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V0Payload.java
@@ -0,0 +1,64 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import androidx.annotation.Nullable;
+import java.lang.ref.Cleaner;
+
+/**
+ * Internal handle type for deserialized V0 advertisements. It provides access to the native data
+ * and allows that data to be deallocated.
+ */
+public final class V0Payload extends OwnedHandle {
+
+ static {
+ System.loadLibrary(NpAdv.LIBRARY_NAME);
+ }
+
+ /**
+ * Create a V0Payload handle from the raw handle id. This will use the default cleaner form {@code
+ * NpAdv#getCleaner()}. This is expected to be called from native code.
+ */
+ /* package-visible */ V0Payload(long handleId) {
+ this(handleId, NpAdv.getCleaner());
+ }
+
+ /** Create a V0Payload handle from the raw handle id. */
+ /* package-visible */ V0Payload(long handleId, Cleaner cleaner) {
+ super(handleId, cleaner, V0Payload::deallocate);
+ }
+
+ /**
+ * Get the data element at the given index.
+ *
+ * @param index The data element's index in the advertisement
+ * @throws IndexOutOfBoundsException if the given index is out of range for this advertisement
+ * @return The data element at that index
+ */
+ public V0DataElement getDataElement(int index) {
+ V0DataElement de = nativeGetDataElement(this.handleId, index);
+ if (de == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return de;
+ }
+
+ @Nullable
+ private static native V0DataElement nativeGetDataElement(long handleId, int index);
+
+ private static native void deallocate(long handleId);
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V1DataElement.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V1DataElement.java
new file mode 100644
index 0000000..b52c7bb
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/V1DataElement.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import java.util.Arrays;
+
+/** Base class for V1 data element types. */
+public abstract class V1DataElement {
+
+ /**
+ * A visitor interface that can be used while iterating data elements in an advertisement to avoid
+ * checking {@code instanceof} on every one.
+ */
+ public interface Visitor {
+ void visitGeneric(Generic generic);
+ }
+
+ // All subclasses should be in this file
+ private V1DataElement() {}
+
+ /** Visit this advertisement with the given visitor. */
+ public abstract void visit(Visitor v);
+
+ /**
+ * A generic data element. This is a data element which has a type that is not known by this
+ * library (e.g. a vendor-specific data element).
+ */
+ public static final class Generic extends V1DataElement {
+ private final long type;
+ private final byte[] data;
+
+ public Generic(long type, byte[] data) {
+ this.type = type;
+ this.data = Arrays.copyOf(data, data.length);
+ }
+
+ public long getType() {
+ return type;
+ }
+
+ public byte[] getData() {
+ return Arrays.copyOf(data, data.length);
+ }
+
+ public void visit(Visitor v) {
+ v.visitGeneric(this);
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialBook.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialBook.java
new file mode 100644
index 0000000..cdcc50b
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialBook.java
@@ -0,0 +1,140 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import com.google.android.nearby.presence.rust.NpAdv;
+import com.google.android.nearby.presence.rust.OwnedHandle;
+import java.lang.ref.Cleaner;
+import java.util.ArrayList;
+
+public final class CredentialBook<M extends CredentialBook.MatchedMetadata> extends OwnedHandle {
+
+ static {
+ System.loadLibrary(NpAdv.LIBRARY_NAME);
+ }
+
+ /** Metadata that is associated with a Credential. */
+ public interface MatchedMetadata {
+ /**
+ * Get the bytes for encrypted metadata. This byte array may be empty if there is no encrypted
+ * metadata.
+ */
+ byte[] getEncryptedMetadataBytes();
+ }
+
+ /** {@link MatchedMetadata} implementation for cases where there is no associated metadata. */
+ public static class NoMetadata implements MatchedMetadata {
+
+ /** An instance to avoid needing additional instances of this class. */
+ public static final NoMetadata INSTANCE = new NoMetadata();
+
+ @Override
+ public byte[] getEncryptedMetadataBytes() {
+ return new byte[0];
+ }
+ }
+
+ /** Thrown when a cryptographic key is given and those key bytes are not valid. */
+ public static final class InvalidPublicKeyException extends RuntimeException {
+ public InvalidPublicKeyException() {
+ super(
+ "The provided public key bytes do not actually represent a valid \"edwards y\" format or"
+ + " that said compressed point is not actually a point on the curve.");
+ }
+ }
+
+ /** Builder for {@code CredentialBook} */
+ public static final class Builder<M extends MatchedMetadata> {
+ private Cleaner cleaner;
+ private CredentialSlab slab;
+
+ // Each credential should be given an id of its metadata index so that this array is an
+ // id-to-metadata map.
+ private ArrayList<M> matchDataList;
+
+ /**
+ * Create a builder instance. The {@link CredentialBook#builder()} factory method can be used to
+ * create a {@code Builder} with the default {@link Cleaner}. This can fail if there isn't room
+ * to create a new {@code CredentialSlab} handle.
+ *
+ * @param cleaner The cleaner instance to use for the {@link CredentialSlab} and {@code
+ * CredentialBook}.
+ */
+ public Builder(Cleaner cleaner) {
+ this.cleaner = cleaner;
+ this.slab = new CredentialSlab(cleaner);
+ this.matchDataList = new ArrayList<>();
+ }
+
+ /** Add a {@link V0DiscoveryCredential} to the book. */
+ public Builder<M> addDiscoveryCredential(V0DiscoveryCredential credential, M matchData) {
+ int credIdx = matchDataList.size();
+ matchDataList.add(matchData);
+ slab.addDiscoveryCredential(credential, credIdx, matchData.getEncryptedMetadataBytes());
+ return this;
+ }
+
+ /**
+ * Add a {@link V1DiscoveryCredential} to the book. May throw {@link
+ * CredentialBook.InvalidPublicKeyException} if the key inside {@code credential} is improperly
+ * formatted.
+ */
+ public Builder<M> addDiscoveryCredential(V1DiscoveryCredential credential, M matchData) {
+ int credIdx = matchDataList.size();
+ matchDataList.add(matchData);
+ slab.addDiscoveryCredential(credential, credIdx, matchData.getEncryptedMetadataBytes());
+ return this;
+ }
+
+ /**
+ * Create the {@code CredentialBook}. This can fail if there isn't room to create a new {@code
+ * CredentialBook} handle.
+ */
+ public CredentialBook<M> build() {
+ return new CredentialBook(slab, matchDataList, cleaner);
+ }
+ }
+
+ /** Create a credential book builder with the default cleaner from {@link NpAdv#getCleaner()}. */
+ public static <M extends MatchedMetadata> Builder<M> builder() {
+ return new Builder<M>(NpAdv.getCleaner());
+ }
+
+ /**
+ * Create an empty credential book. This is useful for when only plaintext advertisements are
+ * being deserialized.
+ */
+ public static CredentialBook<NoMetadata> empty() {
+ return new Builder<NoMetadata>(NpAdv.getCleaner()).build();
+ }
+
+ private final ArrayList<M> matchData;
+
+ /**
+ * Create a new credential book. This always consumes the slab handle. This should only be called
+ * from {@code Builder}. {@code matchData} is formatted so that each credential is given an id of
+ * the index of its metadata in {@code matchData}.
+ */
+ private CredentialBook(CredentialSlab slab, ArrayList<M> matchData, Cleaner cleaner) {
+ super(allocate(slab.move()), cleaner, CredentialBook::deallocate);
+ this.matchData = matchData;
+ }
+
+ private static native long allocate(long slabHandleId);
+
+ private static native void deallocate(long handleId);
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialSlab.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialSlab.java
new file mode 100644
index 0000000..35fc610
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/CredentialSlab.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import com.google.android.nearby.presence.rust.NpAdv;
+import com.google.android.nearby.presence.rust.OwnedHandle;
+import java.lang.ref.Cleaner;
+
+/**
+ * A {@code CredentialSlab} handle that is used to build the native-side structures for a {@link
+ * CredentialBook}. Clients should use {@link CredentialSlab.Builder} instead of this class.
+ */
+final class CredentialSlab extends OwnedHandle {
+ static {
+ System.loadLibrary(NpAdv.LIBRARY_NAME);
+ }
+
+ /** Create a new {@code CredentialSlab} with the given {@code cleaner}. */
+ public CredentialSlab(Cleaner cleaner) {
+ super(allocate(), cleaner, CredentialSlab::deallocate);
+ }
+
+ /** Add a V0 discovery credential to this slab. */
+ public void addDiscoveryCredential(
+ V0DiscoveryCredential credential, int credId, byte[] encryptedMetadataBytes) {
+ nativeAddV0DiscoveryCredential(handleId, credential, credId, encryptedMetadataBytes);
+ }
+
+ /**
+ * Add a V1 discovery credential to this slab. May throw {@link
+ * CredentialBook.InvalidKeyException} if the key inside {@code credential} is improperly
+ * formatted.
+ */
+ public void addDiscoveryCredential(
+ V1DiscoveryCredential credential, int credId, byte[] encryptedMetadataBytes) {
+ nativeAddV1DiscoveryCredential(handleId, credential, credId, encryptedMetadataBytes);
+ }
+
+ /**
+ * Mark this slab handle as moved and return the handle id. This will leak the handle. This should
+ * be done when the handle is moved to the Rust side to avoid freeing it early.
+ */
+ public long move() {
+ leak();
+ return handleId;
+ }
+
+ private static native long allocate();
+
+ private static native boolean nativeAddV0DiscoveryCredential(
+ long handleId, V0DiscoveryCredential cred, int credId, byte[] encryptedMetadataBytes);
+
+ private static native boolean nativeAddV1DiscoveryCredential(
+ long handleId, V1DiscoveryCredential cred, int credId, byte[] encryptedMetadataBytes);
+
+ private static native void deallocate(long handleId);
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/Utils.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/Utils.java
new file mode 100644
index 0000000..c38bbcf
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/Utils.java
@@ -0,0 +1,35 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import java.util.Arrays;
+
+/** Util functions used by multiple files. */
+final class Utils {
+
+ /**
+ * Create a copy of a 32-byte array of key data. Will throw {@code IllegalArgumentException} if
+ * the array is not exactly 32 bytes.
+ */
+ public static byte[] copyKeyBytes(byte[] key) {
+ if (key.length != 32) {
+ throw new IllegalArgumentException(
+ String.format("Expected key length to be 32 bytes, got %s bytes", key.length));
+ }
+ return Arrays.copyOf(key, key.length);
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V0DiscoveryCredential.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V0DiscoveryCredential.java
new file mode 100644
index 0000000..be8734b
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V0DiscoveryCredential.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import static com.google.android.nearby.presence.rust.credential.Utils.copyKeyBytes;
+
+/** A V0 discovery credential in a format that is ready to be passed to native code. */
+public final class V0DiscoveryCredential {
+ private final byte[] keySeed;
+ private final byte[] identityTokenHmac;
+
+ /** Create the credential. Each array is exactly 32 bytes. */
+ public V0DiscoveryCredential(byte[] keySeed, byte[] identityTokenHmac) {
+ this.keySeed = copyKeyBytes(keySeed);
+ this.identityTokenHmac = copyKeyBytes(identityTokenHmac);
+ }
+}
diff --git a/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V1DiscoveryCredential.java b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V1DiscoveryCredential.java
new file mode 100644
index 0000000..c2afefa
--- /dev/null
+++ b/nearby/presence/np_java_ffi/java/com/google/android/nearby/presence/rust/credential/V1DiscoveryCredential.java
@@ -0,0 +1,44 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import static com.google.android.nearby.presence.rust.credential.Utils.copyKeyBytes;
+
+/** A V1 discovery credential in a format that is ready to be passed to native code. */
+public final class V1DiscoveryCredential {
+ private final byte[] keySeed;
+ private final byte[] expectedMicShortSaltIdentityTokenHmac;
+ private final byte[] expectedMicExtendedSaltIdentityTokenHmac;
+ private final byte[] expectedSignatureIdentityTokenHmac;
+ private final byte[] pubKey;
+
+ /** Create the credential. Each array is exactly 32 bytes. */
+ public V1DiscoveryCredential(
+ byte[] keySeed,
+ byte[] expectedMicShortSaltIdentityTokenHmac,
+ byte[] expectedMicExtendedSaltIdentityTokenHmac,
+ byte[] expectedSignatureIdentityTokenHmac,
+ byte[] pubKey) {
+ this.keySeed = copyKeyBytes(keySeed);
+ this.expectedMicShortSaltIdentityTokenHmac =
+ copyKeyBytes(expectedMicShortSaltIdentityTokenHmac);
+ this.expectedMicExtendedSaltIdentityTokenHmac =
+ copyKeyBytes(expectedMicExtendedSaltIdentityTokenHmac);
+ this.expectedSignatureIdentityTokenHmac = copyKeyBytes(expectedSignatureIdentityTokenHmac);
+ this.pubKey = copyKeyBytes(pubKey);
+ }
+}
diff --git a/nearby/presence/np_java_ffi/settings.gradle.kts b/nearby/presence/np_java_ffi/settings.gradle.kts
new file mode 100644
index 0000000..0c9915a
--- /dev/null
+++ b/nearby/presence/np_java_ffi/settings.gradle.kts
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+rootProject.name = "np-java-ffi"
diff --git a/nearby/presence/np_java_ffi/src/class.rs b/nearby/presence/np_java_ffi/src/class.rs
new file mode 100644
index 0000000..9c07137
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class.rs
@@ -0,0 +1,62 @@
+// 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.
+
+//! Rust wrappers for Java classes.
+//!
+//! The pattern being used here it to create a new wrapper type for each Java class being used by
+//! this library. Each wrapper type will implement the required accessors for its members so that
+//! JNI code using a member can be easily found in case that member is changed. Native methods will
+//! also be implemented along side the wrapper of the class they are implementing.
+//!
+//! This library is primarily meant to be used from Java. The Java entrypoint to this library is
+//! `class NpAdv`.
+
+use jni::JNIEnv;
+
+/// Trait to allow Java exceptions to be thrown from rust Errors
+pub trait ToJavaException {
+ /// Convert this error to a Java exception and throw it.
+ fn throw_java_exception<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()>;
+}
+
+mod credential_book;
+mod credential_slab;
+mod deserialization_exception;
+mod deserialize_result;
+mod deserialized_v0_advertisement;
+mod deserialized_v1_advertisement;
+mod deserialized_v1_section;
+mod handle;
+mod identity_kind;
+mod legible_v1_sections;
+mod np_adv;
+mod owned_handle;
+mod v0_discovery_credential;
+mod v0_payload;
+mod v1_discovery_credential;
+
+pub mod v0_data_element;
+pub mod v1_data_element;
+
+pub use deserialization_exception::{InvalidFormatException, InvalidHeaderException};
+pub use deserialize_result::{DeserializeResult, DeserializeResultError};
+pub use deserialized_v0_advertisement::{DeserializedV0Advertisement, V0AdvertisementError};
+pub use deserialized_v1_advertisement::DeserializedV1Advertisement;
+pub use deserialized_v1_section::DeserializedV1Section;
+pub use handle::InvalidHandleException;
+pub use identity_kind::IdentityKind;
+pub use legible_v1_sections::LegibleV1Sections;
+pub use owned_handle::NoSpaceLeftException;
+pub use v0_discovery_credential::V0DiscoveryCredential;
+pub use v1_discovery_credential::V1DiscoveryCredential;
diff --git a/nearby/presence/np_java_ffi/src/class/credential_book.rs b/nearby/presence/np_java_ffi/src/class/credential_book.rs
new file mode 100644
index 0000000..ea371da
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/credential_book.rs
@@ -0,0 +1,65 @@
+// 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.
+
+use jni::{objects::JClass, sys::jlong, JNIEnv};
+
+use crate::class::{InvalidHandleException, NoSpaceLeftException};
+use handle_map::{Handle, HandleLike};
+use np_ffi_core::credentials::{
+ create_credential_book_from_slab, deallocate_credential_book, CreateCredentialBookResult,
+ CredentialBook, CredentialSlab,
+};
+use pourover::jni_method;
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialBook",
+ method_name = "allocate"
+)]
+extern "system" fn allocate_book<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ slab_handle_id: jlong,
+) -> jlong {
+ let slab = CredentialSlab::from_handle(Handle::from_id(slab_handle_id as u64));
+
+ match create_credential_book_from_slab(slab) {
+ CreateCredentialBookResult::Success(handle) => handle.get_as_handle().get_id() as jlong,
+ CreateCredentialBookResult::InvalidSlabHandle => {
+ let _ = InvalidHandleException::throw_new(&mut env);
+ 0
+ }
+ CreateCredentialBookResult::NoSpaceLeft => {
+ // Make sure slab is consumed.
+ let _ = slab.deallocate();
+ let _ = NoSpaceLeftException::throw_new(&mut env);
+ 0
+ }
+ }
+}
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialBook",
+ method_name = "deallocate"
+)]
+extern "system" fn deallocate_book<'local>(
+ _env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+) {
+ // Swallow errors here since there's nothing meaningful to do.
+ let _ =
+ deallocate_credential_book(CredentialBook::from_handle(Handle::from_id(handle_id as u64)));
+}
diff --git a/nearby/presence/np_java_ffi/src/class/credential_slab.rs b/nearby/presence/np_java_ffi/src/class/credential_slab.rs
new file mode 100644
index 0000000..7e8f37d
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/credential_slab.rs
@@ -0,0 +1,160 @@
+// 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.
+
+use jni::{
+ objects::{JByteArray, JClass, JObject, JThrowable},
+ sys::{jboolean, jint, jlong, JNI_FALSE, JNI_TRUE},
+ JNIEnv,
+};
+
+use crate::class::{
+ InvalidHandleException, NoSpaceLeftException, V0DiscoveryCredential, V1DiscoveryCredential,
+};
+use handle_map::Handle;
+use np_ffi_core::credentials::{
+ create_credential_slab, deallocate_credential_slab, AddV0CredentialToSlabResult,
+ AddV1CredentialToSlabResult, CreateCredentialSlabResult, CredentialSlab, MatchedCredential,
+};
+use pourover::{desc::ClassDesc, jni_method};
+
+static INVALID_KEY_EXCEPTION_CLASS: ClassDesc = ClassDesc::new(
+ "com/google/android/nearby/presence/rust/credential/CredentialBook$InvalidPublicKeyException",
+);
+
+/// Rust representation of `class InvalidPublicKeyException`.
+#[repr(transparent)]
+pub struct InvalidPublicKeyException<Obj>(pub Obj);
+
+impl<'local> InvalidPublicKeyException<JObject<'local>> {
+ /// Create a new instance.
+ pub fn construct(env: &mut JNIEnv<'local>) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &INVALID_KEY_EXCEPTION_CLASS, "()V").map(Self)
+ }
+
+ /// Create a new instance and throw it.
+ pub fn throw_new(env: &mut JNIEnv<'local>) -> jni::errors::Result<()> {
+ Self::construct(env)?.throw(env)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> InvalidPublicKeyException<Obj> {
+ /// Throw this exception.
+ pub fn throw<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ env.throw(<&JThrowable>::from(self.0.as_ref()))
+ }
+}
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialSlab",
+ method_name = "allocate"
+)]
+extern "system" fn allocate_slab<'local>(mut env: JNIEnv<'local>, _cls: JClass<'local>) -> jlong {
+ let CreateCredentialSlabResult::Success(slab) = create_credential_slab() else {
+ let _ = NoSpaceLeftException::throw_new(&mut env);
+ return 0;
+ };
+
+ slab.get_as_handle().get_id() as jlong
+}
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialSlab"
+)]
+extern "system" fn nativeAddV0DiscoveryCredential<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+ credential: V0DiscoveryCredential<JObject<'local>>,
+ cred_id: jint,
+ encrypted_metadata_bytes: JByteArray<'local>,
+) -> jboolean {
+ let mut add_cred = move || {
+ let slab = CredentialSlab::from_handle(Handle::from_id(handle_id as u64));
+
+ let core_cred = credential.get_as_core(&mut env)?;
+ let match_data = MatchedCredential::from_arc_bytes(
+ cred_id as u32,
+ env.convert_byte_array(&encrypted_metadata_bytes)?.into(),
+ );
+
+ Ok::<_, jni::errors::Error>(match slab.add_v0(core_cred, match_data) {
+ AddV0CredentialToSlabResult::Success => JNI_TRUE,
+ AddV0CredentialToSlabResult::InvalidHandle => {
+ InvalidHandleException::throw_new(&mut env)?;
+ JNI_FALSE
+ }
+ })
+ };
+
+ match add_cred() {
+ Ok(ret) => ret,
+ Err(_) => JNI_FALSE,
+ }
+}
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialSlab"
+)]
+extern "system" fn nativeAddV1DiscoveryCredential<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+ credential: V1DiscoveryCredential<JObject<'local>>,
+ cred_id: jint,
+ encrypted_metadata_bytes: JByteArray<'local>,
+) -> jboolean {
+ let mut add_cred = move || {
+ let slab = CredentialSlab::from_handle(Handle::from_id(handle_id as u64));
+
+ let core_cred = credential.get_as_core(&mut env)?;
+ let match_data = MatchedCredential::from_arc_bytes(
+ cred_id as u32,
+ env.convert_byte_array(&encrypted_metadata_bytes)?.into(),
+ );
+
+ Ok::<_, jni::errors::Error>(match slab.add_v1(core_cred, match_data) {
+ AddV1CredentialToSlabResult::Success => JNI_TRUE,
+ AddV1CredentialToSlabResult::InvalidHandle => {
+ InvalidHandleException::throw_new(&mut env)?;
+ JNI_FALSE
+ }
+ AddV1CredentialToSlabResult::InvalidPublicKeyBytes => {
+ InvalidPublicKeyException::throw_new(&mut env)?;
+ JNI_FALSE
+ }
+ })
+ };
+
+ match add_cred() {
+ Ok(ret) => ret,
+ Err(_) => JNI_FALSE,
+ }
+}
+
+#[jni_method(
+ package = "com.google.android.nearby.presence.rust.credential",
+ class = "CredentialSlab",
+ method_name = "deallocate"
+)]
+extern "system" fn deallocate_slab<'local>(
+ _env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+) {
+ let slab = CredentialSlab::from_handle(Handle::from_id(handle_id as u64));
+ let _ = deallocate_credential_slab(slab);
+}
diff --git a/nearby/presence/np_java_ffi/src/class/deserialization_exception.rs b/nearby/presence/np_java_ffi/src/class/deserialization_exception.rs
new file mode 100644
index 0000000..a48c515
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/deserialization_exception.rs
@@ -0,0 +1,86 @@
+// 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.
+
+use jni::{
+ objects::{JObject, JThrowable},
+ JNIEnv,
+};
+use np_adv::AdvDeserializationError;
+use pourover::desc::ClassDesc;
+
+static INVALID_HEADER_CLASS: ClassDesc = ClassDesc::new(
+ "com/google/android/nearby/presence/rust/DeserializationException$InvalidHeaderException",
+);
+
+/// Rust representation of `class DeserializationException.InvalidHeaderException`.
+#[repr(transparent)]
+pub struct InvalidHeaderException<Obj>(pub Obj);
+
+impl<'local> InvalidHeaderException<JObject<'local>> {
+ /// Create a new instance.
+ pub fn construct(env: &mut JNIEnv<'local>) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &INVALID_HEADER_CLASS, "()V").map(Self)
+ }
+
+ /// Create a new instance and throw it.
+ pub fn throw_new(env: &mut JNIEnv<'local>) -> jni::errors::Result<()> {
+ Self::construct(env)?.throw(env)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> InvalidHeaderException<Obj> {
+ /// Throw this exception.
+ pub fn throw<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ env.throw(<&JThrowable>::from(self.0.as_ref()))
+ }
+}
+
+static INVALID_FORMAT_CLASS: ClassDesc = ClassDesc::new(
+ "com/google/android/nearby/presence/rust/DeserializationException$InvalidFormatException",
+);
+
+/// Rust representation of `class DeserializationException.InvalidFormatException`.
+#[repr(transparent)]
+pub struct InvalidFormatException<Obj>(pub Obj);
+
+impl<'local> InvalidFormatException<JObject<'local>> {
+ /// Create a new instance.
+ pub fn construct(env: &mut JNIEnv<'local>) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &INVALID_FORMAT_CLASS, "()V").map(Self)
+ }
+
+ /// Create a new instance and throw it.
+ pub fn throw_new(env: &mut JNIEnv<'local>) -> jni::errors::Result<()> {
+ Self::construct(env)?.throw(env)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> InvalidFormatException<Obj> {
+ /// Throw this exception.
+ pub fn throw<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ env.throw(<&JThrowable>::from(self.0.as_ref()))
+ }
+}
+
+/// Allow AdvDeserializationError to be thrown as a Java exception.
+impl super::ToJavaException for AdvDeserializationError {
+ fn throw_java_exception<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ match *self {
+ AdvDeserializationError::VersionHeaderParseError => {
+ InvalidHeaderException::throw_new(env)
+ }
+ AdvDeserializationError::ParseError { .. } => InvalidFormatException::throw_new(env),
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/deserialize_result.rs b/nearby/presence/np_java_ffi/src/class/deserialize_result.rs
new file mode 100644
index 0000000..a38df0f
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/deserialize_result.rs
@@ -0,0 +1,103 @@
+// 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.
+
+use jni::{
+ objects::JObject,
+ signature::{JavaType, Primitive},
+ sys::jint,
+ JNIEnv,
+};
+use pourover::desc::{ClassDesc, StaticFieldDesc};
+
+use crate::class::{DeserializedV0Advertisement, DeserializedV1Advertisement};
+
+static DESERIALIZE_RESULT_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/DeserializeResult");
+
+/// Rust representation of `class DeserializeResult`.
+#[repr(transparent)]
+pub struct DeserializeResult<Obj>(pub Obj);
+
+impl<'local> DeserializeResult<JObject<'local>> {
+ /// Create a result representing the given error.
+ pub fn construct_from_error(
+ env: &mut JNIEnv<'local>,
+ error: DeserializeResultError,
+ ) -> jni::errors::Result<Self> {
+ let error = error.lookup_java_value(env)?;
+ pourover::call_constructor!(env, &DESERIALIZE_RESULT_CLASS, "(I)V", error).map(Self)
+ }
+
+ /// Create a result containing the given advertisement.
+ pub fn from_v0_advertisement(
+ env: &mut JNIEnv<'local>,
+ adv: DeserializedV0Advertisement<impl AsRef<JObject<'local>>>,
+ ) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(
+ env,
+ &DESERIALIZE_RESULT_CLASS,
+ "(Lcom/google/android/nearby/presence/rust/DeserializedV0Advertisement;)V",
+ adv.as_obj()
+ )
+ .map(Self)
+ }
+
+ /// Create a result containing the given advertisement.
+ pub fn from_v1_advertisement(
+ env: &mut JNIEnv<'local>,
+ adv: DeserializedV1Advertisement<impl AsRef<JObject<'local>>>,
+ ) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(
+ env,
+ &DESERIALIZE_RESULT_CLASS,
+ "(Lcom/google/android/nearby/presence/rust/DeserializedV1Advertisement;)V",
+ adv.as_obj()
+ )
+ .map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> DeserializeResult<Obj> {
+ /// Get a reference to the inner `jni` crate [`JObject`].
+ pub fn as_obj(&self) -> &JObject<'local> {
+ self.0.as_ref()
+ }
+}
+
+static DESERIALIZE_RESULT_KIND_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/DeserializeResult$Kind");
+
+/// An error that occurs during deserialization
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum DeserializeResultError {
+ /// An unspecified error has occurred.
+ UnknownError,
+}
+
+impl DeserializeResultError {
+ /// Fetch the Java `@IntDef` value for this error.
+ fn lookup_java_value(&self, env: &mut JNIEnv<'_>) -> jni::errors::Result<jint> {
+ static UNKNOWN_ERROR_STATIC_FIELD: StaticFieldDesc =
+ DESERIALIZE_RESULT_KIND_CLASS.static_field("UNKNOWN_ERROR", "I");
+ match self {
+ DeserializeResultError::UnknownError => env
+ .get_static_field_unchecked(
+ UNKNOWN_ERROR_STATIC_FIELD.cls(),
+ &UNKNOWN_ERROR_STATIC_FIELD,
+ JavaType::Primitive(Primitive::Int),
+ )
+ .and_then(|ret| ret.i()),
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/deserialized_v0_advertisement.rs b/nearby/presence/np_java_ffi/src/class/deserialized_v0_advertisement.rs
new file mode 100644
index 0000000..1d91ae9
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/deserialized_v0_advertisement.rs
@@ -0,0 +1,79 @@
+// 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.
+
+use jni::{
+ objects::JObject,
+ sys::{jint, jlong},
+ JNIEnv,
+};
+use np_ffi_core::deserialize::v0::{DeserializedV0IdentityKind, V0Payload};
+use pourover::desc::ClassDesc;
+
+use crate::class::IdentityKind;
+
+static DESERIALIZED_V0_ADVERTISEMENT_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/DeserializedV0Advertisement");
+
+/// Rust representation of `class DeserializedV0Advertisement`.
+#[repr(transparent)]
+pub struct DeserializedV0Advertisement<Obj>(pub Obj);
+
+impl<'local> DeserializedV0Advertisement<JObject<'local>> {
+ /// Create an illegible advertisment with the given error.
+ pub fn construct_from_error(
+ env: &mut JNIEnv<'local>,
+ error: V0AdvertisementError,
+ ) -> jni::errors::Result<Self> {
+ let error = IdentityKind::error_for_v0(env, error)?;
+
+ pourover::call_constructor!(env, &DESERIALIZED_V0_ADVERTISEMENT_CLASS, "(I)V", error)
+ .map(Self)
+ }
+
+ /// Create a legible advertisment.
+ pub fn construct(
+ env: &mut JNIEnv<'local>,
+ num_des: u8,
+ v0_payload: V0Payload,
+ identity: DeserializedV0IdentityKind,
+ ) -> jni::errors::Result<Self> {
+ let num_des = jint::from(num_des);
+ let payload_handle = v0_payload.get_as_handle().get_id() as jlong;
+ let identity = IdentityKind::value_for_v0(env, identity)?;
+
+ pourover::call_constructor!(
+ env,
+ &DESERIALIZED_V0_ADVERTISEMENT_CLASS,
+ "(IJI)V",
+ num_des,
+ payload_handle,
+ identity
+ )
+ .map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> DeserializedV0Advertisement<Obj> {
+ /// Get a reference to the inner `jni` crate [`JObject`].
+ pub fn as_obj(&self) -> &JObject<'local> {
+ self.0.as_ref()
+ }
+}
+
+/// A reason for an advertisment being illegible
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum V0AdvertisementError {
+ /// There is no matching credential in the credential book.
+ NoMatchingCredentials,
+}
diff --git a/nearby/presence/np_java_ffi/src/class/deserialized_v1_advertisement.rs b/nearby/presence/np_java_ffi/src/class/deserialized_v1_advertisement.rs
new file mode 100644
index 0000000..e537052
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/deserialized_v1_advertisement.rs
@@ -0,0 +1,50 @@
+// 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.
+
+use jni::{objects::JObject, sys::jint, JNIEnv};
+use pourover::desc::ClassDesc;
+
+static DESERIALIZED_V1_ADVERTISEMENT_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/DeserializedV1Advertisement");
+
+/// Rust representation of `class DeserializedV1Advertisement`.
+#[repr(transparent)]
+pub struct DeserializedV1Advertisement<Obj>(pub Obj);
+
+impl<'local> DeserializedV1Advertisement<JObject<'local>> {
+ /// Create a new advertisement.
+ pub fn construct(
+ env: &mut JNIEnv<'local>,
+ num_legible_sections: jint,
+ num_undecryptable_sections: jint,
+ legible_sections: super::LegibleV1Sections<impl AsRef<JObject<'local>>>,
+ ) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(
+ env,
+ &DESERIALIZED_V1_ADVERTISEMENT_CLASS,
+ "(IILcom/google/android/nearby/presence/rust/LegibleV1Sections;)V",
+ num_legible_sections,
+ num_undecryptable_sections,
+ legible_sections.as_obj()
+ )
+ .map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> DeserializedV1Advertisement<Obj> {
+ /// Get a reference to the inner `jni` crate [`JObject`].
+ pub fn as_obj(&self) -> &JObject<'local> {
+ self.0.as_ref()
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/deserialized_v1_section.rs b/nearby/presence/np_java_ffi/src/class/deserialized_v1_section.rs
new file mode 100644
index 0000000..b3f6dba
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/deserialized_v1_section.rs
@@ -0,0 +1,50 @@
+// 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.
+
+use jni::{objects::JObject, sys::jint, JNIEnv};
+use np_ffi_core::deserialize::v1::DeserializedV1IdentityKind;
+use pourover::desc::ClassDesc;
+
+use crate::class::{IdentityKind, LegibleV1Sections};
+
+static DESERIALIZED_V1_SECTION_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/DeserializedV1Section");
+
+/// Rust representation of `class DeserializedV1Section`.
+#[repr(transparent)]
+pub struct DeserializedV1Section<Obj>(pub Obj);
+
+impl<'local> DeserializedV1Section<JObject<'local>> {
+ /// Create a new deserialized section
+ pub fn construct<'a>(
+ env: &mut JNIEnv<'local>,
+ legible_sections_handle: LegibleV1Sections<impl AsRef<JObject<'a>>>,
+ legible_section_index: u8,
+ num_des: u8,
+ identity_kind: DeserializedV1IdentityKind,
+ ) -> jni::errors::Result<Self> {
+ let identity = IdentityKind::value_for_v1(env, identity_kind)?;
+
+ pourover::call_constructor!(
+ env,
+ &DESERIALIZED_V1_SECTION_CLASS,
+ "(Lcom/google/android/nearby/presence/rust/LegibleV1Sections;III)V",
+ legible_sections_handle.as_obj(),
+ jint::from(legible_section_index),
+ jint::from(num_des),
+ identity
+ )
+ .map(Self)
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/handle.rs b/nearby/presence/np_java_ffi/src/class/handle.rs
new file mode 100644
index 0000000..7505507
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/handle.rs
@@ -0,0 +1,45 @@
+// 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.
+
+use jni::{
+ objects::{JObject, JThrowable},
+ JNIEnv,
+};
+use pourover::desc::ClassDesc;
+
+static INVALID_HANDLE_EXCEPTION_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/Handle$InvalidHandleException");
+
+/// Rust representation of `class InvalidHandleException`.
+#[repr(transparent)]
+pub struct InvalidHandleException<Obj>(pub Obj);
+
+impl<'local> InvalidHandleException<JObject<'local>> {
+ /// Create a new instance.
+ pub fn construct(env: &mut JNIEnv<'local>) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &INVALID_HANDLE_EXCEPTION_CLASS, "()V").map(Self)
+ }
+
+ /// Create a new instance and throw it.
+ pub fn throw_new(env: &mut JNIEnv<'local>) -> jni::errors::Result<()> {
+ Self::construct(env)?.throw(env)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> InvalidHandleException<Obj> {
+ /// Throw this exception.
+ pub fn throw<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ env.throw(<&JThrowable>::from(self.0.as_ref()))
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/identity_kind.rs b/nearby/presence/np_java_ffi/src/class/identity_kind.rs
new file mode 100644
index 0000000..8fce071
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/identity_kind.rs
@@ -0,0 +1,117 @@
+// 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.
+
+use jni::{
+ signature::{JavaType, Primitive},
+ sys::jint,
+ JNIEnv,
+};
+use np_ffi_core::deserialize::{v0::DeserializedV0IdentityKind, v1::DeserializedV1IdentityKind};
+use pourover::desc::{ClassDesc, StaticFieldDesc};
+use std::sync::RwLock;
+
+use crate::class::V0AdvertisementError;
+
+static IDENTITY_KIND_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/IdentityKind");
+
+/// Rust representation of `@IdentityKind`. These are `jints` on the Java side, so this type can't
+/// be instantiated.
+pub enum IdentityKind {}
+
+impl IdentityKind {
+ /// Fetch the `NO_MATCHING_CREDENTIALS` constant
+ pub fn no_matching_credentials<'local>(env: &mut JNIEnv<'local>) -> jni::errors::Result<jint> {
+ static NO_MATCHING_CREDENTIALS: StaticFieldDesc =
+ IDENTITY_KIND_CLASS.static_field("NO_MATCHING_CREDENTIALS", "I");
+ static VALUE: RwLock<Option<jint>> = RwLock::new(None);
+ Self::lookup_static_value(env, &NO_MATCHING_CREDENTIALS, &VALUE)
+ }
+
+ /// Fetch the `PLAINTEXT` constant
+ pub fn plaintext<'local>(env: &mut JNIEnv<'local>) -> jni::errors::Result<jint> {
+ static PLAINTEXT: StaticFieldDesc = IDENTITY_KIND_CLASS.static_field("PLAINTEXT", "I");
+ static VALUE: RwLock<Option<jint>> = RwLock::new(None);
+ Self::lookup_static_value(env, &PLAINTEXT, &VALUE)
+ }
+
+ /// Fetch the `DECRYPTED` constant
+ pub fn decrypted<'local>(env: &mut JNIEnv<'local>) -> jni::errors::Result<jint> {
+ static DECRYPTED: StaticFieldDesc = IDENTITY_KIND_CLASS.static_field("DECRYPTED", "I");
+ static VALUE: RwLock<Option<jint>> = RwLock::new(None);
+ Self::lookup_static_value(env, &DECRYPTED, &VALUE)
+ }
+
+ /// Look up the given field and cache it in the given cache. The lookup will only be performed
+ /// once if successful. This uses `RwLock` instead of `OnceCell` since the fallible `OnceCell`
+ /// APIs are nightly only.
+ fn lookup_static_value<'local>(
+ env: &mut JNIEnv<'local>,
+ field: &StaticFieldDesc,
+ cache: &RwLock<Option<jint>>,
+ ) -> jni::errors::Result<jint> {
+ // Read from cache
+ if let Some(value) = *cache.read().unwrap_or_else(|poison| poison.into_inner()) {
+ return Ok(value);
+ }
+
+ // Get exclusive access to the cache for the lookup
+ let mut guard = cache.write().unwrap_or_else(|poison| poison.into_inner());
+
+ // In case of races, only lookup the value once
+ if let Some(value) = *guard {
+ return Ok(value);
+ }
+
+ let value = env
+ .get_static_field_unchecked(field.cls(), field, JavaType::Primitive(Primitive::Int))
+ .and_then(|ret| ret.i())?;
+
+ *guard = Some(value);
+
+ Ok(value)
+ }
+
+ /// Get the Java representation of [`V0AdvertisementError`].
+ pub fn error_for_v0<'local>(
+ env: &mut JNIEnv<'local>,
+ identity: V0AdvertisementError,
+ ) -> jni::errors::Result<jint> {
+ match identity {
+ V0AdvertisementError::NoMatchingCredentials => Self::no_matching_credentials(env),
+ }
+ }
+
+ /// Get the Java representation of [`DeserializedV0IdentityKind`].
+ pub fn value_for_v0<'local>(
+ env: &mut JNIEnv<'local>,
+ identity: DeserializedV0IdentityKind,
+ ) -> jni::errors::Result<jint> {
+ match identity {
+ DeserializedV0IdentityKind::Plaintext => Self::plaintext(env),
+ DeserializedV0IdentityKind::Decrypted => Self::decrypted(env),
+ }
+ }
+
+ /// Get the Java representation of [`DeserializedV1IdentityKind`].
+ pub fn value_for_v1<'local>(
+ env: &mut JNIEnv<'local>,
+ identity: DeserializedV1IdentityKind,
+ ) -> jni::errors::Result<jint> {
+ match identity {
+ DeserializedV1IdentityKind::Plaintext => Self::plaintext(env),
+ DeserializedV1IdentityKind::Decrypted => Self::decrypted(env),
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/legible_v1_sections.rs b/nearby/presence/np_java_ffi/src/class/legible_v1_sections.rs
new file mode 100644
index 0000000..911c78d
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/legible_v1_sections.rs
@@ -0,0 +1,159 @@
+// 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.
+
+use jni::{
+ objects::{JClass, JObject},
+ sys::{jint, jlong},
+ JNIEnv,
+};
+
+use crate::class::{v1_data_element::Generic, DeserializedV1Section};
+use handle_map::{Handle, HandleLike};
+use np_ffi_core::deserialize::v1::{
+ GetV1DEResult, GetV1SectionResult, LegibleV1Sections as LegibleSectionsHandle, V1DataElement,
+};
+use pourover::{desc::ClassDesc, jni_method};
+
+static LEGIBLE_V1_SECTIONS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/LegibleV1Sections");
+
+/// Rust representation for `class LegibleV1Sections`.
+#[repr(transparent)]
+pub struct LegibleV1Sections<Obj>(pub Obj);
+
+impl<'local> LegibleV1Sections<JObject<'local>> {
+ /// Create new Java instance for the given handle. On the Java side this an `OwnedHandle` and
+ /// Java will be responsible to deallocating it.
+ pub fn construct(
+ env: &mut JNIEnv<'local>,
+ handle: LegibleSectionsHandle,
+ ) -> jni::errors::Result<Self> {
+ let handle_id = handle.get_as_handle().get_id() as jlong;
+
+ pourover::call_constructor!(env, &LEGIBLE_V1_SECTIONS, "(J)V", handle_id,).map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> LegibleV1Sections<Obj> {
+ /// Get a reference to the inner `jni` crate [`JObject`].
+ pub fn as_obj(&self) -> &JObject<'local> {
+ self.0.as_ref()
+ }
+
+ /// Get the Rust [`HandleLike`] representation from this Java object.
+ pub fn as_rust_handle<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<LegibleSectionsHandle> {
+ let handle_id = self.get_handle_id(env)?;
+ Ok(LegibleSectionsHandle::from_handle(Handle::from_id(handle_id as u64)))
+ }
+
+ /// Get `long handleId` from the Java object
+ fn get_handle_id<'env_local>(
+ &self,
+ env: &mut JNIEnv<'env_local>,
+ ) -> jni::errors::Result<jlong> {
+ use jni::signature::{Primitive, ReturnType};
+ use pourover::desc::FieldDesc;
+
+ static HANDLE_ID_FIELD: FieldDesc = LEGIBLE_V1_SECTIONS.field("handleId", "J");
+
+ env.get_field_unchecked(
+ self.0.as_ref(),
+ &HANDLE_ID_FIELD,
+ ReturnType::Primitive(Primitive::Long),
+ )
+ .and_then(|val| val.j())
+ }
+}
+
+// Native method implementations
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "LegibleV1Sections")]
+extern "system" fn nativeGetSection<'local>(
+ mut env: JNIEnv<'local>,
+ legible_sections_obj: LegibleV1Sections<JObject<'local>>,
+ index: jint,
+) -> JObject<'local> {
+ let Ok(legible_sections) = legible_sections_obj.as_rust_handle(&mut env) else {
+ return JObject::null();
+ };
+ let Ok(index) = u8::try_from(index) else {
+ return JObject::null();
+ };
+
+ let GetV1SectionResult::Success(section) = legible_sections.get_section(index) else {
+ return JObject::null();
+ };
+
+ match DeserializedV1Section::construct(
+ &mut env,
+ legible_sections_obj,
+ index,
+ section.num_des(),
+ section.identity_kind(),
+ ) {
+ Ok(section) => section.0,
+ Err(_) => JObject::null(),
+ }
+}
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "LegibleV1Sections")]
+extern "system" fn nativeGetSectionDataElement<'local>(
+ mut env: JNIEnv<'local>,
+ legible_sections_obj: LegibleV1Sections<JObject<'local>>,
+ section_index: jint,
+ de_index: jint,
+) -> JObject<'local> {
+ let Ok(legible_sections) = legible_sections_obj.as_rust_handle(&mut env) else {
+ return JObject::null();
+ };
+ let Ok(section_index) = u8::try_from(section_index) else {
+ return JObject::null();
+ };
+ let Ok(de_index) = u8::try_from(de_index) else {
+ return JObject::null();
+ };
+
+ let GetV1DEResult::Success(de) = legible_sections.get_section_de(section_index, de_index)
+ else {
+ return JObject::null();
+ };
+
+ let ret = match de {
+ V1DataElement::Generic(generic) => {
+ let de_type = jlong::from(generic.de_type().to_u32());
+ let Some(slice) = generic.payload.as_slice() else {
+ return JObject::null();
+ };
+
+ env.byte_array_from_slice(slice)
+ .and_then(|data| Generic::construct(&mut env, de_type, data))
+ .map(|obj| obj.0)
+ }
+ };
+
+ ret.unwrap_or_else(|_err| JObject::null())
+}
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "LegibleV1Sections")]
+extern "system" fn deallocate<'local>(
+ _env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+) {
+ // Swallow errors here since there's nothing meaningful to do.
+ let _ = LegibleSectionsHandle::from_handle(Handle::from_id(handle_id as u64)).deallocate();
+}
diff --git a/nearby/presence/np_java_ffi/src/class/np_adv.rs b/nearby/presence/np_java_ffi/src/class/np_adv.rs
new file mode 100644
index 0000000..88513cc
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/np_adv.rs
@@ -0,0 +1,95 @@
+// 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.
+
+use jni::{
+ objects::{JByteArray, JClass, JObject},
+ sys::{jint, jlong},
+ JNIEnv,
+};
+
+use crate::class::{
+ DeserializeResult, DeserializeResultError, DeserializedV0Advertisement,
+ DeserializedV1Advertisement, LegibleV1Sections, V0AdvertisementError,
+};
+use handle_map::Handle;
+use np_ffi_core::{credentials::CredentialBook, deserialize::deserialize_advertisement_from_slice};
+use pourover::{jni_method, ToUnsigned};
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "NpAdv")]
+extern "system" fn nativeDeserializeAdvertisement<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ service_data: JByteArray<'local>,
+ credential_book: jlong,
+) -> JObject<'local> {
+ let credential_book = CredentialBook::from_handle(Handle::from_id(credential_book as u64));
+
+ // Unpack the service data
+ let mut service_data_buf = [0i8; 256];
+ let Some(service_data) = env.get_array_length(&service_data).ok().and_then(|len| {
+ let len = usize::try_from(len).ok()?;
+ let region = service_data_buf.get_mut(0..len)?;
+ env.get_byte_array_region(&service_data, 0, region).ok()?;
+ Some(region.to_unsigned())
+ }) else {
+ return DeserializeResult::construct_from_error(
+ &mut env,
+ DeserializeResultError::UnknownError,
+ )
+ .map(|obj| obj.0)
+ .unwrap_or(JObject::null());
+ };
+
+ use np_ffi_core::deserialize::{
+ v0::DeserializedV0Advertisement::{Legible, NoMatchingCredentials},
+ DeserializeAdvertisementResult::{Error, V0, V1},
+ };
+
+ let res = match deserialize_advertisement_from_slice(service_data, credential_book) {
+ Error => {
+ DeserializeResult::construct_from_error(&mut env, DeserializeResultError::UnknownError)
+ .map(|obj| obj.0)
+ }
+
+ V0(NoMatchingCredentials) => DeserializedV0Advertisement::construct_from_error(
+ &mut env,
+ V0AdvertisementError::NoMatchingCredentials,
+ )
+ .and_then(|adv| DeserializeResult::from_v0_advertisement(&mut env, adv))
+ .map(|obj| obj.0),
+
+ V0(Legible(adv)) => DeserializedV0Advertisement::construct(
+ &mut env,
+ adv.num_des(),
+ adv.payload(),
+ adv.identity_kind(),
+ )
+ .and_then(|adv| DeserializeResult::from_v0_advertisement(&mut env, adv))
+ .map(|obj| obj.0),
+
+ V1(adv) => LegibleV1Sections::construct(&mut env, adv.legible_sections)
+ .and_then(|sections| {
+ DeserializedV1Advertisement::construct(
+ &mut env,
+ jint::from(adv.num_legible_sections),
+ jint::from(adv.num_undecryptable_sections),
+ sections,
+ )
+ })
+ .and_then(|adv| DeserializeResult::from_v1_advertisement(&mut env, adv))
+ .map(|res| res.0),
+ };
+
+ res.unwrap_or(JObject::null())
+}
diff --git a/nearby/presence/np_java_ffi/src/class/owned_handle.rs b/nearby/presence/np_java_ffi/src/class/owned_handle.rs
new file mode 100644
index 0000000..8dc6e11
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/owned_handle.rs
@@ -0,0 +1,45 @@
+// 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.
+
+use jni::{
+ objects::{JObject, JThrowable},
+ JNIEnv,
+};
+use pourover::desc::ClassDesc;
+
+static NO_SPACE_LEFT_EXCEPTION_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/OwnedHandle$NoSpaceLeftException");
+
+/// Rust representation of `class OwnedHandle.NoSpaceLeftException`.
+#[repr(transparent)]
+pub struct NoSpaceLeftException<Obj>(pub Obj);
+
+impl<'local> NoSpaceLeftException<JObject<'local>> {
+ /// Create a new instance.
+ pub fn construct(env: &mut JNIEnv<'local>) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &NO_SPACE_LEFT_EXCEPTION_CLASS, "()V").map(Self)
+ }
+
+ /// Create a new instance and throw it.
+ pub fn throw_new(env: &mut JNIEnv<'local>) -> jni::errors::Result<()> {
+ Self::construct(env)?.throw(env)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> NoSpaceLeftException<Obj> {
+ /// Throw this exception.
+ pub fn throw<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<()> {
+ env.throw(<&JThrowable>::from(self.0.as_ref()))
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/v0_data_element.rs b/nearby/presence/np_java_ffi/src/class/v0_data_element.rs
new file mode 100644
index 0000000..759a486
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/v0_data_element.rs
@@ -0,0 +1,172 @@
+// 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.
+
+//! Data Elementes for v0 advertisements. See `class V0DataElement`.
+
+use crate::class::IdentityKind;
+use jni::{
+ objects::{JClass, JObject},
+ signature::{Primitive, ReturnType},
+ sys::{jboolean, jint, JNI_FALSE, JNI_TRUE},
+ JNIEnv,
+};
+use np_ffi_core::{deserialize::v0::DeserializedV0IdentityKind, v0};
+use pourover::desc::{ClassDesc, FieldDesc};
+
+static TX_POWER_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/V0DataElement$TxPower");
+
+/// Rust representation of `class V0DataElement.TxPower`.
+#[repr(transparent)]
+pub struct TxPower<Obj>(pub Obj);
+
+impl<'local> TxPower<JObject<'local>> {
+ /// Create a new TxPower date element with the given `tx_power`.
+ pub fn construct(env: &mut JNIEnv<'local>, tx_power: jint) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &TX_POWER_CLASS, "(I)V", tx_power).map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> TxPower<Obj> {
+ /// Cast the given Java object to `TxPower` if it is an instance of the type. Returns `None` if
+ /// the object's type does not match.
+ pub fn checked_cast<'other_local>(
+ env: &mut JNIEnv<'other_local>,
+ obj: Obj,
+ ) -> jni::errors::Result<Option<Self>> {
+ Ok(env.is_instance_of(obj.as_ref(), &TX_POWER_CLASS)?.then(|| Self(obj)))
+ }
+
+ /// Gets the value of the `int txPower` field.
+ pub fn get_tx_power<'env_local>(
+ &self,
+ env: &mut JNIEnv<'env_local>,
+ ) -> jni::errors::Result<jint> {
+ static TX_POWER_FIELD: FieldDesc = TX_POWER_CLASS.field("txPower", "I");
+ env.get_field_unchecked(
+ self.0.as_ref(),
+ &TX_POWER_FIELD,
+ ReturnType::Primitive(Primitive::Int),
+ )
+ .and_then(|ret| ret.i())
+ }
+}
+
+static V0_ACTIONS_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/V0DataElement$V0Actions");
+
+/// Rust representation of `class V0DataElement.V0Actions`.
+#[repr(transparent)]
+pub struct V0Actions<Obj>(pub Obj);
+
+impl<'local> V0Actions<JObject<'local>> {
+ /// Create a new TxPower date element with the given identity and action bits.
+ pub fn construct(
+ env: &mut JNIEnv<'local>,
+ identity_kind: DeserializedV0IdentityKind,
+ action_bits: jint,
+ ) -> jni::errors::Result<Self> {
+ let identity_kind = IdentityKind::value_for_v0(env, identity_kind)?;
+
+ pourover::call_constructor!(env, &V0_ACTIONS_CLASS, "(II)V", identity_kind, action_bits)
+ .map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> V0Actions<Obj> {
+ /// Cast the given Java object to `V0Actions` if it is an instance of the type. Returns `None` if
+ /// the object's type does not match.
+ pub fn checked_cast<'other_local>(
+ env: &mut JNIEnv<'other_local>,
+ obj: Obj,
+ ) -> jni::errors::Result<Option<Self>> {
+ Ok(env.is_instance_of(obj.as_ref(), &V0_ACTIONS_CLASS)?.then(|| Self(obj)))
+ }
+
+ /// Get the `int identityKind` field from the Java object.
+ pub fn get_identity_kind<'env_local>(
+ &self,
+ env: &mut JNIEnv<'env_local>,
+ ) -> jni::errors::Result<jint> {
+ static IDENTITY_KIND: FieldDesc = V0_ACTIONS_CLASS.field("identityKind", "I");
+
+ env.get_field_unchecked(
+ self.0.as_ref(),
+ &IDENTITY_KIND,
+ ReturnType::Primitive(Primitive::Int),
+ )
+ .and_then(|ret| ret.i())
+ }
+
+ /// Get the `int actionBits` field from the Java object.
+ pub fn get_action_bits<'env_local>(
+ &self,
+ env: &mut JNIEnv<'env_local>,
+ ) -> jni::errors::Result<jint> {
+ static ACTION_BITS_FIELD: FieldDesc = V0_ACTIONS_CLASS.field("actionBits", "I");
+
+ env.get_field_unchecked(
+ self.0.as_ref(),
+ &ACTION_BITS_FIELD,
+ ReturnType::Primitive(Primitive::Int),
+ )
+ .and_then(|ret| ret.i())
+ }
+}
+
+/// Helper to build a [`V0Actions`][v0::V0Actions] instance from raw Java fields.
+fn construct_actions_from_ints(
+ env: &mut JNIEnv<'_>,
+ identity_kind: jint,
+ action_bits: jint,
+) -> Option<v0::V0Actions> {
+ let wrapper = if identity_kind == IdentityKind::plaintext(env).ok()? {
+ v0::V0Actions::Plaintext
+ } else if identity_kind == IdentityKind::decrypted(env).ok()? {
+ v0::V0Actions::Encrypted
+ } else {
+ return None;
+ };
+
+ let bits = v0::V0ActionBits::from(action_bits as u32);
+
+ Some(wrapper(bits))
+}
+
+#[pourover::jni_method(
+ package = "com.google.android.nearby.presence.rust",
+ class = "V0DataElement.V0Actions"
+)]
+extern "system" fn nativeHasAction<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ identity_kind: jint,
+ action_bits: jint,
+ action: jint,
+) -> jboolean {
+ let Some(actions) = construct_actions_from_ints(&mut env, identity_kind, action_bits) else {
+ return JNI_FALSE;
+ };
+
+ let Ok(action) = u8::try_from(action).map_err(From::from).and_then(v0::ActionType::try_from)
+ else {
+ return JNI_FALSE;
+ };
+
+ if actions.has_action(action).unwrap_or(false) {
+ JNI_TRUE
+ } else {
+ JNI_FALSE
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/v0_discovery_credential.rs b/nearby/presence/np_java_ffi/src/class/v0_discovery_credential.rs
new file mode 100644
index 0000000..d8f21cf
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/v0_discovery_credential.rs
@@ -0,0 +1,72 @@
+// 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.
+
+use jni::{
+ objects::{JByteArray, JObject},
+ signature::ReturnType,
+ JNIEnv,
+};
+
+use np_ffi_core::credentials::V0DiscoveryCredential as CoreV0DiscoveryCredential;
+use pourover::desc::{ClassDesc, FieldDesc};
+
+static V0_DISCOVERY_CREDENTIAL_CLS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/credential/V0DiscoveryCredential");
+
+/// Rust representation of `class V0DiscoveryCredential`.
+#[repr(transparent)]
+pub struct V0DiscoveryCredential<Obj>(pub Obj);
+
+impl<'local, Obj: AsRef<JObject<'local>>> V0DiscoveryCredential<Obj> {
+ /// Get an array field as a Rust array.
+ fn get_array<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ field: &FieldDesc,
+ ) -> jni::errors::Result<[u8; 32]> {
+ let arr: JByteArray<'env> =
+ env.get_field_unchecked(self.0.as_ref(), field, ReturnType::Array)?.l()?.into();
+
+ let mut buf = [0; 32];
+ env.get_byte_array_region(arr, 0, &mut buf[..])?;
+ Ok(buf.map(|byte| byte as u8))
+ }
+
+ /// Get the key seed.
+ pub fn get_key_seed<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<[u8; 32]> {
+ static KEY_SEED: FieldDesc = V0_DISCOVERY_CREDENTIAL_CLS.field("keySeed", "[B");
+ self.get_array(env, &KEY_SEED)
+ }
+
+ /// Get the identity token hmac.
+ pub fn get_identity_token_hmac<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<[u8; 32]> {
+ static IDENTITY_TOKEN_HMAC: FieldDesc =
+ V0_DISCOVERY_CREDENTIAL_CLS.field("identityTokenHmac", "[B");
+ self.get_array(env, &IDENTITY_TOKEN_HMAC)
+ }
+
+ /// Convert this to the `np_ffi_core` representation.
+ pub fn get_as_core<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<CoreV0DiscoveryCredential> {
+ Ok(CoreV0DiscoveryCredential::new(
+ self.get_key_seed(env)?,
+ self.get_identity_token_hmac(env)?,
+ ))
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/v0_payload.rs b/nearby/presence/np_java_ffi/src/class/v0_payload.rs
new file mode 100644
index 0000000..9b5e05b
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/v0_payload.rs
@@ -0,0 +1,73 @@
+// 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.
+
+use crate::class::v0_data_element::{TxPower, V0Actions};
+use handle_map::{Handle, HandleLike};
+use jni::{
+ objects::{JClass, JObject},
+ sys::{jint, jlong},
+ JNIEnv,
+};
+use np_ffi_core::deserialize::v0::{DeserializedV0IdentityKind, V0Payload};
+use np_ffi_core::v0::V0Actions as CoreV0Actions;
+use pourover::jni_method;
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "V0Payload")]
+extern "system" fn nativeGetDataElement<'local>(
+ mut env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+ index: jint,
+) -> JObject<'local> {
+ let v0_payload = V0Payload::from_handle(Handle::from_id(handle_id as u64));
+ let Ok(index) = u8::try_from(index) else {
+ return JObject::null();
+ };
+
+ use np_ffi_core::{
+ deserialize::v0::GetV0DEResult::{Error, Success},
+ v0::V0DataElement::{Actions, TxPower as TxPow},
+ };
+ let ret = match v0_payload.get_de(index) {
+ Success(TxPow(tx_power)) => {
+ TxPower::construct(&mut env, jint::from(tx_power.as_i8())).map(|obj| obj.0)
+ }
+ Success(Actions(actions)) => {
+ let identity_kind = match &actions {
+ CoreV0Actions::Plaintext(_) => DeserializedV0IdentityKind::Plaintext,
+ CoreV0Actions::Encrypted(_) => DeserializedV0IdentityKind::Decrypted,
+ };
+
+ V0Actions::construct(&mut env, identity_kind, actions.as_u32() as jint).map(|obj| obj.0)
+ }
+ Error => {
+ return JObject::null();
+ }
+ };
+
+ match ret {
+ Ok(de) => de,
+ Err(_jni_err) => JObject::null(),
+ }
+}
+
+#[jni_method(package = "com.google.android.nearby.presence.rust", class = "V0Payload")]
+extern "system" fn deallocate<'local>(
+ _env: JNIEnv<'local>,
+ _cls: JClass<'local>,
+ handle_id: jlong,
+) {
+ // Swallow errors here since there's nothing meaningful to do.
+ let _ = V0Payload::from_handle(Handle::from_id(handle_id as u64)).deallocate();
+}
diff --git a/nearby/presence/np_java_ffi/src/class/v1_data_element.rs b/nearby/presence/np_java_ffi/src/class/v1_data_element.rs
new file mode 100644
index 0000000..6401165
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/v1_data_element.rs
@@ -0,0 +1,51 @@
+// 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.
+
+//! Data Elements for v1 advertisements. See `class V1DataElement`.
+
+use jni::{
+ objects::{JByteArray, JObject},
+ sys::jlong,
+ JNIEnv,
+};
+use pourover::desc::ClassDesc;
+
+static GENERIC_CLASS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/V1DataElement$Generic");
+
+/// Rust representation of `class V1DataElement.Generic`.
+#[repr(transparent)]
+pub struct Generic<Obj>(pub Obj);
+
+impl<'local> Generic<JObject<'local>> {
+ /// Create a new Java instance from the given data element info.
+ pub fn construct<'data>(
+ env: &mut JNIEnv<'local>,
+ de_type: jlong,
+ data: JByteArray<'data>,
+ ) -> jni::errors::Result<Self> {
+ pourover::call_constructor!(env, &GENERIC_CLASS, "(J[B)V", de_type, data).map(Self)
+ }
+}
+
+impl<'local, Obj: AsRef<JObject<'local>>> Generic<Obj> {
+ /// Cast the given Java object to `Generic` if it is an instance of the type. Returns `None` if
+ /// the object's type does not match.
+ pub fn checked_cast<'other_local>(
+ env: &mut JNIEnv<'other_local>,
+ obj: Obj,
+ ) -> jni::errors::Result<Option<Self>> {
+ Ok(env.is_instance_of(obj.as_ref(), &GENERIC_CLASS)?.then(|| Self(obj)))
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/class/v1_discovery_credential.rs b/nearby/presence/np_java_ffi/src/class/v1_discovery_credential.rs
new file mode 100644
index 0000000..923446a
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/class/v1_discovery_credential.rs
@@ -0,0 +1,101 @@
+// 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.
+
+use jni::{
+ objects::{JByteArray, JObject},
+ signature::ReturnType,
+ JNIEnv,
+};
+
+use np_ffi_core::credentials::V1DiscoveryCredential as CoreV1DiscoveryCredential;
+use pourover::desc::{ClassDesc, FieldDesc};
+
+static V1_DISCOVERY_CREDENTIAL_CLS: ClassDesc =
+ ClassDesc::new("com/google/android/nearby/presence/rust/credential/V1DiscoveryCredential");
+
+/// Rust representation of `class V1DiscoveryCredential`.
+#[repr(transparent)]
+pub struct V1DiscoveryCredential<Obj>(pub Obj);
+
+impl<'local, Obj: AsRef<JObject<'local>>> V1DiscoveryCredential<Obj> {
+ /// Get an array field as a Rust array.
+ fn get_array<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ field: &FieldDesc,
+ ) -> jni::errors::Result<[u8; 32]> {
+ let arr: JByteArray<'env> =
+ env.get_field_unchecked(self.0.as_ref(), field, ReturnType::Array)?.l()?.into();
+
+ let mut buf = [0; 32];
+ env.get_byte_array_region(arr, 0, &mut buf[..])?;
+ Ok(buf.map(|byte| byte as u8))
+ }
+
+ /// Get the key seed.
+ pub fn get_key_seed<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<[u8; 32]> {
+ static KEY_SEED: FieldDesc = V1_DISCOVERY_CREDENTIAL_CLS.field("keySeed", "[B");
+ self.get_array(env, &KEY_SEED)
+ }
+
+ /// Get the expected mic short salt identity token hmac.
+ pub fn get_expected_mic_short_salt_identity_token_hmac<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<[u8; 32]> {
+ static EXPECTED_MIC_SHORT_SALT_IDENTITY_TOKEN_HMAC: FieldDesc =
+ V1_DISCOVERY_CREDENTIAL_CLS.field("expectedMicShortSaltIdentityTokenHmac", "[B");
+ self.get_array(env, &EXPECTED_MIC_SHORT_SALT_IDENTITY_TOKEN_HMAC)
+ }
+
+ /// Get the expected mic extended salt identity token hmac.
+ pub fn get_expected_mic_extended_salt_identity_token_hmac<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<[u8; 32]> {
+ static EXPECTED_MIC_EXTENDED_SALT_IDENTITY_TOKEN_HMAC: FieldDesc =
+ V1_DISCOVERY_CREDENTIAL_CLS.field("expectedMicExtendedSaltIdentityTokenHmac", "[B");
+ self.get_array(env, &EXPECTED_MIC_EXTENDED_SALT_IDENTITY_TOKEN_HMAC)
+ }
+
+ /// Get the expected signature identity token hmac.
+ pub fn get_expected_signature_identity_token_hmac<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<[u8; 32]> {
+ static EXPECTED_SIGNATURE_IDENTITY_TOKEN_HMAC: FieldDesc =
+ V1_DISCOVERY_CREDENTIAL_CLS.field("expectedSignatureIdentityTokenHmac", "[B");
+ self.get_array(env, &EXPECTED_SIGNATURE_IDENTITY_TOKEN_HMAC)
+ }
+
+ /// Get the pub key.
+ pub fn get_pub_key<'env>(&self, env: &mut JNIEnv<'env>) -> jni::errors::Result<[u8; 32]> {
+ static PUB_KEY: FieldDesc = V1_DISCOVERY_CREDENTIAL_CLS.field("pubKey", "[B");
+ self.get_array(env, &PUB_KEY)
+ }
+
+ /// Convert this to the `np_ffi_core` representation.
+ pub fn get_as_core<'env>(
+ &self,
+ env: &mut JNIEnv<'env>,
+ ) -> jni::errors::Result<CoreV1DiscoveryCredential> {
+ Ok(CoreV1DiscoveryCredential::new(
+ self.get_key_seed(env)?,
+ self.get_expected_mic_short_salt_identity_token_hmac(env)?,
+ self.get_expected_mic_extended_salt_identity_token_hmac(env)?,
+ self.get_expected_signature_identity_token_hmac(env)?,
+ self.get_pub_key(env)?,
+ ))
+ }
+}
diff --git a/nearby/presence/np_java_ffi/src/lib.rs b/nearby/presence/np_java_ffi/src/lib.rs
new file mode 100644
index 0000000..7a688e8
--- /dev/null
+++ b/nearby/presence/np_java_ffi/src/lib.rs
@@ -0,0 +1,21 @@
+// 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.
+
+//! Java bindings for np_ffi_core.
+
+// Named lifetimes are being used to match jni crate conventions.
+// See: https://docs.rs/jni/latest/jni/struct.JNIEnv.html#lifetime-names
+#![allow(clippy::needless_lifetimes)]
+
+pub mod class;
diff --git a/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/DeserializeTests.java b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/DeserializeTests.java
new file mode 100644
index 0000000..d4f146e
--- /dev/null
+++ b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/DeserializeTests.java
@@ -0,0 +1,199 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import static com.google.android.nearby.presence.rust.TestData.*;
+import static com.google.android.nearby.presence.rust.credential.CredentialBook.NoMetadata;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.android.nearby.presence.rust.credential.CredentialBook;
+import org.junit.jupiter.api.Test;
+
+public class DeserializeTests {
+
+ DeserializeResult parsePublicAdv(byte[] bytes) {
+ // Call parse with an empty CredentialBook
+ try (CredentialBook<NoMetadata> book = CredentialBook.empty()) {
+ return NpAdv.deserializeAdvertisement(bytes, book);
+ }
+ }
+
+ DeserializeResult parsePrivateAdv(byte[] bytes) {
+ try (CredentialBook<NoMetadata> book =
+ CredentialBook.<NoMetadata>builder()
+ .addDiscoveryCredential(V0_CRED, NoMetadata.INSTANCE)
+ .addDiscoveryCredential(V1_CRED, NoMetadata.INSTANCE)
+ .build()) {
+ return NpAdv.deserializeAdvertisement(bytes, book);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_canParsePublic() {
+ try (DeserializeResult result = parsePublicAdv(V0_PUBLIC)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V0_ADVERTISEMENT);
+
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.isLegible()).isTrue();
+ assertThat(adv.getIdentity()).isEqualTo(IdentityKind.PLAINTEXT);
+ assertThat(adv.getDataElementCount()).isEqualTo(2);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_canParsePublicWithCreds() {
+ try (DeserializeResult result = parsePrivateAdv(V0_PUBLIC)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V0_ADVERTISEMENT);
+
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.isLegible()).isTrue();
+ assertThat(adv.getIdentity()).isEqualTo(IdentityKind.PLAINTEXT);
+ assertThat(adv.getDataElementCount()).isEqualTo(2);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_canParsePrivate() {
+ try (DeserializeResult result = parsePrivateAdv(V0_PRIVATE)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V0_ADVERTISEMENT);
+
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.isLegible()).isTrue();
+ assertThat(adv.getIdentity()).isEqualTo(IdentityKind.DECRYPTED);
+ assertThat(adv.getDataElementCount()).isEqualTo(1);
+ assertThat(adv.getDataElement(0)).isInstanceOf(V0DataElement.TxPower.class);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_cannotParsePrivateWithoutCreds() {
+ try (DeserializeResult result = parsePublicAdv(V0_PRIVATE)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V0_ADVERTISEMENT);
+
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.isLegible()).isFalse();
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_canReadTxPowerDe() {
+ try (DeserializeResult result = parsePublicAdv(V0_PUBLIC)) {
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ V0DataElement de = adv.getDataElement(0);
+
+ assertThat(de).isInstanceOf(V0DataElement.TxPower.class);
+ V0DataElement.TxPower txPower = (V0DataElement.TxPower) de;
+ assertThat(txPower.getTxPower()).isEqualTo(20);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v0_canReadActionsDe() {
+ try (DeserializeResult result = parsePublicAdv(V0_PUBLIC)) {
+ DeserializedV0Advertisement adv = result.getAsV0();
+
+ V0DataElement de = adv.getDataElement(1);
+
+ assertThat(de).isInstanceOf(V0DataElement.V0Actions.class);
+ V0DataElement.V0Actions actions = (V0DataElement.V0Actions) de;
+ assertThat(actions.getIdentityKind()).isEqualTo(IdentityKind.PLAINTEXT);
+ assertThat(actions.hasAction(V0DataElement.V0ActionType.NEARBY_SHARE)).isTrue();
+ assertThat(actions.hasAction(V0DataElement.V0ActionType.CROSS_DEV_SDK)).isFalse();
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v1_canParsePublic() {
+ try (DeserializeResult result = parsePublicAdv(V1_PUBLIC)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V1_ADVERTISEMENT);
+
+ DeserializedV1Advertisement adv = result.getAsV1();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.getNumLegibleSections()).isEqualTo(1);
+ assertThat(adv.getNumUndecryptableSections()).isEqualTo(0);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v1_canParsePrivate() {
+ try (DeserializeResult result = parsePrivateAdv(V1_PRIVATE)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V1_ADVERTISEMENT);
+
+ DeserializedV1Advertisement adv = result.getAsV1();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.getNumLegibleSections()).isEqualTo(1);
+ assertThat(adv.getNumUndecryptableSections()).isEqualTo(0);
+
+ DeserializedV1Section section = adv.getSection(0);
+ assertThat(section.getIdentityKind()).isEqualTo(IdentityKind.DECRYPTED);
+ assertThat(section.getDataElementCount()).isEqualTo(1);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v1_canParsePrivateWithoutCreds() {
+ try (DeserializeResult result = parsePublicAdv(V1_PRIVATE)) {
+ assertThat(result.getKind()).isEqualTo(DeserializeResult.Kind.V1_ADVERTISEMENT);
+
+ DeserializedV1Advertisement adv = result.getAsV1();
+
+ assertThat(adv).isNotNull();
+ assertThat(adv.getNumLegibleSections()).isEqualTo(0);
+ assertThat(adv.getNumUndecryptableSections()).isEqualTo(1);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v1_canParsePublicSection() {
+ try (DeserializeResult result = parsePublicAdv(V1_PUBLIC)) {
+ DeserializedV1Advertisement adv = result.getAsV1();
+
+ DeserializedV1Section section = adv.getSection(0);
+
+ assertThat(section).isNotNull();
+ assertThat(section.getIdentityKind()).isEqualTo(IdentityKind.PLAINTEXT);
+ assertThat(section.getDataElementCount()).isEqualTo(1);
+ }
+ }
+
+ @Test
+ void deserializeAdvertisement_v1_canReadGenericDe() {
+ try (DeserializeResult result = parsePublicAdv(V1_PUBLIC)) {
+ DeserializedV1Advertisement adv = result.getAsV1();
+ DeserializedV1Section section = adv.getSection(0);
+
+ V1DataElement de = section.getDataElement(0);
+
+ assertThat(de).isNotNull();
+ assertThat(de).isInstanceOf(V1DataElement.Generic.class);
+ V1DataElement.Generic generic = (V1DataElement.Generic) de;
+ assertThat(generic.getType()).isEqualTo(0x05 /* V1 TxPower */);
+ assertThat(generic.getData()).asList().containsExactly((byte) 6);
+ }
+ }
+}
diff --git a/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/TestData.java b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/TestData.java
new file mode 100644
index 0000000..8ee26a1
--- /dev/null
+++ b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/TestData.java
@@ -0,0 +1,410 @@
+/*
+ * 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 com.google.android.nearby.presence.rust;
+
+import com.google.android.nearby.presence.rust.credential.V0DiscoveryCredential;
+import com.google.android.nearby.presence.rust.credential.V1DiscoveryCredential;
+
+public class TestData {
+
+ public static final byte[] V0_PUBLIC = {
+ 0x00, // adv header
+ 0x15, 20, // tx power
+ 0x26, 0x00, 0x40, // actions
+ };
+
+ public static final byte[] V1_PUBLIC = {
+ 0x20, // NP Version Header
+ 0x00, // Section format
+ 0x02, // section len
+ 0x15, 0x06, // tx power value 6
+ };
+
+ public static final byte[] V0_KEY_SEED = {
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11
+ };
+
+ public static final byte[] V0_IDENTITY_TOKEN = {
+ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+ 0x33, 0x33, 0x33, 0x33
+ };
+
+ public static final byte[] V0_IDENTITY_TOKEN_HMAC = {
+ (byte) 0x09,
+ (byte) 0xFE,
+ (byte) 0x9E,
+ (byte) 0x81,
+ (byte) 0xB7,
+ (byte) 0x3E,
+ (byte) 0x5E,
+ (byte) 0xCC,
+ (byte) 0x76,
+ (byte) 0x59,
+ (byte) 0x57,
+ (byte) 0x71,
+ (byte) 0xE0,
+ (byte) 0x1F,
+ (byte) 0xFB,
+ (byte) 0x34,
+ (byte) 0x38,
+ (byte) 0xE7,
+ (byte) 0x5F,
+ (byte) 0x24,
+ (byte) 0xA7,
+ (byte) 0x69,
+ (byte) 0x56,
+ (byte) 0xA0,
+ (byte) 0xB8,
+ (byte) 0xEA,
+ (byte) 0x67,
+ (byte) 0xD1,
+ (byte) 0x1C,
+ (byte) 0x3E,
+ (byte) 0x36,
+ (byte) 0xFD
+ };
+
+ public static final V0DiscoveryCredential V0_CRED =
+ new V0DiscoveryCredential(V0_KEY_SEED, V0_IDENTITY_TOKEN_HMAC);
+
+ public static final byte[] V0_PRIVATE = {
+ 0x04, // adv header
+ 0x22,
+ 0x22, // salt
+ (byte) 0xD8,
+ (byte) 0x22,
+ (byte) 0x12,
+ (byte) 0xEF,
+ (byte) 0x16,
+ (byte) 0xDB,
+ (byte) 0xF8,
+ (byte) 0x72,
+ (byte) 0xF2,
+ (byte) 0xA3,
+ (byte) 0xA7,
+ (byte) 0xC0,
+ (byte) 0xFA,
+ (byte) 0x52,
+ (byte) 0x48,
+ (byte) 0xEC // ciphertext for metadata key & txpower DE
+ };
+
+ public static final byte[] V1_IDENTITY_TOKEN = {
+ (byte) 0x58,
+ (byte) 0x31,
+ (byte) 0x00,
+ (byte) 0x48,
+ (byte) 0x11,
+ (byte) 0xe4,
+ (byte) 0xea,
+ (byte) 0x43,
+ (byte) 0xe9,
+ (byte) 0x01,
+ (byte) 0x76,
+ (byte) 0x25,
+ (byte) 0xd8,
+ (byte) 0xaf,
+ (byte) 0xd6,
+ (byte) 0x92
+ };
+
+ public static final byte[] V1_KEY_SEED = {
+ (byte) 0xc8,
+ (byte) 0xdd,
+ (byte) 0x01,
+ (byte) 0x4d,
+ (byte) 0x25,
+ (byte) 0x01,
+ (byte) 0xc0,
+ (byte) 0xbf,
+ (byte) 0x5b,
+ (byte) 0x2a,
+ (byte) 0x05,
+ (byte) 0x48,
+ (byte) 0x49,
+ (byte) 0x8c,
+ (byte) 0xe6,
+ (byte) 0xbf,
+ (byte) 0x48,
+ (byte) 0x5b,
+ (byte) 0x89,
+ (byte) 0xb8,
+ (byte) 0x47,
+ (byte) 0x13,
+ (byte) 0xcc,
+ (byte) 0xdd,
+ (byte) 0xa0,
+ (byte) 0x18,
+ (byte) 0xac,
+ (byte) 0xd9,
+ (byte) 0xef,
+ (byte) 0x58,
+ (byte) 0x9f,
+ (byte) 0x76
+ };
+
+ public static final byte[] V1_MIC_SHORT_HMAC = {
+ (byte) 0x09,
+ (byte) 0x48,
+ (byte) 0x4e,
+ (byte) 0x8f,
+ (byte) 0x39,
+ (byte) 0xdc,
+ (byte) 0x16,
+ (byte) 0x27,
+ (byte) 0x85,
+ (byte) 0x0a,
+ (byte) 0xea,
+ (byte) 0xfc,
+ (byte) 0x84,
+ (byte) 0xf6,
+ (byte) 0x43,
+ (byte) 0x51,
+ (byte) 0x62,
+ (byte) 0x16,
+ (byte) 0xf1,
+ (byte) 0x8d,
+ (byte) 0xda,
+ (byte) 0xd3,
+ (byte) 0xbc,
+ (byte) 0xba,
+ (byte) 0x43,
+ (byte) 0xf1,
+ (byte) 0x62,
+ (byte) 0x4e,
+ (byte) 0xa7,
+ (byte) 0x09,
+ (byte) 0xda,
+ (byte) 0xde
+ };
+
+ public static final byte[] V1_MIC_LONG_HMAC = {
+ (byte) 0xb9,
+ (byte) 0x6a,
+ (byte) 0xd2,
+ (byte) 0x3e,
+ (byte) 0x8e,
+ (byte) 0x08,
+ (byte) 0xe0,
+ (byte) 0xf4,
+ (byte) 0xe9,
+ (byte) 0xba,
+ (byte) 0xe9,
+ (byte) 0xbb,
+ (byte) 0x3d,
+ (byte) 0xe3,
+ (byte) 0x2f,
+ (byte) 0xd1,
+ (byte) 0x14,
+ (byte) 0x3a,
+ (byte) 0x51,
+ (byte) 0x19,
+ (byte) 0x54,
+ (byte) 0xf8,
+ (byte) 0x66,
+ (byte) 0x9f,
+ (byte) 0xf6,
+ (byte) 0xdb,
+ (byte) 0xf6,
+ (byte) 0x03,
+ (byte) 0xf7,
+ (byte) 0x41,
+ (byte) 0x20,
+ (byte) 0xd7
+ };
+
+ public static final byte[] V1_SIG_HMAC = {
+ (byte) 0xc4,
+ (byte) 0x19,
+ (byte) 0x6e,
+ (byte) 0x84,
+ (byte) 0x95,
+ (byte) 0x3a,
+ (byte) 0x8a,
+ (byte) 0x97,
+ (byte) 0xb9,
+ (byte) 0xed,
+ (byte) 0xf0,
+ (byte) 0xba,
+ (byte) 0xd2,
+ (byte) 0x5d,
+ (byte) 0xa4,
+ (byte) 0x32,
+ (byte) 0xb1,
+ (byte) 0xf2,
+ (byte) 0x1a,
+ (byte) 0xf7,
+ (byte) 0x7d,
+ (byte) 0x95,
+ (byte) 0x8f,
+ (byte) 0xeb,
+ (byte) 0x5f,
+ (byte) 0xbe,
+ (byte) 0xfd,
+ (byte) 0x62,
+ (byte) 0xa7,
+ (byte) 0xc0,
+ (byte) 0x16,
+ (byte) 0x66
+ };
+
+ public static final byte[] V1_PUB_KEY = {
+ (byte) 0x3c,
+ (byte) 0x59,
+ (byte) 0xd7,
+ (byte) 0x30,
+ (byte) 0x58,
+ (byte) 0x8c,
+ (byte) 0x45,
+ (byte) 0x26,
+ (byte) 0x7e,
+ (byte) 0x52,
+ (byte) 0x29,
+ (byte) 0x54,
+ (byte) 0xca,
+ (byte) 0xc9,
+ (byte) 0xcb,
+ (byte) 0xca,
+ (byte) 0x72,
+ (byte) 0x94,
+ (byte) 0x24,
+ (byte) 0xd8,
+ (byte) 0xf5,
+ (byte) 0xa6,
+ (byte) 0x1e,
+ (byte) 0xcf,
+ (byte) 0x04,
+ (byte) 0x3e,
+ (byte) 0x8f,
+ (byte) 0x91,
+ (byte) 0x81,
+ (byte) 0x6d,
+ (byte) 0x19,
+ (byte) 0x74
+ };
+
+ public static final V1DiscoveryCredential V1_CRED =
+ new V1DiscoveryCredential(
+ V1_KEY_SEED, V1_MIC_SHORT_HMAC, V1_MIC_LONG_HMAC, V1_SIG_HMAC, V1_PUB_KEY);
+
+ public static final byte[] V1_PRIVATE = {
+ (byte) 0x20,
+ (byte) 0x03,
+ (byte) 0xfc,
+ (byte) 0x32,
+ (byte) 0xb7,
+ (byte) 0x5d,
+ (byte) 0xdd,
+ (byte) 0x6a,
+ (byte) 0xdb,
+ (byte) 0xb0,
+ (byte) 0x89,
+ (byte) 0x7d,
+ (byte) 0xb9,
+ (byte) 0xcd,
+ (byte) 0xa9,
+ (byte) 0x6e,
+ (byte) 0x73,
+ (byte) 0x6d,
+ (byte) 0x7a,
+ (byte) 0xfc,
+ (byte) 0xeb,
+ (byte) 0x2b,
+ (byte) 0x0c,
+ (byte) 0x02,
+ (byte) 0x3d,
+ (byte) 0xc8,
+ (byte) 0xfa,
+ (byte) 0xc8,
+ (byte) 0x78,
+ (byte) 0x83,
+ (byte) 0x56,
+ (byte) 0xfa,
+ (byte) 0x53,
+ (byte) 0x11,
+ (byte) 0x42,
+ (byte) 0x08,
+ (byte) 0x9e,
+ (byte) 0xfe,
+ (byte) 0x70,
+ (byte) 0xd0,
+ (byte) 0x68,
+ (byte) 0x6c,
+ (byte) 0x7c,
+ (byte) 0x29,
+ (byte) 0x86,
+ (byte) 0xd6,
+ (byte) 0x76,
+ (byte) 0x2b,
+ (byte) 0x03,
+ (byte) 0xa4,
+ (byte) 0xc7,
+ (byte) 0x47,
+ (byte) 0x5c,
+ (byte) 0x41,
+ (byte) 0x9d,
+ (byte) 0x21,
+ (byte) 0x15,
+ (byte) 0x54,
+ (byte) 0x89,
+ (byte) 0x43,
+ (byte) 0x32,
+ (byte) 0x44,
+ (byte) 0x47,
+ (byte) 0x34,
+ (byte) 0xd7,
+ (byte) 0xbd,
+ (byte) 0x4f,
+ (byte) 0x38,
+ (byte) 0x83,
+ (byte) 0x74,
+ (byte) 0xe4,
+ (byte) 0xdb,
+ (byte) 0xcf,
+ (byte) 0xfe,
+ (byte) 0xe4,
+ (byte) 0x7a,
+ (byte) 0xae,
+ (byte) 0xa8,
+ (byte) 0xe2,
+ (byte) 0xf5,
+ (byte) 0x69,
+ (byte) 0xb8,
+ (byte) 0x42,
+ (byte) 0xf5,
+ (byte) 0x67,
+ (byte) 0x7a,
+ (byte) 0x34,
+ (byte) 0x6d,
+ (byte) 0x86,
+ (byte) 0x8b,
+ (byte) 0x4c,
+ (byte) 0xa9,
+ (byte) 0x7f,
+ (byte) 0x45,
+ (byte) 0x1c,
+ (byte) 0x37,
+ (byte) 0xf1,
+ (byte) 0x6e,
+ (byte) 0xfc,
+ (byte) 0xae,
+ (byte) 0xc6
+ };
+}
diff --git a/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/credential/CredentialBookTests.java b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/credential/CredentialBookTests.java
new file mode 100644
index 0000000..12302d3
--- /dev/null
+++ b/nearby/presence/np_java_ffi/test/com/google/android/nearby/presence/rust/credential/CredentialBookTests.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.google.android.nearby.presence.rust.credential;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.*;
+
+import java.lang.ref.Cleaner;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class CredentialBookTests {
+
+ @Mock Cleaner cleaner;
+
+ @Test
+ void CredentialBook_wasRegisteredWithCleaner() {
+ try (CredentialBook book = new CredentialBook.Builder(cleaner).build()) {
+ assertThat(book).isNotNull();
+ verify(cleaner).register(same(book), any());
+ }
+ }
+}
diff --git a/nearby/presence/rand_ext/src/lib.rs b/nearby/presence/rand_ext/src/lib.rs
index d767143..587279d 100644
--- a/nearby/presence/rand_ext/src/lib.rs
+++ b/nearby/presence/rand_ext/src/lib.rs
@@ -20,8 +20,8 @@ extern crate alloc;
use alloc::vec::Vec;
use crypto_provider::{CryptoProvider, CryptoRng};
use log::info;
-pub use rand;
use rand::{Rng as _, SeedableRng};
+pub use {rand, rand_pcg};
/// Returns a random Vec with the provided length.
pub fn random_vec<C: CryptoProvider>(rng: &mut C::CryptoRng, len: usize) -> Vec<u8> {
@@ -52,7 +52,7 @@ pub fn random_bytes_rc<const B: usize, R: rand::Rng>(rng: &mut R) -> [u8; B] {
}
/// Returns a fast rng seeded with the thread rng (which is itself seeded from the OS).
-pub fn seeded_rng() -> impl rand::Rng {
+pub fn seeded_rng() -> rand_pcg::Pcg64 {
let mut seed: <rand_pcg::Pcg64 as rand::SeedableRng>::Seed = Default::default();
rand::thread_rng().fill(&mut seed);
// print it out so if a test fails, the seed will be visible for further investigation
diff --git a/nearby/presence/test_helper/Cargo.toml b/nearby/presence/test_helper/Cargo.toml
index c52d6bf..340a843 100644
--- a/nearby/presence/test_helper/Cargo.toml
+++ b/nearby/presence/test_helper/Cargo.toml
@@ -10,3 +10,4 @@ workspace = true
[dependencies]
hex.workspace = true
serde_json.workspace = true
+itertools.workspace = true
diff --git a/nearby/presence/test_helper/src/lib.rs b/nearby/presence/test_helper/src/lib.rs
index 8b42623..76dccf4 100644
--- a/nearby/presence/test_helper/src/lib.rs
+++ b/nearby/presence/test_helper/src/lib.rs
@@ -16,6 +16,7 @@
#![allow(clippy::unwrap_used, clippy::expect_used)]
+use itertools::Itertools;
use std::fs;
use std::io::Read;
@@ -62,3 +63,16 @@ pub fn extract_key_array<const N: usize>(value: &serde_json::Value, key: &str) -
pub fn string_to_hex(str: &str) -> Vec<u8> {
hex::decode(str).unwrap()
}
+
+/// Format data as hex bytes for the convenience of test data in FFI tests.
+///
+/// # Examples
+///
+/// ```
+/// use test_helper::hex_bytes;
+///
+/// assert_eq!("0x12, 0x34", hex_bytes(&[0x12, 0x34]));
+/// ```
+pub fn hex_bytes(data: impl AsRef<[u8]>) -> String {
+ hex::encode_upper(data).chars().tuples().map(|(a, b)| format!("0x{}{}", a, b)).join(", ")
+}
diff --git a/nearby/presence/test_vector_hkdf/Cargo.toml b/nearby/presence/test_vector_hkdf/Cargo.toml
new file mode 100644
index 0000000..cf5d1a2
--- /dev/null
+++ b/nearby/presence/test_vector_hkdf/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "test_vector_hkdf"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
+crypto_provider.workspace = true
+crypto_provider_default = { workspace = true, features = ["rustcrypto"] }
+
+[dev-dependencies]
+
+
+
diff --git a/nearby/presence/test_vector_hkdf/src/lib.rs b/nearby/presence/test_vector_hkdf/src/lib.rs
new file mode 100644
index 0000000..d067eec
--- /dev/null
+++ b/nearby/presence/test_vector_hkdf/src/lib.rs
@@ -0,0 +1,91 @@
+// 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.
+
+//! Tools for generating test vector data in a repeatable way.
+//!
+//! The common approach of just using an RNG means that even a small change to how test vectors are
+//! created will regenerate everything. Instead, by using a predictable seed and deriving data from
+//! that with per-datum names, incremental changes can be made without regenerating everything.
+//!
+//! # Examples
+//!
+//! Generating 100 groups of data:
+//!
+//! ```
+//! use crypto_provider_default::CryptoProviderImpl;
+//! use test_vector_hkdf::TestVectorHkdf;
+//!
+//! for i in 0_u32..100 {
+//! let hkdf = TestVectorHkdf::<CryptoProviderImpl>::new(
+//! "Spiffy test vectors - random seed: hunter2",
+//! i.to_be_bytes().as_slice());
+//!
+//! let vec = hkdf.derive_vec(
+//! "fun data",
+//! hkdf.derive_range_element("fun data length", 3..=18).try_into().unwrap());
+//! let array = hkdf.derive_array::<16>("array data");
+//! // store the generated data somewhere
+//! }
+//! ```
+
+#![allow(clippy::unwrap_used)]
+
+use crypto_provider::hkdf::Hkdf;
+use crypto_provider::CryptoProvider;
+use crypto_provider_default::CryptoProviderImpl;
+use std::ops;
+
+/// Typical usage would generate one instance per loop, and derive all data needed for that loop
+/// iteration.
+///
+/// The `description` passed to all `derive_` calls should be distinct, unless identical data is
+/// desired.
+pub struct TestVectorHkdf<C: CryptoProvider = CryptoProviderImpl> {
+ hkdf: C::HkdfSha256,
+}
+
+impl<C: CryptoProvider> TestVectorHkdf<C> {
+ /// Create a new instance for the provided namespace and iteration.
+ ///
+ /// The namespace should contain a blob of randomly generated data. If reshuffling the generated
+ /// data is desired, just change the blob of random data.
+ pub fn new(namespace: &str, iteration: &[u8]) -> Self {
+ Self { hkdf: C::HkdfSha256::new(Some(namespace.as_bytes()), iteration) }
+ }
+
+ /// Derive an array of `N` bytes.
+ pub fn derive_array<const N: usize>(&self, description: &str) -> [u8; N] {
+ let mut arr = [0; N];
+ self.hkdf.expand(description.as_bytes(), &mut arr).unwrap();
+ arr
+ }
+
+ /// Derive a Vec of the specified `len`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `len` is too long for an HKDF output.
+ pub fn derive_vec(&self, description: &str, len: usize) -> Vec<u8> {
+ let mut vec = vec![0; len];
+ self.hkdf.expand(description.as_bytes(), &mut vec).unwrap();
+ vec
+ }
+
+ /// Generated a biased element in a range using a sloppy sampling technique.
+ /// Will be increasingly biased as the range gets bigger.
+ pub fn derive_range_element(&self, description: &str, range: ops::RangeInclusive<u64>) -> u64 {
+ let num = u64::from_be_bytes(self.derive_array(description));
+ num % (range.end() - range.start() + 1) + range.start()
+ }
+}
diff --git a/nearby/presence/xts_aes/fuzz/Cargo.lock b/nearby/presence/xts_aes/fuzz/Cargo.lock
index a08ab7c..52831cd 100644
--- a/nearby/presence/xts_aes/fuzz/Cargo.lock
+++ b/nearby/presence/xts_aes/fuzz/Cargo.lock
@@ -55,9 +55,9 @@ dependencies = [
[[package]]
name = "arbitrary"
-version = "1.3.0"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
+checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
@@ -92,9 +92,9 @@ dependencies = [
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cbc"
@@ -107,11 +107,12 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
+ "libc",
]
[[package]]
@@ -132,24 +133,24 @@ dependencies = [
[[package]]
name = "const-oid"
-version = "0.9.4"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-bigint"
-version = "0.5.2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array",
"rand_core",
@@ -211,9 +212,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek"
-version = "4.0.0"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -227,9 +228,9 @@ dependencies = [
[[package]]
name = "curve25519-dalek-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
@@ -238,9 +239,9 @@ dependencies = [
[[package]]
name = "der"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
dependencies = [
"const-oid",
"zeroize",
@@ -248,9 +249,9 @@ dependencies = [
[[package]]
name = "derive_arbitrary"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
+checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
@@ -270,18 +271,18 @@ dependencies = [
[[package]]
name = "ed25519"
-version = "2.2.1"
+version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"signature",
]
[[package]]
name = "ed25519-dalek"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
@@ -292,9 +293,9 @@ dependencies = [
[[package]]
name = "elliptic-curve"
-version = "0.13.5"
+version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
+checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -321,9 +322,9 @@ dependencies = [
[[package]]
name = "fiat-crypto"
-version = "0.1.20"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
[[package]]
name = "generic-array"
@@ -338,9 +339,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.10"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
@@ -370,9 +371,9 @@ dependencies = [
[[package]]
name = "hkdf"
-version = "0.12.3"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac",
]
@@ -398,9 +399,9 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.26"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
@@ -414,15 +415,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libfuzzer-sys"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beb09950ae85a0a94b27676cccf37da5ff13f27076aa1adbc6545dd0d0e1bd4e"
+checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7"
dependencies = [
"arbitrary",
"cc",
@@ -431,9 +432,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
@@ -453,9 +454,9 @@ dependencies = [
[[package]]
name = "platforms"
-version = "3.0.2"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
+checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
[[package]]
name = "polyval"
@@ -477,27 +478,27 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "primeorder"
-version = "0.13.2"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3"
+checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -554,9 +555,9 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.18"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "sha2"
@@ -571,9 +572,9 @@ dependencies = [
[[package]]
name = "signature"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
[[package]]
name = "subtle"
@@ -583,9 +584,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "2.0.26"
+version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@@ -600,15 +601,15 @@ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "universal-hash"
@@ -634,9 +635,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "x25519-dalek"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
@@ -665,6 +666,6 @@ dependencies = [
[[package]]
name = "zeroize"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/nearby/presence/xts_aes/fuzz/Cargo.toml b/nearby/presence/xts_aes/fuzz/Cargo.toml
index 4d00c49..5d99173 100644
--- a/nearby/presence/xts_aes/fuzz/Cargo.toml
+++ b/nearby/presence/xts_aes/fuzz/Cargo.toml
@@ -9,27 +9,17 @@ edition = "2018"
cargo-fuzz = true
[dependencies]
-libfuzzer-sys = "0.4"
-arbitrary = { version = "1.1.7", features = ["derive"] }
+arbitrary = { workspace = true, features = ["derive"] }
+crypto_provider.workspace = true
+crypto_provider_rustcrypto.workspace = true
+derive_fuzztest.workspace = true
+ldt_tbc.workspace = true
+xts_aes.workspace = true
-[dependencies.xts_aes]
-path = ".."
-
-[dependencies.crypto_provider]
-path = "../../../crypto/crypto_provider"
-
-[dependencies.crypto_provider_rustcrypto]
-path = "../../../crypto/crypto_provider_rustcrypto"
-
-[dependencies.ldt_tbc]
-path = "../../../presence/ldt_tbc"
-
-# Prevent this from interfering with workspaces
-[workspace]
-members = ["."]
+[target.'cfg(fuzzing)'.dependencies]
+libfuzzer-sys.workspace = true
[[bin]]
-name = "xts-roundtrip"
-path = "fuzz_targets/xts_roundtrip.rs"
-test = false
+name = "xts_roundtrip"
+path = "src/bin/xts_roundtrip.rs"
doc = false
diff --git a/nearby/presence/xts_aes/fuzz/fuzz_targets/xts_roundtrip.rs b/nearby/presence/xts_aes/fuzz/src/bin/xts_roundtrip.rs
index b7133de..f135c3b 100644
--- a/nearby/presence/xts_aes/fuzz/fuzz_targets/xts_roundtrip.rs
+++ b/nearby/presence/xts_aes/fuzz/src/bin/xts_roundtrip.rs
@@ -1,4 +1,4 @@
-#![no_main]
+#![cfg_attr(fuzzing, no_main)]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,11 +14,12 @@
// limitations under the License.
use crypto_provider_rustcrypto::RustCrypto;
+use derive_fuzztest::fuzztest;
use ldt_tbc::{TweakableBlockCipherDecrypter, TweakableBlockCipherEncrypter};
-use libfuzzer_sys::fuzz_target;
use xts_aes::*;
-fuzz_target!(|data: XtsFuzzInput| {
+#[fuzztest]
+fn test(data: XtsFuzzInput) {
// XTS requires at least one block
if data.plaintext.len() < 16 {
return;
@@ -37,14 +38,12 @@ fuzz_target!(|data: XtsFuzzInput| {
let mut buffer = data.plaintext.clone();
- xts_enc
- .encrypt_data_unit(tweak.clone(), &mut buffer[..])
- .unwrap();
+ xts_enc.encrypt_data_unit(tweak.clone(), &mut buffer[..]).unwrap();
xts_dec.decrypt_data_unit(tweak, &mut buffer[..]).unwrap();
assert_eq!(data.plaintext, buffer);
-});
+}
-#[derive(Debug, arbitrary::Arbitrary)]
+#[derive(Clone, Debug, arbitrary::Arbitrary)]
struct XtsFuzzInput {
key: [u8; 32],
tweak: [u8; 16],
diff --git a/nearby/presence/xts_aes/tests/compare_with_xts_mode_test.rs b/nearby/presence/xts_aes/tests/compare_with_xts_mode_test.rs
index abe1077..10b8c7d 100644
--- a/nearby/presence/xts_aes/tests/compare_with_xts_mode_test.rs
+++ b/nearby/presence/xts_aes/tests/compare_with_xts_mode_test.rs
@@ -15,16 +15,14 @@
#![allow(clippy::unwrap_used)]
use aes::{cipher, cipher::KeyInit as _};
-use alloc::vec::Vec;
use crypto_provider::aes::*;
use crypto_provider::CryptoProvider;
use crypto_provider_default::CryptoProviderImpl;
use ldt_tbc::TweakableBlockCipherDecrypter;
use ldt_tbc::TweakableBlockCipherEncrypter;
-use rand::{self, distributions, Rng as _};
+use rand::{distributions, Rng as _};
use rand_ext::seeded_rng;
use xts_aes::{Tweak, XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
-extern crate alloc;
#[test]
fn identical_to_xtsmode_crate() {
diff --git a/nearby/presence/xts_aes/tests/wycheproof_test_vectors.rs b/nearby/presence/xts_aes/tests/wycheproof_test_vectors.rs
index 1f92f89..ede231d 100644
--- a/nearby/presence/xts_aes/tests/wycheproof_test_vectors.rs
+++ b/nearby/presence/xts_aes/tests/wycheproof_test_vectors.rs
@@ -20,7 +20,7 @@ use ldt_tbc::TweakableBlockCipherDecrypter;
use ldt_tbc::TweakableBlockCipherEncrypter;
use ldt_tbc::TweakableBlockCipherKey;
use wycheproof::cipher::TestGroup;
-use xts_aes::{self, XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
+use xts_aes::{XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
#[test]
fn run_wycheproof_vectors() {
diff --git a/nearby/presence/xts_aes/tests/xts_nist_test_vectors.rs b/nearby/presence/xts_aes/tests/xts_nist_test_vectors.rs
index 6ceb8b9..6661e96 100644
--- a/nearby/presence/xts_aes/tests/xts_nist_test_vectors.rs
+++ b/nearby/presence/xts_aes/tests/xts_nist_test_vectors.rs
@@ -21,7 +21,7 @@ use ldt_tbc::TweakableBlockCipherDecrypter;
use ldt_tbc::TweakableBlockCipherEncrypter;
use ldt_tbc::TweakableBlockCipherKey;
use std::{collections::hash_map, fs, io, io::BufRead as _};
-use xts_aes::{self, XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
+use xts_aes::{XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
#[test]
fn nist_test_vectors_data_unit_seq_128() -> Result<(), anyhow::Error> {
diff --git a/nearby/presence/xts_aes/tests/xts_roundtrip_tests.rs b/nearby/presence/xts_aes/tests/xts_roundtrip_tests.rs
index 924b665..ab967dc 100644
--- a/nearby/presence/xts_aes/tests/xts_roundtrip_tests.rs
+++ b/nearby/presence/xts_aes/tests/xts_roundtrip_tests.rs
@@ -14,16 +14,14 @@
#![allow(clippy::unwrap_used)]
-use alloc::vec::Vec;
use crypto_provider::aes::*;
use crypto_provider::CryptoProvider;
use crypto_provider_default::CryptoProviderImpl;
use ldt_tbc::TweakableBlockCipherDecrypter;
use ldt_tbc::TweakableBlockCipherEncrypter;
-use rand::{self, distributions, Rng as _};
+use rand::{distributions, Rng as _};
use rand_ext::seeded_rng;
use xts_aes::{Tweak, XtsAes128Key, XtsAes256Key, XtsDecrypter, XtsEncrypter, XtsKey};
-extern crate alloc;
#[test]
fn roundtrip_self() {
diff --git a/nearby/scripts/openssl-patches/0001-Apply-android-patches.patch b/nearby/scripts/openssl-patches/0001-Apply-android-patches.patch
deleted file mode 100644
index 0ee52b1..0000000
--- a/nearby/scripts/openssl-patches/0001-Apply-android-patches.patch
+++ /dev/null
@@ -1,1017 +0,0 @@
-From 5c9103f02cb56f0f04444b16dd67eeaa05429d47 Mon Sep 17 00:00:00 2001
-From: Nabil Wadih <nwadih@google.com>
-Date: Thu, 24 Aug 2023 15:51:26 -0700
-Subject: [PATCH] Apply android patches
-
----
- openssl/.cargo/config.toml | 2 +
- openssl/src/asn1.rs | 2 +-
- openssl/src/bio.rs | 6 +-
- openssl/src/bn.rs | 2 +-
- openssl/src/cipher.rs | 4 +
- openssl/src/dh.rs | 2 +-
- openssl/src/dsa.rs | 5 +-
- openssl/src/ec.rs | 20 ++++
- openssl/src/ecdsa.rs | 2 +-
- openssl/src/encrypt.rs | 4 +-
- openssl/src/hash.rs | 2 +-
- openssl/src/hkdf.rs | 89 +++++++++++++++
- openssl/src/hmac.rs | 217 +++++++++++++++++++++++++++++++++++++
- openssl/src/lib.rs | 12 ++
- openssl/src/md_ctx.rs | 2 +-
- openssl/src/pkey.rs | 22 ++--
- openssl/src/pkey_ctx.rs | 21 +++-
- openssl/src/rsa.rs | 2 +-
- openssl/src/sign.rs | 10 +-
- openssl/src/symm.rs | 7 +-
- openssl/src/x509/mod.rs | 52 +++++++--
- 21 files changed, 439 insertions(+), 46 deletions(-)
- create mode 100644 openssl/.cargo/config.toml
- create mode 100644 openssl/src/hkdf.rs
- create mode 100644 openssl/src/hmac.rs
-
-diff --git a/openssl/.cargo/config.toml b/openssl/.cargo/config.toml
-new file mode 100644
-index 00000000..e2b197d8
---- /dev/null
-+++ b/openssl/.cargo/config.toml
-@@ -0,0 +1,2 @@
-+[patch.crates-io]
-+bssl-ffi = { package = "bssl-sys", version = "0.1.0", path = "../../../boringssl/build/rust", optional=true }
-diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs
-index b02f9ac4..939a1732 100644
---- a/openssl/src/asn1.rs
-+++ b/openssl/src/asn1.rs
-@@ -651,7 +651,7 @@ impl fmt::Debug for Asn1ObjectRef {
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl273))] {
-+ if #[cfg(any(ossl110, libressl273, boringssl))] {
- use ffi::ASN1_STRING_get0_data;
- } else {
- #[allow(bad_style)]
-diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs
-index 6a72552a..03242188 100644
---- a/openssl/src/bio.rs
-+++ b/openssl/src/bio.rs
-@@ -4,7 +4,7 @@ use std::marker::PhantomData;
- use std::ptr;
- use std::slice;
-
--use crate::cvt_p;
-+use crate::{cvt_p, SignedLenType};
- use crate::error::ErrorStack;
-
- pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
-@@ -25,7 +25,7 @@ impl<'a> MemBioSlice<'a> {
- let bio = unsafe {
- cvt_p(BIO_new_mem_buf(
- buf.as_ptr() as *const _,
-- buf.len() as c_int,
-+ buf.len() as SignedLenType,
- ))?
- };
-
-@@ -78,7 +78,7 @@ cfg_if! {
- use ffi::BIO_new_mem_buf;
- } else {
- #[allow(bad_style)]
-- unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO {
-+ unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: SignedLenType) -> *mut ffi::BIO {
- ffi::BIO_new_mem_buf(buf as *mut _, len)
- }
- }
-diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs
-index 1cd00dd4..dbd7ae94 100644
---- a/openssl/src/bn.rs
-+++ b/openssl/src/bn.rs
-@@ -814,7 +814,7 @@ impl BigNumRef {
- /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
- /// ```
- #[corresponds(BN_bn2binpad)]
-- #[cfg(ossl110)]
-+ #[cfg(any(boringssl, ossl110))]
- pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
- let mut v = Vec::with_capacity(pad_to as usize);
- unsafe {
-diff --git a/openssl/src/cipher.rs b/openssl/src/cipher.rs
-index ab5f49d2..84a82654 100644
---- a/openssl/src/cipher.rs
-+++ b/openssl/src/cipher.rs
-@@ -208,6 +208,7 @@ impl Cipher {
- unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
- }
-
-+ #[cfg(not(boringssl))]
- pub fn aes_192_cfb128() -> &'static CipherRef {
- unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
- }
-@@ -253,6 +254,7 @@ impl Cipher {
- unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
- }
-
-+ #[cfg(not(boringssl))]
- pub fn aes_256_cfb128() -> &'static CipherRef {
- unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
- }
-@@ -282,11 +284,13 @@ impl Cipher {
- }
-
- #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
-+ #[cfg(not(boringssl))]
- pub fn bf_cbc() -> &'static CipherRef {
- unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
- }
-
- #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
-+ #[cfg(not(boringssl))]
- pub fn bf_ecb() -> &'static CipherRef {
- unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
- }
-diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs
-index 12170b99..e781543e 100644
---- a/openssl/src/dh.rs
-+++ b/openssl/src/dh.rs
-@@ -239,7 +239,7 @@ where
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl270))] {
-+ if #[cfg(any(ossl110, libressl270, boringssl))] {
- use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
- } else {
- #[allow(bad_style)]
-diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs
-index 5f59ba8a..0aceeb55 100644
---- a/openssl/src/dsa.rs
-+++ b/openssl/src/dsa.rs
-@@ -7,6 +7,7 @@
-
- use cfg_if::cfg_if;
- use foreign_types::{ForeignType, ForeignTypeRef};
-+#[cfg(not(boringssl))]
- use libc::c_int;
- use std::fmt;
- use std::mem;
-@@ -283,7 +284,7 @@ impl<T> fmt::Debug for Dsa<T> {
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl273))] {
-+ if #[cfg(any(ossl110, libressl273, boringssl))] {
- use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
- } else {
- #[allow(bad_style)]
-@@ -462,7 +463,7 @@ impl DsaSigRef {
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl273))] {
-+ if #[cfg(any(ossl110, libressl273, boringssl))] {
- use ffi::{DSA_SIG_set0, DSA_SIG_get0};
- } else {
- #[allow(bad_style)]
-diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs
-index 24b38322..20785428 100644
---- a/openssl/src/ec.rs
-+++ b/openssl/src/ec.rs
-@@ -954,6 +954,26 @@ impl EcKey<Private> {
- EcKey<Private>,
- ffi::d2i_ECPrivateKey
- }
-+
-+ /// Decodes a DER-encoded elliptic curve private key structure for the specified curve.
-+ #[corresponds(EC_KEY_parse_private_key)]
-+ #[cfg(boringssl)]
-+ pub fn private_key_from_der_for_group(
-+ der: &[u8],
-+ group: &EcGroupRef,
-+ ) -> Result<EcKey<Private>, ErrorStack> {
-+ unsafe {
-+ let mut cbs = ffi::CBS {
-+ data: der.as_ptr(),
-+ len: der.len(),
-+ };
-+ cvt_p(ffi::EC_KEY_parse_private_key(
-+ &mut cbs as *mut ffi::CBS,
-+ group.as_ptr(),
-+ ))
-+ .map(|p| EcKey::from_ptr(p))
-+ }
-+ }
- }
-
- impl<T> Clone for EcKey<T> {
-diff --git a/openssl/src/ecdsa.rs b/openssl/src/ecdsa.rs
-index 0a960e7b..f3b27b39 100644
---- a/openssl/src/ecdsa.rs
-+++ b/openssl/src/ecdsa.rs
-@@ -110,7 +110,7 @@ impl EcdsaSigRef {
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl273))] {
-+ if #[cfg(any(ossl110, libressl273, boringssl))] {
- use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
- } else {
- #[allow(bad_style)]
-diff --git a/openssl/src/encrypt.rs b/openssl/src/encrypt.rs
-index 3cb10fcc..34a9eb8b 100644
---- a/openssl/src/encrypt.rs
-+++ b/openssl/src/encrypt.rs
-@@ -148,7 +148,7 @@ impl<'a> Encrypter<'a> {
- /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
- ///
- /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
-- #[cfg(any(ossl102, libressl310))]
-+ #[cfg(any(ossl102, libressl310, boringssl))]
- pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
- unsafe {
- cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
-@@ -352,7 +352,7 @@ impl<'a> Decrypter<'a> {
- /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
- ///
- /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
-- #[cfg(any(ossl102, libressl310))]
-+ #[cfg(any(ossl102, libressl310, boringssl))]
- pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
- unsafe {
- cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
-diff --git a/openssl/src/hash.rs b/openssl/src/hash.rs
-index 8e27505a..7f6fa89e 100644
---- a/openssl/src/hash.rs
-+++ b/openssl/src/hash.rs
-@@ -43,7 +43,7 @@ use crate::nid::Nid;
- use crate::{cvt, cvt_p};
-
- cfg_if! {
-- if #[cfg(ossl110)] {
-+ if #[cfg(any(ossl110, boringssl))] {
- use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
- } else {
- use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
-diff --git a/openssl/src/hkdf.rs b/openssl/src/hkdf.rs
-new file mode 100644
-index 00000000..cc7e5b3a
---- /dev/null
-+++ b/openssl/src/hkdf.rs
-@@ -0,0 +1,89 @@
-+use crate::cvt;
-+use crate::error::ErrorStack;
-+use crate::md::MdRef;
-+use foreign_types::ForeignTypeRef;
-+use openssl_macros::corresponds;
-+
-+/// Computes HKDF (as specified by RFC 5869).
-+///
-+/// HKDF is an Extract-and-Expand algorithm. It does not do any key stretching,
-+/// and as such, is not suited to be used alone to generate a key from a
-+/// password.
-+#[corresponds(HKDF)]
-+#[inline]
-+pub fn hkdf(
-+ out_key: &mut [u8],
-+ md: &MdRef,
-+ secret: &[u8],
-+ salt: &[u8],
-+ info: &[u8],
-+) -> Result<(), ErrorStack> {
-+ unsafe {
-+ cvt(ffi::HKDF(
-+ out_key.as_mut_ptr(),
-+ out_key.len(),
-+ md.as_ptr(),
-+ secret.as_ptr(),
-+ secret.len(),
-+ salt.as_ptr(),
-+ salt.len(),
-+ info.as_ptr(),
-+ info.len(),
-+ ))?;
-+ }
-+
-+ Ok(())
-+}
-+
-+/// Computes a HKDF PRK (as specified by RFC 5869).
-+///
-+/// WARNING: This function orders the inputs differently from RFC 5869
-+/// specification. Double-check which parameter is the secret/IKM and which is
-+/// the salt when using.
-+#[corresponds(HKDF_extract)]
-+#[inline]
-+pub fn hkdf_extract<'a>(
-+ out_key: &'a mut [u8],
-+ md: &MdRef,
-+ secret: &[u8],
-+ salt: &[u8],
-+) -> Result<&'a [u8], ErrorStack> {
-+ let mut out_len = out_key.len();
-+ unsafe {
-+ cvt(ffi::HKDF_extract(
-+ out_key.as_mut_ptr(),
-+ &mut out_len,
-+ md.as_ptr(),
-+ secret.as_ptr(),
-+ secret.len(),
-+ salt.as_ptr(),
-+ salt.len(),
-+ ))?;
-+ }
-+
-+ Ok(&out_key[..out_len])
-+}
-+
-+/// Computes a HKDF OKM (as specified by RFC 5869).
-+#[corresponds(HKDF_expand)]
-+#[inline]
-+pub fn hkdf_expand(
-+ out_key: &mut [u8],
-+ md: &MdRef,
-+ prk: &[u8],
-+ info: &[u8],
-+) -> Result<(), ErrorStack> {
-+ unsafe {
-+ cvt(ffi::HKDF_expand(
-+ out_key.as_mut_ptr(),
-+ out_key.len(),
-+ md.as_ptr(),
-+ prk.as_ptr(),
-+ prk.len(),
-+ info.as_ptr(),
-+ info.len(),
-+ ))?;
-+ }
-+
-+ Ok(())
-+}
-diff --git a/openssl/src/hmac.rs b/openssl/src/hmac.rs
-new file mode 100644
-index 00000000..465781e2
---- /dev/null
-+++ b/openssl/src/hmac.rs
-@@ -0,0 +1,217 @@
-+use crate::error::ErrorStack;
-+use crate::md::MdRef;
-+use crate::{cvt, cvt_p};
-+use ffi::HMAC_CTX;
-+use foreign_types::ForeignTypeRef;
-+use libc::{c_uint, c_void};
-+use openssl_macros::corresponds;
-+use std::convert::TryFrom;
-+use std::ptr;
-+
-+/// Computes the HMAC as a one-shot operation.
-+///
-+/// Calculates the HMAC of data, using the given |key|
-+/// and hash function |md|, and returns the result re-using the space from
-+/// buffer |out|. On entry, |out| must contain at least |EVP_MD_size| bytes
-+/// of space. The actual length of the result is used to resize the returned
-+/// slice. An output size of |EVP_MAX_MD_SIZE| will always be large enough.
-+/// It returns a resized |out| or ErrorStack on error.
-+#[corresponds(HMAC)]
-+#[inline]
-+pub fn hmac<'a>(
-+ md: &MdRef,
-+ key: &[u8],
-+ data: &[u8],
-+ out: &'a mut [u8],
-+) -> Result<&'a [u8], ErrorStack> {
-+ assert!(out.len() >= md.size());
-+ let mut out_len = c_uint::try_from(out.len()).unwrap();
-+ unsafe {
-+ cvt_p(ffi::HMAC(
-+ md.as_ptr(),
-+ key.as_ptr() as *const c_void,
-+ key.len(),
-+ data.as_ptr(),
-+ data.len(),
-+ out.as_mut_ptr(),
-+ &mut out_len,
-+ ))?;
-+ }
-+ Ok(&out[..out_len as usize])
-+}
-+
-+/// A context object used to perform HMAC operations.
-+///
-+/// HMAC is a MAC (message authentication code), i.e. a keyed hash function used for message
-+/// authentication, which is based on a hash function.
-+///
-+/// Note: Only available in boringssl. For openssl, use `PKey::hmac` instead.
-+#[cfg(boringssl)]
-+pub struct HmacCtx {
-+ ctx: *mut HMAC_CTX,
-+ output_size: usize,
-+}
-+
-+#[cfg(boringssl)]
-+impl HmacCtx {
-+ /// Creates a new [HmacCtx] to use the hash function `md` and key `key`.
-+ #[corresponds(HMAC_Init_ex)]
-+ pub fn new(key: &[u8], md: &MdRef) -> Result<Self, ErrorStack> {
-+ unsafe {
-+ // Safety: If an error occurred, the resulting null from HMAC_CTX_new is converted into
-+ // ErrorStack in the returned result by `cvt_p`.
-+ let ctx = cvt_p(ffi::HMAC_CTX_new())?;
-+ // Safety:
-+ // - HMAC_Init_ex must be called with a context previously created with HMAC_CTX_new,
-+ // which is the line above.
-+ // - HMAC_Init_ex may return an error if key is null but the md is different from
-+ // before. This is avoided here since key is guaranteed to be non-null.
-+ cvt(ffi::HMAC_Init_ex(
-+ ctx,
-+ key.as_ptr() as *const c_void,
-+ key.len(),
-+ md.as_ptr(),
-+ ptr::null_mut(),
-+ ))?;
-+ Ok(Self {
-+ ctx,
-+ output_size: md.size(),
-+ })
-+ }
-+ }
-+
-+ /// `update` can be called repeatedly with chunks of the message `data` to be authenticated.
-+ #[corresponds(HMAC_Update)]
-+ pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
-+ unsafe {
-+ // Safety: HMAC_Update returns 0 on error, and that is converted into ErrorStack in the
-+ // returned result by `cvt`.
-+ cvt(ffi::HMAC_Update(self.ctx, data.as_ptr(), data.len())).map(|_| ())
-+ }
-+ }
-+
-+ /// Finishes the HMAC process, and places the message authentication code in `output`.
-+ /// The number of bytes written to `output` is returned.
-+ ///
-+ /// # Panics
-+ ///
-+ /// Panics if the `output` is smaller than the required size. The output size is indicated by
-+ /// `md.size()` for the `Md` instance passed in [new]. An output size of |EVP_MAX_MD_SIZE| will
-+ /// always be large enough.
-+ #[corresponds(HMAC_Final)]
-+ pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
-+ assert!(output.len() >= self.output_size);
-+ unsafe {
-+ // Safety: The length assertion above makes sure that `HMAC_Final` will not write longer
-+ // than the length of `output`.
-+ let mut size: c_uint = 0;
-+ cvt(ffi::HMAC_Final(
-+ self.ctx,
-+ output.as_mut_ptr(),
-+ &mut size as *mut c_uint,
-+ ))
-+ .map(|_| size as usize)
-+ }
-+ }
-+}
-+
-+impl Drop for HmacCtx {
-+ #[corresponds(HMAC_CTX_free)]
-+ fn drop(&mut self) {
-+ unsafe {
-+ ffi::HMAC_CTX_free(self.ctx);
-+ }
-+ }
-+}
-+
-+#[cfg(test)]
-+mod tests {
-+ use super::*;
-+ use crate::md::Md;
-+
-+ const SHA_256_DIGEST_SIZE: usize = 32;
-+
-+ #[test]
-+ fn hmac_sha256_test() {
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
-+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let data = b"Hi There";
-+ let hmac_result =
-+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ assert_eq!(&hmac_result, &expected_hmac);
-+ }
-+
-+ #[test]
-+ #[should_panic]
-+ fn hmac_sha256_output_too_short() {
-+ let mut out = vec![0_u8; 1];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let data = b"Hi There";
-+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ }
-+
-+ #[test]
-+ fn hmac_sha256_test_big_buffer() {
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
-+ let mut out: [u8; 100] = [0; 100];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let data = b"Hi There";
-+ let hmac_result =
-+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ assert_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-+ assert_eq!(&hmac_result, &expected_hmac);
-+ }
-+
-+ #[test]
-+ fn hmac_sha256_update_test() {
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
-+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let data = b"Hi There";
-+ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
-+ hmac_ctx.update(data).unwrap();
-+ let size = hmac_ctx.finalize(&mut out).unwrap();
-+ assert_eq!(&out, &expected_hmac);
-+ assert_eq!(size, SHA_256_DIGEST_SIZE);
-+ }
-+
-+ #[test]
-+ fn hmac_sha256_update_chunks_test() {
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
-+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
-+ hmac_ctx.update(b"Hi").unwrap();
-+ hmac_ctx.update(b" There").unwrap();
-+ let size = hmac_ctx.finalize(&mut out).unwrap();
-+ assert_eq!(&out, &expected_hmac);
-+ assert_eq!(size, SHA_256_DIGEST_SIZE);
-+ }
-+
-+ #[test]
-+ #[should_panic]
-+ fn hmac_sha256_update_output_too_short() {
-+ let mut out = vec![0_u8; 1];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
-+ hmac_ctx.update(b"Hi There").unwrap();
-+ hmac_ctx.finalize(&mut out).unwrap();
-+ }
-+}
-diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs
-index 891651ec..e8d07d8a 100644
---- a/openssl/src/lib.rs
-+++ b/openssl/src/lib.rs
-@@ -120,6 +120,9 @@
- #![doc(html_root_url = "https://docs.rs/openssl/0.10")]
- #![warn(rust_2018_idioms)]
-
-+#[cfg(all(soong, boringssl))]
-+extern crate bssl_ffi as ffi;
-+
- #[doc(inline)]
- pub use ffi::init;
-
-@@ -155,6 +158,10 @@ pub mod ex_data;
- #[cfg(not(any(libressl, ossl300)))]
- pub mod fips;
- pub mod hash;
-+#[cfg(boringssl)]
-+pub mod hkdf;
-+#[cfg(boringssl)]
-+pub mod hmac;
- #[cfg(ossl300)]
- pub mod lib_ctx;
- pub mod md;
-@@ -189,6 +196,11 @@ type LenType = libc::size_t;
- #[cfg(not(boringssl))]
- type LenType = libc::c_int;
-
-+#[cfg(boringssl)]
-+type SignedLenType = libc::ssize_t;
-+#[cfg(not(boringssl))]
-+type SignedLenType = libc::c_int;
-+
- #[inline]
- fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
- if r.is_null() {
-diff --git a/openssl/src/md_ctx.rs b/openssl/src/md_ctx.rs
-index c4d3f06b..156f3c2f 100644
---- a/openssl/src/md_ctx.rs
-+++ b/openssl/src/md_ctx.rs
-@@ -93,7 +93,7 @@ use std::convert::TryFrom;
- use std::ptr;
-
- cfg_if! {
-- if #[cfg(ossl110)] {
-+ if #[cfg(any(ossl110, boringssl))] {
- use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
- } else {
- use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
-diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs
-index 2039e7e9..21ba7118 100644
---- a/openssl/src/pkey.rs
-+++ b/openssl/src/pkey.rs
-@@ -47,7 +47,7 @@ use crate::dh::Dh;
- use crate::dsa::Dsa;
- use crate::ec::EcKey;
- use crate::error::ErrorStack;
--#[cfg(ossl110)]
-+#[cfg(any(boringssl, ossl110))]
- use crate::pkey_ctx::PkeyCtx;
- use crate::rsa::Rsa;
- use crate::symm::Cipher;
-@@ -86,14 +86,14 @@ impl Id {
- pub const DH: Id = Id(ffi::EVP_PKEY_DH);
- pub const EC: Id = Id(ffi::EVP_PKEY_EC);
-
-- #[cfg(ossl110)]
-+ #[cfg(any(boringssl, ossl110))]
- pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
-
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
- #[cfg(ossl111)]
- pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
- #[cfg(ossl111)]
- pub const X448: Id = Id(ffi::EVP_PKEY_X448);
-@@ -252,7 +252,7 @@ where
- /// This function only works for algorithms that support raw public keys.
- /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
- #[corresponds(EVP_PKEY_get_raw_public_key)]
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> {
- unsafe {
- let mut len = 0;
-@@ -303,7 +303,7 @@ where
- /// This function only works for algorithms that support raw private keys.
- /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`].
- #[corresponds(EVP_PKEY_get_raw_private_key)]
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> {
- unsafe {
- let mut len = 0;
-@@ -484,7 +484,7 @@ impl PKey<Private> {
- ctx.keygen()
- }
-
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> {
- let mut ctx = PkeyCtx::new_id(id)?;
- ctx.keygen_init()?;
-@@ -514,7 +514,7 @@ impl PKey<Private> {
- /// assert_eq!(secret.len(), 32);
- /// # Ok(()) }
- /// ```
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> {
- PKey::generate_eddsa(Id::X25519)
- }
-@@ -568,7 +568,7 @@ impl PKey<Private> {
- /// assert_eq!(signature.len(), 64);
- /// # Ok(()) }
- /// ```
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> {
- PKey::generate_eddsa(Id::ED25519)
- }
-@@ -718,7 +718,7 @@ impl PKey<Private> {
- ///
- /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
- #[corresponds(EVP_PKEY_new_raw_private_key)]
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn private_key_from_raw_bytes(
- bytes: &[u8],
- key_type: Id,
-@@ -759,7 +759,7 @@ impl PKey<Public> {
- ///
- /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
- #[corresponds(EVP_PKEY_new_raw_public_key)]
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn public_key_from_raw_bytes(
- bytes: &[u8],
- key_type: Id,
-diff --git a/openssl/src/pkey_ctx.rs b/openssl/src/pkey_ctx.rs
-index f79372fb..3d4203fa 100644
---- a/openssl/src/pkey_ctx.rs
-+++ b/openssl/src/pkey_ctx.rs
-@@ -470,7 +470,7 @@ impl<T> PkeyCtxRef<T> {
- ///
- /// Requires OpenSSL 1.1.0 or newer.
- #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
-- #[cfg(ossl110)]
-+ #[cfg(any(ossl110, boringssl))]
- #[inline]
- pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
- unsafe {
-@@ -503,10 +503,13 @@ impl<T> PkeyCtxRef<T> {
- ///
- /// Requires OpenSSL 1.1.0 or newer.
- #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
-- #[cfg(ossl110)]
-+ #[cfg(any(ossl110, boringssl))]
- #[inline]
- pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
-+ #[cfg(not(boringssl))]
- let len = c_int::try_from(key.len()).unwrap();
-+ #[cfg(boringssl)]
-+ let len = key.len();
-
- unsafe {
- cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
-@@ -523,10 +526,13 @@ impl<T> PkeyCtxRef<T> {
- ///
- /// Requires OpenSSL 1.1.0 or newer.
- #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
-- #[cfg(ossl110)]
-+ #[cfg(any(ossl110, boringssl))]
- #[inline]
- pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
-+ #[cfg(not(boringssl))]
- let len = c_int::try_from(salt.len()).unwrap();
-+ #[cfg(boringssl)]
-+ let len = salt.len();
-
- unsafe {
- cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
-@@ -543,10 +549,13 @@ impl<T> PkeyCtxRef<T> {
- ///
- /// Requires OpenSSL 1.1.0 or newer.
- #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
-- #[cfg(ossl110)]
-+ #[cfg(any(ossl110, boringssl))]
- #[inline]
- pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
-+ #[cfg(not(boringssl))]
- let len = c_int::try_from(info.len()).unwrap();
-+ #[cfg(boringssl)]
-+ let len = info.len();
-
- unsafe {
- cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
-@@ -604,7 +613,7 @@ mod test {
- #[cfg(not(boringssl))]
- use crate::cipher::Cipher;
- use crate::ec::{EcGroup, EcKey};
-- #[cfg(any(ossl102, libressl310))]
-+ #[cfg(any(ossl102, libressl310, boringssl))]
- use crate::md::Md;
- use crate::nid::Nid;
- use crate::pkey::PKey;
-@@ -689,7 +698,7 @@ mod test {
- }
-
- #[test]
-- #[cfg(ossl110)]
-+ #[cfg(any(ossl110, boringssl))]
- fn hkdf() {
- let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
- ctx.derive_init().unwrap();
-diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs
-index 68cf64b0..f155b12d 100644
---- a/openssl/src/rsa.rs
-+++ b/openssl/src/rsa.rs
-@@ -581,7 +581,7 @@ impl<T> fmt::Debug for Rsa<T> {
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl273))] {
-+ if #[cfg(any(ossl110, libressl273, boringssl))] {
- use ffi::{
- RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
- RSA_set0_crt_params,
-diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs
-index b675825e..e5e80608 100644
---- a/openssl/src/sign.rs
-+++ b/openssl/src/sign.rs
-@@ -290,7 +290,7 @@ impl<'a> Signer<'a> {
- self.len_intern()
- }
-
-- #[cfg(not(ossl111))]
-+ #[cfg(not(any(boringssl, ossl111)))]
- fn len_intern(&self) -> Result<usize, ErrorStack> {
- unsafe {
- let mut len = 0;
-@@ -303,7 +303,7 @@ impl<'a> Signer<'a> {
- }
- }
-
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- fn len_intern(&self) -> Result<usize, ErrorStack> {
- unsafe {
- let mut len = 0;
-@@ -360,7 +360,7 @@ impl<'a> Signer<'a> {
- /// OpenSSL documentation at [`EVP_DigestSign`].
- ///
- /// [`EVP_DigestSign`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestSign.html
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn sign_oneshot(
- &mut self,
- sig_buf: &mut [u8],
-@@ -382,7 +382,7 @@ impl<'a> Signer<'a> {
- /// Returns the signature.
- ///
- /// This is a simple convenience wrapper over `len` and `sign_oneshot`.
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> {
- let mut sig_buf = vec![0; self.len()?];
- let len = self.sign_oneshot(&mut sig_buf, data_buf)?;
-@@ -596,7 +596,7 @@ impl<'a> Verifier<'a> {
- /// OpenSSL documentation at [`EVP_DigestVerify`].
- ///
- /// [`EVP_DigestVerify`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestVerify.html
-- #[cfg(ossl111)]
-+ #[cfg(any(boringssl, ossl111))]
- pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> {
- unsafe {
- let r = ffi::EVP_DigestVerify(
-diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs
-index c75bbc0c..beff5fc2 100644
---- a/openssl/src/symm.rs
-+++ b/openssl/src/symm.rs
-@@ -119,6 +119,7 @@ impl Cipher {
- unsafe { Cipher(ffi::EVP_aes_128_cfb1()) }
- }
-
-+ #[cfg(not(boringssl))]
- pub fn aes_128_cfb128() -> Cipher {
- unsafe { Cipher(ffi::EVP_aes_128_cfb128()) }
- }
-@@ -164,6 +165,7 @@ impl Cipher {
- unsafe { Cipher(ffi::EVP_aes_192_cfb1()) }
- }
-
-+ #[cfg(not(boringssl))]
- pub fn aes_192_cfb128() -> Cipher {
- unsafe { Cipher(ffi::EVP_aes_192_cfb128()) }
- }
-@@ -214,6 +216,7 @@ impl Cipher {
- unsafe { Cipher(ffi::EVP_aes_256_cfb1()) }
- }
-
-+ #[cfg(not(boringssl))]
- pub fn aes_256_cfb128() -> Cipher {
- unsafe { Cipher(ffi::EVP_aes_256_cfb128()) }
- }
-@@ -242,12 +245,12 @@ impl Cipher {
- unsafe { Cipher(ffi::EVP_aes_256_ocb()) }
- }
-
-- #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
-+ #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))]
- pub fn bf_cbc() -> Cipher {
- unsafe { Cipher(ffi::EVP_bf_cbc()) }
- }
-
-- #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
-+ #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))]
- pub fn bf_ecb() -> Cipher {
- unsafe { Cipher(ffi::EVP_bf_ecb()) }
- }
-diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
-index edd54aa8..a03a8aa6 100644
---- a/openssl/src/x509/mod.rs
-+++ b/openssl/src/x509/mod.rs
-@@ -353,6 +353,19 @@ impl X509Builder {
- unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
- }
-
-+ /// Signs the certificate with a private key but without a digest.
-+ ///
-+ /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
-+ /// message digest.
-+ #[cfg(boringssl)]
-+ #[corresponds(X509_sign)]
-+ pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
-+ where
-+ T: HasPrivate,
-+ {
-+ unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), ptr::null())).map(|_| ()) }
-+ }
-+
- /// Consumes the builder, returning the certificate.
- pub fn build(self) -> X509 {
- self.0
-@@ -880,13 +893,13 @@ impl X509NameBuilder {
- pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
- unsafe {
- let field = CString::new(field).unwrap();
-- assert!(value.len() <= c_int::max_value() as usize);
-+ assert!(value.len() <= isize::max_value() as usize);
- cvt(ffi::X509_NAME_add_entry_by_txt(
- self.0.as_ptr(),
- field.as_ptr() as *mut _,
- ffi::MBSTRING_UTF8,
- value.as_ptr(),
-- value.len() as c_int,
-+ value.len() as isize,
- -1,
- 0,
- ))
-@@ -907,13 +920,13 @@ impl X509NameBuilder {
- ) -> Result<(), ErrorStack> {
- unsafe {
- let field = CString::new(field).unwrap();
-- assert!(value.len() <= c_int::max_value() as usize);
-+ assert!(value.len() <= isize::max_value() as usize);
- cvt(ffi::X509_NAME_add_entry_by_txt(
- self.0.as_ptr(),
- field.as_ptr() as *mut _,
- ty.as_raw(),
- value.as_ptr(),
-- value.len() as c_int,
-+ value.len() as isize,
- -1,
- 0,
- ))
-@@ -928,13 +941,13 @@ impl X509NameBuilder {
- /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html
- pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
- unsafe {
-- assert!(value.len() <= c_int::max_value() as usize);
-+ assert!(value.len() <= isize::max_value() as usize);
- cvt(ffi::X509_NAME_add_entry_by_NID(
- self.0.as_ptr(),
- field.as_raw(),
- ffi::MBSTRING_UTF8,
- value.as_ptr() as *mut _,
-- value.len() as c_int,
-+ value.len() as isize,
- -1,
- 0,
- ))
-@@ -954,13 +967,13 @@ impl X509NameBuilder {
- ty: Asn1Type,
- ) -> Result<(), ErrorStack> {
- unsafe {
-- assert!(value.len() <= c_int::max_value() as usize);
-+ assert!(value.len() <= isize::max_value() as usize);
- cvt(ffi::X509_NAME_add_entry_by_NID(
- self.0.as_ptr(),
- field.as_raw(),
- ty.as_raw(),
- value.as_ptr() as *mut _,
-- value.len() as c_int,
-+ value.len() as isize,
- -1,
- 0,
- ))
-@@ -1260,6 +1273,29 @@ impl X509ReqBuilder {
- }
- }
-
-+ /// Sign the request using a private key without a digest.
-+ ///
-+ /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
-+ /// message digest.
-+ ///
-+ /// This corresponds to [`X509_REQ_sign`].
-+ ///
-+ /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html
-+ #[cfg(boringssl)]
-+ pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
-+ where
-+ T: HasPrivate,
-+ {
-+ unsafe {
-+ cvt(ffi::X509_REQ_sign(
-+ self.0.as_ptr(),
-+ key.as_ptr(),
-+ ptr::null(),
-+ ))
-+ .map(|_| ())
-+ }
-+ }
-+
- /// Returns the `X509Req`.
- pub fn build(self) -> X509Req {
- self.0
---
-2.42.0.rc2.253.gd59a3bf2b4-goog
-
diff --git a/nearby/scripts/openssl-patches/README.md b/nearby/scripts/openssl-patches/README.md
deleted file mode 100644
index ab1fcea..0000000
--- a/nearby/scripts/openssl-patches/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-This directory contains patch files for `rust-openssl` for it to build successfully with
-`--features=unstable_boringssl`.
-
-After running `prepare-rust-openssl`, the `rust-openssl` git repo is cloned to
-`beto-rust/boringssl-build/rust-openssl/openssl`, and the patches in this directory will be applied.
-
-If you make further changes, or update the "base commit" in `prepare-rust-openssl`, you can
-regenerate the patch files by following these steps:
-
-1. Run `cargo run -- prepare-rust-openssl`
-2. `cd boringssl-build/rust-openssl/` and make the necessary changes
-3. Commit the changes
-4. `git format-patch BASE_COMMIT`. (Note: `BASE_COMMIT` is set by `prepare-rust-openssl`)
-5. The patch files will be generated in the current working directory. Move them here in
- `nearby/scripts/openssl-patches`.
-
-### Regenerate patches based on AOSP changes
-
-In the "make the necessary changes" part in Step 2 above, follow these steps:
-
-1. Download the patch files in https://googleplex-android.googlesource.com/platform/external/rust/crates/openssl/+/master/patches
-2. `cd` into the openssl directory since the AOSP project starts at that root:
- ```sh
- $ cd openssl
- ```
-3. Reset your branch to `BASE_COMMIT` to ensure the AOSP patches apply cleanly.
- ```sh
- $ git co BASE_COMMIT
- $ git co -b create-patch
- ```
-4. Apply the patches from AOSP
- ```sh
- for i in /path/to/android/external/rust/crates/openssl/patches/*; do patch -p1 < $i; done
- ```
-5. Remove unneeded files (like `.orig`). Commit the changes.
-6. Patches locally in `scripts/openssl-patches` but not in AOSP are lost in this process. Reapply
- the appropriate ones at this point, using `git apply` or `git am`.
-7. Continue with `git format-patch` described in step 4 in the previous section.
diff --git a/nearby/src/coverage.rs b/nearby/src/coverage.rs
new file mode 100644
index 0000000..329e11c
--- /dev/null
+++ b/nearby/src/coverage.rs
@@ -0,0 +1,14 @@
+// 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.
+
diff --git a/nearby/src/crypto_ffi.rs b/nearby/src/crypto_ffi.rs
index 20d1d5d..b1e08e9 100644
--- a/nearby/src/crypto_ffi.rs
+++ b/nearby/src/crypto_ffi.rs
@@ -14,23 +14,13 @@
use anyhow::anyhow;
use cmd_runner::{run_cmd_shell, run_cmd_shell_with_color, YellowStderr};
-use owo_colors::OwoColorize as _;
use semver::{Version, VersionReq};
-use std::{
- env, fs,
- path::{Path, PathBuf},
-};
+use std::{env, fs, path::Path};
use crate::CargoOptions;
-pub fn boringssl_check_everything(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
- check_boringssl(root, cargo_options)?;
- check_openssl(root, cargo_options)?;
- Ok(())
-}
-
pub fn build_boringssl(root: &Path) -> anyhow::Result<()> {
- let bindgen_version_req = VersionReq::parse(">=0.61.0")?;
+ let bindgen_version_req = VersionReq::parse(">=0.69.4")?;
let bindgen_version = get_bindgen_version()?;
if !bindgen_version_req.matches(&bindgen_version) {
@@ -82,91 +72,45 @@ pub fn check_boringssl(root: &Path, cargo_options: &CargoOptions) -> anyhow::Res
run_cmd_shell(&bssl_dir, format!("cargo check {locked_arg}"))?;
run_cmd_shell(&bssl_dir, "cargo fmt --check")?;
run_cmd_shell(&bssl_dir, "cargo clippy --all-targets")?;
- run_cmd_shell(&bssl_dir, format!("cargo test {locked_arg} -- --color=always"))?;
+ run_cmd_shell(&bssl_dir, cargo_options.test("check_boringssl", ""))?;
run_cmd_shell(&bssl_dir, "cargo doc --no-deps")?;
-
- run_cmd_shell(root, "cargo test -p ukey2_connections -p ukey2_rs --no-default-features --features test_boringssl")?;
-
- Ok(())
-}
-
-pub fn prepare_patched_rust_openssl(root: &Path) -> anyhow::Result<()> {
- let mut vendor_dir =
- root.parent().ok_or_else(|| anyhow!("project root dir no parent dir"))?.to_path_buf();
- vendor_dir.push("boringssl-build");
- fs::create_dir_all(&vendor_dir)?;
-
- let repo_dir = clone_repo_if_needed(
- &vendor_dir,
- "rust-openssl",
- "https://github.com/sfackler/rust-openssl.git",
- )?;
-
- run_cmd_shell_with_color::<YellowStderr>(
- &repo_dir,
- "git checkout 7df56869c5e1e32369091ab106750d644d3aa0c4",
- )?;
- run_cmd_shell_with_color::<YellowStderr>(&repo_dir, "git branch -f BASE_COMMIT")?;
- run_cmd_shell_with_color::<YellowStderr>(
- &repo_dir,
- format!(
- "git am {}/scripts/openssl-patches/*.patch",
- root.to_str().ok_or_else(|| anyhow!("root dir is not UTF-8"))?
+ run_cmd_shell(
+ root,
+ cargo_options.test(
+ "check_boringssl_ukey2",
+ "-p ukey2_connections -p ukey2_rs --no-default-features --features test_boringssl",
),
)?;
+ Ok(())
+}
- println!("{}", "Preparation complete. The required repositories are downloaded to `beto-rust/boringssl-build`. If
-you need to go back to a clean state, you can remove that directory and rerun this script.
-
-You can now build and test with boringssl using the following command
- `cargo --config .cargo/config-boringssl.toml test -p crypto_provider* --features=boringssl,std`
-".cyan());
+/// Checks out latest boringssl commit and runs our crypto provider tests against it
+pub fn check_boringssl_at_head(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
+ // TODO: find a better way, a kokoro implemented auto-roller?
+ build_boringssl_at_latest(root)?;
+ let bssl_dir = root.join("crypto/crypto_provider_boringssl");
+ run_cmd_shell(&bssl_dir, "cargo check")?;
+ run_cmd_shell(&bssl_dir, cargo_options.test("check_boringssl_latest", ""))?;
Ok(())
}
-pub fn check_openssl(root: &Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
- log::info!("Checking rust openssl");
- prepare_patched_rust_openssl(root)?;
- let locked_arg = if cargo_options.locked { "--locked" } else { "" };
-
- // test the openssl crate with the boringssl feature
+fn build_boringssl_at_latest(root: &Path) -> anyhow::Result<()> {
+ // Now check boringssl against HEAD. Kokoro does not allow us to directly update the git submodule
+ // so we must use manual hackery instead :/
+ run_cmd_shell(root.parent().unwrap(), "rm -Rf third_party/boringssl")?;
run_cmd_shell(
- root,
- format!(
- concat!(
- "cargo --config .cargo/config-boringssl.toml test {locked_arg} -p crypto_provider_openssl ",
- "--features=boringssl -- --color=always"
- ),
- locked_arg=locked_arg
- ),
+ &root.parent().unwrap().join("third_party"),
+ "git clone https://boringssl.googlesource.com/boringssl",
)?;
-
+ run_cmd_shell(
+ &root.parent().unwrap().join("third_party/boringssl"),
+ "git checkout origin/master",
+ )?;
+ build_boringssl(root)?;
Ok(())
}
-/// If the repo dir doesn't exist, or errors when running `git fetch -a`, re-clone it.
-///
-/// Returns the repo dir
-fn clone_repo_if_needed(
- dir: &Path,
- repo_subdir_name: &str,
- repo_url: &str,
-) -> anyhow::Result<PathBuf> {
- let mut repo_dir = dir.to_path_buf();
- repo_dir.push(repo_subdir_name);
-
- if run_cmd_shell_with_color::<YellowStderr>(&repo_dir, "git fetch -a").is_err() {
- // delete it and start over
- if repo_dir.exists() {
- fs::remove_dir_all(&repo_dir)?;
- }
- run_cmd_shell_with_color::<YellowStderr>(dir, format!("git clone {}", repo_url))?;
- }
-
- Ok(repo_dir)
-}
-
fn get_bindgen_version() -> anyhow::Result<Version> {
let bindgen_version_output = run_cmd_shell(&env::current_dir().unwrap(), "bindgen --version")?;
diff --git a/nearby/src/ffi.rs b/nearby/src/ffi.rs
index 01fe58a..ac0c585 100644
--- a/nearby/src/ffi.rs
+++ b/nearby/src/ffi.rs
@@ -12,76 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::CargoOptions;
+use crate::{crypto_ffi, CargoOptions};
use cmd_runner::{run_cmd_shell, run_cmd_shell_with_color, YellowStderr};
use std::{fs, path};
// wrapper for checking all ffi related things
-pub fn check_everything(root: &path::Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
- check_np_ffi_rust(root, cargo_options)?;
- check_ldt_ffi_rust(root)?;
- check_ldt_cmake(root, cargo_options)?;
+pub fn check_ffi(root: &path::Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
+ crypto_ffi::check_boringssl(root, cargo_options)?;
check_np_ffi_cmake(root, cargo_options)?;
-
- Ok(())
-}
-
-pub fn check_np_ffi_rust(root: &path::Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
- log::info!("Checking np_c_ffi cargo build");
- let ffi_dir = root.join("presence/np_c_ffi");
- let locked_arg = if cargo_options.locked { "--locked" } else { "" };
- for cargo_cmd in [
- "fmt --check",
- // Default build, RustCrypto
- format!("check {locked_arg} --quiet").as_str(),
- // Build with BoringSSL for crypto
- format!("check {locked_arg} --no-default-features --features=boringssl").as_str(),
- "clippy",
- "deny check",
- "doc --quiet --no-deps",
- ] {
- run_cmd_shell(&ffi_dir, format!("cargo {}", cargo_cmd))?;
- }
- Ok(())
-}
-
-pub fn check_ldt_ffi_rust(root: &path::Path) -> anyhow::Result<()> {
- log::info!("Checking LFT ffi cargo build");
- let ffi_dir = root.to_path_buf().join("presence/ldt_np_adv_ffi");
-
- for cargo_cmd in [
- "fmt --check",
- // Default build, RustCrypto + no_std
- "check --quiet",
- // Turn on std, still using RustCrypto
- "check --quiet --features=std",
- // Turn off default features and try to build with std",
- "check --quiet --no-default-features --features=std",
- // Turn off RustCrypto and use boringssl
- "check --quiet --no-default-features --features=boringssl",
- "doc --quiet --no-deps",
- "clippy --release",
- "clippy --features=std",
- "clippy --no-default-features --features=openssl",
- "clippy --no-default-features --features=std",
- "deny check",
- ] {
- run_cmd_shell(&ffi_dir, format!("cargo {}", cargo_cmd))?;
- }
+ check_ldt_cmake(root, cargo_options)?;
Ok(())
}
pub fn check_np_ffi_cmake(root: &path::Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
log::info!("Checking CMake build and tests for np ffi c/c++ code");
- let build_dir = root.to_path_buf().join("presence/cmake-build");
+ let build_dir = root.join("presence/cmake-build");
fs::create_dir_all(&build_dir)?;
let locked_arg = if cargo_options.locked { "--locked" } else { "" };
run_cmd_shell_with_color::<YellowStderr>(
&build_dir,
- "cmake -G Ninja -DENABLE_TESTS=true -DCMAKE_BUILD_TYPE=Release ..",
+ "cmake -G Ninja -DENABLE_TESTS=true -DCMAKE_BUILD_TYPE=Release -DENABLE_FUZZ=false ..",
)?;
// verify sample and benchmarks build
@@ -91,7 +44,7 @@ pub fn check_np_ffi_cmake(root: &path::Path, cargo_options: &CargoOptions) -> an
run_cmd_shell_with_color::<YellowStderr>(&build_dir, "cmake --build . --target np_ffi_bench")?;
// Run tests with different crypto backends
- let tests_dir = build_dir.to_path_buf().join("np_cpp_ffi/tests");
+ let tests_dir = build_dir.join("np_cpp_ffi/tests");
for build_config in [
// test with default build settings (rustcrypto)
format!("build {locked_arg} --quiet --release"),
@@ -115,19 +68,17 @@ pub fn check_np_ffi_cmake(root: &path::Path, cargo_options: &CargoOptions) -> an
pub fn check_ldt_cmake(root: &path::Path, cargo_options: &CargoOptions) -> anyhow::Result<()> {
log::info!("Checking CMake build and tests for ldt c/c++ code");
- let build_dir = root.to_path_buf().join("presence/cmake-build");
+ let build_dir = root.join("presence/cmake-build");
fs::create_dir_all(&build_dir)?;
let locked_arg = if cargo_options.locked { "--locked" } else { "" };
run_cmd_shell_with_color::<YellowStderr>(
&build_dir,
- "cmake -G Ninja -DENABLE_TESTS=true -DCMAKE_BUILD_TYPE=Release ..",
+ "cmake -G Ninja -DENABLE_TESTS=true -DCMAKE_BUILD_TYPE=Release -DENABLE_FUZZ=false ..",
)?;
- // verify sample and benchmarks build
- let ldt_ffi_crate_dir = root.to_path_buf().join("presence/ldt_np_adv_ffi");
- run_cmd_shell(&ldt_ffi_crate_dir, format!("cargo build {locked_arg} --release"))?;
+ run_cmd_shell(root, format!("cargo build {locked_arg} -p ldt_np_adv_ffi --quiet --release"))?;
run_cmd_shell_with_color::<YellowStderr>(&build_dir, "cmake --build . --target ldt_c_sample")?;
run_cmd_shell_with_color::<YellowStderr>(
&build_dir,
@@ -136,23 +87,18 @@ pub fn check_ldt_cmake(root: &path::Path, cargo_options: &CargoOptions) -> anyho
// Run the LDT ffi unit tests. These are rebuilt and tested against all of the different
// Cargo build configurations based on the feature flags.
- let ldt_tests_dir = build_dir.to_path_buf().join("ldt_np_c_sample/tests");
+ let ldt_tests_dir = build_dir.join("ldt_np_adv_ffi/c/tests");
for build_config in [
// test with default build settings (rustcrypto, no_std)
format!("build {locked_arg} --quiet --release"),
- // test with std and default features
- format!("build {locked_arg} --quiet --features std --release"),
// test with boringssl crypto feature flag
format!("build {locked_arg} --quiet --no-default-features --features boringssl --release"),
// test without defaults and std feature flag
format!("build {locked_arg} --quiet --no-default-features --features std --release"),
] {
- run_cmd_shell(&ldt_ffi_crate_dir, format!("cargo {}", build_config))?;
+ run_cmd_shell(root, format!("cargo {} -p ldt_np_adv_ffi", build_config))?;
// Force detection of updated `ldt_np_adv_ffi` static lib
- let _ = run_cmd_shell_with_color::<YellowStderr>(
- &build_dir,
- "rm ldt_np_c_sample/tests/ldt_ffi_tests",
- );
+ let _ = run_cmd_shell_with_color::<YellowStderr>(&ldt_tests_dir, "rm ldt_ffi_tests");
run_cmd_shell_with_color::<YellowStderr>(
&build_dir,
"cmake --build . --target ldt_ffi_tests",
diff --git a/nearby/src/fuzzers.rs b/nearby/src/fuzzers.rs
index 192d59c..fa4f21e 100644
--- a/nearby/src/fuzzers.rs
+++ b/nearby/src/fuzzers.rs
@@ -12,26 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use cmd_runner::{run_cmd_shell_with_color, YellowStderr};
+use cmd_runner::{run_cmd_shell, run_cmd_shell_with_color, YellowStderr};
use std::{fs, path};
pub(crate) fn run_rust_fuzzers(root: &path::Path) -> anyhow::Result<()> {
log::info!("Running rust fuzzers");
run_cmd_shell_with_color::<YellowStderr>(
&root.join("presence/xts_aes"),
- "cargo +nightly fuzz run xts-roundtrip -- -runs=10000 -max_total_time=60",
+ "cargo +nightly fuzz run xts_roundtrip -- -runs=10000 -max_total_time=60",
)?;
run_cmd_shell_with_color::<YellowStderr>(
&root.join("presence/ldt"),
- "cargo +nightly fuzz run ldt-roundtrip -- -runs=10000 -max_total_time=60",
+ "cargo +nightly fuzz run ldt_roundtrip -- -runs=10000 -max_total_time=60",
)?;
run_cmd_shell_with_color::<YellowStderr>(
&root.join("presence/ldt_np_adv"),
- "cargo +nightly fuzz run ldt-np-decrypt -- -runs=10000 -max_total_time=60",
+ "cargo +nightly fuzz run ldt_np_decrypt -- -runs=10000 -max_total_time=60",
)?;
run_cmd_shell_with_color::<YellowStderr>(
&root.join("presence/ldt_np_adv"),
- "cargo +nightly fuzz run ldt-np-roundtrip -- -runs=10000 -max_total_time=60",
+ "cargo +nightly fuzz run ldt_np_roundtrip -- -runs=10000 -max_total_time=60",
)?;
run_cmd_shell_with_color::<YellowStderr>(
&root.join("connections/ukey2/ukey2_connections"),
@@ -52,7 +52,7 @@ pub(crate) fn run_rust_fuzzers(root: &path::Path) -> anyhow::Result<()> {
run_cmd_shell_with_color::<YellowStderr>(
&root.join("crypto/crypto_provider_test"),
concat!(
- "cargo +nightly fuzz run fuzz_p256 --features=openssl --no-default-features ",
+ "cargo +nightly fuzz run fuzz_p256 --features=boringssl --no-default-features ",
"-- -runs=10000 -max_total_time=60"
),
)?;
@@ -60,22 +60,25 @@ pub(crate) fn run_rust_fuzzers(root: &path::Path) -> anyhow::Result<()> {
Ok(())
}
-pub(crate) fn build_ffi_fuzzers(root: &path::Path) -> anyhow::Result<()> {
- log::info!("Building ffi fuzzers");
- // TODO currently broken because the FFI stuff hasn't necessarily been built yet
- let mut build_dir = root.to_path_buf();
- build_dir.push("presence/ldt_np_adv_ffi_fuzz/cmake-build");
+// Runs the fuzztest fuzzers as short lived unit tests, compatible with gtest
+pub(crate) fn build_fuzztest_unit_tests(root: &path::Path) -> anyhow::Result<()> {
+ log::info!("Checking fuzztest targets in unit test mode");
- if build_dir.exists() {
- fs::remove_dir_all(&build_dir)?;
- }
+ // first build the rust static libs to link against
+ let np_ffi_crate_dir = root.join("presence/np_c_ffi");
+ run_cmd_shell(&np_ffi_crate_dir, "cargo build --release")?;
+ let build_dir = root.join("presence/cmake-build");
fs::create_dir_all(&build_dir)?;
- run_cmd_shell_with_color::<YellowStderr>(
- &build_dir,
- "cmake -G Ninja ../.. -DENABLE_FUZZ=true",
- )?;
- run_cmd_shell_with_color::<YellowStderr>(&build_dir, "cmake --build .")?;
- fs::remove_dir_all(&build_dir)?;
+ run_cmd_shell_with_color::<YellowStderr>(&build_dir, "cmake -G Ninja -DENABLE_FUZZ=true ..")?;
+
+ for target in ["deserialization_fuzzer", "ldt_fuzzer"] {
+ run_cmd_shell_with_color::<YellowStderr>(
+ &build_dir,
+ format!("cmake --build . --target {}", target),
+ )?;
+ }
+ run_cmd_shell_with_color::<YellowStderr>(&build_dir.join("np_cpp_ffi/fuzz/"), "ctest")?;
+ run_cmd_shell_with_color::<YellowStderr>(&build_dir.join("ldt_np_adv_ffi/c/fuzz/"), "ctest")?;
Ok(())
}
diff --git a/nearby/src/jni.rs b/nearby/src/jni.rs
index efd6e6c..54aafdc 100644
--- a/nearby/src/jni.rs
+++ b/nearby/src/jni.rs
@@ -17,9 +17,7 @@ use std::path;
// This has to happen after both boringssl has been built and prepare rust openssl patches has been run.
pub fn check_ldt_jni(root: &path::Path) -> anyhow::Result<()> {
- for feature in ["opensslbssl", "boringssl"] {
- run_cmd_shell(root, format!("cargo --config .cargo/config-boringssl.toml build -p ldt_np_jni --no-default-features --features={}", feature))?;
- }
+ run_cmd_shell(root, "cargo build -p ldt_np_jni --no-default-features --features=boringssl")?;
Ok(())
}
@@ -30,7 +28,15 @@ pub fn run_kotlin_tests(root: &path::Path) -> anyhow::Result<()> {
}
pub fn run_ukey2_jni_tests(root: &path::Path) -> anyhow::Result<()> {
+ run_cmd_shell(root, "cargo build -p ukey2_jni")?;
let ukey2_jni_path = root.to_path_buf().join("connections/ukey2/ukey2_jni/java");
run_cmd_shell(&ukey2_jni_path, "./gradlew :test")?;
Ok(())
}
+
+pub fn run_np_java_ffi_tests(root: &path::Path) -> anyhow::Result<()> {
+ run_cmd_shell(root, "cargo build -p np_java_ffi -F crypto_provider_default/rustcrypto")?;
+ let ukey2_jni_path = root.to_path_buf().join("presence/np_java_ffi");
+ run_cmd_shell(&ukey2_jni_path, "./gradlew :test --info --rerun")?;
+ Ok(())
+}
diff --git a/nearby/src/license.rs b/nearby/src/license.rs
index 387ca27..2229d04 100644
--- a/nearby/src/license.rs
+++ b/nearby/src/license.rs
@@ -12,75 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use chrono::Datelike;
-use file_header::{check_headers_recursively, license::spdx::*};
-use std::path;
+use cmd_runner::license_checker::LicenseChecker;
-pub(crate) fn check_license_headers(root: &path::Path) -> anyhow::Result<()> {
- log::info!("Checking license headers");
- let ignore = license_ignore()?;
- let results = check_headers_recursively(
- root,
- |p| !ignore.is_match(p),
- APACHE_2_0.build_header(YearCopyrightOwnerValue::new(
- u32::try_from(chrono::Utc::now().year())?,
- "Google LLC".to_string(),
- )),
- 4,
- )?;
-
- for path in results.no_header_files.iter() {
- eprintln!("Header not present: {path:?}");
- }
-
- for path in results.binary_files.iter() {
- eprintln!("Binary file: {path:?}");
- }
- if !results.binary_files.is_empty() {
- eprintln!("Consider adding binary files to the ignore list in src/licence.rs.");
- }
-
- if results.has_failure() {
- Err(anyhow::anyhow!("License header check failed"))
- } else {
- Ok(())
- }
-}
-
-pub(crate) fn add_license_headers(root: &path::Path) -> anyhow::Result<()> {
- let ignore = license_ignore()?;
- for p in file_header::add_headers_recursively(
- root,
- |p| !ignore.is_match(p),
- APACHE_2_0.build_header(YearCopyrightOwnerValue::new(
- u32::try_from(chrono::Utc::now().year())?,
- "Google LLC".to_string(),
- )),
- )? {
- println!("Added header: {:?}", p);
- }
-
- Ok(())
-}
-
-fn license_ignore() -> Result<globset::GlobSet, globset::Error> {
- let mut builder = globset::GlobSetBuilder::new();
- for lic in license_ignore_dirs() {
- builder.add(globset::Glob::new(lic)?);
- }
- builder.build()
-}
-
-fn license_ignore_dirs() -> Vec<&'static str> {
- vec![
+pub const LICENSE_CHECKER: LicenseChecker = LicenseChecker {
+ // These will be checked against the absolute path of each file.
+ ignore: &[
"**/android/build/**",
- "target/**",
"**/target/**",
"**/.idea/**",
"**/cmake-build/**",
"**/java/build/**",
"**/java/*/build/**",
"**/ukey2_c_ffi/cpp/build/**",
+ "**/np_java_ffi/build/**",
"**/*.toml",
"**/*.md",
"**/*.lock",
@@ -109,5 +53,19 @@ fn license_ignore_dirs() -> Vec<&'static str> {
"**/*.class",
"**/fuzz/artifacts/**",
"**/cmake-build-debug/**",
- ]
+ "**/tags",
+ "**/MODULE.bazel",
+ "**/WORKSPACE",
+ "**/.bazelrc",
+ ],
+};
+
+#[cfg(test)]
+mod tests {
+ use super::LICENSE_CHECKER;
+
+ #[test]
+ fn new_ignore_is_likely_buggy() {
+ LICENSE_CHECKER.check_new_ignore_is_likely_buggy()
+ }
}
diff --git a/nearby/src/main.rs b/nearby/src/main.rs
index 1d1ac16..25fe348 100644
--- a/nearby/src/main.rs
+++ b/nearby/src/main.rs
@@ -15,9 +15,10 @@
extern crate core;
use clap::Parser as _;
-use cmd_runner::run_cmd_shell;
+use cmd_runner::{license_checker::LicenseSubcommand, run_cmd, run_cmd_shell, YellowStderr};
use env_logger::Env;
-use std::{env, path};
+use license::LICENSE_CHECKER;
+use std::{env, ffi::OsString, path};
mod crypto_ffi;
mod ffi;
@@ -35,28 +36,34 @@ fn main() -> anyhow::Result<()> {
);
match cli.subcommand {
- Subcommand::CheckEverything { ref check_options } => {
- check_everything(&root_dir, check_options)?
+ Subcommand::RunDefaultChecks(ref check_options) => {
+ run_default_checks(&root_dir, check_options)?;
+ print!(concat!(
+ "Congratulations, the default checks passed. Since you like quality, here are\n",
+ "some more checks you may like:\n",
+ " cargo run -- run-rust-fuzzers\n",
+ " cargo run -- check-stack-usage\n",
+ ));
}
+ Subcommand::VerifyCi { ref check_options } => verify_ci(&root_dir, check_options)?,
Subcommand::CleanEverything => clean_everything(&root_dir)?,
+ Subcommand::CheckFormat(ref options) => check_format(&root_dir, options)?,
Subcommand::CheckWorkspace(ref options) => check_workspace(&root_dir, options)?,
- Subcommand::FfiCheckEverything(ref options) => ffi::check_everything(&root_dir, options)?,
- Subcommand::BoringsslCheckEverything(ref options) => {
- crypto_ffi::boringssl_check_everything(&root_dir, options)?
- }
+ Subcommand::CheckAllFfi(ref options) => ffi::check_ffi(&root_dir, options)?,
Subcommand::BuildBoringssl => crypto_ffi::build_boringssl(&root_dir)?,
Subcommand::CheckBoringssl(ref options) => crypto_ffi::check_boringssl(&root_dir, options)?,
- Subcommand::PrepareRustOpenssl => crypto_ffi::prepare_patched_rust_openssl(&root_dir)?,
- Subcommand::CheckOpenssl(ref options) => crypto_ffi::check_openssl(&root_dir, options)?,
+ Subcommand::CheckBoringsslAtLatest(ref options) => {
+ crypto_ffi::check_boringssl_at_head(&root_dir, options)?
+ }
Subcommand::RunRustFuzzers => fuzzers::run_rust_fuzzers(&root_dir)?,
- Subcommand::BuildFfiFuzzers => fuzzers::build_ffi_fuzzers(&root_dir)?,
- Subcommand::CheckLicenseHeaders => license::check_license_headers(&root_dir)?,
- Subcommand::AddLicenseHeaders => license::add_license_headers(&root_dir)?,
- Subcommand::CheckLdtFfi => ffi::check_ldt_ffi_rust(&root_dir)?,
+ Subcommand::CheckFuzztest => fuzzers::build_fuzztest_unit_tests(&root_dir)?,
+ Subcommand::License(license_subcommand) => {
+ license_subcommand.run(&LICENSE_CHECKER, &root_dir)?
+ }
Subcommand::CheckUkey2Ffi(ref options) => ukey2::check_ukey2_ffi(&root_dir, options)?,
Subcommand::RunUkey2JniTests => jni::run_ukey2_jni_tests(&root_dir)?,
+ Subcommand::RunNpJavaFfiTests => jni::run_np_java_ffi_tests(&root_dir)?,
Subcommand::CheckLdtJni => jni::check_ldt_jni(&root_dir)?,
- Subcommand::CheckNpFfi(ref options) => ffi::check_np_ffi_rust(&root_dir, options)?,
Subcommand::CheckLdtCmake(ref options) => ffi::check_ldt_cmake(&root_dir, options)?,
Subcommand::CheckNpFfiCmake(ref options) => ffi::check_np_ffi_cmake(&root_dir, options)?,
Subcommand::RunKotlinTests => jni::run_kotlin_tests(&root_dir)?,
@@ -65,28 +72,73 @@ fn main() -> anyhow::Result<()> {
Ok(())
}
+fn check_format(root: &path::Path, options: &FormatterOptions) -> anyhow::Result<()> {
+ // Rust format
+ {
+ let fmt_command = if options.reformat { "cargo fmt" } else { "cargo fmt --check" };
+ run_cmd_shell(root, fmt_command)?;
+ }
+
+ // Java format. This uses the jar downloaded as part of the CI script or the local
+ // `google-java-format` executable. The jar file path can be overridden with the
+ // `GOOGLE_JAVA_FORMAT_ALL_DEPS_JAR` environment variable. See
+ // <go/google-java-format#installation> for setup instructions for your dev environment if
+ // needed.
+ {
+ let jar_path = std::env::var("GOOGLE_JAVA_FORMAT_ALL_DEPS_JAR").unwrap_or_else(|_| {
+ "/opt/google-java-format/google-java-format-all-deps.jar".to_owned()
+ });
+
+ let mut fmt_command: Vec<OsString> = Vec::new();
+
+ if path::PathBuf::from(&jar_path).exists() {
+ fmt_command.extend(["java".into(), "-jar".into(), jar_path.into()]);
+ } else {
+ fmt_command.push("google-java-format".into());
+ }
+
+ if options.reformat {
+ fmt_command.push("-i".into());
+ } else {
+ fmt_command.extend(["--set-exit-if-changed".into(), "--dry-run".into()]);
+ }
+
+ let root_str =
+ glob::Pattern::escape(root.to_str().expect("Non-unicode paths are not supported"));
+ let search = format!("{}/**/*.java", root_str);
+ let java_files: Vec<_> = glob::glob(&search).unwrap().filter_map(Result::ok).collect();
+
+ for file_set in java_files.chunks(100) {
+ let mut args = fmt_command[1..].to_vec();
+ args.extend(file_set.iter().map(OsString::from));
+
+ run_cmd::<YellowStderr, _, _, _>(root, &fmt_command[0], args)?;
+ }
+ }
+
+ Ok(())
+}
+
pub fn check_workspace(root: &path::Path, options: &CheckOptions) -> anyhow::Result<()> {
log::info!("Running cargo checks on workspace");
- let fmt_command = if options.reformat { "cargo fmt" } else { "cargo fmt --check" };
+ // ensure formatting is correct (Check for it first because it is fast compared to running tests)
+ check_format(root, &options.formatter_options)?;
for cargo_cmd in [
- // ensure formatting is correct (Check for it first because it is fast compared to running tests)
- fmt_command,
// make sure everything compiles
"cargo check --workspace --all-targets --quiet",
// run all the tests
- //TODO: re-enable the openssl tests, this was potentially failing due to UB code in the
- // upstream rust-openssl crate's handling of empty slices. This repros consistently when
- // using the rust-openssl crate backed by openssl-sys on Ubuntu 20.04.
- "cargo test --workspace --quiet --exclude crypto_provider_openssl -- --color=always",
+ &options.cargo_options.test("check_workspace", "--workspace --quiet"),
// Test ukey2 builds with different crypto providers
- "cargo test -p ukey2_connections -p ukey2_rs --no-default-features --features test_rustcrypto",
- "cargo test -p ukey2_connections -p ukey2_rs --no-default-features --features test_openssl",
+ &options.cargo_options.test(
+ "check_workspace_ukey2",
+ "-p ukey2_connections -p ukey2_rs --no-default-features --features test_rustcrypto",
+ ),
// ensure the docs are valid (cross-references to other code, etc)
concat!(
- "RUSTDOCFLAGS='--deny warnings -Z unstable-options --enable-index-page --generate-link-to-definition' ",
- "cargo +nightly doc --quiet --workspace --no-deps --document-private-items ",
+ "RUSTDOCFLAGS='--deny warnings' ",
+ "cargo doc --quiet --workspace --no-deps --document-private-items ",
"--target-dir target/dist_docs",
),
"cargo clippy --all-targets --workspace -- --deny warnings",
@@ -98,29 +150,37 @@ pub fn check_workspace(root: &path::Path, options: &CheckOptions) -> anyhow::Res
Ok(())
}
-/// Runs checks to ensure lints are passing and all targets are building
-pub fn check_everything(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()> {
- license::check_license_headers(root)?;
+/// Runs default checks that are suiable for verifying a local change.
+pub fn run_default_checks(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()> {
+ license::LICENSE_CHECKER.check(root)?;
check_workspace(root, check_options)?;
crypto_ffi::check_boringssl(root, &check_options.cargo_options)?;
- crypto_ffi::check_openssl(root, &check_options.cargo_options)?;
- ffi::check_everything(root, &check_options.cargo_options)?;
- jni::check_ldt_jni(root)?;
- jni::run_kotlin_tests(root)?;
- jni::run_ukey2_jni_tests(root)?;
+ ffi::check_ffi(root, &check_options.cargo_options)?;
+ if !cfg!(target_os = "windows") {
+ fuzzers::build_fuzztest_unit_tests(root)?;
+ }
+ crypto_ffi::check_boringssl_at_head(root, &check_options.cargo_options)?;
ukey2::check_ukey2_ffi(root, &check_options.cargo_options)?;
- fuzzers::run_rust_fuzzers(root)?;
- fuzzers::build_ffi_fuzzers(root)?;
+ if !cfg!(target_os = "windows") {
+ // Test below requires Java SE 9, but on Windows we only have Java SE 8 installed
+ jni::run_np_java_ffi_tests(root)?;
+ }
+ jni::run_ukey2_jni_tests(root)?;
+ Ok(())
+}
+/// Runs checks to ensure lints are passing and all targets are building
+pub fn verify_ci(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()> {
+ run_default_checks(root, check_options)?;
Ok(())
}
pub fn clean_everything(root: &path::Path) -> anyhow::Result<()> {
run_cmd_shell(root, "cargo clean")?;
- run_cmd_shell(&root.join("presence/ldt_np_adv_ffi"), "cargo clean")?;
run_cmd_shell(&root.join("presence/np_c_ffi"), "cargo clean")?;
run_cmd_shell(&root.join("crypto/crypto_provider_boringssl"), "cargo clean")?;
run_cmd_shell(&root.join("connections/ukey2/ukey2_c_ffi"), "cargo clean")?;
+ run_cmd_shell(&root.join("presence/np_java_ffi"), "./gradlew :clean")?;
Ok(())
}
@@ -132,61 +192,61 @@ struct Cli {
#[derive(clap::Subcommand, Debug, Clone)]
enum Subcommand {
- /// Checks everything in beto-rust
- CheckEverything {
+ /// Runs all of the checks that CI runs
+ VerifyCi {
#[command(flatten)]
check_options: CheckOptions,
},
+ /// Runs the default set of checks suitable for verifying local changes.
+ RunDefaultChecks(CheckOptions),
/// Cleans the main workspace and all sub projects - useful if upgrading rust compiler version
/// and need dependencies to be compiled with the same version
CleanEverything,
+ /// Checks code formatting
+ CheckFormat(FormatterOptions),
/// Checks everything included in the top level workspace
CheckWorkspace(CheckOptions),
- /// Checks everything related to the boringssl version (equivalent of running check-boringssl
- /// + check-openssl)
- BoringsslCheckEverything(CargoOptions),
/// Clones boringssl and uses bindgen to generate the rust crate
BuildBoringssl,
/// Run crypto provider tests using boringssl backend
CheckBoringssl(CargoOptions),
- /// Applies AOSP specific patches to the 3p `openssl` crate so that it can use a boringssl
- /// backend
- PrepareRustOpenssl,
- /// Run crypto provider tests using openssl crate with boringssl backend
- CheckOpenssl(CargoOptions),
+ /// Checks out latest boringssl commit and runs our tests against it
+ CheckBoringsslAtLatest(CargoOptions),
/// Build and run pure Rust fuzzers for 10000 runs
RunRustFuzzers,
- /// Build FFI fuzzers
- BuildFfiFuzzers,
+ /// Builds and runs fuzztest property based unit tests
+ CheckFuzztest,
/// Builds and runs tests for all C/C++ projects. This is a combination of CheckNpFfi,
/// CheckLdtFfi, and CheckCmakeBuildAndTests
- FfiCheckEverything(CargoOptions),
- /// Builds the crate checks the cbindgen generation of C/C++ bindings
- CheckNpFfi(CargoOptions),
- /// Builds ldt_np_adv_ffi crate with all possible different sets of feature flags
- CheckLdtFfi,
+ CheckAllFfi(CargoOptions),
/// Checks the CMake build and runs all of the C/C++ tests
CheckLdtCmake(CargoOptions),
/// Checks the CMake build and runs all of the C/C++ tests
CheckNpFfiCmake(CargoOptions),
- /// Checks the workspace 3rd party crates and makes sure they have a valid license
- CheckLicenseHeaders,
- /// Generate new headers for any files that are missing them
- AddLicenseHeaders,
+ #[command(flatten)]
+ License(LicenseSubcommand),
/// Builds and runs tests for the UKEY2 FFI
CheckUkey2Ffi(CargoOptions),
- /// Checks the build of ldt_jni wrapper with non default features, ie rust-openssl, and boringssl
+ /// Checks the build of ldt_jni wrapper with non default features, ie boringssl
CheckLdtJni,
/// Runs the kotlin tests of the LDT Jni API
RunKotlinTests,
/// Checks the build of the ukey2_jni wrapper and runs tests
RunUkey2JniTests,
+ /// Checks the build of the np_java_ffi wrapper and runs tests
+ RunNpJavaFfiTests,
}
#[derive(clap::Args, Debug, Clone, Default)]
-pub struct CheckOptions {
- #[arg(long, help = "reformat files with cargo fmt")]
+pub struct FormatterOptions {
+ #[arg(long, help = "reformat files files in the workspace with the code formatter")]
reformat: bool,
+}
+
+#[derive(clap::Args, Debug, Clone, Default)]
+pub struct CheckOptions {
+ #[command(flatten)]
+ formatter_options: FormatterOptions,
#[command(flatten)]
cargo_options: CargoOptions,
}
@@ -195,4 +255,23 @@ pub struct CheckOptions {
pub struct CargoOptions {
#[arg(long, help = "whether to run cargo with --locked")]
locked: bool,
+ #[arg(long, help = "gather coverage metrics")]
+ coverage: bool,
+}
+
+impl CargoOptions {
+ /// Run `cargo test` or `cargo llvm-cov` depending on the configured options.
+ pub fn test(&self, tag: &str, args: impl AsRef<str>) -> String {
+ format!(
+ "cargo {subcommand} {locked} {args} {cov_args} -- --color=always",
+ subcommand = if self.coverage { "llvm-cov" } else { "test" },
+ locked = if self.locked { "--locked" } else { "" },
+ args = args.as_ref(),
+ cov_args = if self.coverage {
+ format!("--lcov --output-path \"target/{tag}.info\"")
+ } else {
+ String::default()
+ },
+ )
+ }
}
diff --git a/nearby/src/ukey2.rs b/nearby/src/ukey2.rs
index e548ab0..5e711a1 100644
--- a/nearby/src/ukey2.rs
+++ b/nearby/src/ukey2.rs
@@ -28,22 +28,18 @@ pub(crate) fn check_ukey2_ffi(
// Default build, RustCrypto
run_cmd_shell(&ffi_dir, format!("cargo build {locked_arg} --quiet --release --lib"))?;
- // OpenSSL
+ // BoringSSL
run_cmd_shell(
&ffi_dir,
- format!("cargo build {locked_arg} --quiet --no-default-features --features=openssl"),
+ format!("cargo build {locked_arg} --quiet --no-default-features --features=boringssl"),
)?;
+ run_cmd_shell(&ffi_dir, "cargo clippy --no-default-features --features=boringssl")?;
- run_cmd_shell(&ffi_dir, "cargo doc --quiet --no-deps")?;
- run_cmd_shell(&ffi_dir, "cargo clippy --no-default-features --features=openssl")?;
-
- run_cmd_shell(&ffi_dir, "cargo deny check")?;
-
+ // now run cmake build
let ffi_build_dir = ffi_dir.join("cpp/build");
fs::create_dir_all(&ffi_build_dir)?;
run_cmd_shell_with_color::<YellowStderr>(&ffi_build_dir, "cmake ..")?;
run_cmd_shell_with_color::<YellowStderr>(&ffi_build_dir, "cmake --build .")?;
run_cmd_shell_with_color::<YellowStderr>(&ffi_build_dir, "ctest")?;
-
Ok(())
}
diff --git a/remoteauth/Cargo.lock b/remoteauth/Cargo.lock
index 55841b9..165b375 100644
--- a/remoteauth/Cargo.lock
+++ b/remoteauth/Cargo.lock
@@ -4,18 +4,33 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "1.0.5"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "anstream"
-version = "0.5.0"
+version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -27,33 +42,33 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.2"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
-version = "0.2.1"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.0.0"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
-version = "2.1.0"
+version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys",
@@ -61,15 +76,25 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.72"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
+checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
-name = "bitflags"
-version = "2.4.0"
+name = "autocfg"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
+
+[[package]]
+name = "bstr"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+dependencies = [
+ "memchr",
+ "serde",
+]
[[package]]
name = "build-scripts"
@@ -77,36 +102,58 @@ version = "0.1.0"
dependencies = [
"anyhow",
"clap",
- "cmd-runner",
+ "cmd_runner",
"env_logger",
"log",
]
[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
name = "cc"
-version = "1.0.83"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
- "libc",
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets",
]
[[package]]
name = "clap"
-version = "4.4.1"
+version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
- "once_cell",
]
[[package]]
name = "clap_builder"
-version = "4.4.1"
+version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
@@ -116,9 +163,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.4.0"
+version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck",
"proc-macro2",
@@ -128,17 +175,23 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
-name = "cmd-runner"
+name = "cmd_runner"
version = "0.1.0"
dependencies = [
"anyhow",
+ "chrono",
+ "clap",
+ "file-header",
+ "globset",
+ "log",
"owo-colors",
"shell-escape",
+ "xshell",
]
[[package]]
@@ -148,6 +201,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "crossbeam"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
name = "ctap_protocol"
version = "0.1.0"
dependencies = [
@@ -156,9 +271,9 @@ dependencies = [
[[package]]
name = "env_logger"
-version = "0.10.0"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
@@ -168,37 +283,42 @@ dependencies = [
]
[[package]]
-name = "errno"
-version = "0.3.3"
+name = "file-header"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
+checksum = "b5568149106e77ae33bc3a2c3ef3839cbe63ffa4a8dd4a81612a6f9dfdbc2e9f"
dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys",
+ "crossbeam",
+ "lazy_static",
+ "license",
+ "thiserror",
+ "walkdir",
]
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
+name = "globset"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
- "cc",
- "libc",
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
]
[[package]]
name = "heck"
-version = "0.4.1"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
-version = "0.3.2"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "humantime"
@@ -207,45 +327,103 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "is-terminal"
-version = "0.4.9"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
- "rustix",
+ "libc",
"windows-sys",
]
[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
-name = "linux-raw-sys"
-version = "0.4.5"
+name = "license"
+version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
+checksum = "3bba2f02ee1d13cd4bea565658939cd851d70e391f34f7c27b45b2077df3a2e4"
+dependencies = [
+ "reword",
+ "serde",
+ "serde_json",
+]
[[package]]
name = "log"
-version = "0.4.20"
+version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
-version = "2.6.1"
+version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f478948fd84d9f8e86967bf432640e46adfb5a4bd4f14ef7e864ab38220534ae"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+]
[[package]]
name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "owo-colors"
@@ -262,27 +440,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.32"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
-version = "1.9.4"
+version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
@@ -292,9 +470,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.3.7"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
@@ -303,9 +481,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.7.5"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "remote_auth_protocol"
@@ -315,16 +493,58 @@ dependencies = [
]
[[package]]
-name = "rustix"
-version = "0.38.10"
+name = "reword"
+version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed6248e1caa625eb708e266e06159f135e8c26f2bb7ceb72dc4b2766d0340964"
+checksum = "fe272098dce9ed76b479995953f748d1851261390b08f8a0ff619c885a1f0765"
dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys",
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.198"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.198"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.116"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
]
[[package]]
@@ -335,15 +555,15 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
[[package]]
name = "strsim"
-version = "0.10.0"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
-version = "2.0.28"
+version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
@@ -352,18 +572,44 @@ dependencies = [
[[package]]
name = "termcolor"
-version = "1.2.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
+name = "thiserror"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "unicode-ident"
-version = "1.0.11"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "utf8parse"
@@ -372,6 +618,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -389,9 +699,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
@@ -403,23 +713,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
name = "windows-sys"
-version = "0.48.0"
+version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
+ "windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
@@ -428,42 +748,63 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.5"
+version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.5"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+
+[[package]]
+name = "xshell"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
+dependencies = [
+ "xshell-macros",
+]
+
+[[package]]
+name = "xshell-macros"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
diff --git a/remoteauth/Cargo.toml b/remoteauth/Cargo.toml
index 20b2ec3..d86adc0 100644
--- a/remoteauth/Cargo.toml
+++ b/remoteauth/Cargo.toml
@@ -22,6 +22,6 @@ publish.workspace = true
[dependencies]
anyhow.workspace = true
clap = { version = "4.0.25", features = ["derive"] }
-cmd-runner = { path = "../cmd-runner" }
+cmd_runner = { path = "../common/cmd_runner" }
env_logger = "0.10.0"
log = "0.4.17" \ No newline at end of file