2011-06-27 4 views
9

J'ai une autorité de certification Windows que j'utilise pour émettre des certificats d'authentification client via .net/C#. J'ai réussi à l'obtenir pour émettre des certificats par programmation en appelant l'API de l'autorité de certification via COM. J'émets un nouveau certificat lorsque je configure un client. Au moment de l'exécution, ces clients attachent les certificats aux demandes envoyées à mon serveur. Comment puis-je vérifier par programme qu'un X509Certificate2 a été signé par le certificat racine de mon autorité de certification (et rejeter les certificats signés par une autre source)?Comment puis-je valider qu'un certificat a été créé par une autorité de certification particulière?

+1

devrait être sur security.se (peut-être) – Woot4Moo

+2

pourquoi? ma question est comment valider la signature en code ... –

+0

Avez-vous trouvé un moyen de coder cela? – MiguelM

Répondre

14

J'ai fait cela beaucoup lot. Voici un code facile à utiliser.

La partie dans le bloc if (!isChainValid) consiste à faire un joli message d'erreur. Vous n'avez pas besoin de l'utiliser si vous ne le voulez pas, mais vous devriez lancer une erreur si la chaîne ne peut pas être construite. Les éléments de la chaîne sont nécessaires pour vérifier votre racine.

X509Certificate2 authority = GetAuthorityCertificate(); 
X509Certificate2 certificateToValidate = GetCertificateToValidate(); 

X509Chain chain = new X509Chain(); 
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; 
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; 
chain.ChainPolicy.VerificationTime = DateTime.Now; 
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0); 

// This part is very important. You're adding your known root here. 
// It doesn't have to be in the computer store at all. Neither certificates do. 
chain.ChainPolicy.ExtraStore.Add(authority); 

bool isChainValid = chain.Build(certificateToValidate); 

if (!isChainValid) 
{ 
    string[] errors = chain.ChainStatus 
     .Select(x => String.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status)) 
     .ToArray(); 
    string certificateErrorsString = "Unknown errors."; 

    if (errors != null && errors.Length > 0) 
    { 
     certificateErrorsString = String.Join(", ", errors); 
    } 

    throw new Exception("Trust chain did not complete to the known authority anchor. Errors: " + certificateErrorsString); 
} 

// This piece makes sure it actually matches your known root 
var valid = chain.ChainElements 
    .Cast<X509ChainElement>() 
    .Any(x => x.Certificate.Thumbprint == authority.Thumbprint); 

if (!valid) 
{ 
    throw new Exception("Trust chain did not complete to the known authority anchor. Thumbprints did not match."); 
} 
+0

les erreurs ne seront jamais nulles;) – HelloWorld

+0

@HelloWorld Eh bien, si j'écrivais ceci aujourd'hui, j'utiliserais tout simplement 'if (errors? .Length> 0)' de toute façon. :) C# 6. Bon à savoir; Je n'ai pas plongé dans l'implémentation de ToArray() pour voir ce qui se passe si 'IEnumerable' de Select()' ne renvoie aucun résultat. –

+0

@ChrisBenard Le code pour vérifier que le certificat correspond vraiment à votre racine connue? Ce morceau de code devrait correspondre à quelque chose comme ceci et retourner presque toujours vrai: 'chain.ChainElements.Cast (). Tous (x => x.Certificate.Thumbprint! =" XX ");' – Ogglas

0

Si vous dites que vous avez un racine (qui est autosigné) certificat, alors votre seule option est de garder ce certificat racine disponible sur votre serveur (sans la clé privée bien sûr) et d'effectuer une procédure de validation de certificat contre votre certificat racine. Il s'agit d'une situation en miroir pour le client Web validant la chaîne de certificats du serveur.

+1

J'ai exactement ce scénario. Je clarifierai ma question, mais je cherche le code particulier nécessaire pour valider la signature en C#. –

+0

@Jeffrey Je sais comment cela se fait dans notre SecureBlackbox for .NET, mais pas comment il est fait pure .NET Framework. –

+0

Il existe peut-être un meilleur moyen, mais consultez la classe [X509Chain] (http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx). L'exemple de documentation montre le code pour parcourir la chaîne en examinant chaque élément au fur et à mesure. –

Questions connexes