[文字コード] 一般化可変長整数
一般化可変長整数
国際化ドメイン名では, マルチバイト文字のドメイン名がDNS上でASCII文字にエンコードされてやり取りが行われる.
そのときに使われるエンコーディング方式はPunycodeと呼ばれ, Punycodeでのエンコード・デコード処理の一部にこの一般化可変長整数と呼ばれる仕組みが利用されている.
数値と一般化可変長整数の対応を以下に示す.
数値(10進数表記) | 一般化可変長整数 |
---|---|
0 | a |
1 | ba |
2 | ca |
... | ... |
34 | 8a |
35 | 9a |
36 | bba |
37 | cba |
... | ... |
70 | 9ba |
71 | bca |
72 | cca |
... | ... |
1260 | 99a |
1261 | bbb |
1262 | cbb |
... | ... |
31885 | 99z |
31886 | bb0a |
... | ... |
44135 | 999a |
44136 | bb0b |
... | ... |
一般化可変長整数では, aが0, zが25, 0が26, 9が35を表し, リトルエンディアンのため, 一番右側の桁が最上位桁となる.
また, 一般化可変長整数には桁ごとに閾値が設定されており, 数値(10進数表記)から一般化可変長整数への変換は以下の式によって求められる.
数値(10進数表記) = 1桁目 + 2桁目 * 35 + 3桁目 * 1225 + 4桁目 * 12250
例えば, ひらがなの「あ」の一般化可変長整数l8j
を10進数の整数に変換する場合, 11 + 34 * 35 + 9 * 1225 = 12226
となる.
Punycodeでは, 1文字目は128からの差分で文字を表現するルールとなっているため, 128 + 12226 = 12354 = 0x3042 = U+3042
となり, Unicodeでの「あ」を表現しているということが分かる.
また, 各桁に次の文字が使われていたらそこで数値の終了を表す.
桁 | 数値 |
---|---|
1 | a |
2 | a |
3 | a - z |
4 | a - z |
さらに, マルチバイト文字の2文字目以降は桁の重み付けのルールが変わる.
次も近くの文字が採用されるという前提でエンコード後の表現ができるだけ短くなるように
- 数値(10進数表記)から一般化可変長整数への変換式
- 数値の終了を意味する文字
が変更される.
[文字コード] Punycode
Punycode
Punycode(ピュニコード, プニコード)とは, 国際化ドメイン名で使用されるエンコーディング方式で, RFC 3492で定義され, RFC 5891で更新されている.
Adam M. Costello氏によって考案され, 仮称はAMC-ACE-Zであった.
ASCII文字で対応できる文字をそのまま利用することで全体的な文字数を減らす努力がなされている.
また, Base64などに比べ高い圧縮率のエンコーディング方式である.
デコード手順
xn--3B-ww4c5e180e575a65lsy2b
を例にデコードを行う.
最終的なデコード結果は『3年B組金八先生』となる.
1. 接頭辞を取る
Punycodeでエンコードされた文字列は接頭辞としてxn--
が付加されるため, デコード時にはこれを取り外す.
xn--3B-ww4c5e180e575a65lsy2b
-> 3B-ww4c5e180e575a65lsy2b
2. ASCII文字とマルチバイト文字を分ける
3B-ww4c5e180e575a65lsy2b
の内, -(ハイフン)よりも前の文字はASCII文字であるため, デコードの対象にならない.
3B-ww4c5e180e575a65lsy2b
-> ww4c5e180e575a65lsy2b
3. デコード処理
ww4c5e180e575a65lsy2b
の部分は一般化可変長整数と呼ばれる仕組みでエンコードされているため, これを通常の10進数に戻す.
ww4c5e180e575a65lsy2b
-> 62042
, 139
, 16683
, 34821
, 14592
, 42088
次に, 62042
のUnicodeスカラ値と挿入位置を計算する.
// Unicodeスカラ値の計算 n = 128 n += 62042 / 3 n = 20808 = U+5148 = 先 // 挿入位置の計算 62042 mod 3 = 2
この計算から, nが「先」の文字コードで挿入位置が2であることが分かったため,
添字 | 文字 |
---|---|
0 | 3 |
1 | B |
2 | 先 |
となる.
次に, 139
のUnicodeスカラ値と挿入位置を計算する.
// Unicodeスカラ値の計算 n += (((2 + 1) + 139) / 4) n = 20808 + 35 n = 20843 = U+516B = 八 // 挿入位置の計算 ((2 + 1) + 139) / 4 = 2
このとき, (((2 + 1) + 139) / 4)
における2
は62042 mod 3 = 2
の2
で, 1
は処理上加算される値である.
この計算から, nが「八」の文字コードで挿入位置が2であることが分かったため,
添字 | 文字 |
---|---|
0 | 3 |
1 | B |
2 | 八 |
3 | 先 |
となる.
続く16683
, 34821
, 14592
, 42088
のUnicodeスカラ値と挿入位置も同様の計算方法によって求められる.
エンコード手順
最終的なエンコード結果は"xn--3B-ww4c5e180e575a65lsy2b"となる.
1. 数値化する
文字 | 16進数表記 | 10進数表記 |
---|---|---|
3 | U+0033 | 51 |
年 | U+5E74 | 24180 |
B | U+0042 | 66 |
組 | U+7D44 | 32068 |
金 | U+91D1 | 37329 |
八 | U+516B | 20843 |
先 | U+5148 | 20808 |
生 | U+751F | 29983 |
2. ASCII文字とマルチバイト文字を分ける
文字 | 16進数表記 | 10進数表記 |
---|---|---|
3 | U+0033 | 51 |
B | U+0042 | 66 |
文字 | 16進数表記 | 10進数表記 |
---|---|---|
年 | U+5E74 | 24180 |
組 | U+7D44 | 32068 |
金 | U+91D1 | 37329 |
八 | U+516B | 20843 |
先 | U+5148 | 20808 |
生 | U+751F | 29983 |
3. マルチバイト文字をUnicodeスカラ値順に昇順ソートする
文字 | 16進数表記 | 10進数表記 |
---|---|---|
先 | U+5148 | 20808 |
八 | U+516B | 20843 |
年 | U+5E74 | 24180 |
生 | U+751F | 29983 |
組 | U+7D44 | 32068 |
金 | U+91D1 | 37329 |
4. エンコード処理
delta, n, m, c, hの5つの変数を用いる.
- delta: 各Unicodeスカラ値のエンコード後の値を格納する変数
- n: 次のソートされたUnicodeスカラ値を格納するときに現在のUnicodeスカラ値を格納しておく変数
- m: ソートされたUnicodeスカラ値を順に格納する変数
- c: ソート前のUnicodeスカラ値を順に格納する変数
- h: 何文字目の処理かを格納する変数
なお, deltaの初期値は0であるが, ソート後のUnicodeスカラ値を選択したときにdelta += (m - n) * h
が格納される.
また, nの初期値は128
である.
hの初期値は今回の場合,
添字 | 文字 |
---|---|
0 | 3 |
1 | B |
のように0文字目と1文字目はすでに決まっているので2が格納される.
// 初期化 n = 128 h = 2 delta = 0 // deltaの計算 h++ delta += (m - n) * h delta += (20808 - 128) * 3 delta = 62040 // nの計算 n += 1 n = 20809
次にソート前のUnicodeスカラ値の並びである51
, 24180
, 66
, 32068
, 37329
, 20843
, 20808
, 29983
とソート後のUnicodeスカラ値の1つ目である20808
を順に比較する.
文字 | 10進数表記 | 比較 | 比較対象「先」 | delta | h |
---|---|---|---|---|---|
3 | 51 | < | 20808 | 62041 | 3 |
年 | 24180 | > | 20808 | 62041 | 3 |
B | 66 | < | 20808 | 62042 | 3 |
組 | 32068 | > | 20808 | 62042 | 3 |
金 | 37329 | > | 20808 | 62042 | 3 |
八 | 20843 | > | 20808 | 62042 | 3 |
先 | 20808 | = | 20808 | 0 | 4 |
生 | 29983 | > | 20808 | 0 | 4 |
// deltaの計算 delta = (m - n) * h delta += (20843 - 20809) * 4 delta = 137 // nの計算 n += 1 n = 20844
先と同じように比較する.
文字 | 10進数表記 | 比較 | 比較対象「先」 | delta | h |
---|---|---|---|---|---|
3 | 51 | < | 20843 | 138 | 4 |
年 | 24180 | > | 20843 | 138 | 4 |
B | 66 | < | 20843 | 139 | 4 |
組 | 32068 | > | 20843 | 139 | 4 |
金 | 37329 | > | 20843 | 139 | 4 |
八 | 20843 | = | 20843 | 0 | 5 |
先 | 20808 | < | 20843 | 1 | 5 |
生 | 29983 | > | 20808 | 1 | 5 |
同様にdelta
の計算を続けると, 最終的に62042
, 139
, 16683
, 34821
, 14592
, 42088
となる.
これに一般化可変長引数の仕組みを利用して変換し, 接頭辞と3B
を繋げると, xn--3B-ww4c5e180e575a65lsy2b
となる.
[文字コード] ホモグラフ攻撃
ホモグラフ攻撃
ホモグラフ攻撃(同形異字語攻撃)とは, URLのホスト名の文字として, 真正なサイトに酷似した異なる文字を用いて偽装し, 偽サイトに誘導するスプーフィングの一種である.
IDNホモグラフ攻撃
国際化ドメイン名(IDN: Internationalized Domain Name)を使用したホモグラフ攻撃のことを特にIDNホモグラフ攻撃と呼ぶことがある.
ドメイン名に使用できる文字は, 原則としてアルファベット(A - Z), 数字(0 - 9), ハイフン(-), ドット(.)のみであるが, 国際化ドメイン名ではUnicode及び非ASCII文字をPunycodeによりエンコードして利用できる.
半角英字(ラテン語)と形が酷似した
などが悪用される.
Unicodeにはゼロ幅スペースやゼロ幅非接合子, 双方向テキストに関する制御コードなどの悪用できそうな文字が定義されているが, これらはおおむね国際化ドメインには使用できない.
ホモグラフ攻撃の例
正: GOOGLE.COM 偽: G0OGLE.COM(半角数字の0(ゼロ)が半角英大文字のO(オー)に偽装) 正: google.com 偽: googIe.com(半角英大文字のI(アイ)が半角英小文字のl(エル)に偽装) 正: microsoft.com 偽: rnicrosoft.com(半角英小文字のr(アール)とn(エヌ)を繋げて半角英小文字m(エム)に偽装) 正: apple.com 偽: appie.com(半角英小文字のi(アイ)が半角英大文字のl(エル)に偽装)
IDNホモグラフ攻撃の例
正: wikipedia.org 偽: wikipedia.org(全角英小文字のa(エー)が半角英小文字のa(エー)に偽装) 正: wikipedia.org 偽: wíkipedia.org(アキュート・アクセントを付加した英小文字í(アイ)が半角英小文字のi(アイ)に偽装) 正: 朝日.com 義: 朝曰.com(曰が日に偽装)
[PHP] コンストラクタとデストラクタ
コンストラクタ
コンストラクタはクラスをインスタンス化したときに暗黙的にコールされる.
PHPでは__construct()
というマジックメソッドで実現されている.
コンストラクタは一般的にプロパティの初期化などに用いられる.
<?php class Foo { public function __construct($name = 'Anonymous') { $this->name = $name; } }
デストラクタ
デストラクタはインスタンスが消滅するときに暗黙的にコールされる.
インスタンスの消滅するときとは, 具体的にはどの変数からも参照されなくなったときのことを指す.
PHPでは__destruct()
というマジックメソッドで実現されている.
<?php class Foo { public function __destruct() { echo 'This instance has been deleted.' } }
[アーキテクチャ] x86アーキテクチャ
x86アーキテクチャ
x86アーキテクチャとは, Intel社が開発したマイクロプロセッサのシリーズ名.
このシリーズのプロセッサは8086 -> 80186 -> 80286 -> i386 -> i486 -> Pentiumの順にリリースされたため, この名前で呼ばれている.
8086
8086は, 1978年に発売されたx86シリーズ初のプロセッサで, 16ビットプロセッサである.
従来の8ビットプロセッサ(8008, 8080, 8085)では接続可能なメモリが最大で64KBと少ない点を補うべく, データバス幅が16ビット, アドレスバスが20ビットに拡張され, 接続できるメモリの容量が最大1MBに増加した.
80186
80186は, 1982年に発売された16ビットプロセッサである.
8086にクロックジェネレータ, 割り込みコントローラ, タイマ, DMAコントローラ, チップセレクタなどの周辺回路を統合し, 1チップ化したことで, コストの低下と消費電力の削減が実現した.
DMAコントローラーが従来と異なることから, 当初見込んでいたデスクトップPCとしての採用は殆どなく, 8086の後継のプロセッサとしては失敗に終わったが, 消費電力を極力削減する必要のあるモバイルPCや組み込み機器などに採用された.
他にも, CMOS化による消費電力の削減を実現した80C186, 接続できるメモリを16MBに拡張した18677, 動作電圧を3Vに下げパワーマネジメント機能を追加した80C186EX, 動作クロックを25MHzまで引き上げられるようにした80C186XLなどの派生製品が存在する.
80286
80286は, 1982年に発売された16ビットプロセッサである.
8086を大幅に改良し, 約4倍の高速化を実現した.
従来互換のリアルモードに加えて新たに高速なプロテクトモードが追加され, アドレスバスも24ビットに拡張され, 16MBまでのメモリを扱えるようになった.
また, 80286にはPGA(Pin Grid Array)と呼ばれるパッケージの裏にピンが出ているタイプ, PLCC(Plastic Leaded Chip Carrier)と呼ばれるパッケージの側面からピンが出ているタイプ, LCC(Leadless Chip Carrier)と呼ばれるパッケージの裏に端子が並ぶ板状タイプの3種類が存在した.
8086の流れで爆発的にヒットしたため, Intelの他にもAMDやIBMなども互換プロセッサを製造した.
i386
i386(80386)は, 80286の後継で1985年に発売されたx86シリーズ初の32ビットプロセッサである.
他にも, 1988年にデータバス幅を16ビットとした廉価版のi386SX(80386SX), それに伴いi386から改称されたi386DX(80386DX), ノートPCに適するように安全なレジューム機能やクロックの停止機能が追加されたi386SL(80386SL)などの派生製品が存在する.
レジスタのデータ長が従来の16ビットから32ビットに拡張されたため, ソフトウェアが対応していればより高速な処理が可能となった.
従来との互換性も確保されているため, 16ビットプロセッサ向けのソフトウェアも殆どそのまま動作する.
i386で導入された32ビットの命令セットアーキテクチャ(ISA: Instruction Set Architecture)はその後も引き継がれている.
i486
i486(80486)は, i386の後継で1989年に発売されたプロセッサである.
基本的にはi386の仕様を受け継いでいるが, 大幅な性能の向上が図られ, 従来は外部に付属していた数値演算用のコプロセッサであるFPU(Floating-Point Unit)やキャッシュメモリをプロセッサ内部の回路に統合するなどの改良が施された.
他にも, FPUを省いた廉価版のi486SX(80486SX), それに伴いi486から改称されたi486DX(80486DX), i486SXとi486DXのそれぞれでプロセッサ内部が外部クロックの2倍で動作するi486SX2とi486DX2, プロセッサ内部が外部クロックの3倍で動作するi486DX4, ノートPCに適したi486SLなどの派生製品が存在する.
Pentium
Pentium(ペンティアム)は, i486の後継で1993年に発売されたプロセッサである.
8086以降のプロセッサとの互換性を維持しつつ高速化が図られている.
MMX機能を追加した製品はMMX Pentiumと呼ばれ, これと区別するために旧製品は無印Pentiumなどと呼ばれることがある.
i486DX2と比べ, 約3倍にあたる310万個のトランジスタから構成され, 内部処理は32ビットだが, データバス幅は64ビットである.
パイプライン方式により2つの命令を並列実行できるようになっている.
[PHP] ショートタグ
short_open_tag = on
short_open_tag = on
は, <?php
を<?
で始められるようにするための, php.iniの設定.
short_open_tag = off
が推奨であるのは, XMLの記法である<? ?>
が誤動作する可能性を排除するためである.
現状でもshort_open_tag = off
が推奨されている.
ショートタグ
<?=
は<?php echo
のショートタグで, PHP 5.4.0以降, short_open_tag
の設定に関わらず有効である.
すなわち, 非推奨であるshort_open_tag = on
に影響されず, 開始タグを省略して記述できる.