ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C#コミュの暗号化通信をするには?

  • mixiチェック
  • このエントリーをはてなブックマークに追加
C#で暗号化通信をしようとしているのですがどうしてもうまく行きません。
TCPストリームから1行づつ読み込んでいくと言うものなのですが、改行コード(下のプログラムの場合X)が送信されずに、reader.ReadByte()でとまってしまいます。
おそらく暗号化が64bit毎に行われているので、8バイト毎にしか送信されないからだと思うのですが、解決方法が分かりません。
writer.FlushFinalBlockをFlushに変えてもだめでした。
バイナリを送信した直後に、writer.Close();を入れて、ソケットを閉じると、正常に復号化されました。

うまく行かない部分を取り出すと以下のようになります。

もしどなたか分かる方がいれば教えてください。よろしくお願いします。

// 1番ポートを開いて待つ
TcpListener listen = new TcpListener(IPAddress.Any, 1);
listen.Start();

// 1番ポートにクライアント接続
TcpClient tcpCliant = new TcpClient();
tcpCliant.Connect("localhost", 1);
NetworkStream ns1 = tcpCliant.GetStream();

// 1番ポートをサーバ接続
Socket tcpServer = listen.AcceptSocket();
NetworkStream ns2 = new NetworkStream(tcpServer);

// 3DES を初期化する。
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.GenerateIV();
des.GenerateKey();

byte[] buf = Encoding.UTF8.GetBytes("こんにちは^^;X");

// 暗号化して送信
CryptoStream writer = new CryptoStream(ns1, des.CreateEncryptor(), CryptoStreamMode.Write);
writer.Write(buf, 0, buf.Length);
writer.FlushFinalBlock();

// 読み込んで復号化
CryptoStream reader = new CryptoStream(ns2, des.CreateDecryptor(), CryptoStreamMode.Read);
MemoryStream mem2 = new MemoryStream();
while(true)
{
int b = reader.ReadByte();
if(b=='X') break;
mem2.WriteByte((byte)b);
}

// 復号化した文字を出力
MessageBox.Show(Encoding.UTF8.GetString(mem2.ToArray()));

コメント(8)

試しに writer.Write(buf, 0, buf.Length);の後ろにwriter.WriteByte(0);を7個入れてみたらうまくいきました。
インチキ?
おおなるほど、1バイトずつ書き込むわけですか、

writer.Write(buf, 0, ((buf.Length-1) / 8) * 8 + 1);

とかやって無理やり、書き込むようにしたのですが、ならなくて途方にくれてました。
この際なれば、何でもいいです。早速試してみます。
いや、偽者のデータを後ろに書き込んで押し出してるだけです。文字列なら使える手かもしれないですけど。
押し出すために書き込むデータのバイト数が一定ではないようです。
7バイトで押し出されるときもあれば、15バイトで押し出されるときもあるようです。
かなり気持ち悪いですが、とりあえず、0を大量に書き込んで、押し出すようにしてみました。
もし他にもいい方法があればどなたか教えてください。よろしくお願いします。
writer.FlushFinalBlock() の下に ns1.Close() を入れると正常に動作しました。

多分、ns1 が閉じられてないから、書き込んだブロックが ns1 に残ってるのでは、と思うのですが確証は無いです……。
TripleDESなど
の共通鍵暗号は複数のバイトをまとめて暗号化するブロック暗号
なので、そのブロック長になるまで処理されないのは
ある意味当たり前です。
(RC4だったらそうではないのですが、.NET Framework の中に見当たらない…)

Close の時にはもうこれ以上こないことが分かるので、
残っているものを送信するということでしょう。

私はTripleDESは使わないのですが64bit=8byte単位のようですね。
(Rijndael=AESばっかり使います。速くて強力)
なるほど、やはり対話型の通信で暗号化をするときには、ストリームごと暗号化するのは難しそうですね。
データ毎に暗号化して、普通のソケットのストリームを使用するようにしてみようと思います。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

C# 更新情報

C#のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング