.NETプログラミング研究 第17号

.NET Tips

秘密鍵暗号方式による暗号化

注意

この記事の最新版は「ファイルを暗号化する」及び「文字列を暗号化する」で公開しています。

ここでは共有キー暗号方式 (対称暗号化方式、秘密鍵暗号方式)による暗号化、復号化について説明します。共有キー暗号方式では、単一の共有キーを使用してデータの暗号化と復号化が行われます。「秘密鍵暗号システム」に関して「アスキー デジタル用語辞典」(http://yougo.ascii24.com/)では、

「暗号システムにおいて、暗号化に使用する鍵と復号化に使用する鍵が同じもののこと。従来の暗号システムはほとんどすべてがこれに相当するため、慣用暗号システムとも呼ばれる。鍵が1種類しかないため、暗号化に使用した鍵を、通信路とは別の安全な手段を使って、通信相手に届けておく必要がある。」

と説明されています。

ファイルを暗号化する方法は「マイクロソフト サポート技術情報 - 307010」にて詳しく説明されています。

ただしこのサンプルには2つの欠点があります。パスワードを必ず8バイトにする必要がある点と、暗号化されるファイルがUTF-8エンコーディングである必要がある(復号化の時、元のファイルがUTF-8として読み込み、UTF-8で出力している)という点です。

これではほとんど役に立たないので、この2点を修正したものを書いてみました。共有キー(秘密キー)と初期化ベクタは、与えられたパスワードが何バイトであるかにかかわらず、適切なバイト数に調節して設定しています。また、暗号化するファイルのエンコーディングはShift JISとしています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/// <summary>
/// ファイルを暗号化する
/// </summary>
/// <remarks>
/// 暗号化されたファイルは"(ファイル名).enc"として保存される
/// </remarks>
/// <param name="fileName">暗号化するファイル名</param>
/// <param name="key">パスワード</param>
public static void EncryptFile(string fileName, string key) 
{
    //暗号化するファイルを読み込む
    System.IO.FileStream fsIn = 
        new System.IO.FileStream(fileName, 
        System.IO.FileMode.Open, System.IO.FileAccess.Read);
    //すべて読み込む
    byte[] bytesIn = new byte[fsIn.Length];
    fsIn.Read(bytesIn, 0, bytesIn.Length);
    //閉じる
    fsIn.Close();
 
    //DESCryptoServiceProviderオブジェクトの作成
    System.Security.Cryptography.DESCryptoServiceProvider des =
        new System.Security.Cryptography.DESCryptoServiceProvider();
 
    //共有キーと初期化ベクタを決定
    //パスワードをバイト配列にする
    byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
    //共有キーと初期化ベクタを設定
    des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
    des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
    //暗号化されたファイルの保存先
    string outFileName = fileName + ".enc";
    //暗号化されたファイルを書き出すためのFileStream
    System.IO.FileStream fsOut = 
        new System.IO.FileStream(outFileName,
        System.IO.FileMode.Create, System.IO.FileAccess.Write);
    //DES暗号化オブジェクトの作成
    System.Security.Cryptography.ICryptoTransform desdecrypt =
        des.CreateEncryptor();
    //書き込むためのCryptoStreamの作成
    System.Security.Cryptography.CryptoStream cryptStreem =
        new System.Security.Cryptography.CryptoStream(fsOut,
        desdecrypt,
        System.Security.Cryptography.CryptoStreamMode.Write);
    //書き込む
    cryptStreem.Write(bytesIn, 0, bytesIn.Length);
    //閉じる
    cryptStreem.Close();
    fsOut.Close();
}
 
/// <summary>
/// ファイルを復号化する
/// </summary>
/// <param name="fileName">復号化するファイル名</param>
/// <param name="key">パスワード</param>
public static void DecryptFile(string fileName, string key) 
{
    //DESCryptoServiceProviderオブジェクトの作成
    System.Security.Cryptography.DESCryptoServiceProvider des =
        new System.Security.Cryptography.DESCryptoServiceProvider();
 
    //共有キーと初期化ベクタを決定
    //パスワードをバイト配列にする
    byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
    //共有キーと初期化ベクタを設定
    des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
    des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
    //暗号化されたファイルを読み込むためのFileStream
    System.IO.FileStream fsIn = 
        new System.IO.FileStream(fileName, 
        System.IO.FileMode.Open, System.IO.FileAccess.Read);
    //DES復号化オブジェクトの作成
    System.Security.Cryptography.ICryptoTransform desdecrypt =
        des.CreateDecryptor();
    //読み込むためのCryptoStreamの作成
    System.Security.Cryptography.CryptoStream cryptStreem =
        new System.Security.Cryptography.CryptoStream(fsIn,
        desdecrypt,
        System.Security.Cryptography.CryptoStreamMode.Read);
 
    //復号化されたファイルの保存先
    string outFileName;
    if (fileName.ToLower().EndsWith(".enc"))
        outFileName = fileName.Substring(0, fileName.Length - 4);
    else
        outFileName = fileName + ".dec";
 
    //復号化されたデータを書き出すためのStreamWriter
    System.IO.StreamWriter sw =
        new System.IO.StreamWriter(outFileName, false,
        System.Text.Encoding.GetEncoding("sjis"));
    //復号化されたデータを読み込む
    System.IO.StreamReader sr =
        new System.IO.StreamReader(cryptStreem,
        System.Text.Encoding.GetEncoding("sjis"));
    //復号化されたデータを書き出す
    sw.Write(sr.ReadToEnd());
    sw.Flush();
 
    //閉じる
    sr.Close();
    sw.Close();
    cryptStreem.Close();
    fsIn.Close();
}
 
/// <summary>
/// 共有キー用に、バイト配列のサイズを変更する
/// </summary>
/// <param name="bytes">サイズを変更するバイト配列</param>
/// <param name="newSize">バイト配列の新しい大きさ</param>
/// <returns>サイズが変更されたバイト配列</returns>
private static byte[] ResizeBytesArray(byte[] bytes, int newSize)
{
    byte[] newBytes = new byte[newSize];
    if (bytes.Length < newSize)
    {
        for (int i = 0; i < bytes.Length; i++)
            newBytes[i] = bytes[i];
    }
    else
    {
        int pos = 0;
        for (int i = newSize; i < bytes.Length; i++)
        {
            newBytes[pos++] ^= bytes[i];
            if (pos >= newBytes.Length)
                pos = 0;
        }
    }
    return newBytes;
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです
'http://www.aspalliance.com/aldotnet/examples/translate.aspx
'
'/ <summary>
'/ ファイルを暗号化する
'/ </summary>
'/ <remarks>
'/ 暗号化されたファイルは"(ファイル名).enc"として保存される
'/ </remarks>
'/ <param name="fileName">暗号化するファイル名</param>
'/ <param name="key">パスワード</param>
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) 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)
    '書き込む
    cryptStreem.Write(bytesIn, 0, bytesIn.Length)
    '閉じる
    cryptStreem.Close()
    fsOut.Close()
