.NET-4 应用程序中的某些设置值是加密存储的[在注册表中]。初始代码使用
AesManaged
类(与此类似)。 6 年前,当我们发现托管实施不符合 FIPS 时,它被 AesCryptoServiceProvider
类取代。
我们采用 Thales / Gemalto / Sentinel / Alladin HASP“包装”进行版权保护和许可。因此,如果/当包装代码中发生异常时,其堆栈跟踪既不会暴露原始对象名称,也不会暴露行号,这使得解开变得相当困难 - 除非在编写原始代码时遵循某些规则(例如使方法简短而简单) )。加密/解密方法位于 HASP 包装的库之一内。
一切都很顺利,直到最近的打包构建在启用 FIPS 的环境中启动失败(!)。更令人惊讶的是:当我尝试旧的打包版本(启用 FIPS)时,它们都失败了。
诚然,这可能是 QA 团队在通常的验证过程中跳过这些路径的结果(不好,但我不负责),但这里有一个意想不到的观察结果:未包装的代码在相同的启用 FIPS 的环境中执行得非常好操作系统! 嗯??
现在,更奇怪的是堆栈跟踪,由我的
UnhandledExceptionEventHandler( )
写入 Windows 事件日志:
System.TypeInitializationException: The type initializer for 'XYZ.Main.Utils' threw an exception.
---> System.InvalidOperationException:
This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
at System.Security.Cryptography.RijndaelManaged..ctor()
at 150694719.150694754.714439608(String 146425350)
at XYZ.Main.Utils..cctor()
--- End of inner exception stack trace ---
at XYZ.Main.Utils.SetModuleTitle(FileVersionInfo fvi)
at XYZ.AppSuite.Program.Main(String[] saArg) in G:\DEV\XYZ\XYZ.AppSuite\Program.cs:line 316
此异常与此处提到的异常非常相似,但指示的代码甚至没有触及任何加密:
/// <summary>Provides common and auxiliary objects and methods</summary>
public partial class Utils
{
/// ** Utils class is exposing global static methods and properties and does not have any constructors - at all! **
..
/// <summary>Returns and sets <see cref="iBuild"/> and <see cref="dBuilt"/>, extracted from the version string (use on 'MM.NNN.*'-versioned assemblies)</summary>
public static DateTime GetBuildFromVersion( string sVersion )
{
Utils.sVersion = sVersion;
Utils.dBuilt = new DateTime( 2000, 1, 1 );
string[] saVersion= sVersion.Split( Utils.ccTokPeriod );
if( saVersion.Length == 4 )
{
Utils.iBuild = Convert.ToInt32( saVersion[ 2 ], CultureInfo.InvariantCulture );
int iBuilt = Convert.ToInt32( saVersion[ 3 ], CultureInfo.InvariantCulture );
Utils.dBuilt = Utils.dBuilt.AddDays( Utils.iBuild );
Utils.dBuilt = Utils.dBuilt.AddSeconds( iBuilt << 1 );
if( TimeZone.IsDaylightSavingTime( Utils.dBuilt, TimeZone.CurrentTimeZone.GetDaylightChanges( Utils.dBuilt.Year ) ) )
Utils.dBuilt = Utils.dBuilt.AddHours( 1 );
}
return Utils.dBuilt;
}
/// <summary>Sets <see cref="Utils.sModInfo"/> and <see cref="Utils.sModTitle"/> strings, based on given assembly version data</summary>
public static void SetModuleTitle( FileVersionInfo fvi )
{
try
{
Utils.sMachine = Dns.GetHostName( );
}
catch
{
Utils.sMachine = Environment.MachineName;
}
Utils.sModInfo = string.Format( Utils.scFmtModId, fvi.FileDescription, fvi.Comments, fvi.FileVersion, Utils.GetBuildFromVersion( fvi.FileVersion ) );
Utils.sModTitle = string.Format( Utils.scFmtModId1, fvi.FileDescription, fvi.Comments, fvi.FileVersion );
Utils.sModStart = string.Format( Utils.scFmtModId3, Utils.idModule, Utils.iBuild, Utils.sMachine );
if( Utils.bService )
Utils.sModTitle = string.Format( Utils.scFmtModId4, Utils.idModule, Utils.iBuild );
}
}
HASP 包装是否有可能调用其自己的
System.Security.Cryptography.RijndaelManaged..ctor()
实例?据我了解,AesCryptoServiceProvider
类肯定不会打电话给RijndaelManaged..ctor()
,对吗?我不使用HASP,所以我不能在这里给你100%的答案,但有一些标准线索我们可以解释。
The type initializer for 'XYZ.Main.Utils' threw an exception.
当类型(静态类或具有静态成员的类型)的静态初始值设定项引发异常时,会出现此类错误消息。进一步支持这一点的是:
at XYZ.Main.Utils..cctor()
cctor()
成员是类型的静态构造函数,可以是您编写的显式构造函数,也可以是编译器创建的用于处理静态成员初始化的自动静态构造函数。
沿着跟踪备份行,我们调用了一个混淆方法
150694719.150694754.714439608()
,它尝试构造 System.Security.Cryptography.RijndaelManaged
的实例...它会抛出 InvalidOperationException
。
这对我来说意味着您的 HASP 实现正在尝试使用
RijndaelManaged
来处理类中静态数据的解密。在配置为符合 FIPS 的计算机上,这将导致您看到的 InvalidOperationException
,因为 Rijndael 不是符合 FIPS 的算法。
您的最佳选择是找到符合 FIPS 标准的更新的 HASP 实施。