2009/06/12

パスワードの暗号化

http://highrisklowreturn.blogspot.com/2010/01/quicker-update.html

暗号化に関しては、こっちのほうがよさそうなので、誘導リンク(2010/01/25)

--

最近作ろうと思ってるソフトで、パスワードを保存する必要がありそうなので、パスワードを暗号化して保存する方法を少し調べてみた。


ぐぐってみると、予想通りCryptAPI関連のお話がちまちまと。

公開鍵暗号でも使うべきなんだろうけど、通信上に乗せるデータを作るわけじゃないし、


使い方的には、キーを決めておいて、パスワードに暗号化。で、キーを生成する方法をうまくプログラム内に隠蔽してしまえば、保存してあるデータは、ある程度安全であるといえる感じ。

やることは

  • パスワードとキーで暗号化
  • キーと暗号化文字列で、パスワードを複合
  • キーはとりあえずはしょっぱい文字列で。

この2つができれば、いいような。キーの生成方法は、「こうだ」って説明した瞬間に意味がなくなるので説明しない。

ソースはこんな感じ。ネットで拾ってきたサンプルを元に、少し手を加えて、関数を共通化したりとか。

つか、ソースを折りたたんでおきたいな。あとでスクリプトでも書くか・・・ でも毎回スクリプト編集するのか?うーん、悩みどころ

とりあえず折りたたみできるようになったから、すこし工事しよう。

== C# ==
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// 暗号化関連
using System.Security;
using System.Security.Cryptography;

namespace Crypt
{
class Crypto
{
/// <summary>
/// 暗号化キー
/// </summary>
private string key;
/// <summary>
/// 暗号化キー
/// </summary>
private string Key
{
get
{
return key;
}
set
{
key = value;
}
}

/// <summary>
/// コンストラクタ
/// </summary>
public Crypto()
{
// キーの生成
MakeKey();
}

/// <summary>
/// キーの生成
/// </summary>
private void MakeKey()
{
// 思いっきり適当に。(ここでゴニョゴニョやる)
Key = "DefaultDummyKeyData";
}

/// <summary>
/// DES暗号化オブジェクトの生成
/// </summary>
/// <returns></returns>
private ICryptoTransform CreateCryptoTransform( bool IsEncrypto)
{
// キーをバイト配列にする
byte[] bytesKey = System.Text.Encoding.UTF8.GetBytes( Key );

// DESCryptoServiceProviderの作成
DESCryptoServiceProvider des = new DESCryptoServiceProvider();

// 共有キーと初期化ベクタを決定(サイズはオブジェクト側に合わせる)
des.Key = ResizeBytesArray( bytesKey, des.Key.Length );
des.IV = ResizeBytesArray( bytesKey, des.IV.Length );

// DES暗号化オブジェクトの作成
ICryptoTransform desCrypto = IsEncrypto ? des.CreateEncryptor() : des.CreateDecryptor();

return desCrypto;
}

/// <summary>
/// 暗号化
/// </summary>
/// <param name="str">暗号化する文字列</param>
/// <returns>暗号化されたデータ</returns>
public byte[] Encrypt( string str )
{
// 文字列をバイト型配列にする
byte[] bytesIn = Encoding.UTF8.GetBytes( str );

// 暗号化オブジェクトの生成
ICryptoTransform desEncrypt = CreateCryptoTransform( true );

// 暗号化されたデータを書き出すためのMemoryStream
byte[] bytesOut;
using ( MemoryStream msOut = new MemoryStream() ) {

// 書き込むためのCryptoStreamの作成
using ( CryptoStream cryptStreem = new CryptoStream( msOut, desEncrypt, CryptoStreamMode.Write ) ) {
//書き込む
cryptStreem.Write( bytesIn, 0, bytesIn.Length );
cryptStreem.FlushFinalBlock();

cryptStreem.Close();
}

// 暗号化されたデータを取得
bytesOut = msOut.ToArray();

msOut.Close();
}

return bytesOut;
}

/// <summary>
/// 暗号化された文字列を復号化する
/// </summary>
/// <param name="str">暗号化データ</param>
/// <returns>復号化された文字列</returns>
public string Decrypt( byte[] data )
{
// DES復号化オブジェクトの作成
ICryptoTransform desDecrypt = CreateCryptoTransform( false );

// 暗号化されたデータを読み込むためのMemoryStream
string result;
using ( MemoryStream msIn = new MemoryStream( data ) ) {

// 読み込むためのCryptoStreamの作成
using ( CryptoStream cryptStreem = new CryptoStream( msIn, desDecrypt, CryptoStreamMode.Read ) ) {

// 復号化されたデータを取得するためのStreamReader
using ( StreamReader srOut = new StreamReader( cryptStreem, Encoding.UTF8 ) ) {

// 復号化されたデータを取得する
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 = 0; i < bytes.Length; i++ ) {
newBytes[pos++] ^= bytes[i];
if ( pos >= newBytes.Length )
pos = 0;
}
}
return newBytes;
}
}
}
== end ==


なんとかソースはきれいに出たな。

あとは、幅設定が壊れなければいいんだけど・・・

0 件のコメント:

コメントを投稿