LoginSignup
5
10

More than 5 years have passed since last update.

user.configファイルを[部分的に]暗号化するシンプルな方法

Posted at

動機は何でも構わないんですが…

user.configファイルの中身が剥き出しってどうよ?
って思ってしまったのが運の尽きで…

折々に手法を凝らして工夫してきましたが、まぁ帯だったり襷だったり褌だったり。

そんな中でも、一番のお気に入りを披露しちゃおうと思います。

特徴

  • プログラム本体側では通常のプロパティアクセスを行うだけでオッケー
  • .csファイルを増やすだけで暗号化対応完了
  • user.configファイルを別ユーザ・別パソコンにコピーしても正規ファイルとは認められません
  • 残念ながらstring型のプロパティにしか対応できません…
    =ここが部分的

実装

Settings.Crypto.cs
using System;
using System.Security.Cryptography;
using System.Text;

namespace TestSettings.Properties {
    internal sealed partial class Settings {
        public override object this[string propertyName] {
            get {
                if(!(base[propertyName] is string)) {
                    return base[propertyName];
                }

                try {
                    return Decrypt(base[propertyName]);
                }
                catch {
                    return Settings.Default.Properties[propertyName].DefaultValue;
                }
            }

            set {
                if(base[propertyName] is string)
                    try {
                        base[propertyName] = Encrypt(value);
                    }
                    catch {
                        base[propertyName] = Settings.Default.Properties[propertyName].DefaultValue;
                    } else
                    base[propertyName] = value;
            }
        }

        byte[] entropy = { 141, 238, 28, 197, 169, 105, 209, 230 };

        object Encrypt(object text) {
            return Convert.ToBase64String(ProtectedData.Protect(Encoding.UTF8.GetBytes(text as string), entropy, DataProtectionScope.CurrentUser));
        }

        object Decrypt(object text) {
            return Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(text as string), entropy, DataProtectionScope.CurrentUser));
        }
    }
}
  • namespaceはプロジェクトに合わせて下さい
  • エントロピーは適当に変えていただいて構いません

肝はSettingsクラスのインデクサをoverrideしてるとこですね。で、ここで暗号化/復号化をしちゃってるので、プロパティを使う側は全く無意識でuser.config内は暗号化されちゃっていると云う感じ。

配置方法

クラスファイルは、↓此処の位置に配置するのが宜しいかと…
Propertiesフォルダ配下)
image

やってみる

image
こんな感じの設定をして…

Program.cs
using System;

namespace TestSettings {
    class Program {
        static void Main(string[] args) {
            Console.WriteLine(Properties.Settings.Default.TestString);

            Properties.Settings.Default.TestString = "とほほ…";
            Properties.Settings.Default.Save();

            Console.WriteLine(Properties.Settings.Default.TestString);

            Console.ReadKey();
        }
    }
}

このプログラムの初回実行では、
image

この時、user.configの中身は、
image

暗号化されてるでしょ?
で、二回目の実行では、
image

ちゃんと、復号化も出来ている様で、めでたい。

心残り

  • アプリケーションスコープのプロパティを事前暗号化しておきたい時には、この方式は全く馴染みません
  • 暗号化にはDPAPIを使ってるので、他のユーザとか他のパソコンにこのuser.configを持って行ったとしても復号化には失敗する(筈)
    此処の検証ができていないのが残念(単なるめんどくさがり、と云うだけですが)
  • 上記のケース等の様に復号化に失敗した場合は、設定画面で指定した既定値が復活するようになっています
    user.configの中身を改竄した場合も同様
  • string以外も暗号化したい場合はどうしたらいいんだろう?
    違うアプローチが必要そうなので、何かが下りてくるまで熟考したい
5
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
10