Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

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以外も暗号化したい場合はどうしたらいいんだろう?
    違うアプローチが必要そうなので、何かが下りてくるまで熟考したい
Toraja
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away