2017-01-23 4 views
0

Meine App verwendet den Schlüsselspeicher von Android, um einige Daten nach der Authentifizierung mit einem Fingerabdruck zu verschlüsseln. Nutzer von Google Pixel-Geräte die folgende Ausnahme berichten geworfen:InvalidKeyException auf Google PIxel-Geräten

java.security.InvalidKeyException: Es wird nur SecretKey unterstützt

Mein Code für die Verschlüsselung im Grunde das bedeutet:

_keystore.Load(null); 
       _keyGen.Init(new KeyGenParameterSpec.Builder(_keyId, 
        KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt) 
        .SetBlockModes(KeyProperties.BlockModeCbc) 
        // Require the user to authenticate with a fingerprint to authorize every use 
        // of the key 
        .SetUserAuthenticationRequired(true) 
        .SetEncryptionPaddings(KeyProperties.EncryptionPaddingPkcs7) 
        .Build()); 
       _keyGen.GenerateKey(); 

Cipher _cipher = Cipher.GetInstance(KeyProperties.KeyAlgorithmAes + "/" 
               + KeyProperties.BlockModeCbc + "/" 
               + KeyProperties.EncryptionPaddingPkcs7); 

KeyStore _keystore = KeyStore.GetInstance("AndroidKeyStore"); 
FingerprintManager _fingerprintManager = (FingerprintManager) Context.GetSystemService(Context.FingerprintService); 

_keystore.Load(null); 
var key = _keystore.GetKey(_keyId, null); 
_cipher.Init(CipherMode.EncryptMode, key); 
_cryptoObject = new FingerprintManager.CryptoObject(_cipher); 
_fingerprintManager.Authenticate(_cryptoObject, _cancellationSignal, 0 /* flags */, this, null); 

//OnAuthSucceeded: 
var mySecret = _cipher.DoFinal(System.Text.Encoding.UTF8.GetBytes(textToEncrypt)); 

Es ist wie GetKey scheint gibt null zurück. Unterstützen diese neuen Geräte nur die asymmetrische Verschlüsselung? Bedeutet das, dass ich ein Schlüsselpaar generieren muss oder gibt es eine andere Lösung?

+0

helfen Wie haben Sie '_keyId' erzeugt? Es muss zuvor in KeyStore generiert werden. Android Keystore unterstützt symmetrische und asymmetrische Schlüssel https://developer.android.com/training/articles/keystore.html – pedrofb

+0

Bitte klären: welche Art von Android-Code ist das 'System.Text.Encoding.UTF8.GetBytes (textToEncrypt)'? – pedrofb

+0

@pedrofb Ich habe den Code für die Schlüsselgenerierung hinzugefügt. Der Code ist in Mono für Android. Der Code, den Sie angeben, gibt einfach einige Bytes zurück, die ich verschlüsseln möchte. – Philipp

Antwort

0

diesen Code von mir versuchen, wenn es

public KeyStore getKeyStore() { 
    try { 
     return KeyStore.getInstance("AndroidKeyStore"); 
    } catch (KeyStoreException exception) { 
     throw new RuntimeException("Failed to get an instance of KeyStore", exception); 
    } 
} 

public KeyPairGenerator getKeyPairGenerator() { 
    try { 
     return KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); 
    } catch(NoSuchAlgorithmException | NoSuchProviderException exception) { 
     throw new RuntimeException("Failed to get an instance of KeyPairGenerator", exception); 
    } 
} 

public Cipher getCipher() { 
    try { 
     return Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); 
    } catch(NoSuchAlgorithmException | NoSuchPaddingException exception) { 
     throw new RuntimeException("Failed to get an instance of Cipher", exception); 
    } 
} 

private void createKeyPair() { 
    try { 
     mKeyPairGenerator.initialize(
       new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT) 
         .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) 
         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP) 
         .setUserAuthenticationRequired(true) 
         .build()); 
     mKeyPairGenerator.generateKeyPair(); 
    } catch(InvalidAlgorithmParameterException exception) { 
     throw new RuntimeException("Failed to generate key pair", exception); 
    } 
} 

private boolean initCipher(int opmode) { 
    try { 
     mKeyStore.load(null); 

     if(opmode == Cipher.ENCRYPT_MODE) { 
      PublicKey key = mKeyStore.getCertificate(KEY_ALIAS).getPublicKey(); 

      PublicKey unrestricted = KeyFactory.getInstance(key.getAlgorithm()) 
        .generatePublic(new X509EncodedKeySpec(key.getEncoded())); 

      OAEPParameterSpec spec = new OAEPParameterSpec(
        "SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); 

      mCipher.init(opmode, unrestricted, spec); 
     } else { 
      PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_ALIAS, null); 
      mCipher.init(opmode, key); 
     } 

     return true; 
    } catch (KeyPermanentlyInvalidatedException exception) { 
     return false; 
    } catch(KeyStoreException | CertificateException | UnrecoverableKeyException 
      | IOException | NoSuchAlgorithmException | InvalidKeyException 
      | InvalidAlgorithmParameterException exception) { 
     throw new RuntimeException("Failed to initialize Cipher", exception); 
    } 
} 

private void encrypt(String password) { 
    try { 
     initCipher(Cipher.ENCRYPT_MODE); 
     byte[] bytes = mCipher.doFinal(password.getBytes()); 
     String encrypted = Base64.encodeToString(bytes, Base64.NO_WRAP); 
     mPreferences.getString("password").set(encrypted); 
    } catch(IllegalBlockSizeException | BadPaddingException exception) { 
     throw new RuntimeException("Failed to encrypt password", exception); 
    } 
} 

private String decrypt(Cipher cipher) { 
    try { 
     String encoded = mPreferences.getString("password").get(); 
     byte[] bytes = Base64.decode(encoded, Base64.NO_WRAP); 
     return new String(cipher.doFinal(bytes)); 
    } catch (IllegalBlockSizeException | BadPaddingException exception) { 
     throw new RuntimeException("Failed to decrypt password", exception); 
    } 
} 
+0

bitte don ' t einfach post code. Können Sie bitte erklären Sie Ihre Wahl der Algorithmen? Warum enthalten Sie nicht PURPOSE_ENCRYPT? Auch meine Frage war: Gibt es eine symmetrische Möglichkeit, dies zu tun? – Philipp