Стандартизированный подход к цифровым подписям файлов через.NET

(здесь разработчик V8.) Краткий ответ: в этом примере bar обладает «быстрыми» свойствами.

Вы можете убедиться в этом сами, запустив d8 (или узел) с флагом --allow-natives-syntax, а затем воспользовавшись специальной функцией %HasFastProperties(bar).

Тем не менее, это внутренняя деталь реализации, которая может со временем измениться. Это не должно быть то, что ваш код должен иметь причины для заботы.

В частности, я не знаю, поэтому ли вы спрашиваете об этом, поэтому я просто хотел бы сказать превентивно, что я настоятельно рекомендую против создать любой пользовательский «форсированный быстрый режим» помощники, которые копируют объекты - по всей вероятности, это сожжет больше времени и памяти, чем экономит, и может внезапно прекратить делать то, что, как вы думаете, делает, даже без вашего ведома.

Более общая картина здесь заключается в том, что «быстрые свойства» и «медленные свойства» являются неправильными. Лучшими терминами были бы «свойства для быстрого чтения» и «свойства для быстрого изменения»: причина, по которой оператор delete (обычно) переводит объект в режим словаря, заключается в том, что добавление и удаление свойств очень много быстрее , когда объект находится в режиме словаря, чем когда он находится в (плохо названном) «режиме быстрого свойства». В большинстве случаев эвристика V8 делает довольно хорошую работу по выбору правильного внутреннего режима для ваших объектов, и вы обычно можете сосредоточиться на написании чистого кода, а не беспокоиться о внутренностях движка.

(Если бы это было так же просто, как иметь «хороший случай» и «плохой случай», то V8 было бы глупо иметь «плохой случай» вообще, и вы бы хотели флаг --always-good-case ( или просто --dont-be-silly), верно? ;-) Реальность такова, что это компромисс: «хорошо для одного» против «хорошо для другого».)

5
задан Paul Stovell 30 January 2009 в 14:33
поделиться

2 ответа

Существует стандартный API для создания подписанных пакетов ZIP.

Система. Пространство имен IO.Packaging содержит необходимые классы для создания OPS (открытая упаковочная спецификация) совместимые пакеты ZIP с цифровыми подписями.

15
ответ дан 18 December 2019 в 05:36
поделиться

Я попробовал предложение aku Системы. IO.Packaging и вполне понравился он, хотя получение подписей работать было довольно трудно и не интуитивно (к моему крохотному уму, так или иначе). Вот шаги, которые я сделал, в случае, если кто-либо еще должен сделать это.

Основным вопросом является документация, просто говорит "сертификаты", но я должен был создать защищенный паролем PFX, чтобы заставить его работать. Две полезных ссылки:

  1. MSDN: Платформа цифровой подписи открытых упаковочных конвенций
  2. Создание самоподписало PFX's

Как вторая ссылка указывает, у Вас есть две опции для создания PFX. Можно создать .cer, установить его и затем экспортировать его с помощью GUI, или можно загрузить pvkimport с Microsoft.

Вот команды, которые я использовал (редактирование: можно использовать OpenSSL, чтобы сделать, это - видит нижнюю часть):

makecert -r -n "CN=Paul Stovell" -b 01/01/2000 -e 01/01/2099 -eku 1.3.6.1.5.5.7.3.3 -sv PaulStovell.pvk PaulStovell.cer
cert2spc PaulStovell.cer PaulStovell.spc
pvkimprt -pfx PaulStovell.spc PaulStovell.pvk

В последней команде появляется мастер. Вас спрашивают, хотите ли Вы экспортировать закрытый ключ, который требует, чтобы PFX был защищен паролем. Выберите "да". Затем существует флажок на следующей странице, спрашивающей, "Экспортировать ли все расширенные свойства", к которому я также выбрал "да".

Это уезжает, Вы с защищенным паролем самоподписали файл PFX, который можно использовать для подписания документов и пакетов с.

Вот некоторый код, чтобы создать, подписать и сохранить пакет, и затем вновь открыть и проверить его.

private const string _digitalSignatureUri = "/package/services/digital-signature/_rels/origin.psdsor.rels";

