X.509 Self Signed Certificates - private-key

I'm trying to understand more about X.509 Digital Certificates. There seems to be lots of contradiction around. I am using Bouncy Castle to generate a key pair, using
public static void SaveToFile(X509Certificate newCert, AsymmetricCipherKeyPair kp, string filePath, string certAlias, string password)
{
var newStore = new Pkcs12Store();
var certEntry = new X509CertificateEntry(newCert);
newStore.SetCertificateEntry(certAlias, certEntry);
newStore.SetKeyEntry(certAlias,
new AsymmetricKeyEntry(kp.Private), new[] { certEntry });
using (var certFile = File.Create(filePath))
newStore.Save(certFile, password.ToCharArray(), new SecureRandom(new CryptoApiRandomGenerator()));
}
This saves the generated certificate to disk. Some articles tell us there is no need to password protect the certificate as there is no PRIVATE KEY stored in there. Then this article says the certificate does indeed contain the PRIVATE KEY.
I guess I have two questions that will hopefully help me understand this:
If I generate my keys in this way, should the password be the SAME as the passphrase for the PRIVATE KEY?
Do I distribute the X.509 certificate to prove the PUBLIC KEY is mine (being paired to my name in the certificate) or should the certificate be kept as safe and secret as the PRIVATE KEY and what use is a self-signed certificate?

A PKCS#12 file can contain both the certificate and the private key. They are, however, stored as separate, distinct objects. The certificate itself has the public key embedded within it. Since the certificate only contains the public key, it is considered "public" as well. You can feel free to distribute the certificate, as it does not contain the private key, which should be kept confidential. This is the basis of the security in asymmetric cryptography.
Because a PKCS#12 file contains both items, it is encrypted with a password to protect the private key within it. That said, you would use the private key to prove that the certificate you distribute belongs to you. For example, through the use of a digital signature on a document.
Hope that helps!

Certificate is actually the block of information which binds your identity (i.e. your name, email, whatever else) to some public key. It is public so everyone can know that this key belongs to you.
So when you will sign something they will know that actually you signed this.
The other thing is validating certificate - that's for what trusted root certificates are used.
Private key is your own secret information, and MUST be kept secret.

Related

Encrypted SAML Assertion

Based on my reading, we use both the certificate and a public key to encrypt the assertion, and to decrypt the assertion, we have to use the private key to decrypt it. I do not want to share my private key with my client, Is there other way to not provide the private key? I want to keep the private key, encrypt my assertion and give the response to my client, the client will use the public key instead to decrypt my message, does this thinking work at all?
Thank you.
The private key is just a very long number and is used to decrypt. The public key is just a very long number and is used to encrypt. Only the corresponding private key can decrypt what a public key encrypts.
A certificate (X509 public certificate) wraps the public key and the private key in identity information. The certificate is digitally signed by a certificate authority to say, to the best of its knowledge that the key belongs to who it says it belongs to.
You give your public key to your client. They verify it's from you by checking the digital signature on its certificate and they encrypt information with your public key.
You then decrypt that information using the corresponding private key which you never ever give to anyone.
It's all about Public Key Infrastructure (PKI).
I want to keep the private key, encrypt my assertion and give the response to my client, the client will use the public key instead to decrypt my message
From the text I assume you're implementing a SAML IdP.
Actually you need the client's SP public key to encrypt the assertion for the SP. And then sign the assertions with your (IdP) private key.
The SP must validate the SAML assertion signature with the IdP's public key and then they may decrypt the assertions with their SP private key.
So indeed the private keys stay with their owners.

Information to be kept for non-repudiation?

