Skip to content

Add Argon2id key derivation function#427

Open
madhav1k wants to merge 2 commits intoapple:mainfrom
madhav1k:main
Open

Add Argon2id key derivation function#427
madhav1k wants to merge 2 commits intoapple:mainfrom
madhav1k:main

Conversation

@madhav1k
Copy link

@madhav1k madhav1k commented Jan 19, 2026

Add Argon2id key derivation function (RFC 9106)

Checklist

  • I've run tests to see all new and existing tests pass
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

If you've made changes to gyb files

  • I've run ./scripts/generate_boilerplate_files_with_gyb.sh and included updated generated files in a commit of this pull request

Motivation:

Argon2id is the recommended password hashing algorithm by OWASP and the winner of the Password Hashing Competition. It provides superior resistance to GPU/ASIC attacks compared to bcrypt and PBKDF2. BoringSSL does not currently include Argon2, making a pure Swift implementation necessary for cross-platform support.

Modifications:

- Added KDF.Argon2id public API following the existing KDF.Scrypt pattern
- Implemented pure Swift Argon2id (RFC 9106) with internal BLAKE2b primitive (variable-length output of 64–1024 bytes required by Argon2, not available in BoringSSL's fixed BLAKE2b-256)
- Added test case verified against official RFC 9106 Section 5.3 test vector

Files added:
- Sources/CryptoExtras/Key Derivation/Argon2/Argon2.swift
- Sources/CryptoExtras/Key Derivation/Argon2/Native/Argon2id+Native.swift
- Sources/CryptoExtras/Key Derivation/Argon2/Native/Blake2b.swift
- Tests/CryptoExtrasTests/Argon2Tests.swift

Result:

Users can derive cryptographic keys using Argon2id:

let key = try KDF.Argon2id.deriveKey(
    from: password,
    salt: salt,
    outputByteCount: 32,
    iterations: 3,
    memoryByteCount: 64 * 1024 * 1024,
    parallelism: 4
)

Copy link
Contributor

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR!

This is an interesting idea. However, because it lacks a BoringSSL backend, I think the bar for accepting it into this repo is quite high. In general things without BoringSSL backends can just as easily be shipped outside swift-crypto as inside, because there is no need for a new set of C backend libraries. To that end, I'd encourage you to publish this code as a standalone Swift package.

@madhav1k
Copy link
Author

Thank you for the quick response. I appreciate the desire to stay close to BoringSSL's feature set.

I'd like to share why I believe Argon2id is a critical addition for the Swift community right now:

  1. Essential Migration: Argon2id is the modern replacement for bcrypt and scrypt. New projects are currently forced to either use legacy algorithms or rely on third-party packages. Providing this in swift-crypto enables developers to start with the best possible security defaults.
  2. First-Party Integration: In the crypto space, "who" wrote the code matters as much as the code itself. An implementation inside the apple/swift-crypto org provides the level of trust required for enterprise and security-sensitive applications to migrate away from older standards. While several third-party Argon2 packages exist, providing a verified implementation within swift-crypto ensures a higher standard of auditability and consistent integration with the library's KeyDerivation patterns. While a standalone package is an option, it would lack the deep integration with CryptoExtras types (like SymmetricKey or PBKDF2) and the first-party auditability that developers expect when implementing modern standards like Argon2id. This provides a clear, official recommendation for developers moving away from PBKDF2 or legacy algorithms.
  3. BLAKE2b Technical Constraint: During implementation, I explored using the existing BoringSSL BLAKE2b backend. However, BoringSSL's implementation is fixed-length (256-bit), whereas the Argon2 specification (RFC 9106) strictly requires variable-length output (typically 64 bytes up to 1024 bytes). This necessitated a focused, internal BLAKE2b implementation to ensure RFC compliance.
  4. Pure Swift Safety: This implementation avoids the complexity and security surface area of vendoring another C library (like the reference PHC Argon2 C code), while still passing all RFC 9106 test vectors.
  5. Upstream Alignment: I have already submitted the Argon2id implementation to BoringSSL (Gerrit 87627). While the upstream path is the ideal long-term resolution, the review and vendoring cycle can be extensive. Providing this Swift-native implementation in CryptoExtras allows the community to adopt Argon2id immediately, with the flexibility to swap the backend logic once it is fully vendored upstream.

Given the importance of Argon2id for modern security, would you be open to hosting this Swift-native version in CryptoExtras as the upstream BoringSSL work progresses? If not we can wait for the BoringSSL implementation to be merged.

@Lukasa
Copy link
Contributor

Lukasa commented Jan 23, 2026

I remain inclined to think that a best version of the Swift ecosystem is one in which people feel comfortable doing important work outside of Apple-owned repositories. Swift Crypto has access to the vendored copy of BoringSSL, which provides some of the best cryptographic implementations on the planet in terms of performance and correctness. That's highly valuable, and getting access to those primitives is a good reason to add something to the library. When that access is unnecessary, I want to encourage folks to feel free to innovate away from the slower cycles of this library.

As and when BoringSSL support lands, we can of course revisit.

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.

2 participants