平成 12 年度
学士学位論文モバイルコンテンツ課金プロトコル
Billing Protocols in Mobile Communication
Environments

1010374

大石 恭裕

指導教員

清水 明宏

2001 年 2 月 5 日
高知工科大学 情報システム工学科

要 旨

モバイルコンテンツ課金プロトコル
大石 恭裕

本研究室では，コンテンツ流通支援方式の研究を行っている．近年，i-mode に代表される携帯電話でのコンテンツ流通が注目を浴びており，課金システムの開発が急務となっている．コンテンツを円滑に流通させるために，課金システムは重要であり，その中核として認証方式が位置付けられる．
本検討の目的は，本研究室で提案している SAS(Simple And Secure) と呼ぶワンタイム
パスワード認証プロトコル，SAS をベースとした小額課金システムである SAS コインを，
モバイルコミュニケーション，特に携帯電話等の処理能力の低い端末へ適用する際の最適な実装方式を確立することである．
本検討では，SAS に対する問題点を指摘し，それらを解決する SAS-K を提案し，評価を行った．さらに，SAS-K を用いた小額課金システムである SAS コインのプロトコルについて考察した．実装フィールドとして，ユーザ，コンテンツプロバイダ，課金センタの三者から構成される小額課金システムのプラットフォームを作成し，その環境において SAS-K お
よび SAS コインの実装を行った．
提案方式 SAS-K を利用することにより，モバイル環境を含むあらゆる環境において，極めて安全な認証を行うことを可能とした．

キーワード

ワンタイムパスワード，パスワード認証方式，SAS，盗聴，なりすまし–i–Abstract
Billing Protocols in Mobile Communication Environments
Yasuhiro OISHI

We are studying on contents communications systems. Contents communication
using “browser phones”, particularly i-mode, have been getting popular. Billing systems
are located as many functions in contents communications systems.
The research is aiming to install security functions, which are a one-time password
authentication protocol, called SAS, and billing system, called SAS-Coin, to mobile
communication environments with lower processing abilities.
First, SAS-K, a new type of one-time password authentication method, is proposed
to cope with some attacks on SAS. Next, the SAS-Coin is studied, which is a simple
billing method applying SAS-K. The SAS-K and SAS-Coin protocols are installed on aplatform which has three players, Customer, Vendor, and Broker.
SAS-K, and an SAS-K based billing method, SAS-Coin have brought secure functions to mobile communications environments.
key words

one-time password ，password authentication ，SAS，wiretapping，inper-

sonation– ii –

目次
第1章

はじめに

1

第2章

SAS，SAS コインの問題点

4

2.1

2.2

第3章

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4

2.1.1

すり替え攻撃 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4

2.1.2

でたらめ攻撃 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5

2.1.3

同期問題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6

SAS コインの問題点と改良方針 . . . . . . . . . . . . . . . . . . . . . . .

6

2.2.1

SAS コインの問題点. . . . . . . . . . . . . . . . . . . . . . . . .

6

2.2.2

改良方針 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6

SAS の問題点

SAS-K の提案

8

3.1

攻撃対策 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

3.2

同期対策 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

SAS-K の評価

12

安全性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

4.1.1

認証情報の盗聴 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

4.1.2

すり替え攻撃 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

4.1.3

でたらめ攻撃 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

エラーリカバリ (同期問題) . . . . . . . . . . . . . . . . . . . . . . . . . .

14

4.2.1

User から Host へ . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

4.2.2

Host から User へ . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

処理量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

第4章

4.1

4.2

4.3

– iii –

目次

第5章

SAS-K を記憶領域のない端末に実装する場合

16

5.1

手順 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

5.2

評価 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

実装

18

プラットフォームについての考察 . . . . . . . . . . . . . . . . . . . . . .

18

6.1.1

システム構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

6.1.2

システム用件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

実装内容 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

6.2.1

小額課金プラットフォーム . . . . . . . . . . . . . . . . . . . . . .

20

6.2.2

SAS-K，SAS コイン . . . . . . . . . . . . . . . . . . . . . . . . .

21

第6章

6.1

6.2

第7章

今後の課題

28

第8章

むすび

30

謝辞

31

参考文献

32

付録 A

SAS について

34

A.1

定義と記法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

A.2

SAS の手順 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

A.2.1 登録フェーズ (n = 0) . . . . . . . . . . . . . . . . . . . . . . . . .

35

A.2.2 認証フェーズ (n = k) . . . . . . . . . . . . . . . . . . . . . . . . .

36

SAS の評価 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

SAS コインについて

37

B.1

定義と記法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

B.2

SAS コインの手順 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

A.3
付録 B

– iv –

目次

B.3

付録 C

B.2.1 初期データ配分 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

B.2.2 コイン生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

B.2.3 支払フェーズ . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

B.2.4 コインの回収 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

40

B.2.5 マルチベンダシステム . . . . . . . . . . . . . . . . . . . . . . . . .

40

SAS コインの評価 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

B.3.1 信用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

B.3.2 安全性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

プログラム

44

–v–

図目次
2.1

単位毎の計算. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7

3.1

SAS-K の登録，および認証フェーズ . . . . . . . . . . . . . . . . . . . . .

9

3.2

カウンタを利用した同期方法 . . . . . . . . . . . . . . . . . . . . . . . . .

11

4.1

アタック方法. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

5.1

記憶領域がない場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

6.1

小額課金プラットフォーム . . . . . . . . . . . . . . . . . . . . . . . . . .

20

6.2

Customer 登録のフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

6.3

Vendor 登録のフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

6.4

金額登録 (初回) のフロー . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

6.5

金額登録 (k 回目) のフロー . . . . . . . . . . . . . . . . . . . . . . . . . .

25

6.6

使用フェーズのフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

6.7

支払フェーズのフロー . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

A.1 SAS の登録，および認証フェーズ . . . . . . . . . . . . . . . . . . . . . .

35

B.1 初期データ配分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

B.2 コイン生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

B.3 支払フェーズ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

B.4 マルチベンダシステム . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41– vi –

第1章

はじめに
本研究室では，コンテンツ流通支援方式の研究を行っている．近年，i-mode に代表される携帯電話でのコンテンツ流通が注目を浴びており，課金システムの開発が急務となっている．コンテンツを円滑に流通させるために，課金システムは重要であり，その中核として認証方式が位置付けられる．
資格認証方法として，(1) 指紋や顔，声等の身体情報を利用したもの，(2) IC カードのような本人の所有物を利用したもの，(3) パスワードや暗証番号等の本人の知識によるものが考えられる．しかし，(1)，(2) は指紋，顔，声あるいは IC カード等を読み込む装置が必要であり，インターネットやモバイルコミュニケーション環境で利用するにはコストが大きく，現実的でない．
そこで，これらの環境でよく用いられるのが (3) のパスワード等を用いた資格認証方法である．パスワード等の認証情報を用いて通信相手やユーザの資格を認証する方法は，公開鍵暗号方式を応用したものと，共通鍵暗号方式を応用したものの二つに大別することができるが，インターネット関連の通信プロトコル等への組み込みにおいては，公開鍵暗号方式
より格段の高速処理が可能な共通鍵暗号方式を応用した方法，特に，パスワード認証方式[1, 2, 3, 4, 5] がよく用いられる．基本的なパスワード認証の手順は以下の通りである．
まず，被認証者（装置を含む）が認証者（サーバなどの装置を含む）にパスワードを送信する．認証者は，受信したパスワードと登録されているパスワードを比較する．
しかし，この方法には，次のような問題点がある．

(a) 認証側にあるパスワードファイルの盗見によりパスワードが盗まれる．
(b) 通信中，回線盗聴によってパスワードが盗まれる．

–1–

(c) 被認証者は認証者に，自分の秘密情報であるパスワードを公開する必要がある．
最初の問題 (a) を解決する方法として，例えば，被認証者が認証者に，パスワードに一方向性関数を施したデータを登録しておき，認証時に，認証者が受信したパスワードに同じ一方向性関数を施し，結果を比較するという方法がある．
一方向性関数とは，入力の総当たり以外に，出力から入力を得る効率的な手段が存在しな
い関数であり，総当たりの計算量を十分大きくしておけば，無資格者が入力データを算出して，被認証者になりすますことを防止できる．一般に，一方向性関数は，ハッシュ関数ある
いは DES[6] や FEAL[7] などの共通鍵暗号方式によって得ることができる．共通鍵暗号方式は，共通秘密鍵を用いて入力される平文を処理して暗号文を出力として得るもので，平文と暗号文が与えられても共通秘密鍵が算出できない．特に FEAL では，平文や共通秘密鍵の入力が 1 ビット変化しただけでも，その入力変化の痕跡を全くとどめない出力を得ることができるという特徴を有している．
以上説明した通り，一方向性関数を用いた方法によって，基本的なパスワード認証方式の問題 (a) は解決できる．しかし，これを回線盗聴が簡単なインターネットに適用する場合，問題 (b) を解決することはできない．また，問題 (c) に関しては，この基本的なパスワード
認証方式は，銀行の顧客認証などには適用できても，同一レベルのユーザ同士の資格認証には適していない．
このような問題を解決する方法として，パスワードなどの認証情報を可変にする資格認証方法 [3, 4, 5] が広く用いられている．しかし，それらにもいくつかの問題点があった．

Lamport の方法 [3] には，被認証者がパスワードを定期的に再設定する必要性や，認証者側に比較して処理能力の小さい被認証者側での処理負担が大きいという問題がある．また，

CINON 法 [4] では，Lamport の方法の欠点であるパスワードの更新の必要性をなくすことができたが，被認証者および認証者における計算量が大きいという問題は依然残った．さらに，通信途中の認証情報を第三者により二回続けて盗聴された場合，「なりすまし」の危険性もあった．
そこで我々は，セキュリティが十分でないネットワーク上でユーザ等の資格認証を行う–2–

際，被認証者側および認証者側共に，実行する計算量が極めて少なく，被認証者側にも認証者側にも簡易で小さいプログラムサイズで実現可能，さらに，通信路上での盗聴に強い安全な認証方式，SAS パスワード認証方法 [8] を提案した．そして，SAS を応用した小額課金シ
ステムである SAS コイン [9] も併せて提案した．しかし，これらの提案方式にもいくつかの問題点が残されている．SAS については，同期の問題，さらに通信路上での盗聴や不正操作により，「なりすまし」や「いたずら」の危険性がある．SAS コインについては，計算量の問題や，コイン追加方法などの問題が残されている．
本論文では，SAS にほとんど追加コストを必要とすることなく，それらの問題点を克服できる方法，SAS-K を提案する．さらに，SAS-K を用いた小額課金システムである SAS コ
インについて考察し，これらの提案方式をモバイルコミュニケーション，特に携帯電話等の処理能力の低い端末に実装する際の最適な実装方式を確立することを目指す．実装フィール
ドとして，Customer(ユーザ)，Vendor(コンテンツプロバイダ)，Broker(課金センタ) の三者から構成される小額課金システムのプラットフォームを作成し，その環境に SAS-K および SAS コインを実装する．
本論文の以下の部分では，まず SAS に対する脅威および同期問題，SAS コインの問題点について第 2 章で述べる．そしてそれらの問題点を解決する方式である SAS-K の提案を第3 章で行い，SAS-K に対する評価を第 4 章で行う．さらに，第 5 章で記憶装置を持たない端末での実装方法を述べる．続いて第 6 章で SAS-K，SAS コインを実装するフィールドとして小額課金プラットフォームについて考察し，実装内容を記す．第 7 章では残された課題について述べ，最後に第 8 章で本論文のまとめとする．
なお，付録として，従来の提案方式である SAS，SAS コインについての概要を添付して
いる．

–3–

第2章

SAS，SAS コインの問題点
現在，清水研究室では SAS および SAS コインを提案しているが，これらにはいくつかの問題点が残されている．本章では，これらの問題点について指摘する．
なお，従来の SAS，SAS コインについては付録 A，B としている．

2.1

SAS の問題点

