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

転置式暗号

転置式暗号とは

平文の順番を入れ替える暗号方式を転置式暗号という。 平文を一定のブロックに分けて、順番を入れ替えていく。ブロックの長さを n とすると平文の文字の数が n の場合数出ない場合は綺麗にブロック分けができない。余ったブロックには何らかの文字を入れパディングする方法やそのままにして順番を入れ替えない方法等がある。 パディングする場合は単純にパティングしてしまうとパティング文字以外の移動位置がバレてしまう可能性があるので注意が必要である。

プログラム

transposition-cipher.py
import random
def generate_transposition_table(size: int):
table = [i for i in range(size)]
random.shuffle(table)
return table


def transposition_cipher(input_text: str, transposition_table: list[int], direction: str = "encryption"):
input_text = input_text.upper()
result = []
size = len(transposition_table)
if direction == "decryption":
temp_table = [0] * size
for i in range(size):
temp_table[transposition_table[i]] = i
transposition_table = temp_table

for i in range(0, len(input_text) - size+1, size):
temp_text = ""
for j in range(size):
temp_text += input_text[i + transposition_table[j]]
result.append(temp_text)
if len(input_text) % size != 0:
result.append(
input_text[-(len(input_text) % size):]
)
return "".join(result)

動作

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

  // 転置するブロック数
  const size = 3;

  // 暗号化 or 復号化
  const direction = "encryption";

  //Fisher-Yatesシャッフルアルゴリズム
  function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; --i) {
      const j = Math.floor(Math.random() * (i + 1));
      // 要素の交換
      [array[i], array[j]] = [array[j], array[i]];
    }
  }

  function generateTranspositionTable(size) {
    let table = Array.from({ length: size }, (_, index) => index);
    shuffleArray(table);
    return table;
  }

  function transpositionCipher(
    inputText,
    transpositionTable,
    direction = "encryption"
  ) {
    inputText.toUpperCase();
    let result = [];
    const size = transpositionTable.length;
    if (direction === "decryption") {
      let tempTable = new Array(size).fill(0);
      for (let i = 0; i < size; ++i) {
        tempTable[transpositionTable[i]] = i;
      }
      transpositionTable = tempTable;
    }
    for (let i = 0; i < inputText.length - size + 1; i += size) {
      let tempText = "";
      for (let j = 0; j < size; ++j) {
        tempText += inputText[i + transpositionTable[j]];
      }
      result.push(tempText);
    }
    if (inputText.length % size !== 0) {
      result.push(
        inputText.substring(inputText.length - (inputText.length % size))
      );
    }
    let ret_string = "";
    for (let i = 0; i < result.length; ++i) {
      ret_string += result[i];
    }
    return ret_string;
  }

  // React
  const [table, setTable] = useState(undefined);
  const [cipher, setCipher] = useState(undefined);

  // tableが生成された後に暗号化を行う
  useEffect(() => {
    if (!table) return;
    const cipher = transpositionCipher(inputText, table, "encryption");
    setCipher(cipher);
  }, [table]);
  // 読み込み時に一度だけ呼び出す
  useEffect(() => {
    // 読み込みできてから呼びだす
    setTable(generateTranspositionTable(size));
  }, []);

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "row",
        flexWrap: "nowrap",
        alignItems: "flex-start",
        justifyContent: "space-evenly",
      }}
    >
      <div>
        <h3>元の文字列</h3>
        <p>{inputText}</p>
      </div>
      {table === undefined || cipher === undefined ? (
        /* 変換テーブルを生成してるかつ暗号化済みであれば表示 */ <></>
      ) : (
        <>
          <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>
            <p style={{ padding: "1px", margin: "2px" }}>
              {transpositionCipher(cipher, table, "decryption")}
            </p>
          </div>
        </>
      )}
    </div>
  );
}
結果
Loading...