Ошибка дешифрования содержимого MIME - встречено неправильное значение тега ASN1 - PullRequest
0 голосов
/ 20 декабря 2018

Я написал функцию для создания сообщения MIME и шифрования контента с помощью открытого сертификата пользователя, который хранится в хранилище сертификатов, в то время как закрытые ключи хранятся на моей смарт-карте.Моя функция просто сохраняет содержимое pkcs7mime в файл.У меня есть другая функция тестирования, которая просто читает файл и пытается расшифровать содержимое.Однако, когда я пытаюсь расшифровать, я получаю ошибку: ASN1 встретился со значением тега.

Код моей функции шифрования:

private static void EncryptMime()
    {
        MimeMessage mm = new MimeMessage();
        var ctx = new WindowsSecureMimeContext();
        mm.From.Add(new MailboxAddress("Bob", "Bob@diamondsg.onmicrosoft.com"));
        mm.To.Add(new MailboxAddress("Alice", "Alice@diamondsg.onmicrosoft.com"));

        mm.Subject = "Smime Test";

        mm.Body = new TextPart("plain")
        {
            Text = @"This is a test."
        };

        var signer = mm.From.Mailboxes.FirstOrDefault();
        var recipients = mm.To.Mailboxes.AsEnumerable();
        ApplicationPkcs7Mime p7m = ApplicationPkcs7Mime.SignAndEncrypt(ctx, signer, DigestAlgorithm.Sha1, recipients, mm.Body);

        MemoryStream ms = new MemoryStream();
        p7m.WriteTo(ms, true);
        byte[] bytes = ms.GetBuffer();
        File.WriteAllBytes("smime.p7m", bytes);
    }

Вот моя функция расшифровки:

private static void DecryptMime()
    {

        CryptographyContext.Register(typeof(WindowsSecureMimeContext));

        string messagetext = "";
        // Read the p7m file           
        byte[] bytes = 
        File.ReadAllBytes("smime.p7m");
        MemoryStream ms = new MemoryStream(bytes);
        ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
        // WindowsSecureMimeContext ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);

        if (p7m != null && p7m.SecureMimeType == SecureMimeType.EnvelopedData)
        {
            Console.WriteLine("Decrypting message...");
            try
            {
                p7m = p7m.Decrypt() as ApplicationPkcs7Mime;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error decrypting: " + ex.Message);
            }
        }

        if (p7m != null && p7m.SecureMimeType == SecureMimeType.CompressedData)
        {
            Console.WriteLine("Decompressing message...");
            p7m = p7m.Decompress() as ApplicationPkcs7Mime;
        }

        if (p7m != null && p7m.SecureMimeType == SecureMimeType.SignedData)
        {
            Console.WriteLine("Verifying message...");
            p7m.Verify(out MimeEntity entity);
            MimeMessage mm = new MimeMessage(entity);
            messagetext = mm.GetTextBody(MimeKit.Text.TextFormat.Text);
            Console.WriteLine("Decrypted Message: " + messagetext);
        }           
    }

Редактировать: я пытался изолировать проблему с помощью следующего кода:

MemoryStream ms = new MemoryStream();
        p7m.WriteTo(ms);    
ApplicationPkcs7Mime new_p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);  

        if (new_p7m != null && new_p7m.SecureMimeType == SecureMimeType.EnvelopedData)
        {
            Console.WriteLine("Decrypting message...");
            try
            {
                new_p7m = new_p7m.Decrypt() as ApplicationPkcs7Mime;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error decrypting: " + ex.Message);
            }
        }

Таким образом, проблема, кажется, начинается еще в функции WriteTo () ...

Обновление № 2: Хорошо, поэтому я сделал toString как для объекта p7m, так и для объекта new_p7m.Видимо, содержание отличается ...

p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
    name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64

MIIOOwYJKoZIhvcNAQcDoIIOLDCCDigCAQIxggEwMIIBLAIBAoAU2NQqDvYHJuMeC27IpyiV
....

New p7m: Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
    name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
Content-Transfer-Encoding: base64

Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wa2NzNy1taW1lOyBzbWltZS10eXBlPWVudmVs
....

То, как-то фактическое содержание меняется ... очень странно ...

1 Ответ

0 голосов
/ 21 декабря 2018

Держу пари, что ваш код для сохранения содержимого на диск записывает поврежденный файл:

MemoryStream ms = new MemoryStream();
p7m.WriteTo(ms, true);
byte[] bytes = ms.GetBuffer();
File.WriteAllBytes("smime.p7m", bytes);

Проблема с приведенным выше кодом состоит в том, что GetBuffer() возвращает больше байтов, чем фактически используетсяпоток памяти в большинстве случаев.Приведенная выше логика также сохранит содержимое в base64, что, вероятно, не то, что вам нужно.Следующий фрагмент кода декодирует содержимое base64 в файл smime.p7m:

using (var stream = File.Create ("smime.p7m"))
    p7m.Content.DecodeTo (stream);

Затем, чтобы восстановить часть MIME для расшифровки, выполните следующие действия:

var bytes = File.ReadAllBytes ("smime.p7m");
var ms = new MemoryStream (bytes);
var p7m = new ApplicationPkcs7Mime (SecureMimeType.EnvelopedData, ms);

ПроблемаВы сталкивались с тем, что контент был ранее закодирован в base64, и его не должно было быть.

Конечно, если нет необходимости сохранять только необработанный контент, а затем заново создавать часть application / pkcs7-mimeтрудный путь, почему бы просто не сохранить всю часть MIME следующим образом?

using (var stream = File.Create ("smime.p7m"))
    p7m.WriteTo (stream);

А затем снова загрузить ее так:

using (var stream = File.OpenRead ("smime.p7m"))
    p7m = (ApplicationPkcs7Mime) MimeEntity.Load (stream);

Тогда вам не о чем беспокоитьсяо том, что все неправильно.

...