簡體   English   中英

在C#中使用具有正確私鑰和公鑰對的RSA解密時,數據異常異常

[英]Bad data exception when decrypting using RSA with correct private and public key pair in C#

這是我的解密過程代碼:

    private RSACryptoServiceProvider _rsa;
    private string _privateKey;
    private string _publicKey;

    public RsaLibrary()
    {
        //initialsing the RSA object taking the option of a 1024 key size
        _rsa = new RSACryptoServiceProvider(1024);
        _privateKey = _rsa.ToXmlString(true);
        _publicKey = _rsa.ToXmlString(false);

    }

 public string Decrypt(string ciphertext, string privateKey_ = null)
    {
        if (String.IsNullOrEmpty(privateKey_))
        {
            return DecryptToBytes(ciphertext, _privateKey);
        }
        else
        {
            return DecryptToBytes(ciphertext, privateKey_);
        }
    }

    private string DecryptToBytes(string ciphertext, string privateKey)
    {
        if (String.IsNullOrEmpty(privateKey))
        {
            throw new ArgumentNullException("Error: No key provided.");
        }
        if (ciphertext.Length<=0)
        {
            throw new ArgumentNullException("Error: No message to decrypt.");
        }

        byte[] plaintext;
        byte[] ciphertext_Bytes = Encoding.Unicode.GetBytes(ciphertext);
        _rsa.FromXmlString(privateKey);

        plaintext = _rsa.Decrypt(ciphertext_Bytes, false);

        return Encoding.Unicode.GetString(plaintext);
    }

加密代碼:

        private string EncryptToByte(string plaintext, string publicKey)
    {
        if (String.IsNullOrEmpty(publicKey))
        {
            throw new ArgumentNullException("Error: No key provided.");
        }
        if (plaintext.Length<=0)
        {
            throw new ArgumentNullException("Error: No message to incrypt");
        }


        byte[] ciphertext;
        byte[] plaintext_Bytes = Encoding.Unicode.GetBytes(plaintext);
        _rsa.FromXmlString(publicKey);

        ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
        return Convert.ToBase64String(ciphertext);
    }

我看不到我要去哪里錯了。 我已確保密鑰正確。 我在構造函數中使用此行提取的公共代碼:_publicKey = _rsa.ToXmlString(false); 此公共密鑰顯示在我創建的表單上。 私人我使用“ true”代替false。

有任何想法嗎?

密文不太可能是真正的UTF-16編碼文本。 假設加密端具有以下內容:

string encryptedText = Encoding.Unicode.GetString(encryptedBytes);

您基本上已經丟失了數據。 加密的結果不是文本-​​它是任意二進制數據。 如果出於某種運輸原因要將其轉換為文本,則應使用Base64,例如

string base64EncryptedText = Convert.ToBase64String(encryptedBytes);

然后使用Convert.FromBase64String恢復准備解密的原始加密二進制數據。

這是Jon建議的使用base-64字符串的RsaLibrary類:

    class RsaLibrary
    {
        //initializing the RSA object taking the option of a 1024 key size
        readonly RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider(1024);
        readonly string _privateKey;
        readonly string _publicKey;

        public RsaLibrary()
        {
            _privateKey = _rsa.ToXmlString(true);
            _publicKey = _rsa.ToXmlString(false);
        }

        public string Decrypt(string ciphertext, string privateKey_ = null)
        {
            if (ciphertext.Length <= 0) throw new ArgumentNullException("ciphertext");

            string key = String.IsNullOrEmpty(privateKey_) ? _privateKey : privateKey_;
            return DecryptToBytes(ciphertext, key);
        }
        private string DecryptToBytes(string ciphertext, string privateKey)
        {
            if (String.IsNullOrEmpty(privateKey)) throw new ArgumentNullException("privateKey");

            byte[] ciphertext_Bytes = Convert.FromBase64String(ciphertext);
            _rsa.FromXmlString(privateKey);

            byte[] plaintext = _rsa.Decrypt(ciphertext_Bytes, false);
            return Encoding.Unicode.GetString(plaintext);
        }

        public string Encrypt(string plaintext, string publicKey_ = null)
        {
            if (plaintext.Length <= 0) throw new ArgumentNullException("plaintext");

            string key = String.IsNullOrEmpty(publicKey_) ? _publicKey : publicKey_;
            return EncryptToBytes(plaintext, key);
        }
        private string EncryptToBytes(string plaintext, string publicKey)
        {
            if (String.IsNullOrEmpty(publicKey)) throw new ArgumentNullException("publicKey");

            byte[] plaintext_Bytes = Encoding.Unicode.GetBytes(plaintext);
            _rsa.FromXmlString(publicKey);

            byte[] ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
            return Convert.ToBase64String(ciphertext);
        }
    }

