GVKun编程网logo

在Android中使用KeyStore存储密钥(android keystore存储数据)

16

本文将分享在Android中使用KeyStore存储密钥的详细内容,并且还将对androidkeystore存储数据进行详尽解释,此外,我们还将为大家带来关于Android4.3KeyStore–在尝

本文将分享在Android中使用KeyStore存储密钥的详细内容,并且还将对android keystore存储数据进行详尽解释,此外,我们还将为大家带来关于Android 4.3 KeyStore – 在尝试检索密钥时链== null、Android Eclipse keystore.jks文件生成,根据keystore密钥获取SHA1安全码 ,apk打包、Android Java更新证书和Android KeyStore中的私钥、android keystore的相关知识,希望对你有所帮助。

本文目录一览:

在Android中使用KeyStore存储密钥(android keystore存储数据)

在Android中使用KeyStore存储密钥(android keystore存储数据)

我正在使用KeyStore保护我的私钥,但是在以下行中:

FileOutputStream fos = ctx.openFileOutput("bs.keystore", Context.MODE_PRIVATE);

被执行,我有这个异常:

''java.lang.NullPointerException''.

我不明白问题出在哪里。

码:

    private Context ctx;    public DataSec(Context ctx)     {    ctx = this.ctx;    }    public void genKey() throws Exception    {    SecretKey key = KeyGenerator.getInstance("AES").generateKey();    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());    ks.load(null, "clavedekey".toCharArray());    PasswordProtection pass = new PasswordProtection("fedsgjk".toCharArray());    KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(key);    ks.setEntry("secretKeyAlias", skEntry, pass);    FileOutputStream fos = ctx.openFileOutput("bs.keystore", Context.MODE_PRIVATE);    ks.store(fos, "clavedekey".toCharArray());    fos.close();            }

谢谢您的帮助!

答案1

小编典典

更改:

public DataSec(Context ctx) {ctx = this.ctx;}

public DataSec(Context ctx) {    this.ctx = ctx;}

现在,您正在将方法中的context参数分配为与全局值相同的值,该值为null。因此,您的上下文实际上没有被存储。

Android 4.3 KeyStore – 在尝试检索密钥时链== null

Android 4.3 KeyStore – 在尝试检索密钥时链== null

在 this blog之后,我使用此代码在Android KeyStore中创建和存储KeyPair:
Context ctx = getApplicationContext();
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
notAfter.add(1,Calendar.YEAR);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(ctx).
setAlias(RSA_KEYS_ALIAS).setSubject(
  new X500Principal(String.format("CN=%s,OU=%s",getApplicationName(),ctx.getPackageName()))).
setSerialNumber(BigInteger.ONE).
setStartDate(notBefore.getTime()).setEndDate(notAfter.getTime()).build();

KeyPairGenerator kpGenerator;
try {
    kpGenerator = KeyPairGenerator.getInstance("RSA","AndroidKeyStore");

    kpGenerator.initialize(spec);
    kpGenerator.generateKeyPair();
} catch (Exception e) {
    showException(e);
}

当我尝试使用此代码从KeyStore检索公钥时,抛出带有消息链== null的NullPointerException.

public RSAPublicKey getRSAPublicKey() {
    RSAPublicKey result = null;
    try {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyStore.PrivateKeyEntry keyEntry = 
            (KeyStore.PrivateKeyEntry) keyStore.getEntry(RSA_KEYS_ALIAS,null); // --< exception is thrown here
        result = (RSAPublicKey) keyEntry.getCertificate().getPublicKey();
    }
    } catch (Exception e) {
        showException(e);
    }
    return result;
}

检索私钥的代码也是如此.

更新:

我将我的代码与Google BasicAndroidKeyStore sample进行了比较.在该示例中生成,存储和检索密钥对的机制几乎与我实现的相同.我很困惑为什么这段代码在经过几个月的完美工作后已停止运作.

任何建议或提示将不胜感激.

解决方法

显然,Android KeyStore中的名称在所有应用程序中必须是唯一的.我有另一个应用程序,它的键使用相同的名称.更改两个应用程序使用的公共库以创建和使用键在其键名中包含包名称后,问题就消失了……

Android Eclipse keystore.jks文件生成,根据keystore密钥获取SHA1安全码 ,apk打包

Android Eclipse keystore.jks文件生成,根据keystore密钥获取SHA1安全码 ,apk打包

keystore.jks文件生成,打包APK

选中项目右键-> Android Tools->Export Signed Application Package ,如图:

  

之后

              

点击Next,下图 (建议文件名后缀为.keystore)

            

进入到”Key Creation“界面,完成信息,点击Next

           

完成信息,(选择APK生成的路径)

          

可以到保存路径下看生成的android.keystore文件了

          

接下来APK打包

         

点击之后,选择保存路径:

                

之后APK生成成功

                 

根据keystore密钥获取SHA1安全码

通常做项目大多数都要用到SHA1安全码,比如:地图,获取SHA1安全码的也有两种,分为调试版和发布版,他们的SHA1都是不一样的,

debug测试版:

Window+R 打开控制台  输入cmd点击确定

之后在弹框中完成以下操作就可以看到SHA1安全码了

上图的密钥库口令默认的是:android  (注:输入口令是看不见的,输入完成Enter即可)

发布版(这个版本可以看到测试版和发布版的SHA1):

这个版本就需要我们前面生成的keystore文件了, Custom debug keystore:导入生成的keystore文件,点击Apply生成发布版本的密钥SHA1

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

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

我有一个使用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 certificate
byte[] 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 key
try {
    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 on

conn = (HttpURLConnection)url.openConnection();
SSLContext sslContext = m_sslContext;

if(conn instanceof HttpsURLConnection && sslContext != null) {
    ((HttpsURLConnection)conn).setSSLSocketFactory(sslContext.getSocketFactory());
}

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

android keystore

android keystore

我用 eclipse 在其他路径生成了一个 keystore,但是 password 是随便写的,现在我能修改 password 吗?

关于在Android中使用KeyStore存储密钥android keystore存储数据的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android 4.3 KeyStore – 在尝试检索密钥时链== null、Android Eclipse keystore.jks文件生成,根据keystore密钥获取SHA1安全码 ,apk打包、Android Java更新证书和Android KeyStore中的私钥、android keystore的相关知识,请在本站寻找。

本文标签: