質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

解決済

バイト列をBinaryWriterで出力してもテキストで出力される

tomy-c
tomy-c

総合スコア179

バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

1回答

0評価

1クリップ

1877閲覧

投稿2020/12/14 01:01

編集2020/12/14 05:23

現在、数年来のリハビリがてら、
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で見つけたので試した →テキスト出力される

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

Zuishin

2020/12/14 01:07

BinaryWriter が何をするものかを調べてください。
SurferOnWww

2020/12/14 01:12 編集

コードのどの行のことを言っているのですか? コメント「//正しくバイト型に変換できている」の下のこれですか? ⇒ writer.Write(p,0,p.Length);
tomy-c

2020/12/14 01:22 編集

SurferOnWwwさん、申し訳ありません、問題発生箇所は writer.Write(p,0,p.Length); の出力部分になります。
kikukiku

2020/12/14 01:23

public_key = rsa.ToXmlString(false);でセットされたpublic_keyは、 テキスト情報なので勘違いしていませんか?
退会済みユーザー

退会済みユーザー

2020/12/14 01:30

入力元データと、実際に出力したい(想定している)データを記載した方がよいかもしれません。現状、stringをバイト配列にして書き込んでいるだけなので、テキストが出力されるのは当たり前です。
SurferOnWww

2020/12/14 01:35

文字列 "ABC あいう" の utf-8 のバイト列をファイルに書き込んだからメモ帳でそのファイルを開くとその文字列が表示されるという当たり前の話のように思えますが?
tomy-c

2020/12/14 01:52 編集

皆さんのご指摘からおそらく自分のファイル関連に関しての基礎知識が色々間違っていると確信し始めていますが(このあたりのコードを組むのが初めて)、鍵情報が含まれた文字列をバイナリデータ(2進数のデータ)に変換してBinaryWriterで出力することでバイナリファイル(ヘキサエディタを使わないと読めないようなファイル)を目的として作っています。
SurferOnWww

2020/12/14 01:53 編集

> 成果物としてはRSACryptoServiceProvider.ToXmlStringで出力したstringをテキストエディタで普通に開いただけでは内容が理解できないバイナリファイルにすることをイメージしています。 あなたの言う「バイナリファイル」というのは一体何なのですか? 「出力したstring」というのは開けば読める文字列らしいので、それを暗号化してファイルに保存しない限りはファイルを開いて読めるのは当たり前ですけど、そのあたり理解できてますか? 暗号化まではしなくても BASE64 にエンコードして保存してはいかが? それでも読む人が読めば読めますけど、知らない人には理解不能ですから。
Zuishin

2020/12/14 01:59

BinaryWriter が何をするものか調べましたか?
Zuishin

2020/12/14 02:03

> 自戒の為に書く問題解決の心得 この中に「信頼できる情報ソースにあたる」がありません。根本的に間違っています。
退会済みユーザー

退会済みユーザー

2020/12/14 02:17

> 鍵情報が含まれた文字列をバイナリデータ(2進数のデータ)に変換してBinaryWriterで出力することでバイナリファイル(ヘキサエディタを使わないと読めないようなファイル)を目的として作っています。 まず、そのバイナリ形式をどうするかから考える所から始めてください。例えば、テキストをzipファイルに圧縮すれば、一応テキストエディタでは読めないバイナリが出来上がります。(圧縮解凍ソフトでは当然読めますが) インプットとアウトプットを明確にしないと、誰も回答する事は出来ません。
tomy-c

2020/12/14 02:19

<Zuishinさん MSDNでは ''' プリミティブ型をバイナリでストリームに書き込みます。特定のエンコーディングの文字列の書き込みをサポートします。 注釈: プリミティブデータ型のストリームへの書き込みを容易にするメソッドが用意されています。 たとえば、メソッドを使用し Write て、1バイト値としてストリームにブール値を書き込むことができます。 ''' とあり、バイナリでストリームに書き込みます。とあったのでこちらを使えばバイナリで書き込まれると認識していました。 (いろいろ調べても普通のテキスト形式で書き込むStreamWriterとバイナリ形式で書き込むBinaryWriterという形でヒットしました。)
tomy-c

2020/12/14 02:24

<SurferOnWwwさん < あなたの言う「バイナリファイル」というのは一体何なのですか?  という箇所についてですが、自分の中(独学なので間違っている気がしますが)ではバイナリ(2進数)のデータを出力した[人には理解しづらい]ファイル という認識でいました。 そのため、文字列をバイト配列に変換して出力すればそれはバイナリファイルなのではという考えでこのプログラムを作っています。
退会済みユーザー

退会済みユーザー

2020/12/14 02:25

何かすごい勘違いをしていそうですが、貴方の言うテキストというものも、ファイルに書き込まれた状態では、テキストと解釈する事が出来る形式の只のバイナリなのです。
SurferOnWww

2020/12/14 02:39

> 自分の中(独学なので間違っている気がしますが)ではバイナリ(2進数)のデータを出力した[人には理解しづらい]ファイル という認識でいました。 先のコメントでも書きましたが、文字列 "ABC あいう" の utf-8 のバイト列をファイルに書き込んだからメモ帳でそのファイルを開くとその文字列が表示されるという当たり前の話ということを理解してください。そこに理解がないとこの先話は通じません。 これも先のコメントに書きましたが、「出力したstring」というのは開けば読める文字列らしいので、それを暗号化してファイルに保存しない限りはファイルを開いて読めるのは当たり前です。エンコーディングによってバイト列の内容は異なりますが、読めることには変わりありません。 暗号化まではしなくても BASE64 にエンコードして保存してはいかが? それでも読む人が読めば読めますけど、知らない人には理解不能ですから。
SurferOnWww

2020/12/14 03:03

BASE64 にエンコードして保存する案を回答欄に書いておきます。BASE64 では読む人が読めば読めるのでダメと言うことであれば、BASE64 に代えて暗号化を考えるということになると思います。
tomy-c

2020/12/14 03:05

<radianさん、SurferOnWwwさん <何かすごい勘違いをしていそうですが、貴方の言うテキストというものも、ファイルに書き込まれた状態では、テキストと解釈する事が出来る形式の只のバイナリなのです。 <先のコメントでも書きましたが、文字列 "ABC あいう" の utf-8 のバイト列をファイルに書き込んだからメモ帳でそのファイルを開くとその文字列が表示されるという当たり前の話ということを理解してください。 あぁ、なるほど。メモ帳などのテキストエディタは[文字のバイナリ]を文字列にデコードすることで人が理解できる文字として表示するから、今回平文の文字列を何も加工せずにバイナリとして出力したら当然メモ帳で開いたときにテキストとして表示されるということですね。 その辺の知識が欠落していたため、今回の動作は正常なのに異常と自身が認識したんだと思います・・・
kikukiku

2020/12/14 03:12

「暗号化、復号化に関しては正しく動作するプログラムが完成しているのですが」と記述されているので 暗号化キーを記録したファイルを読みだしてなんかするアプリはすでに出来ていると解釈しました。 だとすると、そのアプリのファイル仕様が明確になっているはずです。 その仕様を確認しましょう。 その仕様とは、暗号化キーをファイル出力と言っても、 形式をどのようなものにするかによっても変わってきますので、 もっと深く仕様を確認する必要があります。 その仕様が出てくると、具体的にこんなコードで出力できるという回答をすることができます。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。