C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[11]: バイナリファイルの暗号化について


(過去ログ 63 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■36104 / inTopicNo.1)  バイナリファイルの暗号化について
  
□投稿者/ ms (1回)-(2009/05/20(Wed) 23:12:49)

分類:[.NET 全般] 

現在、バイナリファイルを暗号化、複合化しています。
ですが、暗号化ファイルを書き込む箇所で"配列を作成する場合サイズが適切であることを確認します。"というエラーが出て書き込みできません。
短いファイルの場合は、エラーが出ないのですが、書き込むファイルのバイト数が大きい場合、エラーが出ます。
どなたかご教授いただけないでしょうか?
お願いします。

コードは、WEB公開のコードを参考にしています。環境はVB2008、XPです。
コードは以下になります。
Public Shared Sub EncryptFile(ByVal fileName As String, _
                             ByVal key As String)
        '暗号化するファイルを読み込む
        Dim fsIn As New System.IO.FileStream(fileName, _
            System.IO.FileMode.Open, System.IO.FileAccess.Read)
        'すべて読み込む
        Dim bytesIn(fsIn.Length - 1) As Byte
        fsIn.Read(bytesIn, 0, bytesIn.Length)
        '閉じる
        fsIn.Close()

        'DESCryptoServiceProviderオブジェクトの作成
        Dim des As New System.Security.Cryptography.DESCryptoServiceProvider

        '共有キーと初期化ベクタを決定
        'パスワードをバイト配列にする
        Dim bytesKey As Byte() = System.Text.Encoding.UTF8.GetBytes(key)
        '共有キーと初期化ベクタを設定
        des.Key = ResizeBytesArray(bytesKey, des.Key.Length)
        des.IV = ResizeBytesArray(bytesKey, des.IV.Length)

        '暗号化されたファイルの保存先
        Dim outFileName As String = fileName + ".enc"
        '暗号化されたファイルを書き出すためのFileStream
        Dim fsOut As New System.IO.FileStream(outFileName, _
            System.IO.FileMode.Create, System.IO.FileAccess.Write)
        'DES暗号化オブジェクトの作成
        Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
            des.CreateEncryptor()
        '書き込むためのCryptoStreamの作成
        Dim cryptStreem As New System.Security.Cryptography.CryptoStream( _
            fsOut, desdecrypt, _
            System.Security.Cryptography.CryptoStreamMode.Write)
        MsgBox(bytesIn.ToString)
        '書き込む
    '■■■■■■■■■ここでエラーが出ます。(エラー内容:"配列を作成する場合サイズが適切であることを確認します。")
        cryptStreem.Write(bytesIn, 0, bytesIn.Length)
       
        '閉じる
        cryptStreem.Close()
        fsOut.Close()
    End Sub

引用返信 編集キー/
■36105 / inTopicNo.2)  Re[1]: バイナリファイルの暗号化について
□投稿者/ Azulean (390回)-(2009/05/20(Wed) 23:17:07)
No36104 (ms さん) に返信
> ですが、暗号化ファイルを書き込む箇所で"配列を作成する場合サイズが適切であることを確認します。"というエラーが出て書き込みできません。
> 短いファイルの場合は、エラーが出ないのですが、書き込むファイルのバイト数が大きい場合、エラーが出ます。
成功するファイルのサイズはどのくらいで、失敗するときのファイルのサイズはどのくらいなのですか?
引用返信 編集キー/
■36107 / inTopicNo.3)  Re[2]: バイナリファイルの暗号化について
□投稿者/ ms (2回)-(2009/05/20(Wed) 23:26:13)

> 成功するファイルのサイズはどのくらいで、失敗するときのファイルのサイズはどのくらいなのですか?

