C# RSA 分段加解密


 

RSA加解密:

1024位的證書,加密時最大支持117個字節,解密時為128;
2048位的證書,加密時最大支持245個字節,解密時為256。

加密時支持的最大字節數:證書位數/8 -11(比如:2048位的證書,支持的最大加密字節數:2048/8 - 11 = 245)

.NET中的RSA加密算法為了提高安全性,在待加密數據前要添加一些隨機數,因此,使用.NET中的RSA加密算法一次最多加密117字節數據(多於117字節需要拆分成多段分別加密再連接起來),經過加密后得到一個長度為128字節的加密數據

RSA實際可加密的明文長度最大也是1024bits,但問題就來了:如果小於這個長度怎么辦?就需要進行padding,因為如果沒有padding,用戶無法區分解密后內容的真實長度,字符串之類的內容問題還不大,以0作為結束符,但對二進制數據就很難理解,因為不確定后面的0是內容還是內容結束符。只要用到padding,那么就要占用實際的明文長度,於是才有117字節的說法。我們一般使用的padding標准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建議的padding就占用了11個字節。如果大於這個長度怎么辦?很多算法的padding往往是在后邊的,但PKCS的padding則是在前面的,此為有意設計,有意的把第一個字節置0以確保m的值小於n。這樣,128字節(1024bits)-減去11字節正好是117字節,但對於RSA加密來講,padding也是參與加密的,所以,依然按照1024bits去理解,但實際的明文只有117字節了。

C#代碼實現:

 RSA 填充模式:PKCS1PADDING
分片大小: 加密244、解密256

 

internal static string GetEncryptedMsg(string xml)
{
    byte[] encryptedData;
    using (var rsa = GetPublicKey(Configs.PublicKeyFilePath))
    {
        var plainData = Encoding.UTF8.GetBytes(xml);
        using (var plaiStream = new MemoryStream(plainData))
        {
            using (var crypStream = new MemoryStream())
            {
                var offSet = 0;
                var inputLen = plainData.Length;
                for (var i = 0; inputLen - offSet > 0; offSet = i*244)
                {
                    if (inputLen - offSet > 244)
                    {
                        var buffer = new Byte[244];
                        plaiStream.Read(buffer, 0, 244);
                        var cryptograph = rsa.Encrypt(buffer, false);
                        crypStream.Write(cryptograph, 0, cryptograph.Length);
                    }
                    else
                    {
                        var buffer = new Byte[inputLen - offSet];
                        plaiStream.Read(buffer, 0, inputLen - offSet);
                        var cryptograph = rsa.Encrypt(buffer, false);
                        crypStream.Write(cryptograph, 0, cryptograph.Length);
                    }
                    ++i;
                }
                crypStream.Position = 0;
                encryptedData = crypStream.ToBytes();
            }
        }
    }
    return BitConverter.ToString(encryptedData).Replace("-", string.Empty);
}

internal static byte[] GetDecryptedMsg(byte[] encryptedBytes)
{
    using (var rsa = GetPrivateKey(Configs.PrivateKeyFilePath, Configs.PrivateKeyPasswd))
    {
        byte[] decryptedData;
        using (var plaiStream = new MemoryStream(encryptedBytes))
        {
            using (var decrypStream = new MemoryStream())
            {
                var offSet = 0;
                var inputLen = encryptedBytes.Length;
                for (var i = 0; inputLen - offSet > 0; offSet = i * 256)
                {
                    if (inputLen - offSet > 256)
                    {
                        var buffer = new Byte[256];
                        plaiStream.Read(buffer, 0, 256);
                        var decrypData = rsa.Decrypt(buffer, false);
                        decrypStream.Write(decrypData, 0, decrypData.Length);
                    }
                    else
                    {
                        var buffer = new Byte[inputLen - offSet];
                        plaiStream.Read(buffer, 0, inputLen - offSet);
                        var decrypData = rsa.Decrypt(buffer, false);
                        decrypStream.Write(decrypData, 0, decrypData.Length);
                    }
                    ++i;
                }
                decrypStream.Position = 0;
                decryptedData = decrypStream.ToBytes();
            }
        }
        return decryptedData;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM