2014-05 << 2014-06 >> 2014-07

2014-06-22 (日)

*[JavaScript] JSEncryptを使ってみる

最近はJavaScriptの実行速度もかなり良い感じになってきたので,RSAの鍵生成とかも実用に耐える気がします.

JavaScriptでRSA暗号を扱うために,JSEncryptを使ってみます.MTIライセンス.

https://github.com/travist/jsencrypt

まず,適当に bin/jsencrypt.js を読み込む.

RSAキーを生成してみる.

    var crypt = new JSEncrypt({default_key_size: 1024});
    console.log(crypt.getKey());
    console.log("pub:" +crypt.getPublicKey() );
    console.log("pri:" +crypt.getPrivateKey() );

pem形式で出力される.

getKey()を呼ぶと,鍵がなければ新たに作るらしい.

512ビットだと一瞬だけど1024だと1~2秒待たされる.2048とかだと結構待たされるので,非同期にしたほうが良さげ.getKey()に何か関数渡すと非同期になるっぽい.

キーを生成するときの乱数は,window.crypto + マウスイベントを使っている.まぁ,大丈夫そうに見える.

setKeyで,pemフォーマットの鍵を読み込める.

    var crypt = new JSEncrypt({default_key_size: 1024});
    crypt.setKey(document.getElementById('ras_key').innerText);
    console.log(crypt.getKey());
    console.log("pub:" +crypt.getPublicKey() );

あたりまえだけど,公開鍵を setKey()に渡した場合は,getPrivateKey()は呼べない.

得られるのはPEM形式の鍵なので,SSH形式が欲しい場合はRFC4253を読みつつ,

function hex2b64(h) {
  var len = h.length / 2;
  var buf = new Uint8Array(len);
  for (var i=0; i<len; i++) {
    buf[i] = parseInt(h.substr(i*2,2),16);
  }
  return btoa(String.fromCharCode.apply(null, buf));
}

function int2hex(n) {
     return ("0000000" + n.toString(16)).substr(-8);
}
function sshkey(key) {
    var e = "0"+key.e.toString(16);
    var n = "0"+key.n.toString(16);
    var e = e.substr(e.length%2);
    var n = n.substr(n.length%2);
    var hex = int2hex(7) + stohex("ssh-rsa") + int2hex(e.length/2) + e + int2hex(n.length/2) + n;
    return "ssh-rsa " + hex2b64(hex);
}

console.log(sshkey(crypt.getKey()));

みたいにすればそれっぽくなる.(ちゃんと出来てるかは確認してない)

hex2b64()関数は,JSEncrypt内にあるけど外から呼べないのでコピペしてくるほうが良さげかも?.

自分でパースした公開鍵を読み込むには,RSAKey や BigIntegerを自分では作れないので,setKey(null)で初期化したあと,getKey().setPublic(n,e)でセットするしかなさそう(?).

あとは,encrypt(), decrypt()メソッドが使えるので良しなに.

色々やるにはJSEncrypt.js使うより,JSEncryptが中で使ってるRSAライブラリを直接使うほうが良さそう.

2014-05 << 2014-06 >> 2014-07