Azuleanさんご返信ありがとうございます。
成功するファイルのサイズは、149MBで、失敗するファイルのサイズは、456MBです。
引用返信 編集キー/
■36109 / inTopicNo.4)  Re[3]: バイナリファイルの暗号化について
□投稿者/ Hongliang (384回)-(2009/05/20(Wed) 23:42:47)
さすがに数百 MB をオンメモリで処理しようというのは難しいかと思います。
FileStream から一気にすべて読み出すのではなく、たとえば数 MB ずつ読み出しては CryptoStream に書き込むのを繰り返す、とかすればどうでしょう。
引用返信 編集キー/
■36113 / inTopicNo.5)  Re[4]: バイナリファイルの暗号化について
□投稿者/ ms (3回)-(2009/05/21(Thu) 08:44:45)
No36109 (Hongliang さん) に返信
> さすがに数百 MB をオンメモリで処理しようというのは難しいかと思います。
> FileStream から一気にすべて読み出すのではなく、たとえば数 MB ずつ読み出しては CryptoStream に書き込むのを繰り返す、とかすればどうでしょう。

Hongliang さんご返信ありがとうございます。
> さすがに数百 MB をオンメモリで処理しようというのは難しいかと思います。
そうだったんですね。
オンメモリというのも知らなかったので、勉強になります。早速調べて実装し、コードをアップします。

引用返信 編集キー/
■36145 / inTopicNo.6)  Re[5]: バイナリファイルの暗号化について
□投稿者/ ms (4回)-(2009/05/22(Fri) 09:22:33)
No36113 (ms さん) に返信
> ■No36109 (Hongliang さん) に返信
>>さすがに数百 MB をオンメモリで処理しようというのは難しいかと思います。
>>FileStream から一気にすべて読み出すのではなく、たとえば数 MB ずつ読み出しては CryptoStream に書き込むのを繰り返す、とかすればどうでしょう。
>

実装してみたのですが、どうにもうまくいきません。
最初のファイルを少しづつ読み込むのは、できたのですが、その後、少しづつファイルへ書き込むことができません。ですので、暗号化のファイルを書き込むところまで、たどり着いていません。
ファイルをバイト配列に読み込んだ後、ファイルに書き出す方法をどなたかご教授いただけないでしょうか?
お願いします。

コードは以下になります。
mports System.IO
Public Class Form1
'ファイル読み込み用(バイトで読込む)
Dim readByte As Byte() = Nothing
Dim WriteByte As Byte() = Nothing
Dim fileName As String = ""
Dim outFileName As String = ""

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'読み込むファイル名
fileName = "C:\TEST.txt"
    '読み込んだファイルを書き出すファイル名
outFileName = "C:\TEST2.txt"

'配列のインスタンスを生成する
readByte = New Byte(1023) {}

'ファイルの有無確認
If IO.File.Exists(fileName) = True Then

'ファイルを開く
Dim fs As New System.IO.FileStream(fileName, _
System.IO.FileMode.Open, _
System.IO.FileAccess.Read, _
System.IO.FileShare.Read, _
&H1000, _
True)

'非同期の読込みを開始する
fs.BeginRead(readByte, 0, readByte.Length, _
New AsyncCallback(AddressOf ReadBytescallback), fs)

End If

End Sub

'ファイルを読込む
Private Sub ReadBytescallback(ByVal ar As IAsyncResult)

'バイト配列にファイルを読込む
'fileStreamの取得
Dim fs As System.IO.FileStream = _
CType(ar.AsyncState, System.IO.FileStream)

'読込んだサイズを取得
Dim readSize As Integer = fs.EndRead(ar)

If readSize > 0 Then
'読み込み始めたとき
'残りの読み込みを行う
'readByteに読込んだデータが格納されている
fs.BeginRead(readByte, 0, readByte.Length, _
New AsyncCallback(AddressOf ReadBytescallback), fs)


Else
'ファイルを閉じる
fs.Close()

'ファイルを開く'アクセス権(書き込み)
Dim fsWrite As New System.IO.FileStream(outFileName, _
System.IO.FileMode.Append, _
System.IO.FileAccess.Write, _
System.IO.FileShare.None, _
&H1000, _
True)

'非同期の書き込みを開始する
fsWrite.BeginWrite(readByte, 0, readByte.Length, _
New AsyncCallback(AddressOf WriteBytescallback), fsWrite)

End If

End Sub

'ファイルを書き込む
Private Sub WriteBytescallback(ByVal ar As IAsyncResult)


'バイト配列にファイルを読込む
'fileStreamの取得
Dim fs As System.IO.FileStream = _
CType(ar.AsyncState, System.IO.FileStream)

