ICS Android は、KeyChain API を介して、システム キーストアと信頼できる CA への統合アクセスをサポートしているためです。
とてもいいのですが、このソースからの秘密鍵をクライアント証明書認証に使用しようとすると、次のような問題が発生します。
ここでいくつかの回答を確認しましたが、見つかった最高のものは次のとおりです。Android 4.0 SSL認証
これは 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 では機能しません。これは、getEncoded() メソッドが呼び出されたときに KeyChain.getPrivateKey() によって返される PrivateKey オブジェクトが null を返し、KeyStore を初期化できないためです。
4.1でこれを行う他の方法はありますか?
更新 - KeyStore と KeyStoreSpi の独自の実装を定義する正しい方法はこちら KeyStore と 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
}
}
}
ありがとうございました
ヴァシル