2014-09-25 10 views
8

Sto tentando di utilizzare il provider di chiavi USB che è diventato disponibile in Android 4.3 per salvare in modo sicuro una chiave privata e utilizzare quindi questa chiave privata per crittografare e decodificare i dati.Come archiviare la chiave utilizzando il provider di chiavi USB Store

Penso di aver implementato l'approccio corretto e il codice per questo finora, ma attualmente sto affrontando un problema strano che non riesco a capire.

ho una classe denominata KeyStorage che uso per creare la coppia di chiavi, caricare il KeyStore e recuperare la chiave privata, il codice per questa classe è la seguente:

public class KeyStorage { 

public static final String ANDROID_KEYSTORE = "AndroidKeyStore"; 
private KeyStore keyStore; 

public void loadKeyStore() { 
    try { 
     keyStore = KeyStore.getInstance(ANDROID_KEYSTORE); 
     keyStore.load(null); 
     Enumeration<String> aliases = keyStore.aliases(); 
     while(aliases.hasMoreElements()) 
      Log.e("E", "Aliases = " + aliases.nextElement()); 
    } catch (Exception e) { 
     // TODO: Handle this appropriately in your app 
     e.printStackTrace(); 
    } 
} 

public void generateNewKeyPair(String alias, Context context) 
     throws Exception { 

    Calendar start = Calendar.getInstance(); 
    Calendar end = Calendar.getInstance(); 
    // expires 1 year from today 
    end.add(1, Calendar.YEAR); 

    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context) 
      .setAlias(alias) 
      .setSubject(new X500Principal("CN=" + alias)) 
      .setSerialNumber(BigInteger.TEN) 
      .setStartDate(start.getTime()) 
      .setEndDate(end.getTime()) 
      .build(); 

    // use the Android keystore 
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", ANDROID_KEYSTORE); 
    gen.initialize(spec); 

    // generates the keypair 
    gen.generateKeyPair(); 
} 

public PrivateKey loadPrivteKey(String alias) throws Exception { 

    if (keyStore.isKeyEntry(alias)) { 
     Log.e("E", "Could not find key alias: " + alias); 
     return null; 
    } 

    KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null); 

    if (!(entry instanceof KeyStore.PrivateKeyEntry)) { 
     Log.e("E", " alias: " + alias + " is not a PrivateKey"); 
     return null; 
    } 

    return ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); 
} 

Ho poi avere una classe chiamata CredentialStore in cui cerco di utilizzarlo. Creo un alias chiamato "MySecureKey" e provo a creare e memorizzare una chiave privata basata su questo. Quindi, come puoi vedere, provo a creare la nuova coppia di chiavi basata su Alias, carica il keystore e infine recupero la chiave privata. Tuttavia non funziona.

public class CredentialStore { 

public static final String KEY_ALIAS = "MySecureKey"; 

private KeyStorage KeyStorage; 

public CredentialStore(Activity context){ 

    keyStorage = new KeyStorage(); 
    try { 
     keyStorage.generateNewKeyPair(KEY_ALIAS, context); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    blueBirdKeyStorage.loadKeyStore(); 

    try { 
     keyStorage.loadPrivteKey(KEY_ALIAS); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 

ottengo i registri come segue:

Aliases = MySecureKey 
Could not find key alias: MySecureKey 

Così quando controllo gli alias nel metodo loadKeyStore sembra che è lì come si sta tornando nel registro. Tuttavia, quando provo a chiamarlo usando il metodo loadKeyStore, ottengo il log dicendo che non è possibile trovare la chiave "MySecureKey".

Non riesco a trovare alcuna ragione per questo e la ricerca in linea si è dimostrata infruttuosa, quindi mi chiedevo se qualcuno ha qualche idea di cosa potrebbe andare storto.

+4

1. generare coppia di chiavi e non fanno uso di esso. Il tuo metodo generateNewKeyPair non restituisce nulla. 2. Non si salva nulla su KeyStore per caricarlo successivamente. si prega di fare riferimento a un campione sull'uso di KeyStore. Potrebbe aiutarti http://developer.android.com/samples/BasicAndroidKeyStore/index.html –

+0

@AlexanderZhak nonostante i molti upvotes, il tuo commento è errato: consulta il documento ufficiale: https://developer.android.com/ training/articles/keystore.html # UserAuthentication questo è il modo in cui si utilizza il Keystore Android: non è necessario inserire la chiave esplicitamente se si utilizza KeyFactory con l'istanza di Android Keystore. – for3st

risposta

1

Perché è blueBirdKeyStore in:

blueBirdKeyStorage.loadKeyStore(); 

Non dovrebbe essere:

keyStorage.loadKeyStore(); 

Inoltre, non è stato utilizzato il 'alias' nel vostro loadPrivateKey():

KeyStore.Entry entry = keyStore.getEntry(EnhancedCredentialStore.KEY_ALIAS, null); 

Ora, non sono sicuro, ma non dovresti usare l'alias in questo?

0

loadPrivateKey nella classe non utilizza l '"alias" per recuperare la chiave. Sta usando la costante di un'altra classe, quindi non sono sicuro di cosa ti aspetti qui.

+0

No, utilizza l'alias corretto. – for3st

1

Il tuo metodo per verificare se esiste la chiave è difettosa:

if (keyStore.isKeyEntry(alias)) { 
    Log.e("E", "Could not find key alias: " + alias); 
    return null; 
} 

Secondo javadoc .isKeyEntry() ha il seguente comportamento

Restituisce vero se la voce identificato dal alias dato è stato creato da una chiamata a setKeyEntry o creata da una chiamata a setEntry con un PrivateKeyEntry o un SecretKeyEntry.

ma la chiave non è stata creata tramite setEntry(). Immagino che se carichi la chiave con

KeyStore.Entry entry = ks.getEntry(alias, null); 

non sarà nullo.

Here is a full example with simple methods on how to use the Android Keystore with pre-M and M Apis.