「jQuery」 カテゴリーの記事です。

JavaScriptでCryptoJSを使って、AESの暗号化と復号を行う


ウェブサイトを見回してみても、正しく実装されていなかったり、良いサンプルが無かったので、記事にしてみました。

→ DEMO&ソースコード:https://jsfiddle.net/hibara/qzono8jb/

CryptJSについては、以下にあります。
https://code.google.com/archive/p/crypto-js/

暗号化するにあたって

CryptJSの本題に入る前に、少し暗号化についてのお作法を知っておく必要があります。詳細は僕が書いた、別記事の「Visual Studio C#でファイルを暗号化してみる」を参照していただきたいですが、一応ざっとおさらい。

暗号化モードではCBCモードを使うのがベター

ブロック暗号方式と呼ばれるものは、その名のとおり、何バイトかずつブロック単位で暗号化していきますが、ここでやりがちなのがECBモードでしょうか。

ECBモード

これの何が問題かといえば、毎回同じデータ、同じパスワードだと、毎回同じ内容の暗号化データがでてきしまうという点です。

あるいは、各ブロックが小さくなるので、暗号化データへの総当たり攻撃(ブルート・フォースアタック)がしやすくなります。

基本的には、CBCモードを使いましょう。

CBCモード/暗号化

冒頭に、乱数による初期化ベクトル(Initialization Vector)を与えて、各暗号化ブロックに捻り合わせて行くイメージでしょうか。

CBCモード/復号する

ちなみに、暗号の大家であるブルース・シュナイアー氏がその著書『暗号技術大全』(日本語訳版は絶版・・・)の中でも、

ファイルを暗号化するのであれば、CBCモードがベストだろう。このモードを使えば、セキュリティは大きく向上するし、保存したデータに多少エラーが発生しても、同期エラーが発生することはまずない。アプリケーションが(ハードウェアではなく)ソフトウェアベースであれば、CBCがほぼ確実にいちばんいい。

と書いています。

パディングモード

ブロック暗号方式では、何バイトかのブロック単位で暗号化することにより、場合によっては、「端数」が出てしまいます。

これは暗号化されると、どこまでが暗号化データだったのか、復号時に正しく判別ができなくなくなるということです。

パディングモードでよく使われるのは、PKCS7のパディングモードでしょうか。

たとえば、以下の例ですと、データ長が8バイトで、実際のデータ列が9バイトあれば、残りの7バイトは、以下のように埋められます。

PKCS7パディングモード

つまり「余り」に埋められた合計サイズが、数値として埋められるというわけです。
これにより、復号時に、データ境界線をプログラムで判別できるようになります。

CryptoJSにはすべて揃っている

ところが、いざ、CBCモードで、PKCS7のパディングモードで暗号化したいと、該当のソースファイルを当たったら、どこにも見当たらない。「おかしい」と思って、本家のページを当たってみたところ、いずれも「Default」であるということが判明。

ユーザーが万一、なにも設定せずに使ってしまっても、黙ってCBCモードでPKCS7パディングモードで暗号化されるという親切設計でした(笑)。

CryptoJS supports the following modes:

CBC (the default)
CFB
CTR
OFB
ECB
And CryptoJS supports the following padding schemes:

Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding

暗号化キーは鍵空間を広く使う

これは暗号化ユーティリティを使うすべてのユーザーにも言えることですが、パスワードはなるべく長い文字列で使ってほしいところです。当然、総当たり攻撃がしやすいという問題があるからです。

とはいえ、ユーザビリティを強制するのも、ツールの自由度を下げます。ただ、開発者側もそういった問題に少なからずフォローすることはできます。

たとえば、一文字のみパスワードを入れられても、鍵空間を目一杯使って、毎回異なるパスワードキーを生成してあげれば、多少この問題を和らげることができます(ただし、ブルートフォースアタックのような攻撃には何の訳にも立ちません)。

鍵空間

本題の「CryptoJS」

さて、本題の「CryptoJS」ですが、Google Code Archiveに上がっている、ライブラリです。そのサイトには、こう書かれています。

CryptoJS is a growing collection of standard and secure cryptographic algorithms implemented in JavaScript using best practices and patterns. They are fast, and they have a consistent and simple interface.

CryptoJSは、ベストプラクティス、ベストな形で、JavaScriptにおいての安全な暗号アルゴリズム標準となるべく開発しているものの一つです。これらは高速であり、一貫性とシンプルなインターフェイスを提供しています。

実際、オープンソースで、CDNやGitHubにも上がっています。

使い方は、たしかに簡単で、実際に使いたいjsファイルをhtmlヘッダ内で定義するだけです。

CryptoJSのAESを使ってみる

通常なら、「aes.js」だけで行けますが、今回は鍵空間を広げるためのライブラリを使うので、「pbkdf2.js」を含めました。

