如何将Android的公钥转换为字符串并再次转换回来?

4

我正在尝试创建一个加密用户消息的应用。用户的公钥需要以字符串形式发布到服务器上。我生成Android Keystore PublicKey的方式如下:

    public static PublicKey getOrCreatePublicKey(String alias) throws GeneralSecurityException, IOException {

    KeyStore keyStore = KeyStore.getInstance(ANDROID_PROVIDER);
    keyStore.load(null);
    if (!keyStore.containsAlias(alias) || keyStore.getCertificate(alias) == null) {

        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
                alias,
                KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                .setDigests(KeyProperties.DIGEST_SHA256,
                        KeyProperties.DIGEST_SHA512)
                .build();
        KeyPairGenerator generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_PROVIDER);
        generator.initialize(spec);
        generator.generateKeyPair();
    }
    return keyStore.getCertificate(alias).getPublicKey();
}

我尝试将公钥转换为字符串,再将其转换回公钥,如下:

public static PublicKey stringToPublicKey(String publStr)  {

    PublicKey publicKey = null;
    try {
        byte[] data = Base64.decode(publStr, Base64.DEFAULT);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        publicKey = fact.generatePublic(spec);
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    }
    return publicKey;
}


public static String publicKeyToString(PublicKey publ) {
    String publicKeyString = null;
    try {
        KeyFactory fact = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec spec = fact.getKeySpec(publ,
                X509EncodedKeySpec.class);
        publicKeyString = Base64.encodeToString(spec.getEncoded(), Base64.DEFAULT);
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    }
    return publicKeyString;
}

我尝试使用公钥和私钥加密和解密用户消息。

如果不将公钥转换为字符串,则加密可以正常进行。但是,如果将公钥转换为字符串并再次转换回公钥,则加密将无法正常工作。

我做错了什么?谢谢。

   PublicKey publicKey1 = getOrCreatePublicKey("alias");
        String publicKeyStr = publicKeyToString(publicKey1);
        PublicKey publicKey2 = stringToPublicKey(publicKeyStr);

    //this one works            
        String message = encrypt(str, publicKey1);
        String decryptm = decrypt(message, privateKey);

    //this one doesn't work
    String message = encrypt(str, publicKey2);
        String decryptm = decrypt(message, privateKey);

你的代码看起来是正确的。尝试使用publicKeyString = Base64.encodeToString(publicKey.getEncoded(), Base64.DEFAULT);对密钥进行编码。 - pedrofb
你试过运行代码了吗?还是不起作用。我怎么比较两个公钥?以某种方式将其转换为字符串再返回,会改变密钥。 - Daniel Foo
我在将您的字符串解析为pK函数时遇到了公钥解析错误。 - Jones
2个回答

1
我已经将 KeyProperties.ENCRYPTION_PADDING_RSA_OAEP 替换为 KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1
我还将 Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); 替换为 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
现在它可以工作了。但是我仍然不知道第一次为什么不起作用。

1
你的publicKeyToString函数走了一个非常漫长的路。它不应该是从stringToPublicKey做所有步骤的“反向”重复。我的意思是,你不需要构造一个对象,你已经有公钥作为对象了。将PublicKey转换为String基本上只需要一行代码。
public static String publicKeyToString(PublicKey publ) {
    String publicKeyString = Base64.encodeToString(publ.getEncoded(), 2);
    return publicKeyString;
}

这应该输出一个字符串,可与您的stringToPublicKey函数配合使用(在我看来它是正确的)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接