使用 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 的 Java 加密无法在 .NET 中解密

Posted

技术标签:

【中文标题】使用 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 的 Java 加密无法在 .NET 中解密【英文标题】:Encryption in Java with RSA/ECB/OAEPWithSHA-256AndMGF1Padding could not be decrypted in .NET 【发布时间】:2020-05-07 18:46:00 【问题描述】:

我们有一个要求,Java 进行加密,.NET 进行解密。问题在于 .NET 中的非对称解密、Java 中使用的算法、模式和填充,而加密是“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”。在 .NET 上,我尝试使用 OAEP 填充以各种不同的方式解密 RsaCng、Rsa、Chilkat Rsa、Bouncy Castle,但到目前为止没有任何效果。下面是代码sn-ps。只有当Java的加密方式改为“RSA/ECB/OAEPWithSHA-1AndMGF1Padding”时,.NET才能解密,但出于安全原因,Java不能改变加密方式。我们使用 PEM 文件进行解密,同时使用 CERT 进行加密。请让我们知道解决问题的最佳方法。是否与创建基于 SHA256 哈希的 PEM 文件有关?如果有人可以帮助我,我将不胜感激。

错误如下所述。 RsaCng 和 Rsa:- 参数不正确。 RsaCryptoService:- 解码 OAEP 填充时发生错误。 Bouncy Castle:- 它给出了一个带有符号的 alpha-unicode 字符串。 Chilkat:- 返回 null。

用于非对称加密的 Java Snippet:-

                 // Encrypt the symetric key
                 X509Certificate cert = ConduentCertificateLocator.getConduentCertificate();
                 PublicKey certKey = cert.getPublicKey();
                 Cipher c2 = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
                 //Cipher c2 = Cipher.getInstance("RSA");
                 c2.init(Cipher.ENCRYPT_MODE, certKey);
                 byte[] inputCertKey = key.getEncoded();
                 byte[] encryptedKey = c2.doFinal(inputCertKey);
                 String encryptedKeyUrl = encodeToURL(encryptedKey);

.NET Snippet for Asymmetric Decryption:- 我们确实尝试了几种不同的方法。下面是代码。

一个。 RSACryptoService

           using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
            
                using (var stream = File.OpenRead(_appSettings.PEM))
                using (var reader = new PemUtils.PemReader(stream))
                
                    var rsaParameters = reader.ReadRsaKey();
                    csp.ImportParameters(rsaParameters);

                    var resultBytes = csp.Decrypt(ksBytes, true);
                    finalResult = Convert.ToBase64String(resultBytes);
                
            

b.呸呸呸

           using (RSA rsa = new RSACng())
            
                using (var stream = File.OpenRead(_appSettings.PEM))
                using (var reader = new PemUtils.PemReader(stream))
                    rsa.ImportParameters(reader.ReadRsaKey());
                byte[] decrypted2 = rsa.Decrypt(ksBytes, RSAEncryptionPadding.OaepSHA256);
                var ss = Encoding.UTF8.GetString(decrypted2);
            

c。 Rsa (System.Security.Cryptography)

          using (RSA rsa = RSA.Create())
            
                using (var stream = File.OpenRead(_appSettings.PEM))
                using (var reader = new PemUtils.PemReader(stream))
                
                    var rsaParameters = reader.ReadRsaKey();

                    rsa.ImportParameters(rsaParameters);
                


                finalResult = rsa.Decrypt(ksBytes, RSAEncryptionPadding.OaepSHA256);
            

d。奇尔卡特

       using (PrivateKey pkey = new PrivateKey())
        
            pkey.LoadPemFile(_appSettings.PEMFile);
            key = pkey.GetXml();
        

        using (Chilkat.Rsa decryptor = new Chilkat.Rsa())
            
                decryptor.ImportPrivateKey(key);

                // Make sure we have the same settings used for encryption.
                decryptor.OaepPadding = true;
                decryptor.EncodingMode = "hex";
                decryptor.OaepHash = "sha-256";

                string eStr = decryptor.DecryptStringENC(ks, true);
            

e。充气城堡

        AsymmetricCipherKeyPair keyPair;
        using (var reader = File.OpenText(_appSettings.PEM))
            keyPair = (AsymmetricCipherKeyPair)new 
           Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
          var decryptEngine = new OaepEncoding(new RsaBlindedEngine(), new Sha256Digest(), new 
               Sha1Digest(), null);
            decryptEngine.Init(false, keyPair.Private);
            var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(ksBytes, 0, 
             ksBytes.Length));

【问题讨论】:

没有安全理由不在 Java 中使用 RSA/ECB/OAEPWithSHA-1AndMGF1Padding。 使用 Java 的客户端有一个 VeraCode 扫描系统,它不允许使用较弱的填充或哈希算法。因此,与 SHA-256 相比,SHA-1 的使用是一种较弱的散列算法。.NET 是否理解带有 OAEP 的 SHA-256 散列算法?请帮帮我。 哈哈,Java 的“RSA/ECB/OAEPWithSHA-256AndMGF1Padding”也在 MGF-1 中使用 SHA1。 是的,但我们无法在 .NET 上解密,有什么解决办法吗?请告诉我。 Bouncy Castle 说它可以解密 SHA 256 散列非对称密钥,但我得到了一些 unicode 特殊字符。我可以尝试的任何其他框架,请告诉我。 最好在一个单独的问题中发布 Bouncy Castle 示例。如果您得到错误的字符而不是填充异常,那么可能会出现正确 【参考方案1】:

我的情况有点不同,但它应该对你有所帮助。我需要用 java 解密,它是用 .NET 加密的。所以与提出的问题相反,但就像其他人提到的那样。即使您指定 RSA/ECB/OAEPWithSHA-256AndMGF1Padding ,引擎盖下的 Java 也默认为 SHA-1。对我来说,诀窍是传递一个额外的参数,告诉它实际使用 SHA-256。

JAVA:

private static byte[] decryptBytes(byte[] buffer, Key key) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException 
    Cipher rsa;
    rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    rsa.init(Cipher.DECRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT));
    return rsa.doFinal(buffer);

.NET

var encryptedBytes = publicKey.Encrypt(bytesToEncrypt, RSAEncryptionPadding.OaepSHA256);

【讨论】:

以上是关于使用 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 的 Java 加密无法在 .NET 中解密的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)