Thursday, January 30, 2014

Q4M 0.9.12 has been released

Today I have released version 0.9.12 of Q4M - a message queue storage engine for MySQL.

As of the release, Q4M finally includes CMakeFiles.txt, file necessary for building Q4M together with MySQL 5.5 and above. The installation procedure is described in q4m.github.io/install.html.

Changelog is also available at the homepage. Have fun!

Tuesday, January 28, 2014

SSL/TLSライブラリの正しい使い方(もしくは、コモンネームの検証について)

スマホアプリの市場拡大に伴い、直接SSL/TLSライブラリを使用するプログラムを書く機会も増えてきている今日この頃かと思います。

SSL/TLSライブラリを使う際には、接続確立時にサーバの認証を正しく行う必要があります。具体的には、クライアントプログラムで以下の2種類の検証を行うことになります

  • SSL/TLSライブラリがサーバの証明書の検証に成功したこと
  • サーバの証明書に含まれるコモンネーム注1が接続しようとしたサーバと同一であること

前者については、OpenSSLの場合はSSL_CTX_set_verifyの引数にSSL_VERIFY_PEERを指定するなどして、ライブラリ側で処理を行わせることが可能です(証明書の検証に失敗した場合はSSL_connectがエラーを返します)。

一方、後者についてはSSL/TLSライブラリによって差があり、検証機能を有効にするために特別な呼出が必要だったり、あるいは検証機能を提供していないライブラリもあるため注意が必要です(これは、SSL/TLSが任意のストリームで安全な通信手段を確立するためのものであるのに対し、コモンネームの検証はTCP/IP+DNS上でSSL/TLSを使用する場合に必要となる作業である、という要件のズレによるものです)。

たとえば、OpenSSLはコモンネームの検証機能を提供していないので、アプリケーションプログラマが独自に同機能を実装する必要があります。具体的な方法はいくつかあるのですが、最も単純な形で以下のようになるかと思います注2

