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