Skip to content

feat: add cardano-crypto-wallet package#653

Open
disassembler wants to merge 5 commits into
masterfrom
wallet-cbits
Open

feat: add cardano-crypto-wallet package#653
disassembler wants to merge 5 commits into
masterfrom
wallet-cbits

Conversation

@disassembler
Copy link
Copy Markdown
Contributor

@disassembler disassembler commented May 11, 2026

Introduces a new package providing authenticated envelope wrapping for HD wallet extended private keys.

cbits are vendored from cardano-crypto. This is done in the first commit which can be largely ignored by reviewers.

Key design:

  • C layer handles ed25519 key generation, public-key derivation, signing, and BIP32 child derivation; it stores and operates on plaintext key material only; public symbols are prefixed cardano_ to avoid linker conflicts with the legacy cardano-crypto C library
  • Haskell layer owns all encryption: Argon2id key derivation (128 MiB, t=3, p=4) and XChaCha20-Poly1305 AEAD wrapping with a freshly randomized salt and nonce per write
  • CBOR-encoded versioned envelope with explicit associated data binding format version, KDF parameters, cipher, payload shape, public key, and chain code — preventing silent swaps without detection
  • Fail-closed public API: passphrase-using operations return Either and reject wrong passphrases at authentication time
  • Test helpers for fast-KDF and deterministic randomness modes keep the test suite sub-second without touching production paths
  • Benchmark suite covers create, validate, sign, and change-passphrase under production Argon2id parameters

Description

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated
  • All visible changes are prepended to the latest section of a CHANGELOG.md for the affected packages.
    New section is never added with the code changes. (See RELEASING.md)
  • When applicable, versions are updated in .cabal and CHANGELOG.md files according to the
    versioning process.
  • The version bounds in .cabal files for all affected packages are updated.
    If you change the bounds in a cabal file, that package itself must have a version increase. (See RELEASING.md)
  • Self-reviewed the diff

@disassembler disassembler force-pushed the wallet-cbits branch 2 times, most recently from 64068a5 to 0ddedc7 Compare May 11, 2026 17:31
@disassembler disassembler changed the title feat: add cardano-crypto-wallet-v2 package feat: add cardano-crypto-wallet package May 11, 2026
@disassembler disassembler force-pushed the wallet-cbits branch 3 times, most recently from 80b8cc1 to 1e10820 Compare May 11, 2026 18:12
Vendors the ed25519-donna implementation from the cardano-crypto
package into this repository.
Adds encrypted_sign.c implementing HD wallet key operations using
libsodium (Argon2id KDF, XChaCha20-Poly1305 AEAD, HMAC-SHA512).
Updates ed25519-hash.h to use libsodium SHA-512 instead of crypton.
Adds the cardano-crypto-wallet Haskell package exposing
Cardano.Crypto.WalletHD.Encrypted, which provides authenticated
encryption and key derivation for HD wallet keys using the v2 envelope
format (Argon2id KDF + XChaCha20-Poly1305 AEAD via libsodium).
Adds round-trip, format, and signing tests plus a criterion benchmark
suite for the cardano-crypto-wallet package.
Four internal ByteString allocations held the raw 128-byte extended
private key (ed25519 scalar || public key || chain code) in memory
without guaranteed zeroing on GC.  Switch them to ScrubbedBytes so
the memory package zeroes the pages when they are collected.

  - keyMaterialFromLegacyBytes: avoids an intermediate full :: ByteString
    carrying all 128 bytes; slices secret/pub/cc directly from ScrubbedBytes
  - legacyMaterialFromSecret / legacyMaterialFromMasterKey / legacyDerivePrivate:
    type annotations changed from ByteString to ScrubbedBytes so B.allocRet
    allocates scrubbed pages from the start

No public API or serialisation changes.
@erikd
Copy link
Copy Markdown
Contributor

erikd commented May 15, 2026

I am not in any way a crypto guy, but I am a Haskell guy and I did spend decades coding in C, but have not done an C in over a decade. I will review this, but it should also be reviewed by a crypto guy that also knows Haskell and C.

For the Haskell code:

  • All top level constants initialized with unsafePerformIO tagged with a NOINLINE pragma. ✔️
  • Sensitive data held in ScrubbedBytes. ✔️ . Possibly also store salt and nonce to ScrubbedBytes. ❓
  • Maybe use {-# LANGUAGE Strict #-} to ensure sensitive data is not held in an un-evaludated thunk longer than it should be. ❓
  • This package currently depends on the memory package which i think is unmaintained. The ram package is supposed to be a drop in replacement. ❓

For the C code (cardano-crypto-wallet/cbits/encrypted_sign.c only):

  • Seems fine. ✔️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants