JSとcanvasで縦組みエンジンを作ろう( ・∀・) その3


例によってサンプルのみです。Google App Engineでギコ文庫というアプリを作ってみました。

ギコ文庫http://gikobunko.appspot.com


ギコ文庫はWebテキストを縦書き+アンチエリアスで読めるかも知れないサービスです。

URLを入れて実行を押すと、htmlが生成される。

js側の方は調整してないので表示がグダグダなのがわかる。
縦書き用のフォントはIPAフォントのダウンロード || OSS iPediaのIPAexフォントを利用した。ライセンスは詳しく調べてない。問題ありそう。

細かい解説や技術情報は今週末になると思います。あくまでサンプルです。実用に耐えられるようには出来ていません。

Perl挫折記


本当はこの記事は、typeface.js(http://typeface.neocracy.org/)のコードを読んでみたっていう記事にしようかと思っていた。

ただ、…そこまで行く前に挫折してしまった。それを報告したい。少しイライラが溜まって変な文章になってることをお断りしたい。

Perl Module

typeface.jsのコードは、http://typeface.neocracy.org/download.htmlにある。本体のほかに、フォントパスを含んだJSを作るGenerating typeface.js Fontsも配布されている。

まず、第一の選択ミスは最初にこれを選んだことだった。


tar.gzという見慣れない拡張子を解凍すると、中にpmという拡張子を持つファイルが入っていた。

Perl。私にとってこの言語は鬼門だった。本当に、最初の頃、小さなアプリケーションをこれで作ろうとして、挫折した。それから私はPHPで同じ物を作った。簡単だった。以後、Perlは封印し、ほとんど無害として放置しておいた。

今、この言語は私にとって、どうしても必要になった。pmの大きさはあまりにも小さかった。TrueTypeを扱っているだろうサイズとしては不自然だったのだ。中を見る。

use Font::FreeType
use Font::TTF

とても一般的とは思えないライブラリー。これを含んだ実行環境が必要なのは目にみえていた。

EXAMPP

第二の選択ミスは、ここで、「XAMPP(http://www.apachefriends.org/jp/xampp-windows.html)」を選んだことである。私は甘く考えていた。XAMPPにはPerlフォルダがあった。だから動くと。


だがわからなかったことがあった。FreeTypeやTrueTypeのライブラリはどこにあるのか?Perlフォルダの中にはPerl.exeが1つあっただけだった。


結論からいうと、これはXAMPPのバージョンが古いだけだった。ver1.7.1の人はPerlを使えるようにver1.7.3にバージョアップしなければならない。これはどこにも書いてないから注意書きを書くべきだろう。


ともかく、Perlフォルダのなかはbin、lib、siteとずいぶん賑やかになったのだが、肝心のFontフォルダーがlibにもsiteにも無いのはどういう事だろうか。どこからか持ってこい、そういう訳か!


第三の選択ミスは、ここでcpan.batではなくてppm.batをチョイスしたことだ。CUIと英語という卑劣さを乗り越えて、以下のコマンドを実行した。

install Font::FreeType

うまくいかなかった。

search Font

目的とする物はなかった。


だいぶたってから、私は目的とする物がCPANという場所にあることを突き止めた。そしてしばらくして、使っていたものが間違っていたことに気がついた。あぁぁ

エラー、エラー、またエラー

cpan.batを実行する。

i /Font::FreeType/

Module    Font::FreeType         (GEOFFR/Font-FreeType-0.03.tar.gz)
Module    Font::FreeType::Face   (GEOFFR/Font-FreeType-0.03.tar.gz)
Module    Font::FreeType::Glyph  (GEOFFR/Font-FreeType-0.03.tar.gz)
Module    Imager::Font::FreeType2 (TONYC/Imager-0.73.tar.gz)
Module    SWF::Builder::Character::Font::FreeType (YSAS/SWF-Builder-0.16.tar.gz)
5 items found

ああ…、あったあった。インストール。

install Font::FreeType

カスみたいなエラーが出て、止まる。nmakeが…。Pathを通してやる。clが…。Pathを通してやる。mspdb80.dllが…。Pathを通してやる。sys/types.hが…。Microsoft Platform SDK…は今はMicrosoft Windows SDK になってて、そこにsys/types.hは無かった。


諦めた。

結論:Perlとはウマが合わない

cygwin? VMPayerでLinux? もうやめよう。そこまでしてPerlWindowsで動かしたくない。
きっと生粋のPerlerからはクソみたいな扱いを受けるけど、いいんだ。諦めてそこで試合終了にしよう。
PHPでいいじゃん。セキュリティ穴だらけとか言われてるけど、使いこなせなきゃPerlだって同じだろう。
なんだろう。すごい虚しさを感じる。

     ∩_∩     人人人人人人人人人人人人人人人人人人人人人人人人人人人人人 
    / \ /\   < なんだろう。                                   > 
   |  (゚)=(゚) |   <                                            > 
   |  ●_●  |   <                                            > 
  /        ヽ  <                                            > 
  | 〃 ------ ヾ | <                                            > 
  \__二__ノ    YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY

アスキーアートのデータベースを作る

1.AAのデータベースを作る

 AAのデータベースは幾つかあるけれども、重かったり検索できなかったり(参考資料1,2)したので自分で作ることにした。利用したのはMySQLphpで、サーバーはpf-x上のを利用した。形としてはAAに複数のタグをつけられる物を目指した。DBをいじるのは初めてなのでとんでもないことをしているかもしれない。

2.テーブルの形

まずサーバーにphpMyAdmin(参考資料3)を導入し、テーブルを作った。
AAのIDとAAそのものを収めるhtmltableとタグとAAのIDを結びつけるtagtableを作った。

CREATE TABLE `asciiart`.`htmltable` (
`aaid` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`html` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
) ENGINE = MYISAM ;

CREATE TABLE `asciiart`.`tagtable` (
`tag` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`aaid` INT( 11 ) NOT NULL ,
`tagHiragana` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`rank` INT( 11 ) NOT NULL
) ENGINE = MYISAM ;

ここでtagHiraganaはタグのひらがなであり、rankはタグの重要度である。tagtableのインデックスはtagHiraganaとaaidに付けた。

3.AAの挿入とタグの挿入

 AA一つに対して、一つ以上のタグが挿入される。

INSERT INTO `asciiart`.`htmltable` (`aaid`,`html`)
VALUES (NULL,
'  ∧_∧
 ( ´∀`)
 (    )        ∧∧
 | | |   〜′ ̄ ̄(,,゚Д゚)
 (__)_)    UU ̄U U'
);

INSERT INTO `asciiart`.`tagtable` (`tag`, `aaid`, `tagHiragana`,`rank`)
VALUES ('モナー',LAST_INSERT_ID(),'もなー',1);

INSERT INTO `asciiart`.`tagtable` (`tag`, `aaid`, `tagHiragana`,`rank`)
VALUES ('ぎこ',LAST_INSERT_ID(),'ぎこ',1);

INSERT INTO `asciiart`.`tagtable` (`tag`, `aaid`, `tagHiragana`,`rank`)
VALUES ('モナー系AA',LAST_INSERT_ID(),'もなーけいAA',2);

ここでLAST_INSERT_ID()は最後に挿入したプライマリなIDを取得する関数である(参考資料4)。

4.タグで検索してAAを取得

 任意の一つ以上のタグが付いているAAをリストする方法は参考資料5に詳しい。GROUP BYとHAVINGを使えば割と簡単に記述できる。
AAの数が少ないうちは以下のようなクエリを発行していた。

SELECT `html`
FROM `htmltable`
WHERE `aaid`
IN(
SELECT tT.aaid AS aaid
FROM tagtable tT
WHERE 'もなー' = tT.tagHiragana
OR 'ぎこ' = tT.tagHiragana
GROUP BY tT.aaid
HAVING COUNT( tT.tagHiragana ) =2 #タグの個数
)
LIMIT 0 , 30;

しかし、これはAAの数が多くなると実行に1秒以上かかる様になってしまった。(ただしtagHiraganaにインデックスをつけると1/4秒程度と少し早くなった。)原因オプティマイザがINをEXISTに書き換えることで、参考資料6,7に詳しい。以下の用に書き換えると早くなった。

SELECT `html`
FROM `tagtable`
INNER JOIN `htmltable` ON tagtable.aaid = htmltable.aaid
WHERE 'もなー' = tagtable.tagHiragana
OR 'ぎこ' = tagtable.tagHiragana
GROUP BY tagtable.aaid
HAVING COUNT( tagtable.tagHiragana ) =2 #タグの個数
LIMIT 0 , 30

なぜこれで早くなるかはよく分からない。

5.タグリスト

以下のようなクエリを発行すると重複している数と合わせてタグの一覧が取得できる(参考資料8)。

SELECT `tag`, COUNT(*) AS Count
FROM `tagtable`
GROUP BY `tag`
HAVING (COUNT(*) > 0)
ORDER BY `Count` DESC

6.サンプル

 AAを取り出すには[外部リンク] JavaScript IMEのInput methods ServerをAAテストにして「ひらがな」を入力してスペースを押します。「@」で区切ると複数のタグが付いた項目を抜き出せます。例)「もなー」、「もなー@ぎこ」もしくは「ぎこ@もなー」
 どのようなAAが登録されているのか見るには[外部リンク] タグ一覧を使用してください。

C++とCOM

C++とCOM、難しい。調べれば調べるほど分からないところが出てくる。(;^ω^)

1.staticとextern

staticは初期化される。externをつけるとグローバル変数になるのではなくて、コンパイルエラーが出ないようにするために付ける。
C言語編 第32章 ファイル分割

2.IDL

MSDNのメソッドのSyntaxで出てくる[in]とか[out]とか何なんだろうなと思っていたけど、IDLというものらしい。[in]が付いてる引数は読み込みのみ。[out]が付いてる引数はポインタで、変更してよし。[in out]は読み込みと書き込みがOK。

COM プログラミングの基本 (中)

3.GUIDとRFFIIDとCLSID

COMではインターフェースとインターフェースを実装したクラスに一意のIDをつけて管理している。インターフェースにつけられるIDがIIDでクラスにつけられるIDがCLSIDである。REFIIDは・・・わからない。全てGUIDの別名である(defineされている)。GUIDとは非常に大きい範囲を持つIDである。用意されているインターフェースのIIDはIID_名前で定義されている。CLSIDも同様。

typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[ 8 ];
} GUID;

乱数で勝手に決めても範囲が大きいのでかぶらないと思う思想に基づいている。下記のサイトで生成することができる。
Generate GUID (guidgen)


GUID - Wikipedia

4.HERSULT

BOOLの進化系。単なる数値である。マクロはS_〜が成功、E_〜がエラーになるように定義されている。SUCCEEDEDとFAILEDマクロは成功したか、失敗したかをbooleanで返す。
HRESULT型とは?(UsefullCode.net)

5.IUnknown

全てのインターフェースはIUnknownから派生している。従ってIUnknownのQueryInterfaceとAddRefとReleaseの3つのメソッドは必ず実装する必要がある。
QueryInterfaceはそのクラスで実装している他のインターフェースを取得するメソッドである。他のというのはIUnknown以外のということである。

class CClassFactory : public IClassFactory{
 〜
}

STDAPI CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
{
    if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
    {
        *ppvObj = this;
        DllAddRef();
        return NOERROR;
    }
    *ppvObj = NULL;
    return E_NOINTERFACE;
}

つまるところ、クラスで実装されているメソッドを.や::で使うのではなく、インターフェースを取ってからメソッドを使用しているわけである。
AddRefとReleaseはオブジェクトのメモリ管理に利用する。二つのメソッド以外にカウンタとなる変数を用意しておく必要がある。

STDAPI_(ULONG) CCaseTextService::AddRef(){
    return ++_cRef;
}

STDAPI_(ULONG) CCaseTextService::Release(){
    LONG cr = --_cRef;

    assert(_cRef >= 0);

    if (_cRef == 0)
    {
        delete this;
    }

    return cr;
}

GCを手動でやっているようにも見える。
GC/standard/Reference Counter - GCアルゴリズム詳細解説 - livedoor Wiki(ウィキ)

6.STDAPI、CALLBACK、STDMETHODIMP、WINAPI

 最終的に__stdcallにたどり着く。呼び出し規約と呼ばれるものでデフォルトでは__cdeclが使われる。__stdcallにするのはよく分からない。EXTERN_Cは関数の名前をC的につけることを意味させるものらしい。

Windows APIステップバイステップ 〜WINAPI呼び出し規約について〜
ITエンジニアの技術メモ C言語の関数呼び出し - extern "C"
DllGetClassObject の実装 (mixi 日記アーカイブ)

7.I〜sinkとITfSource

I〜sinkというインターフェースはコールバック用らしい。ITfSource->AdviseSinkは其れにイベントを監視させるためのメソッド?。キー入力に関してはpKeystrokeMgr->AdviseKeyEventSinkを使う。
ITfSource Interface (Windows)
ITfKeystrokeMgr Interface (Windows)

追記:2009/3/28

8.CoCreateInstance

CoCreateInstanceはIDLのコクラスをnewするためのもの・・・だと思う。IDLのコクラスはC++のクラスではないのでnewできないのでこれを使う。

関数リファレンス - CoCreateInstance

9.DllGetClassObject、CClassFactory

プロセス(スレッド?タスク?)ごとにIMEインスタンス(ここではCCaseTextService)が必要となる。DllGetClassObjectはインスタンスを要求するときに呼ばれる?もので、CCaseTextServiceをnewするようなファクトリクラス(CClassFactory)を返している。

第3回 マルチタスクに不可欠な同期の仕組みを学ぶ:ITpro
[OLE] OLE スレッド モデルの概要としくみ

TSFのサンプル?

1.前回やったことと今回やること

 WindowsにおけるIM(InputMethod)に基礎技術となるCOMとTSFについて解説した。C++によるWindows開発の環境を無料で構築した。WindowsSDKのサンプルにある3つのTSFのサンプルの一つ「TSFCase」をビルドし、できたDLLをIMとしてWindowsに登録した。今回はDLL、regsvr32、レジストリの登録、TSF、言語プロファイル、カテゴリの登録までの調べたことを報告する。

2.DLL

 前回ビルドしたらDLLができた。DLLとはプログラムの汎用部品である。(参考資料1)外部に公開する関数と内部のみで使われる関数を分離することでカプセル化される。途中でdefファイルを読み込む処理をしたが、defファイルにはDLLが外部に公開する関数の名前が書かれている。以下にdefファイルの中身を示す。

LIBRARY Case.dll

EXPORTS
        DllGetClassObject               PRIVATE
        DllCanUnloadNow                 PRIVATE
        DllRegisterServer               PRIVATE
        DllUnregisterServer             PRIVATE

defファイルについての詳細は省略する。(参考資料2)

2.regsvr32

 できたDLLをコマンドプロンプトからregsvr32で処理した。実際にはregsvr32は以下の処理を実行しているだけ。(参考資料3)

  1. OleInitialize
  2. LoadLibrary DLL を読み込む
  3. DllRegisterServer または DllUnregisterServer
  4. FreeLibrary
  5. OleUninitialize

 OleInitializeとOleUninitializeは何をやっているかわからない。参考資料4と8に英語で説明あり。LoadLibraryが実行されると、DLL内のDLLMain関数を呼び出す(参考資料5,6)。DllRegisterServerはDLL内のDllRegisterServer関数を読み込む。DllUnregisterServerも同様。FreeLibraryが実行されるとDLLMainが実行される。(参考資料7)TSFCaseではDLLMainがdllmain.cppに、DllRegisterServer等がserver.cppにある。

3.レジストリの登録

 レジストリに登録する作業は、DllRegisterServer関数にて自前で行わなくてはならない。TSFCaseではDllRegisterServerにてCCaseTextService::RegisterServer()を実行して、そこでレジストリの登録処理を行っている。レジストリの処理に使う関数は以下の5つである(参考資料9)。

  • RegCreateKeyEx レジストリのキーを作ります。
  • RegOpenKeyEx  レジストリのキーをオープン(使えるように)します。
  • RegCloseKey   レジストリのキーをクローズ(使えないように)します。
  • RegQueryValueEx レジストリの値を読みます。
  • RegSetValueEx  レジストリの値を書き込みます。

引数が多いので注意のこと。

4.TSF、言語プロファイル、カテゴリの登録

レジストリの登録のほかにTSFへテキスト サービスの登録、言語プロファイルの登録、カテゴリの登録をする必要がある。(参考資料10)

テキスト サービスの登録

作成したテキストサービスのIDを指定して登録する。InputProcessProfilesインターフェースのRegister関数を使用する。TSFCaseではregister.cppのCCaseTextService::RegisterProfiles内に処理があり、DllRegisterServerから呼び出されている。

言語プロファイルの登録

JPとかENなどの、どの言語なのかを登録する。ITfInputProcessorProfilesインターフェースのAddLanguageProfileを使用する。TSFCaseではregister.cppのCCaseTextService::RegisterProfiles内に処理があり、DllRegisterServerから呼び出されている。

カテゴリの登録

使用目的だろうか?参考資料11は明らかに編集ミスだろう。何もかいていない。以下msctf.cppより抽出したものを示す。

EXTERN_C const GUID GUID_TFCAT_CATEGORY_OF_TIP;
EXTERN_C const GUID GUID_TFCAT_TIP_KEYBOARD;
EXTERN_C const GUID GUID_TFCAT_TIP_SPEECH;
EXTERN_C const GUID GUID_TFCAT_TIP_HANDWRITING;
EXTERN_C const GUID GUID_TFCAT_TIPCAP_SECUREMODE;
EXTERN_C const GUID GUID_TFCAT_TIPCAP_UIELEMENTENABLED;
EXTERN_C const GUID GUID_TFCAT_TIPCAP_INPUTMODECOMPARTMENT;
EXTERN_C const GUID GUID_TFCAT_TIPCAP_COMLESS;
EXTERN_C const GUID GUID_TFCAT_TIPCAP_WOW16;

EXTERN_C const GUID GUID_TFCAT_PROP_AUDIODATA;
EXTERN_C const GUID GUID_TFCAT_PROP_INKDATA;

EXTERN_C const GUID GUID_TFCAT_PROPSTYLE_CUSTOM;
EXTERN_C const GUID GUID_TFCAT_PROPSTYLE_STATIC;
EXTERN_C const GUID GUID_TFCAT_PROPSTYLE_STATICCOMPACT;

EXTERN_C const GUID GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER;
EXTERN_C const GUID GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY;

5.まとめ

以上のことがdllをregsvr32した時に行われる処理である。

雑記

Twitterはじめました。Twitter / gnagaoka

C++をかじる

1.goto文

ラベルまで処理を飛ばす。

printf("a");
goto Exit;
printf("b");//実行されない。
Exit:
 printf("c");

goto文

2.インライン関数

マクロ→文字列置換、インライン関数→関数挿入
c++ inline関数

3.アクセス指定子

public:公開
private:非公開
protected:継承先から見てpublic、それ以外private
C++編(言語解説) 第14章 protectedメンバ

4.継承、クラス、

class クラス名 : public 継承元クラス名1,継承元クラス名2 {
アクセス指定子:
 クラス名(){
  処理
 }
 ~クラス名(){
  処理
 }
  返り値 メンバ関数名1(引数の型 引数の名前);
 virtual 返り値 メンバ関数名2(引数の型 引数の名前);
};

返り値 クラス名::メンバ関数名1(引数の型 引数の名前){
 処理内容
}

返り値 クラス名::メンバ関数名2(引数の型 引数の名前){
 処理内容
}

多重継承の仕組み。メンバ関数はクラスの内側、もしくは外側で定義する。クラス名のメンバ関数はコンストラクタ。それの頭に(~)が付いているのはデストラクタ。デストラクタはオブジェクトが破棄される時に呼ばれる。外側で定義する場合はスコープ解決演算子(::)を使う。クラスの最後にセミコロン(;)を入れるのを忘れない。virtualをつけると継承先でオーバーライドできる。
C++ Class
C++編(言語解説) 第9章 オーバーライド

5.friend

アクセス指定子とは無関係にアクセスできる。
C++編(言語解説) 第22章 フレンドクラスとフレンド関数

6.慣習的なアンダーバー

プライベートなメンバ関数には名前の頭にアンダーバー(_)をつけることがある。もしくはスペース( )の代わり。

7.NULL、FALSE、TRUE

大文字になっているのはマクロだから
NULLについて

8.コンストラクタ初期化子

継承元のコンストラクタに投げる。そんで自分も処理する。

class CUpdateTextEditSession : public CEditSessionBase{
public:
    CUpdateTextEditSession(ITfContext *pContext, ITfRange *pRange, CSnoopWnd *pSnoopWnd) : CEditSessionBase(pContext){
        _pSnoopWnd = pSnoopWnd;
        _pRange = pRange;
        if (_pRange != NULL)
        {
            _pRange->AddRef();
        }
    }
〜

コンストラクタ(後編)

9.deleteとnew

mallocとfree→newとdelete。普通に用意した場合とどこが違うのか?→メモリのどこにおかれるかの違い。
>>>ttp://d.hatena.ne.jp/arvitos/20080728/1217249837

10.**

・int* a= new int[2];
スタック          ヒープ
a:[s100]:[h100]←────[h100]:""
                       [h101]:""

・int** a= new int*[2];
スタック          ヒープ
a:[s100]:[h100]←────[h100]:[ ]
                       [h101]:[ ]

ポインタのポインタ
*(アスタリスク)の使い方について - C++ Builder / Turbo C++ 質問の木

11.const

変えないよと宣言する。≠#define
C++の基礎 : const 修飾子

13.charとWCHAR(L"文字列")とTCHAR(TEXT("文字列"))

char→1バイト。Asciiに。
WCHAR→2バイト。Unicodeに。
TCHAR→ビルドによって大きさが変わる。

char、wchar_t(WCHAR)とTCHAR (dinop.com)

次回

             /)
           ///)
          /,.=゙''"/
   /     i f ,.r='"-‐'つ____   こまけぇこたぁいいんだよ!!
  /      /   _,.-‐'~/⌒  ⌒\
    /   ,i   ,二ニ⊃( ●). (●)\
   /    ノ    il゙フ::::::⌒(__人__)⌒::::: \
      ,イ「ト、  ,!,!|     |r┬-|     |
     / iトヾヽ_/ィ"\      `ー'´     /

次回はCOMとTSF

ゆとりで学ぶ 共通鍵と公開鍵

         ∧ ∧
        (・∀ ・) <通信の暗号化ってなんだろ
         ノ(  )ヽ
         <  >


共通鍵暗号 - Wikipedia
公開鍵暗号 - Wikipedia
基礎知識 SSLの仕組み

         ∧ ∧
       ヽ(・∀ ・)ノ <ぜんぜんわかんねーよ。
       (( ノ(  )ヽ ))
         <  >


        `゙`・;`'  バチュン
         ノ(  )ヽ
         <  >


         __O)二)))(・ω・`)ググレカス
   0二━━ )____)┐ノヽ
         A   ||ミ|\ くく

調べてみました。

1.共通鍵暗号方式

暗号鍵と複合鍵が同じなもの。

┌─────────────┐
│IBM −−−−−→ HAL    .│
└─────────────┘
「IBM」という文字列のぞれぞれのアルファベットを1戻してやる(BならAに、AならZに)と「HAL」という文字列になる。

┌─────────────┐
│HAL −−−−−→ IBM    .│
└─────────────┘
「HAL」という文字列のぞれぞれのアルファベットを1進めてやる(AならBに、ZならAに)と「IBM」という文字列になる。

ここでは鍵が「1」となる。
 鍵をもっと複雑にしたり(12とか54とか)、変換方法を複雑にしたり(10をかけたり2を足したり)すると複雑な(解析されにくい)暗号方式となる。

お互いが鍵を知っていることで秘密が保持される。逆の通信も同じ。

IBM > HALにして送るよ
  ∧_∧                            ∧∧
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <HAL > IBM。なるほど。
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  ( ゚∀゚) <HAL ?なんのこっちゃ?

有名なものにDESとAESがある。以下のサイトでDESを試すことができる。
Sample of des.js

2.共通鍵方式の問題点

                      ∧ ∧    <なるほど、分かった気がする
                     (・∀ ・) =3
         ノ(  )ヽ 
         <  >


         ∧ ∧    <これでもう終わり?
        (・∀ ・) カチッ
         ノ(  )ヽ 
         <  >


         __O)二)))(・ω・#) いいや、共通鍵には重大な問題がある。
   0二━━ )____)┐ノヽ それはお互いが鍵を予め知っておかなくてはならないという点だ。
         A   ||ミ|\ くく


        `゙`・;`'  バチュン
         ノ`゙`・;`'  バチュン
         < ``'  バチュン


例えば鍵がばれてしまったとする。

IBM > HALにして送るよ
  ∧_∧                            ∧∧
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <HAL > IBM。なるほど。
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  ( ゚∀゚) <HAL > IBM。ふむふむ。

鍵を交換する必要があるが、一方が勝手に交換することはできない。

  ∧_∧
 (;´∀`)<( ゚∀゚)の口ぶり。あれは(,,゚Д゚)とのやり取りを知ってるって顔だな。

  ∧_∧
 ( ´∀`)<鍵を「2」にするもな。


IBM > GZKにして送るよ
  ∧_∧                            ∧∧   #鍵が「1」だと思っている。
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <GZK > HAL。なんのこっちゃ
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  ( ゚∀゚) <GZK > HAL。なんのこっちゃ。

 これを解決するには(,,゚Д゚)にだけこっそり、鍵「2」を教える必要がある。近所に住んでいるなら口で伝えればいいけど、東京と札幌の二人ではそうも行かない。以前の鍵「1」を使えば(,,゚Д゚)に鍵が「2」になったよと伝えることができるが、其れだと( ゚∀゚)にも鍵が「2」であることがばれてしまう。

(・ω・`) この問題を解決するために生まれたのが公開鍵暗号方式だ。

         /:;;
         (・::;
         ノ(::;
         <;  

2.公開鍵暗号方式

〜ある掲示板にて

  ∧_∧
 ( ´∀`)つ■ <ギコさん、( ゚∀゚)のとんでもない秘密を知りました。( ゚∀゚)に知られないように送りたいんですが。

  ∧∧
  (,,゚Д゚) <コイツを使ってくれ。

  ______
 ∠三Ω三三三/\
  \ \     \ \
   \/____\/
   /|      /|    
  /  |    /./|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/

  ∧∧
  (,,゚Д゚) <こいつの中にモノを入れて蓋を閉めれば、 後は俺の持っている鍵♂でしか開けられない。

 (#゚∀゚)<・・・

  ∧_∧
 ( ´∀`)<■を入れて

  ______
 ∠三Ω三三三/\
  \ \     \ \
   \/____\/
   /|      /|
  /  | ■  /./|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/


  ∧_∧
 ( ´∀`)<箱を閉じると

    ______
   /     //|
 ∠三Ω三三///|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/


箱をおくるよー
  ∧_∧                            ∧∧   
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <鍵♂を使って箱を開ける。■があると。
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  (#゚∀゚) <くっそー開かない。中には何が入っているんだ?

 共通鍵の用に送信者( ´∀`)と受信者(,,゚Д゚)が同じ鍵を持つ必要が無い。受信者(,,゚Д゚)が鍵と箱のセットを自由に用意できるため、利便性があがる。
 誰でもが(,,゚Д゚)に暗号化したモノを送ることができるといい。箱は広く公開しても問題はない。

  ∧∧
  (,,゚Д゚)<今度から俺にやばいものを送る時はこれに入れて送るように!
  ______
 ∠三Ω三三三/\
  \ \     \ \
   \/____\/
   /|      /|    
  /  |    /./|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/

この「箱」に当たるものを「公開鍵」という。

    ♂

閉じた箱を開く鍵は絶対に知られてはならない。これにあたるものを「秘密鍵」という。


みんなが秘密鍵と公開鍵を持って、公開鍵を広く公開しておけば、互いに暗号通信ができる仕組み。
このような仕組みを持つものにRSA暗号方式がある。

(・ω・`) 以上が公開鍵暗号方式の概要だ。

         ∧/;;
         (・∀::;  <比喩だらけで逆にわかんなかった。
         ノ( ::;
         < ;;

(・ω・`) 仕方が無い。所詮は比喩だから。そういう時はRSA暗号の計算をやってみるといい。

         ∧∧
         (・∀・;  <これで終わり?
         ノ(  );;:
         <  >

   ,_,    tr xiニニI     .        
 <ii,、lニニニlニ(・ω・ )ニニl二l  <いや、共通鍵方式と公開鍵方式の組み合わせがまだ残っている。
       '`i,∃lと,lIi;`          
         i:k-`l            
         !];-!I!           
         レ^し ,             
                              
                                
          (⌒`r          フキトベ!マタンキ            
  ,,_,     (⌒`),;,;,从     xiニニI    .    ⌒`),  
 <iiノ=, 三 (⌒`-= : :'lニニニlニ(ω・ )ニニl二l≡`:⌒`)  
  ゛    ''゛(⌒`'`'`W   '`,∃と,lIi;`     '' ⌒`),  
        ''゛         'J`,,_て                     

AAの出展

3.共通鍵と公開鍵方式の組み合わせ

共通鍵方式ではお互いに鍵を安全に伝えることができないのが問題だった。
そこで、公開鍵方式を利用して共通鍵方式の「鍵」を暗号化して送ることにする。

  ∧_∧
 ( ´∀`)<共通鍵方式の鍵「2」を(,,゚Д゚)に送るもなー

  ______
 ∠三Ω三三三/\
  \ \     \ \
   \/____\/
   /|      /|    
  /  | 2  /./|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/

    ______
   /     //|
 ∠三Ω三三///|
 |三三三三三|//|
 |三三三三三|//
 |三三三三三|/


箱をおくるよー
  ∧_∧                            ∧∧   
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <鍵♂を使って箱を開ける。共通鍵方式の鍵は「2」だな
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  (#゚∀゚) <くっそー開かない。中には何が入っているんだ?

鍵が送られたら其れを使って共通鍵方式で通信をする。

IBM > GZKにして送るよ
  ∧_∧                            ∧∧
 ( ´∀`) −−−┬−−−−−−−−−−−→   (,,゚Д゚) <GZK > IBM。なるほど。
         .   │
         .   │傍受                  _ 
         .   └−−−−−−−−−−−→  ( ;∀;) <GZK? だめだー。共通鍵方式の鍵が分からない
                                      元の文字列がわからないよー。

これに改竄防止のためのHash値をつけたり、成りすましのための証明書を貼り付けたりするするとSSLの基礎部分になる。

4.aSSLを試してみる

 ∫  ∫ ∬
.;.;..;;.;::::.;::.;::::.;.;.;
 ;;;;:::;;;;;:::;:;;::;;
        .  iニニI     .        
         (ω・ ) ヤリスギタカナ....
         (`i,'lと,lIi;`          
         i:k-`l            
         !];-!I!           
         レ^し ,             


 ∧ ∧ ∬
=@..;;;@@=3::.;::.;:@=3.;
 ;;;;;:::::@=3:::;;;:
        .  iニニI     .
         (・ω・ ) ン?
         (`i,'lと,lIi;`          
         i:k-`l            
         !];-!I!           
         レ^し ,             

  ∧ ∧ 
=@(・∀ ・) ;@=3;
;;:=@( ;;@=3;;;

        .  iニニI     .        
         (ω゚ ) ・・・
         (`i,'lと,lIi;`          
         i:k-`l            
         !];-!I!           
         レ^し ,                

 SSLは高度な安全を提供するが、サーバーが対応していないとできなかったり、証明書にお金が掛かったりして初心者には敷居が高い。またhttpsからhttpにまたその逆へ通信が送れない。これはブックマークレットには困る。
 今回はJavaScriptIMEの暗号化の実装にJavaScriptPHPを利用して「3.共通鍵と公開鍵方式の組み合わせ」をエミュレートするaSSL - Ajax Secure Service Layerというものを使った。名前にSSLと入っているが、単なるエミュレートなので全く違うものと考えていい。安全性は十分に保障されない。また、phpスクリプトもお世辞にも出来がよくないので使う際には自己責任でお願いしたい。

phpスクリプトの変更点

5.サンプル

RSA秘密鍵及び公開鍵は配布されたままで変更していません。SocialIMEで「きたー」などと変換するとバグります。クッキーを使用します。IE7ではOKを出してください。
!人柱注意!=>http://www.geocities.jp/project_the_tower2/web_mozi/nihongoime/17/

6.次回の実装

〜バックスペース
〜マウスイベント