diff options
Diffstat (limited to 'crypto/src/openpgp/PgpSignatureGenerator.cs')
-rw-r--r-- | crypto/src/openpgp/PgpSignatureGenerator.cs | 193 |
1 files changed, 110 insertions, 83 deletions
diff --git a/crypto/src/openpgp/PgpSignatureGenerator.cs b/crypto/src/openpgp/PgpSignatureGenerator.cs index c5309689f..12edf9f89 100644 --- a/crypto/src/openpgp/PgpSignatureGenerator.cs +++ b/crypto/src/openpgp/PgpSignatureGenerator.cs @@ -5,19 +5,20 @@ using Org.BouncyCastle.Bcpg.Sig; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC.Rfc8032; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Bcpg.OpenPgp { /// <remarks>Generator for PGP signatures.</remarks> - // TODO Should be able to implement ISigner? public class PgpSignatureGenerator { private static readonly SignatureSubpacket[] EmptySignatureSubpackets = new SignatureSubpacket[0]; - private PublicKeyAlgorithmTag keyAlgorithm; - private HashAlgorithmTag hashAlgorithm; + private readonly PublicKeyAlgorithmTag keyAlgorithm; + private readonly HashAlgorithmTag hashAlgorithm; + private PgpPrivateKey privKey; private ISigner sig; private IDigest dig; @@ -35,33 +36,39 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.keyAlgorithm = keyAlgorithm; this.hashAlgorithm = hashAlgorithm; - dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm)); - sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm)); + dig = PgpUtilities.CreateDigest(hashAlgorithm); } /// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, - PgpPrivateKey key) + PgpPrivateKey privKey) { - InitSign(sigType, key, null); + InitSign(sigType, privKey, null); } /// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, - PgpPrivateKey key, + PgpPrivateKey privKey, SecureRandom random) { - this.privKey = key; + this.privKey = privKey; this.signatureType = sigType; - try + AsymmetricKeyParameter key = privKey.Key; + + if (sig == null) { - ICipherParameters cp = key.Key; + this.sig = PgpUtilities.CreateSigner(keyAlgorithm, hashAlgorithm, key); + } + + try + { + ICipherParameters cp = key; if (random != null) { - cp = new ParametersWithRandom(key.Key, random); + cp = new ParametersWithRandom(cp, random); } sig.Init(true, cp); @@ -75,72 +82,68 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp lastb = 0; } - public void Update( - byte b) + public void Update(byte b) { if (signatureType == PgpSignature.CanonicalTextDocument) { - doCanonicalUpdateByte(b); + DoCanonicalUpdateByte(b); } else { - doUpdateByte(b); + DoUpdateByte(b); } } - private void doCanonicalUpdateByte( - byte b) + private void DoCanonicalUpdateByte(byte b) { if (b == '\r') { - doUpdateCRLF(); + DoUpdateCRLF(); } else if (b == '\n') { if (lastb != '\r') { - doUpdateCRLF(); + DoUpdateCRLF(); } } else { - doUpdateByte(b); + DoUpdateByte(b); } lastb = b; } - private void doUpdateCRLF() + private void DoUpdateCRLF() { - doUpdateByte((byte)'\r'); - doUpdateByte((byte)'\n'); + DoUpdateByte((byte)'\r'); + DoUpdateByte((byte)'\n'); } - private void doUpdateByte( - byte b) + private void DoUpdateByte(byte b) { sig.Update(b); dig.Update(b); } - public void Update( - params byte[] b) + public void Update(params byte[] b) { Update(b, 0, b.Length); } - public void Update( - byte[] b, - int off, - int len) + public void Update(byte[] b, int off, int len) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Update(b.AsSpan(off, len)); +#else if (signatureType == PgpSignature.CanonicalTextDocument) { int finish = off + len; for (int i = off; i != finish; i++) { - doCanonicalUpdateByte(b[i]); + DoCanonicalUpdateByte(b[i]); } } else @@ -148,9 +151,28 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp sig.BlockUpdate(b, off, len); dig.BlockUpdate(b, off, len); } +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void Update(ReadOnlySpan<byte> input) + { + if (signatureType == PgpSignature.CanonicalTextDocument) + { + for (int i = 0; i < input.Length; ++i) + { + DoCanonicalUpdateByte(input[i]); + } + } + else + { + sig.BlockUpdate(input); + dig.BlockUpdate(input); + } } +#endif - public void SetHashedSubpackets( + public void SetHashedSubpackets( PgpSignatureSubpacketVector hashedPackets) { hashed = hashedPackets == null @@ -180,15 +202,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { SignatureSubpacket[] hPkts = hashed, unhPkts = unhashed; - if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime)) + if (!IsPacketPresent(hashed, SignatureSubpacketTag.CreationTime)) { - hPkts = insertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow)); + hPkts = InsertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow)); } - if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) - && !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId)) + if (!IsPacketPresent(hashed, SignatureSubpacketTag.IssuerKeyId) + && !IsPacketPresent(unhashed, SignatureSubpacketTag.IssuerKeyId)) { - unhPkts = insertSubpacket(unhPkts, new IssuerKeyId(false, privKey.KeyId)); + unhPkts = InsertSubpacket(unhPkts, new IssuerKeyId(false, privKey.KeyId)); } int version = 4; @@ -239,17 +261,41 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp byte[] sigBytes = sig.GenerateSignature(); byte[] digest = DigestUtilities.DoFinal(dig); - byte[] fingerPrint = new byte[] { digest[0], digest[1] }; + byte[] fingerPrint = new byte[2]{ digest[0], digest[1] }; - // an RSA signature - bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign - || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral; - - MPInteger[] sigValues = isRsa - ? PgpUtilities.RsaSigToMpi(sigBytes) - : PgpUtilities.DsaSigToMpi(sigBytes); + MPInteger[] sigValues; + if (keyAlgorithm == PublicKeyAlgorithmTag.EdDsa) + { + int sigLen = sigBytes.Length; + if (sigLen == Ed25519.SignatureSize) + { + sigValues = new MPInteger[2]{ + new MPInteger(new BigInteger(1, sigBytes, 0, 32)), + new MPInteger(new BigInteger(1, sigBytes, 32, 32)) + }; + } + else if (sigLen == Ed448.SignatureSize) + { + sigValues = new MPInteger[2]{ + new MPInteger(new BigInteger(1, Arrays.Prepend(sigBytes, 0x40))), + new MPInteger(BigInteger.Zero) + }; + } + else + { + throw new InvalidOperationException(); + } + } + else if (keyAlgorithm == PublicKeyAlgorithmTag.RsaSign || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral) + { + sigValues = PgpUtilities.RsaSigToMpi(sigBytes); + } + else + { + sigValues = PgpUtilities.DsaSigToMpi(sigBytes); + } - return new PgpSignature( + return new PgpSignature( new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm, hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues)); } @@ -258,9 +304,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <param name="id">The ID we are certifying against the public key.</param> /// <param name="pubKey">The key we are certifying against the ID.</param> /// <returns>The certification.</returns> - public PgpSignature GenerateCertification( - string id, - PgpPublicKey pubKey) + public PgpSignature GenerateCertification(string id, PgpPublicKey pubKey) { UpdateWithPublicKey(pubKey); @@ -276,9 +320,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <param name="userAttributes">The ID we are certifying against the public key.</param> /// <param name="pubKey">The key we are certifying against the ID.</param> /// <returns>The certification.</returns> - public PgpSignature GenerateCertification( - PgpUserAttributeSubpacketVector userAttributes, - PgpPublicKey pubKey) + public PgpSignature GenerateCertification(PgpUserAttributeSubpacketVector userAttributes, PgpPublicKey pubKey) { UpdateWithPublicKey(pubKey); @@ -287,7 +329,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp // try { - MemoryStream bOut = new MemoryStream(); + var bOut = new MemoryStream(); foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray()) { packet.Encode(bOut); @@ -299,16 +341,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp throw new PgpException("cannot encode subpacket array", e); } - return this.Generate(); + return Generate(); } /// <summary>Generate a certification for the passed in key against the passed in master key.</summary> /// <param name="masterKey">The key we are certifying against.</param> /// <param name="pubKey">The key we are certifying.</param> /// <returns>The certification.</returns> - public PgpSignature GenerateCertification( - PgpPublicKey masterKey, - PgpPublicKey pubKey) + public PgpSignature GenerateCertification(PgpPublicKey masterKey, PgpPublicKey pubKey) { UpdateWithPublicKey(masterKey); UpdateWithPublicKey(pubKey); @@ -319,16 +359,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp /// <summary>Generate a certification, such as a revocation, for the passed in key.</summary> /// <param name="pubKey">The key we are certifying.</param> /// <returns>The certification.</returns> - public PgpSignature GenerateCertification( - PgpPublicKey pubKey) + public PgpSignature GenerateCertification(PgpPublicKey pubKey) { UpdateWithPublicKey(pubKey); return Generate(); } - private byte[] GetEncodedPublicKey( - PgpPublicKey pubKey) + private static byte[] GetEncodedPublicKey(PgpPublicKey pubKey) { try { @@ -340,42 +378,31 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - private bool packetPresent( - SignatureSubpacket[] packets, - SignatureSubpacketTag type) + private static bool IsPacketPresent(SignatureSubpacket[] packets, SignatureSubpacketTag type) { for (int i = 0; i != packets.Length; i++) { if (packets[i].SubpacketType == type) - { return true; - } } return false; } - private SignatureSubpacket[] insertSubpacket( - SignatureSubpacket[] packets, - SignatureSubpacket subpacket) + private static SignatureSubpacket[] InsertSubpacket(SignatureSubpacket[] packets, SignatureSubpacket subpacket) { - SignatureSubpacket[] tmp = new SignatureSubpacket[packets.Length + 1]; - tmp[0] = subpacket; - packets.CopyTo(tmp, 1); - return tmp; + return Arrays.Prepend(packets, subpacket); } - private void UpdateWithIdData( - int header, - byte[] idBytes) + private void UpdateWithIdData(int header, byte[] idBytes) { - this.Update( + Update( (byte) header, (byte)(idBytes.Length >> 24), (byte)(idBytes.Length >> 16), (byte)(idBytes.Length >> 8), (byte)(idBytes.Length)); - this.Update(idBytes); + Update(idBytes); } private void UpdateWithPublicKey( @@ -383,11 +410,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { byte[] keyBytes = GetEncodedPublicKey(key); - this.Update( - (byte) 0x99, + Update( + 0x99, (byte)(keyBytes.Length >> 8), (byte)(keyBytes.Length)); - this.Update(keyBytes); + Update(keyBytes); } } } |