From 02d07a1f8bd57f4141ef1a1dc006e5f72c1116c5 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 11 Oct 2018 17:41:20 +0700 Subject: Refactoring to support custom ISignatureFactory - see https://github.com/bcgit/bc-csharp/issues/153 --- crypto/BouncyCastle.Android.csproj | 10 +- crypto/BouncyCastle.csproj | 10 +- crypto/BouncyCastle.iOS.csproj | 10 +- crypto/crypto.csproj | 50 ++++-- crypto/src/cms/CMSAuthenticatedDataGenerator.cs | 2 +- .../src/cms/CMSAuthenticatedDataStreamGenerator.cs | 2 +- crypto/src/cms/CMSEnvelopedHelper.cs | 2 +- crypto/src/cms/CMSSignedDataGenerator.cs | 3 +- crypto/src/cms/CMSSignedDataStreamGenerator.cs | 2 +- crypto/src/cms/DigOutputStream.cs | 28 --- crypto/src/cms/MacOutputStream.cs | 28 --- crypto/src/cms/SigOutputStream.cs | 43 ----- crypto/src/cms/SignerInformation.cs | 14 +- crypto/src/crypto/IRsa.cs | 16 ++ crypto/src/crypto/engines/RSABlindedEngine.cs | 13 +- crypto/src/crypto/engines/RSABlindingEngine.cs | 12 +- crypto/src/crypto/engines/RSACoreEngine.cs | 29 ++- crypto/src/crypto/engines/RsaEngine.cs | 24 ++- crypto/src/crypto/io/DigestSink.cs | 35 ++++ crypto/src/crypto/io/MacSink.cs | 35 ++++ crypto/src/crypto/io/SignerSink.cs | 35 ++++ crypto/src/crypto/operators/Asn1Signature.cs | 194 +-------------------- .../crypto/operators/DefaultSignatureCalculator.cs | 28 +++ .../src/crypto/operators/DefaultSignatureResult.cs | 27 +++ .../crypto/operators/DefaultVerifierCalculator.cs | 28 +++ .../src/crypto/operators/DefaultVerifierResult.cs | 29 +++ crypto/src/crypto/signers/RsaDigestSigner.cs | 13 +- crypto/src/security/ParameterUtilities.cs | 9 + crypto/src/security/SignerUtilities.cs | 12 ++ 29 files changed, 406 insertions(+), 337 deletions(-) delete mode 100644 crypto/src/cms/DigOutputStream.cs delete mode 100644 crypto/src/cms/MacOutputStream.cs delete mode 100644 crypto/src/cms/SigOutputStream.cs create mode 100644 crypto/src/crypto/IRsa.cs create mode 100644 crypto/src/crypto/io/DigestSink.cs create mode 100644 crypto/src/crypto/io/MacSink.cs create mode 100644 crypto/src/crypto/io/SignerSink.cs create mode 100644 crypto/src/crypto/operators/DefaultSignatureCalculator.cs create mode 100644 crypto/src/crypto/operators/DefaultSignatureResult.cs create mode 100644 crypto/src/crypto/operators/DefaultVerifierCalculator.cs create mode 100644 crypto/src/crypto/operators/DefaultVerifierResult.cs (limited to 'crypto') diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 8936ecbc1..80a50ff56 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -602,7 +602,6 @@ - @@ -610,7 +609,6 @@ - @@ -622,7 +620,6 @@ - @@ -841,8 +838,11 @@ + + + @@ -880,6 +880,10 @@ + + + + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index e66bb4e5d..fb4baa9b5 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -596,7 +596,6 @@ - @@ -604,7 +603,6 @@ - @@ -616,7 +614,6 @@ - @@ -835,8 +832,11 @@ + + + @@ -874,6 +874,10 @@ + + + + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index ad433e3dc..34e7b4ec3 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -597,7 +597,6 @@ - @@ -605,7 +604,6 @@ - @@ -617,7 +615,6 @@ - @@ -836,8 +833,11 @@ + + + @@ -875,6 +875,10 @@ + + + + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index d0f672e8e..85cf632c8 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -2868,11 +2868,6 @@ SubType = "Code" BuildAction = "Compile" /> - - - + + + + + + + maxLength) throw new DataLengthException("input too large for RSA cipher."); @@ -93,7 +106,9 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual byte[] ConvertOutput( BigInteger result) { - byte[] output = result.ToByteArrayUnsigned(); + CheckInitialised(); + + byte[] output = result.ToByteArrayUnsigned(); if (forEncryption) { @@ -115,7 +130,9 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual BigInteger ProcessBlock( BigInteger input) { - if (key is RsaPrivateCrtKeyParameters) + CheckInitialised(); + + if (key is RsaPrivateCrtKeyParameters) { // // we have the extra factors, use the Chinese Remainder Theorem - the author diff --git a/crypto/src/crypto/engines/RsaEngine.cs b/crypto/src/crypto/engines/RsaEngine.cs index 4399b4409..95bfb2371 100644 --- a/crypto/src/crypto/engines/RsaEngine.cs +++ b/crypto/src/crypto/engines/RsaEngine.cs @@ -1,5 +1,7 @@ using System; +using Org.BouncyCastle.Math; + namespace Org.BouncyCastle.Crypto.Engines { /** @@ -8,7 +10,17 @@ namespace Org.BouncyCastle.Crypto.Engines public class RsaEngine : IAsymmetricBlockCipher { - private RsaCoreEngine core; + private readonly IRsa core; + + public RsaEngine() + : this(new RsaCoreEngine()) + { + } + + public RsaEngine(IRsa rsa) + { + this.core = rsa; + } public virtual string AlgorithmName { @@ -25,9 +37,6 @@ namespace Org.BouncyCastle.Crypto.Engines bool forEncryption, ICipherParameters parameters) { - if (core == null) - core = new RsaCoreEngine(); - core.Init(forEncryption, parameters); } @@ -69,10 +78,9 @@ namespace Org.BouncyCastle.Crypto.Engines int inOff, int inLen) { - if (core == null) - throw new InvalidOperationException("RSA engine not initialised"); - - return core.ConvertOutput(core.ProcessBlock(core.ConvertInput(inBuf, inOff, inLen))); + BigInteger input = core.ConvertInput(inBuf, inOff, inLen); + BigInteger output = core.ProcessBlock(input); + return core.ConvertOutput(output); } } } diff --git a/crypto/src/crypto/io/DigestSink.cs b/crypto/src/crypto/io/DigestSink.cs new file mode 100644 index 000000000..98307e5f7 --- /dev/null +++ b/crypto/src/crypto/io/DigestSink.cs @@ -0,0 +1,35 @@ +using System; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class DigestSink + : BaseOutputStream + { + private readonly IDigest mDigest; + + public DigestSink(IDigest digest) + { + this.mDigest = digest; + } + + public virtual IDigest Digest + { + get { return mDigest; } + } + + public override void WriteByte(byte b) + { + mDigest.Update(b); + } + + public override void Write(byte[] buf, int off, int len) + { + if (len > 0) + { + mDigest.BlockUpdate(buf, off, len); + } + } + } +} diff --git a/crypto/src/crypto/io/MacSink.cs b/crypto/src/crypto/io/MacSink.cs new file mode 100644 index 000000000..c4fe7169a --- /dev/null +++ b/crypto/src/crypto/io/MacSink.cs @@ -0,0 +1,35 @@ +using System; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class MacSink + : BaseOutputStream + { + private readonly IMac mMac; + + public MacSink(IMac mac) + { + this.mMac = mac; + } + + public virtual IMac Mac + { + get { return mMac; } + } + + public override void WriteByte(byte b) + { + mMac.Update(b); + } + + public override void Write(byte[] buf, int off, int len) + { + if (len > 0) + { + mMac.BlockUpdate(buf, off, len); + } + } + } +} diff --git a/crypto/src/crypto/io/SignerSink.cs b/crypto/src/crypto/io/SignerSink.cs new file mode 100644 index 000000000..c9bd8b9c8 --- /dev/null +++ b/crypto/src/crypto/io/SignerSink.cs @@ -0,0 +1,35 @@ +using System; + +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.IO +{ + public class SignerSink + : BaseOutputStream + { + private readonly ISigner mSigner; + + public SignerSink(ISigner signer) + { + this.mSigner = signer; + } + + public virtual ISigner Signer + { + get { return mSigner; } + } + + public override void WriteByte(byte b) + { + mSigner.Update(b); + } + + public override void Write(byte[] buf, int off, int len) + { + if (len > 0) + { + mSigner.BlockUpdate(buf, off, len); + } + } + } +} diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs index 373ba0cee..3fa193273 100644 --- a/crypto/src/crypto/operators/Asn1Signature.cs +++ b/crypto/src/crypto/operators/Asn1Signature.cs @@ -236,91 +236,6 @@ namespace Org.BouncyCastle.Crypto.Operators } } - internal class SignerBucket - : Stream - { - protected readonly ISigner signer; - - public SignerBucket( - ISigner signer) - { - this.signer = signer; - } - - public override int Read( - byte[] buffer, - int offset, - int count) - { - throw new NotImplementedException (); - } - - public override int ReadByte() - { - throw new NotImplementedException (); - } - - public override void Write( - byte[] buffer, - int offset, - int count) - { - if (count > 0) - { - signer.BlockUpdate(buffer, offset, count); - } - } - - public override void WriteByte( - byte b) - { - signer.Update(b); - } - - public override bool CanRead - { - get { return false; } - } - - public override bool CanWrite - { - get { return true; } - } - - public override bool CanSeek - { - get { return false; } - } - - public override long Length - { - get { return 0; } - } - - public override long Position - { - get { throw new NotImplementedException (); } - set { throw new NotImplementedException (); } - } - - public override void Flush() - { - } - - public override long Seek( - long offset, - SeekOrigin origin) - { - throw new NotImplementedException (); - } - - public override void SetLength( - long length) - { - throw new NotImplementedException (); - } - } - /// /// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve /// signature algorithm details. @@ -373,14 +288,9 @@ namespace Org.BouncyCastle.Crypto.Operators public IStreamCalculator CreateCalculator() { - ISigner sig = SignerUtilities.GetSigner(algorithm); - ICipherParameters cp = privateKey; - if (random != null) - { - cp = new ParametersWithRandom(cp, random); - } - sig.Init(true, cp); - return new SigCalculator(sig); + ISigner signer = SignerUtilities.InitSigner(algorithm, true, privateKey, random); + + return new DefaultSignatureCalculator(signer); } /// @@ -392,52 +302,6 @@ namespace Org.BouncyCastle.Crypto.Operators } } - internal class SigCalculator : IStreamCalculator - { - private readonly ISigner sig; - private readonly Stream stream; - - internal SigCalculator(ISigner sig) - { - this.sig = sig; - this.stream = new SignerBucket(sig); - } - - public Stream Stream - { - get { return stream; } - } - - public object GetResult() - { - return new SigResult(sig); - } - } - - internal class SigResult : IBlockResult - { - private readonly ISigner sig; - - internal SigResult(ISigner sig) - { - this.sig = sig; - } - - public byte[] Collect() - { - return sig.GenerateSignature(); - } - - public int Collect(byte[] destination, int offset) - { - byte[] signature = Collect(); - - Array.Copy(signature, 0, destination, offset, signature.Length); - - return signature.Length; - } - } - /// /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve /// signature algorithm details. @@ -481,57 +345,9 @@ namespace Org.BouncyCastle.Crypto.Operators public IStreamCalculator CreateCalculator() { - ISigner sig = SignerUtilities.GetSigner(X509Utilities.GetSignatureName(algID)); - - sig.Init(false, publicKey); - - return new VerifierCalculator(sig); - } - } - - internal class VerifierCalculator : IStreamCalculator - { - private readonly ISigner sig; - private readonly Stream stream; - - internal VerifierCalculator(ISigner sig) - { - this.sig = sig; - this.stream = new SignerBucket(sig); - } - - public Stream Stream - { - get { return stream; } - } - - public object GetResult() - { - return new VerifierResult(sig); - } - } - - internal class VerifierResult : IVerifier - { - private readonly ISigner sig; - - internal VerifierResult(ISigner sig) - { - this.sig = sig; - } - - public bool IsVerified(byte[] signature) - { - return sig.VerifySignature(signature); - } - - public bool IsVerified(byte[] signature, int off, int length) - { - byte[] sigBytes = new byte[length]; - - Array.Copy(signature, 0, sigBytes, off, sigBytes.Length); + ISigner verifier = SignerUtilities.InitSigner(X509Utilities.GetSignatureName(algID), false, publicKey, null); - return sig.VerifySignature(signature); + return new DefaultVerifierCalculator(verifier); } } diff --git a/crypto/src/crypto/operators/DefaultSignatureCalculator.cs b/crypto/src/crypto/operators/DefaultSignatureCalculator.cs new file mode 100644 index 000000000..8ca1c01d9 --- /dev/null +++ b/crypto/src/crypto/operators/DefaultSignatureCalculator.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.IO; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class DefaultSignatureCalculator + : IStreamCalculator + { + private readonly SignerSink mSignerSink; + + public DefaultSignatureCalculator(ISigner signer) + { + this.mSignerSink = new SignerSink(signer); + } + + public Stream Stream + { + get { return mSignerSink; } + } + + public object GetResult() + { + return new DefaultSignatureResult(mSignerSink.Signer); + } + } +} diff --git a/crypto/src/crypto/operators/DefaultSignatureResult.cs b/crypto/src/crypto/operators/DefaultSignatureResult.cs new file mode 100644 index 000000000..615f67dcb --- /dev/null +++ b/crypto/src/crypto/operators/DefaultSignatureResult.cs @@ -0,0 +1,27 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class DefaultSignatureResult + : IBlockResult + { + private readonly ISigner mSigner; + + public DefaultSignatureResult(ISigner signer) + { + this.mSigner = signer; + } + + public byte[] Collect() + { + return mSigner.GenerateSignature(); + } + + public int Collect(byte[] sig, int sigOff) + { + byte[] signature = Collect(); + signature.CopyTo(sig, sigOff); + return signature.Length; + } + } +} diff --git a/crypto/src/crypto/operators/DefaultVerifierCalculator.cs b/crypto/src/crypto/operators/DefaultVerifierCalculator.cs new file mode 100644 index 000000000..c985e81a5 --- /dev/null +++ b/crypto/src/crypto/operators/DefaultVerifierCalculator.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Crypto.IO; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class DefaultVerifierCalculator + : IStreamCalculator + { + private readonly SignerSink mSignerSink; + + public DefaultVerifierCalculator(ISigner signer) + { + this.mSignerSink = new SignerSink(signer); + } + + public Stream Stream + { + get { return mSignerSink; } + } + + public object GetResult() + { + return new DefaultVerifierResult(mSignerSink.Signer); + } + } +} diff --git a/crypto/src/crypto/operators/DefaultVerifierResult.cs b/crypto/src/crypto/operators/DefaultVerifierResult.cs new file mode 100644 index 000000000..fb259c8f8 --- /dev/null +++ b/crypto/src/crypto/operators/DefaultVerifierResult.cs @@ -0,0 +1,29 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Operators +{ + public class DefaultVerifierResult + : IVerifier + { + private readonly ISigner mSigner; + + public DefaultVerifierResult(ISigner signer) + { + this.mSigner = signer; + } + + public bool IsVerified(byte[] signature) + { + return mSigner.VerifySignature(signature); + } + + public bool IsVerified(byte[] sig, int sigOff, int sigLen) + { + byte[] signature = Arrays.CopyOfRange(sig, sigOff, sigOff + sigLen); + + return IsVerified(signature); + } + } +} diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs index d9b19cf6b..b210de03e 100644 --- a/crypto/src/crypto/signers/RsaDigestSigner.cs +++ b/crypto/src/crypto/signers/RsaDigestSigner.cs @@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Signers public class RsaDigestSigner : ISigner { - private readonly IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine()); + private readonly IAsymmetricBlockCipher rsaEngine; private readonly AlgorithmIdentifier algId; private readonly IDigest digest; private bool forSigning; @@ -59,7 +59,18 @@ namespace Org.BouncyCastle.Crypto.Signers } public RsaDigestSigner(IDigest digest, AlgorithmIdentifier algId) + : this(new RsaCoreEngine(), digest, algId) { + } + + public RsaDigestSigner(IRsa rsa, IDigest digest, DerObjectIdentifier digestOid) + : this(rsa, digest, new AlgorithmIdentifier(digestOid, DerNull.Instance)) + { + } + + public RsaDigestSigner(IRsa rsa, IDigest digest, AlgorithmIdentifier algId) + { + this.rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine(rsa)); this.digest = digest; this.algId = algId; } diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs index 792067bba..dc6992833 100644 --- a/crypto/src/security/ParameterUtilities.cs +++ b/crypto/src/security/ParameterUtilities.cs @@ -299,6 +299,15 @@ namespace Org.BouncyCastle.Security throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); } + public static ICipherParameters WithRandom(ICipherParameters cp, SecureRandom random) + { + if (random != null) + { + cp = new ParametersWithRandom(cp, random); + } + return cp; + } + private static Asn1OctetString CreateIVOctetString( SecureRandom random, int ivLength) diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index a9045ae6e..6107bf878 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -602,5 +602,17 @@ namespace Org.BouncyCastle.Security { return (string) algorithms[oid.Id]; } + + public static ISigner InitSigner(DerObjectIdentifier algorithmOid, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random) + { + return InitSigner(algorithmOid.Id, forSigning, privateKey, random); + } + + public static ISigner InitSigner(string algorithm, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random) + { + ISigner signer = SignerUtilities.GetSigner(algorithm); + signer.Init(forSigning, ParameterUtilities.WithRandom(privateKey, random)); + return signer; + } } } -- cgit 1.4.1