How can I add a private key to a certificate in the windows trust store in c++? - certificate

I have a file with a certificate in it, and I have a file with a private key file in it.
if I run this command
certutil –MergePFX certfile.cer certfile.pfx
I get a pfx file that if I run with explorer, it runs the windows certificate import wizard. If I run through the wizard, I end up with the cert with the key in the windows trust store. Exactly what I need.
I'm trying to do this programatically.
The problem seems to be in the CertAddCertificateContextToStore function.
In the remarks it says:
The certificate context is not duplicated using CertDuplicateCertificateContext. Instead, the function creates a new copy of the context and adds it to the store. In addition to the encoded certificate, CertDuplicateCertificateContext also copies the context's properties, with the exception of the CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID properties.
So certduplicatecertificatecontext very specifically will not copy the private key, and it seems that CertAddCertificateContextToStore doesn't either.
I have a HCRYPTPROV struct with my private key and I use CERT_KEY_CONTEXT_PROP_ID and CERT_KEY_PROV_HANDLE_PROP_ID (I tried them both) to CertSetCertificateContextProperty my certificate context, and then I store it in the windows trust store with CertAddCertificateContextToStore. And no matter what I try, the certificate goes in without the private key.
I'm verifying this with the certmgr tool that shows if a private key is attached, and I can also see it not work when I use that client certificate in a curl request I'm making.
Another thing I tried was this:
The last parameter to CertAddCertificateContextToStore is the handle to the copy of the context that is made. I figure the original context is the one I created where I read the certificate in from disk. This new certificate is the one tied to the actual on-disk store that certmgr reads.
So after I call CertAddCertificateContextToStore, I take the new cert and I add the private key, again via CertSetCertificateContextProperty, and then for good measure, I call CertControlStore to push the in-memory version of the context to disk. Still no effect. Every function call succeeds, but the private key never makes it to the windows trust store.
So in short, my question is what is the windows certificate import tool doing that I am not that will allow me to store a private key along with the certificate in the windows trust store?
I've found a handful of other questions and program examples and message boards dating back to 2002 and none are very explicit, and none of the code examples do exactly what I need, but I know I have all the pieces, they just don't yield the result.

I strongly believe that you set incorrect properties. You should set only CERT_KEY_PROV_INFO_PROP_ID context property in the CertSetCertificateContextProperty call to associate certificate with private key.
If you have a HCRYPTPROV handle, then you have all necessary information to construct CRYPT_KEY_PROV_INFO structure.

Related

Smart Card Retrieve public key from CA certificate

I'm trying to read out a tachograph company smart card. I can read all data just fine except the identification part. Which is the part I actually need. When I select that DF the security environment is reset and I have to re-authenticate. This process is described in sub appendix-11 of ECE/TRANS/SC.1/2006/2/Add.1. Although this document is a bit hard to understand for me.
In this picture you see the data structure of a tachograph company card. The "AUT" behind the ID part tells you that you need to authenticate.
After asking another question on SO and doing a lot of research on how public/private keys are used I think I have some basic understanding on how I should do the authentication. In the documentation, there is also a pretty detailed flow chart on how to get the authentication done. It's to big unfortunately to place here. But I have a question about this part:
Now, I'm counting from the top, downwards. So the first top left square is step one, the last bottom left is step 7. The middle section arrows are APDU commands that need to be send to the card, and the right section is the smart card. PK means public key. CA means certificate authority.
If you do not know the public keys, you see you need to get both the card and the CA certificate. I've done that and I can read them from the card. The part I don't understand are step 6 and 7. You see I need to verify the Card CA.C (which is some part of the certificate) with the European Public key. Where do I get the European public key and what algorithm is used to decrypt it?
EDIT:
Is this the Verification process? And if so, it says to open the sign with the CA public key, How do I get this?
EDIT 2:
I've found the European public key from this link. The CAR part of the CA certificate on the card matches the first 8 bytes from the public key. Meaning it is the correct public key. Now If I understand correctly, I need to Open the sign following step three from CSM_019 from the picture above. To open the sign, I need the correct algorithm using the public key I quess? Does anyone know what algorithm is used?
Step 6: Nothing to decrypt here: You verify the signature, also part of the certificate (Card.CA.C), and if it is correct the contained key (public key of card CA) may be extracted and used for the next step.
Step 7: You verify the signature of card certificate (made with the card.ca key just retrieved) and if it is correct you now have the public key of the card (with the certainty, that it is correct, otherwise signature would have mismatched).
The scheme uses this two-step approach, so that only the Eur.PK public key is needed instead of the keys of all card CAs.

