BouncyCastle使用文件名中的Cyrillik(俄语)字母加密和签名文件

时间:2012-04-12 15:37:15

标签: c# character-encoding bouncycastle sign pgp

如何使用文件名中的西里尔字母(俄语)加密和签名文件。然后解密并验证签名。请帮帮我,我无法验证签名 异常----“流中的未知对象保留”

    public void VerifySignature(Stream input, string outputpath)
    {
        input = PgpUtilities.GetDecoderStream(input);
        PgpObjectFactory pgpObjF = new PgpObjectFactory(input);            

        PgpEncryptedDataList enc = (PgpEncryptedDataList) pgpObjF.NextPgpObject();

        PgpPrivateKey sKey = null;
        PgpPublicKeyEncryptedData pbe = null;
        PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.
            GetDecoderStream(File.OpenRead(m_encryptionKeys.PrivateKeyPathd)));

        foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
        {
            sKey = FindSecretKey(pgpSec, pked.KeyId, m_encryptionKeys.PassPhrase.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);
        PgpCompressedData cData = (PgpCompressedData)plainFact.NextPgpObject();
        PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());
        PgpObject message = pgpFact.NextPgpObject();

        if (message is PgpOnePassSignatureList)
        {
            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)message;
            PgpOnePassSignature ops = p1[0];

            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
            Stream dIn = p2.GetInputStream();

            PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.
                        GetDecoderStream(File.OpenRead(m_encryptionKeys.PublicKeyPathd)));
            PgpPublicKey key = pgpRing.GetPublicKey(ops.KeyId);


            Stream fos = File.Create(p2.FileName);
            ops.InitVerify(key);

            int ch;
            while ((ch = dIn.ReadByte()) >= 0)
            {
                ops.Update((byte)ch);
                fos.WriteByte((byte)ch);
            }
            fos.Close();

            //PgpObject p3 = pgpFact.NextPgpObject();
            //if(p3 is PgpSignature)
            //    throw new PgpException("signature verified.");
            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
            PgpSignature firstSig = p3[0];
            if (ops.Verify(firstSig))
            {

                throw new PgpException("signature verified.");
            }
            else
            {

                throw new PgpException("signature verification failed.");
            }

        }



    }

加密类:

public class PgpEncrypt
    {

        private PgpEncryptionKeys m_encryptionKeys;

        private const int BufferSize = 0x10000; // should always be power of 2 

        /// <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 EncryptAndSign(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.");

            /*string ext = unencryptedFileInfo.Extension;
            File.Move(unencryptedFileInfo.FullName, unencryptedFileInfo.DirectoryName +"\\554"  + ext);*/

            using (Stream encryptedOut = ChainEncryptedOut(outputStream))
            using (Stream compressedOut = ChainCompressedOut(encryptedOut))
            {

                PgpSignatureGenerator signatureGenerator = InitSignatureGenerator(compressedOut);

                using (Stream literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))
                using (FileStream inputFile = unencryptedFileInfo.OpenRead())                
                {
                    StreamReader strRdr = new StreamReader(inputFile);
                    Encoding code = strRdr.CurrentEncoding;
                    WriteOutputAndSign(compressedOut, literalOut, inputFile, signatureGenerator);
                }

            }

        }

        public Encoding DetectEncoding(String fileName)
        {
            // open the file with the stream-reader:
            using (StreamReader reader = new StreamReader(fileName, true))
            {

                // return the encoding.
                return reader.CurrentEncoding;
            }
        }


        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 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 ChainCompressedOut(Stream encryptedOut)
        {
            PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
            return compressedDataGenerator.Open(encryptedOut);
        }

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

        private PgpSignatureGenerator InitSignatureGenerator(Stream compressedOut)
        {
            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;

        }
    }

堆栈跟踪:

    at Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory.NextPgpObject()
   at OpenPGPzzz.PgpDecrypt.VerifySignature(Stream input, String outputpath) in E:\repo\PgpDe\OpenPGPzzz\Renaissance.cs:line 302
   at PgpDE.MainWindow.button2_Click(Object sender, RoutedEventArgs e) in E:\repo\PgpDe\PgpDE\MainWindow.xaml.cs:line 68
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at PgpDE.App.Main() in E:\repo\PgpDe\PgpDE\obj\x86\Debug\App.g.cs:line 0
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

1 个答案:

答案 0 :(得分:0)

问题解决了! 我在PgpLiteralDataGenerator类中进行了一些更改,并且每件事都以正确的方式进行 以下是我的更改:

public Stream Open(
            Stream      outStr,
            char        format,
            string      name,
            long        length,
            DateTime    modificationTime)
        {
            if (pkOut != null)
                throw new InvalidOperationException("generator already in open state");
            if (outStr == null)
                throw new ArgumentNullException("outStr");

            // Do this first, since it might throw an exception
            long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime);

            byte[] encName = Encoding.GetEncoding(65001).GetBytes(name);

            pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData,
                length + 2 + encName.Length + 4, oldFormat);

            WriteHeader(pkOut, format, name, unixMs);

            return new WrappedGeneratorStream(this, pkOut);
        }