Crypto Agility (Hardcoded Algorithm Selection)

ID

kotlin.crypto_agility

Severity

info

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Cryptography

Language

Kotlin

Tags

ASVS50:v11.2.1, ASVS50:v11.6.1, CWE:327, NIST.IR.8547, OWASP:2025:A04, crypto, crypto-agility, pqc, quantum

Description

Flags a cryptographic API call that selects a quantum-relevant algorithm with the choice hardcoded in source — whether passed as a literal argument (e.g. getInstance("RSA")) or fixed by the chosen API / function / type itself (e.g. rsa.GenerateKey, hashlib.sha256(), P256.Signing.PrivateKey()). When the algorithm is baked into code, changing it — most importantly the migration to post-quantum cryptography — becomes a code change rather than a configuration change. This is the crypto-agility axis of post-quantum readiness, complementary to pqc_readiness (which algorithms must migrate) and pqc_weak_keylength (which key sizes are too small).

Rationale

Crypto-agility is the ability to swap a cryptographic algorithm with minimal disruption. A call that hardcodes its algorithm — whether as a literal argument (KeyPairGenerator.getInstance("RSA")) or by calling an algorithm-specific API/function/type directly (rsa.GenerateKey, hashlib.sha256(), P256.Signing.PrivateKey()) — ties the choice to the source: every algorithm change requires editing, rebuilding and redeploying code. Externalizing the choice — reading the algorithm from configuration, or selecting it through a provider/factory abstraction — turns the post-quantum migration (and any future change) into a configuration update.

A finding is raised when the algorithm is statically determined in source (a literal/compile-time constant argument, or fixed by the chosen API); a value read from runtime configuration does not resolve and is treated as already agile. Only quantum-relevant primitives are reported — algorithms broken by Shor’s algorithm (public-key) or weakened by Grover’s (symmetric/hash) — since those are the ones that will need to change; an already quantum-safe choice (e.g. ML-KEM) is not flagged.

In Kotlin the algorithm is hardcoded as the JCA factory argument; reading it from configuration instead keeps the choice swappable:

KeyPairGenerator.getInstance("RSA")        // hardcoded — the PQC swap is a code change
Cipher.getInstance("AES/CBC/PKCS5Padding") // hardcoded algorithm selection

KeyPairGenerator.getInstance(cfg.keyAlgorithm()) // agile — algorithm comes from configuration

Remediation

Externalize the algorithm selection so it is not hardcoded at the call site: read the algorithm name from configuration, or obtain the primitive through a provider/factory abstraction whose algorithm is configurable. The goal is that the next algorithm change — notably the post-quantum migration to ML-KEM / ML-DSA (optionally in a classical+PQC hybrid) — is a configuration change, not a code change.

References

  • CWE-327 : Use of a Broken or Risky Cryptographic Algorithm.

  • NIST IR 8547 : Transition to Post-Quantum Cryptography Standards.

  • NIST SP 1800-38 : Migration to Post-Quantum Cryptography.