Signature verification using only a hashed/encoded message

Is there any way to verify the OpenSSL signature using only {signature,hashed message} pair, skipping the original file to be presented for verification?
I need to verify the signature with only {signature,hashed message} pair remotely so using the original file is cumbersome specially when its very large.
Is there any way to verify the OpenSSL signature using only hash value and without needing the original file?
Yes, but there are strings attached.
The scheme which requires the original message to be presented to the verifying function is a Signature Scheme with Appendix (SSA). A scheme like the old PKCS #1.0 signing is an example of it.
The scheme which does not require the original message is a Signature Scheme with Recovery (PSSR). In a PSSR, the encoded message is part of the signature and masked. A scheme like the new PKCS #2.0 PSSR signing is an example of it.
There are no schemes that take just a hash, as far as I know. You have to have the {message,signature} pair. Allowing the message to be disgorged from the signing or verification can be a security violation.
OpenSSL provides both of them, as does most other security libraries, like Botan, Crypto++, NSS, etc.
Also see RSA signature on TLS on Information Security Stack Exchange.
I have been trying to verify the signature with hash value remotely so using the original file is cumbersome specially when its very large.
That's the insecure thing signature schemes want to avoid....

How do I verify a root DNS trust anchor?

I am trying to verify root Key Signing Key (KSK) against the trust anchor (Kjqmt7v.crt) downloaded from here. I am getting root KSK using the Net::DNS module.
I am very confused at present on how to verify that both are the same. I tried to convert the .crt file to a Keyset object, but it is resulting in an error.
This is my code.
#!/usr/bin/perl
use strict;
use warnings;
use Net::DNS::Keyset;
my $keyset = Net::DNS::Keyset->new('Kjqmt7v.crt');
$keyset->print;
This is the error
We expected a match RDATA
0��0���0 *�H�� 0K10 U
this Should not happen
at a.pl line 5
I am very confused and therefore unable to provide any proper code, as I have no idea how to start. Pointing me in the right direction would be very helpful.
I want a way to verify trust anchor against the KSK that I am getting from root DNS servers. If there is any other way to do that please update me.
You seem to have misunderstood what's in the files IANA provides. None of them except the public root key itself is actually DNSSEC data. The Kjqmt7v.crt file, for example, is an X.509 certificate in DER format (so it's no wonder that Net::DNS::Keyset chokes on it). If you look at it (with the openssl x509 command, for example), you can see that included in its DN field is the textual representation of a DS record for the root KSK. So if you verify that certificate, you know that DS is genuine, and you can use that to verify the DNSKEY.
Another alternative available at the same URL, which is probably easier to use for most people, is a DS for the KSK in XML format, with a detached PGP signature. Verify the signature, use the data in the XML file to build a proper DS record in your favorite programming language, and then you can use that to verify the KSK DNSKEY record.

IIS FTP passwords encryption schema

