Voor een project heb ik eigen certificaten gegenereerd. Nu faalt de controle in C# omdat mijn CA root certificate niet geaccepteerd is. Via internet heb ik gevonden dat ik via de X509Chain klasse zelf de chain kan opbouwen, en opnieuw kan valideren. Alleen accepteert deze niet een eigen CA Root certificate. Daarvoor moet je weer handmatig door de gehele chain gaan en controleren.
Uiteindelijk heb ik dit stukje code kunnen schrijven om de chain te kunnen controleren. Ik ben benieuwd of ik dingen gemist heb of niet. Let niet teveel op schoonheid van code oid, het is puur nog een proof of concept.
De client logica is als volgt (in hoeverre het interessant is):
Uiteindelijk heb ik dit stukje code kunnen schrijven om de chain te kunnen controleren. Ik ben benieuwd of ik dingen gemist heb of niet. Let niet teveel op schoonheid van code oid, het is puur nog een proof of concept.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| private static bool ValidateServerCertificate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { X509Certificate2 root = new X509Certificate2("ca.cer"); X509Certificate2 cert = new X509Certificate2(certificate); chain.Reset(); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreRootRevocationUnknown; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.ExtraStore.Add(root); if (chain.Build(cert) == false) { // errors occured: unable to check any or all certificates of the chain bool chainHasErrors = false; // Assume no errors as of yet foreach (X509ChainStatus status in chain.ChainStatus) { switch (status.Status) { case X509ChainStatusFlags.NoError: chainHasErrors |= false; break; case X509ChainStatusFlags.UntrustedRoot: { // Untrusted Root error can happen when user has not installed our CA in their CA Root Certificate Store. // We check if the CA-ROOT certificate is indeed our CA root certificate. bool RootOk = false; foreach (X509ChainElement el in chain.ChainElements) { if (RootOk == true) { // Our CA is expected to be the Root(=last) certificate.. It's not! RootOk = false; break; } if (root.Thumbprint == el.Certificate.Thumbprint) { RootOk = true; } } chainHasErrors |= !RootOk; } break; default: // no other errors are expected // @todo: Might want to log the information here to a file if errors were found! chainHasErrors |= true; break; } } return !chainHasErrors; } return true; } |
De client logica is als volgt (in hoeverre het interessant is):
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| X509Certificate2 cert = new X509Certificate2("client.p12"); txtLog.Text= txtLog.Text.Insert(0, "Created client certificate!\r\n"); TcpClient client = new TcpClient("127.0.0.1", 7331); txtLog.Text = txtLog.Text.Insert(0, "Connected!\r\n"); SslStream test = new SslStream(client.GetStream(),false,ValidateServerCertificate,CertificateSelectionCallback); txtLog.Text = txtLog.Text.Insert(0, "SSL Stream started. !\r\n"); test.AuthenticateAsClient("What_is_targethost", new X509CertificateCollection(new []{cert}), System.Security.Authentication.SslProtocols.Default, false); txtLog.Text = txtLog.Text.Insert(0, "Authenticate as client!!\r\n"); |