【问题标题】:Android XML RSA, ERROR: java.security.InvalidKeyException: unknown key type passed to RSAAndroid XML RSA,错误:java.security.InvalidKeyException:传递给 RSA 的未知密钥类型
【发布时间】:2015-10-11 00:25:36
【问题描述】:

我遇到了使用 RSA 加密字符串的问题。 我的 RSA 是 XML 格式的,看起来像这样:

<RSAKeyValue><Modulus>lT8ykfyV0R8o3mJZZezLKTKJpYB90Pzvp0moLzh9CTGfgsxLKYiAl+YGaoRfQ7hVQos5UlLIONHWKPNco9kKcmL6EBJvFc8wqBnhX0p4ML2WSv1yDIRsm9XXra82WHIa3+fxK8bNUJHrucxmpr9pDRPdZGZkz+Q9s94FcOyFKbs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

我正在尝试使用此类加密字符串:

import java.io.BufferedReader;
import java.io.StringReader;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.Security;
import javax.crypto.Cipher;
import org.bouncycastle.openssl.PEMReader;
import android.util.Base64;
import android.util.Log;

public class RsaEncryption {

private String publicKey;

public RsaEncryption(String publicKey)
{
    this.publicKey = publicKey;

}


/*
 * Function to encrypt the data.
 *
 */

public String encrypt( String data ) throws Exception
{



    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");


    byte[] keyBytes =   Base64.decode( this.publicKey, 0 );

    PublicKey publickey       = strToPublicKey(new String(keyBytes));
    cipher.init( Cipher.ENCRYPT_MODE , publickey );

    // Base 64 encode the encrypted data
    byte[] encryptedBytes = Base64.encode( cipher.doFinal(data.getBytes()), 0 );

    return new String(encryptedBytes);


}


public static PublicKey strToPublicKey(String s)
{

    PublicKey pbKey = null;
    try {

        BufferedReader br   = new BufferedReader( new StringReader(s) );
        PEMReader pr        = new PEMReader(br);
        Object obj = pr.readObject();

        if( obj instanceof PublicKey )
        {
            pbKey = (PublicKey) pr.readObject();
        }
        else if( obj instanceof KeyPair )
        {
            KeyPair kp = (KeyPair) pr.readObject();
            pbKey = kp.getPublic();
        }
        pr.close();

    }
    catch( Exception e )
    {
        Log.d("CIPHER", e.getMessage() );
    }

    return pbKey;
}

}

如你所见,我正在使用 bouncycastle 的罐子 我得到的错误是: java.security.InvalidKeyException:传递给 RSA 的未知密钥类型

我不确定这部分

Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");

也许这就是问题所在? 如果是,那还需要什么?

我做了几个小时的研究,仍然没有找到解决方案......

提前致谢:)

【问题讨论】:

    标签: java android xml encryption cryptography


    【解决方案1】:

    XML 不是 PEM。

    您需要从 XML 中提取模数和公共指数,然后使用 "RSA" KeyFactory 实例和 RSAPublicKeySpec 生成密钥。

    【讨论】:

    • 谢谢,现在我正在尝试使用从 XML 中提取的模数和指数,我该怎么做?我确实尝试了 raked.void 的建议,但还没有成功。
    【解决方案2】:
    Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
    

    也许这就是问题所在?

    不,不是。

    OAEPWith<digest>And<mgf>Padding
    

    表示在PKCS1 中定义的最佳非对称加密填充 方案,其中&lt;digest&gt; 应替换为消息摘要 算法,&lt;mgf&gt; 应替换为掩码生成函数。示例:OAEPWithMD5AndMGF1PaddingOAEPWithSHA-512AndMGF1Padding

    参考Standard NamesRFC 4055

    问题出在您的公钥一代。由于您的密钥采用 XML 格式,并且采用 Base64 编码:

    • 首先您需要将模数和指数分开。
    • 然后 Base64 解码模数和指数。

    解码后你会得到模数和指数的字节数组,所以你可以很容易地准备公钥对象,如下程序:

    BigInteger modBigInteger = new BigInteger(1, modulus);//modulus must be byte array
    BigInteger exBigInteger = new BigInteger(1, exponent);//exp must be byte array
    
    RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = factory.generatePublic(spec);
    

    【讨论】:

    • 谢谢,但现在我在使用您的方法时遇到了其他问题 java.lang.NumberFormatException: Invalid int: "pD"
    • 模数和指数是Base64编码的,需要先解码。请看一下,当我解码您的指数AQAB 时,我得到了十六进制010001,即65537 通常用作公共指数。
    • 这就是我试图对它进行base64解码时得到的:指数:��它不会给我一个数字
    • @TomerOfer,这意味着您的解码过程失败,decode here 看到结果。
    • @TomerOfer,base64解码后你可能会得到byte array而不是hex string,所以你可以直接使用它们。请参阅我编辑的答案。
    猜你喜欢
    • 2023-03-23
    • 2014-10-26
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多