В данной заметке мы выдадим ЭЦП для произвольной строки. Результатом работы нашей программы будет файл, содержащий подпись в формате openPGP, оформленный по всем стандартам.
Как и в первой статье цикла («OpenPGP для C# .Net (1). Просмотр хранилища ключей») будем использовать библиотеку от «The Legion of the Bouncy Castle».
Вы уже знаете как обращаться с хранилищем секретных ключей:
// путь до хранилища секретных ключей
string path = @"secring_bak.gpg";
// прочитаем хранилище ключей
Stream BundleStream = File.OpenRead(path);
BundleStream = PgpUtilities.GetDecoderStream(BundleStream);
PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(BundleStream);Syhi-подсветка кода
Теперь нужно найти ключ, на котором мы будем подписывать. Напомню, что PGP-ключ состоит из 2-х половинок: секретного и открытого ключей.
Для того чтобы использовать секретную половинку нужно указать пароль доступа. Приведенный ниже код выполняет поиск PGP-ключа и указывает пароль для секретной половинки.
// отыщем ключ по уникальному идентификатору
long keyId = -7764185142489588446;
PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);
// для доступа к секретному ключу нужно указать пароль
string pass = "1";
PgpPrivateKey pgpPrivKey =
pgpSecKey.ExtractPrivateKey(pass.ToCharArray());Syhi-подсветка кода
Далее следует создать объект генератора подписи, предварительно выбрав алгоритм хеширования:
// для генерации подписи нужно выбрать
// функцию хеширования, в данном случае Sha1
HashAlgorithmTag digest = HashAlgorithmTag.Sha1;
// создадим объект генератора подписи
PgpSignatureGenerator sGen = new PgpSignatureGenerator(
pgpSecKey.PublicKey.Algorithm, digest);
sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);Syhi-подсветка кода
На этом подготовительные операции заканчиваются. Определим строку, которую хотим подписать, а также файл для хранения подписи в нужном формате. Корректность подписи из такого файла можно проверить стандартными средствами, например для windows можно использовать winPT.
// строку, которую будем подписывать,
// необходимо представить в виде массива байт
string str = "12привет";
byte[] byteStr = Encoding.UTF8.GetBytes(str);
// файл для хранения прозрачной подписи
Stream fos = File.Create("my_sign.asc");
// непосредственно подписание
sGen.Update(byteStr);
// формирование файла, нужного вида
ArmoredOutputStream aOut = new ArmoredOutputStream(fos);
aOut.BeginClearText(digest);
aOut.Write(byteStr);
aOut.Write((byte)'\r');
aOut.Write((byte)'\n');
aOut.EndClearText();
BcpgOutputStream bOut = new BcpgOutputStream(aOut);
sGen.Generate().Encode(bOut);Syhi-подсветка кода
Собирем весь код вместе:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("**Подпишим строку**\n");
// путь до хранилища секретных ключей
string path = @"secring_bak.gpg";
// прочитаем хранилище ключей
Stream BundleStream = File.OpenRead(path);
BundleStream =
PgpUtilities.GetDecoderStream(BundleStream);
PgpSecretKeyRingBundle pgpSec =
new PgpSecretKeyRingBundle(BundleStream);
// отыщем ключ по уникальному идентификатору
long keyId = -7764185142489588446;
PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);
// для доступа к секретному ключу нужно указать пароль
string pass = "pass";
PgpPrivateKey pgpPrivKey =
pgpSecKey.ExtractPrivateKey(pass.ToCharArray());
// для генерации подписи нужно выбрать
// функцию хеширования, в данном случаи Sha1
HashAlgorithmTag digest = HashAlgorithmTag.Sha1;
PgpSignatureGenerator sGen = new PgpSignatureGenerator(
pgpSecKey.PublicKey.Algorithm, digest);
sGen.InitSign(
PgpSignature.CanonicalTextDocument, pgpPrivKey);
// строку, которую будем подписывать,
// необходимо представить в виде массива байт
string str = "12привет";
byte[] byteStr = Encoding.UTF8.GetBytes(str);
// файл для хранения прозрачной подписи
Stream fos = File.Create("my_sign.asc");
// непосредственно подписание
sGen.Update(byteStr);
// формирование файла, нужного вида
ArmoredOutputStream aOut = new ArmoredOutputStream(fos);
aOut.BeginClearText(digest);
aOut.Write(byteStr);
aOut.Write((byte)'\r');
aOut.Write((byte)'\n');
aOut.EndClearText();
BcpgOutputStream bOut = new BcpgOutputStream(aOut);
sGen.Generate().Encode(bOut);
aOut.Close();
fos.Close();
Console.ReadLine();
}}}Syhi-подсветка кода
В итоге у нас получился файл следующего вида:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
12привет
-----BEGIN PGP SIGNATURE-----
Version: BCPG v1.32
iEYEARECAAYFAkd2NP0ACgkQlEASv9OK3SL0+wCeNq2PKsTZcGmJzbixpcMx8N1J
bSIAoKX9ERFgDOJaPO6FWm1OcBGbudaV
=Hw18
-----END PGP SIGNATURE-----