स्वचालित विस्तारित सत्यापन (EV) कोड पर हस्ताक्षर करना


82

हमने हाल ही में DigiCert EV कोड साइनिंग सर्टिफिकेट खरीदा है। हम signtool.exe का उपयोग करके .exe फ़ाइलों को साइन इन करने में सक्षम हैं। हालाँकि, हर बार जब हम किसी फ़ाइल पर हस्ताक्षर करते हैं, तो यह SafeNet eToken पासवर्ड के लिए संकेत देता है।

हम इस प्रक्रिया को स्वचालित कैसे कर सकते हैं, उपयोगकर्ता के हस्तक्षेप के बिना, पासवर्ड को कहीं पर संग्रहीत / कैशिंग करके?


सवाल " SafeNet eToken 5110 या इसी तरह के क्रिप्टोग्राफिक हार्डवेयर टोकन के पासवर्ड संकेत कितने सुरक्षित हैं? " कुछ हद तक संबंधित है, अगर यह कभी भी जवाब मिलता है तो यह उन लोगों के लिए रुचि का होना चाहिए जो पासवर्ड प्रविष्टि को स्वचालित करना चाहते हैं। जैसा कि मैं उस पर हूँ, अगर कोई व्यक्ति जो वर्तमान में उसका मालिक है या इसी तरह का कोई टोकन है, तो आप उसे पढ़कर "हैक" करने का प्रयास कर सकते हैं और जवाब दे सकते हैं कि यह सवाल बहुत सराहा जाएगा :)
gbr

दुर्भाग्य से वह जवाब जो मेरे लिए काम करता है और जिसे सबसे अधिक वोट मिलता है, वह उत्तर सूची के अंत में दिखाई देता है, इसलिए अपना समय न
गंवाएं

इनमें से किसी भी समाधान का प्रयास करने से पहले सिर्फ एक सिर। हार्डवेयर टोकन में एक "टोकन पासवर्ड रिट्रीस" काउंटर है (इसे सेफनेट ऑथेंटिकेशन क्लाइंट में जांचा जा सकता है)। प्रयोग करते समय, सुनिश्चित करें कि यह कभी भी स्पष्ट कारणों से शून्य तक नहीं पहुंचता है। अन्यथा आपका संभवतः स्थायी रूप से आपके हार्डवेयर टोकन से लॉक हो जाएगा और आपको एक नया ऑर्डर करना होगा! सीखा इस मुश्किल तरीके से ...
संडे

साइमन का जवाब दुर्भाग्य से अब काम नहीं करता है ( जवाब के लिए मेरी टिप्पणी देखें )। और ऑस्टिन द्वारा जवाब न केवल काम करता है, लेकिन वैसे भी बेहतर है।
मार्टिन प्रिक्रील

जवाबों:


64

लॉगिन डायलॉग AFAIK को बायपास करने का कोई तरीका नहीं है, लेकिन आप क्या कर सकते हैं SafeNet Authentication Client को कॉन्फ़िगर किया गया है, इसलिए यह केवल लॉगिन सत्र के अनुसार इसे पूछता है।

मैं यहां SAC डॉक (एक बार स्थापित \ProgramFiles\SafeNet\Authentication\SAC\SACHelp.chm, अध्याय ' Client Settings', ' Enabling Client Logon') को उद्धृत करता हूं :

जब एकल लॉगऑन सक्षम होता है, तो उपयोगकर्ता प्रत्येक कंप्यूटर सत्र के दौरान टोकन पासवर्ड के लिए केवल एक अनुरोध के साथ कई अनुप्रयोगों तक पहुंच सकते हैं। यह उपयोगकर्ता को प्रत्येक एप्लिकेशन के लिए अलग से लॉग ऑन करने की आवश्यकता को कम करता है।

डिफ़ॉल्ट रूप से अक्षम की गई इस सुविधा को सक्षम करने के लिए, SAC की उन्नत सेटिंग पर जाएं, और "सिंगल लॉगऑन सक्षम करें" बॉक्स की जांच करें:

यहाँ छवि विवरण दर्ज करें

अपने कंप्यूटर को पुनरारंभ करें, और इसे अब केवल एक बार टोकन पासवर्ड के लिए संकेत देना चाहिए। हमारे मामले में, हमारे पास प्रत्येक बिल्ड पर हस्ताक्षर करने के लिए 200 से अधिक बायनेरिज़ हैं, इसलिए यह कुल होना चाहिए

अन्यथा, यहां एक छोटा सी # कंसोल नमूना कोड (m1st0 एक के बराबर) है जो आपको लॉगऑन संवादों के लिए स्वचालित रूप से प्रतिक्रिया करने की अनुमति देता है (संभवतः व्यवस्थापक के रूप में चलाने की आवश्यकता है) (आपको अपने कंसोल प्रोजेक्ट ( UIAutomationClient.dllऔर UIAutomationTypes.dll) से संदर्भ लेने की आवश्यकता है :

using System;
using System.Windows.Automation;

namespace AutoSafeNetLogon {
   class Program {
      static void Main(string[] args) {
         SatisfyEverySafeNetTokenPasswordRequest("YOUR_TOKEN_PASSWORD");
      }


      static void SatisfyEverySafeNetTokenPasswordRequest(string password) {
         int count = 0;
         Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, (sender, e) =>
         {
            var element = sender as AutomationElement;
            if (element.Current.Name == "Token Logon") {
               WindowPattern pattern = (WindowPattern)element.GetCurrentPattern(WindowPattern.Pattern);
               pattern.WaitForInputIdle(10000);
               var edit = element.FindFirst(TreeScope.Descendants, new AndCondition(
                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
                   new PropertyCondition(AutomationElement.NameProperty, "Token Password:")));

               var ok = element.FindFirst(TreeScope.Descendants, new AndCondition(
                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
                   new PropertyCondition(AutomationElement.NameProperty, "OK")));

               if (edit != null && ok != null) {
                  count++;
                  ValuePattern vp = (ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern);
                  vp.SetValue(password);
                  Console.WriteLine("SafeNet window (count: " + count + " window(s)) detected. Setting password...");

                  InvokePattern ip = (InvokePattern)ok.GetCurrentPattern(InvokePattern.Pattern);
                  ip.Invoke();
               } else {
                  Console.WriteLine("SafeNet window detected but not with edit and button...");
               }
            }
         });

         do {
            // press Q to quit...
            ConsoleKeyInfo k = Console.ReadKey(true);
            if (k.Key == ConsoleKey.Q)
               break;
         }
         while (true);
         Automation.RemoveAllEventHandlers();
      }
   }
}

