维吉尼亚密码
QUOTE 《密码编码学与网络安全——原理与实践(第五版)》
多表代替密码中最著名和最简单的是 Vigenere 密码。它的代替规则集由 26 个 Caesar 密码的代替表组成,其中每一个代替表是对明文字母表移位 0 到 25 次后得到的代替单表。
算法描述
-
明文: P = p 1 p 2 . . . p n {\rm P = p_1 p_2 ... p_n} P=p1p2...pn
-
密钥: K = k 1 k 2 . . . k m {\rm K = k_1 k_2 ... k_m} K=k1k2...km
-
密文: C = c 1 c 2 . . . c n {\rm C = c_1 c_2 ... c_n} C=c1c2...cn
-
加密: c i = ( p i + k i m o d m ) m o d 26 {\rm c_i = (p_i + k_{i \, mod \, m}) \, mod \, 26} ci=(pi+kimodm)mod26
-
解密: p i = ( c i − k i m o d m ) m o d 26 {\rm p_i = (c_i - k_{i \, mod \, m}) \, mod \, 26} pi=(ci−kimodm)mod26
算法实现
加密:
function encodeWithVigenere(pStr, kStr) {
const p = pStr.replace(/\s/g, '').toLowerCase().split('').map(piStr => piStr.charCodeAt() - 97);
const k = kStr.replace(/\s/g, '').toLowerCase().split('').map(kiStr => kiStr.charCodeAt() - 97);
const m = k.length;
const c = [];
for (let i = 0; i < p.length; i++) {
let ci = (p[i] + k[i % m]) % 26;
c.push(ci);
}
return c.map(ci => String.fromCharCode(ci + 97)).join('');
}
解密:
function decodeWithVigenere(cStr, kStr) {
const c = cStr.replace(/\s/g, '').toLowerCase().split('').map(ciStr => ciStr.charCodeAt() - 97);
const k = kStr.replace(/\s/g, '').toLowerCase().split('').map(kiStr => kiStr.charCodeAt() - 97);
const m = k.length;
const p = [];
for (let i = 0; i < c.length; i++) {
let temp = (c[i] - k[i % m]);
let pi = ((temp < 0 ? temp + 26 : temp)) % 26;
p.push(pi);
}
return p.map(pi => String.fromCharCode(pi + 97)).join('');
}
测试:
let cStr = encodeWithVigenere('we are discovered save yourself', 'deceptive');
console.log('p =', cStr);
let pStr = decodeWithVigenere(cStr, 'deceptive');
console.log('c =', pStr);
$ node a.js
p = zicvtwqngrzgvtwavzhcqyglmgj
c = wearediscoveredsaveyourself