'読込んだサイズを取得■■■■■■■■■■ここでエラーが出ます。"IAsyncResult オブジェクトは、この型の対応する非同期
                                                メソッドから派生していません。"

Dim readSize As Integer = fs.EndRead(ar)

If readSize > 0 Then

'非同期の書き込みを開始する
fsWrite.BeginWrite(readByte, 0, readByte.Length, _
New AsyncCallback(AddressOf WriteBytescallback), fsWrite)

end If

  end Sub



引用返信 編集キー/
■36160 / inTopicNo.7)  Re[6]: バイナリファイルの暗号化について
□投稿者/ Hongliang (388回)-(2009/05/22(Fri) 12:37:42)
2009/05/22(Fri) 12:38:32 編集(投稿者)
そりゃ BeginWrite の完了後に呼び出されるコールバックで EndRead すりゃ、
怒られるのは当然だと思いますが。
同期アクセス(Read/Write)で実装すれば十分だと思いますよ。
ざっくりこんな感じ。

バッファ確保
Do
    読み取り量 = 読み取り元.Read(バッファ)
    If (読み取り量 > 0) Then
        書き込み先.Write(バッファに読み取れた分だけ)
    Else
        ループ終了
Loop

引用返信 編集キー/
■36161 / inTopicNo.8)  Re[7]: バイナリファイルの暗号化について
□投稿者/ ms (5回)-(2009/05/22(Fri) 13:04:17)

Hongliang さんご返信ありがとうございます。

> そりゃ BeginWrite の完了後に呼び出されるコールバックで EndRead すりゃ、
> 怒られるのは当然だと思いますが。

そうだったんですね。
書き込み時にもデータが保存されているバッファを読み込んでから、書き込むという風にしていました。

> 同期アクセス(Read/Write)で実装すれば十分だと思いますよ。
> ざっくりこんな感じ。
>
> バッファ確保
> Do
> 読み取り量 = 読み取り元.Read(バッファ)
> If (読み取り量 > 0) Then
> 書き込み先.Write(バッファに読み取れた分だけ)
> Else
> ループ終了
> Loop
そのように、書き直し、実装して、コードをアップします。

引用返信 編集キー/
■36544 / inTopicNo.9)  Re[8]: バイナリファイルの暗号化について
□投稿者/ ms (6回)-(2009/06/01(Mon) 10:36:52)
 実装できました!!
コードは次のようになりました。
1GBあるファイルも暗号化中エラーにはなりませんでした。
皆様ありがとうございました。



