Skip to content

Pre-1.0: polyjose is not published yet, and its APIs may change before 1.0. Read the security policy before you rely on it.

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.

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.

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.

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.
The cryptographic libraries polyjose builds on, with their upstream project, license, what polyjose uses each one for, and its public audit status
CrateUpstreamLicenseWhat polyjose uses it forPublic audit status
aesRustCryptoMIT OR Apache-2.0The 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-gcmRustCryptoMIT OR Apache-2.0AES-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-kwRustCryptoMIT OR Apache-2.0AES 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.

cbcRustCryptoMIT OR Apache-2.0The CBC mode of AES-CBC content encryption with HMAC (A128CBC-HS256, A192CBC-HS384, A256CBC-HS512).No public independent audit found.

It is widely deployed.

hmacRustCryptoMIT OR Apache-2.0HMAC 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.

sha2RustCryptoMIT OR Apache-2.0SHA-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.

pbkdf2RustCryptoMIT OR Apache-2.0PBKDF2 key derivation for password-based encryption (PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW).No public independent audit found.

It is widely deployed.

p256RustCryptoMIT OR Apache-2.0The P-256 curve for ES256 signatures and ECDH-ES key agreement.No public independent audit found.

It is widely deployed.

p384RustCryptoMIT OR Apache-2.0The P-384 curve for ES384 signatures and ECDH-ES key agreement.No public independent audit found.

It is widely deployed.

p521RustCryptoMIT OR Apache-2.0The P-521 curve for ES512 signatures and ECDH-ES key agreement.No public independent audit found.

It is widely deployed.

k256RustCryptoMIT OR Apache-2.0The 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.

ecdsaRustCryptoMIT OR Apache-2.0The ECDSA signature algorithm shared by ES256, ES384, ES512 and ES256K.No public independent audit found.

It is widely deployed.

elliptic-curveRustCryptoMIT OR Apache-2.0The 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.

rsaRustCryptoMIT OR Apache-2.0RSA 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-bigintRustCryptoMIT OR Apache-2.0The 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.

zeroizeRustCryptoMIT OR Apache-2.0Clearing 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-dalekdalek-cryptographyBSD-3-ClauseThe 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-dalekdalek-cryptographyBSD-3-ClauseEd25519 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-dalekdalek-cryptographyBSD-3-ClauseX25519 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.

subtledalek-cryptographyBSD-3-ClauseComparing 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.

getrandomrust-randomMIT OR Apache-2.0Reading 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.

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.

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 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.”

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.

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 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.