現状の SAS では，以下のような問題点が考えられる．

1. すり替え攻撃 : この攻撃により，次の認証フェーズから，盗聴者は「なりすまし」を行うことが可能になる．

2. でたらめ攻撃 : この攻撃によって，User は再登録を行わない限り，次回から正常な認証を行われなくなる．

3. 同期問題 : 通信が途切れた場合，同期がとれなくなり，以降の認証が正常に行われなくなる．
以下では，これらの問題点について考察する．

2.1.1

すり替え攻撃たとえば，第 k 回目の認証フェーズで，User が Host に対して送信した認証用データ
1
2
2
Ek−1
⊕ Ek−1, Ek2 ⊕ Ek−1
を第三者が盗聴したとする．そして，(k + 1) 回目の認証データをも盗聴し，そのデータ–4–2.1 SAS の問題点

2
A, Ek1 ⊕ Ek2 , Ek+1
⊕ Ek2

を，
2
A, Ek1 ⊕ Ek2 , Ek2 ⊕ Ek−1に置き換える．

Host では，今回認証用のデータを用いて認証を行い，次回認証用データとして，
2
2
Ek−1= (Ek2 ⊕ Ek−1
) ⊕ Ek2を登録してしまう．次回から，第三者は1
2
2
A, Ek−1⊕ Ek−1, Ek2 ⊕ Ek−1と，
2
A, Ek1 ⊕ Ek2 , Ek2 ⊕ Ek−1を交互に送信することにより，ユーザ A になりすますことができる．

2.1.2

でたらめ攻撃たとえば，第 k 回目の認証フェーズで，User が Host に対して送信した認証用データ
1
2
2
A, Ek−1⊕ Ek−1, Ek2 ⊕ Ek−1

を第三者により
1
2
A, Ek−1⊕ Ek−1,Xにすり替えられたとする．すると Host は，はじめの方のデータ Ek1 ⊕ Ek2 を用いて正常に認2を計算し，その証を行う．当然，認証はパスでき，後の方のデータ X を用いて X ⊕ Ek−1

データに対する何のチェックも行わず登録する．そして，次の認証フェーズで，正規のユー
ザは今回認証用データとして，

Ek1 ⊕ Ek2を送信するわけだが，
2
2
E(Ek1 ⊕ Ek2 ⊕ (X ⊕ Ek−1)) = X ⊕ Ek−1

なので，再登録を行わない限り認証をパスすることができなくなってしまう．

–5–

2.2 SAS コインの問題点と改良方針

2.1.3

同期問題

User は認証フェーズ毎に乱数を生成し，それを元に認証用データを作り出しているが，通信が途切れた場合，同期が取れなくなり，その認証フェーズで使用しなければならない乱数
ではなく，一回前の乱数を使ってしまい，正常な認証が行えなくなる．

2.2

SAS コインの問題点と改良方針

2.2.1

SAS コインの問題点

現状の SAS コインでは，小額支払システムとして，以下のような問題点が考えられる．

• コイン追加方法 (利用済み金額の取り扱い等) が不明な点．
• Broker，Vendor 認証情報が更新されない，あるいは両者間での認証の必要性有無．
• 支払いフェーズのロジックが不十分 (セキュアルートの利用必須)．
• 利用金額に対して確認は残金額 (利用金額総計) でしかできない問題．また，アンマッ
チ時の対応が考慮されていない．

• 登録金額が大きくなると処理時間が必要である問題．

2.2.2

改良方針

最初に挙げた問題であるコイン追加方法については図 6.5 の手順により，一つの解決策を提示しているが，さらに検討が必要である．また，最後に挙げた，「登録金額が大きくなると処理時間が必要になる」という問題の解決方法として，単位毎の計算を行うことにより計算量を削減するという方法が考えられる．つまり，我々が日常生活で行う両替と同じ概念を利用するということである．現状の SAS コインにおいて，一円単位でコインを作成するとすると，一万円のコインを生成するには一万回の計算が必要である．ここで，両替の概念を利用し，例えば，一万円のコインを生成するには，一度に五千円を生成する計算を 2 回，五千円のコインを生成する場合は一度に千円を生成する計算を 5 回，というように，単位毎の–6–2.2 SAS コインの問題点と改良方針計算を行う．この際，単位毎のコインを作成するために，単位毎の乱数を生成する必要がある．(図 2.1 参照)
コインの単位 ：

一万円

五千円

千円

五百円

百円

十円

用いる乱数 ：

RNa

RNb

RNc

RNd

RNe

RNf

20

E1(RNa) = E2(RNb) = E10(RNc) = E (RNd) = E100(RNe) = E1000(RNf)

図 2.1 単位毎の計算

–7–

第3章

SAS-K の提案
本章では 2.1 で挙げた問題点を，わずかな変更によって解決することができる方式，

SAS-K の提案を行う．
以下に今回の提案方式 SAS-K を記述し，その過程を図 3.1 に示している．さらに，同期問題の解決策については 3.2 で提案し，その過程を図 3.2 に示している．
なお，提案方式 SAS-K は，従来の SAS と同様に登録および認証フェーズから成り，登録フェーズについては全く同じ手順である．

3.1

攻撃対策

2.1.1 のすり替え攻撃，2.1.2 のでたらめ攻撃の問題を解決するために必要なのは，次回認証用データの正当性を検証することである．従来の SAS と同じく User は，ユーザ ID と認証用データを 2 つ，認証フェーズ毎に Host 側に送信する．具体的には
1
2
2
A, Ek−1⊕ Ek−1, Ek2 ⊕ Ek−1

を，
1
2
2
A, Ek−1⊕ Ek−1⊕ Ek3 , Ek2 ⊕ Ek−1に変更して送信する．その後，Host 側では，
22
Ek2 = (Ek2 ⊕ Ek−1
) ⊕ Ek−1により，次回認証用データを取得する．そして，

Ek3 = E(Ek2 )という認証確認用データを生成する．次に，その Ek3 を用いて，–8–

3.1 攻撃対策

User

n=0

Host
A, E20A, N, E20

A, N, E20

(through a secure channel)
n=1

N1, E10 , E20

A, E10 ⊕ E20 ⊕ E31 , E21 ⊕ E20

E21 , E31Store

E21 = (E21 ⊕ E20) ⊕ E20 …(1)E31 = E(E21)E10 ⊕ E20 = (E10 ⊕ E20 ⊕ E31) ⊕ E31
E10 = (E10 ⊕ E20) ⊕ E20
CompareE20 = E(E10)
Update stored E20 to (1)・・・n = k Nk, E1k-1 , E2k-1
E2k , E3k

・
・
・

・
・
・
E2k-1

A, E1k-1⊕ E2k-1⊕ E3k , E2k ⊕ E2k-1
E2k = (E2k ⊕ E2k-1) ⊕ E2k-1…(K)E3k = E(E2k)E1k-1⊕ E2k-1 = (E1k-1⊕ E2k-1⊕ E3k) ⊕ E3k
E1k-1 = (E1k-1⊕ E2k-1) ⊕ E2k-1
E2k-1= E(E1k-1)

CompareUpdate stored E2k-1 to (k)

・
・
・

・
・
・

・
・
・

図 3.1 SAS-K の登録，および認証フェーズ
1
2
1
2
Ek−1
⊕ Ek−1= (Ek−1⊕ Ek−1⊕ Ek3 ) ⊕ Ek3
2を計算し，さらに，登録されてある Ek−1
を用いて，
1
1
2
2
Ek−1
= (Ek−1⊕ Ek−1) ⊕ Ek−12を導出する．そして，そのデータにもう一度ハッシュ関数を適用し，Ek−1を算出し，その2を比較することによって認証を行う．こうすることによっ
データと，登録されている Ek−1て，認証用データの正当性が検証された認証を可能とする．

–9–

3.2 同期対策

3.2

同期対策

以前より，SAS では，同期の問題があった．ここでは今回提案する SAS-K における通信
切断時の回復方法について検討する．通信が切断される場合として，User から Host への認証用データが未達の時，Host から User への認証 OK のメッセージが未達の時の 2 つが考えられる．これらの問題に対し，User，Host 共にカウンタ (0，もしくは 1 の値を取る) を持ち，カウンタにより同期を取る方式を提案する．(図 3.2 参照)
登録フェーズで，User，Host のカウンタをそろえておく (例えば 0 に)．認証フェーズでUser は，ユーザ ID，認証用データに加え，カウンタの値も Host に送信する．Host 側では受け取ったカウンタの値によって，同期が取れているかどうかを検知．同期が取れていな
い場合は User に対してエラーを返す．User はエラーメッセージを受け取り，前回の認証フェーズで認証 OK のメッセージが受け取れなかったことを検知し，新しい乱数を生成する
ことによって正常な認証を行うことができる．

– 10 –

3.2 同期対策

User

Host

・
・
・

n=k

・
・
・

・
・
・

Nk-1

E2k-1

counter = 0

counter = 0

generate and
store
Nk

counter = 0,
Authentication Data (use Nk-1 ,Nk)
Authentication Succeed
store E2k
Authentication Succeed

counter = 1

counter = 1
clear Nk-1

n = k +1 generate and
store
Nk+1

counter = 1,
Authentication Data (use Nk , Nk+1)
Authentication Succeed
store E2k+1
counter = 0

Authentication Succeed
User coudn’t receive
counter = 1,n = k +2

Authentication Data (use Nk , Nk+1)
Counter Check Failed

Counter Check Failed

counter = 0
clear Nkgenerate and
store
Nk+2

Authentication Data (use Nk+1 , Nk+2)
Authentication Succeed
store E2k+2Authentication Succeed

counter = 1

・
・
・

・
・
・

counter = 1
clear Nk+1
・・・

X …stored data

図 3.2 カウンタを利用した同期方法– 11 –

第4章

SAS-K の評価
4.1

安全性

以下では，考え得る様々な攻撃方法に対しての SAS-K の安全性を評価する．

4.1.1

認証情報の盗聴

たとえば Host にある認証用データ Ek2 を第三者によって盗まれたとする．ハッシュ関数の衝突回避性 (collision free property) と，一方向性 (one-way property) により，第三者
は Ek2 から Ek1 をつくり出すことは不可能である．ゆえに，本当のパスワードを知っている

User のみが Ek1 をつくり出すことができ，認証をパスできる．

4.1.2

すり替え攻撃従来の SAS で，この攻撃が問題になるのは次回認証用データの正当性が全く検証されていないことであった．第三者からすると，今回認証用データの正当性を Host に確認させる
1を変更することはできない．つまり，なためには，このデータの本質的な部分である Ek−1

りすましを成功させるためには，すり替えた今回認証用データの正当性を Host に保証させることである．
今回の提案方式において，もし第 (k + 1) 回目の認証フェーズで，次回認証用データであ22⊕ Ek2 を第 k 回目認証フェーズで送信された次回認証用データである Ek2 ⊕ Ek−1
る Ek+1
2
2にすり替えられたとする．すると，Host では (Ek2 ⊕ Ek−1
) ⊕ Ek2 を計算し，Ek−1を取り– 12 –

4.1 安全性出すことになる．しかし，次回認証用データの正当性の検証に，今回認証用データを用いる
ことにより，そのデータが不当であることが判明し，認証は失敗に終る．
ここで第三者が，なりすましを成功させるために必要なデータについて考えてみる．

⊕

i,

j

g

l,

m

⊕

g

d

⊕

j

b

⊕

k

⊕

(k+3) th

g

⊕

h

f,

⊕

(k+2) th

d

c, d

⊕

e

⊕

(k+1) th

b

⊕

a

⊕

k th

⊕

(図 4.1 参照)

j

d,

g

⊕

j

j

⊕

⊕

k

⊕

In (k+3)th authentication phase a third person needs

j

⊕

k

j

⊕

or
b,

d

or
・
・
・

図 4.1 アタック方法

第 k 回目の認証フェーズにおいて，User から送信される認証用データ
1
2
2
Ek−1
⊕ Ek−1⊕ Ek3 , Ek2 ⊕ Ek−1