Public Sub EncryptFile(ByVal fileName As String, _
                             ByVal key As String)
        Dim cryptStreem As System.Security.Cryptography.CryptoStream = Nothing '書き込み用ストリームの作成
        Dim fsIn As System.IO.FileStream = Nothing 'ファイル読み込み用
        Dim fsOut As System.IO.FileStream = Nothing 'ファイルを書き込むストリームの作成
        Dim Readflg As Boolean = False '読込み様ファイルを開いたか確認
        Dim Writeflg As Boolean = False '書き込み用ファイルを開いたか確認
        Dim StreamWriteflg As Boolean = False '暗合化用ファイルを開いたか確認

        '暗号化のための宣言
        'DESCryptoServiceProviderオブジェクトの作成
        Dim des As New System.Security.Cryptography.DESCryptoServiceProvider

        '共有キーと初期化ベクタを決定
        'パスワードをバイト配列にする
        Dim bytesKey As Byte() = System.Text.Encoding.UTF8.GetBytes(key)
        '共有キーと初期化ベクタを設定
        des.Key = ResizeBytesArray(bytesKey, des.Key.Length)
        des.IV = ResizeBytesArray(bytesKey, des.IV.Length)
        '暗号化されたファイルの保存先
        Dim outFileName = fileName.Substring(0, fileName.Length - 4) + ".enc"

        Try

            '暗号化されたファイルを書き出すためのFileStream
            fsOut = New System.IO.FileStream(outFileName, _
                System.IO.FileMode.Create, System.IO.FileAccess.Write)
            Writeflg = True

            'DES暗号化オブジェクトの作成
            Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
                des.CreateEncryptor()

            '書き込むためのCryptoStreamの作成
            cryptStreem = New System.Security.Cryptography.CryptoStream( _
                fsOut, desdecrypt, _
                System.Security.Cryptography.CryptoStreamMode.Write)
            StreamWriteflg = True 'ストリーム用フラグ

            'ファイルの有無を確認
            If System.IO.File.Exists(fileName) = False Then
                MsgBox("ファイルが見つかりません。") 'ファイルがなければ処理を終わる
                Exit Sub
            End If


            '暗号化するファイルを読み込む
            fsIn = New System.IO.FileStream(fileName, _
                System.IO.FileMode.Open, System.IO.FileAccess.Read)
            Readflg = True 'ファイルを開いた

            'すべて読み込む
            Dim fileSize As Integer = fsIn.Length 'ファイルサイズ
            'データ格納用配列
            Dim readSize As Integer 'Readメソッドで読み込んだバイト数
            Dim remain As Integer = fileSize '読み込む残りのバイト数
            Dim bufpos As Integer 'データ格納用配列内の追加位置

            While remain > 0 'もし残りのファイルサイズ0じゃないとき
                bufpos = 0
                bytesIn1 = New Byte(Math.Min(299999999, _
                                             fileSize - 1)) {}

                '読み込む
                While bufpos < bytesIn1.Length

                    '1000バイトづつ読み込む

                    readSize = fsIn.Read(bytesIn1, bufpos, Math.Min(1000, remain))

                    If remain <= 0 Then 'もし残りのファイルサイズが0なら
                        Exit While '処理を終了
                    End If

                    '暗号化して書き出す
                    cryptStreem.Write(bytesIn1, bufpos, Math.Min(1000, remain)) '書き込む
                    bufpos += readSize '読み込む位置を進める
                    remain -= readSize '残りのファイルサイズを更新

                End While

            End While

        Catch ex As Exception

            MsgBox(ex.ToString)
            Exit Sub

        Finally
            'ファイルを開いていたら()

            If Readflg = True Then

                fsIn.Close() '読み込み用ファイルを閉じる

            End If

            If StreamWriteflg = True Then

                cryptStreem.Close() '暗合化用ファイルが開いていたら閉じる

                If Writeflg = True Then
                    fsOut.Close() '書き込み用ファイルが開いていたら閉じる
                End If

            End If


        End Try

    End Sub

