1
$\begingroup$

The main confusion I have is around the different PKCS and relation with SSL (TLS). I have done a lot of research and have found bits and pieces but not necessarily how these relate, so let me explain but first with a little background.

To start, I am fairly comfortable with how SSL (and subsequently TLS) works, and subsequently mutual TLS. Typically X.509 certs with CA signed for mutual authentication, and sometimes using self signed certs. Also with how the symmetric key is used for the content encryption and the asymmetric key is used for encrypting the symmetric key.

I am also fairly comfortable with PGP, encrypting, signing, different algorithms, features like built in zip compression, etc. Particular interest in RSA encryption and signature algorithms, but more on that later. So, so far we have SSL which security can be enhanced if you encrypt a payload before using the transport level encryption, especially if you're sending data somewhere where you don't want any data to be unencrypted at rest.

Now on to PKCS where it starts to get a little hazy. I know that PKCS are just standards.

PKCS#12 - These are your .pfx or .p12 files, which can be used to store your X.509 certs with the corresponding private key (very simplistic definition). My guess, and please correct me if I'm wrong, is that these are typically created be a server which wants to setup HTTPS. Can use different algorithms, like RSA which is also mentioned in PGP.

PKCS#7 - Subsequently CMS, typically used for generating and verifying digital signatures. Here is where I'm finding some conflicting information. I understand digital signatures, calculate the hash encrypt with the private key so you can verify, with the public key, that the message was not tampered with and that it came from the correct sender. Before I get to the main question relating to auth, I see that PKCS#7 can use AES, which is a symmetric key algorithm. Does this make sense, and if so is this common or how would that work?

Now main questions sorry if that was long winded.

  1. I was told to download a PFX file in order to authenticate with an API, similar to this question. Question on this, and related to my next question on PKCS7, is how does that authentication work? I'm getting the private key and cert in the form of a .pfx file from the server, does that mean that the server is just self signing this and this is essentially mutual TLS using a self signed cert? If not, we then just be using TLS (so encrypted with the servers public key) with the message content being our payload signed with our private key?
  2. Similar for PKCS7. I completely understand how we verify the signature with the public key. How how do we handle the authentication if we are sending data across to some API (typically speaking)? Because technically once we have something that we have a digital signature, really anyone anywhere can send this, so how would we know it is being sent by a particular client or do we not care?

Sorry for the long post and hopefully you can clear some of this up for me.

$\endgroup$
1
$\begingroup$

PKCS#7 - Subsequently CMS, typically used for generating and verifying digital signatures.

I wouldn't go for 'typically' there. There are three main uses of PKCS7/CMS today:

  • signature on various kinds of data ranging from Java or Windows code to PDF documents
  • signature on and/or encryption of mail messages or attachments in S/MIME
  • as a container for certs and/or CRLs, as described in the Q you linked for PKCS12 (and others too)

I don't have numbers and I'll accept the first might be more common, but the others exist.

I understand digital signatures, calculate the hash [and] encrypt with the private key so you can verify, with the public key, that the message was not tampered with and that it came from the correct sender.

No. This is a commonly repeated mistake, but signatures are not 'encrypting with the private key' or 'encrypting backwards'. For RSA only, not other algorithms, there is a mathematical similarity which 30-ish years ago led people to use this description, but the actual signature and encryption schemes are vitally different, and more importantly differ semantically, so informed people no longer say this. See my growing list of Qs or As on this at https://security.stackexchange.com/questions/159282/can-openssl-decrypt-the-encrypted-signature-in-an-amazon-alexa-request-#159289 . As relevant here, compare any CMS even the earliest in 1999 which says SignerInfo.signature "is the result of digital signature generation, using the message digest and the signer's private key" and defines signature generation and verification to use private key and public key respectively but otherwise leaves them to other standards, versus actual PKCS7v1.5 which was redistributed by IETF in 1998 but actually published by then-RSALabs in 1993, which says SignerInfo.encryptedDigest "is the result of encrypting the message digest and associated information with the signer's private key" and in 9.4 essentially copies part of the then-current version of PKCS1.

