Cryptographic failures—previously known as Sensitive Data Exposure—ranked #2 in the OWASP Top 10 (2021) and remain one of the fastest ways attackers turn access into impact. With the OWASP Top 10 (2025) update expected soon, this topic is only growing in relevance: most breaches don’t come from “cracking” modern ciphers but from missing, weak, or misused cryptography.
In this guide, we break down what cryptographic failures are, why they lead to real-world incidents, the most common developer pitfalls (from no TLS to hard-coded secrets and weak hashing), and the concrete steps to prevent them. Use it to audit your stack now—so when the 2025 list lands, you’re already ahead of the curve.
What Are Cryptographic Failures?
In simple terms, cryptographic failures refer to the improper use or absence of cryptography that leads to exposure of sensitive data. In the OWASP Top 10 – 2021, this category replaced the broader “Sensitive Data Exposure” from the 2017 list, emphasizing failures in cryptographic mechanisms rather than just the fact that data was exposed. Essentially, any scenario where data that should have been encrypted or securely stored is left vulnerable – whether by using no encryption, weak encryption, or mismanaging keys and secrets – can be considered a cryptographic failure. Given the prevalence of data breaches and strict privacy regulations, developers need to treat user data like passwords, personal information, financial details, etc. with the highest security. Cryptographic failures open the door for attackers to access this data in transit or at rest, undermining user trust and potentially leading to legal penalties.
Why is this important? Proper cryptography is often the last line of defense that keeps attackers from reading sensitive data even if they breach other controls. OWASP elevated cryptographic failures to a top concern because many breaches aren’t due to hackers breaking strong encryption algorithms; rather, they exploit situations where encryption was absent or implemented incorrectly. In other words, most “sensitive data exposure” incidents result from failures to use cryptography correctly. Understanding this category helps developers and security teams focus on how and where to encrypt data, which algorithms and configurations to use, and how to manage keys and passwords safely.
Common Causes of Cryptographic Failures
Cryptographic failures can take many forms. Below are the most common causes and vulnerabilities that lead to sensitive data being exposed:
- No Encryption (Cleartext Data): Sensitive data is transmitted or stored in plaintext with no encryption at all. For example, an application might send personal information or credentials over plain HTTP or store them in a database without encryption. This leaves data “in the clear”, so anyone who intercepts network traffic or gains access to the storage can read it. Failing to use TLS for transport or not encrypting database fields means attackers can simply eavesdrop or steal files to obtain secrets. In short, if you’re not encrypting sensitive data both in transit and at rest, it’s only a matter of time before it’s exposed.
- Weak or Deprecated Algorithms: Using outdated or broken cryptographic algorithms or protocols is another failure mode. Algorithms like MD5, SHA-1, or DES, and old protocols like SSL 3.0 or early TLS versions, are well-known to be cryptographically broken and crackable. Yet, they still lurk in legacy systems and libraries. Attackers can relatively easily break these algorithms via brute force or cryptanalytic attacks. For instance, hashes generated by MD5 or unsalted SHA-1 can be cracked with precomputed tables, and old ciphers like RC4 or DES can be broken with modern computing power. If your application relies on such algorithms, encrypted data may be as good as plaintext to determined attackers. Always use strong, current standards (e.g. AES-256, SHA-256/3, TLS 1.2+).
- Poor Key Management: Encryption is only as secure as the keys you use – and how well you protect them. A very common cryptographic failure is mismanaging secret keys or passwords. This includes practices like hard-coding encryption keys or credentials in source code, reusing the same keys in multiple places, failing to rotate keys, or storing keys in plaintext config files accessible to the world. If an attacker finds a hard-coded key (say in a public GitHub repo or an APK), they can use it to decrypt data or gain privileged access. Similarly, using weak keys (short or guessable values) or leaving keys past their expiration is dangerous. Proper key management means using secure storage (like vaults or HSMs), restricting access, regularly rotating/expiring keys, and never embedding secrets directly in code.
- Insecure Random Number Generation: Cryptographic functions often require random numbers (for keys, initialization vectors, nonces, etc.). Using a non-cryptographic random generator (like
Math.random()
in many languages) or a predictable source of entropy is a serious vulnerability. If random values like IVs or session tokens can be predicted, attackers can potentially decrypt data or forge tokens. Cryptographic failures occur when developers use insufficient entropy or reuse values that should be random. For example, reusing the same IV for multiple encryption operations in certain modes (like CBC) can leak information. Always use a cryptographically secure pseudorandom number generator (CSPRNG) provided by your platform for keys, IVs, tokens, and ensure you never reuse one-time values like nonces. A related issue is seeding a PRNG with a constant or predictable value – this defeats the purpose of randomness. - Misconfigured TLS/SSL Settings: Encryption in transit can fail due to configuration issues even if you’re using HTTPS. Common mistakes include allowing weak SSL/TLS protocols or ciphers, not validating SSL certificates, or missing crucial security headers. For instance, if your server accepts self-signed or expired certificates without warning, an attacker could perform a man-in-the-middle attack by presenting a fake certificate. Similarly, supporting outdated versions like TLS 1.0 or not enabling secure cipher suites can allow protocol downgrade attacks or eavesdropping. Not enforcing HTTPS everywhere (e.g. missing HSTS headers or content over mixed HTTP) also exposes data to interception. A cryptographic failure means that although encryption technology exists, it’s not effectively applied – often due to misconfigurations that leave gaps for attackers.
- Plaintext or Weakly-Hashed Passwords: Storing passwords (or other sensitive data) in plaintext is an obvious failure, but even hashing them incorrectly counts as a cryptographic failure. Weak hashing practices include using fast, unsalted hashes (like unsalted MD5 or SHA-1) for passwords. Attackers with a leaked password hash database can crack unsalted or weak hashes extremely quickly using rainbow tables or GPU brute-force. For example, an unsalted SHA-1 hash of “password123” can be reversed in seconds with common tools. Proper practice is to use slow, adaptive hashing algorithms with salt, such as bcrypt, PBKDF2, or Argon2. If an application fails to do so – or worse, stores passwords in plaintext – it’s a textbook cryptographic failure. (On the flip side, note that encryption is not appropriate for passwords – they should be irreversibly hashed. Using “encryptions” that are reversible for password storage is also a design failure.)
- Hard-Coded Credentials or Secrets: A special mention should be made of secrets embedded in code or config, since it’s so prevalent. This overlaps with poor key management, but goes beyond encryption keys to things like API keys, tokens, or credentials. If these secrets are exposed (through code repositories, mobile app decompilation, etc.), attackers get instant access to whatever the secrets protect – without needing to exploit an algorithm. For example, a hard-coded database password or API token in a mobile app is a goldmine for attackers who reverse-engineer the app. Always externalize and secure secrets; never commit them to source control. Use environment variables or dedicated secret management services.
Each of the above issues represents a failure to effectively protect data through cryptography. The good news is that all of them are avoidable with proper practices, which we’ll cover below.
Real-World Examples of Cryptographic Failures
To understand the impact of cryptographic failures, let’s look at a few real-world incidents where inadequate or broken encryption practices led to serious security breaches:
1. RockYou2021 – Massive Plaintext Password Leak (2021)
One of the largest password leaks in history occurred in 2021, dubbed RockYou2021. A compilation of 8.4 billion passwords was released on a hacker forum – all in plaintext. This wasn’t from a single breach, but rather a collection of many data leaks over the years where companies had stored passwords improperly (i.e. either unhashed, or with weak hashing that was cracked). The name alludes to the infamous 2009 RockYou breach (32 million plaintext passwords) but on an even larger scale. RockYou2021 highlighted systemic failures in password storage across many organizations – essentially a cryptographic failure by multiple parties. Had those passwords been hashed with strong, salted algorithms, the compilation wouldn’t have been usable. Instead, billions of credentials were exposed in human-readable form, putting countless users at risk. This example underscores the importance of strong password hashing: weak or no cryptography in storing passwords can lead to industry-wide credential exposure.
2. Toyota’s GitHub Key Exposure (2022)
In 2022, a subcontractor for Toyota suffered a breach that demonstrates how poor key management can undermine security. The contractor accidentally uploaded private encryption keys, access tokens, and other secrets to a public GitHub repository, where they remained exposed for some time. These keys were used in Toyota’s internal supply chain systems. Fortunately, Toyota reported no known damages from the incident, but the potential was huge – attackers with those keys could have accessed sensitive internal data or services. This breach was a classic cryptographic failure: not an attack on an algorithm, but a mistake in handling secrets. It underscores the risk of hard-coding or mishandling keys and credentials. Had proper secret management been in place (e.g. using a secure vault and scanning repositories for secrets), this could have been avoided. Toyota’s incident serves as a cautionary tale to all developers: treat keys and tokens like live explosives – never expose them in public code. Even large enterprises can slip up, so implement automated checks and training to prevent secret leaks.
3. Facebook’s Plaintext Passwords in Internal Logs (2019)
In early 2019, Facebook revealed that hundreds of millions of user passwords had been stored in plain text within their internal systems for years. These passwords were accessible to thousands of Facebook employees and were not encrypted or hashed as industry standards require. This disclosure was shocking given Facebook’s size and technical prowess – it illustrated that even top tech companies can commit fundamental security errors. While Facebook claimed the passwords were not exposed outside the company, this was still a major cryptographic failure in password storage practices. It violated the principle that passwords should be salted and hashed so that not even internal staff can read them. The incident tarnished Facebook’s security reputation and reminded everyone that storing passwords in plain text (even in internal logs or servers) is unacceptable. Had a malicious insider or an external attacker compromised those internal logs, they would have obtained millions of real user passwords. Facebook’s mishap reinforces why strong hashing of passwords is absolutely critical – and why you should double-check that every place your application handles credentials is secure.
As these examples illustrate, cryptographic failures are often less about “cracking” encryption and more about organizations not using encryption properly in the first place. Next, we’ll cover how to avoid these mistakes.
Best Practices to Prevent Cryptographic Failures
Preventing cryptographic failures comes down to applying strong encryption everywhere it’s needed, and handling your keys and data with care. The following best practices will help ensure that sensitive data in your application remains confidential and protected even if other defenses fail:
1. Encrypt Sensitive Data in Transit and at Rest with Strong Algorithms
Make sure all sensitive data is encrypted, both when it’s transmitted over networks and when it’s stored. Use proven, up-to-date encryption standards rather than custom or obsolete schemes. For data in transit, that means using HTTPS (TLS) for all client-server communications – ideally TLS 1.2 or TLS 1.3 – and disabling any insecure protocols or cipher suites (no HTTP, SSLv3, or TLS 1.0/1.1). Enable HTTP Strict Transport Security (HSTS) to enforce HTTPS usage. For data at rest, use strong encryption like AES-256. Many modern databases and cloud storage services support encryption at rest – ensure it’s enabled for fields like passwords, personal info, credit card numbers, etc. Do not rely on weak ciphers or homegrown algorithms. For example, don’t use XOR “encryption” or Base64 as a substitute – those are trivially reversible and not true security. By using well-vetted algorithms and libraries (and keeping them updated to patch any flaws), you drastically reduce the risk of attackers deciphering your data. Remember, strong encryption is effective only if applied universally: if even one sensitive field or API endpoint is left in plaintext, attackers will find and exploit that one weak link.
2. Implement Secure Key Management
Proper key management is often the Achilles’ heel of crypto implementation. Follow the principle that keys and secrets should be handled with at least as much care as the data they protect. Never hard-code secrets or encryption keys in your source code or config files that might end up in source control. Instead, use secure secret storage solutions – for example, environment variables (for small projects) or dedicated services like AWS KMS, Azure Key Vault, HashiCorp Vault, etc., which keep keys encrypted and accessible only to authorized services. Enforce key rotation policies: don’t use the same key forever. Rotate keys periodically and certainly replace them if you suspect a breach. Also, use strong, randomly generated keys of appropriate length; avoid human-memorable passwords or keys for system encryption. Control access to keys – minimize who or what can access decryption keys (principle of least privilege). For application-level encryption, consider implementing envelope encryption (data encrypted with a data key, which is in turn encrypted by a master key in a vault). This way, if the data key is exposed, the master key is still needed to use it. In short, managing keys safely is non-negotiable: a failure here can nullify even the strongest algorithms. (We’ll soon publish a detailed guide on key management – stay tuned for that.)
3. Use Strong Password Hashing Algorithms (Never Store Passwords in Plain Text)
When it comes to user passwords (and similar secrets like PINs), never store them in plain text or using reversible encryption. Instead, hash passwords with a strong, adaptive hashing algorithm and a unique salt per password. Recommended algorithms in 2025 include Argon2id, bcrypt, scrypt, or PBKDF2 (with a high iteration count). These functions are designed to be slow and resource-intensive, which greatly hinders attackers’ ability to crack hashes using brute force or GPUs. Avoid outdated or fast hashes like MD5, SHA-1, or unsalted SHA-256 – those are considered cryptographic failures today because they are too easy to reverse with modern hardware. Also ensure your implementation uses a proper salt (most modern hash libraries do this for you) so that each password yields a unique hash, even if two users have the same password. This prevents rainbow table attacks. By using strong hashing, even if your password database is compromised, attackers will not have immediate access to user passwords – it would take them an impractical amount of time to crack strong hashes (ideally, longer than the password’s lifetime). For example, hashing a password with bcrypt (cost factor 12) or Argon2 will slow down an attacker’s attempts drastically compared to a plain SHA-1 hash. Bottom line: storing passwords securely is one of the most critical duties of a developer – it’s directly in your users’ trust. (For a deeper dive into implementing password hashing and salting correctly, see our article Password Hashing & Salting – Function and Algorithm Explained, which covers these concepts in detail.)
4. Enforce TLS and Protect Data in Transit
It’s not enough to “support” HTTPS – you should enforce it everywhere to prevent downgrades or accidental exposure. Configure your application and web server to redirect all HTTP traffic to HTTPS. Use HSTS headers so that browsers remember to always use HTTPS for your site. Ensure that your TLS configuration is robust: use certificates from a trusted CA and do not allow invalid certificates. Your app should validate the server’s certificate chain and hostname. If you have an API client or mobile app, don’t skip certificate validation (and consider certificate pinning for extra security, though manage pinning carefully to avoid lockout on cert changes). Disable legacy protocols and weak cipher suites in your server config – for instance, only allow strong ciphers (e.g., AES-GCM or ChaCha20-Poly1305) and prefer using TLS 1.2 and 1.3. Regularly check your SSL/TLS configuration with tools (like SSL Labs test) to ensure there are no obvious weaknesses. By doing this, you prevent man-in-the-middle (MITM) attacks where attackers could otherwise intercept or alter data. A common cryptographic failure is a site that doesn’t force HTTPS, allowing an attacker to strip encryption by redirecting a user to an HTTP version (SSL stripping). Another is not implementing secure cookies (set the Secure and HttpOnly flags), which could expose session IDs. Treat any network that isn’t encrypted as hostile – always assume someone is listening. Full transport layer protection is a must for any app dealing with user data. (For more on TLS and avoiding MITM risks, keep an eye out for our upcoming post on securing data in transit.)
5. Use Cryptographically Secure Randomness and Safe Protocol Implementations
A subtler but important best practice is to use cryptography the way it was intended – which means leveraging secure libraries and not bypassing their safeguards. Always generate random numbers, IVs, tokens, and passwords using a cryptographically secure random number generator (CSPRNG) provided by your platform. For example, in Python use secrets.randbits
or os.urandom
rather than random.random()
. In Java, use SecureRandom
instead of java.util.Random
. In JavaScript, use the Web Crypto API (like window.crypto.getRandomValues
). These CSPRNGs are designed to produce unpredictable values suitable for cryptographic use. Never attempt to create your own random generator or use time-based or Math.random seeds for crypto, as they will be predictable. Similarly, follow proper encryption mode usage: if using AES, prefer authenticated modes (like AES-GCM or ChaCha20-Poly1305) to prevent manipulation of ciphertext. If using CBC mode, ensure you use a new random IV for each encryption operation (and never reuse an IV with the same key). Do not disable padding checks or other security features unless you really know what you’re doing – such tweaks have led to padding oracle vulnerabilities. Essentially, use battle-tested libraries (like OpenSSL, BoringSSL, libsodium, etc.) and follow their documentation and best practices. Don’t try to invent clever shortcuts or “optimize” cryptographic steps – that’s how critical bugs like Heartbleed and others creep in. Keep your crypto libraries up to date as well, since updates often fix flaws. By using secure random values and standard protocols correctly, you eliminate many of the side-channel and implementation bugs that can plague custom crypto code.
6. Minimize Sensitive Data Storage and Exposure
One of the simplest ways to avoid cryptographic failures is not to have sensitive data lying around in the first place. Only collect and store what you truly need. If you don’t store a piece of data, you don’t have to encrypt it – and it can’t be stolen or leaked. As the OWASP guidelines put it: “Don’t store sensitive data unnecessarily… Data that is not retained cannot be stolen.” If you need to keep data for business reasons, consider techniques like tokenization or truncation. For example, you might store only the last 4 digits of a credit card number along with a token provided by a payment processor, rather than the full card number. That way, even if your database is compromised, the attacker doesn’t get the actual card details. Apply data classification in your system: identify which data is highly sensitive (personal info, financial info, health info, passwords, secrets) and ensure it’s encrypted and access-controlled at the highest level. Less sensitive data might not need the same level of encryption (or any encryption) – but be careful in making that judgment, and consider privacy laws. Also, purge data you no longer need. Have retention policies that securely delete sensitive records after they are no longer required. Many breaches have been worsened because years of old data were left in an archive and got stolen. By limiting the amount and duration of sensitive data storage, you reduce your risk. In practice: turn off unnecessary logging of personal data, don’t include sensitive info in URL parameters (they often end up in logs), and use encryption wherever feasible in backups, exports, or inter-service communications. In summary, lean data practices plus encryption give attackers much less to find even if they break in.
Cryptographic Failure Prevention Checklist
To quickly assess your application’s defenses against cryptographic failures, run through this checklist of questions and controls (if you answer “no” to any, that’s an area to fix):
- Are we encrypting all sensitive data, both in transit and at rest? (No sensitive info should travel or sit in plaintext)
- Are we using strong, modern encryption algorithms and protocols? (e.g. AES-256 for data, TLS 1.2+/HTTPS for transport; no deprecated ciphers or SSL)
- Are encryption keys and secrets managed securely? (Stored in a secure vault or keystore, not in code; with proper access control and rotation)
- Are passwords hashed with a strong salted algorithm? (No plaintext or weak hashes – use bcrypt, Argon2, etc., with unique salts for each password)
- Do we enforce TLS and validate certificates? (HTTPS everywhere, HSTS enabled, no acceptance of self-signed certs in production)
- Are we using secure random values for all cryptographic needs? (Session IDs, tokens, IVs, etc. generated with a CSPRNG, never hardcoded or predictable)
If you can confidently check off each of these items, you’ve significantly reduced your risk of falling victim to OWASP A02 cryptographic failures.
Conclusion & Next Steps
Cryptographic failures continue to be a major threat to applications, but by understanding their causes and following best practices, you can drastically lower the chances of a breach. Remember that attackers will always target the weakest link – if you consistently encrypt sensitive data and handle keys/passwords properly, you’ve removed a huge class of easy exploits from their toolbox. Many of the tips above map directly to OWASP’s recommendations for protecting data everywhere, underscoring that these are not just “nice-to-have” measures but essential security hygiene.
As a developer or security professional, it’s also wise to stay updated. Threats evolve, and so do cryptographic standards. Keep an eye on emerging guidance from OWASP, NIST, and other authorities for when algorithms need to be phased out (for example, SHA-1 was once standard, now it’s disallowed), or when new vulnerabilities (like cryptographic library bugs) are discovered. Implement regular code reviews or automated scans for hard-coded secrets and improper crypto usage. It’s easier to fix a weakness before your product is in production than after a breach.
Finally, consider leveraging tools and services that take the heavy lifting of security off your shoulders. For example, Authgear provides a ready-made authentication and user management solution with robust security built-in – including encrypted data storage, secure token handling, and adherence to cryptographic best practices out of the box. Instead of reinventing the wheel (and risking mistakes), you can rely on such a platform to handle sensitive user data in a compliant, secure manner.
Get started with Authgear – sign up for a free trial or request a demo today – and see how easy it is to integrate strong security into your applications. Don’t wait until after a breach to prioritize cryptography; start preventing cryptographic failures now and stay ahead of threats. Your data deserves nothing less than the best protection.
FAQ: Cryptographic Failures (OWASP Top 10 A02)
1) What is a cryptographic failure (OWASP A02)?
It’s any weakness caused by missing, weak, or misused cryptography that exposes sensitive data—e.g., no TLS, outdated ciphers, poor key handling, or weak password hashing.
2) How is this different from “Sensitive Data Exposure”?
OWASP renamed the category to focus on the root causes. “Sensitive Data Exposure” described the outcome; Cryptographic Failures describes the misconfigurations and bad choices that lead to it.
3) What data should be encrypted?
Anything sensitive: credentials, personal data, tokens, financial/health info, secrets, and backups. Encrypt in transit (TLS) and at rest (e.g., AES-256). Avoid logging sensitive data.
4) Which algorithms/protocols should I use (and avoid)?
Use: TLS 1.2/1.3; AES-GCM or ChaCha20-Poly1305; Argon2id/bcrypt/PBKDF2 for passwords; modern libs (libsodium, OpenSSL).
Avoid: MD5, SHA-1, RC4, DES/3DES, custom/“homegrown” crypto, outdated SSL/TLS versions.
5) How should I store user passwords?
Never plaintext or reversible encryption. Use salted, adaptive hashes (Argon2id or bcrypt; PBKDF2 with high iterations). Optionally add a server-side pepper, stored separately.
6) What are common cryptographic mistakes?
Hard-coded keys/secrets, weak/random-looking but predictable PRNGs, IV/nonce reuse, accepting invalid TLS certs, mixed content (HTTP on HTTPS pages), and failing to rotate keys.
7) How do I handle keys and secrets safely?
Don’t commit them to code or mobile apps. Use a secrets manager/KMS, restrict access (least privilege), rotate regularly, monitor usage, and audit repos with secret-scanning.
8) How can I detect cryptographic failures during development?
Combine SAST/DAST, dependency and TLS config scanners, secret-scanning, and manual reviews. Add unit/integration tests for crypto settings (e.g., enforcing TLS, blocking weak ciphers).
9) Do I always need encryption, even internally?
Yes, if data is sensitive. Assume internal networks and logs can be accessed in an incident. Also practice data minimization—don’t collect/store what you don’t need.
10) How can Authgear help?
Authgear centralizes secure auth flows, strong password hashing, token handling, and TLS-first integrations—reducing crypto foot-guns and helping you meet OWASP best practices faster.