Как проверить подлинность для Javascript в C#
Мне удалось подписать JS-файл с помощью PowerShell Set-AuthenticodeSignature. После этого я вижу подпись в файле в виде:
// SIG // Begin signature block
// SIG // MIIKgAYJKoZIhvcNAQcCoIIKcTCCCm0CAQExCzAJBgUr
// SIG // ....
// SIG // End signature block
Я могу проверить подпись с помощью Get-AuthenticodeSignature. Он говорит, что sig действителен, но я не могу найти способ проверить подпись в коде C#. Все эти варианты не удалось:
- X509Certificate.CreateFromSignedFile
- X509Certificate object C# альтернатива производительности и памяти - исправлено
- Используется WinVerifyTrust от Wintrust.dll
- Портированная часть Get-AuthenticodeSignature из PowerShell!
Может быть, есть некоторые конкретные API для проверки подписи JS?
2 ответа
Недавно я столкнулся с подобной проблемой, и позвольте мне показать, что я сделал, чтобы решить эту проблему. Прежде чем я уйду, я сделаю несколько предположений. Пожалуйста, поправьте меня, если я ошибаюсь.
- wintrust работает для всех других случаев, кроме файлов сценариев, таких как.js или.vbs
- Возможно, вы пытались "wintrustverify" из консольного приложения (C#)
Я понял, что это происходит только с файлами сценариев, как я уже упоминал выше, потому что wintrust ведет себя странно, когда его методы выполняются из модели многопоточных квартир (MTA). Как только это было обернуто в нити STA, это начало работать для меня. Позже я узнал, что это историческая проблема, что мы должны были принять меры предосторожности, когда имеем дело с любыми взаимодействиями COM-компонентов из приложения.Net.
Вот фрагмент кода, вы можете заменить верифицируемую подпись логикой кода wintrust и попробовать. Надеюсь, это поможет.
public static void CheckSignature()
{
STAApartment apt = new STAApartment();
var result = apt.Invoke(() =>
{
return VerifySignature(@".\signedjsfile.js", false);
});
Console.WriteLine(result);
}
private static WinVerifyTrustResult VerifySignature(string filePath, bool verifySignatureOnly)
{
using (var wtd = new WinTrustData(new WinTrustFileInfo(filePath))
{
dwUIChoice = WintrustUIChoice.WTD_UI_NONE,
dwUIContext = WinTrustDataUIContext.WTD_DATA_UI_EXECUTE,
fdwRevocationChecks = WinTrustDataRevocationChecks.WTD_REVOCATION_CHECK_WHOLECHAIN,
dwStateAction = WintrustAction.WTD_STATEACTION_IGNORE,
dwProvFlags = verifySignatureOnly ? WintrustProviderFlags.WTD_HASH_ONLY_FLAG : WintrustProviderFlags.WTD_REVOCATION_CHECK_CHAIN
})
{
var result = WinTrust.WinVerifyTrust(
WinTrust.INVALID_HANDLE_VALUE, new Guid(WinTrust.WINTRUST_ACTION_GENERIC_VERIFY_V2), wtd
);
return result;
}
}
public class STAApartment
{
public T Invoke<T>(Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
Thread thread = new Thread(() =>
{
try
{
tcs.SetResult(func());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task.Result;
}
}
WinVerifyTrust поддерживает проверку файлов, отличных от исполняемых файлов, с помощью флага WTD_CHOICE_BLOB. Убедитесь, что вы предоставили структуру WINTRUST_BLOB_INFO с правильным пакетом предметного интерфейса (SIP). Из того, что я вижу, команда Get-AuthenticodeSignature использует PowerShell SIP {603bcc1f-4b59-4e08-b724-d2c6297ef351} для проверки подписи. Я предполагаю, что Set-AuthenticodeSignature использует тот же SIP для подписи скрипта.