65.9K
CodeProject 正在变化。 阅读更多。
Home

使用加密函数进行128位密钥加密/解密

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.24/5 (7投票s)

2019年5月24日

CPOL

3分钟阅读

viewsIcon

22723

downloadIcon

150

将图像转换为字节, 使用 128 位密钥加密, 然后使用同一密钥解密, 再将字节转换回图像

引言

本文解释了两件事

  1. TripleDESCryptoServiceProvider() 加密函数的工作原理
  2. 图像与字节之间的转换,反之亦然

密码学是一个希腊词,意思是隐藏。计算机中的密码学意味着授权人员之间的安全和受保护的通信。它最初被军队用来交换机密信息,早些时候,国王用它来发送秘密信息。现代密码学旨在实现以下目标

  • 机密性
  • 完整性
    • 身份验证
    • 不可否认性
  • 可用性

密码学有三种类型

  • 对称密码学

    单密钥/秘密密钥/私钥 - 使用相同的密钥和算法进行加密/解密

  • 非对称密码学

    公钥和私钥/两个密钥,一个用于加密,另一个用于按任意顺序解密

  • 混合密码学

    结合了以上两者,采用两者的优点,并舍弃了两者的缺点

现在我们将通过一个将图像编码为密文的例子来理解对称密码学,使用128位密钥并将其发送给其他用户,然后使用相同的密钥进行解码。

理解代码

首先,我们使用任何字符、数字或符号生成一个密钥,将其验证为128位并转换为二进制。

if (keyBoxTxt.Text.Length == 16)
            {
                keyBinTxt.Text = StringToBinary(keyBoxTxt.Text);
                uploadImg.Enabled = true;
            }
            else
                MessageBox.Show("Key size is not appropriate, Please enter 16 characters!"); 

长度 = 16 表示 16 个字符或符号,每个字符或符号 8 位,总共 128 位。

这里使用了一个 StringToBinary() 函数,它将字符串转换为二进制。

public static string StringToBinary(string data)
        {
            StringBuilder sb = new StringBuilder();

            foreach (char c in data.ToCharArray())
            {
                sb.Append(Convert.ToString(c, 2).PadLeft(8, '0'));
            }
            return sb.ToString();
        }

现在使用浏览按钮打开图像

// open file dialog   
            OpenFileDialog open = new OpenFileDialog();
            // image filters  
            open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp)|*.jpg; *.jpeg; *.gif; *.bmp";
            if (open.ShowDialog() == DialogResult.OK)
            {
                // display image in picture box  
                pictureBox1.Image = new Bitmap(open.FileName);
                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
                imgpath = open.FileName;
                encryptBtn.Enabled = true;
            }

FileDialog 读取图像并在图片框中显示。

现在真正的工作开始了,我们开始使用 TripleDESCryptoServiceProvider() 函数

//Convert image to byte
byte[] bytimg = (Byte[])new ImageConverter().ConvertTo(pictureBox1.Image, typeof(Byte[]));  
//Writes to textbox
beforeEnc();
//wrapper for TripleDESCryptoServiceProvider
TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.KeySize = 128;
tripleDES.Key = UTF8Encoding.UTF8.GetBytes(keyBoxTxt.Text);
tripleDES.Mode = CipherMode.ECB;
tripleDES.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tripleDES.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(bytimg, 0, bytimg.Length);
tripleDES.Clear();
afterEncTxt.Text = Convert.ToBase64String(resultArray, 0, resultArray.Length);

首先,使用 imageconverter 将图像转换为字节,然后使用自制函数 beforeEnc() 将字节转换为二进制字符串,并显示在多行文本框中。

现在,为 TripleDESCryptoServiceProvider() 函数创建一个包装对象,即 tripleDES然后,正如我们定义的,我们的密钥大小应该正好是 128 位,因此也为 tripleDES 设置了。将密钥转换为字节后,选择密码算法 ECB。

电子密码本 (ECB)

它是一种用于创建块密码的运算模式,这意味着将使用块密码加密字节或位。密码是使用任何算法加密的纯文本。密码有两种类型

  1. 流密码
  2. 块密码

ECB 是一种块密码算法,它会将重复的纯文本转换为相同的重复密文。 意思是如果 "a" 意思是 0011,那么每次 "a" 出现时,它都会将其编码为 0011。 所以它不适合小块大小,这就是我们使用 128 位块的原因。

公钥密码学标准 (PKCS) # 7

这些是 RSA Data Security Inc. 的公钥加密的事实标准格式。它处理数字签名和证书。 PKCS #7 使用证书的公钥加密消息,并且仅使用该证书的私钥解密。 PKCS #7 的一些扩展功能包括

  • 它可以同时使用多个证书进行加密
  • 递归,意味着一个数字信封包裹在另一个数字信封中,依此类推
  • 加密消息和数字签名的时间戳
  • 计数器签名和用户定义的特征

然后 ICryptoTransform 定义了基本的加密操作,并将加密消息转换为字节数组,并将其分配给文本框以比较加密前后的消息。

现在加密完成!

轮到解密消息了。

由于密钥和加密消息一起发送,因此这里是代码

byte[] inputArray = Convert.FromBase64String(afterEncTxt.Text);
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            tripleDES.KeySize = 128;
            tripleDES.Key = UTF8Encoding.UTF8.GetBytes(binKeyTxt.Text);
            tripleDES.Mode = CipherMode.ECB;
            tripleDES.Padding = PaddingMode.PKCS7;
            ICryptoTransform cTransform = tripleDES.CreateDecryptor();
            byte[] resultArray = 
                   cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
            tripleDES.Clear();
            using (var ms = new MemoryStream(resultArray))
            {
                pictureBox1.Image = Image.FromStream(ms);
            }

使用相同的代码解密消息,原始图像将在 bytes[] 中生成。 这次,我们使用 ICryptoTransform 来创建 Decryptor()。 然后,使用内存流将字节数组转换为图像。

请记住一件事,密码模式和填充模式在双方(加密/解密)应始终相同。

历史

  • 2019年5月24日:初始版本
© . All rights reserved.