而且,您確實應該將SecureString用於純文本。

class RsaLibrary2
{
    //initializing the RSA object taking the option of a 1024 key size
    readonly RSACryptoServiceProvider _rsa = new RSACryptoServiceProvider(1024);
    readonly string _privateKey;
    readonly string _publicKey;

    public RsaLibrary2()
    {
        _privateKey = _rsa.ToXmlString(true);
        _publicKey = _rsa.ToXmlString(false);
    }

    public SecureString Decrypt(string ciphertext, string privateKey_ = null)
    {
        if (ciphertext.Length <= 0) throw new ArgumentNullException("ciphertext");

        string key = String.IsNullOrEmpty(privateKey_) ? _privateKey : privateKey_;
        return DecryptToBytes(ciphertext, key);
    }
    private SecureString DecryptToBytes(string ciphertext, string privateKey)
    {
        if (String.IsNullOrEmpty(privateKey)) throw new ArgumentNullException("privateKey");

        byte[] ciphertext_Bytes = Convert.FromBase64String(ciphertext);
        _rsa.FromXmlString(privateKey);

        byte[] plainbytes = _rsa.Decrypt(ciphertext_Bytes, false);
        char[] plain = Encoding.Unicode.GetChars(plainbytes);
        var retval = new SecureString();
        FromArray(retval, ref plain);
        return retval;
    }

    public string Encrypt(SecureString plaintext, string publicKey_ = null)
    {
        if (plaintext == null) throw new ArgumentNullException("plaintext");
        if (plaintext.Length <= 0) throw new ArgumentOutOfRangeException("plaintext");

        string key = String.IsNullOrEmpty(publicKey_) ? _publicKey : publicKey_;
        return EncryptToBytes(plaintext, key);
    }
    private string EncryptToBytes(SecureString plaintext, string publicKey)
    {
        if (String.IsNullOrEmpty(publicKey)) throw new ArgumentNullException("publicKey");

        byte[] plaintext_Bytes = SecureStringToByteArray(plaintext);
        _rsa.FromXmlString(publicKey);

        byte[] ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
        return Convert.ToBase64String(ciphertext);
    }

    // YIKES! Copies the SecureString to a byte[] array; use with caution!
    static byte[] SecureStringToByteArray(SecureString secureString)
    {
        if (secureString == null) throw new ArgumentNullException(/*MSG0*/"secureString");

        // copy plaintext from unmanaged memory into managed byte[]s
        int stringSize = secureString.Length * sizeof(char); // http://blogs.msdn.com/shawnfa/archive/2005/02/25/380592.aspx
        byte[] bytes = new byte[stringSize];
        IntPtr pString = Marshal.SecureStringToGlobalAllocUnicode(secureString); // do this last to minimize the availability of "pString"
        try // free "pString" even if Copy() throws
        {
            Marshal.Copy(pString, bytes, 0, stringSize);
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(pString); // clear plaintext from unmanaged memory ASAP
        }

        return bytes;
    }

    static void ArrayZero<T>(ref T[] array)
    {
        Array.Clear(array, 0, array.Length); // clear from managed memory
        Array.Resize(ref array, 0); // set Length=0 ASAP; even the length can be valuable
        array = null; // just to "help" callers know there's nothing in the array anymore
    }

    static void FromArray(SecureString secureString, ref char[] array)
    {
        try // clear "array" even if AppendChar() throws
        {
            for (int i = 0; i < array.Length; i++)
            {
                secureString.AppendChar(array[i]);
                array[i] = default(char); // clear plaintext ASAP
            }
        }
        finally
        {
            ArrayZero(ref array); // clear plaintext from managed memory
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM