- PR -

MemoryStreamについて

1
投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-04-04 17:25
こんにちは。

 某スレッドのために、ファイルを経由しないでXML化、とか、ファイルを経由しないでCryptoとかができるようにと思い、MemoryStreamをいろいろいじっていたのですが・・・

 どうもこのMemoryStreamには、8バイト単位でしか書き込みできないようです。8バイト未満の書き込みをすると、バッファには何も書き込まれません。同じ文字列をFileStreamに書き込み、こちらはファイルに書き込まれているのを確認しました。MemoryStreamの方は、デバッガのローカル変数のバッファを覗いてみましたが、何も書き込まれていませんでした。しかし、8バイト渡すと、書き込まれます。7バイト渡してから7バイト渡すと、2度目の書き込みで8バイト分がバッファに入ります。Flushは、MSDNによると、MemoryStreamの書き込み先はRAMであるため機能しない、そうです。しかし、8バイト単位でないと書き込まれない、という記述は見つかりませんでした。
NothingButXMLInfoSet
ベテラン
会議室デビュー日: 2003/03/31
投稿数: 65
投稿日時: 2003-04-04 17:48
まさか。

コード:
MemoryStream ms = new MemoryStream();
byte[] b = new byte[5];
b[0] = 1;
b[1] = 2;
b[2] = 3;
b[3] = 4;
b[4] = 5;
ms.Write(b, 0, 5);


5バイト書き込まれますよ。どういうコードを試されていますか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-04-07 10:00
こんにちは。休日失礼。
引用:

NothingButXMLInfoSetさんの書き込み (2003-04-04 17:48) より:
まさか。
5バイト書き込まれますよ。どういうコードを試されていますか?



 わたしも「まさか」と思うのですが・・・(すみません、これはC#で試みています)
 下コードで、valueが7文字とすると、エンコーダをUnicodeEncodingだと14バイトになります。このとき8バイト書き込まれます。AsciEncodingだと7バイトになり、ストリームには書き込まれません。CryptoStreamの出力先ストリームにしているので、CryptoStreamをFlushしないといけないのかと思い、加えましたが、出力されません。しかし、MemoryStreamをFileStreamにすると、書き込まれます。
コード:
// DES_KEYとDES_IVは、それぞれbyte[8]
// pPasswordはbyte[]
public string Password
{
	set
	{
		Byte[] pass = System.Text.UnicodeEncoding.Unicode.GetBytes(value);

		MemoryStream mem = new MemoryStream();
		DESCryptoServiceProvider des = new DESCryptoServiceProvider();
		des.Padding = PaddingMode.PKCS7;

		ICryptoTransform transformer = des.CreateEncryptor(DES_KEY, DES_IV);
		CryptoStream crypto = new CryptoStream(mem, transformer,
 CryptoStreamMode.Write);
		crypto.Write(pass, 0, pass.Length);
		crypto.Flush();
		mem.Flush();
		mem.Seek(0, SeekOrigin.Begin);
		pPassword = mem.ToArray();
		crypto.Close();
		mem.Close();

		pPassLength = value.Length;
	}
// get省略
}



 次はサポート技術情報にあるサンプルを、少しいじったものです。
コード:
public void EncryptFile(string sInputFilename,
 string sOutputFilename, string sKey) 
{
	DESCryptoServiceProvider DES
		= new DESCryptoServiceProvider();
	FileStream fsEncrypted
		= new FileStream(sOutputFilename,
		FileMode.Create, FileAccess.Write);
	MemoryStream memEncrypted = new MemoryStream(64);
	ICryptoTransform desencrypt
		= DES.CreateEncryptor(DES_KEY, DES_IV);
	CryptoStream cryptostream
		= new CryptoStream(fsEncrypted,
		desencrypt, CryptoStreamMode.Write); 
	CryptoStream cryptomem
		= new CryptoStream(memEncrypted,
		desencrypt, CryptoStreamMode.Write); 
	byte[] pass
		= System.Text.ASCIIEncoding.ASCII.GetBytes(sKey);
	cryptostream.Write(pass, 0, pass.Length);
	cryptostream.Close();
	fsEncrypted.Close();
	cryptomem.Write(pass, 0, pass.Length);
	cryptomem.Flush();
	memEncrypted.Flush();
	memEncrypted.Seek(0, SeekOrigin.Begin);
	pPassword = memEncrypted.ToArray();
	cryptomem.Close();
	memEncrypted.Close();
}


 CryptoStreamとMemoryStreamを追加し、オリジナルのFileStreamと同じようにしまうコードを追加しています。同じようにしているつもりですが、FileStreamには7バイトでも書き込まれるのに、MemoryStreamには8の倍数バイトしか書き込まれません。
NothingButXMLInfoSet
ベテラン
会議室デビュー日: 2003/03/31
投稿数: 65
投稿日時: 2003-04-07 10:45
それはMemoryStreamの問題ではありません。FileStreamだと出力されている「ように見える」のは、Closeした後に別の手段で結果を見られるからです。MemoryStreamでも、Closeした後にメモリを確認できれば、結果が書き込まれているはずです。

ICryptoTransform.InputBlockSizeに満たないサイズのブロックを最後に出力したい場合は、crypto.FlushFinalBlock();をすればいいです。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2003-04-07 11:04
DES はブロック暗号では? http://www.wani.net/bak/crypt/blockstr.htm

[ メッセージ編集済み 編集者: MMX 編集日時 2003-04-07 11:08 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-04-07 11:19
こんにちは。
引用:

MMXさんの書き込み (2003-04-07 11:04) より:
DES はブロック暗号では? http://www.wani.net/bak/crypt/blockstr.htm



 はい。それを、「des.Padding = PaddingMode.PKCS7;」で、
「ブロックに足りない分をパディングしてください」と、お願いしています。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-04-07 11:50
こんにちは。
引用:

NothingButXMLInfoSetさんの書き込み (2003-04-07 10:45) より:
それはMemoryStreamの問題ではありません。FileStreamだと出力されている「ように見える」のは、Closeした後に別の手段で結果を見られるからです。MemoryStreamでも、Closeした後にメモリを確認できれば、結果が書き込まれているはずです。

ICryptoTransform.InputBlockSizeに満たないサイズのブロックを最後に出力したい場合は、crypto.FlushFinalBlock();をすればいいです。


 なるほど・・・確認しました。どうもありがとうございます。CryptoStreamのFlushは、その他のStreamのFlushと動作が少し違うということですね。MSDNの解説文が難解ですが・・・


・暗号化/復号するエンコーダにバッファがある
・CryptoStreamにバッファがある
・CryptoStreamが利用するStreamにバッファがある
→CryptoStream.FlushFinalBlockは、エンコーダのバッファをCryptoStreamにフラッシュさせる
→CryptoStream.Flushは、CryptoStramのバッファ内容をStreamにフラッシュさせる

という理解でよろしいでしょうか。
1

スキルアップ/キャリアアップ(JOB@IT)