Android-编码和用私钥解码RSA? [英] Android - Encode & Decode RSA with Private Key?

查看:75
本文介绍了Android-编码和用私钥解码RSA?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用私钥对Android上的字符串进行编码和解码,该私钥是使用Android 4.3中引入的Android密钥存储提供程序生成和存储的.

I am trying to encode and decode Strings on Android using a Private Key generated and stored using the Android Key Store Provider that was introduced in Android 4.3

我可以使用以下代码成功生成并获取私钥:

I can successfully generate and get the private key using the following code:

 private void generatePrivateKey(Activity context, String alias){
    /** Generate a new entry in the KeyStore by using the  * KeyPairGenerator API. We have to specify the attributes for a  * self-signed X.509 certificate here so the KeyStore can attach  * the public key part to it. It can be replaced later with a  * certificate signed by a Certificate Authority (CA) if needed.  */

    Calendar cal = Calendar.getInstance();
    Date now = cal.getTime();
    cal.add(Calendar.YEAR, 1);
    Date end = cal.getTime();

    KeyPairGenerator kpg = null;
    try {
        kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    }
    try {
        kpg.initialize(new KeyPairGeneratorSpec.Builder(context)
                .setAlias(alias)
                .setStartDate(now)
                .setEndDate(end)
                .setSerialNumber(BigInteger.valueOf(1))
                .setSubject(new X500Principal("CN=" + alias))
                .build());
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }

    KeyPair kp = kpg.generateKeyPair();

    /*
 * Load the Android KeyStore instance using the the
 * "AndroidKeyStore" provider to list out what entries are
 * currently stored.
 */
    KeyStore ks = null;
    try {
        ks = KeyStore.getInstance("AndroidKeyStore");
        ks.load(null);
        Enumeration<String> aliases = ks.aliases();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    /*
 * Use a PrivateKey in the KeyStore to create a signature over
 * some data.
 */

    KeyStore.Entry entry = null;
    try {
        entry = ks.getEntry(alias, null);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
        Log.w("E", "Not an instance of a PrivateKeyEntry");
    }
    else{
        Log.w("E", "Got Key!");
        privateKeyEntry = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
    }

}

这是我用于加密(编码)和解密(解码)的代码:

And here is the code I am using for encrypt (encode) and decrypt (decode):

private String encryptString(String value){
    byte[] encodedBytes = null;
    try {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        cipher.init(Cipher.ENCRYPT_MODE,  privateKeyEntry );
        encodedBytes = cipher.doFinal(value.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }

    return Base64.encodeToString(encodedBytes, Base64.DEFAULT);
}

private String decryptString(String value){
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
        c.init(Cipher.DECRYPT_MODE,  privateKeyEntry );
        decodedBytes = c.doFinal(Base64.decode(value, Base64.DEFAULT));
    } catch (Exception e) {
        e.printStackTrace();
    }

    return new String(decodedBytes);
}

加密似乎可以正常工作,但是当我尝试对其进行解密时,出现以下错误:

The Encryption appears to work fine but when I try to decrypt it I get the following error:

javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02

谷歌搜索似乎表明用于解密的私钥与用于解密的私钥不同,但是在我的代码中,我对两者使用完全相同的私钥.我还看到它建议手动设置密钥大小,但是可以在KeyPairGenerator构建器中执行以下操作:

Googling this seems to suggest that the private key used for decryption is different to the one used for decryption but in my code I use the exact same private key for both. I have also seen it suggested to set the key size manually but doing this in the KeyPairGenerator builder like this:

.setKeySize(1024);

没有用,似乎仅在API 19上可用,我需要定位到API 18.

Did not work and seems to be only available on API 19, I need to target API 18.

有人可以帮我指出正确的解决方案吗?

Can anyone help point me in the right direction as to a solution?

推荐答案

不是使用公钥进行加密.

使用非对称加密算法时,需要使用 密钥加密您的数据,并使用 private 密钥只能再次解密.

When you are using asymmetric encryption algorithms, you need to use the public key to encrypt your data, and the private key only to decrypt it again.

除了加密之外,您还可以使用私有密钥进行签名,但这不是您想要的,因此暂时不要忘记它.

Besides encryption, you can also use the private key for signing, but that's not what you want here, so let's forget about that for the moment.

如果从生成的对中获取公钥,则在对字符串进行加密时以及在解密时使用私钥时,您应该会获得所需的结果.您可以通过访问保存私钥的密钥库对象中的 证书 来提取公钥.

If you take the public key from the generated pair, when you encrypt your string, and the private key when decrypting, you should get the desired result. The public key you can extract by accessing the certificate from the keystore-object that holds your private key.

或者,您也可以使用诸如AES之类的对称算法,从而使您的工作更加轻松.另外,对称算法通常要快得多,这就是为什么不单纯使用非对称算法,而是与对称算法结合使用以构建所谓的混合算法的原因.

Alternatively you could also use a symmetric algorithm like AES and by that make your work a lot easier. Plus, symmetric algorithms are usually much faster, which is why asymmetric algorithms are never used purely, but in conjunction with symmetric algorithms, building so-called hybrid algorithms.

这篇关于Android-编码和用私钥解码RSA?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