10
यह DigiCert का आधिकारिक उत्तर नहीं हो सकता है, लेकिन उनका उत्तर बेकार है, और यह एक भयानक है! सहायता के लिए धन्यवाद!
लॉर्डजैब

2
एक सही उत्तर के लिए +1। यह मुझे उपयोगकर्ता इनपुट को स्वचालित करने के लिए स्क्रिप्ट विकसित करने वाले लोगों को देखता है और इस तरह, पासवर्ड रखने के उद्देश्य को वास्तव में हरा देता है, और उन्हें यह जानने की आवश्यकता थी कि यह विकल्प कहां था। मुझे संदेह है कि यह विकल्प कभी भी गायब हो जाएगा, क्योंकि जारीकर्ता समझते हैं कि हर बार द्विआधारी हस्ताक्षर किए जाने पर डेवलपर्स पासवर्ड में टाइप नहीं कर सकते हैं।
डाइस्टा

3
मैं पुष्टि कर सकता हूं कि यह TeamCity से काम करता है (जब तक TeamCity Windows सेवा में "डेस्कटॉप के साथ बातचीत करने की अनुमति दें सेवा" बॉक्स टिक हो जाती है)। हमें अपनी प्रवेश मशीन पर "इंटरेक्टिव सर्विसेज डिटेक्शन" सेवा को निष्क्रिय करने के लिए पासवर्ड प्रविष्टि प्रक्रिया को दूसरे धागे में चलाने की भी आवश्यकता थी। हमने साइनटूल के चारों ओर एक सी # आवरण बनाया है, जो हस्ताक्षर करता है और एक स्व-निहित ऐप में सभी के रूप में पासवर्ड प्रविष्टि को संभाला है। मैं विश्वास नहीं कर सकता कि इस काम को पाने के लिए हमें कितनी बाधाएं पार करनी पड़ीं, लेकिन एक ही नाव में किसी और के लिए, ऊपर वर्णित C # विधि पर ध्यान दें ...
एलन स्पार्क

1
FYI करें ... सिमेंटेक EV सेर्ट्स SafeNet का भी उपयोग करते हैं। हमें इस प्रक्रिया के चारों ओर एक घिनौना समाधान बनाया गया था, लेकिन आपके उत्तर को पढ़ने और कंसोल ऐप को लागू करने के बाद, इसने हमारी निर्माण प्रक्रिया को पूरी तरह से समाप्त करने में मदद की। धन्यवाद। एक खराब आर्किटेक्चर कोड पर हस्ताक्षर करने की प्रक्रिया के लिए महान समाधान।
ज़ोल्टन

1
मैं कुछ समय के लिए इस उपयोगी समाधान का सफलतापूर्वक उपयोग कर रहा हूं। लेकिन अब जब विंडोज 8 प्रो 2004 के साथ विंडोज 8 प्रो 2004 के साथ नई मशीन पर इसे स्थापित किया गया है, तो विंडोज 8 और इसके बाद के संस्करण 9.0.34 x64 के लिए, यह अब काम नहीं करता है। जहां एक नया पासवर्ड प्रॉम्प्ट है। यह पहले की तरह कस्टम सेफनेट प्रॉम्प्ट के बजाय एक विंडोज बिल्ट-इन वन लगता है। और नए प्रॉम्प्ट का पासवर्ड बॉक्स स्वचालित नहीं है (यह AutomationElementपेड़ में उजागर नहीं है )। मुझे नहीं पता कि यह किसी भी तरह से काम किया जा सकता है या नहीं। लेकिन फिर से इस सवाल पर जाकर @ आस्टिन द्वारा जवाब खोजने पर, मेरा मानना ​​है कि यह एक बेहतर उपाय है।
मार्टिन प्रिक्रील

34

इस थ्रेड में पहले से ही उत्तरों पर विस्तार करते हुए, Microsoft से मानक साइनटूल प्रोग्राम का उपयोग करके टोकन पासवर्ड प्रदान करना संभव है।

0. उन्नत दृश्य में SafeNet क्लाइंट खोलें

इंस्टॉल पथ भिन्न हो सकते हैं, लेकिन मेरे लिए SafeNet क्लाइंट स्थापित है: C:\Program Files\SafeNet\Authentication\SAC\x64\SACTools.exe

"उन्नत दृश्य" खोलने के लिए ऊपरी दाईं ओर स्थित गियर आइकन पर क्लिक करें। सेफनेट एडवांस्ड व्यू

1. अपने सार्वजनिक प्रमाण पत्र को SafeNet क्लाइंट से फ़ाइल में निर्यात करें प्रमाणपत्र को फ़ाइल में निर्यात करना

2. अपना निजी कुंजी कंटेनर नाम ढूंढें
निजी कुंजी कंटेनर का नाम

3. अपने पाठक का नाम खोजें पाठक का नाम

4. यह सब एक साथ प्रारूपित करें

कंटेनर के नाम से टोकन पासवर्ड को पार्स करने के लिए eToken CSP ने (या कम से कम व्यापक रूप से विज्ञापित नहीं) कार्यक्षमता छिपाई है।

प्रारूप निम्नलिखित में से एक है

[]=name
[reader]=name
[{{password}}]=name
[reader{{password}}]=name

कहाँ पे:

  • reader SafeNet क्लाइंट UI से "रीडर का नाम" है
  • password आपका टोकन पासवर्ड है
  • name SafeNet क्लाइंट UI से "कंटेनर नाम" है

यदि आप एक से अधिक पाठक जुड़े हैं, तो संभवतः आपको पाठक का नाम निर्दिष्ट करना होगा - क्योंकि मेरे पास केवल एक पाठक है जो मैं इसकी पुष्टि नहीं कर सकता।

5. साइनटूल को सूचना पास करें

  • /f certfile.cer
  • /csp "eToken Base Cryptographic Provider"
  • /k "<value from step 4>"
  • किसी भी अन्य हस्ताक्षरित झंडे की आवश्यकता है

उदाहरण के रूप में साइनटूल कमांड

signtool sign /f mycert.cer /csp "eToken Base Cryptographic Provider" /k "[{{TokenPasswordHere}}]=KeyContainerNameHere" myfile.exe

इस उत्तर से ली गई कुछ छवियां: https://stackoverflow.com/a/47894907/5420193


2
महान काम करता है, दुःख की बात है कि मुझे दो दिन बाद खुदाई करने और खुद के "साइनटूल" को लागू करने का पता चला: D thx
Lukáš Koten

