为什么RSA加密在C#和Java中会返回不同的结果?

4

我使用:

  • c#: RSACryptoServiceProvider
  • JAVA: KeyFactory.getInstance("RSA")+Cipher

我将公钥(指数+模数)作为字节数组从Java发送到c#,这是可以的,字节是相同的。但是当我尝试使用一个密钥在Java和c#中加密一些数据时,结果不同。

Java密钥生成:

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize( Config.CRYPTO_KEY_NUM_BITS );

m_KeyPair = keyGen.genKeyPair();

m_PublicKey = KeyFactory.getInstance("RSA").generatePublic(
 newX509EncodedKeySpec(m_KeyPair.getPublic().getEncoded()));

byte[] exponent = m_PublicKey.getPublicExponent().toByteArray();
byte[] modulus  = m_PublicKey.getModulus().toByteArray(); // then sending...

C# 键盘接收:

// Recieved...
m_ExternKey = new RSAParameters();
m_ExternKey.Exponent    = exponent;
m_ExternKey.Modulus     = modulus;

m_RsaExtern = new RSACryptoServiceProvider();
m_RsaExtern.ImportParameters(m_ExternKey);

byte[] test = m_RsaExtern.Encrypt(bytesToEncrypt, true);

问题是加密字节不同。

谢谢。

4个回答

21

RSA加密是随机的。对于给定的公钥和消息,每次加密尝试都会产生一个不同的字节序列。这是正常和预期的;随机字节被注入作为填充阶段的一部分,如果不注入随机字节,将导致一个弱加密系统。在解密期间,填充字节被定位并移除,原始消息则得以完好地恢复。

因此,使用Java和C#进行加密时,预计会得到不同的加密消息,即使您两次运行Java或C#代码也是如此。


1
+1 我没有尝试过,但我也非常确定随机填充是导致这个问题的原因。 - stmax

-1

希望这对你有所帮助,在C#中开心编码

            byte[] rsaExp = rsaParameters.Exponent.ToByteArray();
            byte[] Modulus = rsaParameters.Modulus.ToByteArray();

            // Microsoft RSAParameters modulo wants leading zero's removed so create new array with leading zero's removed
            int Pos = 0;
            for (int i = 0; i < Modulus.Length; i++)
            {
                if (Modulus[i] == 0)
                {
                    Pos++;
                }
                else
                {
                    break;
                }
            }
            byte[] rsaMod = new byte[Modulus.Length - Pos];
            Array.Copy(Modulus, Pos, rsaMod, 0, Modulus.Length - Pos);

-1

RSA加密算法不应该在相似的密钥下返回不同的值 - 这是标准化的算法。请检查您的密钥。


2
通常在RSA加密之前会添加随机数据填充(参见PKCS#1,OAEP)。 - stmax

-1

RSA参数包含比模数和指数更多的参数,如果我没记错的话。您需要完全初始化RSA参数才能正确进行加密(在.NET中)。

此外,在.NET中,您的私钥和公钥甚至都没有设置。


是的,但据我所知,RSA加密只需要公共指数和模数。其他参数用于解密。 - ActioN
理论上是可以的,但实现可能需要更多。我建议尝试使用包含私钥的证书,并使用该证书进行加密。 - Henri

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