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

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.

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.

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 to validate an RSA cert in perl

How do you validate an cert given a root cert that signed it? I've got this far:
$root_x509 = Crypt::OpenSSL::X509->new_from_string($root_key_data, FORMAT_ASN1);
$root_key = Crypt::OpenSSL::RSA->new_public_key($x509->pubkey());
$other_x509 = Crypt::OpenSSL::X509->new_from_string($other_key_data, FORMAT_ASN1);
$other_key = Crypt::OpenSSL::RSA->new_public_key($x509->pubkey());
Ok, then what? I'm not seeing an obvious $root_key->verify_certificate($other_x509); Is Crypt::OpenSSL::VerifyX509 the only/best answer? That module is being problematic to compile and install, but I'll continue in that vein if it's the way to go. But I feel like I'm missing something.
It looks like python, for example, has an obvious API an equivalent to which I'm not seeing in any of the OpenSSL perl libraries:
trusted_store = X509Store()
trusted_store.add_cert(trusted_root)
try:
X509StoreContext(trusted_store, itunes_cert).verify_certificate()
except X509StoreContextError as e:
print("iTunes certificate invalid")
After extensive research, the closest thing to a complete solution besides Crypt::OpenSSL::VerifyX509 (see above) is Net::SSLeay, which has a whole bunch of low-level bindings to openssl. They recently added these:
1.83 2018-01-06
X509_STORE_CTX_new and X509_verify_cert
but the documentation is sparse, and I wasn't able to get past related segfaults.
Instead I validated the cert chain by hand:
use Convert::ASN1 to re-encode the tbsCertificate data I had decoded
in my PKCS#7 file ("tbs" is "to-be-signed")
get the signature from the PCKS#7 data
get the subjectPublicKeyInfo.subjectPublic Key from the cert that signed this cert
feed that to $signer_key = Crypt::OpenSSL::RSA->new_public_key($signer_key_pem);
and then do $signer_key->verify($cert_as_signed, $signature)
and repeat for each cert in the chain.
Checking validity dates and extension capabilities on each cert is part of all that.

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

Missing Client-CertificateĀ“s PrivateKey

can someone tell me please why i dont have the cert.PrivateKey (=null) after i instantiated an X509Certificate2 from an HttpClientCertificate during a web method call.. sth like this:
X509Certificate2 cert = new X509Certificate2(Context.Request.ClientCertificate.Certificate, "test");
The HttpClientCertificate has an private key when i check with the debugger, but X509Certificate2 (cert variable) not !
..furthermore i dont even get an CryptographicException when i specify an invalid password.
Can someone please clearify me?
Thanks really a lot in advance!
Kind regards,
Kris
The constructor you are using (data/password) is intended to be used to get a certificate from a PKCS#12 file (PFX file). The Certificate property of ClientCertificate "Gets a string containing the binary stream of the entire certificate content, in ASN.1 format."
ClientCertificate is intended to give you the certificate used during the establishment of the SSL session with the server. I wouln't expect it to expose the private key in the way you are trying to.