は，

a ⊕ b ⊕ c, d ⊕ bと表すことができる．同様に第 (k + 1) 回目から (k + 3) 回目の認証用データをそれぞれe ⊕ d ⊕ f, g ⊕ d，…第 (k + 1) 回目
h ⊕ g ⊕ i, j ⊕ g ，…第 (k + 2) 回目
k ⊕ j ⊕ l, m ⊕ j ，…第 (k + 3) 回目と表すことができる．ここで，第三者はこれまでの全ての通信を盗聴したとし，例えば第(k + 3) 回目の認証フェーズでユーザからの認証データを改ざんし，Host に g を登録するこ– 13 –

4.2 エラーリカバリ (同期問題)とによって第 (k + 2) 回目に戻して，なりすましを行おうとした場合，k ⊕ j ⊕ d, g ⊕ jというデータが必要になる．ここで，第 (k + 2) 回目の認証フェーズで送信された j ⊕ g を利用したとしても，k ⊕ j ⊕ d を作り出すことは不可能である．なぜなら，そのデータを導出するには今回はじめて送信された k というデータが必要になるが，k を取り出すには l というデータが必要となり，このデータもまた，今回はじめて現れるため，k ⊕ j ⊕ d が導出できないからである．つまり，Host に g を登録することは不可能であるため，第 (k + 3) 回目に戻すことはできない．
また，Host に d を登録することによって第 (k + 2) 回目に戻そうとした場合，k ⊕ j ⊕ b, d ⊕ jというデータが必要になる．しかし，この場合も上述したように l を導出できないため，そのデータを作り出すことができない．同様にして，いずれの段階に戻すにしても，なりすましを行うために必要なデータを過去の認証データから作り出すことが不可能であるため，すり替え攻撃に対して安全だと言える．

4.1.3

でたらめ攻撃Host 側では，次回認証用データの正当性を検証し，正当であることが言えた場合のみ次回認証用データを登録するという手順を取るため，通信路上で次回認証用データをでたらめなものにすり替えたとしても，認証をパスすることができないので，全く意味のない攻撃に
なる．

4.2

エラーリカバリ (同期問題)

以下では，提案方式 SAS-K を実装する際，通信が切断された場合の安全性について評価を行う．

– 14 –

4.3 処理量

4.2.1

User から Host へUser から Host への認証用データが未達の場合，タイムアウト処理等ののち，User は次回の認証フェーズで，今回と全く同じデータを送信することになるので，この方式 SAS-Kを利用することにより，エラーとして処理できる．つまり，これは，User から Host への認証用データが未達でも，同期がずれることがないことを示している．
さらに，たとえ送信中に第三者によってカウンタの値を変えられたとしても，Host では認証を拒否するために，認証用データを更新することがないので，全く影響を受けない．

4.2.2

Host から User へ

従来の方式では，Host から User への認証用データが未達の場合，Host では次回認証用の情報が更新されているが，User はそのことを検知できない．このことにより，次の認証フェーズで，一回前の乱数を用いて認証用データを作ってしまい，認証をパスすることができなくなる．しかし，上記の方式によりカウンタを用いると，両者間で認証情報を授受する
際，併せて同期チェックを行うことができるため，確実に同期を取ることができる．

4.3

処理量

従来の SAS と比べ (A.3 参照)，ハッシュ関数の適用回数が User 側，Host 側で 1 度だけ増えるが，これは次回認証用データの正当性を検証する上で避けては通れない最小の過程である．そして，同期問題を解決するためのコストは，カウンタを用意すること，送信データ量がわずか 1bit 増えること，User 側では第 k 回目の認証フェーズで，認証 OK のメッセー
ジが届くまで Nk だけでなく Nk−1 も併せて記憶しておく必要があることである．しかし，
1
2
Nk−1 に代えて Ek−1
，Ek−1
を記憶しておくことにより，User 側で実行しなければならな

いハッシュ関数の適用回数は，わずか 3 回に削減することができる．

– 15 –

第5章

SAS-K を記憶領域のない端末に実装する場合今回の提案方式 SAS-K では，従来の SAS と同様に乱数を用いて認証データを生成している．この方式ではユーザ端末に乱数を発生する機能およびそれを記憶する領域が必要となる．しかし実用の際，ユーザ側に乱数生成機能および記憶領域がない場合も考えられる．
たとえば本研究室で検討中である「Thin Client を用いた Server Based Computing 」にセキュリティ機能を盛り込む場合である．そこでこのような場合にも SAS-K の適用を可能とする方式を提案する．(図 5.1 参照)

5.1

手順

Host 側に User の認証回数を記憶しておく．そして User は認証フェーズ毎にサービスリ
クエストを行い，その都度 Host は User に対して認証回数 (カウンタの値) を送信する．そして User 側では乱数ではなく，認証回数を用いて認証用データを生成する．そして，ユー
ザ ID，認証用データを Host に送信し，Host 側で認証を行う．認証が成立した場合，カウンタを 1 進める．

5.2

評価

この方式を用いた場合，第三者によって送信中のカウンタの値を盗聴，もしくは改ざんされたとしても，認証は失敗に終り，なりすまし等の危険性は全くない．さらに，認証フェー– 16 –

5.2 評価

User

n=0

Host
A, E20A, E20(through a secure channel)

n=1

A, E20 Storecounter = 0

A, Service Request
counter = 0
calculate
Authentication DataA,

Authentication Data
Authentication
update E21
counter = 1
・
・
・

・
・
・
n=k

・
・
・

A, Service Request
counter = k-1
calculate
Authentication DataA,

Authentication Data
Authentication
update E2kcounter = k

・
・
・

・
・
・

・
・
・

図 5.1 記憶領域がない場合

ズ毎に認証回数を送信するために，同期がずれることはない．また，乱数に代えて認証回数を用いることによる SAS-K の安全性は何ら変化ない．なぜならば，SAS-K の安全性は認証
データを生成する際のハッシュ関数の強度に依存しているからである．

– 17 –

第6章

実装
6.1

プラットフォームについての考察

以下では，SAS-K および SAS コインを実装するにあたり，そのプラットフォームにおけるシステム構成，システム用件について考察する．

6.1.1

システム構成本システムは，Broker(課金センタ)，Vendor(コンテンツプロバイダ)，Customer(ユーザ) の 3 者で構成される．デジタルコンテンツを円滑に流通させるために，最低限必要である条件として，3 者の定義を以下に記述する．なお，今回，処理の内容を簡易化する目的で，SAS コインの実装にあたり，それぞれ一つの Broker，一つの Vendor，一人の Customer でシステムを構成している．よって，B.2.5 に示すマルチベンダシステムは利用していない．

Broker は，Customer，Vendor に対するアカウント (口座) の開設，Customer に対する残高の照会機能等を持つ課金情報管理機関である．今回，Broker は中立な立場であり，極めてセキュアな機関であることを前提としている．Broker において管理するデータは，各Customer 毎のユーザ ID，認証情報，および使用可能額である．Vendor に対する管理デー
タは，各 Vendor 毎のベンダ ID と認証情報，利用者の使用額分を移すためのアカウントである．

Vendor は，Customer に対して情報 (デジタルコンテンツ) を提供する．コンテンツには無料コンテンツと有料コンテンツがあり，Customer が有料コンテンツの購入を希望した場
合のみ直接 Customer，Vendor 間で認証処理を行い，認証が成立した場合，コンテンツ配信– 18 –

6.1 プラットフォームについての考察

および課金を行う．

Customer は，Vendor からインターネットを介してコンテンツを閲覧し，購入する．コ
ンテンツの購入を希望した場合のみ，Vendor に認証を依頼する．認証が成立し，課金処理が行われ，コンテンツを受け取る．

6.1.2

システム用件課金システムを構築する際の用件として，次の 2 点が挙げられる．

• 資格を有する Customer のみがサービスを利用できる．
• Customer の秘密情報であるパスワードおよびコインが悪意ある第 3 者に知られない．
また，この小額課金システムでは，小額のデジタルコンテンツの販売を目的としているため，以下の要求条件を満たす必要がある．

• 決済にかかる手数料等のコンテンツ料金以外に必要となるコストが全くない，あるいは極めて小さいこと．

• 十分なセキュリティを確保すること．
さらに，今回，携帯電話等の処理能力の低い端末に実装することを想定しているため，以下の要求条件を満たす必要がある．

• 計算量が小さく，高速な処理が可能であること．
• 小さなプログラムで実装可能であること．
上記 6 つの要求条件を満たすシステムを構築する．Broker に登録されたユーザ ID と認証情報を有する Customer のみ利用を可能とする．また，認証処理で用いる SAS-K 認証方式では，ユーザ認証に必要な認証パラメータが毎回異なるため，ユーザの秘密情報が知られることはない．また，通信路上の情報の不正操作に強いため，極めて安全である．

– 19 –

6.2 実装内容

また，今回，認証時に使用するハッシュ関数の部分には，FEAL[7] を利用することにより，極めて高速な処理および小さいプログラムでの記述が可能となっている．

6.2

実装内容

以下に SAS-K，SAS コインを実装するにあたり，今回作成した小額課金プラットフォー
ム，SAS-K の実装内容，SAS コインのフローチャートについて記述する．
なお，実装にあたり使用した言語は C 言語である．また，上述したように実装する際のハッシュ関数の部分には，FEAL を適用した．(付録 C は，そのソースコード)

6.2.1

小額課金プラットフォーム

以下に，今回作成した小額課金プラットフォームについて記述する．(図 6.1 参照)
本システムは 6.1 に従い，Broker(課金センタ)，Vendor(コンテンツプロバイダ)，Cus-

tomer(ユーザ) の 3 者で構成した．
Broker

Step1

Step2
Step3

Step8

Step4
Customer

Step5

Vendor

Step7

Step6

図 6.1 小額課金プラットフォーム• Step1 : Customer がユーザ登録を行う．(図 6.2)
• Step2 : Vendor がベンダ登録を行う．(図 6.3)
• Step3 : Customer が金額登録を行う．(図 6.4)

– 20 –

6.2 実装内容• Step4 : インターネットを通じて Customer が Vendor に接続し，コンテンツを閲覧．
• Step5 : 有料コンテンツの購入依頼 (認証情報およびコインの提示)．(図 6.6)
• Step6 : 認証処理および課金．(図 6.6)
• Step7 : デジタルコンテンツの送信．
• Step8 : 月一回程度で清算．(図 6.7)
図 6.1 の流れに従い，3 者間での TCP/IP を用いた通信を可能とした．

6.2.2

SAS-K，SAS コイン

以下に認証処理の詳細なフローチャートを示す．(図 6.2〜図 6.7 参照)
従来の SAS コインに対して上記 SAS-K プロトコルを適用することにより，より安全な小額支払システムが提案できる．コイン生成時の計算量の問題については 2.2 に示すような，単位毎の計算を行うことによって，計算量を削減できると考えている．また，コイン追加方法については一つの解決策として図 6.5 に提示した．その他の問題点については，今後の課題としたい．
・図 6.2 は Customer 登録のフローチャートである．(SAS-K の登録手順)
・図 6.3 は Vendor 登録のフローチャートである．Customer の登録と同じ手順で登録を行う．(SAS-K の登録手順)
・図 6.4 は金額登録 (初回) の流れ図である．

Customer は，Broker，Vendor，金額用にそれぞれ乱数を用意し，必要なデータを生成する必要がある．これは，Broker に認証してもらい，金額を登録し，使用フェーズでベンダに認証してもらう必要があるからである．

Broker は認証 (SAS-K の認証手順) を行い，認証が成立した場合，金額を登録し，Customerの Vendor に対する認証情報とコインを Vendor の Customer に対する認証情報でマスクして，送信する．
・図 6.5 は金額登録 (k 回目) のフローチャートである．

– 21 –

6.2 実装内容

Customer 登録フェーズ
CustomerBroker

ユーザ ID = AC
パスワード = SC
乱数 NCB(0) を生成，記憶E(AC, SC) ⊕ NCB(0)E1CB(0)E2CB(0)E(AC, E1CB(0))→→