It is true that digital signature allows the verifier to be certain that the data is untampered and is 'from' (or at least was seen/approved by) the party holding the private key, which should be unique (more below), and can (at least try to) verify that the signer is the 'correct' sender according to whatever criteria are relevant to that correctness.

I see that PKCS#7 can use AES, which is a symmetric key algorithm. Does this make sense, and if so is this common or how would that work?

Only for 'enveloped' (that is, encrypted) messages, not for signed messages or detached signatures; as I said above I don't have numbers on usage.

I was told to download a PFX file in order to authenticate with an API, similar to (link) ... how does that authentication work? I'm getting the private key and cert in the form of a .pfx file from the server, does that mean that the server is just self signing this and this is essentially mutual TLS using a self signed cert? If not, we then just be using TLS (so encrypted with the servers public key) with the message content being our payload signed with our private key?

This is very likely TLS with client authentication also called mutual authenication or just mutual TLS, yes. The certificate must be one that is trusted by the server(s) you connect to; this can be self-signed by the server, it can be signed by the server acting as a CA, or it can be obtained from some other CA which signs it. It doesn't matter to you as long as the result is trusted, although if you are curious you could look at the certs with any of the many tools that can look at a PKCS12/PFX, or a cert or several certs extracted from one.

TLS never encrypts data with the server's public key. TLS encrypts, and authenticates, data in both directions using symmetric algorithms with per session (and connection) 'working' keys which are created by 'key exchange' process during the initial handshake. See e.g. https://security.stackexchange.com/questions/20803/how-does-ssl-work/ for an extensive but slightly out of date explanation -- it hasn't been updated (yet?) for TLS 1.3 which was released in 2018 and is now becoming more and more common. The oldest and now mostly obsolete key exchange, called 'static' or 'plain' RSA, does encrypt the premaster secret using the server public key, but newer key exchanges (especially in 1.3) use Diffie-Hellman signed by the server private key and verified by the client with the server public key (from its certificate, after validation). Conversely, client auth in TLS always signs handshake data with the client private key and it is verified by the server using the client public key (ditto).

Similar for PKCS7. I completely understand how we verify the signature with the public key. How how do we handle the authentication if we are sending data across to some API (typically speaking)? Because technically once we have something that we have a digital signature, really anyone anywhere can send this, so how would we know it is being sent by a particular client or do we not care?

Creating a digital signature that will verify successfully requires using the private key, and the whole concept of public-key cryptography is that only the 'owner' has the private key; everybody else should have only the public key. Thus if a particular key belongs to client X, only client X can create signatures with that key. However in your example, where the server is apparently passing out PKCS12's containing private keys willy-nilly, which is not considered good practice, this guarantee is greatly weakened: it is definitely possible for that server and anyone else who gets a copy of 'your' PKCS12 to forge data (in this case connections) from 'you'. Although if your connections are to this same server, its ability to forge a connection doesn't matter too much, because it could just as easily lie about what it received on a legitimate connection.

$\endgroup$
3
  • $\begingroup$ First off, thanks for the great information and I'll now be a proponent of clarifying that signatures != encrypting with private key. Once I get more reputation I will upvote your answer. To add, the 2 use cases are different API's and different companies. The PFX one you pretty much cleared up. For PKCS#7, I think the use case is they are providing a PKCS#7 certificate list to establish trust with their server (so it's being used as a container for certs which you pointed out in the 3rd use case for PKCS#7). $\endgroup$
    – Joe
    Jan 28 at 3:46
  • $\begingroup$ Just for a little added clarification (different scenario than previous comment). If someone is saying they're using PKCS#7 for signature and encryption, the client will use PKCS#7 to do the signature and encryption and then send to the server. The server's endpoint, in a sense, is a public API in that it doesn't care where the call comes from (could be Postman or a random server I set up), there is no session level mutual authentication. Any request coming into that API they will verify the signature with their public keys and thus that is the authentication. Is that understanding correct? $\endgroup$
    – Joe
    Jan 28 at 5:37
  • $\begingroup$ (@Joe) sounds plausible but only 'someone' actually knows $\endgroup$ Jan 29 at 6:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.