End Sub
 
'/ <summary>
'/ ファイルを復号化する
'/ </summary>
'/ <param name="fileName">復号化するファイル名</param>
'/ <param name="key">パスワード</param>
Public Shared Sub DecryptFile(ByVal fileName As String, _
                            ByVal key As String)
    '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)
 
    '暗号化されたファイルを読み込むためのFileStream
    Dim fsIn As New System.IO.FileStream(fileName, _
        System.IO.FileMode.Open, System.IO.FileAccess.Read)
    'DES復号化オブジェクトの作成
    Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
        des.CreateDecryptor()
    '読み込むためのCryptoStreamの作成
    Dim cryptStreem As New System.Security.Cryptography.CryptoStream( _
        fsIn, desdecrypt, _
        System.Security.Cryptography.CryptoStreamMode.Read)
 
    '復号化されたファイルの保存先
    Dim outFileName As String
    If fileName.ToLower().EndsWith(".enc") Then
        outFileName = fileName.Substring(0, fileName.Length - 4)
    Else
        outFileName = fileName + ".dec"
    End If
    '復号化されたデータを書き出すためのStreamWriter
    Dim sw As New System.IO.StreamWriter( _
        outFileName, False, System.Text.Encoding.GetEncoding("sjis"))
    '復号化されたデータを読み込む
    Dim sr As New System.IO.StreamReader( _
        cryptStreem, System.Text.Encoding.GetEncoding("sjis"))
    '復号化されたデータを書き出す
    sw.Write(sr.ReadToEnd())
    sw.Flush()
 
    '閉じる
    sr.Close()
    sw.Close()
    cryptStreem.Close()
    fsIn.Close()
