2003 年度 卒業論文
セキュアインスタントメッセンジャーの開発
研究指導 中西 祥八郎 教授
菊池 浩明 助教授
内田 理 講師
東海大学 工学部 電気工学科
9
JEP1232 秋山 曜佑
目次
1序論
1.1背景
1.2現状での問題点
1.3目的
2実装システム(暗号化システム)
2.1概要
2.2暗号化理論
2.3例
3実装システム(
IM)
3.1概要
3.2実装システム説明
4システム評価
4.1概要
4.2システム構成
4.3使い方
4.43
M 各機能
4.5システム評価
5結論
6謝辞
7 参考文献
序論
1.1 背景
インスタントメッセンジャー(IM)とは、マイクロソフト、Yahoo!、AOL 等の主要ポータルサ イトで無償提供されている常時接続型のチャット用ソフトでブロードバンド化するネット社会 の中でその普及状況が注目されている。 最近ではインターネットの普及に伴い、インスタントメッセージャーの利用者が増加している。 また、IM のビジネスでの利用も増加している。 Nilsen によると、2002年7月時点での日本における主要な4つの IM サービス{MSN,Yahoo, ICQ,AOL}のユーザ数の合計が250万人に達していることがわかる。[1] 表1:Nilsen による IM 利用者数レポート(2002年7月時点) メッセンジャー名 インストール者数 (単位:人) 利用者数 (単位:人) Total 3,002,762 2,498,185 MSN Messenger 2,251,189 1,803,069 Yahoo! Messenger 698,645 638,660 ICQ 359,908 335,208AOL Instant Messenger 102,327 98,798
また、米国ではすでにオフィスの約70%に普及していると言う報告がある。[2]
IM にはオンライン状況を互いに交換するプレゼンス通知、動的にメンバを構成してのチャット など、従来の電子メールではできなかった機能があり、今後も世界的に導入されることが予想さ れる。
1.2 現状での問題点
世界的な普及に伴い、IM のセキュリティ面での問題が考えられる。ビジネス面での利用を考え るならなおさらである。 オープンソースでXML ベースの IM サービスを開発している JabberSoftwareFundation では SSL encryption を用いたシステムを開発している。商用の製品にも多くでており、Marsan の サーベイによる製品一覧を表2に示す。 表2:セキュアインスタントメッセージングソフトウェアと暗号技術 ベンダー ソフトウェア名 暗号技術Bantu Bantu Messenger And Presence Platform 独自暗号プロトコルおよび SSL Divine Software MindAlign 独自認証プロトコル Ikimbo Ommiprise SSL Jabber Communications Platform SSL (XML encryption) JabCast Secure Realtime
Communications DES これによると多くはSSL による暗号化を採用していることが観察できるが、SSL は閉じた通信 路の暗号化を提供するサービスであり、多くの利用者との複雑なマルチキャストを伴うIM に利 用するためにはサーバを信頼点として、一旦複合化した後に中継することとなる。 SSL の方式では、クライアントが一度暗号化してサーバに送信し、サーバはその暗号文を一度 復号する。そしてその後送信先のクライアントに対応した鍵を用いて暗号化して送信する。 この方式では、送信されているメッセージは常に暗号化されているので外部からの不正なアクセ スに対しては安全だが、サーバは一度暗号文を復号することになる。その結果サーバはメッセー ジを読むことができてしまう。そしてサーバには全てのメッセージが集まることになり、プライ バシーの観点から問題が生じてしまう。 特にビジネスでの利用となれば機密が漏れてしまう可能性は否定できない。 実際に、netrating 社では IM を広告媒体の対象とみなし、IM トラフィックの月間利用実態レ ポートのサービスを開始している。具体的には主要 IM{MSN Messenger、Yahoo! Messenger、 ICQ、AOL Instant Messenger}全体と、各インスタントメッセンジャーごとの「属性情報(性別 /年齢別等 7 項目)」をレポートするというものであり、月額30万にも及ぶと言う。このサービ スの金額からも個人情報は非常に重要なものであることがわかる。それだけにサーバにメッセー ジを読まれないようにすることも重要なことである。
1.3 目的
実際にセキュリティ面での問題点をクリアしたIM を開発することを考えた。 実装に使うプロトコルは以前に提案されたもので、このプロトコルはサーバを介したプレゼンス 通知を行うが、メッセージの中身は読まれることがないモデルを仮定し、DHに基づいた効率の よい鍵交換プロトコルである。[3] よって、このプロトコルには次のような特徴がある。 1. 暗号文は中継サーバに読まれない 2. イニシエータの処理は、同報するメンバ数nに依存しない 3. 送信中は常にメッセージが暗号化されているので安全性が高い このプロトコルを用いて、実際にJava を用いて実装するのが本研究の目的である。 実際に鍵共有の方法等は後述する。 また、実装にJava を用いることによってプラットホームに依存しないシステムを実現すること ができる。 このシステムが実現すると、第三者による盗聴等の被害からメッセージを護ることが可能となり、 ビジネスなどの利用でも安心してIM を利用することが可能となる。第2章 実装システム(暗号化システム)
2.1概要
次に、実際にどのようにしてセキュリティを強化するのかということについて述べる。従来 のインスタントメッセージャーでは、メッセージは何のセキュリティ処理も施されずそのまま平 文として送受信が行われてきた。今回、セキュリティを強化する為に送受信するメッセージに対 して手を加える。 ユーザによって入力装置から打ち込まれた文字は、コンピュータの中では対応する文字コード (16進数で表される。)として扱われる。つまり、他のコンピュータとのメッセージによる通 信というのは、文字コードの送受信であるといえる。人が見てわかるように、ディスプレイなど の出力装置に出力されるときのみ、文字コードを対応する文字にして表示を行っているのである。 メッセージに対して手を加えるというのは、言い換えれば、コンピュータ同士の通信でやり取 りされる文字コード(実際には2進数)に対して手を加えるといえる。 本研究では、メッセージを鍵で暗号化して送信し、受信者は送られたメッセージを鍵で復号化 して受け取る。ここで、メッセージを鍵で暗号化するとは、メッセージ(文字コード)に対して ある数(鍵)を用いて計算を行い、その値を相手に送信した後、受信者は受け取ったメッセージ (文字コード)に対してある数(鍵)を用いて逆の計算を行い、送信者のメッセージを取り出す ということである。 ここで、注意しなくてはならないのはどのようにして鍵を相手に渡すかということである。そ のまま送ったのでは、第3者に鍵をコピーされてしまい暗号化したメッセージが盗聴されてしま う。 そこで、本研究では、第3者が鍵を取得することを困難にしてメッセージの盗聴・改ざんを防 ぐ為に、次に述べる鍵配送の手法を用いた。2.2 暗号化理論
セキュリティ強化システムの方法について、処理を各段階に分割して説明を行う。 (フェイズ1 IMへの登録) IMを利用するために、ユーザはサーバに対して個人情報の登録を行う。その後、サーバはそのユ ーザに対し、乱数により秘密鍵(a)を生成する。さらにサーバは、定数(g,q,p)という各値を使用 して、ユーザへの 参加証p
g
g
1
=
amod
を作成する。そして、それらの値(g,q,p,g1)をユーザに送る。 (ここで、p、qをq|p−1を満たす大きな素数、gを情報群zp*の位数qの原始元とする。)サーバから値(g,q,p,g1)を受け取ったユーザは、乱数を生成し自分の秘密鍵(x)とする。次に、 自分の秘密鍵(x)と参加証g1を用いて
p
g
y
=
1
xmod
から公開鍵(y)を生成する。そして、その公開鍵(y)をサーバに送る。 これらの処理で、サーバは各ユーザに対応した秘密鍵(a)と公開鍵(y)を所有していることにな る。また、ユーザ側は自分で生成した秘密鍵(x)を持っていることになる。 サーバ所持(各ユーザの y,a)−−−−−ここでp
g
p
g
y
=
1
xmod
=
axmod
各ユーザの所持(x) (フェイズ2 公開鍵取得) ユーザは、通信したい他のユーザの公開鍵(y)をサーバから取得する。公開鍵は文字どおり、公 開されている鍵であり、ユーザは誰の公開鍵でもサーバから取得することができる。 (フェイズ3 共通鍵作成) 共通鍵を作成するために、ユーザは(r = 乱数%q)という数式から値rを生成する。(注 こ の値rはフェイズ3を実行するたび毎回変える事ができる。) ユーザ(仮にID=1とする)は この値を用いてp
g
z
=
rmod
という値を求めサーバに送る。zを受け取った後、サーバはユーザ(ID=1)が通信を希望する相 手(仮にID=2とする)の秘密鍵(a)を使って、p
z
b
=
amod
という値を求めて通信相手(ID=2)に送る。 この時点で、サーバの送ったbをgで表すと、p
g
p
z
b
=
amod
=
ramod
となる。 サーバから値bを受け取った相手(ID =2)は,自分の持つ秘密鍵(x)を用いてp
b
k
=
xmod
を求めて共通鍵を生成する。 この共通鍵kをgで表すと
p
g
p
z
p
b
k
=
xmod
=
xamod
=
xarmod
となる。この処理で、通信相手(ID=2)は共通鍵kを取得した。 次に乱数rを生成して値zを送ったほうのユーザ(ID=1)は、通信相手(ID=2)の公開鍵yと乱数r を用いて
p
y
k
'
=
rmod
を求める。ここで、p
g
p
g
y
=
1
xmod
=
xamod
であるから、k'をgで表すと、p
g
p
y
k
'
=
rmod
=
rxamod
となる。ここで、
p
g
k
=
xarmod
p
g
k
'
=
xarmod
よりk=k'となるので、共通鍵として使用することができる。これで、共通鍵でメッセージを暗号化して送受 信する準備ができた。 (フェイズ4 共通鍵を利用して1対1の対話開始) 送信するメッセージはアスキーコードに直して、文字列から数字に変換する。その数字に共通 鍵kを使用してメッセージの暗号化を行った後、相手に送信する。 メッセージを受け取ったほうは、共通鍵kを用いて複号を行った後、メッセージはアスキーコ ードから文字列に変換されて受信者側の画面に表示される。メッセージの暗号化、複号、文字列 からアスキーコード変換などの処理は、プログラム内部で行われる。また、メッセージの表示も 即座に行われるので、ユーザはシステムに関して気にすることなくIMを用いて会話を行うことが できる。 (フェイズ5 3人以上での複数人での会話(チャット)) 複数人での会話の方法について、例を挙げて説明を行う。仮に、A、B、Cという3人が居たと する。このとき、登録してある2者間でのIMによる通信しかできない。これを、A、B、Cの3人で会話ができるようにする。 まず、Aがランダムにチャット用の鍵(key)を生成する。次に、その鍵をそれぞれのユーザとの 共通鍵で暗号化して対応したユーザに送る。受け取った各ユーザは共通鍵を用いて復号し、チャ ット用の鍵(key)を取得する。 この処理で、A、B、C3人が同じチャット用の鍵(key)を持っていることになる。よって、メッ セージを暗号化して送り、受け取ったメッセージを復号し、3人での会話が可能になる。この手 順を用いてチャット用の鍵を共有化し、3人以上の複数の人とIMを利用して会話することができ る。
2.3 例
ここで、これまで説明した鍵共有の理論を一つの例題にそって表してみる。 ユーザ3 人とユーザ 3 人とがいる。g の値を 2、p の値を13とする。 サーバはユーザ3人に対する秘密鍵をそれぞれa1=2、a2=3、a3=4 とする。 ユーザ3 人はそれぞれが持つ秘密鍵を x1=5、x2=2、x3=2 とする。 各ユーザの公開鍵y を求め、ユーザ 1 が鍵共有を行った場合の計算をする。 また、使用する乱数r は 2 とし、ハッシュ関数は考えないものとする。 まずサーバは各ユーザに参加証として4
13
mod
2
mod
1
=
g
1p
=
2=
g
a8
13
mod
2
mod
2
=
g
2p
=
3=
g
a3
13
mod
2
mod
3
=
g
3p
=
4=
g
a をそれぞれに送る、そして各ユーザは公開鍵を10
13
mod
4
mod
1
1
=
g
1p
=
5=
y
x12
13
mod
8
mod
2
2
=
g
2p
=
2=
y
x9
13
mod
3
mod
3
3
=
g
3p
=
2=
y
x より、それぞれ生成する。そして、ユーザ1 が鍵共有を行う時4
13
mod
2
mod
=
2=
=
g
p
z
r をサーバに送信し、ユーザ2 とユーザ 3 の公開鍵を持っていると仮定し1
13
mod
12
mod
2
2
=
y
p
=
2=
K
r3
13
mod
9
mod
3
3
=
y
p
=
2=
K
r これによりユーザ2 との共通鍵 K2 とユーザ 3 との共通鍵 K3 を生成する。 一方、サーバはz を受け取ったあとユーザ2とユーザ 3 に12
13
mod
4
mod
2
=
z
2p
=
3=
b
a9
13
mod
4
mod
3
=
z
3p
=
4=
b
aそれぞれb2、b3 を送信する。 それを受けたユーザ2とユーザ3 はそれぞれ
1
13
mod
12
mod
2
2
=
b
2p
=
2=
K
x3
13
mod
9
mod
3
3
=
b
3p
=
2=
K
x この計算により、ユーザ2、ユーザ3はそれぞれユーザ1との共通鍵を得る。 この値は先にユーザ 1 が求めた値と一致する。これにより鍵共有ができていることが証明され た。3 実装システム(メッセンジャーシステム)
3.1概要
次に、2 章で述べた暗号化理論を実装したインスタントメッセンジャーシステムの構造について 説明を行う。各値が実際にどのように使用されているのかプログラムの面から詳しく説明を行う。3.2実装した
IM のシステムについて
なお、このシステムでは非常に大きな値を使用するために基本的に“BigInteger”を用いる。 このプログラムはサーバ、クライアントともに機能によって5つにわかれている。また、お互い に動作をするために対応したプログラムが下の表のように決まっている。 主な処理 対応するサーバプログラム 対応するクライアントプログラム 個人情報登録 サーバプログラム1 クライアントプログラム1 メンバ追加 サーバプログラム2 クライアントプログラム2 鍵共有 サーバプログラム3 クライアントプログラム3 1対1での会話 サーバプログラム4 クライアントプログラム4 3人以上での会話 サーバプログラム5 クライアントプログラム5 またここでの説明で用いる値は下記の通りである。g
: *の乗法群の原始元 p Zq
p,
:q
|
p
−
1
を満たす大きな素数a
:サーバが持つ各ユーザに対応した秘密鍵x
:各ユーザの秘密鍵y
:各ユーザの公開鍵k
:ユーザ同士の共通鍵 それ以外の値に関しては文中で説明するものとする。・ サーバ
サーバプログラムはクライアントの要求を受けて各処理を行うプログラムである。 サーバは動作開始後、クライアントを待つ待機状態になる。クライアントが接続をしてきたらサ ーバはそのクライアントの処理を行うスレッドを生成し、再びクライアントの接続を待つ待機状 態に戻る。以後そのクライアントとの処理は生成したスレッドの上で行うことになる。 分離したスレッドではまず処理に必要な各値をあらかじめ用意してあるファイル“data”から ‘g’‘q’‘p’より取得、同じくファイル“user”より現在どれだけのクライアントを受け持っ ているかの値、ID 番号の最終値を取得する。そしてその後実際にクライアントとの処理を開始 する。 まずサーバはクライアントが要求する処理を識別することからはじめる。クライアントが最初に 送ってくる値を元に、“switch”文によりその処理を分岐させる。ここで受け取る値はクライア ントプログラムごとに違い、そのプログラム番号に対応している。クライアントは一度処理を行 うたびに接続を切るので各処理を行おうとするたびにここまでの処理を受けることになる。
・サーバプログラム1
クライアントプログラム1(ユーザ情報登録プログラム)に対しての処理ではまず前の処理で取 得してある“ID”の値に1をプラスし、ファイル“user”に書き込む。そしてその値をこのユ ーザのID とする。次に今後そのクライアントとの処理で使用するファイルを生成する。ここで 生成するファイルは“ID”“s+ID”“mlist+ID”“chatlist+ID”“pass+ID”である(ID はその クライアントに割り振った個別の番号である)。次にそのクライアントに対応するサーバ側の秘 密鍵として乱数‘a’を生成する。そしてその値と最初に読み込んでおいた‘g’‘p’を用いてp
g
g
1
=
amod
を計算し‘g1’の値を得る。そしてこれらの値‘ID’‘g’‘q’‘p’‘g1’の値をそのクライア ントへと送信する。その後クライアントから公開鍵‘y’を受け取る。そしてそのクライアント のユーザID と公開鍵をファイル“ID”へと書き込み処理を終える。・サーバプログラム2
クライアントプログラム2(公開鍵配布プログラム)に対しての処理は、クライアントよりID、 そして公開鍵を要求しているクライアントのID を受け取る。クライアントから要求された ID のユーザの公開鍵‘y’をファイル“ID”より読み込みクライアントへと受け渡す。このときフ ァイル“mlist+ID”にそのクライアントが要求した ID 番号を追加して書き込む。・サーバプログラム3
クライアントプログラム3(共通鍵生成プログラム)に対しての処理は、ユーザID、ポート番 号、乱数を用いた値‘z’をクライアントより受け取る。まず始めに接続してきたクライアント のIP を接続情報から読み込み、クライアントが受け渡してきたポート番号の情報とともにファ イル“s+ID”へと書き込む。そしてそのクライアントの ID に対応したファイル“mlist+ID” よりそのユーザのメンバであるユーザに対して‘z’の値に各クライアントに対してのサーバの 秘密鍵‘a’を用いて
p
z
b
=
amod
の計算を行い、そしてそのユーザのIP とポート番号をファイル“s+ID”より読み込みそこへ元 の‘z’を生成したユーザの ID とその値を送信する。そしてこの処理は“mlist+ID”より“while” 文を用いてメンバが読み込めなくなるまでこの処理を繰り返すものとする。これによりユーザが 登録しているメンバ全員にこの処理を行うことができる。・サーバプログラム4
クライアントプログラム4(個人チャットプログラム)に対しての処理は、クライアントよりユ ーザID、ポート番号、メッセージ(暗号文)、そして送信先のユーザ ID を受け取る。まず始め に接続してきたユーザのIP を接続情報から読み込み、クライアントが受け渡してきたポート番 号の情報とともにファイル“s+ID”へと書き込む。そして送信先のユーザに対応したファイル “s+ID”より IP とポート番号を読み込み、送信元のユーザ ID とメッセージ(暗号文)を送信 する。・サーバプログラム5
クライアントプログラム5(チャットプログラム)に対しての処理は、クライアントよりユーザ ID、チャットしたい人の ID、ポート番号、メッセージ(暗号文)を受け取る。まず始めに接続 してきたユーザのIP を接続情報から読み込み、クライアントが受け渡してきたポート番号の情 報とともにファイル“s+ID”へと書き込む。そしてそのユーザが現在チャットしたい人の ID を 受け取り、“chatlist+ID”へ、その ID を書き込む。その ID を書き込まれたファイル“chatlist+ID” よりユーザ ID を読み込みそれぞれのユーザに対して送信先のユーザに対応したファイル “s+ID”より IP とポート番号を読み込み、送信元のユーザ ID とメッセージ(暗号文)を送信 する。この送信する処理は“chatlist+ID”より“while”文を用いてメンバが読み込めなくなる まで行う。これによりチャットを行っているメンバ全員にメッセージ(暗号文)が送信されるこ ととなる。・ クライアント
クライアントプログラムはユーザが実際にチャットを行うために利用するプログラムである。 このプログラムを利用するためにはまずサーバプログラムを動作させておく必要がある。クライ アントは全ての動作をサーバとのやり取りの中で行う。 クライアントプログラムはその動作によっていくつかのプログラムに分かれている、実際にはそ れらのプログラムをインターフェース部分との連動によって動作をさせる。それぞれのプログラ ムごとに番号を付けるものとする。・クライアントプログラム1
クライアントプログラム1はユーザがこのインスタントメッセージング機能を使う上で必要と なる各情報をサーバに登録、そしてクライアント側で取得、生成するプログラムである。最初に このプログラムの識別番号である‘1’をサーバへと送信する。このプログラムではまず各種フ ァイルを生成する。生成するファイルは“userdata”“mlist”“pass”“chatkey”である。そし て次に自分の秘密鍵となる乱数“x”を生成する。その後サーバより‘ID’‘g’‘q’‘p’‘g1’ を受け取り、その値と秘密鍵‘x’の値を用いてp
g
y
=
1
xmod
を計算し、公開鍵‘y’を生成、サーバへと送信する。そしてこれらの値を全てファイル“userdata” に書き込む。・クライアントプログラム2
クライアントプログラム2は実際にメッセージ交換を行いたいユーザを登録するプログラムで ある。最初にこのプログラムの識別番号である‘2’をサーバへと送信する。次に自分の‘ID’、 そしてメンバに登録したいユーザの‘ID’を送信する。そしてこの時メンバに登録したいユー ザとのやり取りで使用するファイル“y+ID”“key+ID”を生成する(ここでの ID は登録したい ユーザのID を指す)。そしてサーバより送信されたそのユーザの公開鍵をファイル“y+ID”に 書き込む。そしてメンバリストであるファイル“mlist”にこのユーザの ID を及び登録したユ ーザのハンドルネームを追加して書き込む。・クライアントプログラム3
クライアントプログラム3はチャットを行うときに暗号化、復号を行うために用いる共通鍵を生成するプログラムである。最初にこのプログラムの識別番号である‘3’をサーバへと送信する。 次にファイル“userdata”より各種値を読み込み、そして乱数‘r’を生成する。‘r’は‘ r = r mod q’を計算し、実際に使える値へと変える。そして
p
g
z
=
rmod
を計算し、‘z’の値を得る。そして自分の‘ID’‘z’、受信用のポート番号、(後述)をサーバ へと送信する。そして“mlist”より ID のみ読み込んだのちメンバであるユーザに対してそれ ぞれの公開鍵をファイル“y+ID”より読み込みp
y
k
=
rmod
の計算を行い、それぞれのユーザの共通鍵‘k’を生成する。生成した共通鍵はそれぞれのユー ザに対応したファイル“key+ID”に書き込む。そしてこの処理は“mlist+ID”より“while” 文を用いてメンバが読み込めなくなるまでこの処理を繰り返すものとする。これによりユーザが 登録しているメンバ全員にこの処理を行うことができる。 またこのプログラムは受信プログラムとも連動している。共通鍵を生成するためのプロセスでは、 最初にオンラインになった場合(送信側)と後からオンラインになった場合(受信側)の2つの 場合があるためである。このプログラムと連動させる受信プログラムでは、まず始めにポートを あいているものよりランダムに選択し、そのポートを開き待機状態に移る。サーバよりメンバ登 録しているユーザのID と値‘b’が送られてきた場合、そのユーザに対応したファイル‘y+ID’ よりそのユーザの公開鍵を読みp
b
k
=
xmod
を計算し共通鍵‘k’を得る。そして先ほどの送信側のときと同じように生成した共通鍵はそれ ぞれのユーザに対応したファイル“key+ID”に書き込む。この時書き込む共通鍵は常に上書き させる。これにより必ず受信側が生成した共通鍵を使用することになり、プログラム面での処理 を単純化させ、共通鍵の更新も個別に頻繁に行えることになるので安全性も増す。・クライアントプログラム4
クライアントプログラム4はメンバ間で個別にチャットを行うためのプログラムである。最初に このプログラムの識別番号である‘4’をサーバへと送信する。メッセージをこちらから送信す る場合、実際にチャットを行うメンバのID こちらから指定する。そしてそのメンバに対応した共通鍵をファイル“key+ID”より読み込み実際に入力されたメッセージを暗号化する。サーバ へは自分の‘ID’、送信先のユーザの‘ID’、受信用のポート番号、そして暗号化されたメッセ ージを送信する。このプログラムではまず始めに‘Online!’のメッセージを自動的にこれらの 処理を経て送信する。それ以後は自由にメッセージを入力し、送信可能である。 このプログラムも受信プログラムと連動していて、メッセージを相手から受ける場合に使用する。 まず始めにポートをあいているものよりランダムに選択し、そのポートを開き待機状態に移る。 そして相手がメッセージを送信してきた場合、サーバよりメッセージを送信してきたユーザの ‘ID’とメッセージを受け取る。メッセージは暗号化されているので、今受け取った送信先の ユーザ‘ID’に対応したファイル‘key+ID’よりそのユーザとの共通鍵を取得し、この暗号化 されたメッセージを復号する。これによって相手から送られてきたメッセージを読むことができ るようになる。そして送信先のユーザの‘ID’とともにメッセージを画面に出力する。
・クライアントプログラム5
クライアントプログラム5は複数のメンバ間でチャットを行うためのプログラムである。最初に このプログラムの識別番号である‘5’をサーバへと送信する。このプログラムは基本的にクラ イアントプログラム4と同じである。あらかじめチャットを行いたいメンバ間全員で同じ共通鍵 を取得し、ファイル“chatkey”に書き込んでおく。そしてメッセージを送信する際はこのファ イル“chatkey”より共通鍵を読み込み、これを用いて暗号化し、サーバへ自分の‘ID’と受信 用のポート番号とともに送信する。このプログラムではまず始めに‘Online!’のメッセージを 自動的にこれらの処理を経て送信する。それ以後は自由にメッセージを入力し、送信可能である。 このプログラムも受信プログラムと連動していて、メッセージを相手から受ける場合に使用する。 まず始めにポートをあいているものよりランダムに選択し、そのポートを開き待機状態に移る。 そして相手がメッセージを送信してきた場合、サーバよりメッセージを送信してきたユーザの ‘ID’とメッセージを受け取る。メッセージは暗号化されているので、今受け取った送信先の ユーザ‘ID’に対応したファイル‘chatkey’よりそのメンバ間での共通鍵を取得し、この暗号 化されたメッセージを復号する。これによって相手から送られてきたメッセージを読むことがで きるようになる。そして送信先のユーザの‘ID’とともにメッセージを画面に出力する。各ファイルの詳細情報
サーバ側
ファイル名 生成プログラム 含まれる値 詳細 data 最初から存在 g q p 処理に必要な値をあらかじめ入力して おく user 最初から存在 ID 現在何人のユーザが登録しているかを 記録する ID サーバ1 a y 各ユーザに対応する秘密鍵と公開鍵を記録しておく mlist+ID サーバ1 ID 番号 そのID のユーザのメンバリスト s+ID サーバ1 IP Port そのID のユーザの接続元の情報 chatlist+ID サーバ1 ID 番号 そのユーザがチャットを行う時のメン バリスト pass+ID サーバ1 パスワード そのユーザのパスワード ※ID は各ユーザのものクライアント側
ファイル名 生成プログラム 含まれる値 詳細 userdata クライアント1 ID x g q p g1 y 処理に必要な値を書き込んでいく mlist クライアント1 ID 番号 メンバのID を書き記していく pass クライアント1 pass 乱数 chatkey クライアント1 k チャットをする時に使う共通鍵を書 き込む y+ID クライアント2 y ID に対応したユーザの公開鍵 key+ID クライアント2 k ID に対応したユーザとの共通鍵 まめに更新される ※ID は各ユーザのもの4章 システム評価
4.1 概要 この章では実装した画面を用いて、どのようにして開発したメッセンジャーで通信を行うのか について説明する。また、開発したメッセンジャーシステムを以後3Mと呼称する。 4.2 システム構成 3Mのシステム構成について分割して説明を行う。登録、鍵の共通化、1対1での通信、多人数 での通信というフェイズに分割して説明を行う。 4.2.1登録 まず、M3を利用する為にユーザ登録を行う。(図1)で「はい」を選択するとユーザ情報登録 画面(図2)に移行する。ここで、「いいえ」を選択した場合はすぐに終了する。 図1 3M使用許諾画面 図2登録画面 (図2)でユーザ情報を入力する。上から、ハンドルネーム、名前、メールアドレス、パスワー ドを入力する。ここで、パスワードを2回入力するが、2つのパスワードが異なる場合再入力を 促すダイアログが表示される。 (図3)パスワードは念のため2回 入力を行う。 図3 パスワードが異なる場合入力したハンドルネーム、登録者名、メールアドレス、パスワードは、ENTER を押すとクラ イアントプログラム1を起動し、サーバに送る。特にハンドルネームは、後述するリストの時の ユーザネームとして使用する。 4.2.2 鍵の共通化 次に通信したい相手の公開鍵を取得する。(図4)の画面で通信したい相手のIDを入力する。 承認ボタンを押すと、通信したい相手の公開鍵(y)とともに相手のハンドルネームを取得する。 そして、登録したID とハンドルネームが mlist に保存される。取得したハンドルネームは通信 を開始する際のリストで使用する。 公開鍵の取得は設定終了を選択するまで何度でも可能である。間違えてID以外の文字を入力し た場合「キャンセル」ボタンで入力した文字を消すことができる。 図4公開鍵取得画面 ここで取得した公開鍵(y)を用いてクライアントプログラム3(共通鍵作成)を実行し、 通 信相手との共通鍵を作成する。作成した共通鍵を用いて通信を行う。 4.2.3 1 対1での通信 まず、mlist から登録されたメンバ名を読み込んでリストに表示する。1対1での通信では、 (図5)のリストから通信したい相手のハンドルネームを選択する。すると、選択した相手との 通信をする為の画面(図6)が表示される。 相手も同様に実行した場合、先にアプリケーションを実行したほうのメッセージ表示エリアに 「ID+online」というメッセージが表示される。
図5 リスト 図6 通信画面 このとき、他の人とも同時に1対1の通信をしたい場合には、リストから他のユーザを選択する ことで同様に選択した相手との通信画面が表示される。 4.2.4 多人数での通信(同報通信) 図7で示すようにリストのメンバを複数選択し、「通信」ボタンを押す。すると、図8のよう に同報通信が可能となり、2人以上で会話を楽しむことができる。 図7 メンバ複数選択 図 8 同報通信 4.3 3Mの使い方 上記4.2では、3Mを使用するためのユーザ登録について説明を行った。4.3では3 Mの各機能について詳しく解説を行う。 1 背景の選択 図9に示すようにリストを起動して「メニューバー→背景の変更」から背景を選択すると、フ
ァイル「haikei.txt」から画像ファイル名を読み込む。読み込んだ画像名と同じ画像が存在する 場合、背景の画像をその画像に変更することができる。(図10) 図9 背景の変更 図10 背景変更後 2 メンバ設定 次に「メニューバー→メンバ設定」の各機能について説明する。(図11) メンバ設定内の「メンバ追加」を選択すると、公開鍵追加画面が起動する。(図12) ここで、まだ公開鍵を取得していない新メンバの公開鍵を取得する。 (図11) メンバ設定 (図12) メンバ追加 新しいメンバの公開鍵取得を「設定終了」ボタンで終了する。その後、「メンバ設定 →リロード」を選択すると(図13)、リストが再表示され、追加したメンバのハンドルネー ムがリストに表示される。(図14)
図13 リロード 図14 追加されたリスト 3 3M通信画面の背景変更 3Mの画面にはメニューの中に背景、ヘルプメニューを実装してある。背景を選択すると、3 種類の画像を背景として使用できる。背景に設定する画像はGIF、JPEG形式の2種類に対 応している。 また、背景に設定する画像の大きさはどのような大きさでもよい。小さい画像は拡大し、大き い画像は縮小する。ただし、縦横の比率が大幅に異なる画像を設定すると、引き伸ばしたように なるのでなるべくなら正方形の画像が使用するほうが良い。 図15 背景設定 図16 画像の登録 画像を新しく登録したい場合は「メニュー→背景設定」を選択する。すると、設定したい画像名 の入力フォームが表示される。(図16) ここで、4種類の画像名を入力する。ここで、初期画像は、アプリケーションを起動した時の 最初に使用される背景である。その後「決定」ボタンを押すと、フォームが閉じる。そして、「メ ニュー→背景の変更」で背景を選択すれば、登録した新しい背景を使うことができる。直接設定
したいのならファイル「3MBACK.txt」に画像名を書き込むこともできる。 4 3Mの各機能 図17における各ボタンの機能について説明する。 メッセージ表示エリア メッセージ入力エリア 図17 3M 送信――――入力エリアに入力されたメッセージの送信を行う。 リセット――入力エリアに入力されたメッセージの削除を行う。 SAVE――メッセージ表示エリアに表示された内容を保存する。 LOAD――保存した内容を読み込む
5.結論
暗号化理論を実装したメッセンジャーを作成した。今回採用した理論によって、第 3 者 および、サーバによるメッセージの盗聴も防ぐ事が出来た。 そしてプログラムを工夫し、鍵共有という処理を、自分と相手がオンラインになるたび 行うことによってオンラインになるたび鍵の値を自動的に変更し、ほぼ完全に盗聴を防ぐ ことができた。また、ユーザにとって使いやすいインターフェースを作成した。謝辞
本研究を遂行するにあたって、多くの方々から御指導、御激励を受け賜りました。特に、 本研究を遂行するにあたり、多大なる御指導を賜りました、東海大学工学科電気工学科 菊 池浩明助教授に深甚なる感謝を申し上げます。 また、本研究における理論の提案をしていただいた、東海大学大学院工学研究科電気工 学専攻博士課程前期 大学院生 多田 美奈子氏に深く感謝を申し上げます。 さらに、本研究を推進するにあたり、御親切なる御指導を賜りました、東海大学工学科 電気工学科 中西祥八郎教授、内田理講師に深甚なる感謝を申し上げます。 そして、本研究を推進するにあたり、多大なる御指導を賜り、本研究を導いて頂きまし た東海大学大学院工学研究科電気工学専攻博士課程後期 大学院生 中里純二氏に厚く感 謝を申し上げます。 最後に2年と半年ほどに楽しさやつらさを分かち合い、支えて頂いた電気第5研究室の 仲間たちに厚く感謝を申し上げます。参考文献
[1]Nielsen//NetRatings,インスタントメッセンジャー調査レポート
http://www.netratings.co.jp/IM.html
[2]Caroly D. Marsan, “Secure Instant messaging software coming for corporate users” Network World Fusion
http://www.nwfusion.com/news/2002/128936_01-14-2002.html [3]菊池,多田,中西「インスタントメッセンジャーにおける鍵配送プロトコルの一提案」 2002年暗号と情報セキュリティシンポジウム Vol.Ⅱ,pp.961-965,2002 [4]「Java 逆引き大全500の極意」 著 高橋 和也 発行 ㈱秀和システム
ソース
server1.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.*; public class server1{public static void main(String argv[]){ //kidou
try{
int port = Integer.parseInt(argv[0]); ServerSocket ss = new ServerSocket(port); while(true){ Socket s = ss.accept(); System.out.println("accept: " + s); new s1t1(s); } }catch(Exception e){ System.out.println(e); } } } class s1t1 extends Thread{
Random rnd= new Random(); BigInteger g = new BigInteger("0"); BigInteger q = new BigInteger("0"); BigInteger p = new BigInteger("0"); BigInteger user = new BigInteger("0");
Socket s; s1t1(Socket s0){ s = s0; start(); } public void run(){
try{
BufferedReader br =
new BufferedReader(new FileReader("data")); String line; line = br.readLine(); g = new BigInteger(line); line = br.readLine(); q = new BigInteger(line); line = br.readLine(); p = new BigInteger(line); br.close(); br =
new BufferedReader(new FileReader("user")); line = br.readLine();
user = new BigInteger(line);
}catch(Exception e){ }
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
//ID kousin
BigInteger g1 = new BigInteger("0"); BigInteger a = new BigInteger("0"); BigInteger y = new BigInteger("0"); BigInteger pa = new BigInteger("0"); user = user.add(BigInteger.valueOf(1)); String UU = user.toString();
PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("user")));
pr.println(user); pr.close();
File file2 = new File(UU); file2.createNewFile();
File file3 = new File("mlist" + UU); file3.createNewFile();
File file4 = new File("s" + UU); file4.createNewFile();
File file5 = new File("chatlist" + UU); file5.createNewFile();
File file6 = new File("pass" + UU); file6.createNewFile();
//kaku user ni taiousita himitukagi seisei
a = new BigInteger(128,rnd); System.out.println("a = " + a); pr =
new PrintWriter(new BufferedWriter(new FileWriter(UU))); pr.println(a); g1 = g.modPow(a,p); //sousin pw.println(user); pw.println(g); pw.println(q); pw.println(p); pw.println(g1); pw.flush(); //jusin String c = d.readLine(); y = new BigInteger(c); c = d.readLine(); pa = new BigInteger(c); pr.println(y); pr.close(); pr =
new PrintWriter(new BufferedWriter(new FileWriter("pass" + UU)));
pr.println(pa); pr.close();
System.out.println("y = " + y); s.close(); }catch(Exception e){ System.out.println(e); } } }
server2.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; public class server2{public static void main(String argv[]){ try{
int port = Integer.parseInt(argv[0]); ServerSocket ss = new ServerSocket(port); while(true){ Socket s = ss.accept(); System.out.println("accept: " + s); new s2t1(s); } }catch(Exception e){ System.out.println(e);
} } } class s2t1 extends Thread{
Socket s;
s2t1(Socket s0){ s = s0; start(); } public void run(){
try{
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
System.out.println(s.getInetAddress()); System.out.println(s.getPort()); String c,ii; ii = d.readLine(); c = d.readLine(); BufferedReader br =
new BufferedReader(new FileReader(c)); String line; line = br.readLine(); line = br.readLine(); br.close(); System.out.println("y = " + line); pw.println(line);
pw.flush(); s.close(); }catch(Exception e){ System.out.println("No user!!"); } } }
server3.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; class server3{public static void main(String argv[]){
try{
int port = Integer.parseInt(argv[0]); ServerSocket ss = new ServerSocket(port); while(true){ Socket s = ss.accept(); System.out.println("accept: " + s); new s3t1(s); } }catch(Exception e){ System.out.println(e); } }
}
class s3t1 extends Thread{ Socket s;
s3t1(Socket s0){ s = s0; start(); } public void run(){
BigInteger g = new BigInteger("0"); BigInteger q = new BigInteger("0"); BigInteger p = new BigInteger("0"); try{
BufferedReader br =
new BufferedReader(new FileReader("data")); String line; line = br.readLine(); g = new BigInteger(line); line = br.readLine(); q = new BigInteger(line); line = br.readLine(); p = new BigInteger(line); br.close(); }catch(Exception e){ }
try{
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
String I,c,uI,yourhost,yourport;
I = d.readLine();
yourhost = d.readLine(); yourport = d.readLine(); c = d.readLine();
BigInteger z = new BigInteger(c); PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("s"+I)));
pr.println(yourhost); pr.println(yourport); pr.close();
BufferedReader br1 =
new BufferedReader(new FileReader("mlist"+I)); while((uI = br1.readLine()) !=null){
BufferedReader br2 =
new BufferedReader(new FileReader(uI)); String line;
BigInteger a = new BigInteger(line); br2.close();
BigInteger b = new BigInteger("0"); b = z.modPow(a,p);
System.out.println("b" + uI + " = " +b); try{
BufferedReader br3 =
new BufferedReader(new FileReader("s"+uI)); String userhost,userport;
userhost = br3.readLine(); userport = br3.readLine();
int userport2 = Integer.parseInt(userport); Socket s2 = new Socket(userhost, userport2); OutputStream os2 = s2.getOutputStream();
PrintWriter pw2 = new PrintWriter(os2); pw2.println(I); pw2.println(b); pw2.flush(); }catch(Exception e){ } } br1.close(); s.close();
}catch(Exception e){ System.out.println(e); } } }
server4.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; class server4{public static void main(String argv[]){
try{
int port = Integer.parseInt(argv[0]); ServerSocket ss = new ServerSocket(port); while(true){ Socket s = ss.accept(); new s4t1(s); } }catch(Exception e){ System.out.println(e); } } }
Socket s;
s4t1(Socket s0){ s = s0; start(); } public void run(){
try{
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
String I,c,uI,yourhost,yourport; I = d.readLine(); uI = d.readLine(); yourhost = d.readLine(); yourport = d.readLine(); c = d.readLine(); System.out.println(c); PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("s"+I))); pr.println(yourhost); pr.println(yourport); pr.close(); try{ BufferedReader br3 =
new BufferedReader(new FileReader("s"+uI)); String userhost,userport;
userhost = br3.readLine(); userport = br3.readLine();
int userport2 = Integer.parseInt(userport); Socket s2 = new Socket(userhost, userport2); OutputStream os2 = s2.getOutputStream();
PrintWriter pw2 = new PrintWriter(os2); pw2.println(I); pw2.println(c); pw2.flush(); }catch(Exception e){ } s.close(); }catch(Exception e){ System.out.println(e); } } }
server5.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*;import java.util.Random; class server5{
public static void main(String argv[]){
try{
int port = Integer.parseInt(argv[0]); ServerSocket ss = new ServerSocket(port); while(true){ Socket s = ss.accept(); new s5t1(s); } }catch(Exception e){ System.out.println(e); } } }
class s5t1 extends Thread{ Socket s;
s5t1(Socket s0){ s = s0; start(); } public void run(){
try{
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
String I,c,uI,yourhost,yourport; I = d.readLine(); yourhost = d.readLine(); yourport = d.readLine(); c = d.readLine(); System.out.println(c); PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("s"+I)));
pr.println(yourhost); pr.println(yourport); pr.close();
BufferedReader br1 =
new BufferedReader(new FileReader("chatlist"+I)); while((uI = br1.readLine()) !=null){
try{
BufferedReader br3 =
new BufferedReader(new FileReader("s"+uI)); String userhost,userport;
userhost = br3.readLine(); userport = br3.readLine();
int userport2 = Integer.parseInt(userport); Socket s2 = new Socket(userhost, userport2);
OutputStream os2 = s2.getOutputStream(); PrintWriter pw2 = new PrintWriter(os2); pw2.println(I); pw2.println(c); pw2.flush(); }catch(Exception e){ } } br1.close(); s.close(); }catch(Exception e){ System.out.println(e); } } }
client1.java
import java.io.*; import java.net.*; import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; class client1{public static void main(String args[]){ Random rnd= new Random();
BigInteger x= new BigInteger(128,rnd); BigInteger g = new BigInteger("0"); BigInteger q = new BigInteger("0"); BigInteger p = new BigInteger("0"); BigInteger g1 = new BigInteger("0"); BigInteger y = new BigInteger("0"); BigInteger pa = new BigInteger(128,rnd);
try{
String host = args[0];
int port = Integer.parseInt(args[1]); Socket s = new Socket(host, port); InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
String c;
File file1 = new File("userdata"); file1.createNewFile();
PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("userdata")));
//jusin
c = d.readLine();
BigInteger ID = new BigInteger(c); System.out.println("ID = " + ID);
System.out.println("x = " + x); c = d.readLine(); g = new BigInteger(c); System.out.println("g = " + g); pr.println(ID); pr.println(x); pr.println(g); c = d.readLine(); q = new BigInteger(c); System.out.println("q = " + q); pr.println(q); c = d.readLine(); p = new BigInteger(c); System.out.println("p = " + p); pr.println(p); c = d.readLine(); g1 = new BigInteger(c); System.out.println("g1 = " + g1); pr.println(g1); //koukaikagi y = g1.modPow(x,p); System.out.println("y = " + y); pr.println(y); pr.close();
//sousin
pw.println(y); pw.println(pa); pw.flush();
File file2 = new File("mlist"); file2.createNewFile(); File file3 = new File("pass"); file3.createNewFile(); pr =
new PrintWriter(new BufferedWriter(new FileWriter("pass"))); pr.println(pa);
pr.close();
File file4 = new File("chatkey"); file4.createNewFile(); }catch(Exception e){ System.out.println(e); } } }
client2.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random;class client2{
public static void main(String args[]){ BigInteger y = new BigInteger("0"); BigInteger I = new BigInteger("0");
try{
String host = args[0];
int port = Integer.parseInt(args[1]); Socket s = new Socket(host, port); InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os); String c;
BufferedReader br =
new BufferedReader(new FileReader("userdata")); String ii; ii = br.readLine(); I = new BigInteger(ii); br.close(); String ID = args[2]; pw.println(I); pw.println(ID); pw.flush(); c = d.readLine(); y = new BigInteger(c); File file1 = new File("y"+ID); file1.createNewFile();
File file2 = new File("key"+ID); file2.createNewFile();
PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("y"+ID))); pr.println(y);
pr.close();
BufferedReader br2 =
new BufferedReader(new FileReader("mlist")); PrintWriter pr2 =
new PrintWriter(new BufferedWriter(new FileWriter("mlist"))); String TI;
while((TI = br2.readLine()) !=null){ pr2.println(TI); pr2.println(ID); } pr2.close(); br2.close(); System.out.println("y" + ID + " = " +y); s.close(); }catch(Exception e){ System.out.println(e); } } }
client3.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; public class client3{
public static void main(String args[]){ Random rnd= new Random();
BigInteger I= new BigInteger("0"); BigInteger x= new BigInteger("0"); BigInteger g = new BigInteger("0"); BigInteger q = new BigInteger("0"); BigInteger p = new BigInteger("0"); BigInteger g1 = new BigInteger("0"); BigInteger y = new BigInteger("0"); try{
BufferedReader br =
new BufferedReader(new FileReader("userdata")); String line; line = br.readLine(); I = new BigInteger(line); line = br.readLine(); x = new BigInteger(line); line = br.readLine(); g = new BigInteger(line); line = br.readLine(); q = new BigInteger(line); line = br.readLine(); p = new BigInteger(line); line = br.readLine();
g1 = new BigInteger(line); line = br.readLine(); y = new BigInteger(line); br.close(); }catch(Exception e){ } try{
String host = args[0];
int port = Integer.parseInt(args[1]); Socket s = new Socket(host, port); InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InetAddress hostname = InetAddress.getLocalHost(); String c;
BigInteger yy = new BigInteger("0"); BigInteger r = new BigInteger(128,rnd); BigInteger r2,z,k;
r2 = r.remainder(q); z = g.modPow(r2,p); String ID;
BufferedReader br1 =
new BufferedReader(new FileReader("mlist")); while((ID = br1.readLine()) !=null){
BufferedReader br =
new BufferedReader(new FileReader("y"+ID)); String line = br.readLine();
yy = new BigInteger(line); br.close();
k = yy.modPow(r2,p); PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("key"+ID))); pr.println(k); pr.close(); System.out.println("key" + ID + " = " +k); } br1.close(); c3t1 tb = new c3t1(); tb.start(); for(int i = 0; i < 100000000; ++i){ } int myport = tb.getport();
pw.println(I); pw.println(hostname.getHostAddress()); pw.println(myport); pw.println(z); pw.flush(); }catch(Exception e){ System.out.println(e); }
} }
class c3t1 extends Thread{ int port;
public int getport(){ return(port); }
public void run(){ try{
port = 0;
ServerSocket ss = new ServerSocket(port); port = ss.getLocalPort();
while(true){
Socket s = ss.accept();
System.out.println("accept: " + s); BigInteger x = new BigInteger("0");
BigInteger p = new BigInteger("0"); BufferedReader br =
new BufferedReader(new FileReader("userdata")); String line; line = br.readLine(); line = br.readLine(); x = new BigInteger(line); line = br.readLine(); line = br.readLine(); line = br.readLine(); p = new BigInteger(line); br.close();
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
BigInteger b = new BigInteger("0"); BigInteger k = new BigInteger("0"); BigInteger y = new BigInteger("0");
String ID = d.readLine(); String c = d.readLine();
b = new BigInteger(c); k = b.modPow(x,p); PrintWriter pr =
new PrintWriter(new BufferedWriter(new FileWriter("key"+ID))); pr.println(k); pr.close(); System.out.println("key" + ID + " = " +k); s.close(); } }catch(Exception e){ System.out.println(e); } }
}
client4.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; import cryptix.provider.key.RawSecretKey; import cryptix.util.core.Hex; import xjava.security.*; public class client4{public static void main(String args[]){ BigInteger I= new BigInteger("0"); c4t1 tb = new c4t1();
tb.setDaemon(true); tb.start();
for(int i = 0; i < 100000000; ++i){ } int myport = tb.getport();
try{
BufferedReader br =
new BufferedReader(new FileReader("userdata")); String line;
line = br.readLine(); I = new BigInteger(line); br.close();
} try{
BufferedReader keyin
= new BufferedReader(new InputStreamReader(System.in)); String a = "Online!";
String host = args[0];
int port = Integer.parseInt(args[1]); int ID2 = Integer.parseInt(args[2]); byte k0[],k1[],k2[], k3[];
k1 = new byte[8];
BigInteger kint = new BigInteger("0"); BufferedReader br2 =
new BufferedReader(new FileReader("key" + ID2)); String line2;
line2 = br2.readLine(); kint = new BigInteger(line2); br2.close();
Socket s = new Socket(host, port);
OutputStream os = s.getOutputStream(); PrintWriter pw = new PrintWriter(os);
InetAddress hostname = InetAddress.getLocalHost(); k0 = kint.toByteArray();
Cipher alg = Cipher.getInstance("DES/ECB/PKCS#7", "Cryptix"); RawSecretKey key = new RawSecretKey("DES", k1);
alg.initEncrypt(key); k2 = alg.crypt(a.getBytes()); pw.println(I); pw.println(ID2); pw.println(hostname.getHostAddress()); pw.println(myport); pw.println(Hex.toString(k2)); pw.flush(); s.close(); while(!a.equals("QUIT") ){ a = keyin.readLine(); s = new Socket(host, port); os = s.getOutputStream();
pw = new PrintWriter(os);
hostname = InetAddress.getLocalHost(); kint = new BigInteger("0");
br2 =
new BufferedReader(new FileReader("key" + ID2)); line2 = br2.readLine();
kint = new BigInteger(line2); br2.close();
for(int i = 0; i < 8; ++i){ k1[i] = k0[i]; }
alg = Cipher.getInstance("DES/ECB/PKCS#7", "Cryptix"); key = new RawSecretKey("DES", k1);
alg.initEncrypt(key); k2 = alg.crypt(a.getBytes()); pw.println(I); pw.println(ID2); pw.println(hostname.getHostAddress()); pw.println(myport); pw.println(Hex.toString(k2)); pw.flush(); System.out.println(I + ":" + a); s.close(); } }catch(Exception e){ } } } class c4t1 extends Thread{ int port;
public int getport(){ return(port); }
public void run(){ try{
ServerSocket ss = new ServerSocket(port); port = ss.getLocalPort();
while(true){
Socket s = ss.accept();
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is); BufferedReader d = new BufferedReader(isr);
String ID = d.readLine(); String c = d.readLine();
BigInteger kint = new BigInteger("0"); BufferedReader br2 =
new BufferedReader(new FileReader("key" + ID)); String line2;
line2 = br2.readLine(); kint = new BigInteger(line2); br2.close();
byte k0[] = kint.toByteArray(); byte k1[] = new byte[8];
for(int i = 0; i < 8; ++i){ k1[i] = k0[i]; } byte k2[], k3[];
Cipher alg = Cipher.getInstance("DES/ECB/PKCS#7", "Cryptix");
RawSecretKey key = new RawSecretKey("DES", k1); k3 = Hex.fromString(c);
alg.initDecrypt(key); k2 = alg.crypt(k3);
System.out.println(ID + ":" + new String(k2)); s.close(); } }catch(Exception e){ System.out.println(e); } } }
client5.java
import java.io.*; import java.net.*; import java.lang.*; import java.math.*; import java.util.Random; import cryptix.provider.key.RawSecretKey; import cryptix.util.core.Hex; import xjava.security.*; public class client5{public static void main(String args[]){ BigInteger I= new BigInteger("0"); c4t1 tb = new c4t1();
tb.setDaemon(true); tb.start();
for(int i = 0; i < 100000000; ++i){ } int myport = tb.getport();
try{
BufferedReader br =
new BufferedReader(new FileReader("userdata")); String line; line = br.readLine(); I = new BigInteger(line); br.close(); }catch(Exception e){ } try{ BufferedReader keyin
= new BufferedReader(new InputStreamReader(System.in)); String a = "Online!";
String host = args[0];
int port = Integer.parseInt(args[1]); byte k0[],k1[],k2[], k3[];
k1 = new byte[8];
BigInteger kint = new BigInteger("0"); BufferedReader br2 =
new BufferedReader(new FileReader("chatkey")); String line2;
line2 = br2.readLine(); kint = new BigInteger(line2); br2.close();