原理介绍
在凯撒密码中,每一个字母通过一定的偏移量(即密钥K)变成另外一个字母,而维吉尼亚密码就是由多个偏移量不同的凯撒密码组成,属于多表密码的一种。在一段时间里它曾被称为“不可破译的密码”。.
维吉尼亚密码在加密和解密时,需要一个表格进行对照。表格一般为26*26的矩阵,行和列都是由26个英文字母组成。加密时,明文字母作为列,密钥字母作为行,所对应坐标上的字母即为对应的密文字母。

可以用上述表格直接查找对应的密文,也可通过取模计算的方式。用0-25代替字母A-Z,C表示密文,P表示明文,K表示密钥,维吉尼亚加密算法可表示为:

密文可表示为:

举例说明,假设明文为“I AM A CHINESE”,密钥为“CHINA”,那么密文就是“L HU N CJPVRSG”。具体过程如下表:

3.2 C#代码
// Vigenere Cipher(维吉尼亚密码)
public sealed class Vigenere
{
    // 加密
    public static string VigenereEncrypt(string plaintext, string key)
    {
        string ciphertext = "";
 
        byte[] origin = Encoding.ASCII.GetBytes(plaintext.ToUpper());
        byte[] keys = Encoding.ASCII.GetBytes(key.ToUpper());
        int length = origin.Length;
        int d = keys.Length;
        for (int i = 0; i < length; i++)
        {
            int asciiCode = (int)origin[i];
 
            // 加密(移位)
            asciiCode = asciiCode + (int)keys[i % d] - (int)'A';
            if (asciiCode > (int)'Z')
            {
                asciiCode -= 26;
            }
 
            byte[] byteArray = new byte[] { (byte)asciiCode };
 
            // 将偏移后的数据转为字符
            ASCIIEncoding asciiEncoding = new ASCIIEncoding();
            string strCharacter = asciiEncoding.GetString(byteArray);
 
            ciphertext += strCharacter;
        }
        return ciphertext;
    }
 
    // 解密
    public static string VigenereDecrypt(string ciphertext, string key)
    {
        string plaintext = "";
 
        byte[] origin = Encoding.ASCII.GetBytes(ciphertext.ToUpper());
        byte[] keys = Encoding.ASCII.GetBytes(key.ToUpper());
        int length = origin.Length;
        int d = keys.Length;
        for (int i = 0; i < length; i++)
        {
            int asciiCode = (int)origin[i];
 
            // 解密(移位)
            asciiCode = asciiCode - (int)keys[i % d] + (int)'A';
            if (asciiCode < (int)'A')
            {
                asciiCode += 26;
            }
 
            byte[] byteArray = new byte[] { (byte)asciiCode };
 
            // 将偏移后的数据转为字符
            ASCIIEncoding asciiEncoding = new ASCIIEncoding();
            string strCharacter = asciiEncoding.GetString(byteArray);
 
            plaintext += strCharacter;
        }
        return plaintext;
    }
}