由於ICS Android支持通過KeyChain API統一訪問系統密鑰庫和可信CA.如何使用Apache客戶端和KeyChain API從Android 4.1進行客戶端證書驗證
這是相當不錯的,但當我嘗試使用此源的私鑰用於客戶端證書認證時,給我帶來了以下麻煩。
我這裏查了一些答案,我發現最好的事情是:Android 4.0 SSL Authentication
它指的是4.0,並提供以下編碼:
更新 - 這個編碼是錯誤的 - 它不會在4.1+工作
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);
然而,這不是在4.1工作,因爲KeyChain.getPrivateKey()返回的專用密鑰對象時的getEncoded()方法被調用和密鑰庫不能被初始化返回null。
4.1還有其他的方法嗎?
更新 - 在這裏正確的方式來定義自己的實現密鑰存儲和KeyStoreSpi 這裏的示例實現密鑰存儲和KeyStoreSpi的:
KeyStoreSpi實現:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.security.PrivateKey;
public class KeyChainProxy extends KeyStoreSpi {
private String alias = null;
private PrivateKey privateKey = null;
private Certificate[] certChain = null;
public KeyChainProxy(String alias, PrivateKey privateKey, Certificate[] certChain) {
this.alias = alias;
this.privateKey = privateKey;
this.certChain = certChain;
}
@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
return privateKey;
}
@Override
public Certificate[] engineGetCertificateChain(String alias) {
return certChain;
}
@Override
public Certificate engineGetCertificate(String alias) {
return certChain[0];
}
@Override
public Date engineGetCreationDate(String alias) {
return new Date();
}
@Override
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException {
throw new KeyStoreException("Not Implemented");
}
@Override
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException {
throw new KeyStoreException("Not Implemented");
}
@Override
public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
throw new KeyStoreException("Not Implemented");
}
@Override
public void engineDeleteEntry(String alias) throws KeyStoreException {
throw new KeyStoreException("Not Implemented");
}
@Override
public Enumeration<String> engineAliases() {
List<String> list = new ArrayList<String>();
list.add(alias);
return Collections.enumeration(list);
}
@Override
public boolean engineContainsAlias(String alias) {
return alias != null && alias.equals(this.alias);
}
@Override
public int engineSize() {
return 1;
}
@Override
public boolean engineIsKeyEntry(String alias) {
return true;
}
@Override
public boolean engineIsCertificateEntry(String alias) {
return false;
}
@Override
public String engineGetCertificateAlias(Certificate cert) {
return null;
}
@Override
public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
}
@Override
public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
}
}
密鑰庫實行:
import java.security.KeyStore;
import java.security.KeyStoreSpi;
import java.security.Provider;
public class KeyChainKeystore extends KeyStore {
public KeyChainKeystore(KeyStoreSpi keyStoreSpi, Provider provider, String type) {
super(keyStoreSpi, provider, type);
try {
load(null, null);
} catch (Exception e) {
// ignore - our spi doesn't do anything
}
}
}
謝謝
瓦西
你能解釋下你如何使用這兩個自定義類嗎?我正在努力解決同樣的問題... – Sandra
我想通了。這裏是尋找這個最後一塊的人:KeyChainProxy keyChainProxy = new KeyChainProxy(「your-alias」,yourKey,yourChain); KeyChainKeystore keyChainKeystore = new KeyChainKeystore(keyChainProxy,null,「type-of-keystore-you-want」); – Sandra
這就是主意。您可以從鑰匙串中創建一個SPI並使用它來初始化密鑰庫。然後,您可以在ssl調用中將此密鑰庫用作客戶端證書。 – vap78