C#如何使用PGP公钥简单地加密文本文件?

时间:2010-11-16 08:33:23

标签: c# encryption public-key pgp public-key-encryption

我已经研究了一些关于如何实现我在问题中所说的内容并找到了几个API,但是大多数API看起来非常复杂,因为我只是这个领域的一个noobie我只想要一个简单的方法,如: / p>

public String Encrypt(String message, PublicKey publicKey)

不知道是否可以这样做?如果没有那么请有人告诉我另一种方法来实现这一点:)

谢谢。

更新:

到目前为止,我只看到所有用于OpenPGP加密的库都需要公钥和私钥来进行加密,而我只想用公钥加密(因为我没有私钥到用它)!

6 个答案:

答案 0 :(得分:8)

我找到了一个教程here,但它需要密钥和公钥来加密数据。然而,我已经修改了一些代码只需要公钥(没有签名,没有压缩),并认为我应该在这里发布它,以防有人也在寻找这个问题的解决方案。 Belows是修改后的代码,是作者的所有学分 - 金先生。

public class PgpEncrypt
    {
        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 PgpEncrypt(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);
            } 
}

当然要运行这些代码,您必须在项目中加入BouncyCastle library 我已经测试了加密然后解密,它运行良好:)

答案 1 :(得分:7)

这可能是一种更清洁的方法:


        var pkr = asciiPublicKeyToRing(ascfilein);
        if (pkr != null)
        {
            try
            {
                EncryptFile(
                tbUnencryptedFile.Text, tbEncryptedFile.Text, getFirstPublicEncryptionKeyFromRing(pkr), true, true);

                MessageBox.Show("File Encrypted.");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }
        else
        {
             MessageBox.Show(ascfilein + " is not a public key.");
        }

    private PgpPublicKeyRing asciiPublicKeyToRing(string ascfilein)
    {
        using (Stream pubFis = File.OpenRead(ascfilein))
        {
            var pubArmoredStream = new ArmoredInputStream(pubFis);

            PgpObjectFactory pgpFact = new PgpObjectFactory(pubArmoredStream);
            Object opgp = pgpFact.NextPgpObject();
            var pkr = opgp as PgpPublicKeyRing;
            return pkr;
        }
    }

    private PgpPublicKey getFirstPublicEncryptionKeyFromRing(PgpPublicKeyRing pkr)
    {
        foreach (PgpPublicKey k in pkr.GetPublicKeys())
        {
            if (k.IsEncryptionKey)
                return k;
        }
        throw new ArgumentException("Can't find encryption key in key ring.");
    }

    public static void EncryptFile(string inputFile, string outputFile, PgpPublicKey encKey, bool armor,
        bool withIntegrityCheck)
    {
        using (MemoryStream bOut = new MemoryStream())
        {
            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
            PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary,
                new FileInfo(inputFile));

            comData.Close();
            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Aes256,
                withIntegrityCheck, new SecureRandom());

            cPk.AddMethod(encKey);
            byte[] bytes = bOut.ToArray();

            using (Stream outputStream = File.Create(outputFile))
            {
                if (armor)
                {
                    using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(outputStream))
                    using (Stream cOut = cPk.Open(armoredStream, bytes.Length))
                    {
                        cOut.Write(bytes, 0, bytes.Length);
                    }
                }
                else
                {
                    using (Stream cOut = cPk.Open(outputStream, bytes.Length))
                    {
                        cOut.Write(bytes, 0, bytes.Length);
                    }
                }
            }
        }
    }

答案 2 :(得分:6)

你看过bouncycastle pgp了吗? http://www.bouncycastle.org/

此处有一个源代码示例,其中包含从BouncyCastle网站获取的文件:Need example for BouncyCastle PGP File encryption in C#

答案 3 :(得分:4)

有一篇关于代码项目http://www.codeproject.com/KB/security/sharpprivacy.aspx?df=100&forumid=15716&exp=0&select=573797的文章,它有方法:

public static string EncryptText(string strMessage, PublicKeyRing pkrPublicKeyRing, SecretKeyRing skrSecretKeyRing, bool bSign
private static void DecryptAndVerify(SecretKeyRing skrSecretKeyRing, PublicKeyRing pkrPublicKeyRing, byte[] bData)

这可能是您正在寻找的,或者至少指出您正确的方向来编写自己的。

答案 4 :(得分:1)

如果您正在寻找一个简单的dotnet库来进行pgp加密,请查看PgpCore。它是Bouncy Castle的包装材料-使其比需要了解Bouncy Castle的内部要容易一些。

答案 5 :(得分:1)

如果要在dotnet核心中同时进行加密和解密,这是我关注的文章:https://nightbaker.github.io/pgp/cryptography/.net/core/2019/02/08/pgp-encryption/

加密部分不需要私钥。

所有版权归原始作者NightBaker所有。

Install-Package  BouncyCastle.NetCore
Install-Package  BouncyCastle.NetCoreSdk
public class Pgp
{
    public static void EncryptFile(
        string outputFileName,
        string inputFileName,
        string encKeyFileName,
        bool armor,
        bool withIntegrityCheck)
    {
        PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName);

        using (Stream output = File.Create(outputFileName))
        {
            EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck);
        }
    }

    private static void EncryptFile(
        Stream outputStream,
        string fileName,
        PgpPublicKey encKey,
        bool armor,
        bool withIntegrityCheck)
    {
        if (armor)
        {
            outputStream = new ArmoredOutputStream(outputStream);
        }

        try
        {
            byte[] bytes = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip);

            PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(
                SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
            encGen.AddMethod(encKey);

            Stream cOut = encGen.Open(outputStream, bytes.Length);

            cOut.Write(bytes, 0, bytes.Length);
            cOut.Close();

            if (armor)
            {
                outputStream.Close();
            }
        }
        catch (PgpException e)
        {
            Console.Error.WriteLine(e);

            Exception underlyingException = e.InnerException;
            if (underlyingException != null)
            {
                Console.Error.WriteLine(underlyingException.Message);
                Console.Error.WriteLine(underlyingException.StackTrace);
            }
        }
    }
}

public class PgpExampleUtilities
{
    internal static PgpPublicKey ReadPublicKey(string fileName)
    {
        using (Stream keyIn = File.OpenRead(fileName))
        {
            return ReadPublicKey(keyIn);
        }
    }

    internal static PgpPublicKey ReadPublicKey(Stream input)
    {
        PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(
            PgpUtilities.GetDecoderStream(input));

        //
        // we just loop through the collection till we find a key suitable for encryption, in the real
        // world you would probably want to be a bit smarter about this.
        //

        foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings())
        {
            foreach (PgpPublicKey key in keyRing.GetPublicKeys())
            {
                if (key.IsEncryptionKey)
                {
                    return key;
                }
            }
        }

        throw new ArgumentException("Can't find encryption key in key ring.");
    }


    internal static byte[] CompressFile(string fileName, CompressionAlgorithmTag algorithm)
    {
        MemoryStream bOut = new MemoryStream();
        PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm);
        PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary,
            new FileInfo(fileName));
        comData.Close();
        return bOut.ToArray();
    }
}

用法:

Pgp.EncryptFile("Resources/output.txt", "Resources/input.txt", "Resources/publicKey.txt", true, true);