使用Java和C#在Bouncy Castle中进行RSA加密的结果之间的差异 [英] Difference between results with RSA Encryption with Bouncy Castle in Java and C#

查看:82
本文介绍了使用Java和C#在Bouncy Castle中进行RSA加密的结果之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Java 可工作示例应用程序(使用Bouncy Castle),需要将其移植到C#(我也将Bouncy Castle用于C#).

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

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

我在哪里弄错了?预先谢谢你!

Java:

 公共静态字符串encodeRSA(String keyModulus,String keyExponent,字符串数据){尝试 {字节btMod [] = Base64.decode(keyModulus);字节btExp [] = Base64.decode(keyExponent);BigInteger模数=新的BigInteger(1,btMod);BigInteger pubExp =新的BigInteger(1,btExp);KeyFactory keyFactory = KeyFactory.getInstance("RSA");RSAPublicKeySpec pubKeySpec =新的RSAPublicKeySpec(modulus,pubExp);RSAPublicKey键=(RSAPublicKey)keyFactory.generatePublic(pubKeySpec);密码cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE,key);byte [] cipherData = cipher.doFinal(data.getBytes());字符串tmp =新字符串(Base64.encode(cipherData));System.out.println(tmp);返回tmp;} catch(Exception e){System.out.println(e.getMessage());}返回 "";} 

C#:

 私有静态字符串EncodeRSA(字符串模数,字符串指数,字符串数据){//Base64,DotNetUtilities函数和BigInteger类型来自Bouncy Castlebyte [] btMod = Base64.Decode(modulus);byte [] btExp = Base64.Decode(exponent);BigInteger mod =新的BigInteger(1,btMod);BigInteger exp =新的BigInteger(1,btExp);RsaKeyParameters bcKeySpec =新的RsaKeyParameters(false,mod,exp);RSAParameters keySpec = DotNetUtilities.ToRSAParameters(bcKeySpec);RSACryptoServiceProvider rsa =新的RSACryptoServiceProvider();rsa.ImportParameters(keySpec);byte [] plaintext = Encoding.UTF8.GetBytes(data);byte []密文= rsa.Encrypt(plaintext,false);字符串cipherresult = Encoding.UTF8.GetString(Base64.Encode(ciphertext));返回密码结果;} 

模量:

<预> <代码> gdBAMJVXCuEGhX0b1hPAggpD7Ayi33JhsARksGkEatQsdox3BG3bTR/vz8M4vZe74EZj0aZrk0rGJGmAEJZ9GlXq6JzIRYBW5zULsBoPDq4spgobECJLsXq8CnZzOrOM + meIXFhoK8Jyob4X9q62HkDwhMMyqsBG0epWMHPIgkU =

指数:

  AQAB 

输出:

 条目"1] teste] 111111] MTExMTExMTExMTExMTExMQ =="的Java输出使用给定的模数/指数dUCVsGrZIwSyh0ZAxon3wMSPPoQqflpRNtQ5c + TILuOR/5IihABJpZRL6E1TjYs62WXvQUbeFqRYbdAvbjY3YZk + aSviBosdN54 + T8 +/5agjveeDBi6LXu6K6S6KX6K9 

编辑-具有给定条目,模数和指数的C#输出

 <代码> CHyg5J + OMuG9H9S7R24Lg2iXeLN/Rgh7XcyDQJqMNZobH0V1hqe2dxrcE3R + UrVl/aDWJg3aXNtP3 + 8YFA17fLr9yIbIYv5o2zeRMdHbyrW/z26JGaynsay096KEzJ0uBAACJQ3LZryd5ei7zzo77Bnka2Un7C9TJvldswhldxM = 

解决方案

RSA加密的输出(或任何安全加密方法)将输出与随机数据区别开来,对攻击者来说是不可区分的.对于对称密码,这是通过IV来完成的;对于RSA,是通过 padding方法来完成的.如果不是这种情况,那么攻击者将能够看到不同密文的相似性.两次加密是",将出现相同的密文.因此,攻击者可以轻松区分 E(pk,"yes")| E(pk,"yes")中的E(pk,"yes") |E(pk,否").

因此Java和C#都输出密文,该密文恰好是编码前模数的大小.但是,在用于RSA的模幂运算之前,首先用安全的随机数据填充明文.验证密文生成正确的方法是使用私钥对密文进行解密.实际上,如果您同时运行Java或C#,那么即使在相同的语言/运行时间内,密文也会不断变化.

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).

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

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

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#:

    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

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

解决方案

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").

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#在Bouncy Castle中进行RSA加密的结果之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