static void Main(string[] args)
{
    var certificate = new X509Certificate2(@"T:\Sample\Input\PaulStovell.pfx", "password");
    using (var package = Package.Open("T:\\Sample\\MyPackage.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
    {
        CreatePart(package, @"/Files/File2.dll", @"T:\Sample\Input\File2.dll");
        CreatePart(package, @"/Files/File2.pdb", @"T:\Sample\Input\File2.pdb");
        CreatePart(package, @"/Files/File2.xml", @"T:\Sample\Input\File2.xml");
        package.PackageProperties.Creator = "Paul Stovell";
        package.PackageProperties.Title = "Paul Stovell's Package";
        package.PackageProperties.Description = "My First Package";
        package.PackageProperties.Identifier = "MyPackage";
        package.PackageProperties.Version = "1.0.0.0";

        // Sign the package
        var toSign = package.GetParts().Select(part => part.Uri).ToList();
        var uriPartSignatureOriginRelationship = PackUriHelper.CreatePartUri(new Uri(_digitalSignatureUri, UriKind.Relative));
        toSign.Add(uriPartSignatureOriginRelationship);

        var dsm = new PackageDigitalSignatureManager(package);
        dsm.CertificateOption = CertificateEmbeddingOption.InSignaturePart;
        dsm.Sign(toSign, certificate);

        package.Close();
    }

    Console.WriteLine("Package written");
    Console.WriteLine("Reading package");

    using (var package = Package.Open("T:\\Sample\\MyPackage.zip", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        Console.WriteLine("  Package name: {0}", package.PackageProperties.Title);
        var dsm = new PackageDigitalSignatureManager(package);
        if (dsm.IsSigned)
        {
            var verificationResult = dsm.VerifySignatures(false);
            var signature = dsm.Signatures[0];
            Console.WriteLine("  Signed by: {0}", signature.Signer.Subject);
            Console.WriteLine("  Issued by: {0}", signature.Signer.Issuer);
            Console.WriteLine("  Verification: {0}", verificationResult);
        }
        else
        {
            Console.WriteLine("  Not signed.");
        }
    }
    Console.ReadKey();
}

private static void CreatePart(Package package, string relativePath, string file)
{
    var packagePartUri = new Uri(relativePath, UriKind.Relative);
    var packagePart = package.CreatePart(packagePartUri, "part/" + Path.GetExtension(file));
    using (var fileContent = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        CopyStream(fileContent, packagePart.GetStream());
    }
}

private static void CopyStream(Stream source, Stream target)
{
    // It is .NET 3.5, surely this kind of thing has gotten easier by now?
    var bufferSize = 0x1000;
    var buf = new byte[bufferSize];
    int bytesRead = 0;
    while ((bytesRead = source.Read(buf, 0, bufferSize)) > 0)
    {
        target.Write(buf, 0, bytesRead);
    }
}

На моей машине вывод:

Package written
Reading package
  Package name: Paul Stovell's Package
  Signed by: CN=Paul Stovell
  Issued by: CN=Paul Stovell
  Verification: Success

Последняя строка интересна. Это - вывод PackageDigitalSignatureManager. VerifySignatures (). Это указывает, что в документ не вмешались. Если я изменяю или удаляю файл после подписания, это больше не возвращает 'Успех'.

Я скопировал .exe, файлы примера и .pfx, к новой машине и получил тот же самый вывод, который, кажется, указывает, что "Проверяют", только проверяет автора подписи и не спрашивает центров сертификации. Я не устанавливал сертификатов на тестовой машине, и она работает на своем собственном домене.

Править: Код выше только проверяет сам документ, он не проверяет сертификат с помощью корневых полномочий CA. Чтобы сделать это, используйте следующее:

Этот вызов возвращает false при вызове против моего самоподписанного сертификата:

var verified = ((X509Certificate2) dsm.Signatures[0].Signer).Verify();

Затем я дважды щелкаю по .cer, который я раньше создавал .pfx из и устанавливал его в местоположение по умолчанию, так, чтобы это стало доверенным центром сертификации. После того как это сделано, вызов выше возвращает true. Таким образом, это, казалось бы, было бы корректным способом проверить идентификационные данные подписывающего лица.

Редактирование 2: полезное примечание. Для взгляда на и игра с сертификатами на машине сделайте следующее:

  1. Запустите-> Выполнение и введите "mmc"
  2. В окне MMC нажмите File-> Add/Remove SnapIn...
  3. Нажмите Certificates, Add->
  4. Выберите одну из учетных записей
  5. Хит хорошо

В моем случае, когда я дважды щелкнул по .cer выше для установки его, он был помещен под Текущим Пользовательским хранилищем под папкой Trusted Root Certification Authorities. Можно затем удалить его для отмены изменений.

Моя заключительная логика проверки похожа на это:

if (dsm.IsSigned)
{
    var verificationResult = dsm.VerifySignatures(false);
    var signature = dsm.Signatures[0];
    var trusted = ((X509Certificate2)dsm.Signatures[0].Signer).Verify();

    Console.WriteLine("  Signed by: {0}", signature.Signer.Subject);
    Console.WriteLine("  Issued by: {0}", signature.Signer.Issuer);
    Console.WriteLine("  Verified: {0}", verificationResult == VerifyResult.Success);
    Console.WriteLine("  Trusted: {0}", trusted);
}
else
{
    Console.WriteLine("  Not signed.");
}

Где это всегда проверяется (если я не вмешиваюсь в содержание), но только доверял, когда сертификат находится в хранилище.

Редактирование 3: Я сделал немного больше чтения. Файлами PFX является на самом деле PKCS 12 файлов, часть спецификации группой RSA. Более легкий способ создать их, а не что я показал выше, состоит в том, чтобы использовать OpenSSL с открытым исходным кодом, который имеет двоичные файлы в наличии для Windows.

После установки OpenSSL создайте файл пары "открытый/закрытый ключ". Я нашел, что должен был выполнить вторую команду ниже как Администратор, таким образом, она могла бы заплатить для запуска этого как администратора.

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout PaulStovell.pem -out PaulStovell.cer

Это спросит приблизительно 7 дополнительных вопросов о Вас и Вашей организации для создания сертификата. Затем, создайте PKCS 12. Это попросит у Вас пароля:

openssl pkcs12 -export -out PaulStovell.pfx -in PaulStovell.pem -name "Paul Stovell"

Введите и повторно введите свой пароль при запросе.

На данном этапе Система. IO.Packaging может использовать Ваш PFX и проверить подпись пакета, но это не будет доверять сертификату. Для создания .cer сертификата, так, чтобы можно было установить его в хранилище доверенных центров сертификации, делают следующее:

openssl x509 -in PaulStovell.pem -out PaulStovell.cer

Теперь можно дважды щелкнуть по сертификату и установить его, и его будут рассматривать как доверяемый сертификат.

17
ответ дан 18 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: