47 messaggi dal 09 luglio 2007
Ciao,
il mio capo mi ha appena passato un bel cetriolone da finire entro 20 giorni, visto che si è venduto con il cliente delle cose impensabili.
Devo fare un modulo in C# (quindi penso a una dll) con queste funzionalità:
1) stream in ingresso --> firma digitale e non ripudiabilità (non crittografia)
2) stream in ingresso firmato --> verifica autenticità e contenuto
3) stream in ingresso firmato --> firma digitale e non ripudiabilità dello stream firmato (in poche parole firmare la firma...)
4) riusabile e estendibile

Purtroppo sono cose che non ho mai fatto praticamente, le ho solo studiate all'università... quindi mi servirebbe qualche indizio per sapere almeno da dove cominciare, oppure qualche esempio di codice da cui partire.

Avete consigli?

Ciao,
N@poleone
"Le battaglie si vincono con gli uomini che si hanno, non con quelli che si vorrebbero" (Napoleone Bonaparte)
501 messaggi dal 09 giugno 2006
Contributi
Ciao.

Suggerisco di partire dalle basi. La crittografia (in senso lato) con .NET è abbastanza semplice:

http://msdn2.microsoft.com/it-it/library/92f9ye3s(VS.80).aspx

Ciao.

.:. Marcello Rutter .:.
47 messaggi dal 09 luglio 2007
Sono andato un po' avanti... nemmeno troppo.
Ora il problema è il seguente.
Sto sviluppando il metodo di verifica della firma che ha come parametri il documento su cui calcolare l'hash, la firma (cioè un hash crittato con la chiave privata di X) e un certificato X509 con la chiave pubblia di X.
Per verificare devo: decrittare la l'hash con la chiave pubblica; calcolare l'has del documento e verificare che siano uguali.
Il problema è che non so con quale algoritmo devo calcoare questo hash... So usando RSA per la firma digitale, quindi si possono usare vari algoritmi per firmare...

In sostanza la domanda è: c'è un modo, partendo dal certificato, di capire quale algoritmo è stato utilizzato per eseguire l'hash e poi firmare?

Questo è un pezzo di codice:
public bool VerifyDigitalSignature(Stream document, byte[] signedHash)
        {
            PublicKey pk = this.cert.PublicKey;
            RSACryptoServiceProvider rsa = pk.Key as RSACryptoServiceProvider;
            RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
            byte[] hash = WhatAlgorithmToCalculateHash(documet);
            return rsaDeformatter.VerifySignature(hash,signedHash);
        }


Avevo pensato di cercare una substring tipo "MD5", "SHA1" all'interno del campo SignatureAlgorithm del certificato, ma una volta fatto ciò mi manca la lunghezza dell'hash, o sbaglio??

Consigli?? O sto sbagliando tutto??

Ciao,
N@poleone
"Le battaglie si vincono con gli uomini che si hanno, non con quelli che si vorrebbero" (Napoleone Bonaparte)
501 messaggi dal 09 giugno 2006
Contributi
Considerato che hai il certificato (presumo quindi che tu stia usando una istanza di X509Certificate2) non puoi utilizzare "cert.SignatureAlgorithm.FriendlyName" (o sbaglio io qualcosa)?

Ciao.

.:. Marcello Rutter .:.
47 messaggi dal 09 luglio 2007
Non so... c'è qualcosa che non va, ma credo sia più un errore concettuale mio!
Comunque il FriendlyName mi ritorna, per esempio, "sha1RSA", che è effettivamente quello che si vede nei dettagli di un certificato.

Solo che da quel nome io dovrei creare un oggetto per calcolare l'hash, quindi uno tra MD5CryptoService, Sha1Crypto... mi sembra un meccanismo un po' farraginoso...
Provo a fare un riassutino di quello che ho capito, di come sto procedendo per vedere se sbaglio qualcosa.

Ho una classe che serve per firmare/verificare documenti. C'è un membro della classe che è un X509Certificate2. Per adesso mi preoccupo della verifica...

Utilizzando RSA, la verifica di una firma digitale dovrebbe avvenire in questo modo:
1) Ottengo la firma (cioè l'hash del documento crittato con la chiave privata)
2) Ottengo il documento
3) decritto la firma con la chiave pubblica
4) Calcolo l'hash del documento
5) verifico i due hash.

Avendo il certificato di chi ha firmato, come posso procedere??
Il codice che ho scritto sopra va nel verso giusto??

Altra domanda: nella firma non è memorizzato il certificato, vero? Se è così, come faccio a capire quale certificato prendere per verificare la firma?

Ciao,
N@poleone
"Le battaglie si vincono con gli uomini che si hanno, non con quelli che si vorrebbero" (Napoleone Bonaparte)
501 messaggi dal 09 giugno 2006
Contributi
Ciao.

Rispondo alla prima parte osservando che FriendlyName in realtà è la rappresentazione del corrispondente OID (cryptographic object identifier) che invece identifica in modo univoco e secondo standard l'algoritmo di crittografia. Per capire meglio questa parte devi far riferimento alle varie RFC (è tutto scritto). Se, a titolo di esempio, utilizzi la classe X509Certificate2 (come hai scritto) allora:

- cert.GetKeyAlgorithm() ti restituisce lo OID in formato stringa dell'algoritmo usato per la chiave (RSA è 1.2.840.113549.1.1.1 dove, in ordine, 1=osi, 2=member-body, 840=us, 113549=rsadsi, 1=pkcs, 1=pkcs-1 e infine l'ultimo 1 indica proprio RSA - vedi la RFC-3370)
- cert.SignatureAlgorithm.Value restituisce lo OID usato per la firma (1.2.840.113549.1.1.5 che corrisponde a SHA1 su RSA, 1.2.840.113549.1.1.2 corrisponde a MD2 su RSA, 1.2.840.113549.1.1.4 corrisponde a MD5 su RSA - vedi sempre la RFC-3370).
- Utilizzando la classe Oid (System.Security.Cryptography) puoi ottenere il nome partendo dall'OID (New Oid("1.2.840.113549.1.1.5").FriendlyName ).
- Utilizzando la classe CryptoConfig puoi infine ottenere un'istanza dell'oggetto di crittografia partendo dal nome (CreateFromName).

Personalmente utilizzo pochissimo questi strumenti quindi non saprei dirti se c'è qualche tecnica diversa per gestire almeno questa parte del problema.

Per il resto la logica mi sembra corretta e cercando in google trovi una miriade di esempi. Lascio comunque spazio a chi ne sa più di me per una risposta più approfondita.

Alla prossima.

.:. Marcello Rutter .:.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.