End Sub
 
'/ <summary>
'/ 共有キー用に、バイト配列のサイズを変更する
'/ </summary>
'/ <param name="bytes">サイズを変更するバイト配列</param>
'/ <param name="newSize">バイト配列の新しい大きさ</param>
'/ <returns>サイズが変更されたバイト配列</returns>
Private Shared Function ResizeBytesArray(ByVal bytes() As Byte, _
                            ByVal newSize As Integer) As Byte()
    Dim newBytes(newSize - 1) As Byte
    If bytes.Length < newSize Then
        Dim i As Integer
        For i = 0 To bytes.Length - 1
            newBytes(i) = bytes(i)
        Next i
    Else
        Dim pos As Integer = 0
        Dim i As Integer
        For i = newSize To bytes.Length - 1
            newBytes(pos) = newBytes(pos) Xor bytes(i)
            pos += 1
            If pos >= newBytes.Length Then
                pos = 0
            End If
        Next i
    End If
    Return newBytes
End Function 'ResizeBytesArray

上記の例では、共有キーと初期化ベクタを決定するために、与えられたパスワード(パスワードをバイト型配列に変換したもの)が短ければ残りを0で埋め、長ければ切り詰めるようにしています。切り詰め方としては単にカットするのではなく(そのようにしているサンプルも多いようですが、こうしてしまうとパスワードのはじめ数文字があっていればOKとなってしまう)、切り詰める部分をXORで合成しています(果たしてこれがよい方法であるかは分かりませんが)。また、共有キーと初期化ベクタのサイズの決定は、DESCryptoServiceProviderのKeyとIVプロパティで取得されるバイト配列の大きさと同じとしていますが、DESCryptoServiceProvider.LegalKeySizesやLegalBlockSizesプロパティを調べて決めた方がよりよいでしょう。

