Package downloads
Each registry's method and its basis are in the table "How each registry's monthly figure is obtained" below. Counts are measured over about the last 30 days in 4 registries and are a 90-day count divided by 3 in 2. The figures for 4 registries are modelled, and CocoaPods has none. They cover 324 of the 355 catalogued cryptographic packages, and every total above sums exactly those. Of the rest, 9 name a package their registry has no record of, and 22 are Go packages inside a module, where the only available signal is the module's repository popularity, and that belongs to the module. Counting it again for each package inside would report one signal many times. A package whose count could not be collected is recorded as unmeasured, never as zero, and a run containing one is not published. Download counts reflect package manager installs (including CI/CD pipelines and transitive dependencies) and may overstate direct application usage.
Package-level scan
2,170,994 packages were listed across 11 ecosystems (npm, PyPI, Go Modules, Maven Central, crates.io, Packagist, NuGet, RubyGems, Hex, pub.dev, CocoaPods) in the scan collected August 3, 2026. 65,686 are counted as matching a catalogued cryptographic library: 12,465 are counted as depending on a library classed weak, 52,868 match modern-classed libraries only, and 353 are counted as declaring a catalogued post-quantum library, in npm (68), PyPI (19), Go Modules (5), crates.io (259), pub.dev (2). Three processing steps removed 19,287 other packages that matched before the counts were made. Maven Central and CocoaPods could not be counted: the catalogue's post-quantum entries for them name packages those registries do not have. Known issues are listed with each ecosystem above.
The packages listed include at least 37,242 that were not read. crates.io counts only crates it read, and Hex only packages it read. RubyGems and pub.dev count every failed request. Hex, RubyGems and pub.dev report none. Whether any pub.dev answer came without a pubspec, which its scanner does not count as a failure, has not been verified.
De-duplication, first of three processing steps, kept one package per registry and normalized name: @a/utils and @b/utils would count as one. It dropped 13,081 of the 84,973 that matched, itself no corrected count; whether each is a separate project is not verified.
The second removed 439 by name alone, such as names ending in -test or under three characters.
The third kept one of any three or more packages in a registry sharing a class and a namespace, so Go modules of one class under github.com/hashicorp became one. It dropped 5,767.
By class, the 19,287 removed were 3,525 counted as weak, 15,702 modern-classed only and 60 post-quantum, so each of the three class totals is low by its part. The split is from the run's output, which is not public.
The weak class mixes libraries that implement broken algorithms with libraries that are deprecated or unmaintained, and holds libraries that the corrected classes do not class as weak. Re-aggregated under those classes, the 12,465 packages counted as depending on a weak library become between 10,749 and 10,809; the 60 between are counted as weak only through libraries whose status is not verified.
2,018 of the 65,686 packages counted as matching a catalogued library are counted only through catalogue entries that are being taken out of the count or through a path-prefix match.
The totals add rows scanned to different limits, so a share of a total is a mixture weighted by those limits and describes no registry: crates.io is 44.5% of the 65,686 packages counted as matching a catalogued library, and the seven rows whose packages are the first part of a registry's list hold 60.8% of the 12,465 counted as weak. The dataset's two shares, weakShareOfCryptoUsing and pqcShareOfCryptoUsing, are such mixtures and are not printed on the page.
This scan is deposited as a citable dataset: 10.5281/zenodo.21791658. The deposit is the repository at a tag, so it resolves to fixed bytes rather than to a branch that moves underneath a citation. Cite that dated DOI rather than the concept DOI for the series, which always resolves to the most recent deposit and so would hand a later reader different figures from the ones quoted here. Issues measured in this dataset after it was deposited are recorded at https://github.com/ecolibria/crypto-census-data/blob/main/errata/2026-08-03.json.
Vulnerability data
CVE counts from NIST NVD REST API v2.0: direct queries for CWE-326 (Inadequate Encryption Strength), CWE-327 (Broken/Risky Crypto Algorithm), and CWE-328 (Weak Hash). These are exact NVD-tagged counts, not expanded via parent CWE hierarchies. Advisory data from GitHub Advisory Database (up to 2000 most recent advisories) filtered client-side for the same CWE IDs.
Classification
Weak: Libraries the catalogue classes as weak. The class mixes libraries that implement broken algorithms with libraries that are deprecated or unmaintained, and it holds libraries that the corrected classes do not class as weak. The corrected classes are not yet applied to the figures on this page. (e.g. broken algorithms such as MD5, SHA-1, DES, 3DES, RC4, Blowfish).
Modern: Actively maintained cryptographic libraries using current-generation algorithms. Includes both quantum-safe symmetric crypto (AES-256, SHA-256, ChaCha20) and quantum-vulnerable asymmetric crypto (RSA, ECDSA, Ed25519). The public-key algorithms in this tier are the ones NIST's draft IR 8547 would deprecate, at 112 bits of security strength, and then disallow. (e.g. AES-GCM, SHA-256, ECDSA, Ed25519, Argon2, bcrypt).
PQC: Implementations of NIST-standardized post-quantum algorithms (ML-KEM, ML-DSA, SLH-DSA) that resist both classical and quantum attacks. NIST's draft IR 8547 names them as the algorithms to migrate to. (e.g. ML-KEM (Kyber), ML-DSA (Dilithium), SLH-DSA (SPHINCS+)).
Stdlib packages providing both weak and strong algorithms are excluded to avoid inflating any tier.
Dates in NIST's draft transition plan
NIST IR 8547 (initial public draft, November 2024) lists classical public-key algorithms that provide 112 bits of security strength as deprecated after 2030, and classical public-key algorithms at every strength as disallowed after 2035. It gives no such date for symmetric ciphers and hash functions that provide at least 128 bits of security. The countdowns on this page run to the first day after each of those years. They are calendar arithmetic, not measurements, and the document is a draft that can change.
Ecosystems covered
npm (JavaScript/TypeScript), PyPI (Python), Go Modules, Maven Central (Java/Kotlin), crates.io (Rust), Packagist (PHP), NuGet (.NET), RubyGems (Ruby), Hex (Elixir/Erlang), pub.dev (Dart/Flutter), CocoaPods (Swift/Objective-C).
Category taxonomy
Packages are classified into 7 categories based on their primary cryptographic function:
- Hashing: Hash functions (MD5, SHA-*, BLAKE, CRC)
- Encryption: Symmetric ciphers and AEAD (AES, ChaCha20, DES, RC4)
- KDF / Password hashing: Key derivation and password hashing (PBKDF2, scrypt, Argon2, bcrypt)
- Signing and key exchange: Digital signatures and key exchange (ECDSA, EdDSA, RSA, ML-DSA)
- JWT: JWT/JWS/JWE token libraries
- TLS, SSH and other protocols: TLS stacks, SSH, and protocol implementations
- General purpose: Multi-purpose cryptographic libraries
Data freshness
The two layers refresh on different schedules, and each carries its own collection date shown above. A fresh download figure does not imply a fresh package scan. Download counts, GitHub enrichment and vulnerability data form the adoption layer, collected together and reflecting the most recent 30-day window each registry API provides. The package scan is a separate, far more expensive job run on its own schedule. Dates above are the actual collection dates of the data on this page, not the schedule it is meant to run on. All timestamps are UTC.
How each registry's monthly figure is obtained
Measured: the registry reports a monthly or 30-day count. Rescaled: a 90-day count divided by 3. Modelled: a proxy multiplied by an assumed constant, a lifetime total divided by an assumed number of months, or a fixed figure typed into the collector; shown for scale and not comparable with a measured count. Unmeasured: the registry publishes no count.
- npm: measured
- api.npmjs.org last-month point, window reported per response
- PyPI: measured
- pypistats.org last_month
- Go Modules: modelled
- fixed figures typed into the collector, with no source found, for 21 standard-library packages (87.2% of the total); GitHub stars x 1,000 for 11 modules; a flat 100,000 for each of 2 modules not on github.com
- Maven Central: modelled
- Maven Central versionCount x 50,000
- crates.io: rescaled
- crates.io recent_downloads (90 days) divided by 3
- Packagist: measured
- packagist.org downloads.monthly
- NuGet: modelled
- lifetime cumulative downloads divided by 36 assumed months
- RubyGems: modelled
- lifetime cumulative downloads divided by 120 assumed months
- Hex: rescaled
- hex.pm downloads.recent (90 days) divided by 3
- pub.dev: measured
- pub.dev downloadCount30Days
- CocoaPods: unmeasured
- CocoaPods trunk publishes no download counts; every figure is 0
| Registry | Method | Basis |
|---|
| npm | measured | api.npmjs.org last-month point, window reported per response |
| PyPI | measured | pypistats.org last_month |
| Go Modules | modelled | fixed figures typed into the collector, with no source found, for 21 standard-library packages (87.2% of the total); GitHub stars x 1,000 for 11 modules; a flat 100,000 for each of 2 modules not on github.com |
| Maven Central | modelled | Maven Central versionCount x 50,000 |
| crates.io | rescaled | crates.io recent_downloads (90 days) divided by 3 |
| Packagist | measured | packagist.org downloads.monthly |
| NuGet | modelled | lifetime cumulative downloads divided by 36 assumed months |
| RubyGems | modelled | lifetime cumulative downloads divided by 120 assumed months |
| Hex | rescaled | hex.pm downloads.recent (90 days) divided by 3 |
| pub.dev | measured | pub.dev downloadCount30Days |
| CocoaPods | unmeasured | CocoaPods trunk publishes no download counts; every figure is 0 |
The basis shown for Go Modules was corrected on October 6, 2026. The download data recorded it as "GitHub stars x 1,000; stdlib packages use fixed survey-derived estimates". The reason is in the list of changes to this page.