2010-09-02 7 views
7

Sto provando a convalidare un certificato X.509 usando C# e .NetCF. Ho il certificato CA e, se ho capito bene, ho bisogno di utilizzare la chiave pubblica da questo certificato CA per decrittografare la firma del certificato non attendibile. Questo dovrebbe darmi il valore hash calcolato del certificato non attendibile. Dovrei quindi calcolare da solo l'hash del certificato e accertarmi che i due valori corrispondano.Come convalidare il certificato X.509 in C# usando Compact Framework

Ho giocato con questo per alcuni giorni e non sto andando molto lontano. Ho utilizzato le classi X509Certificate e RSACryptoServiceProvider. Innanzitutto, ho cercato di estrarre la chiave pubblica e la firma dalla classe X509Certificate. Sono stato in grado di ottenere la chiave pubblica ma non la firma. Successivamente, ho provato ad analizzare i dati binari che compongono il certificato, il che mi ha permesso di ottenere la firma (e qualsiasi altro dato che volevo), ma non sono stato in grado di decifrare la firma utilizzando RSACryptoServiceProvider. Ho provato cose come questa, ma continuato a ottenere eccezioni dicendo "Bad Chiave" quando ho provato a decifrare:

RSAParameters rsaParams = new RSAParameters(); 
rsaParams.Exponent = exp; 
rsaParams.Modulus = mod; 
RSACryptoServiceProvider rsaServ = new RSACryptoServiceProvider(); 
rsaServ.ImportParameters(rsaParams); 
byte[] decryptedSig = rsaServ.Decrypt(encryptedSig, false); 

Qualsiasi consiglio sarebbe molto apprezzato.

Modifica: Ho provato qualcosa che sembra essere migliore ma restituisce uno strano risultato. Sto lavorando con la classe X509Certificate2 qui perché è un po 'più facile per i test, ma in seguito dovrò passare a X509Certificate per .NetCF. Penso che RSACryptoServiceProvider.VerifyData potrebbe essere quello che mi serve. Ho provato il seguente codice.

X509Certificate2 cert = new X509Certificate2(certBytes); 
X509Certificate2 certCA1 = new X509Certificate2(@"C:\certs\certCA1.cer"); 

byte[] encryptedSig = new byte[256]; 
Array.Copy(certBytes, certBytes.Length - 256, encryptedSig, 0, 256); 

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certA1.PublicKey.Key; 
bool good = rsa.VerifyData(cert.RawData, "1.3.14.3.2.26", encryptedSig); 

Come ho detto, io sono in grado di decodificare e interpretare i dati binari del certificato manualmente, quindi sono abbastanza sicuro che la cert.RawData è dati firmati del certificato e gli ultimi 256 byte sono la firma crittografata . La stringa è l'OID dell'algoritmo hash, che ho ottenuto dal certificato, ma non sono sicuro al 100% che sia corretto. VerifyData restituisce false, ma non ne sono ancora sicuro.

Pensieri?

risposta

3

Qui è la mia codice.

RSACryptoServiceProvider rsa = signingCertificate_GetPublicKey(); 
return rsa.VerifyData(SignedValue(), CryptoConfig.MapNameToOID("SHA1"), Signature()); 

RSACryptoServiceProvider signingCertificate_GetPublicKey() 
{ 
    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider(); 

    RSAParameters publicKeyParams = new RSAParameters(); 
    publicKeyParams.Modulus = GetPublicKeyModulus(); 
    publicKeyParams.Exponent = GetPublicKeyExponent(); 

    publicKey.ImportParameters(publicKeyParams); 

    return publicKey; 
} 

byte[] GetPublicKeyExponent() 
{ 
    // The value of the second TLV in your Public Key 
} 

byte[] GetPublicKeyModulus() 
{ 
    // The value of the first TLV in your Public Key 
} 

byte[] SignedValue() 
{ 
    // The first TLV in your Ceritificate 
} 

byte[] Signature() 
{ 
    // The value of the third TLV in your Certificate 
} 

Spero che questo aiuti chiunque stia lavorando su questo problema.

1

WinCE supporta qualcosa compatibile con Win32 MSCrypto.dll? Se sì, dai un'occhiata alla classe .NET X509Certificate2 e anche allo CLR Security library on Codeplex. Contiene molte routine utili per .NET che si trovano sulla libreria crittografica del sistema operativo principale. È possibile scaricare il sorgente e vedere come si compila per .NetCF

Per caricare e convalidare un certificato X509, fare qualcosa di simile (non testata):

var cert = new X509Certificate2("mycert.cer"); 
if (!cert.Verify()) 
{ 
    <fail> 
} 

ci sono quasi una dozzina di costruttori per costruire X509Certificate2 da un'ampia varietà di fonti: file su disco, array di byte in memoria, caricamento da archivio di certificati locali, ecc.

La CA radice utilizzata per firmare il certificato dovrà essere installata nell'archivio certificati locale. Se il certificato non include le CA intermedie nella catena di fiducia, tali intermediari dovranno trovarsi anche sulla macchina locale, fino a una CA radice che si trova nell'archivio certificati attendibile nel computer locale.

Sfortunatamente, non posso dire dai documenti MSDN se X509Certificate2 è disponibile su .NetCF.

+0

I limiti di WinCE possono essere approssimativi e sono completamente nuovo di X.509, quindi in realtà ho cercato di farlo funzionare in un normale ambiente Win32 e non sono nemmeno in grado di farlo. Ho dato un'occhiata alla libreria di sicurezza CLR che hai indicato, ma non ho visto nulla lì per convalidare il certificato X509. Puoi darmi un po 'di più per andare avanti? – Ben

+0

Ho aggiornato la risposta con un codice di esempio. – dthorpe

+0

X509Certificate2 non è disponibile su .NetCF, ma è utile. Grazie. – Ben

0

Funziona per me in win32, ma nel quadro Compact sto affrontando lo stesso problema, non c'è X509Certificate2 così sto in realtà bloccato, con win32 possiamo fare:

X509Certificate2 l__PublicKeyCertificate = new X509Certificate2("cert.cer"); 

RSACryptoServiceProvider l__rsaCspPublic = (RSACryptoServiceProvider)l__PublicKeyCertificate .PublicKey.Key; 

//... 

l__isVerified = l__rsaCspPublic.VerifyData(l__fileData, CryptoConfig.MapNameToOID("SHA1"), l__fileSignature); 
+0

L'ho capito un po 'di tempo fa e ho dimenticato di postare la risposta. Daremo uno sguardo al mio codice sorgente e riceverò la risposta entro lunedì. – Ben

Problemi correlati