[Javascript] ZlibのRawDeflateとRawInflateの相互変換ツール

2024/09/29

Javascript Tool

t f B! P L
eyecatch 平文の文字列をデータとして扱う時に、一抹の不安がよぎるのは、エンジニアの宿命です。 Base64や、文字コード化して、難読化処理を施すのは簡単に実現できますが、 インターネット通信を行う場合は、データを圧縮してできるだけパケット通信を抑えて、通信速度を減らしたいと考えるのも、エンジニアならではの義務感です。 そこで今回は、deflateアルゴリズムを用いた、比較的メジャーな圧縮を使って、文字列の難読化+圧縮処理をツール化してみました。

ツール

ソースコード

index.html

<link rel="stylesheet" href="css/style.css"> <script type="module" src="js/main.js"></script> <section> <textarea class="text-archive" name="string"></textarea> <div class="control"> <button name="encode">文字列を圧縮 ↓</button> <button name="decode">↑ 圧縮データを復元</button> </div> <textarea class="text-archive" name="archive"></textarea> </section>

css/style.css

textarea.text-archive{ width:500px; max-width:100%; min-height:150px; margin:10px; border:1px solid #AAA; border-radius:10px; padding:10px; } .control{ width:500px; display:flex; gap:10px; margin:10px; align-items:center; justify-content:center; }

js/main.js

import { Archive } from "./archive.js" class Main{ constructor(){ new Archive() } } switch(document.readyState){ case "complete": case "interactive": new Main() break default: window.addEventListener("DOMContentLoaded" , (()=>new Main())) }

js/archive.js

export class Archive{ path_rawdeflate = "js/zlib/rawdeflate.min.js" path_rawinflate = "js/zlib/rawinflate.min.js" get elm_textarea_string(){ return document.querySelector(`textarea[name="string"]`) } get elm_textarea_archive(){ return document.querySelector(`textarea[name="archive"]`) } get button_encode(){ return document.querySelector(`button[name="encode"]`) } get button_decode(){ return document.querySelector(`button[name="decode"]`) } constructor(){ this.put_script(this.path_rawdeflate) this.put_script(this.path_rawinflate) this.button_encode.addEventListener("click" , this.encode.bind(this)) this.button_decode.addEventListener("click" , this.decode.bind(this)) } put_script(path){ const script = document.createElement("script") script.src = path document.body.appendChild(script) } encode(){ const str = this.elm_textarea_string.value const val = escape(encodeURIComponent(str)) const arr = new TextEncoder().encode(val) const deflate = new Zlib.RawDeflate(arr).compress() const data = ((chars)=>{ let str = "" for(const char of chars){ str += String.fromCharCode(char) } return str })(deflate) this.elm_textarea_archive.value = btoa(data) } decode(){ const val = atob(this.elm_textarea_archive.value) const chars = ((val)=>{ const arr = [] for(let i=0; i<val.length; i++){ arr.push(val[i].charCodeAt(0)) } return new Uint8Array(arr) })(val) const inflate = new Zlib.RawInflate(chars).decompress() const str = new TextDecoder().decode(inflate); this.elm_textarea_string.value = decodeURIComponent(unescape(str)) } }

zlibモジュールの配置

zlibライブラリは、以下のgithubから取得しています。 https://github.com/imaya/zlib.js cloneして使っても良いんですが、必要なのはrawdeflateとrawinflateの2つだけなので、以下のリンクからソースコードをコピペしても大丈夫です。 rawdeflate : https://github.com/imaya/zlib.js/blob/develop/bin/rawdeflate.min.js rawinflate : https://github.com/imaya/zlib.js/blob/develop/bin/rawinflate.min.js DLした上記ファイルを、js/zlib/以下に配置します。

解説

実は文字列を圧縮する時に、バイナリデータだと、データ量が少なくなるんですが、それをまた文字列にbase64変換しているため、元データよりも大きく膨らんでしまっています。 zipファイルなどでダウンロードする形式にしておけば、軽いデータのやりとりになりますね。 今回、作ってから気がついたので、このまま強引に進めてしまいますwww。 文字エンコードで、new Zlib.RawDeflate(arr).compress()とした直後のデータは、00,00,00みたいな文字コードの配列データのようないわゆるunit8Array形式のデータなので、 これをfromCharCodeで、文字に戻してあげます。 でもこの文字は、asciiキャラクタにならないものもあるので、base64で文字列変換します。 デコードはこの逆の操作ですね。

あとがき

ハマったのは、new TextDecoder()を利用したエンコード、デコードで、文字列を前後で処理しないと、思った通りの文字変換が行われないという事がわかりました。 いったい何度エンコードを行っているんでしょう? きっと、もっとシンプルな変換ができると思うので、今回のバージョンはモックアップとして公開しておきます。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