PgpV3SignatureGenerator
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Date;
using System;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
public class PgpV3SignatureGenerator
{
private readonly PublicKeyAlgorithmTag m_keyAlgorithm;
private readonly HashAlgorithmTag m_hashAlgorithm;
private PgpPrivateKey privKey;
private ISigner sig;
private IDigest dig;
private int signatureType;
private byte lastb;
public PgpV3SignatureGenerator(PublicKeyAlgorithmTag keyAlgorithm, HashAlgorithmTag hashAlgorithm)
{
if (keyAlgorithm == PublicKeyAlgorithmTag.EdDsa)
throw new ArgumentException("Invalid algorithm for V3 signature", "keyAlgorithm");
m_keyAlgorithm = keyAlgorithm;
m_hashAlgorithm = hashAlgorithm;
dig = PgpUtilities.CreateDigest(hashAlgorithm);
}
public void InitSign(int sigType, PgpPrivateKey privKey)
{
InitSign(sigType, privKey, null);
}
public void InitSign(int sigType, PgpPrivateKey privKey, SecureRandom random)
{
this.privKey = privKey;
signatureType = sigType;
AsymmetricKeyParameter key = privKey.Key;
sig = PgpUtilities.CreateSigner(m_keyAlgorithm, m_hashAlgorithm, key);
try {
sig.Init(true, ParameterUtilities.WithRandom(key, random));
} catch (InvalidKeyException innerException) {
throw new PgpException("invalid key.", innerException);
}
dig.Reset();
lastb = 0;
}
public void Update(byte b)
{
if (signatureType == 1)
DoCanonicalUpdateByte(b);
else
DoUpdateByte(b);
}
private void DoCanonicalUpdateByte(byte b)
{
switch (b) {
case 13:
DoUpdateCRLF();
break;
case 10:
if (lastb != 13)
DoUpdateCRLF();
break;
default:
DoUpdateByte(b);
break;
}
lastb = b;
}
private void DoUpdateCRLF()
{
DoUpdateByte(13);
DoUpdateByte(10);
}
private void DoUpdateByte(byte b)
{
sig.Update(b);
dig.Update(b);
}
public void Update(params byte[] b)
{
Update(b, 0, b.Length);
}
public void Update(byte[] b, int off, int len)
{
if (signatureType == 1) {
for (int i = 0; i < len; i++) {
DoCanonicalUpdateByte(b[off + i]);
}
} else {
sig.BlockUpdate(b, off, len);
dig.BlockUpdate(b, off, len);
}
}
public PgpOnePassSignature GenerateOnePassVersion(bool isNested)
{
return new PgpOnePassSignature(new OnePassSignaturePacket(signatureType, m_hashAlgorithm, m_keyAlgorithm, privKey.KeyId, isNested));
}
public PgpSignature Generate()
{
long num = DateTimeUtilities.CurrentUnixMs() / 1000;
byte[] array = new byte[5] {
(byte)signatureType,
0,
0,
0,
0
};
Pack.UInt32_To_BE((uint)num, array, 1);
sig.BlockUpdate(array, 0, array.Length);
dig.BlockUpdate(array, 0, array.Length);
byte[] encoding = sig.GenerateSignature();
byte[] array2 = DigestUtilities.DoFinal(dig);
byte[] fingerprint = new byte[2] {
array2[0],
array2[1]
};
MPInteger[] signature = (m_keyAlgorithm == PublicKeyAlgorithmTag.RsaSign || m_keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral) ? PgpUtilities.RsaSigToMpi(encoding) : PgpUtilities.DsaSigToMpi(encoding);
return new PgpSignature(new SignaturePacket(3, signatureType, privKey.KeyId, m_keyAlgorithm, m_hashAlgorithm, num * 1000, fingerprint, signature));
}
}
}