A, E2CB(0)をセキュアなルートで送信

E2CB(0)をユーザ ACの認証パラメータ(初回認証用)として記憶

図 6.2 Customer 登録のフロー

今回，残っていた金額を，新しく登録する金額に加算し，新しい乱数を生成することにより，新コインを生成する方法を提案している．
・図 6.6 は使用フェーズのフローチャートである．

Customer は Vendor に認証情報およびマスクしたコイン (今回を含む過去の利用金額総計) を送信する．

Vendor 側では認証情報，コイン，今回の使用金額 (コンテンツ料) に対して認証を行い，認証が成立した場合，新しい認証情報，金額，コインを記憶し，デジタルコンテンツを送信する．
・図 6.7 は支払フェーズのフローチャートである．
今回，定期的に (たとえば月一回程度)Vendor は Customer の利用金額総額およびコインを，セキュアルートで Broker に送信するものとしている．

Broker は認証を行ったのち，Customer のアカウントから Vendor のアカウントに振込を行う．
従来の SAS コインに SAS-K を適用することにより，よりセキュリティの高い小額支払– 22 –

6.2 実装内容

Vendor 登録フェーズ
VendorBrokerベンダ ID = AV
パスワード = SV
乱数 NVB(0)を生成，記憶
E1VB(0)E(AV , SV) ⊕ NVB(0)E2VB(0)E(AV , E1VB(0))→→

A, E2VB(0)をセキュアなルートで送信

E2VB(0)をベンダ AVの認証パラメータ(初回認証用)として記憶

図 6.3 Vendor 登録のフロー

システムの提案を行った．また，コイン生成時の計算量の問題は，2.2 に示したように，単位毎の計算を行うことによって解決できる見込みである．さらに，コイン追加方法の問題も
図 6.5 の手順により，一つの解決策を提示できた．その他の問題については，今後の研究課題とする．

– 23 –

6.2 実装内容

金額登録フェーズ(初回)Customer
ユーザ ID = AC
パスワード = SC

BrokerVendorベンダ ID = AV
パスワード = SV

取り引き希望ベンダ ID = AV

乱数 NCB(1)を生成，記憶
乱数 NCV(0)を生成，記憶
E2CB(1)→

E(AC , E(AC , SC ⊕ NCB(1)))

E3CB(1)→

E(AC , E2CB(1))

1
CB(0)

E

→

E(AC , SC ⊕ NCB(0))

E2CB(0)→

FCB(0) = E

E(AC , E1CB(0))
1
CB(0)
2
CB(1)

GCB(1) = E⊕ E2CB(0) ⊕ E3CB(1) …今回認証用…次回認証用⊕ E2CB(0)E2CV(0)E(AC , E(AC , SC ⊕ NCV(0)))…ベンダ認証用
GCV(0) = E2CV(0) ⊕ E2CB(0)→カード等より登録金額Nを設定
乱数RNCVを生成，記憶
HNCB = EN(RNCV) ⊕ E2CB(0)AC , AV , FCB(0) , GCB(1) , GCV(0) , N , HNCBを一般ルートで通知
U = GCB(1) ⊕ ZCB
V E(AC , U)→

W = FCB(0) ⊕ V
X = W ⊕ ZCB→

YE(AC , X)

Y = ZCB
No

認証不成立

Yes

認証成立
YをCの新しい認証パラメータ
ZCB として記憶
G2CV(0) = GCV(0) ⊕ E2CB(0) ⊕ E2VB(0)EN(RNCV) = HNCB ⊕ E2CB(0)HNBV = EN(RNCV) ⊕ E2VB(0)EN(RNCV)を記憶する
Cのアカウントに金額Nを登録する
AC , G2CV(0) , N , HNBVを一般ルートで通知
E2CV(0) = G2CV(0) ⊕ E2VB(0)EN(RNCV) = HNBV ⊕ E2VB(0)AC , N , EN(RNCV)を記憶
E2CV(0)をCの新しい認証パラメータ
ZCV (次回認証用)として記憶

図 6.4 金額登録 (初回) のフロー

– 24 –

6.2 実装内容

金額登録フェーズ(k回目)
Customer
ユーザ ID = AC
パスワード = SC

BrokerVendorベンダ ID = AV
パスワード = SV

取り引き希望ベンダ ID = AV

乱数 NCB(k)を生成，記憶
乱数 NCV(0)を生成，記憶
E2CB(k)→E(AC , E(AC , SC ⊕ NCB(k)))

E3CB(k)→E(AC , E2CB(k))

1
CB(k-1)

E→

E(AC , SC ⊕ NCB(k-1))

E2CB(k-1)→

E(AC , E1CB(k-1))

FCB(k-1) = E
GCB(k) = E

1
CB(k-1)

2
CB(k)⊕ E2CB(k-1) ⊕ E3CB(k)⊕ E2CB(k-1)…今回認証用…次回認証用E2CV(0)E(AC , E(AC , SC ⊕ NCV(0)))
GCV(0) = E2CV(0) ⊕ E2CB(k-1)…ベンダ認証用→

カード金額等と残金を加算し登録金額Nを設定
乱数RNCVを生成，記憶
HNCB = EN(RNCV) ⊕ E2CB(k-1)
AC , AV , FCB(k-1) , GCB(k) , GCV(0) , N , HNCBを一般ルートで通知
U = GCB(k) ⊕ ZCB
V E(AC , U)→

W = FCB(k-1) ⊕ V
X = W ⊕ ZCB→

YE(AC , X)

Y = ZCB
No

認証不成立

Yes

認証成立
YをCの新しい認証パラメータ
ZCB として記憶
G2CV(0) = GCV(0) ⊕ E2CB(k-1) ⊕ E2VB(0)EN(RNCV) = HNCB ⊕ E2CB(k-1)
HNBV = EN(RNCV) ⊕ E2VB(0)EN(RNCV)を記憶する
Cのアカウントに金額Nを登録する
AC , G2CV(0) , N , HNBVを一般ルートで通知
E2CV(0) = G2CV(0) ⊕ E2VB(0)EN(RNCV) = HNBV ⊕ E2VB(0)AC , N , EN(RNCV)を記憶
E2CV(0)をCの新しい認証パラメータ
ZCV (次回認証用)として記憶

図 6.5 金額登録 (k 回目) のフロー

– 25 –

6.2 実装内容

使用フェーズ
Customer

Vendorベンダ ID = AV
パスワード = SV

ユーザ ID = AC
パスワード = SC
乱数 NCV(k)を生成，記憶
E2CV(k)→E(AC , E(AC , SC ⊕ NCV(k)))

E3CV(k)→E(AC , E2CV(k))

1
CV(k-1)→

E(AC , SC ⊕ NCV(k-1))

E2CV(k-1)→

E(AC , E1CV(k-1))

E

FCV(k-1) = E1CV(k-1) ⊕ E2CV(k-1) ⊕ E3CV(k)…今回認証用GCV(k) = E2CV(k) ⊕ E2CV(k-1)
使用金額T1を設定…次回認証用

過去の使用金額TにT1を加算
N-T(RNCV) ⊕ E2CV(k-1)
HN-T
CV = E

AC , FCV(k-1) , GCV(k) , T, HN-T
CV を一般ルートで通知
U = GCV(k) ⊕ ZCV
V E(AC , U)→

W = FCV(k-1) ⊕ V
X = W ⊕ ZCV→YE(AC , X)

Y = ZCB
No
Yes

認証不成立

2
EN-T(RNCV) = HN-T
CV ⊕ ECV(k-1)

X = ET(EN-T(RNCV))

X = EN(RNCV)
No
Yes

認証不成立

T1 = T - TCV

T1 = コンテンツ料
No
Yes

認証不成立
認証成立

YをCの新しい認証パラメータ
ZCB (k+1回目認証用)として記憶送付されてきたTをTCB として記憶計算で算出したEN-T(RNCV)を
EN-T(RNCV)として記憶

デジタルコンテンツを提供

図 6.6

使用フェーズのフロー– 26 –

6.2 実装内容

支払フェーズ
VendorBrokerベンダ ID = A V
パスワード = S V
AV , AC , TCV , EN-T(RNCV) をセキュアなルートで通知

X = ET(EN-T(RNCV))

X = EN(RNCV)
No
Yes

認証不成立

認証成立
Cのアカウントからベンダのアカウントへ振替実施

図 6.7

支払フェーズのフロー– 27 –

第7章

今後の課題
本研究の目的は，清水研究室で提案している SAS パスワード認証方式，SAS をベースとした小額課金システムである SAS コインをモバイルコミュニケーションに適用する際の種々の問題点について考察し，最適な実装方式を確立することであった．
今回 SAS-K を提案することによって，セキュリティが十分保証された認証システムの実現が可能となった．SAS コインについても SAS-K を利用することにより，よりセキュリ
ティの高い小額支払システムの提案ができた．そして，詳細な処理のフローを提示できた．
従来の SAS コインの問題点に対しては，単位毎の計算を行うことによって，計算量の問題は解決できる見込みである．また，コイン追加の問題も図 6.5 の手順により，一つの解決案を提示できた．その他の問題については，さらにシステム全体を通して検討して行く必要がある．
以下に今後検討が必要であろう問題点を指摘する．

• 提案したコイン追加方法 (図 6.5) についての考察．
• Broker，Vendor 認証情報が更新されない，あるいは両者間での認証の必要性有無の問題．

• 支払いフェーズのロジックが不十分 (セキュアルートの利用必須)．
• 利用金額に対して確認は残金額 (利用金額総計) でしかできない問題．また，アンマッ
チ時の対応がない．

• コイン生成時に，単位毎の計算を行うための，詳細な手順の提示．
• コイン送信の際の安全性についての考察．

– 28 –

提案方式，SAS-K，SAS コインをモバイルコミュニケーションに適用する際の最適な実装方式を確立するために，今後，これらの問題点について検討を進め，さらに改良を重ねていく必要がある．

– 29 –

第8章

むすび
本論文では，SAS に残されている問題点について考察し，SAS-K を提案した．この方式
では，今回認証用データと次回認証用データを関連付けて認証を行うことにより，様々なアタックを防ぐことを可能とした．また同期問題についてはカウンタを利用することにより，確実に同期を取ることを可能とした．さらに，User 側に乱数生成装置や，記憶領域がない
場合でも対応できる方法についても併せて提案した．この提案方式 SAS-K は従来の SASと比べ，ほとんど追加コストを必要とせず，また，非常に実用的かつ堅牢な認証システムである．
さらに，SAS-K をベースとした小額課金システムである SAS コインについて考察し，これらの提案方式をモバイルコミュニケーション，特に携帯電話等の処理能力の低い端末に実装する際の最適な実装方式の確立を目指した．実装フィールドとして，Customer，Vendor，Broker の三者から構成される小額課金システムのプラットフォームを作成し，その環境に
SAS-K を実装した．従来の SAS コインに SAS-K を適用することで，よりセキュリティの高い小額課金システムを提案できた．いくつかの問題点のうち，計算量の問題は単位毎の計算を行うことによって解決できる見込みである．また，コイン追加の問題も一つの解決案を提示できた．その他の問題点については，システム全体を通して検討して行く必要があり，今後の検討課題とする．

– 30 –

謝辞
高知工科大学工学部情報システム工学科 清水明宏助教授には，研究室配属以来，就職活
動，卒業研究を含め，学生生活全般に渡って懇切なる御指導，貴重な御教示を賜わった．ここに深謝申し上げる．
また，NTT アドバンステクノロジの渋谷充喜氏には，SAS-K の検討から情報通信学会投稿予定，” 強力なパスワード認証方式の提案 (SAS-K)” の作成まで，有効な御助言を頂き，御指導賜わった．
本学大学院修士課程の井上富幸氏，情報システム工学科の林竜也氏には，SAS-K の検討にあたり，有益な御議論を頂いた．ここに記して謝意を表する．

– 31 –

