180 lines
3.8 KiB
C#
180 lines
3.8 KiB
C#
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;
|
|
|
|
try
|
|
{
|
|
this.sig = SignerUtilities.GetSigner(
|
|
PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new PgpException("can't set up signature object.", e);
|
|
}
|
|
}
|
|
|
|
/// <summary>Initialise the signature object for verification.</summary>
|
|
public void InitVerify(
|
|
PgpPublicKey pubKey)
|
|
{
|
|
lastb = 0;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|