In diesem Dokument wird die ordnungsgemäße Verwendung der kryptografischen Funktionen von Android beschrieben. Außerdem finden Sie einige Beispiele für deren Verwendung. Wenn für Ihre App eine höhere Schlüsselsicherheit erforderlich ist, verwenden Sie das Android Keystore-System.
Anbieter nur mit dem Android Keystore-System angeben
Wenn Sie das Android Keystore-System verwenden, müssen Sie einen Anbieter angeben.
In anderen Fällen kann Android jedoch keinen bestimmten Anbieter für einen bestimmten Algorithmus garantieren. Wenn Sie einen Anbieter angeben, ohne das Android-Schlüsselspeichersystem zu verwenden, kann dies zu Kompatibilitätsproblemen bei zukünftigen Releases führen.
Empfohlenen Algorithmus auswählen
Wenn Sie den Algorithmus frei auswählen können (z. B. wenn keine Kompatibilität mit einem Drittanbietersystem erforderlich ist), empfehlen wir die folgenden Algorithmen:
Klasse | Empfehlung |
---|---|
Chiffre | AES im CBC- oder GCM-Modus mit 256-Bit-Schlüsseln (z. B. AES/GCM/NoPadding ) |
MessageDigest | SHA-2-Familie (z. B. SHA-256 ) |
Mac | HMAC der SHA-2-Familie (z. B. HMACSHA256 ) |
Unterschrift | SHA-2-Familie mit ECDSA (z. B. SHA256withECDSA ) |
Gängige kryptografische Vorgänge ausführen
In den folgenden Abschnitten finden Sie Snippets, die zeigen, wie Sie gängige kryptografische Vorgänge in Ihrer App ausführen.
Nachricht verschlüsseln
Kotlin
val plaintext: ByteArray = ... val keygen = KeyGenerator.getInstance("AES") keygen.init(256) val key: SecretKey = keygen.generateKey() val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING") cipher.init(Cipher.ENCRYPT_MODE, key) val ciphertext: ByteArray = cipher.doFinal(plaintext) val iv: ByteArray = cipher.iv
Java
byte[] plaintext = ...; KeyGenerator keygen = KeyGenerator.getInstance("AES"); keygen.init(256); SecretKey key = keygen.generateKey(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] ciphertext = cipher.doFinal(plaintext); byte[] iv = cipher.getIV();
Nachrichten-Digest generieren
Kotlin
val message: ByteArray = ... val md = MessageDigest.getInstance("SHA-256") val digest: ByteArray = md.digest(message)
Java
byte[] message = ...; MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(message);
Digitale Signatur generieren
Sie benötigen ein PrivateKey
-Objekt mit dem Signaturschlüssel, das Sie je nach Bedarf zur Laufzeit generieren, aus einer mit Ihrer App gebündelten Datei lesen oder aus einer anderen Quelle abrufen können.
Kotlin
val message: ByteArray = ... val key: PrivateKey = ... val s = Signature.getInstance("SHA256withECDSA") .apply { initSign(key) update(message) } val signature: ByteArray = s.sign()
Java
byte[] message = ...; PrivateKey key = ...; Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(key); s.update(message); byte[] signature = s.sign();
Digitale Signatur prüfen
Sie benötigen ein PublicKey
-Objekt mit dem öffentlichen Schlüssel des Unterzeichners. Sie können diesen aus einer Datei lesen, die mit Ihrer App gebündelt ist, aus einem Zertifikat extrahieren oder je nach Bedarf aus einer anderen Quelle abrufen.
Kotlin
val message: ByteArray = ... val signature: ByteArray = ... val key: PublicKey = ... val s = Signature.getInstance("SHA256withECDSA") .apply { initVerify(key) update(message) } val valid: Boolean = s.verify(signature)
Java
byte[] message = ...; byte[] signature = ...; PublicKey key = ...; Signature s = Signature.getInstance("SHA256withECDSA"); s.initVerify(key); s.update(message); boolean valid = s.verify(signature);
Komplexität der Implementierung
Einige Details der Android-Kryptografieimplementierung wirken auf den ersten Blick ungewöhnlich, sind aber aus Kompatibilitätsgründen erforderlich. In diesem Abschnitt werden die Probleme beschrieben, die am ehesten auftreten.
OAEP MGF1-Nachrichten-Digest
RSA-OAEP-Verschlüsselungen werden durch zwei verschiedene Nachrichten-Digests parametrisiert: den „Haupt-Digest“ und den MGF1-Digest. Es gibt Cipher
-IDs, die Digestnamen enthalten, z. B. Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding")
, die den Haupt-Digest angibt und den MGF1-Digest nicht spezifiziert. Für den Android Keystore wird SHA-1 für den MGF1-Digest verwendet, während bei anderen kryptografischen Anbietern von Android die beiden Digests identisch sind.
Wenn Sie mehr Kontrolle über die von Ihrer App verwendeten Hash-Werte haben möchten, fordern Sie eine Chiffre mit OAEPPadding an, wie in Cipher.getInstance("RSA/ECB/OAEPPadding")
, und geben Sie OAEPParameterSpec
bis init()
an, um beide Hash-Werte explizit auszuwählen.
Dies wird im folgenden Code veranschaulicht:
Kotlin
val key: Key = ... val cipher = Cipher.getInstance("RSA/ECB/OAEPPadding") .apply { // To use SHA-256 the main digest and SHA-1 as the MGF1 digest init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)) // To use SHA-256 for both digests init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT)) }
Java
Key key = ...; Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); // To use SHA-256 the main digest and SHA-1 as the MGF1 digest cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)); // To use SHA-256 for both digests cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
Eingestellte Funktionen
In den folgenden Abschnitten werden eingestellte Funktionen beschrieben. Verwenden Sie sie nicht in Ihrer App.
Bouncy Castle-Algorithmen
Die Bouncy Castle-Implementierungen vieler Algorithmen sind eingestellt. Dies gilt nur für Fälle, in denen Sie den Bouncy Castle-Anbieter ausdrücklich anfordern, wie im folgenden Beispiel gezeigt:
Kotlin
Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC") // OR Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))
Java
Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC"); // OR Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"));
Wie im Abschnitt Anbieter nur über das Android Keystore-System angeben erwähnt, wird davon abgeraten, einen bestimmten Anbieter anzufordern. Wenn Sie dieser Richtlinie folgen, sind Sie von der Einstellung nicht betroffen.
Passwortbasierte Verschlüsselungschiffren ohne Initialisierungsvektor
Bei PBE-Verschlüsselungen (Password-Based Encryption), die einen Initialisierungsvektor (IV) erfordern, kann dieser aus dem Schlüssel abgerufen werden, sofern er entsprechend aufgebaut ist, oder aus einem explizit übergebenen IV. Wenn Sie einen PBE-Schlüssel übergeben, der keine IV enthält, und keine explizite IV übergeben, wird bei den PBE-Verschlüsselungen unter Android derzeit eine IV von null angenommen.
Wenn Sie PBE-Chiffren verwenden, geben Sie immer eine explizite IV an, wie im folgenden Code-Snippet gezeigt:
Kotlin
val key: SecretKey = ... val cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC") val iv = ByteArray(16) SecureRandom().nextBytes(iv) cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv))
Java
SecretKey key = ...; Cipher cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC"); byte[] iv = new byte[16]; new SecureRandom().nextBytes(iv); cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
Krypto-Anbieter
Ab Android 9 (API-Ebene 28) wurde der JCA-Anbieter (Crypto Java Cryptography Architecture) entfernt. Wenn Ihre App eine Instanz des Krypto-Anbieters anfordert, z. B. durch Aufrufen der folgenden Methode, tritt eine NoSuchProviderException
auf.
Kotlin
SecureRandom.getInstance("SHA1PRNG", "Crypto")
Java
SecureRandom.getInstance("SHA1PRNG", "Crypto");
Krypto-Bibliothek für Jetpack-Sicherheit
Die Krypto-Bibliothek von Jetpack Security wird nicht mehr unterstützt. Dies betrifft nur Fälle, in denen die folgenden Abhängigkeiten in der build.gradle
-Datei Ihres App-Moduls enthalten sind:
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") }
Unterstützte Algorithmen
Folgende JCA-Algorithmus-IDs werden auf Android-Geräten unterstützt:
AlgorithmParameterGenerator
AlgorithmParameters
CertPathBuilder
CertPathValidator
CertStore
CertificateFactory
Cipher
KeyAgreement
KeyFactory
KeyGenerator
KeyManagerFactory
KeyPairGenerator
KeyStore
Mac
MessageDigest
SSLContext
SSLEngine.Supported
SSLSocket.Supported
SecretKeyFactory
SecureRandom
Signature
TrustManagerFactory