2017-01-23 9 views
0

私のアプリは、Androidのキーストアを使用して指紋で認証した後、一部のデータを暗号化しています。 Googleのピクセルデバイスのユーザーがスローされ、次の例外を報告している:Google PIxelデバイスのInvalidKeyException

java.security.InvalidKeyException:のみのSecretKeyが

をサポートされている暗号化のための私のコードは、基本的にはこの行います

_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)); 

をそれのGetKeyように思えますnullを返します。これらの新しいデバイスは非対称暗号化しかサポートしていませんか?これは鍵ペアを生成する必要があることを意味するのでしょうか、それとも別の解決策がありますか?

+0

どのように助けることができるかどうか私のこのコードを試してみてください? KeyStoreに事前に生成する必要があります。 Androidキーストアは対称キーと非対称キーをサポートしていますhttps://developer.android.com/training/articles/keystore.html – pedrofb

+0

この「System.Text.Encoding.UTF8.GetBytes(textToEncrypt)」はどのようなアンドロイドコードですか? – pedrofb

+0

@pedrofb鍵の生成に使用するコードを追加しました。コードはAndroidのMonoにあります。あなたが引用したコードは、暗号化したいいくつかのバイトを返すだけです。 – Philipp

答えて

0

それはあなたが `_keyId`を生成した

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

してください 'あなたのアルゴリズムの選択肢を説明してもらえますか?なぜPURPOSE_ENCRYPTは含まれていませんか?また、私の質問でした:これを行うための対称的な方法はありますか? – Philipp

関連する問題