web-dev-qa-db-ja.com

C#PGP公開鍵でテキストファイルを単純に暗号化する方法は?

私は質問で私が言ったことを達成する方法について少し調査し、いくつかのAPIを見つけましたが、それらのほとんどは非常に複雑に見え、私はこの分野の初心者なので、次のような簡単な方法が欲しいだけです:

public String Encrypt(String message, PublicKey publicKey)

これが可能かどうか分からないのですか?そうでない場合は、誰かにこれを達成する別の方法を教えてください:)

ありがとうございました。

更新:

これまでのところ、OpenPGP暗号化のすべてのライブラリーで暗号化を行うには公開鍵と秘密鍵の両方が必要であることがわかりましたが、公開鍵で暗号化したいだけです(使用する秘密鍵がないためです)。 !

21
Leo

私はチュートリアル here を見つけましたが、データを暗号化するには秘密鍵と公開鍵の両方が必要です。ただし、公開鍵のみを必要とするようにコードを少し変更しました(署名なし、圧縮なし)。この質問の解決策も探している場合に備えて、ここに公開する必要があると考えました。以下は、修正されたコードであり、作者のすべてのクレジットです-キム氏。

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ライブラリ を含める必要があります。
私は暗号化とそれから復号化をテストしました、そしてそれはうまく動きます:)

11
Leo

これはおそらくよりクリーンなアプローチです:


        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);
                    }
                }
            }
        }
    }
9
azpc

バウンシーキャッスルのpgpをご覧になりましたか? http://www.bouncycastle.org/

BouncyCastleサイトから取得したファイルを暗号化するソースの例があります: C#でのBouncyCastle PGPファイル暗号化の例が必要です

6
kyndigs

コードプロジェクトに関する記事があります 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
JLWarlow