2022年4月16日 星期六

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(四)

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(四)

2022-04-16

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(一)
https://shaurong.blogspot.com/2022/04/aspnetfortify-sca-ciphermodecbc-weak.html

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(二)
https://shaurong.blogspot.com/2022/04/aspnetaspnetfortify-sca-ciphermodecbc.html

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(三)
https://shaurong.blogspot.com/2022/04/aspnetfortify-sca-ciphermodecbc-weak_16.html

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C#

參考下面這篇進行修改

RijndaelManaged 類別 (System.Security.Cryptography) | Microsoft Docs
https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.rijndaelmanaged?view=net-6.0

Default2.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default2.aspx.cs" 
    Inherits="WebApplication1.Default2" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        key:<asp:TextBox ID="TextBox1" runat="server" Width="350px"></asp:TextBox><br />
        iv:<asp:TextBox ID="TextBox2" runat="server" Width="350px"></asp:TextBox><br />
        原文:<asp:TextBox ID="TextBox3" runat="server" Width="350px"></asp:TextBox><br />
        加密後:<asp:TextBox ID="TextBox4" runat="server" Width="350px"></asp:TextBox><br />
        解密後:<asp:TextBox ID="TextBox5" runat="server" Width="350px"></asp:TextBox><br />
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click1" /><br />
        <asp:Label ID="Label_MSG" runat="server"></asp:Label>
    </form>
</body>
</html>

Default2.aspx.cs


using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace WebApplication1
{
    public partial class Default2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            TextBox1.Text = "1234567812345678"; // key, iv
            TextBox2.Text = "12345678"; // key, iv 長度必須是 8
            TextBox3.Text = "Test String";
        }

        // https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography.rijndaelmanaged?view=net-6.0
        protected void Button1_Click1(object sender, EventArgs e)
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the RijndaelManaged
                // class.  This generates a new key and initialization
                // vector (IV).
                using (RijndaelManaged rijAlg = new RijndaelManaged())
                {
                    // 亂碼,不喜歡,保存不方便
                    //rijAlg.GenerateKey();
                    //rijAlg.GenerateIV();
                    //TextBox1.Text = System.Text.Encoding.Unicode.GetString(rijAlg.Key);
                    //TextBox2.Text = System.Text.Encoding.Unicode.GetString(rijAlg.IV);
                    //TextBox5.Text = TextBox2.Text.Length.ToString();
                        
                    rijAlg.Key = System.Text.Encoding.Unicode.GetBytes(TextBox1.Text);

                    //指定的初始化向量 (IV) 不符合此演算法的區塊大小。 
                    // Rijndael IV size doesn't match block size
                    //byte[] iv = new byte[128];
                    //string ivStr = "";
                    //for (int i = 0; i < 16; i++)
                    //    ivStr += "12345678";
                    //TextBox2.Text = ivStr;
                    rijAlg.IV = System.Text.Encoding.Unicode.GetBytes(TextBox2.Text);

                    // Encrypt the string to an array of bytes.
                    byte[] encrypted = EncryptStringToBytes(original, rijAlg.Key, rijAlg.IV);

                    // Decrypt the bytes to a string.
                    string roundtrip = DecryptStringFromBytes(encrypted, rijAlg.Key, rijAlg.IV);

                    //Display the original data and the decrypted data.
                    //Console.WriteLine("Original:   {0}", original);
                    //Console.WriteLine("Round Trip: {0}", roundtrip);
                    TextBox4.Text = original;
                    TextBox5.Text = roundtrip;
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine("Error: {0}", e.Message);
                Label_MSG.Text = "不明錯誤。";
                if (ex!=null)
                    Label_MSG.Text = ex.Message;
            }
        }

        static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;
            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                //rijAlg.Mode = CipherMode.ECB; // 微軟建議別用;可執行
                //rijAlg.Mode = CipherMode.CBC; // 預設,Fortify SCA 認為不安全
                rijAlg.Mode = CipherMode.CFB; // Fortify SCA 認為安全;可執行
                //rijAlg.Mode = CipherMode.OFB; // Fortify SCA 認為安全;System.Security.Cryptography.CryptographicException: '指定的 Cipher 模式對此演算法而言是無效的。'
                                                  // 經查,RijndaelManaged目前不支援OFB模式。
                //rijAlg.Mode = CipherMode.CTS; // Fortify SCA 認為安全;System.Security.Cryptography.CryptographicException: '指定的 Cipher 模式對此演算法而言是無效的。'
                //rijAlg.Mode = CipherMode.CTR; // Fortify SCA 建議,但沒有這種模式

                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }

        static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;
                rijAlg.Mode = CipherMode.CFB;

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }

    }
}

實際測試

解密後字串尾不會再多了 �����,正常了。

(完)

相關

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(一)
https://shaurong.blogspot.com/2022/04/aspnetfortify-sca-ciphermodecbc-weak.html

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(二)
https://shaurong.blogspot.com/2022/04/aspnetaspnetfortify-sca-ciphermodecbc.html

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(三)
https://shaurong.blogspot.com/2022/04/aspnetfortify-sca-ciphermodecbc-weak_16.html

[研究][ASP.NET]Fortify SCA 報告 CipherMode.CBC 有 Weak Encryption: Insecure Mode of Operation 問題之解決(四)
https://shaurong.blogspot.com/2022/04/aspnetfortify-sca-ciphermodecbc-weak_59.html

[研究] [C#] AES-256-CBC 加密字串、解密字串
http://shaurong.blogspot.com/2016/11/c-aes-256-cbc_22.html

System.Security.Cryptography 命名空間 | Microsoft Docs
https://docs.microsoft.com/zh-tw/dotnet/api/system.security.cryptography?view=net-6.0



沒有留言:

張貼留言