実際にCalPol.exeとか .NET Framework 2.0 Configuration でポリシーの設定をして、KeyContainerPermission が付与されない環境で
System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters を呼んでみた。
エラーの時にはどういうpermissionsetが与えられた環境なのかも出力してくれるのね。
発生する例外は SecurityException (この記事末尾参照)であって、ASP.NET で発生した
Exception Details: System.Security.Cryptography.CryptographicException: 指定されたファイルが見つかりません。
ではない!
ASP.NET で発生していた理由は、本当にファイルがないのかもしれんなあ。動作アカウントに関連した C:/Documents And Settings の下に
ユーザ用のキーストアが無いとか。
(1月9日追記: 一度そのアカウントでローカルログオンしたら解消した。この予想が合っていた証拠が増えた。)
今回はSmartCardってわけではなくて、ASP.NETで利用環境が閉じてるのでむしろ managed なクラスが欲しいところだ。
Unhandled Exception: System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters)
at hoge.Main(String[] argv)
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.KeyContainerPermission
The first permission that failed was:
<IPermission class="System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="NoFlags">
<AccessList>
<AccessEntry KeyStore="User"
ProviderName="Microsoft Strong Cryptographic Provider"
ProviderType="1"
KeyContainerName="CLR{05628A34-E00C-4FA9-B752-1074597FAC0D}"
KeySpec="1"
Flags="Export"/>
</AccessList>
</IPermission>
The demand was for:
<IPermission class="System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="NoFlags">
<AccessList>
<AccessEntry KeyStore="User"
ProviderName="Microsoft Strong Cryptographic Provider"
ProviderType="1"
KeyContainerName="CLR{05628A34-E00C-4FA9-B752-1074597FAC0D}"
KeySpec="1"
Flags="Export"/>
</AccessList>
</IPermission>
The granted set of the failing assembly was:
<PermissionSet class="System.Security.PermissionSet" version="1">
<IPermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Access="Open"/>
<IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Allowed="ApplicationIsolationByUser" UserQuota="512000"/>
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Execution"/>
<IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Window="SafeTopLevelWindows" Clipboard="OwnClipboard"/>
<IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Url="file:///c:/temp/hoge.exe"/>
<IPermission class="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Zone="MyComputer"/>
<IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Level="SafePrinting"/>
</PermissionSet>
The assembly or AppDomain that failed was:
hoge, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
The method that caused the failure was:
Void Main(System.String[])
The Zone of the assembly that failed was:
MyComputer
The Url of the assembly that failed was:
file:///c:/temp/hoge.exe
Safeモードで、%SystemRoot%\system32\fntcache.dat を消すというだけではあるが、結構探すのに手間取ったのでメモ。
メーリングリストの登録などで、登録確認のためにURLを埋め込んだりするが、
例えば http://example.com/confirm/key=abcdefg%2bhij というのが、URL表示の時点で http://example.com/confirm/key=abcdefg+hij と解釈されてしまい、 最終的に受け取った際にkeyの値が "abcdefg hij" と+の部分がスペースになっていた。
今回乱数をBase64エンコードした文字列をUrlEncodeしてつっこむという仕様のものを作っていて、 通常のローカルメーラを使ってる環境でのテストでは全く問題が出ていなかったので発見が遅れた。
Base64で利用される記号は +/ であるが、これを ._ に変更したBase64改エンコーディングを利用することにした。 なんかUrlEncodeと相性のいいエンコード方法が規格化されないもんかしら。