使用.NET RSACryptoServiceProvider进行加密,并让OpenSSL解密 [英] Use .NET RSACryptoServiceProvider for encryption and let OpenSSL decrypt

查看:103
本文介绍了使用.NET RSACryptoServiceProvider进行加密,并让OpenSSL解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个.NET客户端,该客户端将加密的消息发送到使用OpenSSL用C编写的服务器,然后在那里解密该消息.
我将RSA与PKCS1填充一起使用.
.NET客户端使用一个OpenSSL服务器生成的公共密钥.
客户端加密没有错误.
但是服务器无法解密.NET客户端的序列.
错误:2006E079:BIO例程:BIO_puts:不受支持的方法

我在代码中看到了3种可能的错误源.
1.服务器为.NET客户端编码的公共密钥不正确,即使它被.NET客户端无误接受的可能性有多大?
2.我在客户端中编码加密序列的方式是错误的.这将是解密期间发生错误的明显原因.
3.有2种不同版本的PKCS1填充.

要测试该方案,我在此邮件末尾使用J#代码.首先,我确保加密/解密仅在J#中有效.
要将使用OpenSSL生成的公钥转换为可在.NET中使用的格式,我使用以下密码库调用:

BIO * b64,* out,* wbio;
b64 = BIO_new(BIO_f_base64());
out = BIO_new(BIO_s_file());
BIO_set_fp(out,stdout,BIO_NOCLOSE);
ushio = BIO_p (b64,out);

int val [1] = {65537};
char * buf =(char *)val;
BIO_write(wbio,val,3); /*指数,仅写入3个字节*/
(void)BIO_flush(wbio);
BIO_write(wbio,rsa_public-> n-> d,128); /*模数*/
(void)BIO_flush(wbio);

服务器使用与生成公钥相同的私钥解密密码:
retval = RSA_private_decrypt(RSA_size(rsa_private) ,cryptoPasswordCharArrayfromNetClient,cleartext-output,rsa_private,RSA_PKCS1_PADDING);

我测试了我的代码,以便使用OpenSSL在C代码中进行加密/解密. RSA的标准.NET类.
我很难将两者结合在一起.如果我将RSA_private_decrypt与从.NET客户端创建的字节序列一起使用,则会收到错误:
错误:537321593
错误:2006E079:BIO例程:BIO_puts:不受支持的方法

调试显示该错误从
case RSA_PKCS1_PADDING:
返回r = RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);


J#客户端代码:

包RSAEncryption. java;

导入System.*;
导入System.Security.Cryptography.*;
导入System.Text.*;

