Minimal repository testing interoperability between:
- Rust:
libcrux+hpke-rs(based on X-Wing draft-06) - Go:
circl(based on X-Wing draft-05) - TypeScript:
@hpke/hybridkem-x-wing+@hpke/core+@hpke/chacha20poly1305(based on X-Wing draft-06)
- KEM: X-Wing (drafts -05 and -06)
- KDF: HKDF-SHA256
- AEAD: ChaCha20Poly1305
- Mode: base
To run the test scripts, you need:
- Rust (with Cargo) - for building Rust programs
- Go (version 1.22+) - for building Go programs
- Node.js (with npm) - for building TypeScript programs
Run the interoperability test scripts:
# Go ↔ Rust
./test_go2rust.sh # Test Encrypt with Go → Decrypt with Rust
./test_rust2go.sh # Test Encrypt with Rust → Decrypt with Go
# Go ↔ TypeScript
./test_go2js.sh # Test Encrypt with Go → Decrypt with TypeScript
./test_js2go.sh # Test Encrypt with TypeScript → Decrypt with Go
# Rust ↔ TypeScript
./test_rust2js.sh # Test Encrypt with Rust → Decrypt with TypeScript
./test_js2rust.sh # Test Encrypt with TypeScript → Decrypt with Rusttest_go2js.sh: Go → TypeScript (works)test_js2go.sh: TypeScript → Go (works)
-
test_go2rust.sh: Rust fails to decrypt Go's output with error:Error: CryptoError("AEAD decryption error: InvalidTag") -
test_rust2go.sh: Go fails to decrypt Rust's output with error:Error opening ciphertext: chacha20poly1305: message authentication failed -
test_rust2js.sh: TypeScript fails to decrypt Rust's output with error:Error: OpenError: invalid tag -
test_js2rust.sh: Rust fails to decrypt TypeScript's output with error:Error: CryptoError("AEAD decryption error: InvalidTag")
Since js↔go interoperability works in both directions, but rust↔go and rust↔js both fail, this suggests the issue is likely in the Rust implementation rather than a draft version incompatibility.
Is the incompatibility because draft versions 5->6 introduced a format-breaking change? See diff here.
The only thing I could find that might break is that the KEM identifier value for XWING changed from 26287 to 25722 (0x647a). But then, the -05-based Circl code does use the correct value 0x647a, and the relevant Circl commit mentions using draft05 but updating codepoint to latest 0x647a.
So in my opinion, this is not the cause of incompatibility.