参考文献[1] A. Evans, W. Kantrowitz and E. Weiss, “A user authentication scheme not requiring
secrecy in the computer,” Commun. ACM, 17, 8, pp. 437–442, 1974.
[2] R.Morris and K. Thompson, “Password security : A case history, “Unix Programmer’s Manual, Seventh Edition, 2B, 1979.
[3] L. Lamport, “Password authentication with insecure communications,” Commun.ACM, vol. 24, no. 11, pp. 770–772, 1981.
[4] A. Shimizu, “A dynamic password authentication method by one-way function,”
IEICE Trans., vol. J73-D-I, no. 7, pp. 630–636, July 1990.
[5] A. Shimizu, T. Horioka, and H. Inagaki, “A password authentication method forcontents communication on the internet,” IEICE Trans. Commun., vol. E81-B, no.
8, pp. 1666–1673, Aug. 1998.
[6] “Data Encryption Standard”, FIPS Publication, 46, NBS (1977)[7] A. Shimizu and S. Miyaguchi, “Fast data encipherment algorithm FEAL,” IEICE
Trans., vol. 170-D, no. 7, pp. 1413–1423, July. 1987.
[8] M. Sandirigama, A. Shimizu, M. Noda, “Simple and Secure Password Authentication Protocol (SAS),” IEICE Trans. Commun., vol. E83-B, no.6, pp. 1363–1365,
June 2000.
[9] M. Sandirigama, A. Shimizu, M. Noda, “Simple and Secure Coin (SAS-Coin)–A
Practical Micropayment System,” IEICE Trans. Fundamentals, vol. E83-A, no.12,
pp. 2679–2688, Des. 2000.
[10] G.B.Purdy, “A high-security log-in procedure,” Commun. ACM, 17, 8, pp. 442–445,
1974.
[11] M. Matsui, “New block encryption algorithm MISTY,” Lecture Notes in Computer– 32 –

参考文献

Science, FSE 1977, pp. 54–68, 1977.
[12] 清水明宏/パスワード方式への FEAL の適用について, 情報処理学会全国大会講演論文
集, Vol. 第 37 回昭和 63 年後期 Num. 1 pp. 211-212 (1988.09)[13] N. Haller, “The S/Key(TM) one-time password system,” Proc. of the InternetSociety Symposium on Network and Distributed System Security, pp. 151–158,
1994.
[14] M. Manasse, “The Millicent Protocol for Inexpensive Electronic Commerce,”
http://www.w3.org/Conferences/WWW4/Papers/246, 1955.
[15] B. Cox, J.D. Tygar, and M. Sirbu, “NetBill Security and Transaction Protocol,”http://www.ini.cmu.edu/netbill/pubs/Usenix.html, 1955.
[16] R. Anderson, C. Manifavas, and C. Sutherland, Netcard - A Practical Electronic
Cash System, Computer Laboratory, Cambridge, 1955.
[17] R. Hauser, M. Steiner, and M. Waidner, Micro-Payments based on iKP, IBM
Zurich, 1996.
[18] R. Rivest and A. Shamir, Payword and Micromint, MIT Laboratory for Computer
Science, May 1996.
[19] A. Shimizu, “Public E-mail Messages Forwarding Services,” IEICE Technical Report, OFS96-39, No. 380, pp. 19–24, 1996.
[20] T. Horioka, M. Toda and A. Shimizu, “E-mail Messages Forwarding Services,”
IEICE Technical Report, OFS97-39, No. 280, pp. 37–42, 1997.
[21] 大石，林，井上，清水，“強力なパスワード認証方式の提案 (SAS-K)” 電子情報通信学会投稿予定.

– 33 –

付録 A

SAS についてSAS(Simple And Secure) パスワード認証方式とは，被認証者から認証者への認証依頼毎にパスワード等の認証情報を変更して認証を行う方法である．そして SAS は，通信プロト
コルに組み込める程，簡易なプロセスで認証を行うことができる方式で，携帯電話上を含めた，コンテンツ流通のプリペイド課金やマイクロペイメントシステムへの応用等が可能である．

SAS の手順は以下の通りである．

A.1

定義と記法

本稿で用いる SAS についての定義と記法は以下の通りである．

1. User を，認証用プロトコルを用いるコンピュータユーザとする．
2. Host を，ユーザを認証するサーバとする．
3. A を，ユーザの ID とする．
4. S を，ユーザのパスワードとする．
5. n を，認証セッション回数を表す 0 以上の整数とする．
6. Nn を，n 回目の認証に対応する乱数とする．
7. E を，暗号用のハッシュ関数とする．また Enm とは，Nn を使い，(S ⊕ Nn ) が m 回
ハッシュされたことを示す．

8. ⊕ は，ビットごとの排他的論理和を表す．

– 34 –

A.2 SAS の手順

A.2

SAS の手順

このプロトコルは登録フェーズと認証フェーズからなる．登録は一度だけ行われ，認証はUser がログインするたびに毎回行われる．その過程を図 A.1 に示している．
User
n=0

Host
A, E20A, N, E20

A, E20(through a secure channel)
n=1

N1 , E10 , E20

A, E10 ⊕ E20 , E21 ⊕ E20

E21

Store

E10 = (E10 ⊕ E20) ⊕ E20
E20 = E(E10)

CompareE = (E ⊕ E ) ⊕ E20
2
1

2
1

2
0

Update・・・n = k Nk , E1k-1 , E2k-1
E2k

・
・
・

・
・
・
E2k-1

A, E1k-1 ⊕ E2k-1 , E2k ⊕ E2k-1

E1k-1 = (E1k-1 ⊕ E2k-1) ⊕ E2k-1
E2k-1 = E(E1k-1)
E = (E ⊕ E
Update
2
k

・
・
・

2
k

・
・
・

Compare2
k-1) ⊕ E2k-1

・・・
X …stored data

図 A.1 SAS の登録，および認証フェーズ

A.2.1

登録フェーズ (n = 0)

User: E02 = E 2 (S ⊕ N0 ) を計算する．
User: A, E02 を Host に安全なチャネルを用いて送信する．
Host: A, E02 を 保存する．

– 35 –

A.3 SAS の評価

A.2.2

認証フェーズ (n = k)User: 以下のデータを計算し，ユーザ ID A と共に Host に送信する．
2
Ek1 ⊕ Ek2 , Ek+1
⊕ Ek2

Host: 受信したデータと，保存されている Ek2 との排他的論理和を取り，以下を取得する．
2
Ek1 , Ek+1

Host: Ek1 にハッシュ関数を適用する．E(Ek1 ) = Ek2
保存されている Ek2 と比較する．
2に更新する．
マッチすれば，User は認証され，次回認証フェーズのために，Ek2 を Ek+1

アンマッチならば認証は拒否される．

A.3

SAS の評価

Host 側では，User 毎に記憶しておかなければならないデータは，Ek2 のただ 1 つのみであり，認証フェーズ毎に Host で実行しなくてはならないハッシュ関数の適用は，1 回のみである．これは従来の方式 [3, 4, 5] と比べ，極めて軽い処理負荷を実現している．また，
1User 側では，ハッシュ関数の適用回数は，4 回 (今回の認証用中間データ Ek−1
, 今回の認2, 次回の認証用中間データ Ek1 , 次回の認証データ Ek2 ) であり，処理は十分に証データ Ek−1

軽くてすむ．さらに，User と Host の間で行われる情報の授受は，認証フェーズ毎に Userから Host への送信が 1 回のみであるため，通信セッション (コネクション) の状態が不安
定なネットワークにおいても確実に認証処理を行うことができる．

– 36 –

付録 B

SAS コインについて
本節では，SAS をベースとした支払システム SAS コインを紹介する．
このモデルには 3 種の関与者が存在する．Broker(B)，Vendor(V)，Customer(C) である．Broker は Vendor と Customer のアカウントを立ち上げ，維持し，金銭取り引きを
行う．

B.1

定義と記法

本稿で用いる SAS コインについての定義と記法は以下の通りである．

1. X ： プリペイドカードに書かれているシリアル番号 (異なるユーザに対応するサブス
クリプトをつける)

2. Y ： プリペイドカードに書かれているマスク処理された乱数 (異なるユーザに対応する
サブスクリプトをつける)2= E 2 (SC ⊕ NnCB ) ： Customer の Broker に対する n 番目のデータ
3. EnCB2
4. EnCV= E 2 (SC ⊕ NnCV ) ： Customer の Vendor に対する n 番目のデータ
2
2
5. EnVB = E (SV ⊕ NnV B ) ： Vendor の Broker に対する n 番目のデータ– 37 –

B.2 SAS コインの手順

B.2

SAS コインの手順

B.2.1

初期データ配分

初期データの配分には，プリペイドカードを用いた安全な方法を使用する．Broker は初期データ配分のためにカードを販売する．カードのシリアル番号 X をユーザ ID として使用する．(図 B.1 参照)

X = Serial Number

Y = Masked Random Number

Customer

Step4

Broker

Step6

Vendor

Step1
Step2

Step3
Card Agent

図 B.1

初期データ配分

1. Broker ： カードを製造し，コンビニエンスストア等に分配する．
2. Customer ： カードを購入する．
3. Vendor ： カードを購入する．
2
4. Customer ： XC , E0CB
⊕ YC を Broker に送信する．
2
5. Broker ： E0CBを取得する．
2
6. Vendor ： XV , E0V
B ⊕ YV を Broker に送信する．
2
7. Broker ： E0V
B を取得する．

– 38 –

B.2 SAS コインの手順

B.2.2

コイン生成

Customer

Step1

Broker

図 B.2

Step2

Vendor

コイン生成

1. Customer ： 乱数 (RN) を生成，E n (RN ) を計算し，以下のデータを Broker に送信する．

• XC ，XV : カスタマ ID と ベンダ ID
2• E0CB⊕ E n (RN ), n : コインとコイン内の単位数 n21• E0CB⊕ E0CB: 今回認証用
2
2• E0CB⊕ E1CB: 次回認証用
2
2• E0CB⊕ E0CV: ベンダ用認証データ
2
2
2. Broker ： SAS を用いて認証し，次回認証用に，E0CB
を E1CBに置き換える．そしてカスタマのアカウントに n 単位振り込み，以下をベンダに送信する．
2
n
• E0V
B ⊕ E (RN )
2
2
• E0V
B ⊕ E0CV , n, Xc
2
3. Vendor ： E n (RN ) と E0CVを取得し，n, XC と共に保存する．

B.2.3

支払フェーズ
Step1

CustomerBroker

図 B.3

支払フェーズ– 39 –

VendorB.2 SAS コインの手順

1. Customer : 以下をベンダに送信する．
2
1• XC , E0CV
⊕ E0CV: 今回認証用
2
2• E0CV⊕ E1CV: 次回認証用• E n−t(RN ) : t 単位支払2222. Vendor : E0CVを取得し，SAS を用いて認証し，次回認証用に E0CV
を E1CVに置き換える．そして，E n−t (RN ) に t 回ハッシュをかけ，E n (RN ) でチェックする．正しければ情報を提供する．
1を使うことがで
注) 必要であれば情報を暗号化するためのセッション鍵として E0CV

きる．

B.2.4

コインの回収1. Vendor : 最終支払 (E n−t (RN ) または RN ) 受領後ブローカに提示する．
2. Broker : 最終支払 (n − t 回または n 回) にハッシュをかけ，ベンダのアカウントを検証し，そこから引き落とす．
カスタマのアカウントが空きの場合，カスタマは金を預ける際の ID として X を使い，匿名性を確保できる．

B.2.5

マルチベンダシステム

本システムではベンダ毎にコインが必要である．これまでの方式の多く ([14, 15, 16, 17,18]) にこの特性がある．これは，銀行，新聞，天気予報会社のように定期的にアクセスされるプロバイダについては問題でない．定期的に利用しないベンダに対して，マルチベン
ダシステムを提案する．このシステムでは，ブローカ–ベンダ間にコイン認証エージェント(CAA) を採用している．システムの概要は図 B.4 の通りである．
このシステムでは，ベンダ (A, B, C 等) が一つの CAA グループを形成し，そのグループ(A, B, C 等) 固有のコインが CAA に送られる．このコインを使えばカスタマはグループ内– 40 –

