PGP加密和解密 [英] PGP Encrypt and Decrypt

查看:220
本文介绍了PGP加密和解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很努力,我需要使用C#中的BouncyCastle加密和解密一个字符串。
我真的试图自己做这个。
我设法创建自己的密钥(私人和公共)。



请记住,我刚出院。

解决方案

p>花了我一段时间找到一个体面的例子,使用弹性城堡为PGP。这是我在生产中使用的。我很确定它源于 here

  using System; 
使用System.IO;
使用Org.BouncyCastle.Bcp​​g;
使用Org.BouncyCastle.Bcp​​g.OpenPgp;
使用Org.BouncyCastle.Security;
使用Org.BouncyCastle.Utilities.IO;

命名空间FileEncryptionTasks.Helpers.PGP
{
public static class PGPEncryptDecrypt
{
private const int BufferSize = 0x10000; //应该永远是2

#region加密

/ *
*加密文件。
* /

public static void EncryptFile(string inputFile,string outputFile,string publicKeyFile,bool armor,bool withIntegrityCheck)
{
try
{
using(Stream publicKeyStream = File.OpenRead(publicKeyFile))
{
PgpPublicKey encKey = ReadPublicKey(publicKeyStream);

使用(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.Cast5,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);
}
}
}
}
}
}
catch(PgpException e)
{
throw;
}
}

#endregion加密

#region加密并签署

/ *
*加密并签署unencryptedFileInfo指向的文件和
* /

public static void EncryptAndSign(string inputFile,string outputFile,string publicKeyFile,string privateKeyFile,string passPhrase,bool armor)
{
PgpEncryptionKeys encryptionKeys = new PgpEncryptionKeys(publicKeyFile,privateKeyFile,passPhrase);

if(!File.Exists(inputFile))
throw new FileNotFoundException(String.Format(Input file [{0}]不存在,inputFile));

如果(!File.Exists(publicKeyFile))
抛出新的FileNotFoundException(String.Format(公钥文件[{0}]不存在,publicKeyFile));

如果(!File.Exists(privateKeyFile))
抛出新的FileNotFoundException(String.Format(私钥文件[{0}]不存在,privateKeyFile));

if(String.IsNullOrEmpty(passPhrase))
throw new ArgumentNullException(Invalid Pass Phrase);

if(encryptionKeys == null)
throw new ArgumentNullException(Encryption Key not found。);

using(Stream outputStream = File.Create(outputFile))
{
if(armor)
using(ArmoredOutputStream armoredOutputStream = new ArmoredOutputStream(outputStream))
{
OutputEncrypted(inputFile,armoredOutputStream,encryptionKeys);
}
else
OutputEncrypted(inputFile,outputStream,encryptionKeys);



private static void OutputEncrypted(string inputFile,Stream outputStream,PgpEncryptionKeys encryptionKeys)
{
using(Stream encryptedOut = ChainEncryptedOut(outputStream, encryptionKeys))
{
FileInfo unencryptedFileInfo = new FileInfo(inputFile);
using(Stream compressedOut = ChainCompressedOut(encryptedOut))
{
PgpSignatureGenerator signatureGenerator = InitSignatureGenerator(compressedOut,encryptionKeys);
using(Stream literalOut = ChainLiteralOut(compressedOut,unencryptedFileInfo))
{
using(FileStream inputFileStream = unencryptedFileInfo.OpenRead())
{
WriteOutputAndSign(compressedOut,literalOut ,inputFileStream,signatureGenerator);
inputFileStream.Close();
$



$ b private static void WriteOutputAndSign(Stream compressedOut,Stream literalOut,FileStream inputFile,PgpSignatureGenerator signatureGenerator)
{
int length = 0;
byte [] buf = new byte [BufferSize];
while((length = inputFile.Read(buf,0,buf.Length))> 0)
{
literalOut.Write(buf,0,length);
signatureGenerator.Update(buf,0,length);
}
signatureGenerator.Generate()。Encode(compressedOut);
}

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

private static Stream ChainCompressedOut(Stream encryptedOut)
{
PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
return compressedDataGenerator.Open(encryptedOut);
}

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

private static PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut,PgpEncryptionKeys m_encryptionKeys)
{
const bool IsCritical = false;
const bool IsNested = false;
PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;
PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(tag,HashAlgorithmTag.Sha1);
pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument,m_encryptionKeys.PrivateKey);
foreach(m_encryptionKeys.SecretKey.PublicKey.GetUserIds()中的string userId)
{
PgpSignatureSubpacketGenerator subPacketGenerator = new PgpSignatureSubpacketGenerator();
subPacketGenerator.SetSignerUserId(IsCritical,userId);
pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());
//只是第一个!
break;
}
pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);
return pgpSignatureGenerator;
}

#endregion加密并签署

#region解密

/ *
*解密给定的流。
* /

public static void Decrypt(string inputfile,string privateKeyFile,string passPhrase,string outputFile)
{
if(!File.Exists(inputfile))
抛出新的FileNotFoundException(String.Format(Encrypted File [{0}] not found。,inputfile));

if(!File.Exists(privateKeyFile))
throw new FileNotFoundException(String.Format(Private Key File [{0}] not found。,privateKeyFile));

if(String.IsNullOrEmpty(outputFile))
throw new ArgumentNullException(Invalid Output file path);

使用(Stream inputStream = File.OpenRead(inputfile))
{
using(Stream keyIn = File.OpenRead(privateKeyFile))
{
解密(inputStream,keyIn,passPhrase,outputFile);
}
}
}

/ *
*解密给定的流。
* /

public static void Decrypt(Stream inputStream,Stream privateKeyStream,string passPhrase,string outputFile)
{
try
{
PgpObjectFactory pgpF = null;
PgpEncryptedDataList enc = null;
PgpObject o = null;
PgpPrivateKey sKey = null;
PgpPublicKeyEncryptedData pbe = null;
PgpSecretKeyRingBundle pgpSec = null;

pgpF = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream));
//找到密钥
pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream));

if(pgpF!= null)
o = pgpF.NextPgpObject();

//第一个对象可能是PGP标记数据包。
if(o是PgpEncryptedDataList)
enc =(PgpEncryptedDataList)o;
else
enc =(PgpEncryptedDataList)pgpF.NextPgpObject();

//解密
foreach(pgpPublicKeyEncryptedData在enc.GetEncryptedDataObjects()中打)
{
sKey = FindSecretKey(pgpSec,pked.KeyId,passPhrase.ToCharArray() );

if(sKey!= null)
{
pbe = pked;
break;
}
}

if(sKey == null)
throw new ArgumentException(未找到消息的秘密密钥);

PgpObjectFactory plainFact = null;

using(Stream clear = pbe.GetDataStream(sKey))
{
plainFact = new PgpObjectFactory(clear);
}

PgpObject message = plainFact.NextPgpObject();

if(message is PgpCompressedData)
{
PgpCompressedData cData =(PgpCompressedData)message;
PgpObjectFactory of = null;

using(Stream compDataIn = cData.GetDataStream())
{
of = new PgpObjectFactory(compDataIn);
}

message = of.NextPgpObject();
if(message is PgpOnePassSignatureList)
{
message = of.NextPgpObject();
PgpLiteralData Ld = null;
Ld =(PgpLiteralData)消息;
using(Stream output = File.Create(outputFile))
{
Stream unc = Ld.GetInputStream();
Streams.PipeAll(unc,output);
}
}
else
{
PgpLiteralData Ld = null;
Ld =(PgpLiteralData)消息;
using(Stream output = File.Create(outputFile))
{
Stream unc = Ld.GetInputStream();
Streams.PipeAll(unc,output);
}
}
}
else if(message is PgpLiteralData)
{
PgpLiteralData ld =(PgpLiteralData)message;
string outFileName = ld.FileName;

使用(Stream fOut = File.Create(outputFile))
{
Stream unc = ld.GetInputStream();
Streams.PipeAll(unc,fOut);
}
}
else if(message is PgpOnePassSignatureList)
throw new PgpException(Encrypted message contains a signed message - not literal data。);
else
throw new PgpException(Message is not a simple encrypted file - type unknown。);

#region注释代码

// if(pbe.IsIntegrityProtected())
// {
// if(!pbe.Verify ))
// msg =消息失败完整性检查。
// //Console.Error.WriteLine(message failed integrity check);
// else
// msg =消息完整性检查已通过。
// //Console.Error.WriteLine(message integrity check passed);
//}
// else
// {
// msg =no message integrity check。
// //Console.Error.WriteLine(no message integrity check);
//}

#endregion注释码
}
catch(PgpException ex)
{
throw;
}
}

