メインコンテンツまでスキップ

ヴィジュネル暗号

ヴィジュネル暗号とは

ヴィジュネル暗号多表式暗号の一種であり、ヴィジュネル表(下図)と言う表を使って暗号化を行う暗号方式。 ヴィジュネル表

赤色エリアの文字が平文を表し、青色エリアの文字が鍵に対応している。緑色エリアの文字が暗号化後の文字を表している。

例えば、APPLEを暗号化したいとする。RINGOを鍵とした場合、平文のAと鍵のRで合致するRが暗号化後の文字となる。

ヴィジュネル暗号1

続けて、PI, PN, LG, EOで暗号文字を導出する。

ヴィジュネル暗号2

平文APPLEと鍵RINGOで暗号化した結果、暗号文RXCRSが得ることができる。

プログラム

vigenere-cipher.py
import random
def generate_key(size: int):
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result = []
for _ in range(size):
result.append(base[random.randint(0, 26)])
return "".join(result)


def vigenere_cipher(input_text: str, key: str, direction: str = "encryption"):
input_text = input_text.upper()
key = key.upper()
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
mod = len(key)

result = []
dx = 1
if direction == "decryption":
dx = -1
for i in range(len(input_text)):
result.append(
base[(dx * base.find(key[i % mod]) + base.find(input_text[i])) % 26])
return "".join(result)

動作

ライブエディター
function SimpleSubstitutionCipher(props) {
  // 暗号化 or 復号化する文字列
  const inputText = "APPLE";

  // encryption or decryption
  const direction = "encryption";

  // 手動で鍵を指定する
  const defaultKey = "RINGO";

  // defaultKeyがnullの場合に作成する鍵の長さ
  const size = 3;

  // 以下は特に変更しなくて良い
  const base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  // 指定範囲内からランダムで数字を生成 [min, max]
  function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min) + min);
  }

  function generateKey(size) {
    let result = "";
    for (let i = 0; i < size; ++i) {
      result += base[getRandomInt(0, 26)];
    }
    return result;
  }

  function vigenereCipher(inputText, key, direction = "encryption") {
    inputText = inputText.toUpperCase();
    key = key.toUpperCase();
    const mod = key.length;
    let dx = 1;
    if (direction == "decryption") dx = -1;
    result = "";
    for (let i = 0; i < inputText.length; ++i) {
      result +=
        base[
          (dx * base.indexOf(key[i % mod]) + base.indexOf(inputText[i]) + 26) %
            26
        ];
    }
    return result;
  }

  // React
  const [key, setKey] = useState(undefined);
  const [cipher, setCipher] = useState(undefined);

  // tableが生成された後に暗号化を行う
  useEffect(() => {
    if (!key) return;
    const cipher = vigenereCipher(inputText, key, "encryption");
    setCipher(cipher);
  }, [key]);
  // 読み込み時に一度だけ呼び出す
  useEffect(() => {
    // 読み込みできてから呼びだす
    if (!defaultKey) {
      setKey(generateKey(size));
    } else {
      setKey(defaultKey);
    }
  }, []);
  return (
    <>
      <div
        style={{
          display: "flex",
          flexDirection: "row",
          flexWrap: "nowrap",
          alignItems: "flex-start",
          justifyContent: "space-evenly",
        }}
      >
        <div>
          <h3>元の文字列</h3>
          <p>{inputText}</p>
        </div>
        {key === undefined || cipher === undefined ? (
          /* 変換テーブルを生成してるかつ暗号化済みであれば表示 */ <></>
        ) : (
          <>
            <span
              className="mrel"
              style={{ padding: "5px", margin: "auto 0px" }}
            >

            </span>
            <div>
              <h3>暗号化</h3>
              <p>{cipher}</p>
            </div>
            <span
              className="mrel"
              style={{ padding: "5px", margin: "auto 0px" }}
            >

            </span>
            <div>
              <h3>復号化</h3>
              <p style={{ padding: "1px", margin: "2px" }}>
                {vigenereCipher(cipher, key, "decryption")}
              </p>
            </div>
          </>
        )}
      </div>
      <h3></h3>
      {key === undefined || cipher === undefined ? (
        /* 変換テーブルを生成してるかつ暗号化済みであれば表示 */ <></>
      ) : (
        <p>{key}</p>
      )}
    </>
  );
}
結果
Loading...