Android - 使用私钥对RSA进行编码和解码?

Don*_*rty 6 encryption android rsa keystore android-keystore

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

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

 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();
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

加密似乎工作正常,但当我尝试解密它时,我收到以下错误:

javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
Run Code Online (Sandbox Code Playgroud)

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

.setKeySize(1024);
Run Code Online (Sandbox Code Playgroud)

没有工作,似乎只在API 19上可用,我需要针对API 18.

任何人都可以帮助我指出解决方案的正确方向吗?

Mjo*_*nir 6

没有使用公钥进行加密。

当您使用非对称加密算法时,您需要使用公钥加密的数据,而私钥仅用于再次解密

除了加密之外,您还可以使用私钥进行签名,但这不是您想要的,所以我们暂时忘记这一点。

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

或者,您也可以使用AES 等对称算法,这样您的工作就会变得更加轻松。另外,对称算法通常要快得多,这就是为什么非对称算法从不纯粹使用,而是与对称算法结合使用,构建所谓的混合算法。