引用返信 編集キー/
■36545 / inTopicNo.10)  Re[9]: バイナリファイルの暗号化について
□投稿者/ ms (7回)-(2009/06/01(Mon) 10:38:48)
No36544 (ms さん) に返信
> 実装できました!!
> コードは次のようになりました。
> 1GBあるファイルも暗号化中エラーにはなりませんでした。
> 皆様ありがとうございました。
>
>
>
> Public Sub EncryptFile(ByVal fileName As String, _
> ByVal key As String)
> Dim cryptStreem As System.Security.Cryptography.CryptoStream = Nothing '書き込み用ストリームの作成
> Dim fsIn As System.IO.FileStream = Nothing 'ファイル読み込み用
> Dim fsOut As System.IO.FileStream = Nothing 'ファイルを書き込むストリームの作成
> Dim Readflg As Boolean = False '読込み様ファイルを開いたか確認
> Dim Writeflg As Boolean = False '書き込み用ファイルを開いたか確認
> Dim StreamWriteflg As Boolean = False '暗合化用ファイルを開いたか確認
>
> '暗号化のための宣言
> 'DESCryptoServiceProviderオブジェクトの作成
> Dim des As New System.Security.Cryptography.DESCryptoServiceProvider
>
> '共有キーと初期化ベクタを決定
> 'パスワードをバイト配列にする
> Dim bytesKey As Byte() = System.Text.Encoding.UTF8.GetBytes(key)
> '共有キーと初期化ベクタを設定
> des.Key = ResizeBytesArray(bytesKey, des.Key.Length)
> des.IV = ResizeBytesArray(bytesKey, des.IV.Length)
> '暗号化されたファイルの保存先
> Dim outFileName = fileName.Substring(0, fileName.Length - 4) + ".enc"
>
> Try
>
> '暗号化されたファイルを書き出すためのFileStream
> fsOut = New System.IO.FileStream(outFileName, _
> System.IO.FileMode.Create, System.IO.FileAccess.Write)
> Writeflg = True
>
> 'DES暗号化オブジェクトの作成
> Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
> des.CreateEncryptor()
>
> '書き込むためのCryptoStreamの作成
> cryptStreem = New System.Security.Cryptography.CryptoStream( _
> fsOut, desdecrypt, _
> System.Security.Cryptography.CryptoStreamMode.Write)
> StreamWriteflg = True 'ストリーム用フラグ
>
> 'ファイルの有無を確認
> If System.IO.File.Exists(fileName) = False Then
> MsgBox("ファイルが見つかりません。") 'ファイルがなければ処理を終わる
> Exit Sub
> End If
>
>
> '暗号化するファイルを読み込む
> fsIn = New System.IO.FileStream(fileName, _
> System.IO.FileMode.Open, System.IO.FileAccess.Read)
> Readflg = True 'ファイルを開いた
>
> 'すべて読み込む
> Dim fileSize As Integer = fsIn.Length 'ファイルサイズ
> 'データ格納用配列
> Dim readSize As Integer 'Readメソッドで読み込んだバイト数
> Dim remain As Integer = fileSize '読み込む残りのバイト数
> Dim bufpos As Integer 'データ格納用配列内の追加位置
>
> While remain > 0 'もし残りのファイルサイズ0じゃないとき
> bufpos = 0
> bytesIn1 = New Byte(Math.Min(299999999, _
> fileSize - 1)) {}
>
> '読み込む
> While bufpos < bytesIn1.Length
>
> '1000バイトづつ読み込む
>
> readSize = fsIn.Read(bytesIn1, bufpos, Math.Min(1000, remain))
>
> If remain <= 0 Then 'もし残りのファイルサイズが0なら
> Exit While '処理を終了
> End If
>
> '暗号化して書き出す
> cryptStreem.Write(bytesIn1, bufpos, Math.Min(1000, remain)) '書き込む
> bufpos += readSize '読み込む位置を進める
> remain -= readSize '残りのファイルサイズを更新
>
> End While
>
> End While
>
> Catch ex As Exception
>
> MsgBox(ex.ToString)
> Exit Sub
>
> Finally
> 'ファイルを開いていたら()
>
> If Readflg = True Then
>
> fsIn.Close() '読み込み用ファイルを閉じる
>
> End If
>
> If StreamWriteflg = True Then
>
> cryptStreem.Close() '暗合化用ファイルが開いていたら閉じる
>
> If Writeflg = True Then
> fsOut.Close() '書き込み用ファイルが開いていたら閉じる
> End If
>
> End If
>
>
> End Try
>
> End Sub
解決済み
引用返信 編集キー/
■36553 / inTopicNo.11)  Re[10]: バイナリファイルの暗号化について
□投稿者/ なちゃ (287回)-(2009/06/01(Mon) 14:24:47)
うーん、ちょっと変なコードになってますね…
最初から1000バイトとかの固定サイズのバッファだけ使えばできるはずですが…

これだとMaxで300MBものバッファを使います。
数値を変えれば小さくは出来るでしょうけどそもそもバッファを2段にする必要はないはずです。

解決済み
引用返信 編集キー/
■36555 / inTopicNo.12)  Re[11]: バイナリファイルの暗号化について
□投稿者/ ms (8回)-(2009/06/01(Mon) 15:29:59)
No36553 (なちゃ さん) に返信
> うーん、ちょっと変なコードになってますね…
> 最初から1000バイトとかの固定サイズのバッファだけ使えばできるはずですが…
>
> これだとMaxで300MBものバッファを使います。
> 数値を変えれば小さくは出来るでしょうけどそもそもバッファを2段にする必要はないはずです。
>


なちゃさんご返信ありがとうございます。

While remain > 0 'もし残りのファイルサイズ0じゃないとき
bufpos = 0
bytesIn1 = New Byte(Math.Min(299999999, _
fileSize - 1)) {}

この部分を


While remain > 0 'もし残りのファイルサイズ0じゃないとき
bufpos = 0
bytesIn1 = New Byte(Math.Min(1000, _
fileSize - 1)) {}

という風に定義しなおせばよろしかったでしょうか?
300MBよみこめばはやく読み込めるかと思いました。
すみませんご教授お願いします。





引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -