{"id":1630,"date":"2016-03-26T17:17:21","date_gmt":"2016-03-26T15:17:21","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=1630"},"modified":"2016-03-26T00:28:59","modified_gmt":"2016-03-25T22:28:59","slug":"signing-with-cryptoapi-using-certificate-and-detached-private-key","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/1630","title":{"rendered":"Signing with CryptoAPI using Certificate and Detached Private Key"},"content":{"rendered":"<p>Use of separated certificate and private key might be confusing without understanding how parts or CryptoAPI are related one to another. Apparently, <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa380281\"><code>CryptSignMessage<\/code><\/a> and friends require private key in order to create a digital signature.<\/p>\n<p>It is not a problem when private key resides right in the signing certificate (such as, for example, imported with <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa387314\"><code>PFXImportCertStore<\/code><\/a>):<\/p>\n<pre><code>CRYPT_SIGN_MESSAGE_PARA Parameters;\r\nZeroMemory(&amp;Parameters, sizeof Parameters);\r\nParameters.cbSize = sizeof Parameters;\r\nParameters.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;\r\nParameters.pSigningCert = CertificateContext; \/\/ &lt;&lt;--- Certificate with Private Key\r\n\/\/ ...\r\n<\/code><\/pre>\n<p>Things get more complicated when the certificate does not contain the private key. API&#8217;s error is <code>CRYPT_E_NO_KEY_PROPERTY<\/code> which is described as follows:<\/p>\n<blockquote><p>&#8220;The <code>pSigningCert<\/code> in <code>*pSignPara<\/code> does not have a <code>CERT_KEY_PROV_INFO_PROP_ID<\/code> or <code>CERT_KEY_CONTEXT_PROP_ID<\/code> property.&#8221;<\/p><\/blockquote>\n<p><code>CERT_KEY_PROV_INFO_PROP_ID<\/code> is a property to be defined with certificate context and it expects a structure of type <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa381420\"><code>CRYPT_KEY_PROV_INFO<\/code><\/a>. The other one, <code>CERT_KEY_CONTEXT_PROP_ID<\/code> takes a <code>CERT_KEY_CONTEXT<\/code> structure.<\/p>\n<p>Even though described as &#8220;The <code>CRYPT_KEY_PROV_INFO<\/code> structure contains information about a key container within a cryptographic service provider (CSP).&#8221; and &#8220;The <code>CERT_KEY_CONTEXT<\/code> structure contains data associated with a <code>CERT_KEY_CONTEXT_PROP_ID<\/code> property.&#8221; respectively, it is not well clear to see where the key is attached exactly.<\/p>\n<p>The missing part is that the private key is not something to be provided explicitly. Instead, the key is to be pre-loaded into provider and then this provider is associated with <code>CERT_KEY_CONTEXT<\/code> structure, which goes as a property value, which in turn is added to signing certificate context, whcih finally gets used for creating a digital signature.<\/p>\n<pre><code>__E(CryptStringToBinary(sPrivateKeyBlob, (DWORD) wcslen(sPrivateKeyBlob), CRYPT_STRING_BASE64_ANY, pnData, &amp;nDataSize, NULL, NULL));\r\n\/\/ ...\r\nCCryptProvider Provider;\r\n__E(Provider.AcquireContext(NULL, NULL, PROV_RSA_FULL, 0));\r\nCCryptKey Key;\r\nKey.Attach(Provider.ImportKey(pnData, nDataSize));\r\n__E(Key);\r\n\/\/ ...\r\nCERT_KEY_CONTEXT KeyContext;\r\nZeroMemory(&amp;KeyContext, sizeof KeyContext);\r\nKeyContext.cbSize = sizeof KeyContext;\r\nKeyContext.hCryptProv = Provider; \/\/ &lt;&lt;--- Here we go, ooh\r\nKeyContext.dwKeySpec = AT_SIGNATURE;\r\nCertificateContext.SetProperty(CERT_KEY_CONTEXT_PROP_ID, &amp;KeyContext);\r\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Use of separated certificate and private key might be confusing without understanding how parts or CryptoAPI are related one to another. Apparently, CryptSignMessage and friends require private key in order to create a digital signature. It is not a problem when private key resides right in the signing certificate (such as, for example, imported with&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/1630\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[513,509,514,70],"class_list":["post-1630","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-cryptoapi","tag-pkcs","tag-signature","tag-winapi"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1630","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=1630"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/1630\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=1630"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=1630"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=1630"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}