ユーザーにプロンプトを表示せずに証明書をインストールしようとしています。これは良い習慣ではないことは知っていますが、それがPMが望んでいることです。
KeyChain.createInstallIntent()
を使用すると、Androidを取得して、startActivity
を呼び出すことで証明書のインストールダイアログを起動できます。ただし、 sendBroadcast
を意図しているので、何も起こりません。セキュリティ上の理由から、プラットフォームがこれをサポートしていないのではないでしょうか。
String CERT_FILE = Environment.getExternalStorageDirectory() + "/test/IAT.crt";
Intent intent = KeyChain.createInstallIntent();
try {
FileInputStream certIs = new FileInputStream(CERT_FILE);
byte [] cert = new byte[(int)certFile.length()];
certIs.read(cert);
X509Certificate x509 = X509Certificate.getInstance(cert);
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, x509.getEncoded());
intent.putExtra(KeyChain.EXTRA_NAME, "IAT Cert");
EapActivity.this.startActivityForResult(intent, 0); // this works but shows UI
EapActivity.this.sendBroadcast(intent); // this doesn't install cert
} catch (IOException e) {
システム権限がある場合にのみ、証明書をサイレントインストールできます。証明書を信頼すると深刻な結果を招く可能性があるため、確認ダイアログを表示することは意図的なものです-Androidは警告などなしにフィッシングサイトを喜んで開く可能性があります。とはいえ、ICS/JBのダイアログはかなり悪いです-インストールしている証明書とその発行者はわかりません。CA証明書であるというだけで、これは明らかです。
したがって、パブリックKeyChain
APIを使用してstartActivity()
を使用して確認ダイアログを表示するか、デバイスをユーザーに処理する前にデバイスを事前プロビジョニングします。
更新:Android 4.4では、DevicePolicyManager
には、証明書をサイレントインストールできる非表示のAPI(installCaCert
)があります。MANAGE_CA_CERTIFICATES
権限が必要です、これはsignature|system
であるため、ユーザーがインストールしたアプリではまだ実行できません。
KeyChain.createInstallIntent() を使用すると、startActivityを呼び出してAndroidを取得し、証明書のインストールダイアログを起動できます。ただし、sendBroadcastにインテントを渡しても何も起こりません。
startActivity()
に渡すIntent
オブジェクトがsendBroadcast()
で機能する場合はほとんどありません。これらは、Intent
システムである準メッセージバスの独立したチャネルです。
システム以外のアプリ開発者の場合-簡単な答えは、ユーザーの操作なしでは実行できないということです。
システムアプリ開発者の場合、次の解決策を見つけました。NBシステムユーザーIDでアプリを実行し、システムキーでアプリに署名する必要があります。そうしないと、サービスは証明書のインストールを拒否します。 。
ステップ1-インターフェースの作成
プロジェクトに新しいパッケージを作成します:Android.security、次にコピー IKeyChainService。 aidl このパッケージに。
ステップ2-サービスにバインドして証明書をインストールする
アクティビティでは、CA証明書をインストールする方法の例を示します。
public class KeyChainTest extends Activity {
private final Object mServiceLock = new Object();
private IKeyChainService mService;
private boolean mIsBoundService =false;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name,
IBinder service) {
synchronized (mServiceLock) {
mService = IKeyChainService.Stub.asInterface(service);
mServiceLock.notifyAll();
try {
byte[] result = YOUR_CA_CERT_AS_BYTE_ARRAY
//The next line actually installs the certificate
mService.installCaCertificate(result);
} catch (Exception e) {
//EXception handling goes here
}
}
}
@Override public void onServiceDisconnected(ComponentName name) {
synchronized (mServiceLock) {
mService = null;
}
}
};
private void bindService() {
mIsBoundService = bindService(new Intent(IKeyChainService.class.getName()),
mServiceConnection,
Context.BIND_AUTO_CREATE);
}
private void unbindServices() {
if (mIsBoundService) {
unbindService(mServiceConnection);
mIsBoundService = false;
}
}
@Override public void onDestroy () {
unbindServices();
}
@Override
protected void onStart() {
super.onStart();
// Bind to KeyChainService
bindService();
}
}
これが誰かに役立つことを願っています-それを解決するのに長い時間がかかりました:)
Root権限をお持ちの場合は、証明書ファイルを/data/misc/user/0/cacerts-added/
にコピーできます。
システムユーザーアプリケーションのみがCA証明書をサイレントインストールできます。 Lollipopでは、GoogleはDevicePolicyManagerを介してサイレント証明書管理APIを導入しましたが、Android-for-Workプロファイルの所有者またはデバイスの所有者である必要があります。
@ ospider の回答に基づいて、次のように証明書を正常にインストールできました。
adb Shell mkdir -p /data/misc/user/0/cacerts-added
adb Push certificate.cer /data/misc/user/0/cacerts-added/807e3b02.0
# Maybe these two lines are not strictly necessary...
adb Shell chmod 644 /data/misc/user/0/cacerts-added/807e3b02.0
adb Shell chown system:system /data/misc/user/0/cacerts-added/807e3b02.0
コピーしたファイルの名前を取得しました(807e3b02.0
)自動化したい証明書を手動でインストールし、Androidがどのように保存したか(adb Shell ls -l /data/misc/user/0/cacerts-added/
)
この助けを願っています。
よろしく。