चेतावनी: यदि आप गलत पासवर्ड दर्ज करते हैं, तो यह समाधान आपके हार्डवेयर टोकन से बाहर निकल सकता है, यहां तक ​​कि सिर्फ दो बार भी! किसी तरह अमान्य पासवर्ड के साथ कमांड को निष्पादित करने के बाद किसी तरह से पासवर्ड शेष काउंटर 15 से घटकर 3 हो गया। "Etokensign.exe" समाधान ठीक काम करता है, हालांकि, शेष पासवर्ड काउंटर कम हो गया क्योंकि यह एक अमान्य पासवर्ड प्रयास के बाद 15 से 14 तक होना चाहिए।
संडे

1
अद्भुत, यह मेरे लिए सेफनेट यूएसबी डोंगल के साथ पूरी तरह से काम करता है जो सेक्टिगो से मेरे पास आया था।
याकूब

1
जहाँ तक मुझे पता है, यह वाक्यविन्यास कहीं भी सार्वजनिक रूप से प्रलेखित नहीं है। मैंने इस कार्यक्षमता को IDA प्रो में ड्राइवर बाइनरी रिवर्स इंजीनियरिंग द्वारा पाया।
ऑस्टिन मॉर्टन

1
यह उन अन्य उत्तरों से बेहतर है जो GUI संकेतों के लिए नकली पासवर्ड इनपुट करते हैं। अन्य के अलावा, यह गैर-संवादात्मक विंडोज सत्रों में भी काम करता है। और अन्य उत्तर नवीनतम उपकरणों के साथ काम नहीं करते प्रतीत होते हैं
मार्टिन प्रिक्रील

19

इस उत्तर पर विस्तार करते हुए , यह CryptAcquireContext और CryptSetProvParam का उपयोग करके स्वचालित रूप से टोकन पिन दर्ज करने के लिए प्रोग्रामेटिक रूप से प्रवेश कर सकता है और CryptUIWizDigitalSign पर हस्ताक्षर करने के लिए प्रोग्राम कर सकता है। मैंने एक कंसोल ऐप (नीचे दिया गया कोड) बनाया, जो कि सर्टिफिकेट फ़ाइल को इनपुट के रूप में लेता है (सेफनेट ऑथेंटिकेशन क्लाइंट में सर्टिफिकेट पर राइट क्लिक करके और "एक्सपोर्ट ..." का चयन करते हुए), प्राइवेट कुंजी कंटेनर नाम (सेफनेट ऑथेंटिकेशन क्लाइंट में पाया जाता है), टोकन पिन, टाइमस्टैम्प URL और हस्ताक्षर करने के लिए फ़ाइल का पथ। यह कंसोल ऐप तब काम करता है जब टीमकिट बिल्ड एजेंट द्वारा बुलाया जाता है जहां यूएसबी टोकन जुड़ा हुआ था।

उदाहरण उपयोग:
etokensign.exe c:\CodeSigning.cert CONTAINER PIN http://timestamp.digicert.com C:\program.exe

कोड:

#include <windows.h>
#include <cryptuiapi.h>
#include <iostream>
#include <string>

const std::wstring ETOKEN_BASE_CRYPT_PROV_NAME = L"eToken Base Cryptographic Provider";

std::string utf16_to_utf8(const std::wstring& str)
{
    if (str.empty())
    {
        return "";
    }

    auto utf8len = ::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), NULL, 0, NULL, NULL);
    if (utf8len == 0)
    {
        return "";
    }

    std::string utf8Str;
    utf8Str.resize(utf8len);
    ::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), &utf8Str[0], utf8Str.size(), NULL, NULL);

    return utf8Str;
}

struct CryptProvHandle
{
    HCRYPTPROV Handle = NULL;
    CryptProvHandle(HCRYPTPROV handle = NULL) : Handle(handle) {}
    ~CryptProvHandle() { if (Handle) ::CryptReleaseContext(Handle, 0); }
};

HCRYPTPROV token_logon(const std::wstring& containerName, const std::string& tokenPin)
{
    CryptProvHandle cryptProv;
    if (!::CryptAcquireContext(&cryptProv.Handle, containerName.c_str(), ETOKEN_BASE_CRYPT_PROV_NAME.c_str(), PROV_RSA_FULL, CRYPT_SILENT))
    {
        std::wcerr << L"CryptAcquireContext failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
        return NULL;
    }

    if (!::CryptSetProvParam(cryptProv.Handle, PP_SIGNATURE_PIN, reinterpret_cast<const BYTE*>(tokenPin.c_str()), 0))
    {
        std::wcerr << L"CryptSetProvParam failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
        return NULL;
    }

    auto result = cryptProv.Handle;
    cryptProv.Handle = NULL;
    return result;
}

int wmain(int argc, wchar_t** argv)
{
    if (argc < 6)
    {
        std::wcerr << L"usage: etokensign.exe <certificate file path> <private key container name> <token PIN> <timestamp URL> <path to file to sign>\n";
        return 1;
    }

    const std::wstring certFile = argv[1];
    const std::wstring containerName = argv[2];
    const std::wstring tokenPin = argv[3];
    const std::wstring timestampUrl = argv[4];
    const std::wstring fileToSign = argv[5];

    CryptProvHandle cryptProv = token_logon(containerName, utf16_to_utf8(tokenPin));
    if (!cryptProv.Handle)
    {
        return 1;
    }

    CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO extInfo = {};
    extInfo.dwSize = sizeof(extInfo);
    extInfo.pszHashAlg = szOID_NIST_sha256; // Use SHA256 instead of default SHA1

    CRYPT_KEY_PROV_INFO keyProvInfo = {};
    keyProvInfo.pwszContainerName = const_cast<wchar_t*>(containerName.c_str());
    keyProvInfo.pwszProvName = const_cast<wchar_t*>(ETOKEN_BASE_CRYPT_PROV_NAME.c_str());
    keyProvInfo.dwProvType = PROV_RSA_FULL;

    CRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pvkInfo = {};
    pvkInfo.dwSize = sizeof(pvkInfo);
    pvkInfo.pwszSigningCertFileName = const_cast<wchar_t*>(certFile.c_str());
    pvkInfo.dwPvkChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK_PROV;
    pvkInfo.pPvkProvInfo = &keyProvInfo;

    CRYPTUI_WIZ_DIGITAL_SIGN_INFO signInfo = {};
    signInfo.dwSize = sizeof(signInfo);
    signInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE;
    signInfo.pwszFileName = fileToSign.c_str();
    signInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK;
    signInfo.pSigningCertPvkInfo = &pvkInfo;
    signInfo.pwszTimestampURL = timestampUrl.c_str();
    signInfo.pSignExtInfo = &extInfo;

    if (!::CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, NULL, NULL, &signInfo, NULL))
    {
        std::wcerr << L"CryptUIWizDigitalSign failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
        return 1;
    }

    std::wcout << L"Successfully signed " << fileToSign << L"\n";
    return 0;
}

