1 files changed, 179 insertions, 0 deletions
diff --git a/Crypto/src/openpgp/PgpOnePassSignature.cs b/Crypto/src/openpgp/PgpOnePassSignature.cs
new file mode 100644
index 000000000..68fc5994d
--- /dev/null
+++ b/Crypto/src/openpgp/PgpOnePassSignature.cs
@@ -0,0 +1,179 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// <remarks>A one pass signature object.</remarks>
+ public class PgpOnePassSignature
+ {
+ private OnePassSignaturePacket sigPack;
+ private int signatureType;
+ private ISigner sig;
+ private byte lastb;
+
+ internal PgpOnePassSignature(
+ BcpgInputStream bcpgInput)
+ : this((OnePassSignaturePacket) bcpgInput.ReadPacket())
+ {
+ }
+
+ internal PgpOnePassSignature(
+ OnePassSignaturePacket sigPack)
+ {
+ this.sigPack = sigPack;
+ this.signatureType = sigPack.SignatureType;
+ }
+
+ /// <summary>Initialise the signature object for verification.</summary>
+ public void InitVerify(
+ PgpPublicKey pubKey)
+ {
+ lastb = 0;
+
+ try
+ {
+ sig = SignerUtilities.GetSigner(
+ PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("can't set up signature object.", e);
+ }
+
+ try
+ {
+ sig.Init(false, pubKey.GetKey());
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new PgpException("invalid key.", e);
+ }
+ }
+
+ public void Update(
+ byte b)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ doCanonicalUpdateByte(b);
+ }
+ else
+ {
+ sig.Update(b);
+ }
+ }
+
+ private void doCanonicalUpdateByte(
+ byte b)
+ {
+ if (b == '\r')
+ {
+ doUpdateCRLF();
+ }
+ else if (b == '\n')
+ {
+ if (lastb != '\r')
+ {
+ doUpdateCRLF();
+ }
+ }
+ else
+ {
+ sig.Update(b);
+ }
+
+ lastb = b;
+ }
+
+ private void doUpdateCRLF()
+ {
+ sig.Update((byte)'\r');
+ sig.Update((byte)'\n');
+ }
+
+ public void Update(
+ byte[] bytes)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ for (int i = 0; i != bytes.Length; i++)
+ {
+ doCanonicalUpdateByte(bytes[i]);
+ }
+ }
+ else
+ {
+ sig.BlockUpdate(bytes, 0, bytes.Length);
+ }
+ }
+
+ public void Update(
+ byte[] bytes,
+ int off,
+ int length)
+ {
+ if (signatureType == PgpSignature.CanonicalTextDocument)
+ {
+ int finish = off + length;
+
+ for (int i = off; i != finish; i++)
+ {
+ doCanonicalUpdateByte(bytes[i]);
+ }
+ }
+ else
+ {
+ sig.BlockUpdate(bytes, off, length);
+ }
+ }
+
+ /// <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
+ public bool Verify(
+ PgpSignature pgpSig)
+ {
+ byte[] trailer = pgpSig.GetSignatureTrailer();
+
+ sig.BlockUpdate(trailer, 0, trailer.Length);
+
+ return sig.VerifySignature(pgpSig.GetSignature());
+ }
+
+ public long KeyId
+ {
+ get { return sigPack.KeyId; }
+ }
+
+ public int SignatureType
+ {
+ get { return sigPack.SignatureType; }
+ }
+
+ public HashAlgorithmTag HashAlgorithm
+ {
+ get { return sigPack.HashAlgorithm; }
+ }
+
+ public PublicKeyAlgorithmTag KeyAlgorithm
+ {
+ get { return sigPack.KeyAlgorithm; }
+ }
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+
+ Encode(bOut);
+
+ return bOut.ToArray();
+ }
+
+ public void Encode(
+ Stream outStr)
+ {
+ BcpgOutputStream.Wrap(outStr).WritePacket(sigPack);
+ }
+ }
+}
|