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

スキュタレー暗号

スキュタレー暗号とは

筒や棒などに紙を巻きつけ、筒の伸びる方向に平文を記述し、余白部分に任意の文字で埋め尽くす。これにより、紙を筒から取り外した際に平文で書いた文字はバラバラに配置されているため、暗号化される。 同じ筒に同じ様に巻きつけることで文字を復元することができる。このような暗号化方式をスキュタレー暗号という。

イメージ図

イメージ図

図のように筒に合わせて文字を書くことで紙を筒から外すとAAKL PXMP PSXQ LWRJ EEAEとなる。(わかりやすいように区切っている。区切りの始めの文字のみを取り出すとAPPLEとなる。)

プログラム

scythia-cipher.py
import random

def scythia_cipher_to_encrypt(input_text: str, width: int = 3):
input_text = input_text.upper()
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
encrypt_box = [[] for _ in range(len(input_text))]
for i in range(len(input_text)):
encrypt_box[i] = input_text[i]
for _ in range(1, width):
encrypt_box[i] += base[random.randint(0, 25)]
rotate_count = random.randint(0, width)
for i in range(len(encrypt_box)):
encrypt_box[i] = encrypt_box[i][rotate_count:] + \
encrypt_box[i][:rotate_count]
return "".join(encrypt_box)


def scythia_cipher_to_decrypt(input_text: str, width: int = 3):
decrypt_box = [[] for _ in range(width)]
for i in range(len(input_text)):
decrypt_box[i % width].append(input_text[i])
for i in range(width):
decrypt_box[i] = "".join(decrypt_box[i])
return decrypt_box

動作

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

  // 文字列を格納する面の個数
  const width = 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 ScythiaCipherToEncrypt(inputText, width = 3) {
    inputText = inputText.toUpperCase();
    let encryptBox = [];
    for (let i = 0; i < inputText.length; ++i) {
      encryptBox.push(inputText[i]);
      for (let j = 1; j < width; ++j) {
        encryptBox[i] += base[getRandomInt(0, 26)];
      }
    }
    let retString = "";
    let rotateCount = getRandomInt(0, width);
    for (let i = 0; i < inputText.length; ++i) {
      retString +=
        encryptBox[i].substring(rotateCount) +
        encryptBox[i].substring(0, rotateCount);
    }
    return retString;
  }
  function ScythiaCipherToDecrypt(inputText, width = 3) {
    let decryptBox = new Array(width).fill("");
    for (let i = 0; i < inputText.length; ++i) {
      decryptBox[i % width] += inputText[i];
    }
    return decryptBox;
  }
  let cipher = ScythiaCipherToEncrypt(inputText, width);
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "row",
        flexWrap: "nowrap",
        alignItems: "flex-start",
        justifyContent: "space-evenly",
      }}
    >
      <div>
        <h3>元の文字列</h3>
        <p>{inputText}</p>
      </div>
      <span className="mrel" style={{ padding: "5px", margin: "auto 0px" }}>

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

      </span>
      <div>
        <h3>復号化</h3>
        {ScythiaCipherToDecrypt(cipher, width).map((data) => (
          <p style={{ padding: "1px", margin: "2px" }}>{data}</p>
        ))}
      </div>
    </div>
  );
}
結果
Loading...