.NET中的RSA加密/解密问题 [英] RSA Encrypt / Decrypt Problem in .NET

查看:87
本文介绍了.NET中的RSA加密/解密问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用RSA对C#加密和解密有问题。我开发了一个Web服务,将发送敏感的财务信息和交易。我想要做的是在客户端,使用客户端RSA私钥加密某些字段,一旦达到我的服务,它将使用客户端公钥进行解密。



目前我不断得到一个要解密的数据超过这个128字节的最大值。例外。我没有太多的C#RSA加密,所以任何帮助将不胜感激。



这是我用来生成密钥的方法

  private void buttonGenerate_Click(object sender,EventArgs e)
{
string secretKey = RandomString(12,true);

CspParameters param = new CspParameters();
param.Flags = CspProviderFlags.UseMachineKeyStore;

SecureString secureString = new SecureString();
byte [] stringBytes = Encoding.ASCII.GetBytes(secretKey); (int i = 0; i< stringBytes.Length; i ++)
{
secureString.AppendChar((char)stringBytes [i]);

}
secureString.MakeReadOnly();
param.KeyPassword = secureString;

RSACryptoServiceProvider rsaProvider =新的RSACryptoServiceProvider(param);
rsaProvider =(RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
rsaProvider.KeySize = 1024;


string publicKey = rsaProvider.ToXmlString(false);
string privateKey = rsaProvider.ToXmlString(true);

Repository.RSA_XML_PRIVATE_KEY = privateKey;
Repository.RSA_XML_PUBLIC_KEY = publicKey;

textBoxRsaPrivate.Text = Repository.RSA_XML_PRIVATE_KEY;
textBoxRsaPublic.Text = Repository.RSA_XML_PUBLIC_KEY;

MessageBox.Show(请注意,生成密钥时,您必须登录gateway \+
来表示密钥,否则事务将失败,密钥交换 MessageBoxButtons.OK,MessageBoxIcon.Information);

}

一旦我生成了密钥,我发送公钥到web服务将它存储为一个XML文件。



现在我决定测试这个,所以这里是我的加密字符串的方法

  public static string RsaEncrypt(string dataToEncrypt)
{
string rsaPrivate = RSA_XML_PRIVATE_KEY;
CspParameters csp = new CspParameters();
csp.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider provider = new RSACryptoServiceProvider(csp);

provider.FromXmlString(rsaPrivate);

ASCIIEncoding enc = new ASCIIEncoding();
int numOfChars = enc.GetByteCount(dataToEncrypt);
byte [] tempArray = enc.GetBytes(dataToEncrypt);
byte [] result = provider.Encrypt(tempArray,true);
string resultString = Convert.ToBase64String(result);
Console.WriteLine(Encrypted:+ resultString);
return resultString;
}

我确实得到似乎是加密值。在我创建的测试crypto web方法中,然后我使用这个加密数据,使用客户端公钥尝试和解密数据,并将其发送回来。但这是抛出异常的地方。这是我的方法负责这个。

  public string DecryptRSA(string data,string merchantId)
{
string clearData = null;
try
{
CspParameters param = new CspParameters();
param.Flags = CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);

string merchantRsaPublic = GetXmlRsaKey(merchantId);
rsaProvider.FromXmlString(merchantRsaPublic);
byte [] asciiString = Encoding.ASCII.GetBytes(data);

byte [] decryptptedData = rsaProvider.Decrypt(asciiString,false);

clearData = Convert.ToString(decryptptedData);
}
catch(CryptographicException ex)
{
Log.Error(尝试解密+ merchantId,ex)的值的加密错误;

}
return clearData;
}

如果有人可以帮助我,这将是真棒,因为我已经说过我有没有做太多的C#RSA加密/解密。

解决方案

