2011-08-30 2 views
2

La configuration de test suivante fonctionne correctement sur l'émulateur Android. Il ouvre une connexion SSL/TLS sur un serveur externe en utilisant l'authentification mutuelle:Configuration à l'exécution du client http SSL/TLS sous Android avec authentification du client

ca.crt (pour vérifier le certificat du serveur):
----- BEGIN CERTIFICATE -----
Codé Base64 STUFF
----- END CERTIFICATE -----

de client.p12 (y compris un certificat client signé par une autorité de certification privée qui est approuvé par le serveur): format PKCS # 12

le Code Java/Android qui s'exécute avec succès:

trustStore = KeyStore.getInstance("bks"); 
trustStore.load(null, null); 
caCertificate = getX509Certificate("/some/path/ca.crt"); 
trustStore.setCertificateEntry("ca-cert", caCertificate); 

keyStore = KeyStore.getInstance("pkcs12"); 
keyStore.load(null, null); 
InputStream is = new FileInputStream("/some/path/client.p12"); 
keyStore.load(is, "passwd".toCharArray()); 

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 
trustManagerFactory.init(trustStore); 
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); 
keyManagerFactory.init(keyStore, null); 

context = SSLContext.getInstance("TLS"); 
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); 

URL url = new URL("https://www.backend.com"); 
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
connection.setSSLSocketFactory(context.getSocketFactory()); 
connection.setDoInput(true); 
connection.setDoInput(true); 
BufferedReader urlReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 
String inputLine; 
while ((inputLine=urlReader.readLine()) != null){ 
    System.out.println(inputLine); 
} 

Toutefois, client.p12 n'est pas disponible au moment de l'exécution. Le client HTTP reçoit la configuration suivante via un canal dédié séparé:

  • PEM codé certificat client X509 (de client.crt)
  • DER formaté client clé privée (client.der)

Par conséquent, J'ai changé le intitialisation keystore ci-dessus en prenant la client.p12 en entrée, en ce qui suit:

keyStore = KeyStore.getInstance("bks"); 
keyStore.load(null, null); 
clientCertificate = getX509Certificate("/some/path/client.crt"); 
byte[] privateKey = getBytesFromFile("/some/path/client.der"); 
Certificate[] chain = new Certificate[2]; 
chain[1] = caCertificate; 
chain[0] = clientCertificate;   
keyStore.setCertificateEntry("client-cert", clientCertificate); 
keyStore.setKeyEntry("client-cert-key", privateKey, chain); 

r untime une exception est levée lors de l'exécution

context = SSLContext.getInstance("TLS"); 
----> context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); 

java.lang.RuntimeException: forget something! 
at org.bouncycastle.jce.provider.JDKKeyStore$StoreEntry.getObject(JDKKeyStore.java:314) 
at org.bouncycastle.jce.provider.JDKKeyStore.engineGetKey(JDKKeyStore.java:604) 
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:376) 
at java.security.KeyStore.getEntry(KeyStore.java:734) 
at org.apache.harmony.xnet.provider.jsse.KeyManagerImpl.<init>(KeyManagerImpl.java:72) 

Résumé: tout fonctionne à l'aide d'un certificat pcks12/paire privatekey, mais pas en utilisant les deux dans le format mentionné.

Des suggestions de ce qui ne va pas ou une suggestion pour implémenter l'authentification client étant donné le client.der/client.pem mentionné précédemment?

P.S. l'exécution de l'exécution de keytool n'est pas une option, car je ne l'ai pas à l'exécution et je ne veux pas aller de cette façon.

Répondre

4

Simple: le passage d'une clé en tant que tableau d'octets n'est pas implémenté. Citation de JDKKeyStore.java:

 else 
     { 
      throw new RuntimeException("forget something!"); 
      // TODO 
      // if we get to here key was saved as byte data, which 
      // according to the docs means it must be a private key 
      // in EncryptedPrivateKeyInfo (PKCS8 format), later... 
      // 
     } 

Vous pouvez essayer d'enregistrer votre clé et le certificat selon la méthode void setKeyEntry(String alias, Key key, char[] password, Certificate[] chain), il semble qu'il est pris en charge (non testé).

Questions connexes