Мы шифруем файл для клиента с помощью BouncyCastle API. Он получает сообщение «Только для ваших глаз» от PGP при попытке расшифровать его. Почему?

#c# #encryption #pgp #gnupg

#c# #шифрование #pgp #gnupg

Вопрос:

Мы используем Bouncy.Castle C # API для выполнения шифрования PGP. Я ни в коем случае не эксперт по PGP-шифрованию и различным доступным вариантам.

Кажется, что шифрование выполняется нормально, однако, когда клиент пытается расшифровать его, он говорит, что PGP не будет выводить в файл, а только на экран, потому что он помечен как «Только для ваших глаз». Это сообщение —verbose:

 pgp --decrypt Client_FileExport_20110510_020011.zip.pgp
  Client_FileExport_20110511_132203.zip.pgp --info verbose

McAfee E-Business Server v8.5 - Full License
(c) 1991-2006 McAfee, Inc.  All Rights Reserved.

Setting temporary directory to C:DOCUME~1$963LOCALS~1Temp
Decoding data....

event 1: initial
event 13: BeginLex
event 8: Analyze
File is encrypted.  event 9: Recipients
Secret key is required to read it.
Key for user ID "Client_RSAv4_Key <Bob.Smith@Client.com>"
event 6: Passphrase
You need a pass phrase to unlock your secret key.

Enter pass phrase:

event 23: Decryption

symmetric cipher used: CAST5
event 11: Output options
typecode: 0062
for your eyes only


This message is marked "For your eyes only".  Display now (Y/n)?
  

Я понятия не имею, как приступить к отладке этого. Кто-нибудь знает?

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

 private void EncryptImpl(Stream inputStream, Stream outputStream, bool signOutput)
    {
        const int BUFFER_SIZE = 1 << 16; // should always be power of 2
        bool armor = true;
        bool withIntegrityCheck = true;

        if (armor)
            outputStream = new ArmoredOutputStream(outputStream);

        var encKey = PgpHelper.ReadPublicKey(this.EncryptionPublicKey);

        // Init encrypted data generator
        PgpEncryptedDataGenerator encryptedDataGenerator =
            new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
        encryptedDataGenerator.AddMethod(encKey);
        Stream encryptedOut = encryptedDataGenerator.Open(outputStream, new byte[BUFFER_SIZE]);

        // Init compression
        PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
        Stream compressedOut = compressedDataGenerator.Open(encryptedOut);

        PgpSignatureGenerator signatureGenerator = null;
        if (signOutput)
        {
            // Init signature
            var pgpSecKey = PgpHelper.ReadSecretKey(this.OrigamiSecretKey);
            PgpPrivateKey pgpPrivKey = pgpSecKey.ExtractPrivateKey(this.PassPhrase.ToCharArray());
            signatureGenerator = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
            signatureGenerator.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
            foreach (string userId in pgpSecKey.PublicKey.GetUserIds())
            {
                PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
                spGen.SetSignerUserId(false, userId);
                signatureGenerator.SetHashedSubpackets(spGen.Generate());
                // Just the first one!
                break;
            }
            signatureGenerator.GenerateOnePassVersion(false).Encode(compressedOut);
        }

        // Create the Literal Data generator output stream
        PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator();

        // TODO: Use lastwritetime from source file
        Stream literalOut = literalDataGenerator.Open(compressedOut, PgpLiteralData.Binary,
            PgpLiteralDataGenerator.Console, DateTime.Now, new byte[BUFFER_SIZE]);

        // Open the input file
        byte[] buf = new byte[BUFFER_SIZE];
        int len;
        while ((len = inputStream.Read(buf, 0, buf.Length)) > 0)
        {
            literalOut.Write(buf, 0, len);

            if (signOutput)
                signatureGenerator.Update(buf, 0, len);
        }

        literalOut.Close();
        literalDataGenerator.Close();

        if (signOutput)
            signatureGenerator.Generate().Encode(compressedOut);

        compressedOut.Close();
        compressedDataGenerator.Close();
        encryptedOut.Close();
        encryptedDataGenerator.Close();
        inputStream.Close();

        if (armor)
            outputStream.Close();
    }
  

Ответ №1:

Я предполагаю, что это PgpLiteralDataGenerator.Консоль — это то, из-за чего он отображается только в консоли клиентского компьютера.

 Stream literalOut = literalDataGenerator.Open(
    compressedOut, 
    PgpLiteralData.Binary,             
    PgpLiteralDataGenerator.Console,
    DateTime.Now, 
    new byte[BUFFER_SIZE]);
  

Комментарии:

1. Возможно, это оно. Спасибо! Я изучу это.

2. зашифрованные данные происходят из файла? Вы могли бы поместить имя файла вместо PgpLiteralDataGenerator. КОНСОЛЬ

3. Да, в данном случае это так, так что это то, что я пытаюсь. В случае, когда оно не исходит из файла — возможно, просто из входного потока, есть ли типичное значение для этого параметра, отличное от _Console? Безопасно ли указывать имя файла-заполнителя типа «Contents»?

4. Замена PgpLiteralDataGenerator. Консоль с именем файла, который мы шифруем, устранила проблему для клиента.

Ответ №2:

Это сообщение отображается, когда зашифрованный файл не содержит имени исходного файла. Если вы не шифруете файл, вы можете поместить в это поле практически все, что угодно (учитывая, что оно представляет собой имя файла, действительное для целевой системы).