はじめに
RevitアドインでパスワードやAPIキーなどの機密情報を扱う際に、ローカルへ安全に保存する方法を説明します。コードをコピペしたい型は コード全体 を確認してください。
プロジェクトにApp.configを追加
App.configとは、アプリケーション固有の設定を記述するXML形式のファイルです。Visual Studioの「新しい項目の追加」ダイアログで アプリケーション構成ファイル を選択して追加します。
必要に応じてkey=value形式で属性を記述します。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Token" value="" />
<add key="UserName" value=""/>
</appSettings>
</configuration>
System.Configuration を参照
「参照マネージャー」ダイアログで System.Configuration にチェックを入れます。
App.configへの読み書き
ConfigurationManager.OpenExeConfiguration()メソッドでApp.configを操作できます。メソッドの引数として現在実行中のアセンブリのパス(このアドインのパス)を渡します。
RevitアドインはRevit.exeプロセス内でホストされて実行されます。そのため、パスを指定せずに設定ファイルを読み込むと、アドイン自体のApp.configではなくホストプロセス(Revit.exe)のApp.configが参照されてしまいます。
public void Save(string key, string value)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
config.AppSettings.Settings[key].Value = value;
config.Save();
}
public static string Get(string key)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
var value = config.AppSettings.Settings[key].Value;
return value;
}
暗号化
パスワードやAPIキーなどの機密情報を平文のままApp.configに保存すると、ファイルがハッキングされたりPCが売却された際に、機密情報が流出してしまう恐れがあります。
そこで、機密情報をApp.configへ保存する前にDPAPIを用いて暗号化します。DPAPIはWindows OSに標準で組み込まれているデータ保護機能です。
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] encryptedBytes = ProtectedData.Protect(plainTextBytes, null, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedText)
{
byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
byte[] plainTextBytes = ProtectedData.Unprotect(encryptedBytes, null, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(plainTextBytes);
}
Saveメソッド・Getメソッドを以下のように修正します。
public void Save(string key, string value)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
+ config.AppSettings.Settings[key].Value = DPAPI.Encrypt(value);
config.Save();
}
public static string Get(string key)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
var value = config.AppSettings.Settings[key].Value;
+ return DPAPI.Decrypt(value);
}
コード全体
using System;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;
namespace Addin
{
/// <summary>
/// DPAPIを使って文字列を暗号化・復号化するクラス
/// </summary>
public static class DPAPI
{
// 文字列を暗号化するメソッド
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] encryptedBytes = ProtectedData.Protect(plainTextBytes, null, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedBytes);
}
// 文字列を復号化するメソッド
public static string Decrypt(string encryptedText)
{
byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
byte[] plainTextBytes = ProtectedData.Unprotect(encryptedBytes, null, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(plainTextBytes);
}
}
/// <summary>
/// App.configの設定値を取得・保存するクラス
/// </summary>
public static class ConfigManager
{
// 設定値を暗号化して保存するメソッド
public static void Save(string key, string value)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
config.AppSettings.Settings[key].Value = DPAPI.Encrypt(value);
config.Save();
}
// 設定値を復号化して取得するメソッド
public static string Get(string key)
{
var config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
var value = config.AppSettings.Settings[key].Value;
return DPAPI.Decrypt(value);
}
}
}