#endregion解密

#region私人助理

/ *
*一个简单的例程打开一个密钥环文件并加载适合加密的第一个可用密钥。
* /

私有静态PgpPublicKey ReadPublicKey(Stream inputStream)
{
inputStream = PgpUtilities.GetDecoderStream(inputStream);

PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);

//我们只是循环收集,直到我们找到一个适合加密的密钥,在真正的
// world中,你可能会想要更聪明一点。
//遍历密钥环。
foreach(pgpPublicKeyRing kRing in pgpPub.GetKeyRings())
{
foreach(pgpPublicKey k in kRing.GetPublicKeys())
{
if(k.IsEncryptionKey)
return k;
}
}

throw new ArgumentException(在密钥环中找不到加密密钥);
}

/ *
*搜索与keyId相对应的密钥的秘密密钥环集合(如果存在)。
* /

private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec,long keyId,char [] pass)
{
PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);

if(pgpSecKey == null)
return null;

返回pgpSecKey.ExtractPrivateKey(pass);
}

#endregion私人助理
}
}

它使用:

  using System; 
使用System.IO;
使用System.Linq;
使用Org.BouncyCastle.Bcp​​g.OpenPgp;

命名空间FileEncryptionTasks.Helpers.PGP
{
public class PgpEncryptionKeys
{
public PgpPublicKey PublicKey {get;私人集合}

public PgpPrivateKey PrivateKey {get;私人集合}

public PgpSecretKey SecretKey {get;私人集合}

///< summary>
///初始化EncryptionKeys类的新实例。
///需要两个密钥来加密和签署数据。您的私钥和收件人公钥。
///数据使用收件人公钥加密,并用您的私钥签名。
///< / summary>
///< param name =publicKeyPath>用于加密数据的密钥< / param>
///< param name =privateKeyPath>用于对数据进行签名的密钥。< / param>
///< param name =passPhrase>访问私有密钥所需的(您的)密码< / param>
///< exception cref =ArgumentException>未找到公钥。找不到私钥。缺少密码< / exception>
public PgpEncryptionKeys(string publicKeyPath,string privateKeyPath,string passPhrase)
{
if(!File.Exists(publicKeyPath))
throw new ArgumentException(未找到公钥文件 ,publicKeyPath);
if(!File.Exists(privateKeyPath))
throw new ArgumentException(Private key file not found,privateKeyPath);
if(String.IsNullOrEmpty(passPhrase))
throw new ArgumentException(passPhrase为null或空,passPhrase);
PublicKey = ReadPublicKey(publicKeyPath);
SecretKey = ReadSecretKey(privateKeyPath);
PrivateKey = ReadPrivateKey(passPhrase);
}

#region Secret Key

private PgpSecretKey ReadSecretKey(string privateKeyPath)
{
using(Stream keyIn = File.OpenRead( privateKeyPath))
{
using(Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
{
PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
if(foundKey!= null)
return foundKey;
}
}
抛出新的ArgumentException(在密钥环中找不到签名密钥);
}

///< summary>
///返回我们可以用来加密的第一个密钥。
///注意:文件可以包含多个密钥(存储在密钥环中)
///< / summary>
private PgpSecretKey GetFirstSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
{
foreach(PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings())
{
PgpSecretKey key = kRing.GetSecretKeys()
.Cast< PgpSecretKey>()
.Where(k => k.IsSigningKey)
.FirstOrDefault();
if(key!= null)
return key;
}
返回null;
}

#endregion秘密密钥

#region公钥

私有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(在公钥环中找不到加密密钥);
}

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;
}
返回null;
}

#endregion公钥

#region私钥

私有PgpPrivateKey ReadPrivateKey(string passPhrase)
{
PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());
if(privateKey!= null)
return privateKey;
throw new ArgumentException(在密钥中找不到私钥);
}

#endregion私钥
}
}

加密文件:

  PGPEncryptDecrypt.EncryptFile(inputFileName,
outputFileName,
recipientKeyFileName,
shouldArmor,
shouldCheckIntegrity);

解密文件:

  PGPEncryptDecrypt.Decrypt(inputFileName,
privateKeyFileName,
passPhrase,
outputFileName);


I am really struggling with this, I need to encrypt and decrypt a string using BouncyCastle in C#. I really did try to do this on my own. I did manage to create my own keys (private and public).