B.3 SAS コインの評価

Broker

Step2

Step1
Coin Authentication Agent
(CAA)

Step3
Customer

Step4
Vendor A

Step5

Vendor B
Vendor C

図 B.4

マルチベンダシステムのどのベンダからでも買物をすることができる．

1. Customer : 認証情報と E n (RN ) をブローカに送る．
2. Broker : カスタマのアカウントの貸方に記入した後，認証情報と E n−t (RN ) をベンダ
自身 (A, B, C 等) ではなく CAA に送る．

3. Customer : カスタマがあるベンダに支払いたいと思えば，利用したいベンダ名，認証情報および E n−t (RN ) をベンダ自身ではなく CAA に送る．

4. CAA : コインをチェックし，情報送出命令を特定のベンダに送る
5. Vendor : 情報をカスタマに送る．

B.3

SAS コインの評価

B.3.1

信用

従来のいずれの支払システムでも，Broker は長期投資しており，信用を失いたくない
ため，信用できる．Broker は Customer と Vendor の両方と長い付き合いを持つ．次に信用のおけるのは Vendor である．Vendor も長期投資し，Broker と長い付き合いがある．

– 41 –

B.3 SAS コインの評価

Vendor は Customer とは長期の付き合いを持たない場合がある．しかしながら，Vendor
は Broker ほど信用が高くない．一番信用が低いのは，システムに出入りする Customer である．Customer は Broker とは多少の期間付き合う可能性はあるが，大抵の場合 Vendorとは一時的な関係しか持たない．それゆえ，従来のどのシステムでも Customer を一番に用心し，次に Vendor，最後に Broker の順に注意を払うべきである．
以下では SAS コインがこの状況下でどのような動きを取るか見てみる．実際，SAS コイ
ンは最低限の信用を必要とするか，あるいは全く必要としない．

• Customer : Customer はコインを作成し，それを Broker へ送る．すると，Broker がCustomer のアカウントの貸方に記入する．そのため，Customer は支払いを逃れることができない．Customer が Broker と良好な関係である場合は，コインをクレジット
ベースで作ることさえできる．Customer は n よりも低く Broker に申告することができるが，この n は Broker から Vendor へ送られるため，Customer は虚偽の申告をすることができない．

Vendor が E n−t (RN ) の最終値を持っているため，Customer は複数回使用することによって Vendor をごまかすことはできない．さらに，各 Customer が持つ E n−t (RN )は独自のパスワード S に基づく認証データと共に保存されているため，他の Customerになりすますこともできない．Vendor が最終支払いの E n−t (RN ) を知っているということは，すなわち Customer がそれを Vendor に送ったことになるため，Customer
は後日いかなる支払いも否定することはできない．

• Vendor :Vendor は Customer がそれを使用するまで最終支払い E n−t (RN ) が分からないので，Customer に不当な支払いを請求できない．

• Broker :Broker は最初の支払いを実現するまでに最終支払 E n−t (RN ) を受け取らなければならないため，Customer の口座から必要以上の金を引き出せない．さらに，Customer だけが乱数を知っているために Broker は Vendor と一緒になって Customerのアカウントを操作することもできない．

– 42 –

B.3 SAS コインの評価

Vendor と Broker ができることと言えば，外部に Customer の認証データを流出させることである．そうすることで外部者が自身のパスワードに基づいて自身の認証データを投入し，通信回線を傍受して一回だけ支払いまで受けることができる．このためのコストを考えると，わずかな支払いを盗んでも割が合わない．それ以前に，Broker は信用ができ，Vendor も争いにより，小銭を失いたくないであろう．

B.3.2

安全性

Customer と Broker 間の取り引きの場合，すべての通信は，SAS を利用するため，極めて高いセキュリティが保証される．また，コインがデータ送信中に重複して使われたり，盗まれたりすることはない．Customer は支払いを逃れることはできず，いかなる者も他人をだますことはできない．

– 43 –

付録 C

プログラム
以下に示すソースコードは，今回作成しunsigned char KS[32];た小額課金プラットフォームに SAS-K を/*-------------makekey-------------*/

適用したものである．