This is one of my first approaches to "crypto in practice". I have found myself a new aim when I stumbled upon my password (AES encrypted) on my FTP server. Since I am eager to get to know new stuff, I decided I'll give it a go and try to 'recover' my password from AES cipher. If I can make it to decipher it 'on the paper' I think I will have a good enough understanding on how it works and how to call it.
As MSDN points out:
The AesProvider provider is an AES provider that uses a session key encrypted using an RSA key container that has permissions for the IIS_IUSRS group, therefore allowing IIS worker processes to encrypt and decrypt configuration encrypted with this provider.
So, the available data:
Session key (RSA encrypted) from <configProtectedData>
AES cipher from the same file (enc:AesProvider:89v45avZx.....)
Machine RSA key (obtained using aspnet_regiis -px "SampleKeys"
keys.xml -pri) (since useMachineContainer flag is true).
If I understand correctly:
In order to decrypt the password:
I need to decrypt the RSA-Encrypted session key with Machine RSA key.
Once I have the decrypted session key I use it as AES key to decrypt the password. Am I mistaken in this thinking?
If the above is correct, I will now describe my attempts:
Using Powershell (my preferable environment):
[xml]$IISXML = [xml](cat .\IISConfigKey.xml)
[System.Xml.XmlElement]$IISElement = $IISXML.RSAKeyValue
$RSA = New-Object System.Security.Cryptography.Xml.RSAKeyValue
$RSA.LoadXml($IISElement)
## Now I have RSA-key loaded as an object from exported XML
$AESSessionKey = "LIAAAZ..1aVods=" // Total length 188
## I am importing the session key from the file
$AESProviderSessionKeyBytes = (Convert-FromBase64 $AESProviderSessionKey).ToCharArray() | % { [byte]$_ }
## 'Convert-FromBase64' is my custom function, which basically converts from Base64 to String
And this seems to be the first culprit I can't get around. Casting $RSA.Key.Decrypt($AESProviderSessionKeyBytes, $true) returns an error that the data exceeded 128 bytes. Which happened in fact, as the SessionKeyBytes is of 140-length.
As the method I am calling happily throws exceptions at me, I have no idea what to try next. The sessionKey seems too long to be RSA-encrypted? Or maybe I should divide it? Or maybe I am just mistaken in principle that it is RSA encrypted.. I tried couple of versions, but none of them progressed me any closer.
Hope you can point me in the right direction!

why do we need the pfx (key exchange) file?

If we make the private key exportable (using -pe option in makecert), then in theory we have both an exportable private key and the public key (public key in certificate) -- which can be transferred or imported to another machine.
So, my question is, why do we still need to create the .pfx file (key exchange file, which contains private and public keys) -- making the private key exportable in certificate could do anything we want? Any scenarios pfx file could cover which making private key exportable in certificate could not achieve?
thanks in advance,
George
Is there a makecert command line you have found that will generate a certificate file that includes a private key? I never have. I have seen someone allude to the fact that there is a version of makecert that can produce .pfx files but also have never seen that.
That means at the very best you can create TWO files with makecert if you want a private key file. One for the certificate and one for the private key. You can copy both those files to another computer and import them using makecert.
The advantage of the .pfx certificate format is that you can combine the two files with the certificate and private key into one. This is more convenient and also means you can use the file with the .Net X509Certificate2 class for use with an SslStream.
Your pfx file can be password protected, that would add a layer of protection
The problem is, the X509 Certificate standard (the certificate) does not include the private key. The certificate contains the subject public key info (aka, the public key) and information about the holder of the private key, but the standard does not support including the private key. This is the basic idea of PKI - the certificate is the public info you share with the world, the private key is something you hold very securely.
Making a private key exportable in any mechanism (for example, makecert), means you are telling that product that the key can be exported. It doesn't specify the file format that you would use to store it. A pfx file is one way of storing the private key - it uses the PKCS 12 standard. Java Key Stores (*.jks) are another way to do the same thing. Most commerically supported standards have similar common features - they protect the private key by encrypting it. The encryption can be unlocked using a password. They couple the private key with the certificate that decribes it.
If you want to build a PFX file, you should have both x509 cert public key and private key file which you can generate using makecert command. PFX can be generated using PVk2PFX command which you can find Microsoft SDK installation directiory.