javascriptと暗号化 配列の並べ替えについて
暗号化、ちょっとワクワクしちゃいますね。
暗号化・復号化の速度を考えなければ色々独自仕様で作るのも楽しいです。
備忘録的に配列の並べ替えについて記載します。
(前提として文字列を、Uint8Arrayと言う値が0~255の数の配列に変換していますので、その並べ替えについてです)
並べ替えについて面白いというか効率的な方法に『フィッシャー–イェーツのシャッフル』と言うアルゴリズムがあります。
フィッシャー–イェーツのシャッフル
https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB
注意点としては使用する乱数が偏らない事が要求されます。
本当の乱数を使うと、毎回結果が異なるため、暗号化した文章を元に戻せなくなりますのでパスワードから疑似的な乱数列を作ります。
(並べ替えじゃなくて変換する場合のキー(個々の数に加算したりする数値)についても同様ですね)
今回は、実際にjavascriptのMath.random()を使って、0から255の値になる数列を、どの数値も最低n個持つような数列を複数(今回は256)作って、それを参照することで疑似的な乱数を取得する事にしました。(要は固定の乱数表を用意)
nの値を増やすと、とんでもない要素数の配列になるので注意です。
(具体的にはビルドにかかる時間が伸びます、かなり)
個々の数値は以下のように求めました。
const rrnd=Math.floor(Math.random()*1000000) % 256;
シャッフルに使う乱数としては、n組のUint8Arrayの要素を使います。
文字列の長さをNとした時、N*3よりも大きくなるような乱数を作り、それをN(正確には処理毎に短くなる)で割った剰余を並べ替え用の配列作成に使用しました。
例えば、乱数① * 256**3 + 乱数② * 256**2 + 乱数③ * 256 + 乱数④ の4つの乱数で一つの大きな乱数を作りました。
さて話を並べ替えに戻します。
例えば
['Jan.','Feb.','Mar.','Apr.','May','Jun.','Jul.','Aug.','Sep.','Oct.','Nov.','Dec.'];
と言う配列があり、これを並べ替える順番を指定した配列が以下のように作ってあるとします。
[4,2,12,6,10,9,1,8,7,5,11,3];
ここからが備忘録なんですが、配列のmap() メソッドとアロー関数式に慣れてきたので以下の記述で処理できます。
---------------------------------------------------------------
const months = ['Jan.','Feb.','Mar.','Apr.','May','Jun.','Jul.','Aug.','Sep.','Oct.','Nov.','Dec.'];
const sort = [4,2,12,6,10,9,1,8,7,5,11,3];
const newMonths=months.map((x,index)=>{
return months[sort[index]-1];
});
console.log(newMonths);
//["Apr.", "Feb.", "Dec.", "Jun.", "Oct.", "Sep.", "Jan.", "Aug.", "Jul.", "May", "Nov.", "Mar."]
console.log(newMonths.length);
//12
---------------------------------------------------------------
胆は以下の部分です(改行外してます)。
const newMonths=months.map((x,index)=>{return months[sort[index]-1];});
最初はなじめませんでしたが、今となっては手放せませんね。アロー関数式。
簡単に説明するとmonthsと言う既存の配列から、newMonthsと言うsort配列に従った並べ替えを行っています。sort配列が1から始めたので月名としては見やすくなりましたが、配列順序的には見ずらいかもですね。(months[sort[index]-1]で、-1しなければならなくなった)
以下のリンクで、色々スクリプトを書いて試せますので、自習としてはお勧めです。
mdnの試してみましょう
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map#%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%82%87%E3%81%86
いつまでたっても覚えることがありますが、楽しいのはありがたい限りですね。
追記:
圧縮等でpromise(非同期処理)が入っているのですが、この際のエラーハンドリング(無効な文字列など)が発生して、以下のサイトが参考になりました。
Promise でのエラーハンドリング
https://ja.javascript.info/promise-error-handling