web-dev-qa-db-fra.com

C # Comment chiffrer simplement un fichier texte avec une clé publique PGP?

J'ai fait des recherches sur la façon de réaliser ce que j'ai dit dans la question et j'ai trouvé plusieurs API, mais la plupart d'entre elles ont l'air très compliquées et comme je suis juste un noobie dans ce domaine, je veux juste une méthode simple comme:

public String Encrypt(String message, PublicKey publicKey)

Je ne sais pas si cela peut être fait? Sinon, s'il vous plaît, quelqu'un m'éclairera d'une autre façon d'y parvenir :)

Je vous remercie.

METTRE À JOUR:

Jusqu'à présent, j'ai seulement vu que toute la bibliothèque pour le cryptage OpenPGP nécessite à la fois la clé publique et la clé privée pour effectuer le cryptage alors que je veux seulement crypter avec la clé publique (parce que je n'ai pas la clé privée pour l'utiliser) !

21
Leo

J'ai trouvé un tutoriel ici mais il nécessite à la fois une clé secrète et une clé publique pour crypter les données. Cependant, j'ai un peu modifié les codes pour ne nécessiter que la clé publique (pas de signature, pas de compression) et j'ai pensé que je devrais le publier ici au cas où quelqu'un chercherait également une solution à cette question. Belows est les codes modifiés, tous les crédits pour l'auteur - M. Kim.

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

Bien sûr, pour exécuter ces codes, vous devez inclure bibliothèque BouncyCastle dans votre projet.
J'ai testé le cryptage puis le décryptage et ça fonctionne bien :)

11
Leo

Voici peut-être une approche plus propre:


        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

Avez-vous jeté un coup d'œil au pgp de bouncycastle? http://www.bouncycastle.org/

Il existe un exemple source de cryptage d'un fichier provenant du site BouncyCastle: Besoin d'un exemple pour le cryptage du fichier PGP BouncyCastle en C #

6
kyndigs

Il y a un article sur le projet de code http://www.codeproject.com/KB/security/sharpprivacy.aspx?df=100&forumid=15716&exp=0&select=573797 , qui a des méthodes:

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

Ce qui peut être ce que vous recherchez, ou du moins vous orienter dans la bonne direction pour écrire le vôtre.

4
JLWarlow