2012-07-20 3 views
0

Я пытаюсь создать устройство чтения RSS-каналов, которое должно выполнить некоторую проверку подлинности SSL на стороне клиента.Android 4.0 SSL Authentication

У меня есть, или, по крайней мере, думаю, что у меня есть сертификат. Однако теперь я не могу понять, как настроить туннель ssl для отправки сертификата на сервер для аутентификации.

Вот то, что я до сих пор:

public class Authenticator extends Activity { 

PrivateKey privateKey = null; 
String SavedAlias = ""; 
private static final String TAG = "AUTHENTICATOR.CLASS"; 
final HttpParams httpParams = new BasicHttpParams(); 
private KeyStore mKeyStore = KeyStore.getInstance(); 

public Handler mHandler = new Handler(Looper.getMainLooper()); 

public void run() 
{ 
    mHandler.post(new Runnable() { 
     public void run() { 
      new AliasLoader().execute(); 
     } 
    }); 
} 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    getCertificates("TEST"); 
} 

public class AliasLoader extends AsyncTask<Void, Void, X509Certificate[]> 
{ 
    X509Certificate[] chain = null; 

    @Override protected X509Certificate[] doInBackground(Void... params) { 
     android.os.Debug.waitForDebugger(); 

     if(!SavedAlias.isEmpty()) 
     { 
       try { 
        chain = KeyChain.getCertificateChain(getApplicationContext(),SavedAlias); 
       } catch (Exception e) { 
        Log.e(TAG, e.getMessage()); 
       } 
     } 
     else 
     { 
      this.cancel(true); 
     } 

     return chain; 
    } 

    @Override 
    protected void onPostExecute(X509Certificate[] chain) 
    { 

     if(chain != null) 
     { 
      Toast.makeText(getApplicationContext(), "YAY, Certificate is not empty", Toast.LENGTH_LONG).show(); 
     } 
     else 
     { 
      Toast.makeText(getApplicationContext(), "Certificate is Empty", Toast.LENGTH_LONG).show(); 
     } 

     /* 
     if (privateKey != null) { 
      Signature signature = null; 
      try { 
       signature = Signature.getInstance("SHA1withRSA"); 
      } catch (NoSuchAlgorithmException e) { 
       Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); 
      } 
      try { 
       signature.initSign(privateKey); 
      } catch (InvalidKeyException e) { 
       Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); 
      } 
     } 
     */ 
    } 
} 

public void getCertificates(String Host) 
{ 
    KeyChainAliasCallback callBack = new KeyChainAliasCallback() { 

     @Override 
     public void alias(String alias) {    
      if (alias != null) 
      { 
       Looper.prepare(); 
       saveAlias(alias); 
       run(); 
       Looper.loop(); 
      } 
     } 
    }; 

    KeyChain.choosePrivateKeyAlias(this, callBack, 
    new String[] {"RSA", "DSA"}, // List of acceptable key types. null for any 
    null,      // issuer, null for any 
    null,  // host name of server requesting the cert, null if unavailable 
    443,       // port of server requesting the cert, -1 if unavailable 
    null);      // alias to preselect, null if unavailable 
} 

public void saveAlias(String alias) 
{ 
    SavedAlias = alias; 
} 
} 

Любая помощь о том, как сделать это было бы весьма признателен, как я никогда не делал никакой аутентификации до и я нашел, что трудно найти что-нибудь по этой теме для android 4.0 как 4.0, похоже, отличается в реализации, а затем более старыми версиями.

+0

Попробуйте это: http://blog.codecentric.de/en/2012/04/one-solution-for-android-tlsssl-client-authentication/ – Robert

+0

Спасибо Роберт, эта ссылка выглядит так, как будто это дает мне почти все, что мне нужно, чтобы это работало. Единственное, с чем я сталкиваюсь с классом в ссылке, это получение сертификата из ресурсов raw-устройств, тогда как в моем случае я получил сертификат, установленный в хранилище системного доверия в контейнере пользователей. Мой код получает сертификат как сертификат X509 [], но я не знаю, как я могу загрузить его в хранилище ключей, которое мы создаем в ссылке. –

ответ

2

Вы должны быть в состоянии получить цепочку сертификатов, а также закрытого ключа и храните его в временное в памяти KeyStore:

String alias = "test"; 
KeyStore memoryKeyStore = KeyStore.getInstance("BKS"); 
memoryKeyStore.load(null); 
X509Certificate[] chain = KeyChain.getCertificateChain(getApplicationContext(),alias); 
PrivateKey key = KeyChain.getPrivateKey(getApplicationContext(),alias); 
memoryKeyStore.setKeyEntry(alias, key.getEncoded(), chain); 

После этого вы можете использовать этот ключ хранилище для инициализации экземпляра SSLContext.

Предупреждение. Обратите внимание, что пример кода содержит реализацию X509TrustManager, которая не выполняет проверку сертификата сервера. Лучше не использовать его.

+0

спасибо за ответ, он очень помог. im все еще возникают проблемы, но по крайней мере теперь он получил сертификат и пытается выполнить рукопожатие на сервере с помощью сертификата. То, где он терпит неудачу, хотя код не производит никаких ошибок, я не могу получить доступ, но я уверен, что это просто какая-то проблема с тем, как я отправляю сертификаты, или потому, что аутентификация набирается где-то =) –

+0

@ Deep.Timon вы его работали с этим кодом? У меня та же проблема, когда мой клиентский сертификат не проверяется сервером, хотя он отправляется на сервер. Это также не приводит к ошибкам. В моем случае оба сертификата клиента и сервера подписываются одним и тем же rootCA, и я просто не знаю, почему рукопожатие не работает. Поделитесь, если у вас есть решение – Sandra