प्रमाणपत्र को फ़ाइल में निर्यात करना:
प्रमाणपत्र को फ़ाइल में निर्यात करना

निजी कुंजी कंटेनर का नाम:
निजी कुंजी कंटेनर का नाम


2
यह एक स्वीकृत उत्तर होना चाहिए, यह एक आकर्षण की तरह काम करता है!
शाम

1
यह पूर्ण है। विशेष रूप से मुझे एहसास होने के बाद कि मुझे केवल इस उपकरण के साथ कुछ डमी फ़ाइल पर हस्ताक्षर करने की आवश्यकता है। यदि "सिंगल लॉगऑन" सक्षम है (SafeNet ड्राइवर), तो बाद के सभी चरण मानक साइनटूल के साथ काम करते हैं। यह Office Addins (VSTO) पर हस्ताक्षर करने के लिए बहुत उपयोगी है, जो एक अलग टूल का उपयोग करते हैं और इसका मतलब यह भी था कि मेरी बिल्ड स्क्रिप्ट / प्रक्रिया के लिए केवल न्यूनतम परिवर्तन आवश्यक थे।
स्टीफन एगली

यह उत्तर एज़हतकिन द्वारा प्रदान किए गए एक अच्छा जोड़ है। इस बिंदु पर कोड signtools.exe को प्रतिस्थापित करने के करीब है। इस कार्यक्रम को क्रॉस साइनिंग का समर्थन करने की आवश्यकता होगी। सौभाग्य से क्रॉस साइन करने के लिए अब एक और एसओ पद है ।
sdc

इस जवाब ने मुझे सबसे ज्यादा मदद की। VS2017 में निर्माण के दौरान मैं एक बाहरी संदर्भ से चूक गया था, लेकिन जब यहाँ सुझाए गए कुछ व्यावहारिक टिप्पणियों को जोड़ते हुए मैं हस्ताक्षर करने के लिए बांस (CI / CD द्वारा एटलसियन) प्राप्त करने में कामयाब रहा।
एचटीबीआर

11

मुझे बीटा टूल बनाया गया है जो निर्माण प्रक्रिया को स्वचालित करने में मदद करेगा।

यह क्लाइंट-सर्वर विंडोज़ एप्लीकेशन है। आप कंप्यूटर पर सर्वर शुरू कर सकते हैं जहां ईवी टोकन डाला गया है। सर्वर-साइड एप्लिकेशन स्टार्टअप पर टोकन के लिए पासवर्ड दर्ज करें। इसके बाद आप फाइलों को रिमोट से साइन कर सकते हैं। क्लाइंट साइड एप्लिकेशन पूरी तरह से signtool.exe को बदल देता है ताकि आप मौजूदा बिल्ड स्क्रिप्ट का उपयोग कर सकें।

स्रोत कोड यहां स्थित है: https://github.com/SirAlex/RemoteSignTool

संपादित करें: हमने अपने बिल्ड सर्वर पर पिछले आधे साल के 24x7 कोड पर हस्ताक्षर करने के लिए इस उपकरण का सफलतापूर्वक उपयोग किया। सभी ठीक काम करता है।


1
यह दृष्टिकोण कितना सुरक्षित है? क्या इसका मतलब यह नहीं है कि जो कोई भी आपके हस्ताक्षर सर्वर से HTTP से जुड़ सकता है, वह आपके ईवी प्रमाण पत्र के साथ किसी भी द्विआधारी को साइन कर सकता है?
जीन पावलोवस्की

6

वास्तव में विंडोज पर आप टोकन पासवर्ड को पूरी तरह से प्रोग्रामेटिक रूप से निर्दिष्ट कर सकते हैं। यह फ्लैग CRYPT_SILENT के साथ एक संदर्भ ( CryptAcquireContext ) बनाकर किया जा सकता है , जो कि "\\। \ AKS ifdh 0" या टोकन कंटेनर नाम के रूप में टोकन नाम का उपयोग कर रहा है, जो प्रमाणीकरण क्लाइंट अनुप्रयोग में कुछ प्रमाणपत्र प्रमाणपत्र गुणों में दिखाई देता है। फिर आपको अपने टोकन पासवर्ड को निर्दिष्ट करने के लिए पैरामीटर PP_SIGNATURE_PIN के साथ CryptSetProvParam का उपयोग करने की आवश्यकता है । इसके बाद प्रक्रिया फाइलों पर हस्ताक्षर करने के लिए उस टोकन पर प्रमाण पत्र का उपयोग कर सकती है।
ध्यान दें: एक बार जब आप संदर्भ बनाते हैं, तो यह केवल वर्तमान प्रक्रिया के लिए पूरी तरह से काम करने के लिए लगता है, इसे अन्य क्रिप्टो एपीआई फ़ंक्शन या किसी भी चीज़ को पारित करने की आवश्यकता नहीं है। लेकिन बेझिझक टिप्पणी करें यदि आपको ऐसी स्थिति मिलती है जब कुछ और प्रयासों की आवश्यकता होगी।
संपादित करें: जोड़ा गया कोड नमूना

HCRYPTPROV OpenToken(const std::wstring& TokenName, const std::string& TokenPin)
{
    const wchar_t DefProviderName[] = L"eToken Base Cryptographic Provider";

    HCRYPTPROV hProv = NULL;
    // Token naming can be found in "eToken Software Developer's Guide"
    // Basically you can either use "\\.\AKS ifdh 0" form
    // Or use token's default container name, which looks like "ab-c0473610-8e6f-4a6a-ae2c-af944d09e01c"
    if(!CryptAcquireContextW(&hProv, TokenName.c_str(), DefProviderName, PROV_RSA_FULL, CRYPT_SILENT))
    {
        DWORD Error = GetLastError();
        //TracePrint("CryptAcquireContext for token %ws failed, error 0x%08X\n", TokenName.c_str(), Error);
        return NULL;
    }
    if(!CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (BYTE*)TokenPin.c_str(), 0))
    {
        DWORD Error = GetLastError();
        //TracePrint("Token %ws unlock failed, error 0x%08X\n", TokenName.c_str(), Error);
        CryptReleaseContext(hProv, 0);
        return NULL;
    }
    else
    {
        //TracePrint("Unlocked token %ws\n", TokenName.c_str());
        return hProv;
    }
}