Please keep in mind that I am fresh out of college.

解决方案

It took me a while to find a decent example of using bouncy castle for PGP. This is what I use in production. I'm pretty sure it originated from here.

using System;
using System.IO;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;

namespace FileEncryptionTasks.Helpers.PGP
{
    public static class PGPEncryptDecrypt
    {
        private const int BufferSize = 0x10000; // should always be power of 2

        #region Encrypt

        /*
         * Encrypt the file.
         */

        public static void EncryptFile(string inputFile, string outputFile, string publicKeyFile, bool armor, bool withIntegrityCheck)
        {
            try
            {
                using (Stream publicKeyStream = File.OpenRead(publicKeyFile))
                {
                    PgpPublicKey encKey = ReadPublicKey(publicKeyStream);

                    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.Cast5, 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);
                                }
                            }
                        }
                    }
                }
            }
            catch (PgpException e)
            {
                throw;
            }
        }

        #endregion Encrypt

        #region Encrypt and Sign

        /*
         * Encrypt and sign the file pointed to by unencryptedFileInfo and
         */

        public static void EncryptAndSign(string inputFile, string outputFile, string publicKeyFile, string privateKeyFile, string passPhrase, bool armor)
        {
            PgpEncryptionKeys encryptionKeys = new PgpEncryptionKeys(publicKeyFile, privateKeyFile, passPhrase);

            if (!File.Exists(inputFile))
                throw new FileNotFoundException(String.Format("Input file [{0}] does not exist.", inputFile));

            if (!File.Exists(publicKeyFile))
                throw new FileNotFoundException(String.Format("Public Key file [{0}] does not exist.", publicKeyFile));

            if (!File.Exists(privateKeyFile))
                throw new FileNotFoundException(String.Format("Private Key file [{0}] does not exist.", privateKeyFile));

            if (String.IsNullOrEmpty(passPhrase))
                throw new ArgumentNullException("Invalid Pass Phrase.");

            if (encryptionKeys == null)
                throw new ArgumentNullException("Encryption Key not found.");

            using (Stream outputStream = File.Create(outputFile))
            {
                if (armor)
                    using (ArmoredOutputStream armoredOutputStream = new ArmoredOutputStream(outputStream))
                    {
                        OutputEncrypted(inputFile, armoredOutputStream, encryptionKeys);
                    }
                else
                    OutputEncrypted(inputFile, outputStream, encryptionKeys);
            }
        }

        private static void OutputEncrypted(string inputFile, Stream outputStream, PgpEncryptionKeys encryptionKeys)
        {
            using (Stream encryptedOut = ChainEncryptedOut(outputStream, encryptionKeys))
            {
                FileInfo unencryptedFileInfo = new FileInfo(inputFile);
                using (Stream compressedOut = ChainCompressedOut(encryptedOut))
                {
                    PgpSignatureGenerator signatureGenerator = InitSignatureGenerator(compressedOut, encryptionKeys);
                    using (Stream literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))
                    {
                        using (FileStream inputFileStream = unencryptedFileInfo.OpenRead())
                        {
                            WriteOutputAndSign(compressedOut, literalOut, inputFileStream, signatureGenerator);
                            inputFileStream.Close();
                        }
                    }
                }
            }
        }

        private static void WriteOutputAndSign(Stream compressedOut, Stream literalOut, FileStream inputFile, PgpSignatureGenerator signatureGenerator)
        {
            int length = 0;
            byte[] buf = new byte[BufferSize];
            while ((length = inputFile.Read(buf, 0, buf.Length)) > 0)
            {
                literalOut.Write(buf, 0, length);
                signatureGenerator.Update(buf, 0, length);
            }
            signatureGenerator.Generate().Encode(compressedOut);
        }

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

        private static Stream ChainCompressedOut(Stream encryptedOut)
        {
            PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
            return compressedDataGenerator.Open(encryptedOut);
        }

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

        private static PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut, PgpEncryptionKeys m_encryptionKeys)
        {
            const bool IsCritical = false;
            const bool IsNested = false;
            PublicKeyAlgorithmTag tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;
            PgpSignatureGenerator pgpSignatureGenerator = new PgpSignatureGenerator(tag, HashAlgorithmTag.Sha1);
            pgpSignatureGenerator.InitSign(PgpSignature.BinaryDocument, m_encryptionKeys.PrivateKey);
            foreach (string userId in m_encryptionKeys.SecretKey.PublicKey.GetUserIds())
            {
                PgpSignatureSubpacketGenerator subPacketGenerator = new PgpSignatureSubpacketGenerator();
                subPacketGenerator.SetSignerUserId(IsCritical, userId);
                pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());
                // Just the first one!
                break;
            }
            pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);
            return pgpSignatureGenerator;
        }

        #endregion Encrypt and Sign

        #region Decrypt

        /*
       * decrypt a given stream.
       */

        public static void Decrypt(string inputfile, string privateKeyFile, string passPhrase, string outputFile)
        {
            if (!File.Exists(inputfile))
                throw new FileNotFoundException(String.Format("Encrypted File [{0}] not found.", inputfile));

            if (!File.Exists(privateKeyFile))
                throw new FileNotFoundException(String.Format("Private Key File [{0}] not found.", privateKeyFile));

            if (String.IsNullOrEmpty(outputFile))
                throw new ArgumentNullException("Invalid Output file path.");

            using (Stream inputStream = File.OpenRead(inputfile))
            {
                using (Stream keyIn = File.OpenRead(privateKeyFile))
                {
                    Decrypt(inputStream, keyIn, passPhrase, outputFile);
                }
            }
        }

        /*
        * decrypt a given stream.
        */

        public static void Decrypt(Stream inputStream, Stream privateKeyStream, string passPhrase, string outputFile)
        {
            try
            {
                PgpObjectFactory pgpF = null;
                PgpEncryptedDataList enc = null;
                PgpObject o = null;
                PgpPrivateKey sKey = null;
                PgpPublicKeyEncryptedData pbe = null;
                PgpSecretKeyRingBundle pgpSec = null;

                pgpF = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream));
                // find secret key
                pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream));

                if (pgpF != null)
                    o = pgpF.NextPgpObject();

                // the first object might be a PGP marker packet.
                if (o is PgpEncryptedDataList)
                    enc = (PgpEncryptedDataList)o;
                else
                    enc = (PgpEncryptedDataList)pgpF.NextPgpObject();

                // decrypt
                foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
                {
                    sKey = FindSecretKey(pgpSec, pked.KeyId, passPhrase.ToCharArray());

                    if (sKey != null)
                    {
                        pbe = pked;
                        break;
                    }
                }

                if (sKey == null)
                    throw new ArgumentException("Secret key for message not found.");

                PgpObjectFactory plainFact = null;

                using (Stream clear = pbe.GetDataStream(sKey))
                {
                    plainFact = new PgpObjectFactory(clear);
                }

                PgpObject message = plainFact.NextPgpObject();

                if (message is PgpCompressedData)
                {
                    PgpCompressedData cData = (PgpCompressedData)message;
                    PgpObjectFactory of = null;

                    using (Stream compDataIn = cData.GetDataStream())
                    {
                        of = new PgpObjectFactory(compDataIn);
                    }

                    message = of.NextPgpObject();
                    if (message is PgpOnePassSignatureList)
                    {
                        message = of.NextPgpObject();
                        PgpLiteralData Ld = null;
                        Ld = (PgpLiteralData)message;
                        using (Stream output = File.Create(outputFile))
                        {
                            Stream unc = Ld.GetInputStream();
                            Streams.PipeAll(unc, output);
                        }
                    }
                    else
                    {
                        PgpLiteralData Ld = null;
                        Ld = (PgpLiteralData)message;
                        using (Stream output = File.Create(outputFile))
                        {
                            Stream unc = Ld.GetInputStream();
                            Streams.PipeAll(unc, output);
                        }
                    }
                }
                else if (message is PgpLiteralData)
                {
                    PgpLiteralData ld = (PgpLiteralData)message;
                    string outFileName = ld.FileName;

                    using (Stream fOut = File.Create(outputFile))
                    {
                        Stream unc = ld.GetInputStream();
                        Streams.PipeAll(unc, fOut);
                    }
                }
                else if (message is PgpOnePassSignatureList)
                    throw new PgpException("Encrypted message contains a signed message - not literal data.");
                else
                    throw new PgpException("Message is not a simple encrypted file - type unknown.");

                #region commented code

                //if (pbe.IsIntegrityProtected())
                //{
                //    if (!pbe.Verify())
                //        msg = "message failed integrity check.";
                //    //Console.Error.WriteLine("message failed integrity check");
                //    else
                //        msg = "message integrity check passed.";
                //    //Console.Error.WriteLine("message integrity check passed");
                //}
                //else
                //{
                //    msg = "no message integrity check.";
                //    //Console.Error.WriteLine("no message integrity check");
                //}

                #endregion commented code
            }
            catch (PgpException ex)
            {
                throw;
            }
        }

        #endregion Decrypt

        #region Private helpers

        /*
        * A simple routine that opens a key ring file and loads the first available key suitable for encryption.
        */

        private static PgpPublicKey ReadPublicKey(Stream inputStream)
        {
            inputStream = PgpUtilities.GetDecoderStream(inputStream);

            PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(inputStream);

            // 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.
            // iterate through the key rings.
            foreach (PgpPublicKeyRing kRing in pgpPub.GetKeyRings())
            {
                foreach (PgpPublicKey k in kRing.GetPublicKeys())
                {
                    if (k.IsEncryptionKey)
                        return k;
                }
            }

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

        /*
        * Search a secret key ring collection for a secret key corresponding to keyId if it exists.
        */

        private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyId, char[] pass)
        {
            PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);

            if (pgpSecKey == null)
                return null;

            return pgpSecKey.ExtractPrivateKey(pass);
        }

        #endregion Private helpers
    }
}