上記の方法では暗号化されるファイルはShift JISである必要がありますが、DecryptFileを次のように変えることにより、どんなファイルでも暗号化、復号化できるようになるでしょう。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
/// <summary>
/// ファイルを復号化する
/// </summary>
/// <param name="fileName">復号化するファイル名</param>
/// <param name="key">パスワード</param>
public static void DecryptFile(string fileName, string key) 
{
    //DESCryptoServiceProviderオブジェクトの作成
    System.Security.Cryptography.DESCryptoServiceProvider des =
        new System.Security.Cryptography.DESCryptoServiceProvider();
 
    //共有キーと初期化ベクタを決定
    //パスワードをバイト配列にする
    byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
    //共有キーと初期化ベクタを設定
    des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
    des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
    //暗号化されたファイルを読み込むためのFileStream
    System.IO.FileStream fsIn = 
        new System.IO.FileStream(fileName, 
        System.IO.FileMode.Open, System.IO.FileAccess.Read);
    //DES復号化オブジェクトの作成
    System.Security.Cryptography.ICryptoTransform desdecrypt =
        des.CreateDecryptor();
    //読み込むためのCryptoStreamの作成
    System.Security.Cryptography.CryptoStream cryptStreem =
        new System.Security.Cryptography.CryptoStream(fsIn,
        desdecrypt,
        System.Security.Cryptography.CryptoStreamMode.Read);
 
    //復号化されたファイルの保存先
    string outFileName;
    if (fileName.ToLower().EndsWith(".enc"))
        outFileName = fileName.Substring(0, fileName.Length - 4);
    else
        outFileName = fileName + ".dec";
    //復号化されたファイルを書き出すためのFileStream
    System.IO.FileStream fsOut =
        new System.IO.FileStream(outFileName,
        System.IO.FileMode.Create, System.IO.FileAccess.Write);
 
    //復号化されたデータを書き出す
    byte[] bs = new byte[256];
    int readLen;
    while ((readLen = cryptStreem.Read(bs, 0, bs.Length)) > 0)
        fsOut.Write(bs, 0, readLen);
 
    //閉じる
    cryptStreem.Close();
    fsIn.Close();
    fsOut.Close();
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです
'http://www.aspalliance.com/aldotnet/examples/translate.aspx
'
'/ <summary>
'/ ファイルを復号化する
'/ </summary>
'/ <param name="fileName">復号化するファイル名</param>
'/ <param name="key">パスワード</param>
Public Shared Sub DecryptFile(ByVal fileName As String, _
                            ByVal key As String)
    '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)
 
    '暗号化されたファイルを読み込むためのFileStream
    Dim fsIn As New System.IO.FileStream(fileName, _
        System.IO.FileMode.Open, System.IO.FileAccess.Read)
    'DES復号化オブジェクトの作成
    Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
        des.CreateDecryptor()
    '読み込むためのCryptoStreamの作成
    Dim cryptStreem As New System.Security.Cryptography.CryptoStream( _
        fsIn, desdecrypt, _
        System.Security.Cryptography.CryptoStreamMode.Read)
 
    '復号化されたファイルの保存先
    Dim outFileName As String
    If fileName.ToLower().EndsWith(".enc") Then
        outFileName = fileName.Substring(0, fileName.Length - 4)
    Else
        outFileName = fileName + ".dec"
    End If '復号化されたファイルを書き出すためのFileStream
    Dim fsOut As New System.IO.FileStream(outFileName, _
        System.IO.FileMode.Create, System.IO.FileAccess.Write)
 
    '復号化されたデータを書き出す
    Dim bs(255) As Byte
    Dim readLen As Integer
    Do
        readLen = cryptStreem.Read(bs, 0, bs.Length)
        If readLen > 0 Then
            fsOut.Write(bs, 0, readLen)
        End If
    Loop While (readLen > 0)
 
    '閉じる
    cryptStreem.Close()
    fsIn.Close()
    fsOut.Close()
End Sub 'DecryptFile

ここでは、DESCryptoServiceProvider クラスを使用し、DES (Data Encryption Standard) アルゴリズムによる暗号化、復号化の例を示しましたが、.NET Framework では、共有キー暗号化アルゴリズムを実装するクラスとして、他にも3つ用意されています(下の表参照)。使い方はDESCryptoServiceProviderと全く同じですので、上記の例の"DESCryptoServiceProvider"を適当なクラス名で置き換えるだけでも動くでしょう。

次にファイルではなく、文字列を暗号化する方法を紹介します。

上記の方法では、ファイルから読み込んだデータを暗号化し、ファイルに書き込んでいるため、CryptoStreamオブジェクトを作成する際に、暗号化の対象とするストリームとしてFileStreamオブジェクトを使用しましたが、ここではMemoryStreamオブジェクトを使用することにします。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/// <summary>
/// 文字列を暗号化する
/// </summary>
/// <param name="str">暗号化する文字列</param>
/// <param name="key">パスワード</param>
/// <returns>暗号化された文字列</returns>
public static string EncryptString(string str, string key) 
{
    //文字列をバイト型配列にする
    byte[] bytesIn = System.Text.Encoding.UTF8.GetBytes(str);
 
    //DESCryptoServiceProviderオブジェクトの作成
    System.Security.Cryptography.DESCryptoServiceProvider des =
        new System.Security.Cryptography.DESCryptoServiceProvider();
 
    //共有キーと初期化ベクタを決定
    //パスワードをバイト配列にする
    byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
    //共有キーと初期化ベクタを設定
    des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
    des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
    //暗号化されたデータを書き出すためのMemoryStream
    System.IO.MemoryStream msOut = new System.IO.MemoryStream();
    //DES暗号化オブジェクトの作成
    System.Security.Cryptography.ICryptoTransform desdecrypt =
        des.CreateEncryptor();
    //書き込むためのCryptoStreamの作成
    System.Security.Cryptography.CryptoStream cryptStreem =
        new System.Security.Cryptography.CryptoStream(msOut,
        desdecrypt,
        System.Security.Cryptography.CryptoStreamMode.Write);
    //書き込む
    cryptStreem.Write(bytesIn, 0, bytesIn.Length);
    cryptStreem.FlushFinalBlock();
    //暗号化されたデータを取得
    byte[] bytesOut = msOut.ToArray();
 
    //閉じる
    cryptStreem.Close();
    msOut.Close();
 
    //Base64で文字列に変更して結果を返す
    return System.Convert.ToBase64String(bytesOut);
}
 
/// <summary>
/// 暗号化された文字列を復号化する
/// </summary>
/// <param name="str">暗号化された文字列</param>
/// <param name="key">パスワード</param>
/// <returns>復号化された文字列</returns>
public static string DecryptString(string str, string key) 
{
    //DESCryptoServiceProviderオブジェクトの作成
    System.Security.Cryptography.DESCryptoServiceProvider des =
        new System.Security.Cryptography.DESCryptoServiceProvider();
 
    //共有キーと初期化ベクタを決定
    //パスワードをバイト配列にする
    byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes(key);
    //共有キーと初期化ベクタを設定
    des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
    des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
 
    //Base64で文字列をバイト配列に戻す
    byte[] bytesIn = System.Convert.FromBase64String(str);
    //暗号化されたデータを読み込むためのMemoryStream
    System.IO.MemoryStream msIn =
        new System.IO.MemoryStream(bytesIn);
    //DES復号化オブジェクトの作成
    System.Security.Cryptography.ICryptoTransform desdecrypt =
        des.CreateDecryptor();
    //読み込むためのCryptoStreamの作成
    System.Security.Cryptography.CryptoStream cryptStreem =
        new System.Security.Cryptography.CryptoStream(msIn,
        desdecrypt,
        System.Security.Cryptography.CryptoStreamMode.Read);
 
    //復号化されたデータを取得するためのStreamReader
    System.IO.StreamReader srOut =
        new System.IO.StreamReader(cryptStreem, 
        System.Text.Encoding.UTF8);
    //復号化されたデータを取得する
    string result = srOut.ReadToEnd();
 
    //閉じる
    srOut.Close();
    cryptStreem.Close();
    msIn.Close();
 
    return result;
}
 
/// <summary>
/// 共有キー用に、バイト配列のサイズを変更する
/// </summary>
/// <param name="bytes">サイズを変更するバイト配列</param>
/// <param name="newSize">バイト配列の新しい大きさ</param>
/// <returns>サイズが変更されたバイト配列</returns>
private static byte[] ResizeBytesArray(byte[] bytes, int newSize)
{
    byte[] newBytes = new byte[newSize];
    if (bytes.Length < newSize)
    {
        for (int i = 0; i < bytes.Length; i++)
            newBytes[i] = bytes[i];
    }
    else
    {
        int pos = 0;
        for (int i = newSize; i < bytes.Length; i++)
        {
            newBytes[pos++] ^= bytes[i];
            if (pos >= newBytes.Length)
                pos = 0;
        }
    }
    return newBytes;
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです
'http://www.aspalliance.com/aldotnet/examples/translate.aspx
'
'/ <summary>
'/ 文字列を暗号化する
'/ </summary>
'/ <param name="str">暗号化する文字列</param>
'/ <param name="key">パスワード</param>
'/ <returns>暗号化された文字列</returns>
Public Shared Function EncryptString(ByVal str As String, _
                                ByVal key As String) As String
    '文字列をバイト型配列にする
    Dim bytesIn As Byte() = System.Text.Encoding.UTF8.GetBytes(str)
 
    '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)
 
    '暗号化されたデータを書き出すためのMemoryStream
    Dim msOut As New System.IO.MemoryStream
    'DES暗号化オブジェクトの作成
    Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
        des.CreateEncryptor()
    '書き込むためのCryptoStreamの作成
    Dim cryptStreem As New System.Security.Cryptography.CryptoStream( _
        msOut, desdecrypt, _
        System.Security.Cryptography.CryptoStreamMode.Write)
    '書き込む
    cryptStreem.Write(bytesIn, 0, bytesIn.Length)
    cryptStreem.FlushFinalBlock()
    '暗号化されたデータを取得
    Dim bytesOut As Byte() = msOut.ToArray()
 
    '閉じる
    cryptStreem.Close()
    msOut.Close()
 
    'Base64で文字列に変更して結果を返す
    Return System.Convert.ToBase64String(bytesOut)
End Function 'EncryptString
 
'/ <summary>
'/ 暗号化された文字列を復号化する
'/ </summary>
'/ <param name="str">暗号化された文字列</param>
'/ <param name="key">パスワード</param>
'/ <returns>復号化された文字列</returns>
Public Shared Function DecryptString(ByVal str As String, _
                            ByVal key As String) As String
    '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)
 
    'Base64で文字列をバイト配列に戻す
    Dim bytesIn As Byte() = System.Convert.FromBase64String(str)
    '暗号化されたデータを読み込むためのMemoryStream
    Dim msIn As New System.IO.MemoryStream(bytesIn)
    'DES復号化オブジェクトの作成
    Dim desdecrypt As System.Security.Cryptography.ICryptoTransform = _
        des.CreateDecryptor()
    '読み込むためのCryptoStreamの作成
    Dim cryptStreem As New System.Security.Cryptography.CryptoStream( _
        msIn, desdecrypt, _
        System.Security.Cryptography.CryptoStreamMode.Read)
 
    '復号化されたデータを取得するためのStreamReader
    Dim srOut As New System.IO.StreamReader( _
        cryptStreem, System.Text.Encoding.UTF8)
    '復号化されたデータを取得する
    Dim result As String = srOut.ReadToEnd()
 
    '閉じる
    srOut.Close()
    cryptStreem.Close()
    msIn.Close()
 
    Return result
End Function 'DecryptString
 
'/ <summary>
'/ 共有キー用に、バイト配列のサイズを変更する
'/ </summary>
'/ <param name="bytes">サイズを変更するバイト配列</param>
'/ <param name="newSize">バイト配列の新しい大きさ</param>
'/ <returns>サイズが変更されたバイト配列</returns>
Private Shared Function ResizeBytesArray(ByVal bytes() As Byte, _
                            ByVal newSize As Integer) As Byte()
    Dim newBytes(newSize - 1) As Byte
    If bytes.Length < newSize Then
        Dim i As Integer
        For i = 0 To bytes.Length - 1
            newBytes(i) = bytes(i)
        Next i
    Else
        Dim pos As Integer = 0
        Dim i As Integer
        For i = newSize To bytes.Length - 1
            newBytes(pos) = newBytes(pos) Xor bytes(i)
            pos += 1
            If pos >= newBytes.Length Then
                pos = 0
            End If
        Next i
    End If
    Return newBytes
End Function 'ResizeBytesArray

コメント



ページ情報
  • カテゴリ : .NET
  • 作成日 : 2003-09-22 (月) 06:00:00
  • 作成者 : DOBON!
  • 最終編集日 : 2010-03-21 (日) 00:49:40
  • 最終編集者 : DOBON!
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]