Cryptographic foundations
This page describes polyjose 0.1.0 as designed. The library is in development and not published yet.
polyjose is designed to implement the JOSE standards (JWS, JWE, JWK and JWT) without implementing any cryptographic primitive itself. Signing and verification, encryption and decryption, hashing and MACs, and random number generation all come from established pure-Rust libraries. This page credits those libraries, says what polyjose uses each one for, and states what independent review each one has had.
Thank you to the maintainers and contributors of RustCrypto, dalek-cryptography and rust-random. polyjose is built on their work.
Why polyjose composes primitives
Section titled “Why polyjose composes primitives”Cryptographic primitives are easy to get subtly wrong and hard to test into correctness. A new implementation would put unreviewed code exactly where mistakes cost the most. So polyjose combines widely used implementations into the JOSE formats, and its own code stays in the JOSE layer: parsing and serialization, key formats, algorithm policy, and the key derivation that the JOSE specifications define on top of the primitives (the Concat KDF of ECDH-ES).
Everything that is not a cryptographic primitive, such as JSON, base64url and DER/PEM handling, is written in polyjose itself. That keeps the dependency tree to the primitives and their own dependencies.
How a library is chosen
Section titled “How a library is chosen”polyjose uses a cryptographic library only when all of these hold:
- It comes from the RustCrypto or dalek-cryptography projects, is written in pure Rust, and is actively maintained.
- It has no unresolved RustSec advisory at the version polyjose pins. A RustSec advisory check is planned for every pull request. The one exception,
rsa, is limited to operations the advisory does not affect; see below. - Its algorithm is not broken for the way JOSE uses it.
- It will be required to pass the RFC, NIST and Wycheproof test vectors at that exact version, in polyjose’s planned conformance tests.
- Its audit status is disclosed, on this page.
Where more than one library qualifies, polyjose prefers the one with the strongest independent audit record, then the widest deployment, then active maintenance. An independent audit counts in a library’s favour, but it is not required: several of the libraries below have none, and the table says so.
Randomness comes only from the operating system’s random number generator, through getrandom from the rust-random project.
Each library will be pinned to an exact version. An upgrade will go only through a change that reruns the full test suite and rechecks the library’s audit status. The exact versions will be listed here once polyjose is published.
Pure Rust gives memory safety, not freedom from side channels. How well each library resists timing attacks is described in its own documentation.
The libraries
Section titled “The libraries”Audit status is given as the reviewers and the libraries’ maintainers published it. A review of an earlier release does not cover code written since, so each entry says what was reviewed where that matters.
- Audited: a public independent report covers the library.
- Audited, earlier release: a public independent review exists, but it covered an earlier release line than the one polyjose uses, or it came before later fixes or a rewrite.
- No public independent audit found: no public independent audit of the library itself was found. These libraries are widely deployed.
| Crate | Upstream | License | What polyjose uses it for | Public audit status |
|---|---|---|---|---|
aes | RustCrypto | MIT OR Apache-2.0 | The AES block cipher beneath AES key wrapping (A128KW, A192KW, A256KW), AES-CBC content encryption (A128CBC-HS256, A192CBC-HS384, A256CBC-HS512) and AES-GCM. | No public independent audit found. It is widely deployed. |
aes-gcm | RustCrypto | MIT OR Apache-2.0 | AES-GCM content encryption (A128GCM, A192GCM, A256GCM) and AES-GCM key wrapping (A128GCMKW, A192GCMKW, A256GCMKW). | Audited, earlier release. NCC Group report (2020) Reviewed by NCC Group in 2020, for MobileCoin, with no significant findings. The review covered the 0.8 line; polyjose uses a later release line. |
aes-kw | RustCrypto | MIT OR Apache-2.0 | AES key wrapping for A128KW, A192KW and A256KW, also used by ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW and the PBES2 algorithms. | No public independent audit found. It is widely deployed. |
cbc | RustCrypto | MIT OR Apache-2.0 | The CBC mode of AES-CBC content encryption with HMAC (A128CBC-HS256, A192CBC-HS384, A256CBC-HS512). | No public independent audit found. It is widely deployed. |
hmac | RustCrypto | MIT OR Apache-2.0 | HMAC for HS256, HS384 and HS512 signatures, for the authentication tag of A128CBC-HS256, A192CBC-HS384 and A256CBC-HS512, and inside PBKDF2 for the PBES2 algorithms. | No public independent audit found. It is widely deployed. |
sha2 | RustCrypto | MIT OR Apache-2.0 | SHA-256, SHA-384 and SHA-512 for the HS, RS, PS and ES signature algorithms, RSA-OAEP-256, the ECDH-ES key derivation and JWK thumbprints. | No public independent audit found. It is widely deployed. |
pbkdf2 | RustCrypto | MIT OR Apache-2.0 | PBKDF2 key derivation for password-based encryption (PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW). | No public independent audit found. It is widely deployed. |
p256 | RustCrypto | MIT OR Apache-2.0 | The P-256 curve for ES256 signatures and ECDH-ES key agreement. | No public independent audit found. It is widely deployed. |
p384 | RustCrypto | MIT OR Apache-2.0 | The P-384 curve for ES384 signatures and ECDH-ES key agreement. | No public independent audit found. It is widely deployed. |
p521 | RustCrypto | MIT OR Apache-2.0 | The P-521 curve for ES512 signatures and ECDH-ES key agreement. | No public independent audit found. It is widely deployed. |
k256 | RustCrypto | MIT OR Apache-2.0 | The secp256k1 curve for ES256K signatures. | Audited, earlier release. NCC Group report (2023) Reviewed by NCC Group in 2023, for Entropy: two high-severity findings, both fixed. The review covered commits 0f27814 and 5c829a4 of k256 (report page 2, section 1, Executive Summary, Scope), on the 0.13 line; polyjose uses a later release line. |
ecdsa | RustCrypto | MIT OR Apache-2.0 | The ECDSA signature algorithm shared by ES256, ES384, ES512 and ES256K. | No public independent audit found. It is widely deployed. |
elliptic-curve | RustCrypto | MIT OR Apache-2.0 | The elliptic-curve arithmetic, key types and Diffie-Hellman shared by the P-256, P-384, P-521 and secp256k1 curves, for ES256, ES384, ES512, ES256K and ECDH-ES. | No public independent audit found. It is widely deployed. |
rsa | RustCrypto | MIT OR Apache-2.0 | RSA public-key operations only: verifying RS256, RS384, RS512, PS256, PS384 and PS512 signatures and encrypting to RSA-OAEP-256 recipients. | Audited, earlier release. Include Security report (2019) Reviewed by Include Security in 2019, with one minor finding. That review predates RUSTSEC-2023-0071 (the Marvin timing attack), and the crate's current rewrite has no published audit. polyjose uses it for public-key operations only. |
crypto-bigint | RustCrypto | MIT OR Apache-2.0 | The big-integer arithmetic beneath the rsa crate and the elliptic curves, for RS256, RS384, RS512, PS256, PS384, PS512, RSA-OAEP-256, ES256, ES384, ES512, ES256K and ECDH-ES. | Audited, earlier release. NCC Group report (2023) Reviewed by NCC Group in 2023, for Entropy, in the same review as k256. The review covered commits fde0661 and ad08a7e of crypto-bigint (report page 2, section 1, Executive Summary, Scope), on the 0.5 line; polyjose uses a later release line. The crate's maintainers report no significant findings, and note that the implementation has diverged significantly since that review. |
zeroize | RustCrypto | MIT OR Apache-2.0 | Clearing private keys, symmetric keys and passwords from memory when they are dropped, for HS256, HS384, HS512, ES256, ES384, ES512, ES256K, EdDSA, ECDH-ES, the AES key-wrap and content-encryption algorithms, dir and PBES2. | No public independent audit found. It is widely deployed. |
curve25519-dalek | dalek-cryptography | BSD-3-Clause | The Curve25519 arithmetic beneath Ed25519 signatures (EdDSA, Ed25519) and X25519 key agreement (ECDH-ES). | Audited, earlier release. Quarkslab report (2019) Reviewed by Quarkslab in 2019, for Tari, which found minor issues only; x25519-dalek and ed25519-dalek were reviewed only marginally. Fixes came after that review: RUSTSEC-2022-0093 in the 1.x line of ed25519-dalek, and a timing fix in Scalar arithmetic (RUSTSEC-2024-0344). polyjose uses a later release line. |
ed25519-dalek | dalek-cryptography | BSD-3-Clause | Ed25519 signatures for the EdDSA and Ed25519 algorithms. | No public independent audit found for this crate on its own: Quarkslab's 2019 review of the dalek libraries reviewed it only marginally, and RUSTSEC-2022-0093, which affected its 1.x line, was fixed after that review. It is widely deployed. |
x25519-dalek | dalek-cryptography | BSD-3-Clause | X25519 key agreement for ECDH-ES and ECDH-ES+A128KW, ECDH-ES+A192KW and ECDH-ES+A256KW with X25519 keys. | No public independent audit found for this crate on its own: Quarkslab's 2019 review of the dalek libraries reviewed it only marginally. It is widely deployed. |
subtle | dalek-cryptography | BSD-3-Clause | Comparing and selecting secret values inside the primitives and in polyjose, for example when checking HS256, HS384 and HS512 signatures and AES-CBC-HMAC authentication tags. | Audited, earlier release. Quarkslab report (2019) Reviewed by Quarkslab in 2019, for Tari, as part of its review of the dalek libraries, which found minor issues only. For this crate, the review checked that the source code, and the assembly that the Rust compiler version nightly-2019-06-11 generated from it, have no trivial time leak. In the post's words, the review "does not validate that the library is immune to time leaks on a specific piece of hardware or outside the scope of the library." Later releases have followed since. |
getrandom | rust-random | MIT OR Apache-2.0 | Reading the operating system's random number generator for key generation, content-encryption keys, initialization vectors, PBES2 salts and ECDH-ES ephemeral keys. | No public independent audit found. It is widely deployed. |
RSA: public-key operations only
Section titled “RSA: public-key operations only”polyjose uses rsa for public-key operations only, because RUSTSEC-2023-0071 (the Marvin attack) has no patched release. The advisory describes a timing side channel that can leak the private key, so it affects operations that use the private key: signing and decryption.
Public-key operations handle no secret, so polyjose offers them: verifying RS256, RS384, RS512, PS256, PS384 and PS512 signatures, and encrypting to RSA-OAEP-256 recipients. RSA signing, RSA decryption and RSA key generation are not offered; RSA private keys explains why and what to use instead.
No SHA-1 and no RSA1_5
Section titled “No SHA-1 and no RSA1_5”polyjose has no SHA-1 anywhere. So there is no RSA-OAEP, which RFC 7518 defines with SHA-1: use RSA-OAEP-256 or ECDH-ES instead. The sha1 crate is not a dependency, which is why it has no row in the table above. There is also no RSA1_5. See SHA-1 and RSA1_5 for the reasons.
What polyjose does not support lists everything that is left out and why.
subtle and zeroize
Section titled “subtle and zeroize”subtle and zeroize are not cryptographic primitives, but they are part of the primitives’ own security model. The RustCrypto and dalek libraries already use them: subtle to compare and select secret values, and zeroize to clear secrets from memory. polyjose uses the same two crates for its own secret comparisons and to wipe key material when it is dropped, rather than writing its own.
subtle describes itself as “pure-Rust traits and utilities for constant-time cryptographic implementations”, and as a “best-effort” attempt, “since side-channels are ultimately a property of a deployed cryptographic system including the hardware it runs on, not just of software.”
Licenses and notices
Section titled “Licenses and notices”The RustCrypto libraries and getrandom are licensed MIT OR Apache-2.0. The dalek-cryptography libraries, including subtle, are licensed BSD-3-Clause. All of them are compatible with polyjose’s own MIT license.
These licenses require their notices to be reproduced when the code is distributed in binary form. When polyjose is published, every prebuilt package (the npm packages, the Android library and the Apple XCFramework) will ship a THIRD-PARTY-NOTICES.txt that lists every crate compiled into it, including transitive dependencies, with its license notice.
Build-time crates on x86_64
Section titled “Build-time crates on x86_64”On x86_64 targets, curve25519-dalek uses its own code generator, curve25519-dalek-derive, to generate its SIMD backends while it compiles. That procedural macro brings in syn, quote, proc-macro2 and unicode-ident. These crates run only at build time and are not linked into the built library. They do appear in dependency listings such as cargo tree, so they are named here.
polyjose itself
Section titled “polyjose itself”polyjose itself has not yet had an independent audit. One is planned before 1.0. It will cover polyjose’s own code: its JSON, base64url and DER/PEM handling, the Concat KDF, and the way it combines the primitives.
polyjose is pre-1.0. Until that audit is published, treat polyjose as code without an independent review of its own, built on the libraries above. To report a security issue, see Reporting a vulnerability.