Lettura file P7m

mercoledì 20 marzo 2024 - 09.41
Tag Elenco Tags  C#

AntCiar Profilo | Expert

Buongiorno a tutti.

Sono alle prese con la lettura dei file p7m relativi alle fatture elettroniche.
Ho usato questo codice (trovato sulla rete) per convertire i file p7m in file xml in modo da poterne leggere il contenuto

byte[] FileFirmatoP7m = File.ReadAllBytes(p7mFilePath);
SignedCms cmsFirmato = new SignedCms();
cmsFirmato.Decode(FileFirmatoP7m);

byte[] FileRilevato = cmsFirmato.ContentInfo.Content;

File.WriteAllBytes(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(p7mFilePath), fileNameConvertito), FileRilevato);
res = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(p7mFilePath), fileNameConvertito);
cmsFirmato = null;


Questo codice per ora ha sempre funzionato. Con alcuni file invece capita che quando viene chiamato il metodo .Decode solleva una eccezione.
Nel testo dell'eccezione mi da "Valore tag ASN1 non valido."

Ho cercato in rete qualcosa per risolvere il problema ma non ho trovato molto.
In molti usano openssl per "convertire" il file firmato in un altro formato "leggibile".
Ho provato con questo ad esempio

openssl smime -verify -noverify -in file.p7m -inform DER -out file.xml

ma ho errori del tipo

Error reading S/MIME message
B0130000:error:068000A8:asn1 encoding routines:asn1_check_tlen:wrong tag:crypto\asn1\tasn_dec.c:1188:
B0130000:error:0688010A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:crypto\asn1\tasn_dec.c:349:Type=PKCS7

Qualcuno di voi ha avuto problemi simili e in qualche modo superati?
Grazie a tutti
Cristian Barca

Davide1986 Profilo | Junior Member

Buongiorno.

Il problema che stai riscontrando con la lettura dei file P7M è abbastanza comune, specialmente quando si ha a che fare con file firmati digitalmente che utilizzano formati o algoritmi di firma non standard o obsoleti. Ecco alcune possibili soluzioni e suggerimenti per risolvere il tuo problema:

## Utilizzo di BouncyCastle

Una delle librerie più robuste per gestire i formati di firma digitale è BouncyCastle. Puoi provare ad utilizzarla al posto della classe `SignedCms` di .NET. Ecco un esempio di come potresti modificare il tuo codice:

```csharp
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.X509;

byte[] FileFirmatoP7m = File.ReadAllBytes(p7mFilePath);
CmsSignedData cmsSignedData = new CmsSignedData(FileFirmatoP7m);
byte[] FileRilevato = cmsSignedData.SignedContent.GetContent();

File.WriteAllBytes(Path.Combine(Path.GetDirectoryName(p7mFilePath), fileNameConvertito), FileRilevato);
```

## Utilizzo di OpenSSL da C#

Se preferisci continuare ad utilizzare OpenSSL, puoi integrarlo nel tuo codice C# utilizzando la libreria `Process` per eseguire i comandi OpenSSL. Ecco un esempio:

```csharp
using System.Diagnostics;

public static byte[] ExtractP7mContent(string p7mFilePath)
{
string tempOutputPath = Path.GetTempFileName();

try
{
using (Process process = new Process())
{
process.StartInfo.FileName = "openssl";
process.StartInfo.Arguments = $"cms -verify -noverify -in \"{p7mFilePath}\" -inform DER -out \"{tempOutputPath}\"";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.Start();

string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (process.ExitCode != 0)
{
throw new Exception($"OpenSSL error: {error}");
}

return File.ReadAllBytes(tempOutputPath);
}
}
finally
{
if (File.Exists(tempOutputPath))
{
File.Delete(tempOutputPath);
}
}
}
```

## Gestione di formati diversi

Poiché alcuni file P7M potrebbero essere codificati in formato PEM invece che DER, puoi provare ad aggiungere un controllo e gestire entrambi i formati:

```csharp
public static byte[] ExtractP7mContent(string p7mFilePath)
{
string format = "DER";
if (File.ReadAllText(p7mFilePath).StartsWith("-----BEGIN"))
{
format = "PEM";
}

// ... resto del codice come sopra, ma usa format al posto di "DER" nell'argomento di OpenSSL
}
```

## Verifica della firma

Se hai bisogno di verificare la firma oltre che estrarre il contenuto, puoi modificare il comando OpenSSL per includere il certificato della CA:

```csharp
process.StartInfo.Arguments = $"cms -verify -CAfile \"path_to_ca_cert.pem\" -in \"{p7mFilePath}\" -inform {format} -out \"{tempOutputPath}\"";
```

Ricorda di sostituire "path_to_ca_cert.pem" con il percorso effettivo del certificato della CA.

Queste soluzioni dovrebbero aiutarti a gestire la maggior parte dei file P7M, anche quelli che causavano problemi con il tuo codice originale. Se continui a riscontrare problemi con file specifici, potrebbe essere necessario analizzarli individualmente per determinare se utilizzano formati o algoritmi di firma non standard[1][2][4].

Citazioni:
[1] Lettura file P7m - Forum - dotNetHell.it https://www.dotnethell.it/Forum/messages.aspx?ThreadID=49889
[2] Cosa devo fare se la verifica della firma dà esito negativo? https://www.sportellotelematico-pomponescosabbioneta.it/faq:s_italia:cosa.devo.fare.se.verifica.firma.esito.negativo
[3] Trying to decrypt S/MIME file using Openssl - Stack Overflow https://stackoverflow.com/questions/28518775/trying-to-decrypt-s-mime-file-using-openssl
[4] Errore openssl nella decodifica dei files p7m con openssl 1.1.1 https://forum.italia.it/t/errore-openssl-nella-decodifica-dei-files-p7m-con-openssl-1-1-1/22770
[5] p7m firma digitale: come estrarre il contenuto - Quoll tech https://quoll.it/firma-digitale-p7m-come-estrarre-il-contenuto/
[6] P7m con problemi - Fatturazione Elettronica - Forum Italia https://forum.italia.it/t/p7m-con-problemi/7764
[7] Decrypting .P7M File with Key (.pem) using OpenSSL https://security.stackexchange.com/questions/90811/decrypting-p7m-file-with-key-pem-using-openssl
[8] p7m viewer firma digitale: come estrarre il contenuto - parte seconda https://quoll.it/p7m-viewer-firma-digitale-parte-seconda/
[9] Problemi di caricamento del documento firmato - mepafacile https://www.mepafacile.it/forums/topic/problemi-di-caricamento-del-documento-firmato/
[10] help errore valore tag asn1 non valido help - Hardware Upgrade https://www.hwupgrade.it/forum/showthread.php?t=2165845

Blog ImaginSystems
http://blogs.dotnethell.it/imaginsystems
http://www.imaginsystems.it
http://www.alpacasrl.it
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5