Smart Card Retrieve public key from CA certificate - 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.

Related

RSA private key included in JWT token

Could someone kindly explain why the private key is included (by default) in the JWT-Token generated by "all" the cpp-based JWT libraries found on github & how to remove it?
The only thing that comes close is the signature of the JWT (the last part in blue at the example in https://jwt.io/).
You need the private key to calculate the signature, but it is definitely not included in the JWT!

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

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.

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....

SecKeyRef from X.509 ASN.1 RSA Public Key in iOS

I realize that there are a lot of similar questions to the one I am about to ask already on Stack Overflow, but none of them have clear answers that really satisfy my needs, so here we go:
My program receives an ASN.1 encoded RSA public key over the network. I have the data stored in a simple NSData instance. I wish to use that public key to encode 16 bytes of data and return those over the network. From my research the best way to do this seems to be to use a SecKeyRef. According to the ridiculously vague documentation provided by Apple this can be done using some code. However, their code presents a problem. Every time I want to use a public key I need to add it to the keychain and give it a unique identifier. The problem with this is that this key is to be used only once. I am looking for a way to obtain a SecKeyRef for a key that is not in the keychain and is created from an ASN.1 encoded key.
I have also considered the possibility of converting it to common PEM by base64-encoding and wrapping it in '-----BEGIN PUBLIC KEY-----' and '-----END PUBLIC KEY-----' and then loading it into a SecKeyRef, but I haven't seen a way to do this either.
Also, I don't have much of a choice in the type of key, key format, etc. Its from a 3rd party java server. Yay.
I currently have this alternate method of loading keys that (maybe) doesn't add them to the key chain but the key evidently (by trial and error :D) is not in DER format and therefore I can't load it like this.
SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data); //data contains the public key - received over the network
SecPolicyRef policyRef = SecPolicyCreateBasicX509();
SecTrustRef trustRef;
OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
NSAssert(status == errSecSuccess, #"SecTrustCreateWithCertificates failed.");
SecTrustResultType trustResult;
status = SecTrustEvaluate(trustRef, &trustResult);
NSAssert(status == errSecSuccess, #"SecTrustEvaluate failed.");
SecKeyRef publicKey = SecTrustCopyPublicKey(trustRef); //The Result :)
NSAssert(publicKey != NULL, #"SecTrustCopyPublicKey failed.");
if (certificateRef) CFRelease(certificateRef);
if (policyRef) CFRelease(policyRef);
if (trustRef) CFRelease(trustRef);
PS: Why does apple make this so hard? Statically linking OpenSSL would be easy, but then all sorts of export regulations and other problems apply.
The problem was apparently with the source of the "certificate", which really wasn't much more than the key wrapped in some DER tags.
On the plus side thanks to the black magic in this http://blog.wingsofhermes.org/?p=75 blog post, I have successfully managed to achieve most of my goals.
Success:
Key loaded from data, not a file
Encryption of secret (AES) key successfully read by java server.
Less success:
Had to use a unique identifier, but I reuse it, so no need for a crazy naming scheme.
Key temporarily added to keychain, but I remove it after its one time use, so that works out too.
I am still not too clear on what the array of if statements mixed with loops and tons of magic numbers does exactly, but at least it works and since the key will always come from the same source, it shouldn't break unless they change the java security provider...oh wait thats actually kinda likely...oh well...at least its a little bit specific in the Java 7 standards.
*crosses fingers* *hopes nothing breaks*

SignedCms.CheckSignature() with renewed cert -> new serial?

i am using
SignedCms.CheckSignature(certColl, true)
(with only one cert in certColl) to verify the signature of a pkcs-7 message. My problem is that i dont want to change the (public part of the) signers certificate on my server after the signer has renewed his certificate :-( The public key, issuer and subject are remaining unchanged after signer has renewed his certificate! So this has to work - at least in my opinion, even if i´m not a crypto-geek :-)
..but, unfortunately the .NET-Framework throws a Cryptographic Exception "Cannot find the original signer" like the stacktrace says exactly at:
SignerInfo.CheckSignature(X509Certificate2Collection extraStore, Boolean verifySignatureOnly)
This must be because the serial number of the signers certificate has changed and the SignerIdentifier property is readonly and set to IssuerAndSerialNumber.
Does anyone know how workaround this?
Or do i have to implement a "handmade" signature verifying with sth like: signedMessage.ComputeSignature(signer, false)?
Thanks in advance and happy programming,
Krile
For all interested on this issue:
Someone told me that this is due to the PKCS #7 specification, which states that the SubjectKeyIdentifier is always set to IssuerAndSerialNumber.