作成した秘密鍵に基づいて厳密な名前でアセンブリに署名すると、次の利点があります。
- 厳密な名前は、公開鍵トークンとデジタル署名をアセンブリに追加することにより、アセンブリのIDの一意性を保証します。
- 厳密な名前を公開鍵と照合して、アセンブリがその公開鍵を持つ発行者からのものであり、その発行者のみであることを証明できます。
- 厳密な名前は、強力な整合性チェックを提供します。.NET Frameworkのセキュリティチェックに合格すると、アセンブリの内容が最後にビルドされてから変更されていないことが保証されます。
アセンブリの作成者を確認するために厳密な名前を使用することは可能ですか?
はい、上で説明したように、厳密な名前付けにより、アセンブリの最新の作成者を確認できます。ただし、元の作成者を確認するものではありません。攻撃者がアセンブリの厳密な名前を置き換えた場合、確認できるのは、あなたがアセンブリの最新の作成者ではなかったことだけです。彼が厳密な名前を削除すると、作成者の検証はまったく実行できなくなります。
改ざんを回避するために、厳密な名前のアセンブリをどの程度検証できますか?
次のC#コードは、厳密な名前を適用したときにアセンブリに書き込まれた公開鍵トークンが攻撃者によって改ざんされていないことを確認します。改ざんを回避することはできませんが、一部の種類の改ざんを検出できます。以下のメソッドは、公開鍵トークンを含むバイト配列を受け入れ、それをアセンブリの実際のトークンと比較します。この手法を効果的にするには、選択した難読化ツールが公開鍵トークンを含む文字列を暗号化し、使用時にその場でのみ復号化する必要があることに注意してください。また、このコードは内部で反射を使用するため、このコードを機能させるにはFullTrust権限が必要であることに注意してください。
// Check that public key token matches what's expected.
private static bool IsPublicTokenOkay_Check(byte [] tokenExpected)
{
// Retrieve token from current assembly
byte [] tokenCurrent = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken();
// Check that lengths match
if (tokenExpected.Length == tokenCurrent.Length)
{
// Check that token contents match
for (int i = 0; i < tokenCurrent.Length; i++)
if (tokenExpected[i] != tokenCurrent[i])
return false;
}
else
{
return false;
}
return true;
}
.NET 3.5SP1より前のバージョンの.NETFrameworkで実行している限り、攻撃者によって厳密な名前が削除された場合や、レジストリ。次のコードは、NativeMethodsと呼ばれる別のクラスの静的メソッドの呼び出しを示しています。ここで検証が実施されます。
// Check that this assembly has a strong name.
private bool IsStrongNameValid_Check()
{
byte wasVerified = Convert.ToByte(false);
byte forceVerification = Convert.ToByte(true);
string assemblyName = AppDomain.CurrentDomain.BaseDirectory +
AppDomain.CurrentDomain.FriendlyName;
return NativeMethods.CheckSignature(assemblyName,
forceVerification,
ref wasVerified);
}
実際の署名の検証は、以下に示すようにP/Invokeを使用して行われます。StrongNameSignatureVerificationEx APIの使用法は非常に複雑です。適切な説明については、このブログエントリを参照してください。
// P/Invoke to check various security settings
// Using byte for arguments rather than bool,
// because bool won't work on 64-bit Windows!
[DllImport("mscoree.dll", CharSet=CharSet.Unicode)]
private static extern bool StrongNameSignatureVerificationEx(string wszFilePath,
byte fForceVerification,
ref byte pfWasVerified);
// Private constructor because this type has no non-static members
private NativeMethods()
{
}
public static bool CheckSignature(string assemblyName,
byte forceVerification,
ref byte wasVerified)
{
return StrongNameSignatureVerificationEx(assemblyName,
forceVerification,
ref wasVerified );
}
これは、強力な名前バイパス機能を備えた.NET3.5SP1以降を使用するアプリケーションではデフォルトで機能しないことに注意してください。構成ファイルに設定を追加することにより、アプリケーションでこの機能を無効にすることができます。ただし、もちろん、その構成ファイルへの読み取り/書き込みアクセス権を持つ攻撃者は、決定を覆す可能性があります。