RE: Fwd: ClearSign signatures and required carriage return at the end

cdgendron <[email protected]>
Newsgroups gmane.comp.encryption.bouncy-castle.devel
Message-ID <[email protected]>
Thanks for your answer.

I now realize using the \r\n was the right thing to do to generate the
clearsigned file, but it caused me problems because I absolutly wanted to
unit test it using the outStr content coming from the VerifyFile() method.

I integrated the \r\n behavior in both methods so I can now auto-add the
\r\n in SignFile() and auto-remove the \r\n from the VerifyFile() original
value I return from it. (Used in unit tests to validate)

Thanks !

Here is my code based on the example

        internal void Sign(
            Stream contentToSignInputStream,
            Stream privateKeyInputStream,
            Stream signedContentOutputStream,
            string password)
        {
           
contentToSignInputStream.ThrowIfNull(nameof(contentToSignInputStream));
           
privateKeyInputStream.ThrowIfNull(nameof(privateKeyInputStream));
           
signedContentOutputStream.ThrowIfNull(nameof(signedContentOutputStream));
            password.ThrowIfNull(nameof(password));

            var pgpSecretKey =
_internalUtilities.ReadSecretKey(privateKeyInputStream);
            var pgpPrivateKey =
pgpSecretKey.ExtractPrivateKey(password.ToCharArray());
            var pgpSignatureGenerator =
_internalUtilities.InitializeSignatureGenerator(pgpSecretKey,
pgpPrivateKey);
            var armoredOutputStream = new
ArmoredOutputStream(signedContentOutputStream);

            armoredOutputStream.BeginClearText(HashAlgorithmTag.Sha512);

            //
            // note the last \n/\r/\r\n in the file is ignored
            //
            var lineOut = new MemoryStream();
            var lookAhead = ReadInputLine(lineOut,
contentToSignInputStream);
            ProcessLine(armoredOutputStream, pgpSignatureGenerator,
lineOut.ToArray());

            if (lookAhead != -1)
            {
                do
                {
                    lookAhead = ReadInputLine(lineOut, lookAhead,
contentToSignInputStream);

                    pgpSignatureGenerator.Update((byte)'\r');
                    pgpSignatureGenerator.Update((byte)'\n');

                    ProcessLine(armoredOutputStream, pgpSignatureGenerator,
lineOut.ToArray());
                }
                while (lookAhead != -1);
            }

            //We add \r\n manually to ensure we respect the PGP clearsign
canonical standard
            ProcessLine(armoredOutputStream, pgpSignatureGenerator, new
byte[] { 13, 10 });
            armoredOutputStream.EndClearText();

            var bcpgOutputStream = new
BcpgOutputStream(armoredOutputStream);
            pgpSignatureGenerator.Generate().Encode(bcpgOutputStream);
            armoredOutputStream.Close();
        }

        internal bool VerifySignature(Stream contentToVerifyInputStream,
Stream publicKeyStream, Stream originalMessageOutputStream = null)
        {
           
contentToVerifyInputStream.ThrowIfNull(nameof(contentToVerifyInputStream));
            publicKeyStream.ThrowIfNull(nameof(publicKeyStream));

            var armoredInputStream = new
ArmoredInputStream(contentToVerifyInputStream);

            var lineOutput = new MemoryStream();
            int lookAhead = ReadInputLine(lineOutput, armoredInputStream);
            var lineSeparator = LineSeparator();

            var innerOriginalMessageOutputStream = new MemoryStream();

            if (lookAhead != -1 && armoredInputStream.IsClearText())
            {
                byte[] line = lineOutput.ToArray();
                innerOriginalMessageOutputStream.Write(line, 0,
GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                innerOriginalMessageOutputStream.Write(lineSeparator, 0,
lineSeparator.Length);

                while (lookAhead != -1 && armoredInputStream.IsClearText())
                {
                    lookAhead = ReadInputLine(lineOutput, lookAhead,
armoredInputStream);

                    line = lineOutput.ToArray();
                    innerOriginalMessageOutputStream.Write(line, 0,
GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                    innerOriginalMessageOutputStream.Write(lineSeparator, 0,
lineSeparator.Length);
                }
            }
            else
            {
                if (lookAhead != -1)
                {
                    byte[] line = lineOutput.ToArray();
                    innerOriginalMessageOutputStream.Write(line, 0,
GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                    innerOriginalMessageOutputStream.Write(lineSeparator, 0,
lineSeparator.Length);
                }
            }

            publicKeyStream =
PgpUtilities.GetDecoderStream(publicKeyStream);
            var pgpPublicKeyRingBundle = new
PgpPublicKeyRingBundle(publicKeyStream);

            var pgpObjectFactory = new PgpObjectFactory(armoredInputStream);
            var pgpSignatureList =
(PgpSignatureList)pgpObjectFactory.NextPgpObject();
            var pgpSignature = pgpSignatureList[0];

           
pgpSignature.InitVerify(pgpPublicKeyRingBundle.GetPublicKey(pgpSignature.KeyId));

            innerOriginalMessageOutputStream.Seek(0, SeekOrigin.Begin);
            lookAhead = ReadInputLine(lineOutput,
innerOriginalMessageOutputStream);
            ProcessLine(pgpSignature, lineOutput.ToArray());

            if (lookAhead != -1)
            {
                do
                {
                    lookAhead = ReadInputLine(lineOutput, lookAhead,
originalMessageOutputStream);

                    pgpSignature.Update((byte)'\r');
                    pgpSignature.Update((byte)'\n');

                    ProcessLine(pgpSignature, lineOutput.ToArray());
                }
                while (lookAhead != -1);
            }

            if (originalMessageOutputStream != null)
            {
                //To remove the \r\n added in the signature method for the
canonical standard
                innerOriginalMessageOutputStream =
RemoveLastStringCharactersBytes(innerOriginalMessageOutputStream, 2);
                innerOriginalMessageOutputStream.Seek(0, SeekOrigin.Begin);
               
innerOriginalMessageOutputStream.CopyTo(originalMessageOutputStream);
            }

            innerOriginalMessageOutputStream.Close();

            return pgpSignature.Verify();
        }

        private MemoryStream RemoveLastStringCharactersBytes(MemoryStream
stream, int numberOfBytesToRemove)
        {
            byte[] buf = stream.GetBuffer();
            Buffer.BlockCopy(buf, numberOfBytesToRemove, buf,
numberOfBytesToRemove, (int)stream.Length);
            stream.SetLength(stream.Length - numberOfBytesToRemove);
            return stream;
        }



--
Sent from: http://bouncy-castle.1462172.n4.nabble.com/Bouncy-Castle-Dev-f1462173.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.