caesar暗号。10世紀経てば5行。


ただシフトするだけ。

const caesar = function(str, amount) {
  const a= (amount < 0)? amount + 26:amount
  ,fc=String.fromCharCode
  ,fn=( d=>((d >= 65) && (d <= 90))?fc(((d - 65 + a) % 26) + 65):fc(((d - 97 + a) % 26) + 97) )
  ;
  return str.split('').map( d=>(d.match(/[a-z]/i) )?fn(d.charCodeAt(0)):d ).join('')
}
;

日本語やウムラウトはbase64する。

fn._btoa =function(str){return btoa( unescape(encodeURIComponent( str )) )}
fn._atob =function(str){return decodeURIComponent( escape(atob( str )) )} 

デモ

let fn={};
fn._btoa =function(str){return btoa( unescape(encodeURIComponent( str )) )}
fn._atob =function(str){return decodeURIComponent( escape(atob( str )) )} 
fn.caesar =function(str, amount) {
  const a= (amount < 0)? amount + 26:amount
  ,fc=String.fromCharCode
  ,fn=( d=>((d >= 65) && (d <= 90))?fc(((d - 65 + a) % 26) + 65):fc(((d - 97 + a) % 26) + 97) )
  ;
  return str.split('').map( d=>(d.match(/[a-z]/i) )?fn(d.charCodeAt(0)):d ).join('')
}
;
fn.ce=(d=>document.createElement(d))
;
let t =fn.ce('textarea')
,r1 =fn.ce('pre')
,r2 =fn.ce('pre')
,s =fn.ce('style')
,sol =(d=>Promise.resolve(d))
;
s.innerHTML=`*{box-sizing:border-box}
body{margin:0;display:flex;width:100vw;height:100vh;flex-direction:column;}
textarea,pre{border:2px solid;width:100%;padding:1rem;flex-grow:1}
textarea,pre{white-space:pre-line;word-wrap: break-word;}`
;[s,t,r1,r2].forEach(d=>document.body.appendChild(d));
t.oninput =on
;
function on(ev){
 let v=this.value;
 sol(v).then((d)=>{ 
    let shift=21,de=fn.caesar( fn._btoa(d) ,shift)
    r1.innerText= de;
    r2.innerText= fn._atob( fn.caesar(de,-1*shift) )
 })
}