CryptoJS を使う上での注意点は、やはり「バイナリ」の扱いでしょうか。

おそらくウェブ上(サーバ間)でのデータのやりとりも考慮されているのか、データをバイナリデータ(Hex = 16進文字列)や、Base64エンコーディングして渡す場面が何度かあります。

ただ、CryptoJS では、それらを適宜、必要なデータへコンバートするためのメソッドも用意されています。

CryptoJS.enc.Hex.parse()
CryptoJS.enc.Base64.parse()
CryptoJS.enc.Utf8.parse()

などを駆使して暗号化します。

まずは、暗号化から。この程度のソースコードにjQueryを使っているのはご容赦ください。

暗号化の際の注意点としては、暗号に必要なsaltやIVなどを、暗号化データに含めないといけない点です。

ここでは単に、カンマ区切りとしていますが、他に方法があるのなら、どのような手段でも良いでしょう。

そして、復号はこちら。

以上です。

実際のデモは、先にも書きましたが、
https://jsfiddle.net/hibara/qzono8jb/

で、見られます。

CodeMirriorコンストラクタの罠


いま、Qt の QtWebKit Bridge(http://qt-project.org/doc/qt-5/qtwebkit-bridge.html)という機能を使っての、MacOSXアプリケーションをつくっています。

いわゆるMarkdown記法を元に、アウトラインを作りながら書いていく、日本語入力のエディタを考えていて、
エディタ部分には、CodeMirroir というライブラリを使います。

ただ、どうもCodeMirrior のコンストラクタで、エディタのインスタンスが、生成されていないみたい。

  
  editor = CodeMirror(document.body, {
    value: "\n",
    mode:  "markdown",
    smartIndent: false,
    tabSize: 2,
    indentWithTabs: true,
    electricChars: false,
    lineWrapping: true,
    lineNumbers: true,
    foldGutter: true,
    enableCompositionMod: true,
    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
  }).on(
    //Changeイベント
    'change', function() {
        //alert('changes!');
        jsBridge.changes();
    });

  editor.setValue("abc");  //←ここでエラー
  

こんな、エラーが発生します。↓

JavaScriptエラー

で、よくよく調べてみたら、意外なところに落とし穴がありました。

ヒントがあったのは、このページ。
https://groups.google.com/d/msg/codemirror/DfR57zf6k18/9kLma4I6dagJ

CodeMirrior は、jQueryみたいにオブジェクトを返さないよー、とある。

な、ん、だ、と・・・

完全に、jQuery脳っていうか、JavaScript的に考えれば、オブジェクトを返すはずで、メソッドチェーンするのは当然だと思ってました。
いや、ふつうそうじゃないのか・・・

なんで、CodeMirrior ではできないのか?

答え:そういう仕様だから(笑)。

コンストラクタした内容をオブジェクト変数に入れて、使い回すことはできない。これ、仕様。

だから、こう書きます。

  
  editor = CodeMirror(document.body, {
    value: "\n",
    mode:  "markdown",
    smartIndent: false,
    tabSize: 2,
    indentWithTabs: true,
    electricChars: false,
    lineWrapping: true,
    lineNumbers: true,
    foldGutter: true,
    enableCompositionMod: true,
    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
  }).on(

  editor.on(
    //Changeイベント
    'change', function() {
    //alert('changes!');
    jsBridge.changes();
  });

  editor.setValue("abc");
  

最初のコンストラクタのみ、オブジェクトを返すので、メソッドチェーンはできません。

なぜ? どうせならオブジェクトをそのまま返してくれればいいだけなのに(笑)。

 
 

jQueryで独自スライドショー作成チュートリアル(1)(スライドショーの基本動作)


車輪の再発明ですか。そうです。

いまさらすぎやしませんか。今でしょ!(強がり)

いや、たしかに、世の中にはスライドショーを実現するのに、便利なjQueryプラグインはすでにゴマンと存在します。

僕のオススメは、<div>単位で扱え、ライセンスも緩やかな、bxSlider や、jQuery Slider2でしょうか。

とはいえ、いろいろいじくっていると、「この機能が無い・・・」とか、この演出を実現するには、「無理くりプラグインの仕様に合わせる必要がある・・・」など出てきます。

ああ、やっぱり、仕組みを押さえながら、自分で一から、シンプルに実装してみたいなあ、といつしか思うように。

今回の連載記事では、僕がどうやってスライドショーを実現するところまで至ったか、その過程を順番に辿っていきます。最終的には、軽量でシンプルなjQueryスライドショー・プラグインをつくってみようと思っています。

また、段階的に、その時点でまとめたサンプルソースも公開していきますので、それを元に、いろいろ参照してくださるなり、勝手に改良してくださってかまいません。

ここで配布されるサンプルデータすべてのライセンスは、前述のbxSliderプラグインに敬意を表し、WTFPL licenseとします(笑)。

(さらに…)

s