使用Java和C#中的Bouncy Castle进行RSA加密的结果之间的差异

时间:2021-08-26 18:34:33

I have a Java working sample app (which uses Bouncy Castle) that I need to port to C# (I'm using Bouncy Castle for C# too).

我有一个Java工作示例应用程序(使用Bouncy Castle),我需要移植到C#(我也在使用Bouncy Castle for C#)。

The code is almost the same. However, even when I provide exactly the same modulus and exponent for both, the result arrays are completely different also the strings.

代码几乎相同。但是,即使我为两者提供完全相同的模数和指数,结果数组也与字符串完全不同。

Reiterating: The Java excerpt is the code that works

重申:Java摘录是有效的代码

Where do I'm getting wrong? Thank you in advance!

我哪里出错了?先谢谢你!

Java:

Java的:

public static String encodeRSA(String keyModulus, String keyExponent,
        String data) {
    try {

        byte btMod[] = Base64.decode(keyModulus);
        byte btExp[] = Base64.decode(keyExponent);

        BigInteger modulus = new BigInteger(1, btMod);
        BigInteger pubExp = new BigInteger(1, btExp);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(modulus, pubExp);
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] cipherData = cipher.doFinal(data.getBytes());
        String tmp = new String(Base64.encode(cipherData));

        System.out.println(tmp);

        return tmp;
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    return "";
}

C#:

C#:

    private static string EncodeRSA(string modulus, string exponent, string data)
    {
        //Base64, DotNetUtilities functions and BigInteger type are from Bouncy Castle
        byte[] btMod = Base64.Decode(modulus);
        byte[] btExp = Base64.Decode(exponent);

        BigInteger mod = new BigInteger(1, btMod);
        BigInteger exp = new BigInteger(1, btExp);

        RsaKeyParameters bcKeySpec = new RsaKeyParameters(false, mod, exp);
        RSAParameters keySpec = DotNetUtilities.ToRSAParameters(bcKeySpec);

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(keySpec);


        byte[] plaintext = Encoding.UTF8.GetBytes(data);
        byte[] ciphertext = rsa.Encrypt(plaintext, false);
        string cipherresult = Encoding.UTF8.GetString(Base64.Encode(ciphertext));
        return cipherresult;
    }

Modulus:

模数:

gdBAMJVXCuEGhX0b1hPAggpD7Ayi33JhsARksGkEatQsdox3BG3bTR/vz8M4vZe74EZj0aZrk0rGJGmAEJZ9GlXq6JzIRYBW5zULsBoPDq4spgobECJLsXq8CnZzOrOM+meIXFhoK8Jyob4X9q62HkDwhMMyqsBG0epWMHPIgkU=

Exponent:

指数:

AQAB

Output:

输出:

Java output for the entry "1]teste]111111]MTExMTExMTExMTExMTExMQ==" 
using the given modulus/exponent

dUCVsGrZIwSyh0ZAxon3wMSPPoQqflpRNtQ5c+TILuOR/5IihABJpZRL6E1TjYs62WXvQUbeFqRYbdAvbjY3YZk+aSviBosdN54+T8+/5agjveeDBi6LXu6r1+KBriq2K1ULg9YC62SrSbRN8VMJ9gkgatF2ux06PyouJOPJPN8=

EDIT - C# Output with given entry, modulus and exponent

EDIT - C#输出给定的条目,模数和指数

CHyg5J+OMuG9H9S7R24Lg2iXeLN/Rgh7XcyDQJqMNZobH0V1hqe2dxrcE3R+UrVl/aDWJg3aXNtP3+8YFA17fLr9yIbIYv5o2zeRMdHbyrW/z26JGaynsay096KEzJ0uBAACJQ3LZryd5ei7zzo77Bnka2Un7C9TJvldswhldxM=

1 个解决方案

#1


1  

The output of RSA encryption, or any secure encryption method, outputs data that is indistinguishable from random to an attacker. This is performed by the IV for symmetric ciphers and by the padding method for RSA. If this wasn't the case then an attacker would be able to see similarities for different ciphertext; encrypt "yes" twice and the same ciphertext would appear. So an attacker could easily distinguish E(pk, "yes") | E(pk, "yes") from E(pk, "yes") | E (pk, "no").

RSA加密的输出或任何安全加密方法将与随机无法区分的数据输出给攻击者。这由对称密码的IV和RSA的填充方法执行。如果不是这种情况,那么攻击者就能看到不同密文的相似之处;加密“是”两次,并出现相同的密文。因此攻击者可以很容易地区分E(pk,“是”)| E(pk,“是”)来自E(p​​k,“是”)| E(pk,“不”)。

So Java and C# both output a ciphertext that is precisely the size of the modulus before encoding. However the plaintext is first padded with secure random data before the modular exponentiation used for RSA. The way to verify that the ciphertext generation was correct is by decrypting the ciphertext using the private key. Actually, if you have multiple runs of either Java or C# you will find that the ciphertext keeps changing even within the same language/runtime.

因此,Java和C#都会在编码之前输出一个恰好是模数大小的密文。然而,在用于RSA的模幂运算之前,首先用安全随机数据填充明文。验证密文生成是否正确的方法是使用私钥解密密文。实际上,如果您有多次运行Java或C#,您会发现即使在相同的语言/运行时内,密文也会不断变化。

#1


1  

The output of RSA encryption, or any secure encryption method, outputs data that is indistinguishable from random to an attacker. This is performed by the IV for symmetric ciphers and by the padding method for RSA. If this wasn't the case then an attacker would be able to see similarities for different ciphertext; encrypt "yes" twice and the same ciphertext would appear. So an attacker could easily distinguish E(pk, "yes") | E(pk, "yes") from E(pk, "yes") | E (pk, "no").

RSA加密的输出或任何安全加密方法将与随机无法区分的数据输出给攻击者。这由对称密码的IV和RSA的填充方法执行。如果不是这种情况,那么攻击者就能看到不同密文的相似之处;加密“是”两次,并出现相同的密文。因此攻击者可以很容易地区分E(pk,“是”)| E(pk,“是”)来自E(p​​k,“是”)| E(pk,“不”)。

So Java and C# both output a ciphertext that is precisely the size of the modulus before encoding. However the plaintext is first padded with secure random data before the modular exponentiation used for RSA. The way to verify that the ciphertext generation was correct is by decrypting the ciphertext using the private key. Actually, if you have multiple runs of either Java or C# you will find that the ciphertext keeps changing even within the same language/runtime.

因此,Java和C#都会在编码之前输出一个恰好是模数大小的密文。然而,在用于RSA的模幂运算之前,首先用安全随机数据填充明文。验证密文生成是否正确的方法是使用私钥解密密文。实际上,如果您有多次运行Java或C#,您会发现即使在相同的语言/运行时内,密文也会不断变化。