Skip to content

Latest commit

 

History

History
117 lines (75 loc) · 4.67 KB

README.md

File metadata and controls

117 lines (75 loc) · 4.67 KB

SD-JWT Interop tool

This tool is used to verify interoperability between the sd-jwt-rust and sd-jwt-python implementations of the IETF SD-JWT specification.

How does the Interop tool work?

The main idea is to generate data structures (SDJWT/presentation/verified claims) using both implementations and compare them.

The sd-jwt-python is used to generate artifacts based on input data (specification.yml) and store them as files. The interop tool (based on sd-jwt-rust) is used to generate artifacts using the same specification file, load artifacts stored in files by sd-jwt-python and compare them. The interop tool doesn't store any files on filesystem.

There are some factors that make impossible to compare data due to non-equivalence data generated by different implementations:

  • Using random 'salt' in each run that make results different even though they are generated by the same implementation.
  • Not equivalent json-serialized strings (different number of spaces) generated under the hood of the different implementations.
  • Using 'decoy' digests in the SD-JWT payload.

In order to reach reproducibility and equivalence of the values generated by both implementations it is required to use the same input data (issuer private key, user claims, etc.) and to get rid of some non-deterministic values during data generating (values of 'salt', for example).

Deterministic 'salt'

In order to make it possible to get reproducible result each run it's required to use deterministic values of 'salt' used in internal algorithms. The sd-jwt-python project implements such behavior for test purposes.

In order to use the same set of 'salt' values by the sd-jwt-rust project Python-implementation stores values in the claims_vs_salts.json file as artifact. The Interop tool loads values from the file and use it instead of random generated values (see the mock_salts feature).

Similar json serialization

In order to have the same json-strings used under the hood of the both implementations there is some code that gets rid of different number of spaces:

    value_str = value_str
        .replace(":[", ": [")
        .replace(',', ", ")
        .replace("\":", "\": ")
        .replace("\":  ", "\": ");

'Decoy' SD items

In order to make it possible to compare SD-JWT payloads that contains decoy it was decided to detect and remove all decoy items from payloads and then compare them.

How to use the interop tool?

  1. Install the prerequisites
  2. Clone and build the sd-jwt-rust project
  3. Clone and build the sd-jwt-python project
  4. Generate artifacts using the sd-jwt-python project
  5. Run the interop tool

Install the prerequisites

In order to be able to build both implementations it is required to setup following tools:

  • Rust/cargo
  • poetry

Clone and build the sd-jwt-rust project

git clone [email protected]:openwallet-foundation-labs/sd-jwt-rust.git
cd sd-jwt-rust/generate
cargo build

Clone and build the sd-jwt-python project

Once the project repo is cloned to local directory it is necessary to apply special patch. This patch is required to have some additional files as artifacts generated by the sd-jwt-python project.

Files:

  • claims_vs_salts.json file contains values of so called 'salt' that have been used during SDJWT issuance.
  • issuer_key.pem file contains the issuer's private key.
  • issuer_public_key.pem file contains the issuer's public key.
  • holder_key.pem file contains the holder's private key.

The files are used to make it possible for this tool to generate the same values of artifacts (SDJWT payload/SDJWT claims/presentation/verified claims) that are generated by sd-jwt-python.

git clone [email protected]:openwallet-foundation-labs/sd-jwt-python.git
cd sd-jwt-python

# apply the patch
git apply ../sd-jwt-rust/generate/sd_jwt_python.patch

# build
poetry install && poetry build

Generate artifacts using the sd-jwt-python project

pushd sd-jwt-python/tests/testcases && poetry run ../../src/sd_jwt/bin/generate.py -- example && popd
pushd sd-jwt-python/examples && poetry run ../src/sd_jwt/bin/generate.py -- example && popd

Run the interop tool

cd sd-jwt-rust/generate
sd_jwt_py="../../sd-jwt-python"
for cases_dir in $sd_jwt_py/examples $sd_jwt_py/tests/testcases; do
    for test_case_dir in $(ls $cases_dir); do
        if [[ -d $cases_dir/$test_case_dir ]]; then
            ./target/debug/sd-jwt-generate -p $cases_dir/$test_case_dir
        fi
    done
done