C#中的BouncyCastle内存中PGP加密

我一直在尝试使用BouncyCastle库来进行PGP加密/解密.我有一些代码需要修改才能使用流 – 没有文件.

我尝试删除PgpUtilities.WriteFileToLiteralData(),然后使其返回流,但它不起作用(输出流为空).

这里要更清楚的是该方法应该是什么:

public static Stream EncryptFile(MemoryStream inputStream,PgpPublicKey encKey,bool withIntegrityCheck)

这是我需要修改的代码:

private static void EncryptFile(Stream outputStream,string fileName,bool armor,bool withIntegrityCheck)
{

    if (armor)
        outputStream = new ArmoredOutputStream(outputStream);

    try
    {
        MemoryStream bOut = new MemoryStream();
        PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(
        CompressionAlgorithmTag.Zip);
        PgpUtilities.WriteFileToLiteralData(
        comData.Open(bOut),PgpLiteralData.Binary,new FileInfo(fileName));
        comData.Close();
        PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(
        SymmetricKeyAlgorithmTag.Cast5,withIntegrityCheck,new SecureRandom());
        cPk.AddMethod(encKey);
        byte[] bytes = bOut.ToArray();
        Stream cOut = cPk.Open(outputStream,bytes.Length);
        cOut.Write(bytes,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 void EncryptFile(string filePath,string publicKeyFile,string pathToSaveFile)
{
    Stream keyIn,fos;
    keyIn = File.OpenRead(publicKeyFile);
    string[] fileSplit = filePath.Split('\\');
    string fileName = fileSplit[fileSplit.Length - 1];
    fos = File.Create(pathToSaveFile + fileName + ".asc");
    EncryptFile(fos,filePath,ReadPublicKey(keyIn),true,true);
    keyIn.Close();
    fos.Close();
}

解决方法

我搞定了.代码使用byte []进行解密和加密的输入和输出 – 没有文件.

这是全班:

class PGP
{
    public PGP() { }

    /**
    * A simple routine that opens a key ring file and loads the first available key suitable for
    * encryption.
    *
    * @param in
    * @return
    * @m_out
    * @
    */
    public 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.
    *
    * @param pgpSec a secret key ring collection.
    * @param keyId keyId we want.
    * @param pass passphrase to decrypt secret key with.
    * @return
    */
    private static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec,long keyId,char[] pass)
    {
        PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyId);
        if (pgpSecKey == null)
            return null;

        return pgpSecKey.ExtractPrivateKey(pass);
    }

    /**
    * Decrypt the byte array passed into inputData and return it as
    * another byte array.
    *
    * @param inputData - the data to decrypt
    * @param keyIn - a stream from your private keyring file
    * @param passCode - the password
    * @return - decrypted data as byte array
    */
    public static byte[] Decrypt(byte[] inputData,Stream keyIn,string passCode)
    {
        byte[] error = Encoding.ASCII.GetBytes("ERROR");

        Stream inputStream = new MemoryStream(inputData);
        inputStream = PgpUtilities.GetDecoderStream(inputStream);
        MemoryStream decoded = new MemoryStream();

        try
        {
            PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);
            PgpEncryptedDataList enc;
            PgpObject o = pgpF.NextPgpObject();

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

            //
            // find the secret key
            //
            PgpPrivateKey sKey = null;
            PgpPublicKeyEncryptedData pbe = null;
            PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(
            PgpUtilities.GetDecoderStream(keyIn));
            foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
            {
                sKey = FindSecretKey(pgpSec,pked.KeyId,passCode.ToCharArray());
                if (sKey != null)
                {
                    pbe = pked;
                    break;
                }
            }
            if (sKey == null)
                throw new ArgumentException("secret key for message not found.");

                Stream clear = pbe.GetDataStream(sKey);
                PgpObjectFactory plainFact = new PgpObjectFactory(clear);
                PgpObject message = plainFact.NextPgpObject();

                if (message is PgpCompressedData)
                {
                    PgpCompressedData cData = (PgpCompressedData)message;
                    PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());
                    message = pgpFact.NextPgpObject();
                }
                if (message is PgpLiteralData)
                {
                    PgpLiteralData ld = (PgpLiteralData)message;
                    Stream unc = ld.GetInputStream();
                    Streams.PipeAll(unc,decoded);
                }
                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.");

                if (pbe.IsIntegrityProtected())
                {
                    if (!pbe.Verify())
                        MessageBox.Show(null,"Message failed integrity check.","PGP Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                    else
                        MessageBox.Show(null,"Message integrity check passed.",MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show(null,"No message integrity check.",MessageBoxIcon.Information);
                }

                return decoded.ToArray();
            }
            catch (Exception e)
            {
                if (e.Message.StartsWith("Checksum mismatch"))
                    MessageBox.Show(null,"Likely invalid passcode. Possible data corruption.","Invalid Passcode",MessageBoxIcon.Error);
                else if (e.Message.StartsWith("Object reference not"))
                    MessageBox.Show(null,"PGP data does not exist.",MessageBoxIcon.Error);
                else if (e.Message.StartsWith("Premature end of stream"))
                    MessageBox.Show(null,"Partial PGP data found.",MessageBoxIcon.Error);
                else
                    MessageBox.Show(null,e.Message,MessageBoxIcon.Error);
                Exception underlyingException = e.InnerException;
                if (underlyingException != null)
                    MessageBox.Show(null,underlyingException.Message,MessageBoxIcon.Error);

                return error;
            }
        }

        /**
        * Encrypt the data.
        *
        * @param inputData - byte array to encrypt
        * @param passPhrase - the password returned by "ReadPublicKey"
        * @param withIntegrityCheck - check the data for errors
        * @param armor - protect the data streams
        * @return - encrypted byte array
        */
        public static byte[] Encrypt(byte[] inputData,PgpPublicKey passPhrase,bool withIntegrityCheck,bool armor)
        {
            byte[] processedData = Compress(inputData,PgpLiteralData.Console,CompressionAlgorithmTag.Uncompressed);

            MemoryStream bOut = new MemoryStream();
            Stream output = bOut;

            if (armor)
                output = new ArmoredOutputStream(output);

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

            Stream encOut = encGen.Open(output,processedData.Length);

            encOut.Write(processedData,processedData.Length);
            encOut.Close();

            if (armor)
                output.Close();

            return bOut.ToArray();
        }

        private static byte[] Compress(byte[] clearData,CompressionAlgorithmTag algorithm)
        {
            MemoryStream bOut = new MemoryStream();

            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm);
            Stream cos = comData.Open(bOut); // open it with the final destination
            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();

            // we want to Generate compressed data. This might be a user option later,// in which case we would pass in bOut.
            Stream pOut = lData.Open(
            cos,// the compressed output stream
            PgpLiteralData.Binary,fileName,// "filename" to store
            clearData.Length,// length of clear data
            DateTime.UtcNow         // current time
            );

            pOut.Write(clearData,clearData.Length);
            pOut.Close();

            comData.Close();

            return bOut.ToArray();
        }
    }

相关文章

1 在Visual Studio 中创建一个Asp.NET WebApi 项目,项目名:...
using ImpromptuInterface; using System; using System.Dyn...
https://blog.csdn.net/michaelgong/article/details/431485...
C#11添加了文件作用域类型功能:一个新的file修饰符,可以应...
在.NET中Newtonsoft.Json(Json.NET)是我们常用来进行Json序列...
设置允许跨域访问的网址--> 设置预检有效时间--&...