| name | apply-mobile-cryptography |
| description | Use when implementing cryptographic operations in a mobile app — encrypting data, hashing passwords, generating keys, signing data, or establishing secure communication channels between the app and backend. |
| source | OWASP Mobile Top 10 2024 M10 (owasp.org/www-project-mobile-top-10/); OWASP MASVS MSTG-CRYPTO; NIST SP 800-175B; Apple CryptoKit documentation; Android Keystore documentation |
| tags | ["security","owasp","mobile","cryptography","encryption","key-management","ios","android"] |
Apply Mobile Cryptography
Use platform-provided cryptographic APIs with approved algorithms (AES-256-GCM, ChaCha20-Poly1305, RSA-2048+) and hardware-backed key storage — never rolling custom crypto or hardcoding keys.
Why This Is Best Practice
Adopted by: OWASP Mobile Top 10 2024 M10 (Insufficient Cryptography). OWASP MASVS MSTG-CRYPTO-1 through MSTG-CRYPTO-6 specify mobile cryptography requirements. Apple's CryptoKit and Android's Keystore API are the official platform cryptography interfaces. NIST SP 800-175B defines approved algorithms. PCI DSS v4.0 Requirement 3.5 mandates strong cryptography for stored cardholder data.
Impact: OWASP's Mobile Security Testing Guide (MSTG) consistently finds weak cryptography in the top 3 mobile app vulnerabilities during assessments. Common findings: AES-ECB mode encryption (identical blocks → visible patterns), hardcoded keys in source code (recovered via static analysis), MD5/SHA-1 for security purposes (collision-vulnerable), and custom XOR encryption (trivially reversible). Mobile app binary analysis tools (jadx, Hopper, frida) make hardcoded keys trivially recoverable.
Why best: Custom cryptography implementations (rolling your own cipher, key derivation, or protocol) are the alternative — they are routinely broken because subtle implementation errors invalidate mathematical security proofs. Platform-provided cryptographic primitives are reviewed, maintained, and hardware-accelerated.
Sources: OWASP Mobile Top 10 2024 M10; OWASP MASVS MSTG-CRYPTO; NIST SP 800-175B; Apple CryptoKit documentation; Android Keystore system documentation
Steps
-
iOS — use Apple CryptoKit for all cryptographic operations:
import CryptoKit
func encrypt(data: Data, key: SymmetricKey) throws -> Data {
let sealedBox = try AES.GCM.seal(data, using: key)
return sealedBox.combined!
}
func decrypt(combined: Data, key: SymmetricKey) throws -> Data {
let sealedBox = try AES.GCM.SealedBox(combined: combined)
return try AES.GCM.open(sealedBox, using: key)
}
let key = SymmetricKey(size: .bits256)
-
Android — use Android Keystore for key generation and storage:
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import javax.crypto.Cipher
javax.crypto.KeyGenerator
javax.crypto.SecretKey
: SecretKey {
keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
)
keyGenerator.(
KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize()
.setUserAuthenticationRequired()
.build()
)
keyGenerator.generateKey()
}
: Pair<ByteArray, ByteArray> {
cipher = Cipher.getInstance()
cipher.(Cipher.ENCRYPT_MODE, key)
ciphertext = cipher.doFinal(plaintext)
Pair(cipher.iv, ciphertext)
}
Rules
- AES-ECB mode is never acceptable for any data longer than 16 bytes — identical input blocks produce identical ciphertext, revealing data patterns.
- IVs/nonces must be unique per encryption operation — reusing an IV with GCM mode completely breaks confidentiality.
- Keys derived from
SecRandomCopyBytes or SecureRandom are CSPRNG-generated; keys derived from Date().timeIntervalSince1970 or device IMEI are not.
- The Secure Enclave (iOS) and StrongBox (Android) cannot export keys — operations happen inside the hardware module. Use them for the highest-value keys.
Common Mistakes
- Using
AES/ECB/PKCS5Padding because it's in the Android documentation examples — older documentation used ECB; always use GCM.
- Deriving an encryption key from the user's password with SHA-256 — SHA-256 is a hash, not a KDF; use Argon2id, scrypt, or PBKDF2.
- Catching certificate validation exceptions and proceeding — "just for testing" certificates in development code often reach production.
- Storing IVs in a predictable location — IVs can be public, but must be random and stored alongside the ciphertext.