RSASample类
{
public static void main(String [] args)
尝试{
尝试//创建一个UnicodeEncoder在字节数组和字符串之间进行转换. unicodeDataToEncrypt [] = byteConverter.GetBytes("myPassword!");

编码ascii = Encoding.get_ASCII();
编码unicode = Encoding.get_Unicode() =编码转换ert(unicode,ascii,unicodeDataToEncrypt);

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

0 =</Modulus>< Exponent>/AQAB</Exponent</RSAKeyValue>";; rsa.FromXmlString(publicRSAKeyXML);

////3.参数:一个布尔型标志,指定不进行OAEP填充.
ubyte [] encryptionData = RSAEncrypt(dataToEncrypt,rsaParameter,false);

//显示加密序列到控制台.
System.out.print(静态签名的char chartedPasswordStringfromNetClient [] = {");
表示(int i = 0; i (i%16 == 0) .out.print((byte)encryptedData [i] +,");
}
System.out.println("\ n};");

catch(ArgumentNullException exp){
//如果加密没有成功,则捕获此异常.
Console.WriteLine(加密失败".")
}//main

public static ubyte [] RSAEncrypt(ubyte dataToEncrypt [],
RSAParameters rsaKeyInfo,boolean doOaepPadding)
{
尝试{<创建一个新的RSACryptoServiceProvider实例.
RSACryptoServiceProvider rsa =新的RSACryptoServ iceProvider();


//导入rsa密钥信息.这仅需要来//包含公共密钥信息.
rsa.ImportParameters(rsaKeyInfo);


//加密传递的字节数组并指定OAEP填充.
//OAEP填充仅在Microsoft Windows XP或更高版本上可用.
返回rsa.Encrypt(dataToEncrypt,doOaepPadding); WriteLine(e.get_Message());
返回null;
}
}//RSAEncrypt

}//RSASample


注意事项,
Paul

I want to write a .NET client that sends an encrypted message to a server written in C with OpenSSL, and decrypt the message there.
I use RSA with PKCS1 padding.
The .NET client uses a public key generated by the OpenSSL server.
The client encrypts without error.
But the server cannot decrypt the sequence from the .NET client.
error:2006E079:BIO routines:BIO_puts:unsupported method
 
I see 3 possible sources of error in my code.
1. How big is the chance that the public key encoded by the server for the .NET client is not correct even so it is accepted by the .NET client without error?
2. The way how I encode the encrypted sequence in the client is wrong. That would be an obvious reason for the error during decryption.
3. There are 2 different versions of PKCS1 padding used.

To test the scenario  I use the J# code at the end of this mail. First I made sure that encryption / decryption works in J# alone.
To get the public key generated with OpenSSL into a format that can be used in .NET I use the following crypto library calls:

    BIO *b64, *out, *wbio;
    b64 = BIO_new(BIO_f_base64());
    out = BIO_new(BIO_s_file());
    BIO_set_fp(out,stdout,BIO_NOCLOSE);
    wbio=BIO_push(b64,out);

    int val[1] = {65537};
    char *buf = (char*) val;
    BIO_write(wbio, val, 3);  /* exponent, only 3 bytes written */
    (void)BIO_flush(wbio);
    BIO_write(wbio, rsa_public->n->d, 128); /* modulus */
    (void)BIO_flush(wbio);

The server decrypts the password with the same private key used to generate the public key:
        retval = RSA_private_decrypt(RSA_size(rsa_private), encryptedPasswordCharArrayfromNetClient, cleartext-output, rsa_private, RSA_PKCS1_PADDING);

I tested my code so that encryption /  decryption works in the C code using OpenSSL.
I tested my J# code so that encryption /  decryption works using standard .NET class  for RSA.
I have trouble to get the two together. If I use RSA_private_decrypt with a byte sequence created from the .NET client I get the error:
Error: 537321593
error:2006E079:BIO routines:BIO_puts:unsupported method

Debugging shows that the error is returned from
    case RSA_PKCS1_PADDING:
        r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);


The J# client code:

package RSAEncryption.java;

import System.*;
import System.Security.Cryptography.*;
import System.Text.*;

class RSASample
{
    public static void main(String[] args)
    {
        try {
            // Create a UnicodeEncoder to convert between byte array and string.
            UnicodeEncoding byteConverter =  new UnicodeEncoding();
            ubyte unicodeDataToEncrypt[] = byteConverter.GetBytes("myPassword!");

            Encoding ascii = Encoding.get_ASCII();
            Encoding unicode = Encoding.get_Unicode();
            ubyte dataToEncrypt[] = Encoding.Convert(unicode, ascii, unicodeDataToEncrypt);
           
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            String publicRSAKeyXML = "<RSAKeyValue><Modulus>h...deleted...0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
            rsa.FromXmlString(publicRSAKeyXML);

            RSAParameters rsaParameter = rsa.ExportParameters(false);

            // 3. parameter: a boolean flag specifying no OAEP padding.
            ubyte [] encryptedData = RSAEncrypt(dataToEncrypt, rsaParameter, false);

    // Display the encrypted sequence to the console.
    System.out.print("static signed char encryptedPasswordStringfromNetClient[] = {");
    for (int i = 0; i < encryptedData.length; i++)
    {
        if (i % 16 == 0)
        {
            System.out.println("");
            System.out.print("    ");
        }
        System.out.print((byte)encryptedData[i] + ", ");
    }
    System.out.println("\n};");
           
        }
        catch (ArgumentNullException exp) {
            //Catch this exception in case the encryption did
            //not succeed.
            Console.WriteLine("Encryption failed.");
        }
    } //main

    public static ubyte[] RSAEncrypt(ubyte dataToEncrypt[],
        RSAParameters rsaKeyInfo, boolean doOaepPadding)
    {
        try {
            // Create a new instance of RSACryptoServiceProvider.
            RSACryptoServiceProvider rsa =  new RSACryptoServiceProvider();
           
            // Import the rsa Key information. This only needs
            // to include the public key information.
            rsa.ImportParameters(rsaKeyInfo);
           
            // Encrypt the passed byte array and specify OAEP padding. 
            // OAEP padding is only available on Microsoft Windows XP or
            // later. 
            return rsa.Encrypt(dataToEncrypt, doOaepPadding);
        }
        // Catch and display a CryptographicException 
        // to the console.
        catch (CryptographicException e) {
            Console.WriteLine(e.get_Message());
            return null ;
        }
    } //RSAEncrypt

} //RSASample

Regards,
Paul

推荐答案

早上好,Alan,该论坛旨在通过我们开放的协议文档帮助客户进行互操作.您的问题似乎与我们的协议文档无关.通过在 http://上的"Security Windows Server Microsoft TechNet论坛"上发布,可以更好地回答您的问题. forums.technet.microsoft.com/zh-CN/winserversecurity/threads/.

关于,
比尔·韦斯

Regards,
Bill Wesse


这篇关于使用.NET RSACryptoServiceProvider进行加密,并让OpenSSL解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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