当使用带有PKCS1填充的RSA加密时,C#和Java(Android)之间有什么区别?

当使用带有PKCS1填充的RSA加密时,C#和Java(Android)之间有什么区别?,java,c#,android,encryption,rsa,Java,C#,Android,Encryption,Rsa,我正在用Java(Android)中带有PKCS1填充的RSA加密文本,之后我必须将其作为Web服务中正文的一部分发送。我的Java代码的输出不起作用,但是如果我用C#,从技术上讲是相同的算法,那么它就工作得很好 这是工作正常的C#代码: static void Main(string[] args) { var plainData = "plain_text"; RSA publicKeyEncryptor = getRSAPublic(@"<pu

我正在用Java(Android)中带有PKCS1填充的RSA加密文本,之后我必须将其作为Web服务中正文的一部分发送。我的Java代码的输出不起作用,但是如果我用C#,从技术上讲是相同的算法,那么它就工作得很好

这是工作正常的C#代码:

static void Main(string[] args)
    {
        var plainData = "plain_text";
        RSA publicKeyEncryptor = getRSAPublic(@"<public_key>");
        var plainBytes = Encoding.ASCII.GetBytes(plainData);
        string encryptedPayload = System.Convert.ToBase64String(publicKeyEncryptor.Encrypt(plainBytes, RSAEncryptionPadding.Pkcs1));
        Console.WriteLine(encryptedPayload);
    }

public static RSA getRSAPublic(string publicKey)
    {
        string publicKeyPem = $"-----BEGIN PUBLIC KEY-----\r\n{ publicKey }\r\n-----END PUBLIC KEY-----\r\n";
        var pemReader = new PemReader(new StringReader(publicKeyPem));
        AsymmetricKeyParameter keyPairRaw = (AsymmetricKeyParameter)pemReader.ReadObject();
        RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
        RSA rsaObj = System.Security.Cryptography.RSA.Create();
        rsaObj.ImportParameters(rsaParams);
        return rsaObj;
    }
static void Main(字符串[]args)
{
var plainData=“纯文本”;
RSA publicKeyEncryptor=getRSAPublic(@“”);
var plainBytes=Encoding.ASCII.GetBytes(plainData);
string encryptedPayload=System.Convert.ToBase64String(publicKeyEncryptor.Encrypt(plainBytes,RSAEncryptionPadding.Pkcs1));
Console.WriteLine(encryptedPayload);
}
公共静态RSA getRSAPublic(字符串公钥)
{
字符串publicKeyPem=$“----开始公钥------\r\n{publicKey}\r\n----结束公钥------\r\n”;
var pemReader=新pemReader(新StringReader(publicKeyPem));
AsymmetricKeyParameter keyPairRaw=(AsymmetricKeyParameter)pemReader.ReadObject();
rsapartameters rsaparms=DotNetUtilities.ToRSAParameters((RsaKeyParameters)keyPairRaw);
RSA rsaObj=System.Security.Cryptography.RSA.Create();
rsaObj.输入参数(rsaparms);
返回rsaObj;
}
当我尝试将其转换为Java(Android)时,这是我想到的代码,但它没有生成有效的输出:

public static void main(String args[]) {
    String stringToEncrypt = "plain_text";
    String publicKey = "<public_key>";
    System.out.println(encrypt(stringToEncrypt, publicKey))
}

public String encrypt(String plain, String publicKey) {
    try {
        byte[] keyBytes = Base64.decode(publicKey, Base64.DEFAULT);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        PublicKey rsaPublicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
        byte[] plainTextBytes = plain.getBytes(Charset.forName("US-ASCII"));
        byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
        return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "";
}
publicstaticvoidmain(字符串参数[]){
字符串stringToEncrypt=“纯文本”;
字符串publicKey=“”;
System.out.println(加密(stringToEncrypt,公钥))
}
公共字符串加密(字符串普通、字符串公钥){
试一试{
byte[]keyBytes=Base64.decode(publicKey,Base64.DEFAULT);
X509EncodedKeySpec=新X509EncodedKeySpec(键字节);
公钥rsaPublicKey=KeyFactory.getInstance(“RSA”).generatePublic(规范);
Cipher Cipher=Cipher.getInstance(“RSA/ECB/PKCS1Padding”);
cipher.init(cipher.ENCRYPT_模式,rsaPublicKey);
byte[]plainTextBytes=plain.getBytes(Charset.forName(“US-ASCII”);
byte[]encryptedBytes=cipher.doFinal(明文字节);
返回Base64.encodeToString(encryptedBytes,Base64.NO_WRAP));
}捕获(例外e){
e、 printStackTrace();
}
返回“”;
}
有什么不同

谢谢

Java和C程序都能产生兼容的输出。兼容,但不完全相同,因为每次输出都应该不同。出于安全原因,PKCS1填充包含一个随机组件。因此,如果您期望相同的输出,那么您的期望是错误的。相同的输出将是某个错误的线索,每次输出都应该是不同的

详细解释正在发生的事情。具体而言,步骤2a表示:

生成长度为k-mLen-3的八位组字符串PS 由伪随机生成的非零八位元组成。 PS的长度至少为八个八位字节


为了验证它们的兼容性,我根据您的代码编写了小型C#和Java程序,发现它们都可以解密对方的输出并得到正确的结果。

这两种代码都是正确的。您可以用与Java版本和C#版本相同的方式加密数据。如果其中一个正在工作,而另一个正在失败,则可能是您使用了错误的公钥(复制/粘贴错误、某些不同的字节等)。

可能是“RSA/
CBC
/PKCS1Padding”该算法不存在,我得到:
java.security.NoSuchAlgorithmException:RSA/CBC/PKCS1Padding
找不到提供程序我也尝试了
RSA/ECB/PKCS1Padding
RSA/NONE/PKCS1Padding
,但它也不起作用。您使用的是BouncyCastle吗?这是安卓吗?是的,这是安卓。我尝试使用BouncyCastle提供程序,通过
Cipher.getInstance(“RSA/ECB/PKCS1Padding”,“BC”)请求密码,但结果相同。@zaitsman我用Java 1.8做了一个测试,结果是一样的,所以它似乎与Android没有关系