此實作不屬於 Windows Platform FIPS 已驗證密碼編譯演算法的一部分

新增一個nodejs的解法。原文關於GPO的設定在本文之後。

最近2020/07月研究了c#調用nodejs,若你的專案可以使用.net 4.5以上,便可以安裝edge.js

交由nodejs來算md5,一樣也不受到FIPS的啟用影響。

直接透過nuget安裝edge.js。

記得引入using EdgeJs;

調用的話

Md5_NodeJs(“Author is so handsome").Wait();

實作

        static async Task<string> Md5_NodeJs(string inputStr) {
            //引入的md5路徑不一定會與此範例相同,請再自行調整,可將md5.js引入到 
            //VS專案中,設好相對路徑,便不需像此範例使用絕對路徑了。
            //md5版本有些實作的不同!有些是回傳buffer,有些是回傳string
            //此範例是回傳是buffer,故要再轉換成string
            Func<object, Task<object>> md5func = Edge.Func(@"
            return function (data, callback) { 
            var md5 = require('C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\uuid\\lib\\md5.js');
            console.log(md5(data));
            const md5CalcResult=md5(data);
            console.log(typeof md5CalcResult);
            md5CalcResultHex=md5CalcResult.toString('hex');
            console.log('Nodejs:'+md5CalcResultHex);
            callback(null, md5CalcResultHex);
        }");
            
            string md5ResultStr = (await md5func(inputStr)).ToString();
            Console.WriteLine(md5ResultStr);
            return md5ResultStr;
        }


看一下第一次po這文的時間,…已經4年前了啊。


政府組態基準GCB有一項標準是
系統密碼編譯: 使用 FIPS 140 相容密碼編譯演算法,包括加密、雜湊與簽署演算法
這個功能若開啟,.net平台就不能用md5
C#以及asp,還有IIS都會被限制,而丟出例外
只有.net平台受到限制,java與Python就沒有受到限制了。

可以自己看一下GPO的設定
路徑是 Security Settings/Local Policies/Security Options/
System cryptography: Use FIPS…..

GCB_FIPS設定

2003 or xp則可以看機碼
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\fipsalgorithmpolicy
是不是被改成1

反組譯.net4.0 的 System.Security.Cryptography.MD5CryptoServiceProvider
可以看見MD5CryptoServiceProvider的建構子

[SecuritySafeCritical]
public MD5CryptoServiceProvider()
{
//就是這個判斷式造成無法用md5的。
if (CryptoConfig.AllowOnlyFipsAlgorithms)
throw new InvalidOperationException(Environment.GetResourceString(“Cryptography_NonCompliantFIPSAlgorithm"));

this._safeHashHandle = Utils.CreateHash(Utils.StaticProvHandle, 32771);
}

.net4可以直接看是否有開啟FIPS的限制,這個屬性是public的
Console.WriteLine(System.Security.Cryptography.CryptoConfig.AllowOnlyFipsAlgorithms);

.net2的話比較煩瑣,要透過叫用NativeCode
[DllImport(“bcrypt.dll")]
internal static extern uint BCryptGetFipsAlgorithmMode(
[MarshalAs(UnmanagedType.U1), Out]out bool pfEnabled);

public static bool IsSecurityOptionsFIPSEnabled
{
get
{
if (Environment.OSVersion.Version.Major >= 6)
{
bool fipsEnabled;
uint policyReadStatus = BCryptGetFipsAlgorithmMode(out fipsEnabled);
return ((policyReadStatus==0) && fipsEnabled);
}
else
{
using (RegistryKey fipsAlgorithmPolicyKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Lsa", false))
{
if (fipsAlgorithmPolicyKey != null)
{
object data = fipsAlgorithmPolicyKey.GetValue(“FIPSAlgorithmPolicy");
if (data != null)
return ((int)data == 1);
}
return false;
}
}
}

}

asp可以改用sha1,但還要在IIS電腦金鑰的地方做調整
電腦金鑰

或是在web.config的<system.web>屬性間加入一行
<system.web>
<machineKey decryption="3DES" validation="SHA1″ />
</system.web>

但我的工具是要與其它產品溝通,沒辦法要求對方也改sha1
所以我一樣得用md5,也可以先用c++寫成處理md5的dll,再來叫用這dll也算是一種解決方式

不過我是採用GNU on Windows的工具
https://github.com/bmatzelle/gow/wiki

md5sum來處理,有3個檔案要複製到
md5sum.exe、libiconv2.dll、libintl3.dll
把我要處理的字串,先存檔
再透過c#叫用此dos指令來計算md5,再濾掉一些不相干的字元