Replace JCE-based Ed25519 key generation with Tink#6
Conversation
Conscrypt 2.5.x ships an Ed25519 KeyFactory but no Ed25519
KeyPairGenerator, and the platform AndroidOpenSSL provider does
not register Ed25519 at all on min SDK 24. The previous code's
KeyPairGenerator.getInstance("Ed25519") therefore crashed the
pairing flow with NoSuchAlgorithmException on every supported
device. Switch the identity-store generator to Tink's standalone
Ed25519Sign.KeyPair, which is already on the runtime classpath
via androidx.security-crypto and does not depend on JCE provider
registration.
There was a problem hiding this comment.
Pull request overview
This PR updates Warpnet’s Android transport identity generation to avoid Android/Conscrypt JCE Ed25519 gaps by generating Ed25519 key material via Google Tink, while keeping the persisted libp2p key format unchanged (seed(32) || publicKey(32)).
Changes:
- Replaced JCE
KeyPairGenerator.getInstance("Ed25519")generation with TinkEd25519Sign.KeyPair.newKeyPair(). - Removed PKCS#8/X.509 parsing and switched to using Tink’s raw 32-byte seed + 32-byte public key.
- Added an explicit
tink-androiddependency via the version catalog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
warpnet-transport/src/main/kotlin/site/warpnet/transport/Ed25519IdentityStore.kt |
Switches Ed25519 keypair generation from JCE to Tink and returns raw seed+pub bytes directly. |
warpnet-transport/build.gradle |
Declares the module-level tink-android dependency needed for compilation. |
gradle/libs.versions.toml |
Adds the tink version and the tink-android library alias to the version catalog. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| val kp = Ed25519Sign.KeyPair.newKeyPair() | ||
| val seed = kp.privateKey | ||
| val pub = kp.publicKey |
There was a problem hiding this comment.
com.google.crypto.tink.subtle.Ed25519Sign is part of Tink’s low-level subtle package (not the higher-level/public Tink APIs). This increases upgrade risk because subtle classes are more likely to change or be relocated between Tink versions. Consider either (a) switching to the public signature APIs if they can provide the raw seed/public key you need, or (b) isolating this behind a small internal adapter (and adding a short comment) so future Tink upgrades only touch one place.
There was a problem hiding this comment.
Tink's public sign/verify APIs (PublicKeySign via KeysetHandle) wrap key material in opaque keysets with extra format/algorithm metadata — they intentionally don't expose the raw 32-byte seed and public key. go-libp2p's crypto.UnmarshalEd25519PrivateKey requires exactly the raw seed(32) || publicKey(32) layout the AAR consumes, so option (a) isn't viable without changing the on-disk and on-wire key format.
Option (b) is already in place: the Tink call is confined to a single private generate() method in Ed25519IdentityStore. If a future Tink version relocates subtle.Ed25519Sign, the fix is one import in one file. Pinning Tink to 1.8.0 (matched to what androidx.security-crypto already pulls in) keeps the upgrade window under our control.
Generated by Claude Code
Summary
Replaces the JCE-based Ed25519 key pair generation in
Ed25519IdentityStorewith Google's Tink library to work around platform limitations on Android.Key Changes
KeyPairGenerator.getInstance("Ed25519")withEd25519Sign.KeyPair.newKeyPair()from Tinktink-androidv1.8.0 to module dependenciesImplementation Details
The previous implementation relied on JCE's Ed25519 support, which has compatibility issues:
NoSuchAlgorithmExceptionon real devicesTink's standalone Ed25519 implementation:
https://claude.ai/code/session_01U4YqA23uAfzZM9oWAEfEBZ