現在、数年来のリハビリがてら、
C#のコンソールプログラムでRSAを用いた暗号化プログラムを作っているのですが、公開鍵、秘密鍵を生成し、バイナリファイルで出力しようとしています。
成果物としてはRSACryptoServiceProvider.ToXmlStringで出力したstringをテキストエディタで普通に開いただけでは内容が理解できないバイナリファイルにすることをイメージしています。
暗号化、復号化に関しては正しく動作するプログラムが完成しているのですが、
肝心の公開鍵、秘密鍵をC#のBinaryWriterで出力しても、出力したファイルは普通のテキスト形式で、メモ帳で開いても普通に中身が見れてしまいます。
そのため、別ツールなどでBinaryReader等を用い読み込んでもフォーマットの問題でエラーが発生してしまいます。
デバッグなどで一時停止し、書き込む中身のバイト配列変数等を確認しても変なデータ等は見られず、似たような事例も探しても見当たらないため、原因がわかりません。
どなたかご存じないでしょうか?
ソースコード
色々調査のためにいじってたので汚いです。
C#
/// <summary> /// 公開鍵、秘密鍵のペアを作成してファイル出力する /// </summary> /// <param name="binary_option_flg">バイナリ形式で出力するか。</param> /// <returns>作成した鍵のファイルを格納したフォルダパス。失敗時はNull</returns> public static string PutRSAKey(bool binary_option_flg = false) { //Assembly myAssembly = Assembly.GetEntryAssembly(); //string path = myAssembly.Location; string putdir = Directory.GetCurrentDirectory() + "/Keypair_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "/"; string pub_file_path = putdir + "public.dat"; string pri_file_path = putdir + "private.dat"; try { string public_key; string private_key; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { public_key = rsa.ToXmlString(false); //falseで公開鍵だけ返却 private_key = rsa.ToXmlString(true); //trueで公開、秘密鍵両方を返却 } //出力フォルダ作成 if (!Directory.Exists(putdir)) { Directory.CreateDirectory(putdir); } //using (var fs_pub = new FileStream(pub_file_path, FileMode.Create)) //using (var fs_pri = new FileStream(pri_file_path, FileMode.Create)) if (binary_option_flg) { using (var writer = new BinaryWriter(new FileStream(pub_file_path, FileMode.Create))) { //byte[] p = Encoding.GetEncoding("utf-8").GetBytes(public_key); byte[] p = Encoding.GetEncoding("utf-8").GetBytes("ABC あいう"); //for (int i=0; i< p.GetLength(0); i++) { // writer.Write(p[i]); //} Console.WriteLine(p[0].ToString()); //正しくバイト型に変換できている writer.Write(p,0,p.Length); //バイナリ形式で出力(※テキストで出力される) } using (var writer = new BinaryWriter(new FileStream(pri_file_path, FileMode.Create))) { writer.Write(private_key); } // byte[] pub = Encoding.GetEncoding("utf-8").GetBytes(public_key); // byte[] pri = Encoding.GetEncoding("utf-8").GetBytes(private_key); // //バイナリ形式で保存 // using (var sw = new BinaryWriter(fs_pub)) //{ // sw.Write(pub); //} //using (var sw = new BinaryWriter(fs_pri)) //{ // sw.Write(pri); //} } else { ////テキスト形式、上書き、UTF-8 //using (var sw = new StreamWriter(fs_pub, Encoding.UTF8)) //{ // sw.Write(public_key); //} //using (var sw = new StreamWriter(fs_pri, Encoding.UTF8)) //{ // sw.Write(private_key); //} } return putdir; } catch { return null; } }
###指摘後修正(ベストアンサー後)
※今回の問題はそもそも自身のイメージしているバイナリファイルの概念が間違っているのが原因でした。
そのため、異常して上げた箇所の動作はそもそもが正常な動作であり、それを間違った解釈から異常と判断していたのが問題でした。
C#
/// <summary> /// 公開鍵、秘密鍵のペアを作成してファイル出力する /// </summary> /// <returns>作成した鍵のファイルを格納したフォルダパス。失敗時はNull</returns> public static string PutRSAKey() { string putdir = Directory.GetCurrentDirectory() + "/Keypair_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "/"; string pub_file_path = putdir + "public.dat"; string pri_file_path = putdir + "private.dat"; try { string public_key; string private_key; using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { public_key = rsa.ToXmlString(false); //falseで公開鍵だけ返却 private_key = rsa.ToXmlString(true); //trueで公開、秘密鍵両方を返却 } //出力フォルダ作成 if (!Directory.Exists(putdir)) { Directory.CreateDirectory(putdir); } //テキスト形式、上書き、UTF-8 using (var sw = new StreamWriter(pub_file_path)) { sw.Write(Base64Encode(public_key)); } using (var sw = new StreamWriter(pri_file_path)) { sw.Write(Base64Encode(private_key)); } return putdir; } catch { return null; } } /// <summary> /// Base64で文字列を難読化する /// </summary> /// <param name="str"></param> /// <returns></returns> /// <remarks>エンコードはutf-8固定</remarks> private static string Base64Encode(string str) { Encoding enc = Encoding.GetEncoding("UTF-8"); return Convert.ToBase64String(enc.GetBytes(str)); } /// <summary> /// Base64で難読化された文字列を復号化する /// </summary> /// <param name="str"></param> /// <returns></returns> /// <remarks>エンコードはutf-8固定</remarks> private static string Base64Decode(string str) { Encoding enc = Encoding.GetEncoding("UTF-8"); return enc.GetString(Convert.FromBase64String(str)); }
試したこと
・バイト配列への変換方法を一文字づつに変えた → 変わらず
・適当な文字列そのものをバイト配列に変換して出力してみた → やっぱりテキストで出力される
・BinaryWriterの引数に普通の型(string)での出力をMSDNで見つけたので試した →テキスト出力される



まだ回答がついていません
会員登録して回答してみよう