将RSA加密Java代码移植到C# [英] Port RSA encryption Java code to C#

查看:76
本文介绍了将RSA加密Java代码移植到C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将以下Java代码移植到等效的C#:

 公共静态字符串加密(字符串值,字符串密钥)抛出InvalidKeySpecException,NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException {byte []个字节= value.getBytes(Charset.forName("UTF-8"));X509EncodedKeySpec x509 =新的X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));KeyFactory factory = KeyFactory.getInstance("RSA");PublicKey publicKey = factory.generatePublic(x509);密码cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE,publicKey);字节= cipher.doFinal(bytes);返回DatatypeConverter.printBase64Binary(bytes);} 

到目前为止,我已经使用.NET的BouncyCastle库在C#中成功编写了以下代码:

 公共静态字符串Encrypt(字符串值,字符串密钥){var bytes = Encoding.UTF8.GetBytes(value);var publicKeyBytes = Convert.FromBase64String(key);var asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);var rsaKeyParameters =(RsaKeyParameters)asymmetricKeyParameter;var cipher = CipherUtilities.GetCipher("RSA");cipher.Init(true,rsaKeyParameters);var processBlock = cipher.DoFinal(bytes);返回Convert.ToBase64String(processBlock);} 

但是,即使使用相同的参数调用,这两种方法也会产生不同的结果.出于测试目的,我使用以下公共RSA密钥:

<预> <代码> MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCZahTj/oz8mL6xsIfnX399Gt6bh8rDHx2ItTMjUhQrE/9kGznP5PVP19vFkQjHhcBBJ0Xi1C1wPWMKMfBsnCPwKTF/g4yga6yw26awEy4rvfjTCuFUsrShSPOz9OxwJ4t0ZIjuKxTRCDVUO7d/GZh2r7lx4zJCxACuHci0DvTQIDAQAB

能否请您帮助我成功移植Java代码或建议使用C#获得相同结果的替代方法?

EDIT1 :每次我运行该程序时,Java中的输出都是不同的.我认为没有指定任何填充,所以我不明白是什么使输出随机的.

EDIT2 :Java默认情况下使用PKCS1,因此只需在C#密码初始化中指定它即可获得相同的加密类型(尽管结果不同,这在当时是无关紧要的)

解决方案

作为有根据的猜测,我想说Java添加了随机填充来创建更强的加​​密.

RSA的大多数实际实现都可以做到这一点,就像 wiki 一样放...

因为RSA加密是一种确定性加密算法-即没有随机成分-攻击者可以通过在公钥下加密可能的明文并测试它们是否等于密文,从而成功地发起了针对密码系统的选定明文攻击.如果攻击者即使知道(或已选择)相应的明文,也无法将两种加密彼此区分开,则该密码系统在语义上称为安全.如上所述,没有填充的RSA在语义上是不安全的.

这很可能是您的两种方法输出的结果不同的原因.

I'm trying to port the following Java code to a C# equivalent:

public static String encrypt(String value, String key) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    byte[] bytes = value.getBytes(Charset.forName("UTF-8"));
    X509EncodedKeySpec x509 = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(key));
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = factory.generatePublic(x509);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    bytes = cipher.doFinal(bytes);
    return DatatypeConverter.printBase64Binary(bytes);
}

So far I managed to write the following in C#, using the BouncyCastle library for .NET:

public static string Encrypt(string value, string key)
    {
        var bytes = Encoding.UTF8.GetBytes(value);
        var publicKeyBytes = Convert.FromBase64String(key);
        var asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
        var rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter;
        var cipher = CipherUtilities.GetCipher("RSA");
        cipher.Init(true, rsaKeyParameters);
        var processBlock = cipher.DoFinal(bytes);
        return Convert.ToBase64String(processBlock);
    }

The two methods, though, produce different results even if called with the same parameters. For testing purposes, I'm using the following public RSA key:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCZahTj/oz8mL6xsIfnX399Gt6bh8rDHx2ItTMjUhQrE/9kGznP5PVP19vFkQjHhcBBJ0Xi1C1wPWMKMfBsnCPwKTF/g4yga6yw26awEy4rvfjTCuFUsrShSPOz9OxwJ4t0ZIjuKxTRCDVUO7d/GZh2r7lx4zJCxACuHci0DvTQIDAQAB

Could you please help me to port the Java code successfully or suggest an alternative to get the same result in C#?

EDIT1: output in Java is different each time I run the program. I don't think that any padding was specified, so I don't understand what makes the output random.

EDIT2: Java uses PKCS1 by default, so it was enough to specify it in the C# cipher initialization to get the same encryption type (although not the same result, which was irrelevant at this point).

解决方案

As an educated guess, I would say that Java adds random padding to create a stronger encryption.

Most practical implementations of RSA do this, and as the wiki puts it...

Because RSA encryption is a deterministic encryption algorithm – i.e., has no random component – an attacker can successfully launch a chosen plaintext attack against the cryptosystem, by encrypting likely plaintexts under the public key and test if they are equal to the ciphertext. A cryptosystem is called semantically secure if an attacker cannot distinguish two encryptions from each other even if the attacker knows (or has chosen) the corresponding plaintexts. As described above, RSA without padding is not semantically secure.

This is likely why your two methods don't output the same.

这篇关于将RSA加密Java代码移植到C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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