请允许我一些术语。 加密是关于保密的。一些敏感数据被转换成不可读的东西,除了知道解密密钥的实体之外。解密密钥必须是私人密钥:如果解密密钥是公共密钥,则每个人都可以解密数据(公共密钥,公共密钥),并且不再有机密性。在非对称加密中,一个用公钥加密,并用相应的私钥进行解密。


  • 数字签名旨在证明完整性。有人通过数据计算一种键控校验和,以便能够稍后验证校验和和数据之间的链接。这是一个签名,因为计算校验和的能力需要知道不公开的东西 - 简而言之,签名使用私钥键。然而,验证应该是任何人都可以做的,因此使用公钥。




  • 有点混乱这意味着RSA算法实际上是可以被拒绝到非对称加密系统和数字签名系统的数学运算。 RSA标准进一步增强了混淆,也就是 PKCS#1 ,这隐含地依赖于如何首先描述RSA数字签名,即作为反向加密(签名者使用他的私钥加密数据)。这导致像RSA签名称为sha1WithRSAEncryption的东西。这是非常不幸的。



    因此,您必须首先决定是否要保密或签名。对于机密性,对于从客户端 服务器发送的数据,服务器应拥有一个私钥,客户端使用 服务器公钥加密数据。对于签名,每个客户端都应拥有自己的私钥,并使用它来签署数据,服务器验证签名。从你的描述中我不能确定你以后真正的感受,感谢我上面提到的混淆。



    另外,还有一些叫做认证这可能看起来像数字签名,但是更弱。签名点比任何人都可以验证签名。特别是,签名可以向法官显示,从而作为签名者的合法武器(签名具有法律约束力 - 至少如果你这样做,并且在现行的法规中电子签名,这不容易)。在大多数情况下,您只需要一些更简单,更简单的服务器就可以说服与正确的客户端进行交流,但是后来不能说服客户真的在那里。任何具有用户密码的网站都使用这种身份验证。



    正如所述...




    • RSA非对称加密仅涵盖短消息。对于1024位RSA密钥(即最重要部分的密钥,RSA模数是2 ^ 1023和2 ^ 1024之间的大数字,加密消息的长度为128字节),加密消息的最大大小为117字节(这是错误消息的实际来源)。当我们想发送更长的消息时,我们使用一个混合系统,其中我们只加密一小堆随机比特(比如128位),并将该束作为对称加密系统的密钥例如AES),它可以处理更长的消息(也快得多)。


    • 类似地,RSA签名只能在短消息上计算,因此PKCS#1标准要求实际上通过散列值计算签名。哈希值是特定哈希函数的输出,它是通过消息进行签名计算的。散列函数具有固定大小的输出(例如SHA-256的256位),但接受(几乎)任意长度的输入消息。散列函数是公开的(它们中没有键),为了正确的安全性,必须有一些特殊的属性。 SHA-256现在不是一个坏的选择。 SHA-1(SHA-256的前身)被证明有一些缺点,应该避免。 MD5具有(一种SHA-1的叔叔)具有更大的弱点,不能使用。


    • 正确使用非对称加密,特别是在混合方案和数字签名,比上述文字可能提出的更为棘手。在某些时候,不可见的可以很容易地弄错它,即代码看起来会起作用,但会泄漏对攻击者有用的数据。使用非对称加密或数字签名的正确的方式是依靠现有的,精心设计的协议。协议是将密码元素组装成一个相干系统,在这些系统中处理泄漏。最主要的例子是TLS,也称为SSL。它是一种确保机密数据传输的协议,具有完整性和认证(可能是相互认证)。 HTTPS协议是HTTP和SSL的混合。明亮的一面是HTTPS具有现有的实现,特别是在C#中。最容易实现和调试的代码是已经实现和调试的代码。所以使用HTTPS,你会活得更长更开心。



    I'm having a problem with C# encrypting and decrypting using RSA. I have developed a web service that will be sent sensitive financial information and transactions. What I would like to be able to do is on the client side, Encrypt the certain fields using the clients RSA Private key, once it has reached my service it will decrypt with the clients public key.

    At the moment I keep getting a "The data to be decrypted exceeds the maximum for this modulus of 128 bytes." exception. I have not dealt much with C# RSA cryptography so any help would be greatly appreciated.

    This is the method i am using to generate the keys

    private void buttonGenerate_Click(object sender, EventArgs e)
    {
        string secretKey = RandomString(12, true);
    
        CspParameters param = new CspParameters();
        param.Flags = CspProviderFlags.UseMachineKeyStore;
    
        SecureString secureString = new SecureString();
        byte[] stringBytes = Encoding.ASCII.GetBytes(secretKey);
        for (int i = 0; i < stringBytes.Length; i++)
        {
            secureString.AppendChar((char)stringBytes[i]);
        }
        secureString.MakeReadOnly();
        param.KeyPassword = secureString;
    
        RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);
        rsaProvider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
        rsaProvider.KeySize = 1024;
    
    
        string publicKey = rsaProvider.ToXmlString(false);
        string privateKey = rsaProvider.ToXmlString(true);
    
        Repository.RSA_XML_PRIVATE_KEY = privateKey;
        Repository.RSA_XML_PUBLIC_KEY = publicKey;
    
        textBoxRsaPrivate.Text = Repository.RSA_XML_PRIVATE_KEY;
        textBoxRsaPublic.Text = Repository.RSA_XML_PUBLIC_KEY;
    
        MessageBox.Show("Please note, when generating keys you must sign on to the gateway\n" +
            " to exhange keys otherwise transactions will fail", "Key Exchange", MessageBoxButtons.OK, MessageBoxIcon.Information);
    
    }
    

    Once i have generated the keys, i send the public key to the web service which stores it as an XML file.

    Now i decided to test this so here is my method to encrypt a string

    public static string RsaEncrypt(string dataToEncrypt)
    {
        string rsaPrivate = RSA_XML_PRIVATE_KEY;
        CspParameters csp = new CspParameters();
        csp.Flags = CspProviderFlags.UseMachineKeyStore;
    
        RSACryptoServiceProvider provider = new RSACryptoServiceProvider(csp);
    
        provider.FromXmlString(rsaPrivate);
    
        ASCIIEncoding enc = new ASCIIEncoding();
        int numOfChars = enc.GetByteCount(dataToEncrypt);
        byte[] tempArray = enc.GetBytes(dataToEncrypt);
        byte[] result = provider.Encrypt(tempArray, true);
        string resultString = Convert.ToBase64String(result);
        Console.WriteLine("Encrypted : " + resultString);
        return resultString;
    }
    

    I do get what seems to be an encrypted value. In the test crypto web method that i created, i then take this encrypted data, try and decrypt the data using the clients public key and send this back in the clear. But this is where the exception is thrown. Here is my method responsible for this.

    public string DecryptRSA(string data, string merchantId)
    {
        string clearData = null;
        try
        {
            CspParameters param = new CspParameters();
            param.Flags = CspProviderFlags.UseMachineKeyStore;
            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);
    
            string merchantRsaPublic = GetXmlRsaKey(merchantId);
            rsaProvider.FromXmlString(merchantRsaPublic);
            byte[] asciiString = Encoding.ASCII.GetBytes(data);
    
            byte[] decryptedData = rsaProvider.Decrypt(asciiString, false);
    
            clearData = Convert.ToString(decryptedData);
        }
        catch (CryptographicException ex)
        {
            Log.Error("A cryptographic error occured trying to decrypt a value for " + merchantId, ex);
    
        }
        return clearData;
    }
    

    If anyone could help me that would be awesome, as i have said i have not done much with C# RSA encryption/decryption.

    解决方案

    Allow me a bit of terminology. There is asymmetric encryption and there is digital signature.

    • Asymmetric encryption is about keeping confidentiality. Some sensitive data is transformed into something unreadable, save for the entity who knows the decryption key. The decryption key is necessarily the private key: if the decryption key is the public key, then everybody can decrypt the data (the public key is, well, public) and there is no confidentiality anymore. In asymmetric encryption, one encrypts with the public key and decrypts with the corresponding private key.

    • Digital signatures are meant to prove integrity. Someone computes a kind of keyed checksum over the data, in such a way that the link between the checksum and the data can be verified later. This is a "signature" only because the power to compute that checksum requires knowledge of something which is not public -- in plain words, signing uses the private key. Verification, however, should be doable by anybody, and thus use the public key.

    A fair bit of confusion is implied by the fact that "the" RSA algorithm is actually a mathematical operation which can be declined into both an asymmetric encryption system, and a digital signature system. The confusion is further enhanced by the RSA standard, aka PKCS#1, which implicitly relies on how RSA digital signatures were first described, i.e. as a "reversed encryption" ("the signer encrypts the data with his private key"). Which leads to things like RSA signatures called "sha1WithRSAEncryption". This is quite unfortunate.

    Therefore, you must first decide whether you want confidentiality or signatures. For confidentiality, for data sent from clients to the server, the server shall own a private key, and the clients use the server public key to encrypt the data. For signatures, each client shall have his own private key and use it to sign the data, and the server verifies the signatures. From your description I cannot tell what you are really after, thanks to the confusion I allude to above.

    Also, there is something called authentication which may look like digital signatures, but is weaker. The point of signatures is than anybody can verify the signature. In particular, the signature can be shown to a judge and thus serve as legal weapon against the signer (the signature is legally binding -- at least if you do it right, and in the current state of regulations over electronic signatures, this is not easy). In most situations you only need something weaker and simpler, in which the server is convinced that it talks to the right client, but cannot afterwards convince anybody else that this client was really there. Any web site with user passwords is using such authentication.

    With that being said...

    • RSA asymmetric encryption covers only short messages. For a 1024-bit RSA key (i.e. a key where the most important part, the "RSA modulus", is a big number with a value between 2^1023 and 2^1024, and encrypted messages will be of length 128 bytes), the maximum size of an encrypted message is 117 bytes (that's the actual source of your error message). When we want to send longer messages, we use an hybrid system, in which we only encrypt a small bunch of random bits (say 128 bits) and use that bunch as a key for a symmetric encryption system (e.g. AES) which can process much longer messages (and much faster, too).

    • RSA signatures, similarly, can be computed only on short messages, hence the PKCS#1 standard mandates that a signature is actually computed over a hash value. The hash value is the output of a specific hash function, which is computed over the message to sign. The hash function has a fixed-sized output (e.g. 256 bits for SHA-256) but accepts input messages of (almost) arbitrary length. Hash functions are public (there is no key in them) and, for proper security, must have some special properties. SHA-256 is, right now, not a bad choice. SHA-1 (a predecessor of SHA-256) has been proven to have some weaknesses and should be avoided. MD5 has (a kind-of uncle of SHA-1) has bigger weaknesses and shall not be used.

    • Proper use of asymmetric encryption, especially in an hybrid scheme, and digital signatures, is trickier than what the text above may suggest. It is awfully easy to get it wrong at some point, invisibly, i.e. the code will appear to work but will leak data useful for an attacker. The right way to use asymmetric encryption or digital signatures is to rely on existing, well-thought protocols. A protocol is an assembly of cryptographic elements into a coherent system, where leaks are taken care of. The prime example is TLS, also known as SSL. It is a protocol which ensures confidential data transmission, with integrity and authentication (possibly mutual authentication). The HTTPS protocol is a mixture of HTTP and SSL. The bright side is that HTTPS has existing implementations, notably in C#. The code which is easiest to implement and debug is the code which has already been implemented and debugged. So use HTTPS and you will live longer and happier.

    这篇关于.NET中的RSA加密/解密问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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