{

makekey(key)unsigned char *key;
unsigned char t[4],b[4],d[4];register i,j;/*/*/*/*/*/*/* 以下は，関数群のヘッダ (sas.h)*/*/*/*/*/*/*/*/*/for ( i = 0 ; i < 4 ; i++ )#include <stdio.h>d[i] = 0;#include <stdlib.h>#include <string.h>for ( i = 0 ; i < 8 ; i++ ) {#include <sys/types.h>for ( j = 0 ; j < 4 ; j++ ){#include <sys/socket.h>t[j] = key[j+4];#include <netinet/in.h>b[j] = key[j+4] ^ d[j];#include <arpa/inet.h>d[j] = key[j];#include <netdb.h>}#define BUFSIZE

1000#define DATALEN

9

key[5] = key[1] ^ key[0];key[6] = key[2] ^ key[3];key[5] = sbox(key[5] + (key[6] ^ b[0]) + 1);#define DEFAULT_PORT_center_user 8000

key[6] = sbox(key[6] + (key[5] ^ b[1]));#define DEFAULT_PORT_provider_center 8001

key[4] = sbox(key[0] + (key[5] ^ b[2]));#define DEFAULT_PORT_provider_user 8002

key[7] = sbox(key[3] + (key[6] ^ b[3]) + 1);#define DEFAULT_PORT 5320

for ( j = 0 ; j < 4 ; j++ )#define MEMBER 30

key[j] = t[j];for ( j = 0 ; j < 4 ; j++ )typedef struct userdata

KS[4*i+j] = key[j+4];{}

char uID[BUFSIZE];
char E2x[BUFSIZE];}

int zannkinn;}udata;/*-------------cipher-------------*/
cipher(block)unsigned char *block;

struct sockaddr_in settei(int port, unsigned long address);
int serverstart(int port);{
unsigned char t[4];int clientstart(int port, unsigned long address);register i,j;

int makekey(unsigned char *key);

int k;

int cipher(unsigned char *block);int sbox(unsigned char data);

k = 16;

void int_to_char(int rn, char *a);void exor(unsigned char *data1, unsigned char *data2);for ( i = 0 ; i < 8 ; i++ )void makeE1x(unsigned char *uID, unsigned char *S,

block[i] = block[i] ^ KS[k++];unsigned char *N0);void loadfile(udata *ap, int *m, char *fn);for ( i = 0 ; i < 4 ; i++ )void savefile(udata *ap, int *m, char *fn);block[i+4] = block[i+4] ^ block[i];int searchmember(char n[20], udata *ap, int m);

k = 0;/*/*/*/*/*/*/*/*/*/* 以下は，関数群 (sas.c)*/*/*/*/*/*/*/*/*/*/for ( i = 0 ; i < 8 ; i++ ) {for ( j = 0 ; j < 4 ; j++ )#include "sas.h"t[j] = block[j+4];– 44 –

block[5] = block[5] ^ block[4] ^ KS[k];rn = rn % 1000000;

block[6] = block[6] ^ block[7] ^ KS[k+1];

n[4] = rn / 100000;

block[5] = sbox(block[5] + block[6] + 1);

rn = rn % 100000;

block[6] = sbox(block[6] + block[5]);n[5] = rn / 10000;

block[4] = sbox(block[4] + block[5]);rn = rn % 10000;

block[7] = sbox(block[7] + block[6] + 1);

n[6] = rn / 1000;for ( j = 0 ; j < 4 ; j++ )rn = rn % 1000;n[7] = rn / 100;

block[j+4] = block[j+4] ^ block[j];rn = rn % 100;for ( j = 0 ; j < 4 ; j++ )n[8] = rn / 10;

block[j] = t[j];rn = rn % 10;

k += 2;n[9] = rn;}

N[0] = n[0] + n[9];for ( i = 0 ; i < 4 ; i++ )N[1] = n[1] + n[8];t[i] = block[i+4];N[2] = n[2] + n[7];for ( i = 0 ; i < 4 ; i++ )N[3] = n[3] + n[6];block[i+4] = block[i] ^ block[i+4];N[4] = n[4] + n[5];for ( i = 0 ; i < 4 ; i++ )block[i] = t[i];k = 24;}/*-------------settei--------------*/
struct sockaddr_in settei(int port, unsigned long address){for ( i = 0 ; i < 8 ; i++ )struct sockaddr_in server;

block[i] = block[i] ^ KS[k++ ];}/* server no settei *//*-------------sbox-------------*/

memset((char *) &server, 0, sizeof(server));sbox(data)server.sin_family= AF_INET;

server.sin_addr.s_addr = address;

unsigned char data;server.sin_port{= htons(port);

return ( data << 2 | data >> 6 );return server;}}/*-------------exor-------------*/
void exor(unsigned char *data1, unsigned char *data2)/*-------------serverstart-------------*/{

int serverstart(int port)
int i, small, big;{struct sockaddr_in server, client;
int s, rs, len;if (strlen(data1) <= strlen(data2)){
small = strlen(data1);
big = strlen(data2);/*socket open*/for (i = 0; i < small; i++)if (( s = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket");data1[i] = data1[i] ^ data2[i];exit(1);for (i = small; i < big; i++)}data1[i] = data2[i];}/*provider-center bind*/else{

if (bind(s, (struct sockaddr *) &server,

small = strlen(data2);
big = strlen(data1);

sizeof(server)) < 0){perror("bind");for (i = 0; i < small; i++)exit(1);

data1[i] = data1[i] ^ data2[i];}for (i = small; i < big; i++)data1[i] = data1[i];listen(s, 1);}}

len = sizeof(client);/*-------------int_to_char-------------*//*provider-center TCP connection no uketuke*/

void int_to_char(int rn, char *N)

if ((rs = accept(s, (struct sockaddr *) &client, &len)) < 0){perror("accept");{exit(1);

int n[10];}n[0] = rn / 1000000000;
rn = rn % 1000000000;

close(s);n[1] = rn / 100000000;

return rs;

rn = rn % 100000000;/* socket close */}n[2] = rn / 10000000;
rn = rn % 10000000;/*-------------clientstart-------------*/

n[3] = rn / 1000000;

int clientstart(int port, unsigned long address){– 45 –

struct sockaddr_in server;

void registration_c_p(void);

int s, len;void comunication_c(void);void start_c(void);/* socket open */if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {extern int rs1, rs2, n;perror( "socket");extern char buf[BUFSIZE];

exit(1);

extern struct sockaddr_in user, provider;
extern int pn1, pn2, n, port_p_c, port_c_u;}

extern char ip[20];if (connect(s, (struct sockaddr *) &server,
sizeof(server)) < 0) {extern unsigned long myaddress, address;
extern int argc2;

perror("connect");

extern char *argv2[];

exit(1);

extern unsigned char uID[DATALEN], uID2[DATALEN];
extern unsigned char pID[DATALEN], pID2[DATALEN];}

extern unsigned char E2xuc[DATALEN], E2xpc[DATALEN];
extern unsigned char konnkai[BUFSIZE], jikai[BUFSIZE],

return s;

kennsyou[BUFSIZE];}

extern unsigned char ninnsyoudata[BUFSIZE], kekka[BUFSIZE];/*-------------makeE1x-------------*/

extern int member, zannkinn, hit;void makeE1x(unsigned char *uID, unsigned char *S,
unsigned char *N0)/*/*/*/*/*/*/* 以下は，Broker の main 関数 (center.c)*/*/*/*/*/*/*/{
makekey(uID);#include "center.h"exor(S, N0);
cipher(S);int rs1, rs2, n;}char buf[BUFSIZE];
struct sockaddr_in user, provider;/*/*/*/*/* 以下は，Broker プログラムのヘッダ (center.h)*/*/*/*/*/

int pn1, pn2, n, port_p_c, port_c_u;char ip[20];#include <stdio.h>

unsigned long myaddress, address;#include <stdlib.h>

int argc2, i;#include <string.h>char *argv2[5];#include <sys/types.h>

unsigned char uID[DATALEN], uID2[DATALEN];#include <sys/socket.h>unsigned char pID[DATALEN], pID2[DATALEN];#include <netinet/in.h>unsigned char E2xuc[DATALEN], E2xpc[DATALEN];#include <arpa/inet.h>unsigned char konnkai[BUFSIZE], jikai[BUFSIZE],#include <netdb.h>kennsyou[BUFSIZE];
unsigned char ninnsyoudata[BUFSIZE], kekka[BUFSIZE];#define BUFSIZE

1000#define DATALEN

9

int member, zannkinn, hit;#define DEFAULT_PORT_center_user 8000

int main(int argc, char *argv[])#define DEFAULT_PORT_provider_center 8001{
int menu;#define DEFAULT_PORT_provider_user 8002
#define DEFAULT_PORT 5320

argc2 = argc;#define MEMBER 30

for (i = 0; i < argc2; i++)argv2[i] = argv[i];typedef struct userdata

start_c();{registration_c_p();char uID[BUFSIZE];
char E2x[BUFSIZE];

do

int zannkinn;{}udata;read(rs2, buf, BUFSIZE);
struct sockaddr_in settei(int port, unsigned long address);menu = atoi(buf);

int serverstart(int port);

printf("menu = %d\n", menu);
switch(menu)

int clientstart(int port, unsigned long address);
int makekey(unsigned char *key);{

int cipher(unsigned char *block);case 1:

int sbox(unsigned char data);

registration_c_u();void int_to_char(int rn, char *a);break;

void exor(unsigned char *data1, unsigned char *data2);
void makeE1x(unsigned char *uID, unsigned char *S,case 2:

unsigned char *N0);

comunication_c();void loadfile(udata *ap, int *m, char *fn);break;

void savefile(udata *ap, int *m, char *fn);
int searchmember(char n[20], udata *ap, int m);case 0:break;

void registration_c_u(void);– 46 –

E2xpc[i] = ninnsyoudata[i+8];
default:
printf("You inputed illegal menu number!\nAHO~!!\n");/*strcpy(tourokudata[member].uID, uID);

break;

strcpy(tourokudata[member].E2xpc, E2xpc);
tourokudata[member].zannkinn = zannkinn;}

member++;}savefile(ap, &member, FILENAME);*/

while(menu != 0);

printf("\nProvider Registration was finished!! \n");close(rs1); /*connection no setudann*/close(rs2); /*connection no setudann*/}exit(0);}/*/*/* 以下は，Broker への Vendor 登録関数 (registration_c_u.c)*/*/*//*/*/*/*/*/*/* 以下は，Broker 起動関数 (start_c.c)*/*/*/*/*/*/*/#include "center.h"#include "center.h"void registration_c_u(void){

void start_c(void)

int i;{/*hikisuu no kennsa*//*------------registration---------------*/

if (argc2 != 1) {printf("\n****Registration of User.****\n\n");fprintf(stderr, "Usage: %s \n", argv2[0]);read(rs2, ninnsyoudata, BUFSIZE);

exit(1);

printf("resieve data from user\n");/*receive touroku you data*/}for (i = 0; i < 8; i++)/* port banngou no settei */uID[i] = ninnsyoudata[i];port_p_c = DEFAULT_PORT_provider_center;myaddress = inet_addr("172.21.32.92");

for (i = 0; i < 8; i++)provider = settei(port_p_c, myaddress);

E2xuc[i] = ninnsyoudata[i+8];

rs1 = serverstart(port_p_c);/*strcpy(tourokudata[member].uID, uID);
strcpy(ip, inet_ntoa(provider.sin_addr));strcpy(tourokudata[member].E2xuc, E2xuc);

pn1 = (int)ntohs(provider.sin_port);

tourokudata[member].zannkinn = zannkinn;

printf("------------------------------------------------\n");member++;printf("Provider IP Address = %s Port Number =savefile(ap, &member, FILENAME);*/%d\n", ip, pn1);
printf("------------------------------------------------\n");printf("\nUser Registration was finished!! \n");}/* port banngou no settei */port_c_u = DEFAULT_PORT_center_user;
user = settei(port_c_u, myaddress);/*/*/*/*/* 以下は，Broker 認証関数 (comunication_c.c)*/*/*/*/*/*/*/

rs2 = serverstart(port_c_u);#include "center.h"
strcpy(ip, inet_ntoa(user.sin_addr));pn2 = (int)ntohs(user.sin_port);

void comunication_c(void)

printf("------------------------------------------------\n");{int i;

printf("User IP Address = %s Port Number =%d\n", ip, pn2);/*------------comunication---------------*/

printf("------------------------------------------------\n");printf("\n****ninnsyou****\n\n");}read(rs2, ninnsyoudata, BUFSIZE); /*receive ninnsyou you data*//*/* 以下は，Broker への Vendor 登録関数 (registration_c_p.c)*/*/*/

printf("receive data\n");#include "center.h"for (i = 0; i < 8; i++)uID[i] = ninnsyoudata[i];void registration_c_p(void)

strcpy(uID2, uID);{
int i;for (i = 0; i < 8; i++)konnkai[i] = ninnsyoudata[i+8];/*------------registration---------------*/
printf("\n****Registration of Provider.****\n\n");for (i = 0; i < 8; i++)read(rs1, ninnsyoudata, BUFSIZE); /*receive touroku you data*/

jikai[i] = ninnsyoudata[i+16];

printf("resieve data from provider\n");printf("uID = %s\n", uID);for (i = 0; i < 8; i++)pID[i] = ninnsyoudata[i];makekey(uID);for (i = 0; i < 8; i++)exor(jikai, E2xuc);– 47 –

cipher(jikai);

int sbox(unsigned char data);exor(konnkai, jikai);

void int_to_char(int rn, char *a);exor(konnkai, E2xuc);

void exor(unsigned char *data1, unsigned char *data2);cipher(konnkai);

void makeE1x(unsigned char *uID, unsigned char *S,
unsigned char *N0);

if (strcmp(E2xuc, konnkai) == 0){

void loadfile(udata *ap, int *m, char *fn);void savefile(udata *ap, int *m, char *fn);

kekka[0] = 1;
write(rs2, kekka, 1);/*send kekka to user*/int searchmember(char n[20], udata *ap, int m);write(rs1, kekka, 1);

void registration_p(void);

printf("send OK\n");void comunication_p(void);

strcpy(E2xuc, jikai);

void start_p(void);

printf("\n****comunication****\n\n");extern int s1, rs2, n;/*n = read(rs1, buf, BUFSIZE);
printf("(2)

recieve \"%s\" from user\n", buf);

extern char buf[BUFSIZE];
extern struct sockaddr_in center, user;
extern int port_p_c, port_p_u, pn1, pn2;

n = read(0, buf, BUFSIZE);

extern char ip1[20], ip2[20];write(s2, buf, n);extern unsigned long myaddress, address;

printf("(3)

extern int argc2, i;send to provider \"%s\"\n", buf);

extern char *argv2[5];n = read(s2, buf, BUFSIZE);

extern unsigned char pID[DATALEN], pID2[BUFSIZE];

printf("(6)

extern unsigned char S[DATALEN], S2[DATALEN];

recieve \"%s\" from provider\n", buf);

extern unsigned char N1pc[5], N0pc[5];n = read(0, buf, BUFSIZE);

extern unsigned char E10pc[DATALEN], E20pc[DATALEN];

write(rs1, buf, n);extern unsigned char E11pc[DATALEN], E21pc[DATALEN];

printf("(7)

extern int rn, content_no;send to user \"%s\"\n", buf);*/}/*/*/*/*/* 以下は，Vendor の main プログラム (provider.c)*/*/*/*/*/

else{
kekka[0] = 0;
write(rs2, kekka, 1);/*send kekka to user*/#include "provider.h"write(rs1, kekka, 1);
printf("send NG\n");int s1, rs2, n;char buf[BUFSIZE];}

struct sockaddr_in center, user;}

int port_p_c, port_p_u, pn1, pn2;char ip1[20], ip2[20];/*/*/*/*/*/* 以下は，Vendor プログラムのヘッダ (provider.h)*/*/*/*/

unsigned long myaddress, address;
int argc2, i;#include <stdio.h>char *argv2[5];#include <stdlib.h>unsigned char pID[DATALEN], pID2[BUFSIZE];#include <string.h>

unsigned char S[DATALEN], S2[DATALEN];#include <sys/types.h>

unsigned char N1pc[5], N0pc[5];#include <sys/socket.h>unsigned char E10pc[DATALEN], E20pc[DATALEN];#include <netinet/in.h>unsigned char E11pc[DATALEN], E21pc[DATALEN];#include <arpa/inet.h>

int rn, content_no;#include <netdb.h>
int main(int argc, char *argv[])#define BUFSIZE

1000#define DATALEN

9{
argc2 = argc;#define DEFAULT_PORT_center_user 8000

for (i = 0; i < argc2; i++)#define DEFAULT_PORT_provider_center 8001

argv2[i] = argv[i];#define DEFAULT_PORT_provider_user 8002
#define DEFAULT_PORT 5320

start_p();#define MEMBER 30
registration_p();typedef struct userdata{

comunication_p();char uID[BUFSIZE];
char E2x[BUFSIZE];

close(s1);

int zannkinn;

close(rs2); /*connection no setudann*/}udata;/*socket close*/exit(0);}struct sockaddr_in settei(int port, unsigned long address);
int serverstart(int port);
int clientstart(int port, unsigned long address);/*/*/*/*/*/*/* 以下は，Vendor 起動関数 (start_p.c)*/*/*/*/*/*/*/*/

int makekey(unsigned char *key);
int cipher(unsigned char *block);#include "provider.h"– 48 –

fclose(fp);*/void start_p(void)
int_to_char(rn, N0pc);{/*hikisuu no kennsa*/

for (i = 0; i < strlen(N0pc); i++)if (argc2 != 2) {printf("N0pc[%d] = %d\n", i, N0pc[i]);fprintf(stderr, "Usage: %s center_hostname \n", argv2[0]);exit(1);

makeE1x(pID, S, N0pc);}/*make E10*/

strcpy(E10pc, S);/* port banngou no settei */cipher(S);port_p_c = DEFAULT_PORT_provider_center;

strcpy(E20pc, S);/*make E20*//* center IP addres no settei */printf("\n");if ((address = inet_addr(argv2[1])) == INADDR_NONE) {struct hostent *he;strcat(pID2, E20pc);
if ((he = gethostbyname(argv2[1])) == NULL) {herror("gethostbyname");write(s1, pID2, strlen(pID2));

exit(1);

printf("send data\n");}/*send touroku you data*/}

memcpy((char *) &address, (char *)he->h_addr, he->h_length);}/*/*/*/*/*/*/* 以下は，Vendor 認証関数 (comunication_p.c)*/*/*/*/*/
center = settei(port_p_c, address);
s1 = clientstart(port_p_c, address);#include "provider.h"

strcpy(ip1, inet_ntoa(center.sin_addr));void comunication_p(void)

pn1 = (int)ntohs(center.sin_port);{

printf("--------------------------------------------------\n");int i;

printf("Center IP Address = %s Port Number = %d\n", ip1, pn1);char content[BUFSIZE];

printf("--------------------------------------------------\n");do{/* port banngou no settei *//*------------comunication---------------*/

port_p_u = DEFAULT_PORT_provider_user;

printf("\n****comunication****\n\n");myaddress = inet_addr("172.21.32.92");n = read(rs2, buf, BUFSIZE);

user = settei(port_p_u, myaddress);

printf("recieve content No. from user\n");rs2 = serverstart(port_p_u);

printf("content No. = %s\n", buf);

strcpy(ip2, inet_ntoa(user.sin_addr));content_no = atoi(buf);

pn2 = (int)ntohs(user.sin_port);
printf("--------------------------------------------------\n");n = read(s1, buf, BUFSIZE);

printf("User IP Address = %s Port Number = %d\n", ip2, pn2);for (i = 0; i < strlen(buf); i++)printf("kekka[%d] = %d\n", i, buf[i]);printf("--------------------------------------------------\n");}if (buf[0] = 1){
switch(content_no)/*/*/*/*/*/* 以下は，Vendor 登録関数 (registration_p.c)*/*/*/*/*/*/{
case 1:(content, "\n\n\nA\nB\nC\nD\n");#include "provider.h"break;
case 2:

void registration_p(void)

strcpy(content, "\n\n\n\nLove\nLove\nLove\n\n");{break;
case 3:
int i;

strcpy(content, "\n\n\n\nYuzu ou!\n\n");break;/*------------registration---------------*/

case 4:
strcpy(content, "\n\n\n\nahhaaaaann\n");printf("\n****Provider Registration.****\n\n");break;}

printf("Input your Provider ID !\n");scanf("%s", pID);

write(rs2, content, BUFSIZE); /*send centent to user*/strcpy(pID2, pID);}

printf("Input your Passward !\n");scanf("%s", S);}while(1);rn = rand();/*n = read(rs1, buf, BUFSIZE);
printf("(4)

recieve \"%s\" from center\n", buf);/*fp = fopen(FILENAME, "w");n = read(0, buf, BUFSIZE);

fprintf(fp, "%d", rn);

– 49 –

write(rs1, buf, n);extern unsigned char E11uc[DATALEN], E21uc[DATALEN],

printf("(5)

E31uc[DATALEN];

send to center\"%s\"\n", buf);

extern unsigned char data[BUFSIZE];n = read(rs2, buf, BUFSIZE);

extern unsigned char kekka[BUFSIZE];

printf("(10)extern int rn, member;recieve \"%s\" from center\n", buf);n = read(0, buf, BUFSIZE);
write(rs2, buf, n);printf("(11)/*/*/*/*/*/*/* 以下は，Customer の main 関数 (user.c)*/*/*/*/*/*/*/

send to center\"%s\"\n", buf);*/#include "user.h"}
int s1, s2, n;char buf[BUFSIZE];/*/*/*/*/* 以下は，Customer プログラムのヘッダ (user.h)*/*/*/*/*/*/

struct sockaddr_in center, provider;
int port_c_u, port_p_u, pn1, pn2;#include <stdio.h>char ip1[20], ip2[20];#include <stdlib.h>unsigned long address1, address2;#include <string.h>

int argc2, i;#include <sys/types.h>char *argv2[5];#include <sys/socket.h>unsigned char uID[DATALEN], uID2[BUFSIZE];#include <netinet/in.h>unsigned char S[DATALEN], S2[DATALEN];#include <arpa/inet.h>unsigned char N1uc[5], N0uc[5];#include <netdb.h>

unsigned char E10uc[DATALEN], E20uc[DATALEN];
unsigned char E11uc[DATALEN], E21uc[DATALEN], E31uc[DATALEN];#define BUFSIZE

1000

unsigned char data[BUFSIZE];#define DATALEN

9

unsigned char kekka[BUFSIZE];#define DEFAULT_PORT_center_user 8000

int rn, member;#define DEFAULT_PORT_provider_center 8001
#define DEFAULT_PORT_provider_user 8002

int main(int argc, char *argv[])#define DEFAULT_PORT 5320{

#define MEMBER 30

int menu, content_no;

typedef struct userdata

argc2 = argc;{

for (i = 0; i < argc2; i++)char uID[BUFSIZE];

argv2[i] = argv[i];char E2x[BUFSIZE];

start_u();

int zannkinn;

do}udata;{printf("\n#------This is SAS_SYSTEM program.------#\n\n");struct sockaddr_in settei(int port, unsigned long address);

printf("#1 : Registration.\n");int serverstart(int port);

printf("#2 : Comunication.\n");int clientstart(int port, unsigned long address);

printf("#0 : Exit.\n");int makekey(unsigned char *key);

scanf("%d",&menu);

int cipher(unsigned char *block);int sbox(unsigned char data);

switch(menu)

void int_to_char(int rn, char *a);{void exor(unsigned char *data1, unsigned char *data2);case 1:

void makeE1x(unsigned char *uID, unsigned char *S,

write(s1, "1", BUFSIZE);

unsigned char *N0);

registration_u();void loadfile(udata *ap, int *m, char *fn);break;

void savefile(udata *ap, int *m, char *fn);case 2:/*send menu no to center.*/

int searchmember(char n[20], udata *ap, int m);

printf("****Conect to Provider****\n");void registration_u(void);

printf("****and Browsing****\n\n");void comunication_u(void);

printf("****Which contents do you want to get?****\n");void start_u(void);

printf("#1 : One day of Ryuya\n");printf("#2 : Chikotto Love\n");extern int s1, s2, n;

printf("#3 : Mr. Colonel Bandana\n");extern char buf[BUFSIZE];

printf("#4 : eroero\n");extern struct sockaddr_in center, provider;scanf("%d",&content_no);extern int port_c_u, port_p_u, pn1, pn2;
extern char ip1[20], ip2[20];switch(content_no)

extern unsigned long address1, address2;{

extern int argc2;

case 1:

extern char *argv2[5];write(s2, "1", BUFSIZE);

extern unsigned char uID[DATALEN], uID2[BUFSIZE];

printf("send content No. 1 to provider");

extern unsigned char S[DATALEN], S2[DATALEN];

break;

extern unsigned char N1uc[5], N0uc[5];case 2:

extern unsigned char E10uc[DATALEN], E20uc[DATALEN];

write(s2, "2", BUFSIZE);– 50 –

printf("send content No. 2 to provider");pn1 = (int)ntohs(center.sin_port);

break;

printf("--------------------------------------------------\n");case 3:printf("Center IP Address = %s Port Number = %d\n", ip1, pn1);
printf("--------------------------------------------------\n");write(s2, "3", BUFSIZE);
printf("send content No. 3 to provider");/* port banngou no settei */break;

port_p_u = DEFAULT_PORT_provider_user;case 4:
write(s2, "4", BUFSIZE);
printf("send content No. 4 to provider");/* provider IP addres no settei */break;

if ((address2 = inet_addr(argv2[2])) == INADDR_NONE) {struct hostent *he;case 0:if ((he = gethostbyname(argv2[2])) == NULL) {write(s1, "0", BUFSIZE);

herror("gethostbyname");break;

exit(1);

default:}

printf("You inputed illegal menu number!\nAHO~!!\n");memcpy((char *) &address2, (char *)he->h_addr, he->h_length);

break;}}
write(s1, "2", BUFSIZE);/*send menu no to center.*/comunication_u();provider = settei(port_p_u, address2);

break;

s2 = clientstart(port_p_u, address2);

case 0:
write(s1, "0", BUFSIZE);

strcpy(ip2, inet_ntoa(provider.sin_addr));/*send menu no to center.*/pn2 = (int)ntohs(provider.sin_port);

break;

printf("--------------------------------------------------\n");default:
write(s1, "9", BUFSIZE);

printf("Provider IP Address = %s Port Number =/*send menu no to center.*/

printf("You inputed illegal menu number!\nAHO~!!\n");%d\n", ip2, pn2);
printf("--------------------------------------------------\n");break;}}}
while(menu != 0);/*/*/*/*/* 以下は，Customer 登録関数 (registration_u.c)/*/*/*/*/*/
close(s1);/* socket close */close(s2);/* socket close */#include "user.h"exit(0);void registration_u(void)}{
int i;/*/*/*/*/*/*/* 以下は，Customer 起動関数 (start_u.c)*/*/*/*/*/*/*//*------------registration---------------*/#include "user.h"printf("\n****User Registration****\n\n");printf("Input your User ID !\n");void start_u(void)

