Android Java更新证书和Android KeyStore中的私钥

Android Java更新证书和Android KeyStore中的私钥,第1张

概述我有一个使用HTTPS客户端证书进行身份验证的系统,但根据以下过程生成证书本身: >客户端设备生成证书(包括公钥和私钥) >客户端设备将公钥发送到服务器,该服务器对公钥进行签名,并将其作为签名证书返回 >客户端以安全的方式存储证书,然后将其用作HTTPS客户端证书 我们有这个系统在iOS上工作,我正在尝试移植到android,但遇到了很多问题,因为Android的文档记录不清,安全API混乱. 我 我有一个使用httpS客户端证书进行身份验证的系统,但根据以下过程生成证书本身:

>客户端设备生成证书(包括公钥和私钥)
>客户端设备将公钥发送到服务器,该服务器对公钥进行签名,并将其作为签名证书返回
>客户端以安全的方式存储证书,然后将其用作httpS客户端证书

我们有这个系统在iOS上工作,我正在尝试移植到android,但遇到了很多问题,因为Android的文档记录不清,安全API混乱.

我的代码大致如下:

生成证书

keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);keyStore.load(null);Date startDate = new Date();Date endDate = new Date(startDate.getTime() + FORTY_YEARS_IN_MILliSECONDS);KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)        .setAlias(alias)        .setKeySize(2048)        .setKeyType(KeyPropertIEs.KEY_ALGORITHM_RSA)        .setSubject(new X500Principal("CN=" + alias))        .setSerialNumber(BigInteger.TEN)        .setStartDate(startDate)        .setEndDate(endDate)        .build();KeyPairGenerator generator = KeyPairGenerator.getInstance(KeyPropertIEs.KEY_ALGORITHM_RSA,ANDROID_KEYSTORE);generator.initialize(spec);KeyPair keyPair = generator.generateKeyPair(); // this will put a certificate and key pair in the keyStore.dumpKeyStore(keyStore);byte[] entireKey = keyPair.getPublic().getEncoded();// chop off first 24 bytes; the java key pair generator puts an object ID of  1.2.840.113549.1.1.1 RSA (RSA_SIGN) before the key which gets mangled when the server signs and sends back the certificatebyte[] publicKeyBytes = Arrays.copyOfRange(entireKey,24,entireKey.length);

dumpKeyStore是一个实用程序方法,它迭代密钥库,调用keyStore.getEntry来获取每个条目,并且只记录事物.
此时,它报告存在具有给定别名的单个条目,并且其类型为KeyStore.PrivateKeyEntry.它有一个关联的证书和公钥,可以从PrivateKeyEntry中重新获得.

发送到服务器

publicKeyBytes被发送到服务器,服务器将其作为新的签名x509证书的公钥,该证书将在响应中发回.我没有放入代码,它只是基本的网络.返回的证书加载,看起来很好.

保存并关联证书

我试图用相同的别名将它放入keyStore,因此它(理论上)可以与之前的正确私钥相关联.到目前为止我的代码是这样的:

KeyStore keyStore;try {    keyStore = KeyStore.getInstance(ANDROID_KEYSTORE);    keyStore.load(null);}catch (IOException | NoSuchAlgorithmException | CertificateException e) {    Log.wtf(TAG,e);    throw new FatalError(TAG,e);}CertificateFactory certificateFactory;try {    certificateFactory = CertificateFactory.getInstance("X.509");} catch (CertificateException e) {    Log.wtf(TAG,e);}Certificate cert = certificateFactory.generateCertificate(new ByteArrayinputStream(certificateFromServer));// find the existing certificate,copy it's private key out,then replace the certificate with the one from the server but keePing the private keytry {    KeyStore.PrivateKeyEntry existingPrivateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias,null);    KeyStore.PrivateKeyEntry newEntry = new KeyStore.PrivateKeyEntry(existingPrivateKeyEntry.getPrivateKey(),new Certificate[]{ cert });    keyStore.setEntry(alias,newEntry,null);} catch (Exception e) {    Log.wtf(TAG,e);}dumpKeyStore(keyStore);