1
दिलचस्प है। होनहार लगता है, आपको चाहिए कि IMHO उस पर विस्तार से बताएं (स्पष्टीकरण प्रदान करें, कोड प्रदान करें, आदि)
शमौन मॉरियर

कृपया एक पूर्ण उदाहरण पोस्ट करें। यह वास्तव में उपयोगी लगता है
9

अतिरिक्त विवरण के लिए धन्यवाद। क्या यह मार्गदर्शिका है जिसका आप उल्लेख करते हैं? read.pudn.com/downloads128/ebook/549477/eToken_SDK_3_50 Is1iding.pdf
dten

मेरा मानना ​​है कि यह सटीक संस्करण नहीं है जो मेरे पास था, लेकिन यह संदर्भ बनाने और पिन प्रदान करने के बारे में समान जानकारी रखता है, हालांकि अलग-अलग उपयोग परिदृश्यों के लिए।
१२:०२ पर एज़हतिन

मुझे लगता है कि आप इस फ़ंक्शन को OpenToken (L "\\\\। \\ AKS ifdh 0", <टोकन पासवर्ड>) कहते हैं ... अच्छी तरह से यह मेरे लिए काम करता है!
माइकल Haephrati

5

मैंने निम्नलिखित स्क्रिप्ट का उपयोग करके पासवर्ड प्रविष्टि को स्वचालित करने के लिए AutoHotKey का उपयोग किया। हम अपने डेवलपर्स के लिए बायनेरिज़ को इस स्क्रिप्ट के साथ विंडोज बॉक्स में भेजने के लिए एक वेब आधारित फ्रंट एंड बनाने की कोशिश कर रहे हैं ताकि इसे साइन किया जा सके और वापस आ सके।

  Loop
  {   
    Sleep 2000

    if (WinExist("Token Logon"))
    {   
      WinActivate ; use the window found above
      SendInput [your_password]
      SendInput {Enter}
    }   
    if (WinExist("DigiCert Certificate Utility for Windows©"))
    {   
      WinActivate ; use the window found above
      SendInput [your_password]
      SendInput {Enter}
    }   
  } 

मुझे ध्यान देना चाहिए कि जो मैंने साझा किया है वह पूरी तरह से सुरक्षित नहीं है, लेकिन हमने इस मुद्दे को भी मारा है, जिसमें प्रत्येक डेवलपर के लिए हस्ताक्षर कुंजी खरीदने या हस्ताक्षर करने वाले प्रबंधक की नौकरी सौंपने की आवश्यकता है जो जारी किए गए सॉफ़्टवेयर के हस्ताक्षर को मंजूरी देगा। मेरा मानना ​​है कि वे बेहतर, सुरक्षित प्रक्रियाएं हैं - कि एक बार जब चीजें गुणवत्ता आश्वासन पारित करती हैं और रिलीज के लिए अनुमोदित हो जाती हैं, तो उन्हें आधिकारिक रूप से हस्ताक्षरित किया जा सकता है। हालांकि, छोटी कंपनी की जरूरत है कि यह कुछ अन्य स्वचालित तरीके से किया जा सकता है।

मैंने मूल रूप से विंडोज निष्पादनयोग्य के हस्ताक्षर को स्वचालित करने के लिए लिनक्स पर (ईवी प्रमाण पत्र से पहले) ओस्सलिग्नकोड का उपयोग किया था (क्योंकि हमारे पास लिनक्स सर्वर था जो डेवलपर आसानी और सहयोग के लिए बहुत काम कर रहा था)। मैंने osslsigncode के डेवलपर से यह देखने के लिए संपर्क किया है कि क्या वह DigiCert SafeNet टोकन का उपयोग करके इसे एक अलग तरीके से स्वचालित करने में मदद कर सकता है क्योंकि मैं उन्हें लिनक्स पर देख सकता हूं। उनके जवाब ने आशा प्रदान की लेकिन मैं किसी भी प्रगति के बारे में अनिश्चित हूं और मैं मदद करने के लिए अधिक समय समर्पित नहीं कर सका


अन्य उत्तर देखें। प्रति सत्र केवल एक बार अनलॉक करने का विकल्प है, जो अधिकांश उपयोगकर्ताओं के लिए पर्याप्त है।
dyasta

5

signtool.exe साइन / fd sha256 / f "sign.cer" / csp "eToken Base क्रिप्टोग्राफ़िक प्रदाता" / kc "[{{टोकन पासवर्ड यहाँ}}] = यहाँ कंटेनर का नाम" "ConsoleApp.exe"

Signtool के लिए Microsoft Windows SDK 10 का उपयोग करें


1
उत्तम! यह एक-लाइनर निश्चित रूप से शर्म करने के लिए अन्य सभी जवाब देता है (हालांकि पहले मैं हैरान था कि मेरे "कंटेनर नाम" का पता कैसे लगाया जाए, जब तक कि मुझे ऊपर दिए गए ड्रेकेटब के जवाब में निर्देश नहीं मिला)।
Dan Z

5

Https://chatalogy.org/docs/installation स्थापित करें (प्रशासनिक कमांड प्रॉम्प्ट से एक कमांड का उपयोग करके किया जा सकता है)

(कमांड प्रॉम्प्ट को पुनरारंभ करें)

प्रत्येक स्थापना के लिए सुपर चोको का निरंतर संकेत:

choco feature enable -n=allowGlobalConfirmation

कमांड का उपयोग करके अजगर को स्थापित करें:

choco install python

(कमांड प्रॉम्प्ट को पुनरारंभ करें) अतिरिक्त अजगर मॉड्यूल स्थापित करें:

pip install pypiwin32

निम्नलिखित पाठ को इसमें सहेजें disableAutoprompt.py:

import pywintypes
import win32con
import win32gui
import time



DIALOG_CAPTION = 'Token Logon'
DIALOG_CLASS = '#32770'
PASSWORD_EDIT_ID = 0x3ea
TOKEN_PASSWORD_FILE = 'password.txt'
SLEEP_TIME = 10


def get_token_password():
    password = getattr(get_token_password, '_password', None)
    if password is None:
        with open(TOKEN_PASSWORD_FILE, 'r') as f:
            password = get_token_password._password = f.read()

    return password