scanf("%s", uID);{

strcpy(uID2, uID);/*hikisuu no kennsa*/

printf("Input your Passward !\n");if (argc2 != 3) {scanf("%s", S);

fprintf(stderr, "Usage: %s sever_hostname
provider_hostname \n",rn = rand();argv2[0]);exit(1);/*fp = fopen(FILENAME, "w");}fprintf(fp, "%d", rn);fclose(fp);*//* port banngou no settei */port_c_u = DEFAULT_PORT_center_user;

int_to_char(rn, N0uc);/* center IP addres no settei */for (i = 0; i < strlen(N0uc); i++)if ((address1 = inet_addr(argv2[1])) == INADDR_NONE) {printf("N0uc[%d] = %d\n", i, N0uc[i]);struct hostent *he;if ((he = gethostbyname(argv2[1])) == NULL) {makeE1x(uID, S, N0uc);

herror("gethostbyname");/*make E10*/

strcpy(E10uc, S);exit(1);}cipher(S);memcpy((char *) &address1, (char *)he->h_addr, he->h_length);

strcpy(E20uc, S);/*make E20*/}
printf("\n");center = settei(port_c_u, address1);
s1 = clientstart(port_c_u, address1);

strcat(uID2, E20uc);

strcpy(ip1, inet_ntoa(center.sin_addr));write(s1, uID2, strlen(uID2));– 51 –/*send touroku you data*/printf("send data\n");if (kekka[0] == 1){}/*fp = fopen(FILENAME, "w");fprintf(fp, "%d", rn);/*/*/*/*/* 以下は，Customer 認証関数 (comunication_u.c)*/*/*/*/*/

fclose(fp);*/#include "user.h"printf("rn was over writed!\n");printf("\n****comunication****\n\n");void comunication_u(void)read(s2, kekka, BUFSIZE);{/*receive content from provider*/int i;

printf("content = %s\n", kekka);/*------------ninnsyou---------------*//*n = read(0, buf, BUFSIZE);

printf("\n****ninnsyou****\n\n");write(s1, buf, n);printf("Input your User ID !\n");printf("(1)

send to center \"%s\"\n", buf);

scanf("%s", uID);
strcpy(uID2, uID);n = read(s1, buf, n);printf("Input your Passward !\n");printf("(8)

recieve \"%s\" from center\n", buf);

scanf("%s", S);n = read(0, buf, BUFSIZE);

strcpy(S2, S);

write(s2, buf, n);printf("(9)/*fp = fopen(FILENAME, "r");send to provider \"%s\"\n", buf);

fscanf(fp, "%d", &rn);
fclose(fp);*/n = read(s2, buf, BUFSIZE);

int_to_char(rn, N0uc);

printf("(12)printf("rn = %d\n", rn);*/}}for (i = 0; i < strlen(N0uc); i++)printf("N0uc[%d] = %d\n", i, N0uc[i]);makeE1x(uID, S, N0uc);/*make E10*/

strcpy(E10uc, S);
cipher(S);/*make E20*/

strcpy(E20uc, S);
rn = rand();int_to_char(rn, N1uc);
printf("rn = %d\n", rn);for (i = 0; i < strlen(N1uc); i++)printf("N1uc[%d] = %d\n", i, N1uc[i]);exor(S2, N1uc);
cipher(S2);/*make E11*/

strcpy(E11uc, S2);
cipher(S2);/*make E21*/

strcpy(E21uc, S2);
cipher(S2);/*make E31*/

strcpy(E31uc, S2);
exor(E10uc, E20uc);
exor(E10uc, E31uc);/*konnkai no ninnsyou data*/exor(E21uc, E20uc);/*jikai no ninnsyou data*/

strcat(uID2, E10uc);
strcat(uID2, E21uc);
write(s1, uID2, strlen(uID2));/*send ninnsyou you data*/

printf("send data\n");read(s1, kekka, BUFSIZE);/*receive kekka*/for (i = 0; i < strlen(kekka); i++)printf("kekka[%d] = %d\n", i, kekka[i]);printf("recieve %s\n", kekka);
printf("strlen(kekka) =%d\n", strlen(kekka));for (i = 0; i < strlen(kekka); i++)printf("kekka[%d] = %d\n", i, kekka[i]);– 52 –

recieve \"%s\" from center\n", buf);