维吉尼亚密码 C# 实现与解析

维吉尼亚密码(Vigenère cipher)是一种经典的多表替换加密算法,通过使用密钥和维吉尼亚方阵(Vigenère square)对明文进行加密和解密。本文将详细介绍维吉尼亚密码的原理,并提供一个完整的 C# Windows Forms 实现。

1. 维吉尼亚密码原理

维吉尼亚密码基于凯撒密码,但使用一个密钥来动态选择加密表。其核心是维吉尼亚方阵,这是一个 26×26 的字母表矩阵:

  • 第一行为 A-Z(明文行)
  • 第一列为 A-Z(密钥行)
  • 每个单元格的字母由“明文列字母”与“密钥行字母”相加(模26)得到

加密时,将明文和密钥转换为数字(A=0, B=1, ..., Z=25),然后通过维吉尼亚方阵查找对应的密文字母。解密则是反向查找过程。

2. C# 实现代码

以下是一个完整的 Windows Forms 应用程序,实现了维吉尼亚密码的加密和解密功能:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Vigenere
{
    public partial class Form1 : Form
    {
        // 维吉尼亚方阵(26×26)
        private string[,] matrix = new string[26, 26];
        private ASCIIEncoding ascii = new ASCIIEncoding();

        // 密钥、密文、明文
        private string key;
        private string code;
        private string text;

        public Form1()
        {
            InitializeComponent();
            
            #region 生成维吉尼亚方阵
            for (int i = 0; i < 26; i++)
            {
                for (int j = 0; j < 26; j++)
                {
                    int number = 65 + i + j;
                    if (number > 90)
                    {
                        number -= 26;
                    }
                    byte[] bt = new byte[] { (byte)number };
                    matrix[i, j] = ascii.GetString(bt);
                }
            }
            #endregion
        }

        // 加密按钮点击事件
        private void button1_Click(object sender, EventArgs e)
        {
            key = this.txtKey.Text.ToString().ToUpper();
            code = "";
            text = this.txtText.Text.ToString().ToUpper();
            List<int> keyNum = new List<int>();

            // 将密钥转换为数字序列(A=0, B=1, ..., Z=25)
            for (int i = 0; i < key.Length; i++)
            {
                string str = key.Substring(i, 1);
                keyNum.Add((int)ascii.GetBytes(str)[0] - 65);
            }

            int index = -1;
            for (int i = 0; i < this.text.Length; i++)
            {
                // 保留空格
                if (this.text.Substring(i, 1).ToString() == " ")
                {
                    code += " ";
                    continue;
                }
                
                index++;
                // 加密:matrix[密钥数字, 明文字母数字]
                code += matrix[keyNum[index % key.Length], 
                              (int)ascii.GetBytes(this.text.Substring(i, 1))[0] - 65];
            }

            this.txtCode.Text = code.ToString();
        }

        // 解密按钮点击事件
        private void button2_Click(object sender, EventArgs e)
        {
            key = this.txtKey.Text.ToString().ToUpper();
            code = this.txtCode.Text.ToString().ToUpper();
            text = "";
            List<int> keyNum = new List<int>();

            // 将密钥转换为数字序列
            for (int i = 0; i < key.Length; i++)
            {
                string str = key.Substring(i, 1);
                keyNum.Add((int)ascii.GetBytes(str)[0] - 65);
            }

            int index = -1;
            for (int i = 0; i < this.code.Length; i++)
            {
                // 保留空格
                if (this.code.Substring(i, 1).ToString() == " ")
                {
                    text += " ";
                    continue;
                }
                
                index++;
                // 解密:在密钥对应的行中查找密文字母
                for (int j = 0; j < 26; j++)
                {
                    if (this.code.Substring(i, 1).ToString() == matrix[keyNum[index % key.Length], j])
                    {
                        byte[] bt = new byte[] { (byte)(j + 65) };
                        text += ascii.GetString(bt);
                        break;
                    }
                }
            }

            this.txtText.Text = text.ToString();
        }
    }
}

3. 代码解析

3.1 维吉尼亚方阵生成

在窗体构造函数中,我们生成一个 26×26 的维吉尼亚方阵:

  • 外层循环 i 表示密钥字母索引(0-25)
  • 内层循环 j 表示明文字母索引(0-25)
  • 每个单元格的字母 ASCII 码为 65 + i + j(A 的 ASCII 码为 65)
  • 如果计算结果超过 90(Z 的 ASCII 码),则减去 26 回到 A-Z 范围
3.2 加密过程
  1. 将密钥和明文转换为大写
  2. 将密钥字母转换为数字(A=0, B=1, ..., Z=25)
  3. 遍历明文字符:
    • 如果是空格,直接保留
    • 否则,使用公式 matrix[密钥数字, 明文字母数字] 查找密文字母
    • 密钥循环使用(index % key.Length
3.3 解密过程
  1. 将密钥和密文转换为大写
  2. 将密钥字母转换为数字
  3. 遍历密文字符:
    • 如果是空格,直接保留
    • 否则,在密钥对应的行中查找密文字母的位置
    • 找到后,将列索引转换为明文字母

4. 使用示例

假设:

  • 密钥:KEY
  • 明文:HELLO WORLD

加密过程:

  1. 密钥 KEY 转换为数字:K=10, E=4, Y=24
  2. 明文 HELLO WORLD 转换为数字:H=7, E=4, L=11, L=11, O=14, W=22, O=14, R=17, L=11, D=3
  3. 加密计算:
    • H(7) + K(10) = R(17)
    • E(4) + E(4) = I(8)
    • L(11) + Y(24) = J(9)(35-26=9)
    • ...以此类推
  4. 得到密文:RIJVS GYJVN

5. 程序界面说明

程序包含以下控件:

  • txtKey:密钥输入框
  • txtText:明文输入框
  • txtCode:密文显示框
  • button1:加密按钮
  • button2:解密按钮

6. 扩展与优化建议

  • 支持小写字母:当前实现只处理大写字母,可扩展支持小写
  • 支持更多字符:可扩展支持数字、标点符号等
  • 性能优化:解密时的查找操作可优化为直接计算
  • 错误处理:添加输入验证和异常处理
  • 文件加密:扩展为文件加密/解密功能

7. 参考资料

对于维吉尼亚方阵及运用维吉尼亚方阵的加密与解密,可参考维吉尼亚密码_百度百科

程序运行画面结果如下:

(此处可插入程序运行截图)

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