トップ回答者
画像にユーザーがアクセスできないようにするには。

質問
回答
-
acslearner さんからの引用 Azuleanさんからの引用
★MemoryStreamを経由して保存する
・MemoryStreamを作る。
・MemoryStreamを使ってBitmapをSaveする。
・MemoryStreamからCryptoStreamに書き写す。
★MemoryStreamを経由して読み出す。
・MemroyStreamを作る。
・CryptoStreamからMemoryStreamに書き写す。
・MemoryStreamの現在位置をSeekで先頭に戻す。
・BitmapコンストラクタにMemoryStreamを渡す。
青字のところでいきなりつまづきました。
青文字のところはできていて、その次のCryptoStreamへの書き写しが引っかかっているように見えました。
acslearner さんからの引用 Azuleanさんからの引用
※ソース中にcs2とfs2の取り違えがある点はご注意ください。
どの部分がどの様に間違っているかはっきりわかりませんでした。
cs2を通して読み込まないといけないのに、new Bitmapに渡しているのがfs2になっている点です。
acslearner さんからの引用 わからないなりにしぼりだしたコードが下記です。
添削よろしくおねがいいたします。
1回、さっくりと書きますので、どういったことを行っているか考えてみてもらえませんか?
お願い:コードをコピペして済まさないでください。
サンプルを見て、知識なり考え方なり、何らかの形で自分の力にしてください。
Code Snippetusing (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
byte[] desKey = des.Key;
byte[] desIV = des.IV;// 暗号化して保存
using (Bitmap fileBitmap = new Bitmap("Test.png"))
{
using (FileStream writeFileStream =
new FileStream("Encrypted.png", FileMode.Create, FileAccess.Write))
using (CryptoStream cryptStream =new CryptoStream(writeFileStream,
des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write))
{
using (MemoryStream writeMemoryStream = new MemoryStream())
{
// MemoryStreamに保存
fileBitmap.Save(writeMemoryStream, ImageFormat.Png);
// MemoryStream→CryptoStream→FileStream
writeMemoryStream.WriteTo(cryptStream);
}
}
}// 復号して読み込み
using (FileStream readFileStream =
new FileStream("Encrypted.png", FileMode.Open, FileAccess.Read))
using (CryptoStream decryptStream = new CryptoStream(readFileStream,
des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read))
using (BinaryReader readBinaryReader = new BinaryReader(decryptStream))
using (MemoryStream temporaryMemoryStream = new MemoryStream())
{
// FileStream→CryptoStream→MemoryStream
byte[] buffer;
while((buffer = readBinaryReader.ReadBytes(1024)) != null)
{
if (buffer.Length == 0) break;
temporaryMemoryStream.Write(buffer, 0, buffer.Length);
}// MemoryStreamから読み込み (Seekしておかないとまずいはず)
temporaryMemoryStream.Seek(0, SeekOrigin.Begin);
using (Bitmap savedBitmap = new Bitmap(temporaryMemoryStream))
{
// 読み込んだ結果を確認するために保存
savedBitmap.Save("Restored.png", ImageFormat.Png);
}
}
}
すべての返信
-
acslearner さんからの引用 アプリケーションと同じ階層に何種類かの画像を置いて、アプリケーションから使用しています。
ユーザーからは、アプリケーションを起動していない時など、アクセスできないようにしたいのですが、
そういったことは可能なのでしょうか?
普通の画像ファイルであれば無理でしょう。
アプリケーションが起動していないときにファイルへのアクセスを制御する術はありません。
アプリケーションのリソースとして必要な画像を持っておけば、簡単には開けなくなります。
(参考:http://dobon.net/vb/dotnet/programing/bitmapresource.html)
アプリケーションの外にファイルを置くのであれば、ファイルを暗号化しておき、必要なときに復号して画面に表示するといったところでしょうか。
(参考:http://dobon.net/vb/dotnet/string/encryptfile.html)
※厳密にはそれなりの知識を持って時間をかければ、リソースから取り出したり、復号したりは可能です。
※ファイルシステムのセキュリティ設定は実行ユーザを設定する等の施策が必要なので、多分回答にならないかなと判断しています。 -
Code Snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testAppli2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap bmp;
private void Form1_Load(object sender, EventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
bmp =new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
Invalidate();
}private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, new Point(0, 0));
}
}
}上記のようにコーディングしたところ、下のようなエラーが出てしまいました。どうすればよいでしょうか。
エラーエラー 1 'testAppli2.Form1.Dispose(bool)': オーバーライドする適切なメソッドが見つかりませんでした。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli2\testAppli2\Form1.Designer.cs 14 33 testAppli2
-
acslearner さんからの引用 上記のようにコーディングしたところ、下のようなエラーが出てしまいました。どうすればよいでしょうか。
エラーエラー 1 'testAppli2.Form1.Dispose(bool)': オーバーライドする適切なメソッドが見つかりませんでした。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli2\testAppli2\Form1.Designer.cs 14 33 testAppli2とりあえず、Form1.Designer.csを確認してみては?
載せられているコードはForm1.csだけなので、エラー内容から原因を教えてくれというのは無理があります。
※恐らくは、Form1.Designer.csに書かれているForm1がFormの派生クラスになっていないとみられますが、現状の情報じゃ何とも言えません。
-
acslearner さんからの引用 Code Snippetprivate void Form1_Load(object sender, EventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
bmp =new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
Invalidate();
}あと、LoadイベントでInvalidateを呼ぶのは辞めた方が良いでしょう。
まだ、Formは表示されていない状態ですから。
-
Form1.Designer.cs
namespace testAppli2
{
partial class Form1
{
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}#region Windows フォーム デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 263);
this.Name = "Form1";
this.Text = "Form1";
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);}
#endregion
}
}Form1.Designer.csは上記の通りです。
-
testAppli3を新たに作ったところ(Form1.Designer.csの中身は同じ)おかしな状態は再現できませんでした。
しかし、testAppli2のForm1.csのビルドアクションが"なし"になっていたので"コンパイル"にしたところ"ビルド正常"と表示されました。
ただしエラー一覧に
エラー警告 1 ファイル内にデザインできるクラスがないため、このファイルのデザイナを表示できませんでした。ファイルの以下のクラスがデザイナで見つかりました:
Form1 --- 基本クラス 'System.Object' をデザインできません。 0 0
が残りました。
何か変なことをしてしまったようなのですが、思い出せません。testAppli3では再現しなかったのでこの問題は置いておいてtestAppli3で話を進めていきたいと思います。すみません。
-
Code Snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace testAppli3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;private void Form1_Load(object sender, EventArgs e)
{
System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();
bmp = new Bitmap(myAssembly.GetManifestResourceStream("Map.png"));
}
private void Form1_MouseDoubleClick(object sender, MouseEventArgs e)
{
Invalidate();
}private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, new Point(0, 0));
}
}
}Azuleanさんからの引用アプリケーションのリソースとして必要な画像を持っておけば、簡単には開けなくなります。
(参考:http://dobon.net/vb/dotnet/programing/bitmapresource.html)
に従って、Map.pngを追加しました。Map.pngのビルドアクションは"埋め込まれたリソース"に設定しました。
上記のコードで、デバッグしましたが、例外「'null' の値は 'stream' に対して有効ではありません。」がでて失敗しました。
-
"Map.png" じゃなくて "testAppli3.Map.png" じゃないですか?
http://msdn.microsoft.com/ja-jp/library/yf17tthe.aspx
Assembly.GetManifestResourceNames メソッド で確認してください。
http://msdn.microsoft.com/ja-jp/library/system.reflection.assembly.getmanifestresourcenames(VS.80).aspx -
Azuleanさんからの引用
アプリケーションの外にファイルを置くのであれば、ファイルを暗号化しておき、必要なときに復号して画面に表示するといったところでしょうか。
(参考:http://dobon.net/vb/dotnet/string/encryptfile.html)
Bitmap bmp=new Bitmap("Map2.png");
Bitmap tBmp;
のあと
①bmpを暗号化しファイル出力して保存する。
②保存したファイルを読み込んで復号化して、tBmpに格納する。
以上をできるだけシンプルに行いたいのですが、力不足で、色々調べたのですが自分ではコーディングできませんでした。
どうかよろしくお願いします。
-
acslearner さんからの引用 Bitmap bmp=new Bitmap("Map2.png");
Bitmap tBmp;
のあと
①bmpを暗号化しファイル出力して保存する。
②保存したファイルを読み込んで複合化して、tBmpに格納する。
以上をできるだけシンプルに行いたいのですが、力不足で、色々調べたのですが自分ではコーディングできませんでした。
どうかよろしくお願いします。
何をお願いしているのか明確ではありませんが、少なくとも私はコードを代理で書く人ではありませんので、ご自身の手でコードを書いて下さい。
私の時間も限られており、あまり余裕がないので、要点だけ書いておきます。
・書き込み
FileStreamを作る。
暗号化Streamを作って、先のFileStreamと関連づける。
暗号化StreamをBitmap.Saveメソッドに渡す。
保存されたファイルは暗号化された状態。
・読み込み
FileStreamを作る。
復号Streamを作って、先のFileStreamと関連づける。
復号StreamをBitmapのコンストラクタに渡す。
復号を行ってBitmapのインスタンスが作成される。
先に示したどぼんさんのサンプルから暗号化・復号の基本的な流れを理解し、Bitmap.Save(Stream)メソッドやBitmap(Stream)コンストラクタをうまく組み合わせる応用ができれば、既存のクラスの組み合わせで実現できるはずです。
(実際にうまくできるかは確かめていません。間違っていることに気づかれた方はご指摘をお願いします)
http://msdn.microsoft.com/ja-jp/library/ms142147.aspx
http://msdn.microsoft.com/ja-jp/library/ms142147.aspx
-
http://www.microsoft.com/japan/msdn/thisweek/300x10/phase2/encrypt/cs.aspx
http://support.microsoft.com/kb/307010/ja
上記の参照も見つけました。まだコーディングには成功していません。格闘中です。
時間のある方はご協力お願いいたします。
-
Code Snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
public bool isClick = false;
private byte[] DesKey;
private byte[] DesIV;
private byte[] cryptData;private void Form1_Load(object sender, EventArgs e)
{
byte[] source = Encoding.Unicode.GetBytes("Map2.png");// Triple DES のサービス プロバイダを生成します
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();// 入出力用のストリームを生成します
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DesKey, DesIV),
CryptoStreamMode.Write);// ストリームに暗号化されたデータを書き込みます
cs.Write(cryptData, 0, cryptData.Length);
bmp.Save(cs);
cs.Close();tBmp(ms);
ms.Close();}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (isClick == false) isClick = true;
else isClick = false;Invalidate();
}private void Form1_Paint(object sender, PaintEventArgs e)
{
if (isClick == true) e.Graphics.DrawImage(bmp, new Point(0, 0));
else if (isClick == false) e.Graphics.DrawImage(tBmp, new Point(0, 0));
}
}
}エラ-エラー 1 'System.Drawing.Image.Save(string)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 42 13 testAppli4
エラー 2 引数 '1': 'System.Security.Cryptography.CryptoStream' から 'string' に変換できません。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 42 22 testAppli4
エラー 3 'testAppli4.Form1.tBmp' は 'フィールド' ですが、'メソッド' のように使用されています。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 45 13 testAppli4
-
もう少し初歩的なところから固めた方が良いのではないかと不安を感じます。
その場限りの答えを示すことはできますが、力になるのかどうか疑問を抱いているため、コードを書いていません。あしからずご了承ください。
(答えがあればそれからどのように間違えていたかを含めて、仕組みを理解できるというのであればその旨レスをください)
acslearner さんからの引用 Code Snippetprivate void Form1_Load(object sender, EventArgs e)
{// 略
bmp.Save(cs);
cs.Close();tBmp(ms);
ms.Close();}
}
(私が言うのも難ですが…、)私の書き間違えをそのまま鵜呑みにしないでください。
そして、エラー内容とヘルプを見比べて下さい。
・Streamを1個だけ渡すSaveメソッドは存在しません。適切な引数を与えて下さい。
・コンストラクタの呼び方についてもう少し初歩から考えてみて下さい。tBmp(ms)はC#の構文上、何がやりたいのか見えない形になっています。
・コンパイルが通っても、実行時にArgumentNullExceptionが置きます。今のコードは何をしているか考えてみて下さい。
暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。
それができてから、暗号化ストリームと組み合わせましょう。
-
Azuleanさんからの引用
暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Drawing.Imaging;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
private void Form1_Load(object sender, EventArgs e)
{
FileStream fs;
fs = new FileStream("Map2.png", FileMode.Open, FileAccess.Read);
bmp = new Bitmap(fs);
bmp.Save(fs, ImageFormat.Png);
fs.Close();
}private void Form1_MouseClick(object sender, MouseEventArgs e)
{}
private void Form1_Paint(object sender, PaintEventArgs e)
{}
}
}やってみましたが、失敗しました(TДT)確かに初歩的なことが分かっていません。
例外Just-In-Time (JIT) デバッグを呼び出すための詳細については、
ダイアログ ボックスではなく、このメッセージの最後を参照してください。************** 例外テキスト **************
System.Runtime.InteropServices.ExternalException: GDI+ で汎用エラーが発生しました。
場所 System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
場所 System.Drawing.Image.Save(Stream stream, ImageFormat format)
場所 testAppli4.Form1.Form1_Load(Object sender, EventArgs e) 場所 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs:行 29
場所 System.Windows.Forms.Form.OnLoad(EventArgs e)
場所 System.Windows.Forms.Form.OnCreateControl()
場所 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
場所 System.Windows.Forms.Control.CreateControl()
場所 System.Windows.Forms.Control.WmShowWindow(Message& m)
場所 System.Windows.Forms.Control.WndProc(Message& m)
場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
場所 System.Windows.Forms.ContainerControl.WndProc(Message& m)
場所 System.Windows.Forms.Form.WmShowWindow(Message& m)
場所 System.Windows.Forms.Form.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
************** 読み込まれたアセンブリ **************
mscorlib
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
testAppli4
アセンブリ バージョン: 1.0.0.0
Win32 バージョン: 1.0.0.0
コードベース: file:///C:/Users/Y/Documents/Visual%20Studio%202005/Projects/testAppli4/testAppli4/bin/Release/testAppli4.exe
----------------------------------------
System.Windows.Forms
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
mscorlib.resources
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
System.Drawing.resources
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing.resources/2.0.0.0_ja_b03f5f7f11d50a3a/System.Drawing.resources.dll
----------------------------------------
System.Windows.Forms.resources
アセンブリ バージョン: 2.0.0.0
Win32 バージョン: 2.0.50727.312 (rtmLHS.050727-3100)
コードベース: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_ja_b77a5c561934e089/System.Windows.Forms.resources.dll
----------------------------------------************** JIT デバッグ **************
Just-In-Time (JIT) デバッグを有効にするには、このアプリケーション、
またはコンピュータ (machine.config) の構成ファイルの jitDebugging
値を system.windows.forms セクションで設定しなければなりません。
アプリケーションはまた、デバッグを有効にしてコンパイルされなければ
なりません。例:
<configuration>
<system.windows.forms jitDebugging="true" />
</configuration>JIT デバッグが有効なときは、このダイアログ ボックスで処理するよりも、
ハンドルされていない例外はすべてコンピュータに登録された
JIT デバッガに設定されなければなりません。http://blog.kaburk.com/lang/csharp-filestream-save.html
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=15772&forum=7&6
以上を参考にしました。
-
acslearner さんからの引用 Code Snippetprivate void Form1_Load(object sender, EventArgs e)
{
FileStream fs;
fs = new FileStream("Map2.png", FileMode.Open, FileAccess.Read);
bmp = new Bitmap(fs);
bmp.Save(fs, ImageFormat.Png);
fs.Close();
}Readという読み取りで開いたFileStreamにSaveという書き込みはできませんよね。
FileStreamクラスのコンストラクタやFileAccess列挙体のヘルプは読みましたか?
新しい要素を使う前には、そのヘルプを一度読み込むぐらいでないと、応用が利かなくなってきますよ。
ありがちなトラブル:
・ファイルを開いたままもう1個開こうとして失敗する。
・読み書きアクセスして、末尾に新しいデータを書き込んだため、サイズが2倍ぐらいにふくれあがる。または壊れるか意図した書き換えが行えない。
・最初に書き込みアクセスしてBitmapクラスのコンストラクタで読み込めない。
ところで、掲示板でやりとりして進めている間は、私の時間的な都合もあるため、1日1レスポンス分しか進みません。
片手間の趣味というのであれば良いのですが、会社の研修であるならば上司か研修担当者に、学術的なものならば周りの詳しい人に相談することをお薦めします。(期限は待ってくれないので)
趣味であっても、これまでに体系的に学べているかどうかで、今後の応用力が変わるので、教本を手に取り直すか、もっと別の本に手を出してみるのも良いかもしれません。 -
★ファイルの保存の流れ
1.ファイルを読み込むか、自分で作るかしてBitmapインスタンスを用意する。
2.FileStreamインスタンスを書き込みで作成する。
3.Saveメソッドに2で作ったインスタンスを渡す。
4.2で作ったインスタンスを閉じる。
★ファイル読み出しの流れ
1.FileStreamインスタンスを読み込みで作成する。
2.Bitmapのコンストラクタに1で作ったインスタンスを渡す。
★暗号化・復号と組み合わせることを考える
・BitmapコンストラクタやSaveメソッドはStreamクラスのインスタンスを引数に取る。
・FileStreamもCryptoStreamもStreamクラスの派生クラスなので、Streamクラスのインスタンスの代わりとして渡すことができる。
・FileStreamで保存・読み込みが実現できればもう一歩。
・FileStreamを使ってCryptoStreamを作り、CryptoStreamをSaveやコンストラクタに渡せれば暗号化しつつ書き込み、復号しつつ読み込みをやってくれる。
-
Azuleanさんからの引用暗号化は一旦置いておいて、FileStreamを使ってBitmapを保存すること、FileStreamを使ってBitmapを読み込むことをまず実現して下さい。Code Snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Drawing.Imaging;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
private void Form1_Load(object sender, EventArgs e)
{
bmp = new Bitmap("Map2.png");
FileStream fs;
fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
bmp.Save(fs, ImageFormat.Png);
fs.Close();
FileStream fs2;
fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
tBmp = new Bitmap(fs2);
fs2.Close();
//確認のため
tBmp.Save("x.png");
}private void Form1_MouseClick(object sender, MouseEventArgs e)
{}
private void Form1_Paint(object sender, PaintEventArgs e)
{}
}
}一段階ですがやっとできました。
-
Code Snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Drawing.Imaging;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
private byte[] DesKey;
private byte[] DesIV;private void Form1_Load(object sender, EventArgs e)
{
FileStream fs;
bmp = new Bitmap("Map2.png");fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);
bmp.Save(cs, ImageFormat.Png);
fs.Close();
cs.Close();FileStream fs2;
fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
CryptoStream cs2 = new CryptoStream(fs2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
tBmp = new Bitmap(fs2);
fs2.Close();
cs2.Close();
//確認のため
tBmp.Save("x.png");
}private void Form1_MouseClick(object sender, MouseEventArgs e)
{}
private void Form1_Paint(object sender, PaintEventArgs e)
{}
}
}エラー警告 1 フィールド 'testAppli4.Form1.DesKey' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 24 24 testAppli4
警告 2 フィールド 'testAppli4.Form1.DesIV' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 25 24 testAppli4 -
acslearner さんからの引用 エラー警告 1 フィールド 'testAppli4.Form1.DesKey' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 24 24 testAppli4
警告 2 フィールド 'testAppli4.Form1.DesIV' は割り当てられません。常に既定値 null を使用します。 C:\Users\Y\Documents\Visual Studio 2005\Projects\testAppli4\testAppli4\Form1.cs 25 24 testAppli4書いてみたのですが、エラーがでてしまいました。アドバイスよろしくお願いいたします。
それはエラーではなく、警告です。
しかし、実行時に例外がスローされて、実行が中断されると思います。
DesKeyやDesIVは暗号化・復号の際に使用されます。
何を設定するかは開発者次第ですが、適切な値を与えてあげないと暗号化・復号はできません。
-
デバッグすると、「GDI+ で汎用エラーが発生しました。」になってしまいました。
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Drawing.Imaging;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
private byte[] DesKey;private byte[] DesIV;
private void Form1_Load(object sender, EventArgs e)
{
FileStream fs;
bmp = new Bitmap("Map2.png");fs = new FileStream("Map3.png", FileMode.Open, FileAccess.Write);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
DesKey = des.Key;
DesIV = des.IV;
CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);
bmp.Save(cs, ImageFormat.Png);
fs.Close();
cs.Close();FileStream fs2;
fs2 = new FileStream("Map3.png", FileMode.Open, FileAccess.Read);
CryptoStream cs2 = new CryptoStream(fs2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
tBmp = new Bitmap(fs2);
fs2.Close();
cs2.Close();
//確認のため
tBmp.Save("x.png");
}private void Form1_MouseClick(object sender, MouseEventArgs e)
{}
private void Form1_Paint(object sender, PaintEventArgs e)
{}
}
} -
acslearner さんからの引用 デバッグすると、「GDI+ で汎用エラーが発生しました。」になってしまいました。
PNGはCanSeek = falseなStream(CryptoStreamがそうなっている)には書けないようです。
JPEGだとうまくいくかと思います。
参考: http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=13363&forum=7
※ソース中にcs2とfs2の取り違えがある点はご注意ください。
PNGフォーマットを暗号化・復号する形で実現したい場合は、一度MemoryStreamか、テンポラリファイルを経由することになりそうです。
★MemoryStreamを経由して保存する
・MemoryStreamを作る。
・MemoryStreamを使ってBitmapをSaveする。
・MemoryStreamからCryptoStreamに書き写す。
★MemoryStreamを経由して読み出す。
・MemroyStreamを作る。
・CryptoStreamからMemoryStreamに書き写す。
・MemoryStreamの現在位置をSeekで先頭に戻す。
・BitmapコンストラクタにMemoryStreamを渡す。
-
暗号化のキーがコードに埋め込まれていると、ディスアセンブルで見えちゃうんですよね。
単純なものでよければ、こんな方法も。
-
あきらめる。
期間の多少はあれ、ほぼ必ずクラックされるので、クラックされるものにリソースをかけるのは無駄かと思います。 -
拡張子を変更する。
単に .bmp を .oresama にするだけでも、ダブルクリックで開けないなどの効果はある。 -
スタンプを変更する。
.bmp など、先頭にフォーマット形式を示すコードがあるものについて、そのコードを書き換えておけば、開けなくはなる。
上との組み合わせが効果的? -
base64 エンコードする。
気休めでしかないけど。
-
-
Azuleanさんからの引用
★MemoryStreamを経由して保存する
・MemoryStreamを作る。
・MemoryStreamを使ってBitmapをSaveする。
・MemoryStreamからCryptoStreamに書き写す。
★MemoryStreamを経由して読み出す。
・MemroyStreamを作る。
・CryptoStreamからMemoryStreamに書き写す。
・MemoryStreamの現在位置をSeekで先頭に戻す。
・BitmapコンストラクタにMemoryStreamを渡す。
青字のところでいきなりつまづきました。
Azuleanさんからの引用
※ソース中にcs2とfs2の取り違えがある点はご注意ください。
どの部分がどの様に間違っているかはっきりわかりませんでした。
わからないなりにしぼりだしたコードが下記です。
「GDI+ で汎用エラーが発生しました。」は解消されていません。
添削よろしくおねがいいたします。
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Drawing.Imaging;
namespace testAppli4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Bitmap bmp;
public Bitmap tBmp;
private byte[] DesKey;
private byte[] DesIV;private void Form1_Load(object sender, EventArgs e)
{
MemoryStream ms;
bmp = new Bitmap("Map2.png");ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Png);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
DesKey = des.Key;
DesIV = des.IV;
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(DesKey, DesIV),CryptoStreamMode.Write);
bmp.Save(cs, ImageFormat.Png);
ms.Close();
cs.Close();MemoryStream ms2;
ms2 = new MemoryStream();
CryptoStream cs2 = new CryptoStream(ms2, des.CreateDecryptor(DesKey, DesIV), CryptoStreamMode.Read);
tBmp = new Bitmap(ms2);
ms2.Close();
cs2.Close();
//確認のため
tBmp.Save("x.png");
}private void Form1_MouseClick(object sender, MouseEventArgs e)
{}
private void Form1_Paint(object sender, PaintEventArgs e)
{}
}
} -
acslearner さんからの引用 Azuleanさんからの引用
★MemoryStreamを経由して保存する
・MemoryStreamを作る。
・MemoryStreamを使ってBitmapをSaveする。
・MemoryStreamからCryptoStreamに書き写す。
★MemoryStreamを経由して読み出す。
・MemroyStreamを作る。
・CryptoStreamからMemoryStreamに書き写す。
・MemoryStreamの現在位置をSeekで先頭に戻す。
・BitmapコンストラクタにMemoryStreamを渡す。
青字のところでいきなりつまづきました。
青文字のところはできていて、その次のCryptoStreamへの書き写しが引っかかっているように見えました。
acslearner さんからの引用 Azuleanさんからの引用
※ソース中にcs2とfs2の取り違えがある点はご注意ください。
どの部分がどの様に間違っているかはっきりわかりませんでした。
cs2を通して読み込まないといけないのに、new Bitmapに渡しているのがfs2になっている点です。
acslearner さんからの引用 わからないなりにしぼりだしたコードが下記です。
添削よろしくおねがいいたします。
1回、さっくりと書きますので、どういったことを行っているか考えてみてもらえませんか?
お願い:コードをコピペして済まさないでください。
サンプルを見て、知識なり考え方なり、何らかの形で自分の力にしてください。
Code Snippetusing (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
byte[] desKey = des.Key;
byte[] desIV = des.IV;// 暗号化して保存
using (Bitmap fileBitmap = new Bitmap("Test.png"))
{
using (FileStream writeFileStream =
new FileStream("Encrypted.png", FileMode.Create, FileAccess.Write))
using (CryptoStream cryptStream =new CryptoStream(writeFileStream,
des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write))
{
using (MemoryStream writeMemoryStream = new MemoryStream())
{
// MemoryStreamに保存
fileBitmap.Save(writeMemoryStream, ImageFormat.Png);
// MemoryStream→CryptoStream→FileStream
writeMemoryStream.WriteTo(cryptStream);
}
}
}// 復号して読み込み
using (FileStream readFileStream =
new FileStream("Encrypted.png", FileMode.Open, FileAccess.Read))
using (CryptoStream decryptStream = new CryptoStream(readFileStream,
des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read))
using (BinaryReader readBinaryReader = new BinaryReader(decryptStream))
using (MemoryStream temporaryMemoryStream = new MemoryStream())
{
// FileStream→CryptoStream→MemoryStream
byte[] buffer;
while((buffer = readBinaryReader.ReadBytes(1024)) != null)
{
if (buffer.Length == 0) break;
temporaryMemoryStream.Write(buffer, 0, buffer.Length);
}// MemoryStreamから読み込み (Seekしておかないとまずいはず)
temporaryMemoryStream.Seek(0, SeekOrigin.Begin);
using (Bitmap savedBitmap = new Bitmap(temporaryMemoryStream))
{
// 読み込んだ結果を確認するために保存
savedBitmap.Save("Restored.png", ImageFormat.Png);
}
}
} -
コードは見事成功していました。心から感謝申し上げますm(__)m
質問させていただきたいのですが、この1024という数字は、これより大きなファイルをあつかう時も有効なのでしょうか?
Code Snippetwhile((buffer = readBinaryReader.ReadBytes(1024)) != null)
-
acslearner さんからの引用 質問させていただきたいのですが、この1024という数字は、これより大きなファイルをあつかう時も有効なのでしょうか?
提示したものは1024バイトずつ、ファイルの終端まで繰り返し読み込むといったコードになっています。
繰り返しますので、1024バイトを越えるファイルでも特に問題ありませんが、1024バイトずつだと遅いとかはあり得るかもしれません。
acslearner さんからの引用 http://msdn.microsoft.com/ja-jp/library/system.io.binaryreader.readbytes(VS.71).aspx
ところで、このページはVS 2003(.NET Framework 1.1)相当です。
Visual Studio 2005や2008であればページ右上にあるリンクから、Visual Studio 2005(.NET Framework 2.0)やVisual Studio 2008(.NET Framework 3.5)向けのページを読むようにした方が良いのかもしれません。