And it uses:

using System;
using System.IO;
using System.Linq;
using Org.BouncyCastle.Bcpg.OpenPgp;

namespace FileEncryptionTasks.Helpers.PGP
{
    public class PgpEncryptionKeys
    {
        public PgpPublicKey PublicKey { get; private set; }

        public PgpPrivateKey PrivateKey { get; private set; }

        public PgpSecretKey SecretKey { 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>
        /// <param name="privateKeyPath">The key used to sign the data.</param>
        /// <param name="passPhrase">The (your) password required to access the private key</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");
            if (!File.Exists(privateKeyPath))
                throw new ArgumentException("Private key file not found", "privateKeyPath");
            if (String.IsNullOrEmpty(passPhrase))
                throw new ArgumentException("passPhrase is null or empty.", "passPhrase");
            PublicKey = ReadPublicKey(publicKeyPath);
            SecretKey = ReadSecretKey(privateKeyPath);
            PrivateKey = ReadPrivateKey(passPhrase);
        }

        #region Secret Key

        private PgpSecretKey ReadSecretKey(string privateKeyPath)
        {
            using (Stream keyIn = File.OpenRead(privateKeyPath))
            {
                using (Stream inputStream = PgpUtilities.GetDecoderStream(keyIn))
                {
                    PgpSecretKeyRingBundle secretKeyRingBundle = new PgpSecretKeyRingBundle(inputStream);
                    PgpSecretKey foundKey = GetFirstSecretKey(secretKeyRingBundle);
                    if (foundKey != null)
                        return foundKey;
                }
            }
            throw new ArgumentException("Can't find signing key in key ring.");
        }