def enumHandler(hwnd, lParam):
    if win32gui.IsWindowVisible(hwnd):
        if win32gui.GetWindowText(hwnd) == DIALOG_CAPTION and win32gui.GetClassName(hwnd) == DIALOG_CLASS:
            print('Token logon dialog has been detected, trying to enter password...')
            try:
                ed_hwnd = win32gui.GetDlgItem(hwnd, PASSWORD_EDIT_ID)
                win32gui.SendMessage(ed_hwnd, win32con.WM_SETTEXT, None, get_token_password())
                win32gui.PostMessage(ed_hwnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
                print('Success.')
            except Exception as e:
                print('Fail: {}'.format(str(e)))
                return False

    return True


def main():
    while True:
        try:
            win32gui.EnumWindows(enumHandler, None)
            time.sleep(SLEEP_TIME)
        except pywintypes.error as e:
            if e.winerror != 0:
                raise e


if __name__ == '__main__':
    print('Token unlocker has been started...')
    print('DO NOT CLOSE THE WINDOW!')
    main()

अपना पासवर्ड passwd.txt में सेव करें, और उसके बाद रन करें

python disableAutoprompt.py

से SafeNet Authentication Client- विन्यास> Client Settings> Advanced> Enable Single Log On विकल्प पासवर्ड संकेत की मात्रा को कम करने के लिए सक्रिय किया जा सकता है, लेकिन यह पूरी तरह से उन्हें निष्क्रिय नहीं करता है (संस्करण 10.4.26.0 पर परीक्षण किया गया)

C # एप्लिकेशन (Eg https://github.com/ganl/safenetpass ) लॉक स्क्रीन के साथ काम नहीं करता है, लेकिन इस पायथन स्क्रिप्ट के साथ काम करता है।


यह स्क्रिप्ट बहुत बढ़िया है, और मैं आसानी से इसे एक य्यूबिक डोंगल के साथ काम करने के लिए अनुकूलित करने में सक्षम था। हालाँकि, विंडोज 10 इसे तोड़ता है। Windows 10 XAML में परिवर्तन करता है और इसलिए win32gui.xxxx () फ़ंक्शन काम नहीं करेगा। / रोशनी। धन्यवाद Microsoft। यही कारण है कि हम अच्छी चीजें नहीं कर सकते हैं।
जॉन रोचा

2

Digicert का जवाब मिला:

दुर्भाग्य से, EV कोड हस्ताक्षर प्रमाण पत्र के साथ सुरक्षा का हिस्सा यह है कि आपको हर बार पासवर्ड दर्ज करना होगा। इसे स्वचालित करने का कोई तरीका नहीं है।


हमें एक ही प्रतिक्रिया मिली, हालांकि वे एक समाधान में देख रहे हैं कि उनके पास कोई समय सीमा नहीं है जब कोई उपलब्ध हो सकता है। वे इस एसओ पद के बारे में जानते हैं, हालांकि उम्मीद है कि उन्हें एहसास होगा कि यह कितना मुद्दा है।
एलन स्पार्क

हमें इसके चारों ओर एक रास्ता मिला: github.com/mareklinka/SafeNetTokenSigner/issues/8
गनलिंग्लॉर

2

मेरा मामला डिजिकर्ट सीआई के लिए एक मानक (ओवी) प्रमाणपत्र जारी करता है, अगर आपके पास पहले से ईवी प्रमाण पत्र है।

मुझे पता है कि यह समाधान नहीं है, लेकिन यदि आप सर्वर (एक क्लाउड सर्वर) में टोकन नहीं डाल सकते, तो यह रास्ता तय करना है।


1

जिस तरह से मैं यह कर रहा हूँ:

  1. टोकन खोलें

    PCCERT_CONTEXT प्रमाण पत्र = OpenToken (SAFENET_TOKEN, EV_PASS);

  2. आवश्यकता होने पर टोकन, रूट / क्रॉस प्रमाण पत्र और मेमोरी में लोड ईवी प्रमाण पत्र का उपयोग करके फ़ाइल पर हस्ताक्षर करें

    HRESULT hr = SignAppxPackage (प्रमाणित, FILETOSIGN);

SignerSignEx2 () का उपयोग करना:

फ़ाइल SignerSignEx2 () का उपयोग कर साइन इन की जाती है, जिसे LoadLibrary () और GetProcAddress () का उपयोग करके मेमोरी में लोड करने की आवश्यकता होती है:

// Type definition for invoking SignerSignEx2 via GetProcAddress
typedef HRESULT(WINAPI *SignerSignEx2Function)(
    DWORD,
    PSIGNER_SUBJECT_INFO,
    PSIGNER_CERT,
    PSIGNER_SIGNATURE_INFO,
    PSIGNER_PROVIDER_INFO,
    DWORD,
    PCSTR,
    PCWSTR,
    PCRYPT_ATTRIBUTES,
    PVOID,
    PSIGNER_CONTEXT *,
    PVOID,
    PVOID);

// Load the SignerSignEx2 function from MSSign32.dll
HMODULE msSignModule = LoadLibraryEx(
    L"MSSign32.dll",
    NULL,
    LOAD_LIBRARY_SEARCH_SYSTEM32);

if (msSignModule)
{
    SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
        GetProcAddress(msSignModule, "SignerSignEx2"));
    if (SignerSignEx2)
    {
        hr = SignerSignEx2(
            signerParams.dwFlags,
            signerParams.pSubjectInfo,
            signerParams.pSigningCert,
            signerParams.pSignatureInfo,
            signerParams.pProviderInfo,
            signerParams.dwTimestampFlags,
            signerParams.pszAlgorithmOid,
            signerParams.pwszTimestampURL,
            signerParams.pCryptAttrs,
            signerParams.pSipData,
            signerParams.pSignerContext,
            signerParams.pCryptoPolicy,
            signerParams.pReserved);
    }
    else
    {
        DWORD lastError = GetLastError();
        hr = HRESULT_FROM_WIN32(lastError);
    }

    FreeLibrary(msSignModule);
}
else
{
    DWORD lastError = GetLastError();
    hr = HRESULT_FROM_WIN32(lastError);
}

// Free any state used during app package signing
if (sipClientData.pAppxSipState)
{
    sipClientData.pAppxSipState->Release();
}

समय मुद्रांकन