I'm using Java applet to sign XML files in a web browser.
what information, in addition to X509 key which is included in signed XML, should I keep to ensure non-repudiation?
I have seen applets transferring private key (encrypted using same private key) or just public key.
In XMLDsig/XAdES signature, the non-repudiation (proof of the integrity and origin of data) is provided by the signature itself.
The integrity is provided because if you change any bytes of the signature you will broke it (the signature can't validate), and the origin of data is provided by the <xmldsig:keyInfo> element which provides you the necessary certificate to validate the signature (however this element it's optional, so if it's not present it's supposed that application context it's enough to get that certificate), if the signature validate with this certificate you've the identity of the signature author. Besides in XAdES standard is defined the <xades:SigningCertificate> attribute which is mandatory and also it references the necessary certificate to validate the signature.
Hope this helps,
You should never transfer a private key except possibly for backup. The safest method of keeping a private key safe is to create a key pair at the location where the private key is required and then transfer the public key using a certificate request.
To verify and validate a certificate, and therefore a signature, you need the following things:
A chain of certificates that starts with the certificate of the key pair used for the signature, up to some trusted certificate. The chain can exist of 1 self signed certificate, but usually it's longer. Usually you trust some root certificate, have 1 or 2 CA certificates, ending with the leaf certificate that performs the signing.
Some method of verifying that any of the certificates in the chain was not revoked. Usually this is a frequently distributed CRL or OCSP.
A clock. Without a trusted clock it is not possibly to verify if the certificate has expire.
These are all required for verification. For signing, you don't have to keep anything. Of course, you normally hold on to your private key and certificate.

Passing signature public key along with the signature

Can anybody explain me a sense of passing a public key along with signature which is practiced in SAML 2.0? As I know signature is needed to make sure the message was not intercepted by someone, so I need to make sure the public key I'm validating the signature with is pertained to the sender, which in case of in SAML 2.0 I can get with metadata beforehand. However if I take a public key from the message in run-time, how can I know it is not intercepted and other interceptor's public key is included?
You not only want to validate that the public key matches the signature, you also want to validate that the public key itself is valid. This is generally done through a certificate chain, where each certificate in the chain is basically a signed public key. You need to ensure that each certificate is valid (has not expired, has not been revoked) and that you trust the signers of each certificate. Be careful who you trust and pay attention to revocation.

Generation of public key

I apologise for mixing notions but my knowledge of assymmetric web service security is shallow.
Right, I've got a java key store containing my private key and a customers public key.
When calling the customers web service I get an error message in return, saying:
"The signature or decryption is invalid".
We have found out that the public key I have in the key store and which is sent upon request, is different from the public key the customer has on its server. Somehow I have given the customer a different public key than the one I have in the key store.
What I would like to do is to regenerate the public key based on my private key in the key store, and send it to Mr Customer again. Is it possible to do so?
To be honest, this is exactly what I did by means of a keytool statement. Result, a file with .cer extension. Is the file with .cer the public key, or what?
Any advice is appreciated.
Solved it:
Above I said I tried to regenerate the public key from the key store, but I wasn't sure this was the right way to do it.
Anyhow, I provided Mr Customer with this newly generated public key and ask them to install it on their server. It worked, we've matching public keys. I used the following keytool command to regenerate the public key:
keytool -export -alias [name of private key in keystore] -file [path
to output] -keystore [path to .jks keystore]
Normally you do have the private key together with a certificate (chain) in the keystore. If you simply retrieve the first certificate from the chain with the same alias as the private key, you should have the correct certificate.
It does not hurt to check this by signing some arbitrary data with the private key and verify it with the public key from the ceritificate of course. Signature.initVerify() should even take a certificate directly. Otherwise, you could compare the (hash over the) modulus of the public and private keys as well.

How to operate with X509 certificates in .NET code

I have some code that needs to work with X509 Certificate information. I have downloaded a sample that does this:
const string CertWithoutPrivateKey = "MII....";
const string CertWithPrivateKey = "MII...";
public static SecurityToken GetSigningToken(bool includePrivateKey)
{
X509Certificate2 cert = null;
if (includePrivateKey)
{
cert = new X509Certificate2(
Convert.FromBase64String(CertWithPrivateKey),
"pw", X509KeyStorageFlags.PersistKeySet);
}
else
{
cert = new X509Certificate2(
Convert.FromBase64String(CertWithoutPrivateKey));
}
return cert;
}
The code needs to be able to get the cert with the private key. The Saml2AuthenticationModule (from the WIF Extension for the SAML 2.0 Protocol) relies on this private key to decrypt information sent from a SAML Identity Provider.
I don't know much about certificates or encryption, but it seems to me that hard-coding the certificate into a class is not secure.
So, how should my code go about retrieving the cert with private key? Afaik, this code is only run one time at app startup (so probably also after an app pool recycle).
I could:
Store the cert as an appSetting in config file. As long as appSettings are config encrypted, is this secure?
Store the cert in a database.
Store the cert as a file in bin/App_Data. Afaik this means it could not be read over the web, but would be in plain view to anyone who can access the host server. Imo if someone can get into my server, letting them read this cert is probably the least of my worries.
Are there any other options? What is most appropriate in this case?
A certificate with or without private key can be save to X509 store of a user or the computer. This already has build-in Windows security that should be sufficient. You can use mmc with Certificates snap-in to add certificates to the store and manage them.
A reference to the certificate, for example, its name or thumbnail, can saved to the config file and used to retrieve the certificate. The retrieval may look like the following:
public static X509Certificate2 GetCertificate(string name)
{
try
{
X509Store store = new X509Store (StoreLocation.LocalMachine);
X509Certificate2Collection collection = store.Certificates;
foreach (X509Certificate2 x509 in collection)
{
if (x509.FriendlyName.Equals(name))
{
return x509;
}
}
}
finally
{
store.Close();
}
return null;
}
Using Find on the collection is another (and cleaner) way to search certificates.
I'm not sure how WIF does it (you could probably use Reflector to see the internals of how it interacts with the certificate store), but it sounds like you are using WIF in an application hosted in IIS. If that's the case, WIF should take care of all the certificate interactions for you. You'll just have to make sure you have the following things set up:
The identity model configuration section set up with references to the thumbprint of the certificate you are using to either encrypt or verify the digital signature of the token.
The certificate needs to be registered in IIS
The application pool's hosting identity needs to have permission to "read" the certificate to extract the private key information (see the accepted answer here)

Resources