        /// <summary>
        /// Return the first key we can use to encrypt.
        /// Note: A file can contain multiple keys (stored in "key rings")
        /// </summary>
        private PgpSecretKey GetFirstSecretKey(PgpSecretKeyRingBundle secretKeyRingBundle)
        {
            foreach (PgpSecretKeyRing kRing in secretKeyRingBundle.GetKeyRings())
            {
                PgpSecretKey key = kRing.GetSecretKeys()
                    .Cast<PgpSecretKey>()
                    .Where(k => k.IsSigningKey)
                    .FirstOrDefault();
                if (key != null)
                    return key;
            }
            return null;
        }

        #endregion Secret Key

        #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 Public Key

        #region Private Key

        private PgpPrivateKey ReadPrivateKey(string passPhrase)
        {
            PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());
            if (privateKey != null)
                return privateKey;
            throw new ArgumentException("No private key found in secret key.");
        }

        #endregion Private Key
    }
}

Encrypt a file:

PGPEncryptDecrypt.EncryptFile(inputFileName, 
                              outputFileName,
                              recipientKeyFileName,
                              shouldArmor,
                              shouldCheckIntegrity);

Decrypt a file:

PGPEncryptDecrypt.Decrypt(inputFileName, 
                          privateKeyFileName,
                          passPhrase, 
                          outputFileName);

这篇关于PGP加密和解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