1

我目前正在开发一个应用程序,该应用程序将创建一个文本文件,使用 PGP 公钥(不是文件,而是十六进制数字和 pgp 名称)加密文件,并按计划将其发布到 FTP。我发布信息的人需要对文件进行 PGP 加密并共享公钥(不是文件,而是十六进制数字和 pgp 名称)。

我卡住的地方是PGP加密部分。我看到了有关如何使用 bouncy castle 库使用公钥文件或公钥环(我理解为一组密钥)加密文本文件的示例。但我拥有的信息是一个 32 位十六进制密钥和一个 PGP 名称。我不确定如何使用这些信息来加密文件。我应该要求对方给我发送公钥文件吗?是否可以根据我拥有的信息创建公钥文件?我对 PGP 加密非常陌生,并且在经过大量谷歌搜索后发布了这个,但没有提供任何信息,所以请帮忙。

这是我迄今为止加密文件的代码。如您所见,代码将文件作为公钥的输入,而不是十六进制代码和名称。我的问题真的是,是否甚至可以使用 pgp 名称和十六进制数字进行 pgp 加密?

public class PGPHelper
{
    private PgpEncryptionKeys m_encryptionKeys;
    private const int BufferSize = 0x10000;
    /// <summary>
    /// Instantiate a new PgpEncrypt class with initialized PgpEncryptionKeys.
    /// </summary>
    /// <param name="encryptionKeys"></param>
    /// <exception cref="ArgumentNullException">encryptionKeys is null</exception>
    public PGPHelper(PgpEncryptionKeys encryptionKeys)
    {
        if (encryptionKeys == null)
        {
            throw new ArgumentNullException("encryptionKeys", "encryptionKeys is null.");
        }
        m_encryptionKeys = encryptionKeys;
    }
    /// <summary>
    /// Encrypt and sign the file pointed to by unencryptedFileInfo and
    /// write the encrypted content to outputStream.
    /// </summary>
    /// <param name="outputStream">The stream that will contain the
    /// encrypted data when this method returns.</param>
    /// <param name="fileName">FileInfo of the file to encrypt</param>
    public void Encrypt(Stream outputStream, FileInfo unencryptedFileInfo)
    {
        if (outputStream == null)
        {
            throw new ArgumentNullException("outputStream", "outputStream is null.");
        }
        if (unencryptedFileInfo == null)
        {
            throw new ArgumentNullException("unencryptedFileInfo", "unencryptedFileInfo is null.");
        }
        if (!File.Exists(unencryptedFileInfo.FullName))
        {
            throw new ArgumentException("File to encrypt not found.");
        }
        using (Stream encryptedOut = ChainEncryptedOut(outputStream))
        {
            using (Stream literalOut = ChainLiteralOut(encryptedOut, unencryptedFileInfo))
            using (FileStream inputFile = unencryptedFileInfo.OpenRead())
            {
                WriteOutput(literalOut, inputFile);
            }
        }
    }

    private static void WriteOutput(Stream literalOut,
        FileStream inputFile)
    {
        int length = 0;
        byte[] buf = new byte[BufferSize];
        while ((length = inputFile.Read(buf, 0, buf.Length)) > 0)
        {
            literalOut.Write(buf, 0, length);
        }
    }

    private Stream ChainEncryptedOut(Stream outputStream)
    {
        PgpEncryptedDataGenerator encryptedDataGenerator;
        encryptedDataGenerator =
            new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes, new SecureRandom());
        encryptedDataGenerator.AddMethod(m_encryptionKeys.PublicKey);
        return encryptedDataGenerator.Open(outputStream, new byte[BufferSize]);
    }

    private static Stream ChainLiteralOut(Stream encryptedOut, FileInfo file)
    {
        PgpLiteralDataGenerator pgpLiteralDataGenerator = new PgpLiteralDataGenerator();
        return pgpLiteralDataGenerator.Open(encryptedOut, PgpLiteralData.Binary, file);
    }

}

public class PgpEncryptionKeys
{

    public PgpPublicKey PublicKey { get; private set; }

    /// <summary>
    /// Initializes a new instance of the EncryptionKeys class.
    /// Two keys are required to encrypt and sign data. Your private key and the recipients public key.
    /// The data is encrypted with the recipients public key and signed with your private key.
    /// </summary>
    /// <param name="publicKeyPath">The key used to encrypt the data</param>
    /// <exception cref="ArgumentException">Public key not found. Private key not found. Missing password</exception>
    public PgpEncryptionKeys(string publicKeyPath, string privateKeyPath, string passPhrase)
    {
        if (!File.Exists(publicKeyPath))
        {
            throw new ArgumentException("Public key file not found", "publicKeyPath");
        }
        PublicKey = ReadPublicKey(publicKeyPath);
    }

    #region Public Key

    private PgpPublicKey ReadPublicKey(string publicKeyPath)
    {
        using (Stream keyIn = File.OpenRead(publicKeyPath))
        using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
        {
            PgpPublicKeyRingBundle publicKeyRingBundle = new PgpPublicKeyRingBundle(inputStream);
            PgpPublicKey foundKey = GetFirstPublicKey(publicKeyRingBundle);
            if (foundKey != null)
            {
                return foundKey;
            }
        }
        throw new ArgumentException("No encryption key found in public key ring.");
    }

    private PgpPublicKey GetFirstPublicKey(PgpPublicKeyRingBundle publicKeyRingBundle)
    {
        foreach (PgpPublicKeyRing kRing in publicKeyRingBundle.GetKeyRings())
        {
            PgpPublicKey key = kRing.GetPublicKeys()
                .Cast<PgpPublicKey>()
                .Where(k => k.IsEncryptionKey)
                .FirstOrDefault();

            if (key != null)
            {
                return key;
            }
        }
        return null;
    }

    #endregion
4

0 回答 0