इसके अलावा, आपको अपनी साइन की गई फ़ाइल को टाइम स्टैम्प करना चाहिए और टाइम स्टैम्पिंग प्राधिकरण का उपयोग करना चाहिए जिससे आप कनेक्ट होते हैं।

यह वर्तमान समय और समय के लिए URL के माध्यम से टाइम स्टैम्पिंग सर्वर को सुरक्षित रूप से जांचने के द्वारा किया जाता है। प्रत्येक साइनिंग अथॉरिटी का अपना टाइम स्टैम्पिंग सर्वर होता है। टाइम स्टैम्पिंग कोड साइनिंग प्रक्रिया में एक अतिरिक्त कदम है, लेकिन जब ईवी कोड पर हस्ताक्षर करने की बात आती है तो यह एक आवश्यकता है जो हस्ताक्षरित पीई में सुरक्षा की एक अतिरिक्त परत जोड़ता है। उस कारण से, अपने कोड को एक जांच में जोड़ें कि क्या उपयोगकर्ता इंटरनेट से जुड़ा है।

DWORD dwReturnedFlag;
if (InternetGetConnectedState(&dwReturnedFlag,0) == NULL) // use https://docs.microsoft.com/en-us/windows/desktop/api/netlistmgr/nf-netlistmgr-inetworklistmanager-getconnectivity
{
    wprintf(L"Certificate can't be dated with no Internet connection\n");
    return 1;
}

एक फ़ाइल से एक प्रमाण पत्र लोड हो रहा है

std::tuple<DWORD, DWORD, std::string> GetCertificateFromFile
(const wchar_t*                         FileName
    , std::shared_ptr<const CERT_CONTEXT>*   ResultCert)
{
    std::vector<unsigned char> vecAsn1CertBuffer;
    auto tuple_result = ReadFileToVector(FileName, &vecAsn1CertBuffer);

    if (std::get<0>(tuple_result) != 0)
    {
        return tuple_result;
    }

    return GetCertificateFromMemory(vecAsn1CertBuffer, ResultCert);
}

स्मृति में एक प्रमाण पत्र लोड हो रहा है

std::tuple<DWORD, DWORD, std::string> GetCertificateFromMemory
(const std::vector<unsigned char>&      CertData
    , std::shared_ptr<const CERT_CONTEXT>*   ResultCert)
{
    const CERT_CONTEXT* crtResultCert = ::CertCreateCertificateContext
    (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
        , &CertData[0]
        , static_cast<DWORD>(CertData.size()));
    if (crtResultCert == NULL)
    {
        return std::make_tuple(E_FAIL
            , ::GetLastError()
            , "CertCreateCertificateContext");
    }

    *ResultCert = std::shared_ptr<const CERT_CONTEXT>(crtResultCert
        , ::CertFreeCertificateContext);
    return std::make_tuple(0, 0, "");
}

सर्टिफिकेट लोड होने के बाद हार्डवेयर टोकन को लोड करने के बाद हम इसे लोड करते हैं:

std::vector<unsigned char> dataCertEV(signingCertContext->pbCertEncoded,
        signingCertContext->pbCertEncoded + signingCertContext->cbCertEncoded);

अंत में, हस्ताक्षर निम्नलिखित समारोह में किया जाता है:

HRESULT SignAppxPackage(
    _In_ PCCERT_CONTEXT signingCertContext,
    _In_ LPCWSTR packageFilePath)
{
    HRESULT hr = S_OK;
    if (PathFileExists(CertAuthority_ROOT))
    {
        wprintf(L"Cross Certificate '%s' was found\n", CertAuthority_ROOT);
    }
    else
    {
        wprintf(L"Error: Cross Certificate '%s' was not found\n", CertAuthority_ROOT);
        return 3;
    }
    DWORD dwReturnedFlag;
    if (InternetGetConnectedState(&dwReturnedFlag,0) == NULL) 
    {
        wprintf(L"Certificate can't be dated with no Internet connection\n");
        return 1;
    }
    if (PathFileExists(CertAuthority_RSA))
    {
        wprintf(L"Cross Certificate '%s' was found\n", CertAuthority_RSA);
    }
    else
    {
        wprintf(L"Error: Cross Certificate '%s' was not found\n", CertAuthority_RSA);
        return 2;
    }
    if (PathFileExists(CROSSCERTPATH))
    {
        wprintf(L"Microsoft Cross Certificate '%s' was found\n", CROSSCERTPATH);

    }
    else
    {
        wprintf(L"Error: Microsoft Cross Certificate '%s' was not found\n", CROSSCERTPATH);
        return 3;
    }
    // Initialize the parameters for SignerSignEx2
    DWORD signerIndex = 0;

    SIGNER_FILE_INFO fileInfo = {};
    fileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
    fileInfo.pwszFileName = packageFilePath;

    SIGNER_SUBJECT_INFO subjectInfo = {};
    subjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
    subjectInfo.pdwIndex = &signerIndex;
    subjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE;
    subjectInfo.pSignerFileInfo = &fileInfo;

    SIGNER_CERT_STORE_INFO certStoreInfo = {};
    certStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
    certStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_STORE;// SIGNER_CERT_POLICY_CHAIN_NO_ROOT;
    certStoreInfo.pSigningCert = signingCertContext;

    // Issuer: 'CertAuthority RSA Certification Authority'
    // Subject 'CertAuthority RSA Extended Validation Code Signing CA'
    auto fileCertAuthorityRsaEVCA = CertAuthority_RSA;
    std::shared_ptr<const CERT_CONTEXT> certCertAuthorityRsaEVCA;
    auto tuple_result = GetCertificateFromFile(fileCertAuthorityRsaEVCA, &certCertAuthorityRsaEVCA);

    if (std::get<0>(tuple_result) != 0)
    {
        std::cout << "Error: " << std::get<0>(tuple_result) << " " << std::get<1>(tuple_result) << " " << std::get<2>(tuple_result) << "\n";
        return std::get<0>(tuple_result);
    }

    std::shared_ptr<const CERT_CONTEXT> certCertEV;
    std::vector<unsigned char> dataCertEV(signingCertContext->pbCertEncoded,
        signingCertContext->pbCertEncoded + signingCertContext->cbCertEncoded);
    tuple_result = GetCertificateFromMemory(dataCertEV, &certCertEV);

    if (std::get<0>(tuple_result) != 0)
    {
        std::cout << "Error: " << std::get<0>(tuple_result) << " " << std::get<1>(tuple_result) << " " << std::get<2>(tuple_result) << "\n";
        return std::get<0>(tuple_result);
    }

    // Issuer:  'Microsoft Code Verification Root'
    // Subject: 'CertAuthority RSA Certification Authority'
    auto fileCertCross = CertAuthority_ROOT;
    std::shared_ptr<const CERT_CONTEXT> certCertCross;
    tuple_result = GetCertificateFromFile(fileCertCross, &certCertCross);

    if (std::get<0>(tuple_result) != 0)
    {
        std::cout << "Error: " << std::get<0>(tuple_result) << " " << std::get<1>(tuple_result) << " " << std::get<2>(tuple_result) << "\n";
        return std::get<0>(tuple_result);
    }

    //certificate 1 Issuer  : '<Certificate Provider> RSA Certification Authority'
    //              Subject : '<Certificate Provider> Extended Validation Code Signing CA'
    //
    //certificate 2 Issuer  : '<Certificate Provider> Extended Validation Code Signing CA'
    //              Subject : '<Your company / entity name>'
    //
    //certificate 3 Issuer  : 'Microsoft Code Verification Root'
    //              Subject : '<Certificate Provider> Certification Authority'

    std::vector<std::shared_ptr<const CERT_CONTEXT> > certs;
    certs.push_back(certCertAuthorityRsaEVCA);
    certs.push_back(certCertEV);
    certs.push_back(certCertCross);

    std::shared_ptr<void> resultStore;
    tuple_result = FormMemoryCertStore(certs, CERT_STORE_ADD_NEW, &resultStore);

    if (std::get<0>(tuple_result) != 0)
    {
        std::cout << "Error: " << std::get<0>(tuple_result) << " " << std::get<1>(tuple_result) << " " << std::get<2>(tuple_result) << "\n";
        return std::get<0>(tuple_result);
    }

    certStoreInfo.hCertStore = resultStore.get();
    //--------------------------------------------------------------------

    SIGNER_CERT cert = {};
    cert.cbSize = sizeof(SIGNER_CERT);
    cert.dwCertChoice = SIGNER_CERT_STORE;
    cert.pCertStoreInfo = &certStoreInfo;

    // The algidHash of the signature to be created must match the
    // hash algorithm used to create the app package
    SIGNER_SIGNATURE_INFO signatureInfo = {};
    signatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
    signatureInfo.algidHash = CALG_SHA_256;
    signatureInfo.dwAttrChoice = SIGNER_NO_ATTR;

    SIGNER_SIGN_EX2_PARAMS signerParams = {};
    signerParams.pSubjectInfo = &subjectInfo;
    signerParams.pSigningCert = &cert;
    signerParams.pSignatureInfo = &signatureInfo;
    signerParams.dwTimestampFlags = SIGNER_TIMESTAMP_RFC3161;
    signerParams.pszAlgorithmOid = szOID_NIST_sha256;
    //signerParams.dwTimestampFlags = SIGNER_TIMESTAMP_AUTHENTICODE;
    //signerParams.pszAlgorithmOid = NULL;
    signerParams.pwszTimestampURL = TIMESTAMPURL;

    APPX_SIP_CLIENT_DATA sipClientData = {};
    sipClientData.pSignerParams = &signerParams;
    signerParams.pSipData = &sipClientData;

    // Type definition for invoking SignerSignEx2 via GetProcAddress
    typedef HRESULT(WINAPI *SignerSignEx2Function)(
        DWORD,
        PSIGNER_SUBJECT_INFO,
        PSIGNER_CERT,
        PSIGNER_SIGNATURE_INFO,
        PSIGNER_PROVIDER_INFO,
        DWORD,
        PCSTR,
        PCWSTR,
        PCRYPT_ATTRIBUTES,
        PVOID,
        PSIGNER_CONTEXT *,
        PVOID,
        PVOID);

    // Load the SignerSignEx2 function from MSSign32.dll
    HMODULE msSignModule = LoadLibraryEx(
        L"MSSign32.dll",
        NULL,
        LOAD_LIBRARY_SEARCH_SYSTEM32);

    if (msSignModule)
    {
        SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
            GetProcAddress(msSignModule, "SignerSignEx2"));
        if (SignerSignEx2)
        {
            hr = SignerSignEx2(
                signerParams.dwFlags,
                signerParams.pSubjectInfo,
                signerParams.pSigningCert,
                signerParams.pSignatureInfo,
                signerParams.pProviderInfo,
                signerParams.dwTimestampFlags,
                signerParams.pszAlgorithmOid,
                signerParams.pwszTimestampURL,
                signerParams.pCryptAttrs,
                signerParams.pSipData,
                signerParams.pSignerContext,
                signerParams.pCryptoPolicy,
                signerParams.pReserved);
        }
        else
        {
            DWORD lastError = GetLastError();
            hr = HRESULT_FROM_WIN32(lastError);
        }

        FreeLibrary(msSignModule);
    }
    else
    {
        DWORD lastError = GetLastError();
        hr = HRESULT_FROM_WIN32(lastError);
    }

    // Free any state used during app package signing
    if (sipClientData.pAppxSipState)
    {
        sipClientData.pAppxSipState->Release();
    }

    return hr;
}

देखिये यह लेख मैंने लिखा है


1

मैं एक गोलाकार प्रमाण पत्र का उपयोग कर रहा हूं और उन्होंने अच्छी तरह से एक ही बात कही।

मानक ईवी कोड पर हस्ताक्षर के साथ हस्ताक्षर करना संभव नहीं है, वे एचएसएम प्लेटफॉर्म के उपयोग को बढ़ावा दे रहे हैं

... जो मेरे बजट से बहुत परे है। उन्होंने जो कहा उसके विपरीत, मैं इसे काम करने में सफल रहा:

"C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /fd sha256 /f "MyCertificate.cer" /csp "eToken Base Cryptographic Provider" /kc "[{{TokenPassword}}]=ContainerTame" "FileToSign"

=> यह कमांड निम्न त्रुटि देता है:

Error information: "CryptExportPublicKeyInfoEx failed" (87/0x57)

मैं वास्तव में इस मुद्दे को नहीं समझता। लेकिन अगर आप दूसरी बार निम्न कमांड चलाते हैं तो यह काम करता है

"C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\SignTool.exe" sign /tr http://timestamp.globalsign.com/scripts/timestamp.dll "MyFileToSign" 
Done Adding Additional Store
Successfully signed: MyFileToSign

यह टीमसिटी बिल्ड के भीतर काम करता है, और टीमसिटी बिल्ड एजेंट में सक्रिय अकाउंट लॉग की कोई आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.