// returns non-zero value if the verification succeeds
static int verify_common_name_of_ssl(SSL* ssl, const char* hostname)
{
    X509* peer;
    X509_NAME* subject_name;
    char peer_name[256];

    peer = X509_get_peer_certificate(ssl);
    if (peer == NULL)
        return 0; // fail
    subject_name = X509_get_subject_name(X509_get_peer_certificate(ssl);
    if (subject_name == NULL)
        return 0; // fail
    if (X509_NAME_get_text_by_NID(subject_name, NID_commonName, peer_name, sizeof(peer_name)) == -1)
        return 0; // fail
    return strcasecmp(peer_name, hostname) == 0;
}

Android SDKを使っている場合は、公式ドキュメントに注意喚起と対応方法の説明があるので、そちらを参考にすれば良いかと思います(参照: Warnings About Using SSLSocket Directly - Security with HTTPS and SSL | Android Developers)。

iOSでSecure Transportを使っている場合は、SSLSetPeerDomainNameを呼び出して、ライブラリに検証を依頼することが推奨されています(参照: Secure Transport Reference)。

詳しくは、お使いのSSL/TLSライブラリのドキュメントを参照することをお勧めします注3

また、SSL/TLSを使用するアプリケーションのコードレビューや検証にあたっては、コモンネームの確認を行っているかを検証項目に含めることが望ましいと言えるでしょう。

注1: コモンネームとは、証明書に含まれる「www.google.com」等のホスト名のことです(参照: コモンネームとは何ですか - knowledge.verisign.co.jp
注2: ワイルドカード証明書への対応など、任意の証明書に対応する実装をするとなると泥沼が待っているかと思います(参照: WildcardCertificates - CAcert Wiki
注3: より高レベルな、ホスト名解決とTCP上でのSSL/TLS接続機能を一体として提供している類のライブラリにおいては、コモンネームの確認機能が組み込まれている場合が多いかと思います

Monday, January 27, 2014

JSX - experimental support for NPM

Based on @shibukawa-sans work, I have added experimental support for NPM-based packages in JSX 0.9.75. It is now possible to publish libraries for JSX using NPM (or use such packages from JSX).

A tiny example would be the following:

package.json:
{
  "dependencies": {
    "nodejs.jsx": "~ 0.1.1"
  }
}

hello-npm.jsx:
import "nodejs.jsx/*.jsx";

class _Main {
  static function main(args : string[]) : void {
    fs.appendFileSync("/dev/fd/1", "hello npm!\n");
  }
}

Running npm install would install nodejs.jsx (JSX binding for node.js) which is specified as a dependency in package.json. And when the compiler is executed (e.g. jsx hello-npm.jsx) it would automatically search for the imported files and use them in the node_modules directory.

For the time being, file specified in the main section of package.json is used if the name of a module is an argument to the import statement (e.g. import "npm-module-name"). Or the directory designated by the dependencies/lib section is searched if a file within an npm module is specified (e.g. import "npm-module-name/filename").

If you have any comments / suggestions please file a issue at the GitHub issues page.

Tuesday, January 21, 2014

Deflate (gzip) のアルゴリズムを視覚化してみた

DeflateとそのバリエーションであるZIPやgzipは、HTTPにおけるデータ転送やファイル圧縮など、様々な場面で使われる圧縮アルゴリズムです。

そのアルゴリズムの解説としてはslideshare.net/7shi/deflateを始め優れたものがいろいろあるかと思いますが、実際のデータをエンコードして視覚化できるものがないのが不満でした

というわけで、作った注1

ソースコードは、github.com/kazuho/visiflateにあります。

こいつをダウンロードして動かすと、記事の末尾の出力結果のようにダラダラと、どのようにエンコードされているかが表示されます。

この出力を見ることで、例えば、不思議の国のアリスのテキストをgzipすると

テキスト圧縮長
(ビット)
複製位置
"Alice was beginning to get very tired of sitt"224なし
"ing "1329バイト前
"by her"32なし
" si"1115バイト前
"st"9なし
"er "117バイト前
"on the bank, an"72なし
"d of "1342バイト前

のような感じにエンコードされることが分かります。

自分の好きなデータで試すことができて便利!という話でした。


PS. 以下は実行結果です。

% make
% gzip < alice.txt > alice.txt.gz
% ./puff -10 alice.txt.gz
puff() succeeded uncompressing 1328 bytes
8 compressed bytes unused
inpos=406,inbits=224,outpos=0,outbytes=45
    41 6c 69 63 65 20 77 61 73 20 62 65 67 69 6e 6e 69 6e 67 20 74 6f 20 67 65 74 20 76 65 72 79 20 74 69 72 65 64 20 6f 66 20 73 69 74 74
    A  l  i  c  e     w  a  s     b  e  g  i  n  n  i  n  g     t  o     g  e  t     v  e  r  y     t  i  r  e  d     o  f     s  i  t  t 

inpos=630,inbits=13,outpos=45,outbytes=4,distance=-29
    69 6e 67 20
    i  n  g    

inpos=643,inbits=32,outpos=49,outbytes=6
    62 79 20 68 65 72
    b  y     h  e  r 

inpos=675,inbits=11,outpos=55,outbytes=3,distance=-15
    20 73 69
       s  i 

inpos=686,inbits=9,outpos=58,outbytes=2
    73 74
    s  t 

inpos=695,inbits=11,outpos=60,outbytes=3,distance=-7
    65 72 20
    e  r    

inpos=706,inbits=72,outpos=63,outbytes=15
    6f 6e 20 74 68 65 20 62 61 6e 6b 2c 20 61 6e
    o  n     t  h  e     b  a  n  k  ,     a  n 

inpos=778,inbits=13,outpos=78,outbytes=5,distance=-42
    64 20 6f 66 20
    d     o  f    

注1: 元にしたのは、zlibに付属する参照実装であるPuff