How to verify a rollover certificate? - c#

I want to verify a certificate that comes from a SAML assertion (issued by AZURE AD)
They can rollover the public key at any time. I am assuming it means that I cannot manage them manually in the trusted root store.
I am using X509Certificate2.Verify() which is returning False if the certificate is not in the Trusted root store. Should I use X509Certificate2.Build() and set it to ignore if it is trusted?

SAML2 uses certificates as a convenient way of representing encryption/signing keys with a standard file format. The contents of the certificate are not relevant because the certificates should be directly exchanged between the involved parties. So there is no need to verify the certificate's validity, in many deployments it won't even validate.
With an Idp that regularly does key rollover you should load and trust the metadata of the Idp instead of directly configuring the certificate.
If you are implementing all of this on your own I'd recommend that you spend some time looking for an existing implementation. Making a complete SAML2 implementation that supports loading metadata is non-trivial and takes a lot of time.

Related

Self-signed TLS certificates in Intranet

I'm writing a system in C#, which consists of REST API server, written with HttpListener and WPF client app, with HttpClient and I want to use HTTPS.
As far as I know, on the server side all I have to do is run HttpListener with prefix with https and bind my certificate (creted for example with makecert) to proper port - now all communication is encrypted.
On the client side, I have to put the public part of certificate in Current User store, so that it can be trusted.
The server is not public, each client has his own instance accesible only after logging in to their VPN.
My questions:
1. Are self-signed certificates secure enough? Is generating new certificate for new client more secure(for example, from license data)?
2. How do I generate the "public part" and "private part" of certificate? How do I ship it?
It isn't a bank, so I don't want to overkill security, but I don't want to go "trust all certificates" way.
Security in general hinges on how well protected your private key is. The algorithm used can be the same as on a public signed certificate.
There is no inherit security gain or loss in using a self signed certificate.
The bigger problem is the distribution of your public key among the member systems. If you run a domain wide CA on your domain controller, it should be relatively easy.
If you do not, you might be able to do it via Group Policy.
In any case it requires admin intervention to get it to run on all your systems and again should the private key be compromised.
The problem arises should you have external clients not connected to your DC. Then LetsEncrypt is definitely the better choice.
I believe that you'll have to add the public key of the self signed certificate to the Trusted Root Certification Authorities store as well.
That is offcourse cumbersome since you'll have to do this on every client ...
Can't you use certificates issued by LetsEncrypt ?

I have several questions about the SslStream Class and about certificates

I have looked at about 10-15 different pages about the SSlStream class and about certificates and I haven't found one that completely explains everything to me. So I have a bunch of questions.
I am currently working on some SslStream code and I have a question about certificates. From my research it appears that the server requires a certificate if we are using TSL12. And it appears optional that the client needs a certificate.
1) Now if we design a system that the client needs a certificate do we use the same certificate for the client and the server? Or do they both use different ones?
2) Also looking at the Microsoft SslStream help page:
https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx
How does the code know if those are the expected certificates?
3) In the Property page on a project under Signing you can Create a Test Certificate. When you click that button it asks for a Password. If a password is used how would that affect the SslStream code? The code on the Microsoft help page above doesn't deal with that at all?
4) Once I have a certificate for the server and the client can I just place them in a directory or do I need to put them in the store?
Thanks.
You can find most answers to your questions here
These are the different certificates. Client certificate used to check client identity. Server certificate used to encrypt key materials and to authenticate itself.
What means expected? You mean whether the client certificate is correct? You can write your own login to check client and certificate. By default expiration date is checked, where it's revoked or not etc. Read there to clarify.
It will create certificate and to use private key you will need to provide password to get it from storage
The base usage is to put it into the store. But you can also get it from .pfx file. You can read there about geting the key from file
1) Now if we design a system that the client needs a certificate do we use the same certificate for the client and the server? Or do they both use different ones?
The best practice is "one certificate per purpose". Think of a server authentication certificate as the "Warner Bros. Studios" sign hanging on the building as you pull up to the guard shack, and a client authentication certificate as an employee ID badge. They both inform the other party what's going on, but it feels a little out of place to then walk down the street to Universal and show your big Warner Bros. sign as identification.
2) Also looking at the Microsoft SslStream help page: https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx How does the code know if those are the expected certificates?
The server authentication certificate you provide is correct, because you provided it.
If you give only one client auth cert, that's correct, because you provided it.
If you give multiple client auth certs then it will use an acceptable CAs list provided by the server TLS handshake to reduce the list, then it takes the first one that was acceptable.
3) In the Property page on a project under Signing you can Create a Test Certificate. When you click that button it asks for a Password. If a password is used how would that affect the SslStream code? The code on the Microsoft help page above doesn't deal with that at all?
Certificates don't have passwords, but PFX/PKCS#12 files do. You need that password to load the file into an X509Certificate2 instance (e.g. new X509Certificate2("servercert.pfx", "1Potato2Potato3Potato4")). Since SslStream won't do the loading for you, it doesn't talk about passwords.
4) Once I have a certificate for the server and the client can I just place them in a directory or do I need to put them in the store?
They should work fine when loaded from a PFX (you need the private key, so it can't be just a .cer). If the certificates can be one-time loaded into cert stores you can avoid the problem of loading or hard-coding PFX passwords... but that just depends on your deployment needs.

Use for every Reyling Party seperate client Certificate?

I'm reading up on SSO and I used this tutorial http://chris.59north.com/post/2013/04/09/Building-a-simple-custom-STS-using-VS2012-ASPNET-MVC.aspx for creating a custom STS.
If I understood correct on the STS machine is installed a certificate. The reyling party sends the thumbprint of the x509 signature. So the relying party will accept only claims of a STS with the proper certificate. Is this correct?
If so, I would like to implement that every relying party is sending a certificate to the STS which the STS got installed too. On a request the STS look up in his trusted relying party list if the sent certificate is known by the STS.
Is this implemention a good idea and is this good practice? Is there a good ressource to implement this?
thanks
implementing a custom STS is hard work. I would advise you to have a look at windows azure ACS or the Thinktecture free STS as a starting point.
This being said, having a separate certificate for a relying party is a common practice. However, the private key of this certificate is normally stored inside some database in the STS (ACS and Thinktecture both support this). The relying party only knows the public key.
The security token (SAML2 or JWT) is then signed by the acs with the security token and the relying party can use the public key (or a thumbprint) to verify the signature.
Please also notice that a SAML2 token can also be encrypted (next to being signed) and that you can use a different certificate for that.
I personally would recommend using a seperate certificate it the STS (or your organisation) has some kind of website were "anybody" can register their application as a relying party. If all your elying parties are "internal" applications I would at least consider using a single certificate to sign all security tokens. This has the advantage that you can publish the (public) key in your Federation meta data document (located at FederationMetadata/2007-06/FederationMetadata.xml). If you wish to update the key, you can update it there (by first publishing new and old key there and later only the new key). Relying parties can then update there keys based on this meta data (adfs uses a similar approach).
So bottom line : having a seperate certificate per RP is good but having a single one (for signing - not encryption) is much easier to update.

Manually trust SSL certificate in C#

I am developing an application in C# that will communicate with a server over HTTP and SSL. Is there some way that I can have the program trust the certificate supplied by the server? This certificate would be distributed together with the software, so that it can identify the server without involving an external CA.
Clarification: I want my client application to trust a single certificate that has been hard-coded in the client so that it will only ever trust my own server.
You can use BouncyCastle.
Load your CA certificate into BC usign DotNetUtilities class using the FromX509Certificate(X509Certificate) function
Load the public key from the server certificate into BC.
Call Verify on the server certificates public key
This way you check the signature of the certificate. Which is the safest way. And also gives you the possibility to update the server certificate without updating the client. (As long as the CA is valid off course)
Source of Verify here: http://www.bouncycastle.org/viewcvs/viewcvs.cgi/csharp/crypto/src/x509/X509Certificate.cs?view=markup Line:540
In my opinion, I don't think you can do this and trust that you have a secure channel. Someone correct me if I'm wrong, but the CA trust chain in SSL isn't to just to verify that the thumbprint is a particular value (or some other part of the certificate). It proves that the the client is communicating with the correct server (due to a shared CA key). This illustration is a good reference. Skipping step 3, will not allow the server to prove its identity to the client (throw certificate validation).
so that it will only ever trust my own server
SSL guarantees this by using a shared CA certificate (like verisign etc). Maybe I don't understand why you would choose not to just use SSL as it was intended.
EDIT:
As the_ajp points out in his answer, there are libraries (like bouncy castle) that will do a full verification on the certificate chain. These can be called manually.

Debugging certificate policy validation failures: "The remote certificate is invalid according to the validation procedure."

I'm trying to write a C# client that consumes a web service. The communication is encrypted. I have downloaded and installed the sites' certificate into that magic place where WinXP keeps them.
When I run my client I fail with "The remote certificate is invalid according to the validation procedure."
When I run certmgr.msc, the GUI informs me that the certificate has an invalid policy. The certificate has valid dates and the certification path is ok. The certificate does have a certificate policy with a policy identify integers interleaved with dots (like 1.2.30...)
Using code from the X509Certificate2.Verify Method documentation, I can see that the Verify message does indeed return false.
In trying to research this error, I found a reference in Brian Komar's Windows Server 2008 PKI and Certificate Security:
Policy validation. If the application that calls the certificate chaining engine expects a specific application policy or certificate OIDs in the certificate, and the required policy or OIDs are not contained within the certificates in the CA chain, the certificate chaining engine considers the certificate to be invalid.
I don't see that I'm setting any expectation of a specific application policy. I'm in the process of porting this WSE3 code to WCF so perhaps it is built in.
Any advice on how to run this down further? Is there really a problem with the certificate?
If the certificate is ok, do I need to configure or extend the CryptoConfig class to turn off checking the policy?
Any and all help appreciated.
You can always disable the validation by setting the ServicePointManager..::.ServerCertificateValidationCallback to a delegate returning true. This would give you time to track down any issues with the certificate.
One technique I've used to track these type of errors down is to visit the Web Service in a browser.
For example, if you have a Web Service at https://server/foo.asmx, drop that address into the browser of your choice, and you may get a more human readable interpretation of the error.

Categories

Resources