Why does signing or decryption operation fail when my code is run in Windows service?
If you use certificates using Windows CryptoAPI interface (TElWinCertStorage class), you can face the problem when your code works fine in the regular application but fails with error when run within the system service or in IIS (Internet Information Server).
The common reason is that the service has no access to the certificate.
Certificates are stored in Windows CryptoAPI in several apartments, the most known of which are HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE keys in Windows registry. As the name suggests, HKEY_CURRENT_USER stores are accessible only to certain user account, and HKEY_LOCAL_MACHINE stores are available all across the system.
By default when you import the certificate to the system it's stored in HKEY_CURRENT_USER store. Such certificate won't be accessible from the service.
The solutions are
1) import the certificate to HKEY_LOCAL_MACHINE store using MMC's "Certificates" applet,
2) make your code impersonate as other user for the purpose of signing, or
3) run the service under the user account of the certain user, and import the certificate to that user's certificate store.
We mention option 2 here for a reason. A fair number of drivers of cryptographic devices (smartcards and USB cryptotokens) map the certificates stored on the device into Windows CryptoAPI stores of the currently logged in user, and this behavior sometimes can not be changed. This means that your code, being executed under some service account, won't ever get access to the device certificates via CryptoAPI, unless it can impersonate itself as a local interactive user with access to the certificates of the hardware device.
The alternative to the latter problem is to access device certificates not via CryptoAPI but via PKCS#11 interface, which is also supported by SecureBlackbox.