Queste classi rendono semplice e veloce per firmare alcuni dati arbitrari, creando un file firmato .p7s. E' possibile caricare una firma p7s, e verificare che i dati sono ancora validi, quindi estrarre i dati. Queste operazioni sono inglobati nella classe SignedCms .
Ecco come si sarebbe creata una semplice firma enveloped:
public static byte[] Sign(byte[] data, X509Certificate2 certificate)
{
if(data == null)
throw new ArgumentNullException("data");
if(certificate == null)
throw new ArgumentNullException("certificate");
// setup the data to sign
ContentInfo content = new ContentInfo(data);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
// create the signature
signedCms.ComputeSignature(signer);
return signedCms.Encode();
}
In primo luogo salviamo i dati in un ContentInfo oggetto. Poi creiamo un oggetto SignedCms per creare la firma, passando il contenuto di firmare e indicare che vogliamo una firma enveloped passando false per il parametro indipendente. L'ultimo passo da eseguire è quella di creare un CmsSigner con il certificato che ha la chiave privata che verrà utilizzato per creare la firma. Registriamo questo certificato, rendendo nota del suo numero di serie di chi c'è l'ha rilasciato. Dopo che il setup è stato fatto, tutto quello che resta da fare è calcolare la firma e codifica i dati p7s.
La verifica della firma è ancora più semplice:
public static bool Verify(byte[] signature, X509Certificate2 certificate)
{
if(signature == null)
throw new ArgumentNullException("signature");
if(certificate == null)
throw new ArgumentNullException("certificate");
// decode the signature
SignedCms verifyCms = new SignedCms();
verifyCms.Decode(signature);
// verify it
try
{
verifyCms.CheckSignature(new X509Certificate2Collection(certificate), false);
return true;
}
catch(CryptographicException)
{
return false;
}
}
Per prima cosa creiamo un SignedCms per fare la verifica. CheckSignature funziona diversamente da altro codice di verifica della firma che viene fornito con il runtime, in quanto non farà nulla se la firma è valida, ma gettano una CryptographicException se la firma non è valida. Al fine di convertire ad un risultato booleano, dobbiamo solo intercettare l'eccezione e restituire false. La mancanza di una deroga significa che possiamo restituire true.
Un'altra operazione si potrebbe desiderare di fare una volta che abbiamo verificato una firma enveloped è quello di estrarre i dati che è stato firmato. La classe SignedCms rende questo una semplice operazione:
public static byte[] ExtractEnvelopedData(byte[] signature)
{
if(signature == null)
throw new ArgumentNullException("signature");
// decode the signature
SignedCms cms = new SignedCms();
cms.Decode(signature);
if(cms.Detached)
throw new InvalidOperationException("Cannot extract enveloped content from a detached signature.");
return cms.ContentInfo.Content;
}
Ancora una volta, abbiamo semplicemente decodificare la firma, e supponendo che si trattava di una firma enveloped tornare il contenuto dall'interno.