此时,最终的dumpKeyStore指示存在具有正确别名的条目,但是当它尝试调用keyStore.getEntry时会引发“NoSuchAlgorithmException:UnkNown key entry”异常.

我想在androID中做什么(替换证书但保留私钥)?如果是这样,我该怎么做?看起来这不是真的有效

谢谢

猎户座

解决方法 事实证明,我做错了.您不需要替换或修改KeyStore中的证书,只需在初始化httpsURLConnection使用的SSLContext时使用自定义KeyManager,并且KeyManager可以选择您想要的任何证书或私钥.

这极大地简化了KeyStore管理.我的情景现在

>使用KeyPairGenerator生成公钥/私钥对,别名为X.
>将公钥发送到服务器,该服务器从该公钥生成新的签名证书,然后将其发回
>使用带有别名X-Signed的setCertificateEntry将此签名证书放入KeyStore

当我建立httpsURLConnection时,它是这样的:

KeyStore androIDKeyStore = KeyStore.getInstance(LocalKeyStore.ANDROID_KEYSTORE);androIDKeyStore.load(null);X509Certificate signedClIEntCertificate = (X509Certificate)androIDKeyStore.getCertificate("X-Signed");KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)androIDKeyStore.getEntry("X",null);X509ExtendedKeyManager keyManager = new X509ExtendedKeyManager() {    @OverrIDe    public String chooseClIEntAlias(String[] keyType,Principal[] issuers,Socket socket) {        return clIEntCertificatealias;    }    @OverrIDe    public String chooseServerAlias(String keyType,Socket socket) {        return null; // different if you're valIDating the server's cert    }    @OverrIDe    public X509Certificate[] getCertificateChain(String alias) {        return new X509Certificate[] { signedClIEntCertificate };    }    @OverrIDe    public String[] getClIEntAliases(String keyType,Principal[] issuers) {        return new String[]{ "X" };    }    @OverrIDe    public String[] getServerAliases(String keyType,Principal[] issuers) {        return null; // different if you're valIDating server's cert    }    @OverrIDe    public PrivateKey getPrivateKey(String alias) {        if(alias != clIEntCertificatealias) {            Log.e(TAG,String.format("X509ExtendedKeyManager is asking for privateKey with unkNown alias %s. Expecting it to ask for %s",alias,clIEntCertificatealias));            return null;        }        return privateKeyEntry.getPrivateKey();    }};x509trustmanager trustServerCertificates = new x509trustmanager() {    @OverrIDe    public voID checkClIEntTrusted(X509Certificate[] chain,String authType) throws CertificateException {        // do nothing,this method doesn't get called    }    @OverrIDe    public voID checkServerTrusted(X509Certificate[] chain,String authType)         // code to valIDate server's cert in here    }    @OverrIDe    public X509Certificate[] getAcceptedissuers() {        return null; // any issuer    }};m_sslContext = SSLContext.getInstance("TLS");m_sslContext.init(new KeyManager[]{ keyManager },new TrustManager[] { trustServerCertificates },null);// later onconn = (httpURLConnection)url.openConnection();SSLContext sslContext = m_sslContext;if(conn instanceof httpsURLConnection && sslContext != null) {    ((httpsURLConnection)conn).setSSLSocketFactory(sslContext.getSocketFactory());}

这对我很有用,我可以继续使用AndroIDKeyStore,它的每个应用程序隐私和硬件支持的存储

总结

以上是内存溢出为你收集整理的Android Java更新证书和Android KeyStore中的私钥全部内容,希望文章能够帮你解决Android Java更新证书和Android KeyStore中的私钥所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1130230.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-30
下一篇 2022-05-30

发表评论

登录后才能评论

评论列表(0条)

保存