diff options
50 files changed, 705 insertions, 587 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index d0f672e8e..c6dd131e7 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -2869,11 +2869,6 @@ BuildAction = "Compile" /> <File - RelPath = "src\cms\DigOutputStream.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\cms\IDigestCalculator.cs" SubType = "Code" BuildAction = "Compile" @@ -2909,11 +2904,6 @@ BuildAction = "Compile" /> <File - RelPath = "src\cms\MacOutputStream.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\cms\OriginatorId.cs" SubType = "Code" BuildAction = "Compile" @@ -2989,11 +2979,6 @@ BuildAction = "Compile" /> <File - RelPath = "src\cms\SigOutputStream.cs" - SubType = "Code" - BuildAction = "Compile" - /> - <File RelPath = "src\cms\SimpleAttributeTableGenerator.cs" SubType = "Code" BuildAction = "Compile" @@ -3139,6 +3124,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\IRsa.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\ISignatureFactory.cs" SubType = "Code" BuildAction = "Compile" @@ -3989,16 +3979,31 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\io\DigestSink.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\io\DigestStream.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "src\crypto\io\MacSink.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\io\MacStream.cs" SubType = "Code" BuildAction = "Compile" /> <File + RelPath = "src\crypto\io\SignerSink.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\io\SignerStream.cs" SubType = "Code" BuildAction = "Compile" @@ -4184,6 +4189,26 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\operators\DefaultSignatureCalculator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\operators\DefaultSignatureResult.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\operators\DefaultVerifierCalculator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\operators\DefaultVerifierResult.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\paddings\BlockCipherPadding.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs index 721299105..738a97eb4 100644 --- a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs +++ b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs @@ -9,14 +9,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class RsaPrivateKeyStructure : Asn1Encodable { - private readonly BigInteger modulus; - private readonly BigInteger publicExponent; - private readonly BigInteger privateExponent; - private readonly BigInteger prime1; - private readonly BigInteger prime2; - private readonly BigInteger exponent1; - private readonly BigInteger exponent2; - private readonly BigInteger coefficient; + private readonly BigInteger modulus; + private readonly BigInteger publicExponent; + private readonly BigInteger privateExponent; + private readonly BigInteger prime1; + private readonly BigInteger prime2; + private readonly BigInteger exponent1; + private readonly BigInteger exponent2; + private readonly BigInteger coefficient; public static RsaPrivateKeyStructure GetInstance(Asn1TaggedObject obj, bool isExplicit) { @@ -33,14 +33,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs } public RsaPrivateKeyStructure( - BigInteger modulus, - BigInteger publicExponent, - BigInteger privateExponent, - BigInteger prime1, - BigInteger prime2, - BigInteger exponent1, - BigInteger exponent2, - BigInteger coefficient) + BigInteger modulus, + BigInteger publicExponent, + BigInteger privateExponent, + BigInteger prime1, + BigInteger prime2, + BigInteger exponent1, + BigInteger exponent2, + BigInteger coefficient) { this.modulus = modulus; this.publicExponent = publicExponent; @@ -56,18 +56,18 @@ namespace Org.BouncyCastle.Asn1.Pkcs public RsaPrivateKeyStructure( Asn1Sequence seq) { - BigInteger version = ((DerInteger) seq[0]).Value; + BigInteger version = ((DerInteger)seq[0]).Value; if (version.IntValue != 0) throw new ArgumentException("wrong version for RSA private key"); - modulus = ((DerInteger) seq[1]).Value; - publicExponent = ((DerInteger) seq[2]).Value; - privateExponent = ((DerInteger) seq[3]).Value; - prime1 = ((DerInteger) seq[4]).Value; - prime2 = ((DerInteger) seq[5]).Value; - exponent1 = ((DerInteger) seq[6]).Value; - exponent2 = ((DerInteger) seq[7]).Value; - coefficient = ((DerInteger) seq[8]).Value; + modulus = ((DerInteger)seq[1]).Value; + publicExponent = ((DerInteger)seq[2]).Value; + privateExponent = ((DerInteger)seq[3]).Value; + prime1 = ((DerInteger)seq[4]).Value; + prime2 = ((DerInteger)seq[5]).Value; + exponent1 = ((DerInteger)seq[6]).Value; + exponent2 = ((DerInteger)seq[7]).Value; + coefficient = ((DerInteger)seq[8]).Value; } public BigInteger Modulus diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs index 7ab661edb..738c28211 100644 --- a/crypto/src/bcpg/BcpgOutputStream.cs +++ b/crypto/src/bcpg/BcpgOutputStream.cs @@ -376,6 +376,7 @@ namespace Org.BouncyCastle.Bcpg if (partialBuffer != null) { PartialFlush(true); + Array.Clear(partialBuffer, 0, partialBuffer.Length); partialBuffer = null; } } diff --git a/crypto/src/bcpg/LiteralDataPacket.cs b/crypto/src/bcpg/LiteralDataPacket.cs index 63a2c6d44..b4d28a201 100644 --- a/crypto/src/bcpg/LiteralDataPacket.cs +++ b/crypto/src/bcpg/LiteralDataPacket.cs @@ -23,7 +23,11 @@ namespace Org.BouncyCastle.Bcpg fileName = new byte[len]; for (int i = 0; i != len; ++i) { - fileName[i] = (byte)bcpgIn.ReadByte(); + int ch = bcpgIn.ReadByte(); + if (ch < 0) + throw new IOException("literal data truncated in header"); + + fileName[i] = (byte)ch; } modDate = (((uint)bcpgIn.ReadByte() << 24) diff --git a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs index 131a4753f..addd14c7d 100644 --- a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs +++ b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs @@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Cms mac.Init(encKey); MemoryStream bOut = new MemoryStream(); - Stream mOut = new TeeOutputStream(bOut, new MacOutputStream(mac)); + Stream mOut = new TeeOutputStream(bOut, new MacSink(mac)); content.Write(mOut); diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs index 4d18d10d4..9d9e2450c 100644 --- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs @@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Cms IMac mac = MacUtilities.GetMac(macAlgId.Algorithm); // TODO Confirm no ParametersWithRandom needed mac.Init(cipherParameters); - Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac)); + Stream mOut = new TeeOutputStream(octetOutputStream, new MacSink(mac)); return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen); } diff --git a/crypto/src/cms/CMSEnvelopedHelper.cs b/crypto/src/cms/CMSEnvelopedHelper.cs index 77d2da47a..930ffcbf1 100644 --- a/crypto/src/cms/CMSEnvelopedHelper.cs +++ b/crypto/src/cms/CMSEnvelopedHelper.cs @@ -223,7 +223,7 @@ namespace Org.BouncyCastle.Cms return new CmsProcessableInputStream( new TeeInputStream( readable.GetInputStream(), - new MacOutputStream(this.mac))); + new MacSink(this.mac))); } catch (IOException e) { diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs index 5aa5f92ab..f2676a440 100644 --- a/crypto/src/cms/CMSSignedDataGenerator.cs +++ b/crypto/src/cms/CMSSignedDataGenerator.cs @@ -6,6 +6,7 @@ using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Security; using Org.BouncyCastle.Security.Certificates; using Org.BouncyCastle.Utilities; @@ -128,7 +129,7 @@ namespace Org.BouncyCastle.Cms IDigest dig = Helper.GetDigestInstance(digestName); if (content != null) { - content.Write(new DigOutputStream(dig)); + content.Write(new DigestSink(dig)); } hash = DigestUtilities.DoFinal(dig); outer._digests.Add(digestOID, hash.Clone()); diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs index 1c8fac22b..29411e132 100644 --- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs @@ -746,7 +746,7 @@ namespace Org.BouncyCastle.Cms Stream result = s; foreach (IDigest digest in digests) { - result = GetSafeTeeOutputStream(result, new DigOutputStream(digest)); + result = GetSafeTeeOutputStream(result, new DigestSink(digest)); } return result; } diff --git a/crypto/src/cms/DigOutputStream.cs b/crypto/src/cms/DigOutputStream.cs deleted file mode 100644 index 103b45cac..000000000 --- a/crypto/src/cms/DigOutputStream.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Utilities.IO; - -namespace Org.BouncyCastle.Cms -{ - internal class DigOutputStream - : BaseOutputStream - { - private readonly IDigest dig; - - internal DigOutputStream(IDigest dig) - { - this.dig = dig; - } - - public override void WriteByte(byte b) - { - dig.Update(b); - } - - public override void Write(byte[] b, int off, int len) - { - dig.BlockUpdate(b, off, len); - } - } -} diff --git a/crypto/src/cms/MacOutputStream.cs b/crypto/src/cms/MacOutputStream.cs deleted file mode 100644 index 8891dbc2c..000000000 --- a/crypto/src/cms/MacOutputStream.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Utilities.IO; - -namespace Org.BouncyCastle.Cms -{ - internal class MacOutputStream - : BaseOutputStream - { - private readonly IMac mac; - - internal MacOutputStream(IMac mac) - { - this.mac = mac; - } - - public override void Write(byte[] b, int off, int len) - { - mac.BlockUpdate(b, off, len); - } - - public override void WriteByte(byte b) - { - mac.Update(b); - } - } -} diff --git a/crypto/src/cms/SigOutputStream.cs b/crypto/src/cms/SigOutputStream.cs deleted file mode 100644 index a807fa7fc..000000000 --- a/crypto/src/cms/SigOutputStream.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; - -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Utilities.IO; -using Org.BouncyCastle.Security; - -namespace Org.BouncyCastle.Cms -{ - internal class SigOutputStream - : BaseOutputStream - { - private readonly ISigner sig; - - internal SigOutputStream(ISigner sig) - { - this.sig = sig; - } - - public override void WriteByte(byte b) - { - try - { - sig.Update(b); - } - catch (SignatureException e) - { - throw new CmsStreamException("signature problem: " + e); - } - } - - public override void Write(byte[] b, int off, int len) - { - try - { - sig.BlockUpdate(b, off, len); - } - catch (SignatureException e) - { - throw new CmsStreamException("signature problem: " + e); - } - } - } -} \ No newline at end of file diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs index 7b9318cc9..df8d1d0a1 100644 --- a/crypto/src/cms/SignerInfoGenerator.cs +++ b/crypto/src/cms/SignerInfoGenerator.cs @@ -110,10 +110,10 @@ namespace Org.BouncyCastle.Cms } /** - * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier. + * Build a generator with the passed in X.509 certificate issuer and serial number as the signerIdentifier. * * @param contentSigner operator for generating the final signature in the SignerInfo with. - * @param certHolder carrier for the X.509 certificate related to the contentSigner. + * @param certificate X.509 certificate related to the contentSigner. * @return a SignerInfoGenerator * @throws OperatorCreationException if the generator cannot be built. */ diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs index 39ecfa6d3..c262806a8 100644 --- a/crypto/src/cms/SignerInformation.cs +++ b/crypto/src/cms/SignerInformation.cs @@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -387,7 +388,7 @@ namespace Org.BouncyCastle.Cms { if (content != null) { - content.Write(new DigOutputStream(digest)); + content.Write(new DigestSink(digest)); } else if (signedAttributeSet == null) { @@ -485,8 +486,15 @@ namespace Org.BouncyCastle.Cms } else if (content != null) { - // TODO Use raw signature of the hash value instead - content.Write(new SigOutputStream(sig)); + try + { + // TODO Use raw signature of the hash value instead + content.Write(new SignerSink(sig)); + } + catch (SignatureException e) + { + throw new CmsStreamException("signature problem: " + e); + } } } else diff --git a/crypto/src/crypto/IRsa.cs b/crypto/src/crypto/IRsa.cs new file mode 100644 index 000000000..f7bcc9e5a --- /dev/null +++ b/crypto/src/crypto/IRsa.cs @@ -0,0 +1,16 @@ +using System; + +using Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Crypto +{ + public interface IRsa + { + void Init(bool forEncryption, ICipherParameters parameters); + int GetInputBlockSize(); + int GetOutputBlockSize(); + BigInteger ConvertInput(byte[] buf, int off, int len); + BigInteger ProcessBlock(BigInteger input); + byte[] ConvertOutput(BigInteger result); + } +} diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs index f95f145f6..7b928c5fb 100644 --- a/crypto/src/crypto/engines/RSABlindedEngine.cs +++ b/crypto/src/crypto/engines/RSABlindedEngine.cs @@ -13,10 +13,21 @@ namespace Org.BouncyCastle.Crypto.Engines public class RsaBlindedEngine : IAsymmetricBlockCipher { - private readonly RsaCoreEngine core = new RsaCoreEngine(); + private readonly IRsa core; + private RsaKeyParameters key; private SecureRandom random; + public RsaBlindedEngine() + : this(new RsaCoreEngine()) + { + } + + public RsaBlindedEngine(IRsa rsa) + { + this.core = rsa; + } + public virtual string AlgorithmName { get { return "RSA"; } diff --git a/crypto/src/crypto/engines/RSABlindingEngine.cs b/crypto/src/crypto/engines/RSABlindingEngine.cs index c636627bf..1289456a6 100644 --- a/crypto/src/crypto/engines/RSABlindingEngine.cs +++ b/crypto/src/crypto/engines/RSABlindingEngine.cs @@ -14,13 +14,23 @@ namespace Org.BouncyCastle.Crypto.Engines public class RsaBlindingEngine : IAsymmetricBlockCipher { - private readonly RsaCoreEngine core = new RsaCoreEngine(); + private readonly IRsa core; private RsaKeyParameters key; private BigInteger blindingFactor; private bool forEncryption; + public RsaBlindingEngine() + : this(new RsaCoreEngine()) + { + } + + public RsaBlindingEngine(IRsa rsa) + { + this.core = rsa; + } + public virtual string AlgorithmName { get { return "RSA"; } diff --git a/crypto/src/crypto/engines/RSACoreEngine.cs b/crypto/src/crypto/engines/RSACoreEngine.cs index fd44e3cc1..5f6e98eea 100644 --- a/crypto/src/crypto/engines/RSACoreEngine.cs +++ b/crypto/src/crypto/engines/RSACoreEngine.cs @@ -9,13 +9,20 @@ namespace Org.BouncyCastle.Crypto.Engines /** * this does your basic RSA algorithm. */ - class RsaCoreEngine + public class RsaCoreEngine + : IRsa { private RsaKeyParameters key; private bool forEncryption; private int bitSize; - /** + private void CheckInitialised() + { + if (key == null) + throw new InvalidOperationException("RSA engine not initialised"); + } + + /** * initialise the RSA engine. * * @param forEncryption true if we are encrypting, false otherwise. @@ -47,6 +54,8 @@ namespace Org.BouncyCastle.Crypto.Engines */ public virtual int GetInputBlockSize() { + CheckInitialised(); + if (forEncryption) { return (bitSize - 1) / 8; @@ -64,7 +73,9 @@ namespace Org.BouncyCastle.Crypto.Engines */ public virtual int GetOutputBlockSize() { - if (forEncryption) + CheckInitialised(); + + if (forEncryption) { return (bitSize + 7) / 8; } @@ -77,7 +88,9 @@ namespace Org.BouncyCastle.Crypto.Engines int inOff, int inLen) { - int maxLength = (bitSize + 7) / 8; + CheckInitialised(); + + int maxLength = (bitSize + 7) / 8; if (inLen > 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/generators/OpenBsdBCrypt.cs b/crypto/src/crypto/generators/OpenBsdBCrypt.cs index 49f79f95b..da6e2b952 100644 --- a/crypto/src/crypto/generators/OpenBsdBCrypt.cs +++ b/crypto/src/crypto/generators/OpenBsdBCrypt.cs @@ -174,7 +174,11 @@ namespace Org.BouncyCastle.Crypto.Generators } catch (Exception nfe) { +#if PORTABLE + throw new ArgumentException("Invalid cost factor: " + bcryptString.Substring(4, 2), "bcryptString"); +#else throw new ArgumentException("Invalid cost factor: " + bcryptString.Substring(4, 2), "bcryptString", nfe); +#endif } if (cost < 4 || cost > 31) throw new ArgumentException("Invalid cost factor: " + cost + ", 4 < cost < 31 expected."); 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 (); - } - } - /// <summary> /// 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); } /// <summary> @@ -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; - } - } - /// <summary> /// 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/parameters/RsaPrivateCrtKeyParameters.cs b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs index 7bd8abd76..557ee94e2 100644 --- a/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs +++ b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs @@ -2,33 +2,34 @@ using System; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Math; +using Org.BouncyCastle.Asn1.Pkcs; namespace Org.BouncyCastle.Crypto.Parameters { public class RsaPrivateCrtKeyParameters - : RsaKeyParameters + : RsaKeyParameters { private readonly BigInteger e, p, q, dP, dQ, qInv; - public RsaPrivateCrtKeyParameters( - BigInteger modulus, - BigInteger publicExponent, - BigInteger privateExponent, - BigInteger p, - BigInteger q, - BigInteger dP, - BigInteger dQ, - BigInteger qInv) - : base(true, modulus, privateExponent) + public RsaPrivateCrtKeyParameters( + BigInteger modulus, + BigInteger publicExponent, + BigInteger privateExponent, + BigInteger p, + BigInteger q, + BigInteger dP, + BigInteger dQ, + BigInteger qInv) + : base(true, modulus, privateExponent) { - ValidateValue(publicExponent, "publicExponent", "exponent"); - ValidateValue(p, "p", "P value"); - ValidateValue(q, "q", "Q value"); - ValidateValue(dP, "dP", "DP value"); - ValidateValue(dQ, "dQ", "DQ value"); - ValidateValue(qInv, "qInv", "InverseQ value"); - - this.e = publicExponent; + ValidateValue(publicExponent, "publicExponent", "exponent"); + ValidateValue(p, "p", "P value"); + ValidateValue(q, "q", "Q value"); + ValidateValue(dP, "dP", "DP value"); + ValidateValue(dQ, "dQ", "DQ value"); + ValidateValue(qInv, "qInv", "InverseQ value"); + + this.e = publicExponent; this.p = p; this.q = q; this.dP = dP; @@ -36,69 +37,82 @@ namespace Org.BouncyCastle.Crypto.Parameters this.qInv = qInv; } - public BigInteger PublicExponent + public RsaPrivateCrtKeyParameters(RsaPrivateKeyStructure rsaPrivateKey) + : this( + rsaPrivateKey.Modulus, + rsaPrivateKey.PublicExponent, + rsaPrivateKey.PrivateExponent, + rsaPrivateKey.Prime1, + rsaPrivateKey.Prime2, + rsaPrivateKey.Exponent1, + rsaPrivateKey.Exponent2, + rsaPrivateKey.Coefficient) + { + } + + public BigInteger PublicExponent { get { return e; } - } - - public BigInteger P - { - get { return p; } - } - - public BigInteger Q - { - get { return q; } - } - - public BigInteger DP - { - get { return dP; } - } - - public BigInteger DQ - { - get { return dQ; } - } - - public BigInteger QInv - { - get { return qInv; } - } - - public override bool Equals( - object obj) - { - if (obj == this) - return true; - - RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters; - - if (kp == null) - return false; - - return kp.DP.Equals(dP) - && kp.DQ.Equals(dQ) - && kp.Exponent.Equals(this.Exponent) - && kp.Modulus.Equals(this.Modulus) - && kp.P.Equals(p) - && kp.Q.Equals(q) - && kp.PublicExponent.Equals(e) - && kp.QInv.Equals(qInv); - } - - public override int GetHashCode() - { - return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode() - ^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode(); - } - - private static void ValidateValue(BigInteger x, string name, string desc) - { - if (x == null) - throw new ArgumentNullException(name); - if (x.SignValue <= 0) - throw new ArgumentException("Not a valid RSA " + desc, name); - } - } + } + + public BigInteger P + { + get { return p; } + } + + public BigInteger Q + { + get { return q; } + } + + public BigInteger DP + { + get { return dP; } + } + + public BigInteger DQ + { + get { return dQ; } + } + + public BigInteger QInv + { + get { return qInv; } + } + + public override bool Equals( + object obj) + { + if (obj == this) + return true; + + RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters; + + if (kp == null) + return false; + + return kp.DP.Equals(dP) + && kp.DQ.Equals(dQ) + && kp.Exponent.Equals(this.Exponent) + && kp.Modulus.Equals(this.Modulus) + && kp.P.Equals(p) + && kp.Q.Equals(q) + && kp.PublicExponent.Equals(e) + && kp.QInv.Equals(qInv); + } + + public override int GetHashCode() + { + return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode() + ^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode(); + } + + private static void ValidateValue(BigInteger x, string name, string desc) + { + if (x == null) + throw new ArgumentNullException(name); + if (x.SignValue <= 0) + throw new ArgumentException("Not a valid RSA " + desc, name); + } + } } diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs index c25ab9364..fb49a02b3 100644 --- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs @@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters { byte[] encoded = new byte[X25519.PointSize]; publicKey.Encode(encoded, 0); - X25519.ScalarMult(data, 0, encoded, 0, buf, off); + if (!X25519.CalculateAgreement(data, 0, encoded, 0, buf, off)) + throw new InvalidOperationException("X25519 agreement failed"); } } } diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs index 291eac10f..d17aa7947 100644 --- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs +++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs @@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters { byte[] encoded = new byte[X448.PointSize]; publicKey.Encode(encoded, 0); - X448.ScalarMult(data, 0, encoded, 0, buf, off); + if (!X448.CalculateAgreement(data, 0, encoded, 0, buf, off)) + throw new InvalidOperationException("X448 agreement failed"); } } } diff --git a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs index 499aab267..f12b832ee 100644 --- a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs +++ b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs @@ -5,18 +5,20 @@ using System.Threading; using System.Threading.Tasks; #endif +using Org.BouncyCastle.Utilities; + namespace Org.BouncyCastle.Crypto.Prng { - /** - * A thread based seed generator - one source of randomness. - * <p> - * Based on an idea from Marcus Lippert. - * </p> - */ - public class ThreadedSeedGenerator - { - private class SeedGenerator - { + /** + * A thread based seed generator - one source of randomness. + * <p> + * Based on an idea from Marcus Lippert. + * </p> + */ + public class ThreadedSeedGenerator + { + private class SeedGenerator + { #if NETCF_1_0 // No volatile keyword, but all fields implicitly volatile anyway private int counter = 0; @@ -26,18 +28,18 @@ namespace Org.BouncyCastle.Crypto.Prng private volatile bool stop = false; #endif - private void Run(object ignored) - { - while (!this.stop) - { - this.counter++; - } - } + private void Run(object ignored) + { + while (!this.stop) + { + this.counter++; + } + } - public byte[] GenerateSeed( + public byte[] GenerateSeed( int numBytes, bool fast) - { + { #if SILVERLIGHT || PORTABLE return DoGenerateSeed(numBytes, fast); #else @@ -59,71 +61,84 @@ namespace Org.BouncyCastle.Crypto.Prng bool fast) { this.counter = 0; - this.stop = false; + this.stop = false; - byte[] result = new byte[numBytes]; - int last = 0; - int end = fast ? numBytes : numBytes * 8; + byte[] result = new byte[numBytes]; + int last = 0; + int end = fast ? numBytes : numBytes * 8; #if NO_THREADS Task.Factory.StartNew(() => Run(null), TaskCreationOptions.None); #else - ThreadPool.QueueUserWorkItem(new WaitCallback(Run)); + ThreadPool.QueueUserWorkItem(new WaitCallback(Run)); +#endif + +#if PORTABLE + AutoResetEvent autoResetEvent = new AutoResetEvent(false); #endif - for (int i = 0; i < end; i++) - { - while (this.counter == last) - { - try - { + try + { + for (int i = 0; i < end; i++) + { + while (this.counter == last) + { + try + { #if PORTABLE - new AutoResetEvent(false).WaitOne(1); + autoResetEvent.WaitOne(1); #else - Thread.Sleep(1); + Thread.Sleep(1); #endif - } - catch (Exception) - { - // ignore - } - } + } + catch (Exception) + { + // ignore + } + } - last = this.counter; + last = this.counter; - if (fast) - { - result[i] = (byte)last; - } - else - { - int bytepos = i / 8; - result[bytepos] = (byte)((result[bytepos] << 1) | (last & 1)); - } - } + if (fast) + { + result[i] = (byte)last; + } + else + { + int bytepos = i / 8; + result[bytepos] = (byte)((result[bytepos] << 1) | (last & 1)); + } + } + } + finally + { +#if PORTABLE + autoResetEvent.Dispose(); +#endif + } - this.stop = true; + this.stop = true; - return result; - } - } + return result; + } + } - /** - * Generate seed bytes. Set fast to false for best quality. - * <p> - * If fast is set to true, the code should be round about 8 times faster when - * generating a long sequence of random bytes. 20 bytes of random values using - * the fast mode take less than half a second on a Nokia e70. If fast is set to false, - * it takes round about 2500 ms. - * </p> - * @param numBytes the number of bytes to generate - * @param fast true if fast mode should be used - */ - public byte[] GenerateSeed( + /** + * Generate seed bytes. Set fast to false for best quality. + * <p> + * If fast is set to true, the code should be round about 8 times faster when + * generating a long sequence of random bytes. 20 bytes of random values using + * the fast mode take less than half a second on a Nokia e70. If fast is set to false, + * it takes round about 2500 ms. + * </p> + * @param numBytes the number of bytes to generate + * @param fast true if fast mode should be used + */ + public byte[] GenerateSeed( int numBytes, bool fast) - { - return new SeedGenerator().GenerateSeed(numBytes, fast); - } - } + { + return new SeedGenerator().GenerateSeed(numBytes, fast); + } + } } diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs index 437247c26..ef8714188 100644 --- a/crypto/src/crypto/signers/Ed25519Signer.cs +++ b/crypto/src/crypto/signers/Ed25519Signer.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; @@ -80,14 +79,9 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - private readonly object lockObject = new object(); - - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey) { - lock (lockObject) + lock (this) { #if PORTABLE byte[] buf = ToArray(); @@ -103,10 +97,9 @@ namespace Org.BouncyCastle.Crypto.Signers } } - //[MethodImpl(MethodImplOptions.Synchronized)] internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] signature) { - lock (lockObject) + lock (this) { #if PORTABLE byte[] buf = ToArray(); @@ -122,16 +115,16 @@ namespace Org.BouncyCastle.Crypto.Signers } } - //[MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { - lock (lockObject) + lock (this) { + long count = Position; #if PORTABLE this.Position = 0L; Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs index 495898349..60c708019 100644 --- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs +++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; @@ -82,14 +81,9 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - private readonly object lockObject = new object(); - - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx) { - lock (lockObject) + lock (this) { #if PORTABLE byte[] buf = ToArray(); @@ -105,10 +99,9 @@ namespace Org.BouncyCastle.Crypto.Signers } } - //[MethodImpl(MethodImplOptions.Synchronized)] internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] signature) { - lock (lockObject) + lock (this) { #if PORTABLE byte[] buf = ToArray(); @@ -124,16 +117,16 @@ namespace Org.BouncyCastle.Crypto.Signers } } - //[MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { - lock (lockObject) + lock (this) { + long count = Position; #if PORTABLE this.Position = 0L; Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs index 3318f6438..548ca1f29 100644 --- a/crypto/src/crypto/signers/Ed25519phSigner.cs +++ b/crypto/src/crypto/signers/Ed25519phSigner.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs index 455400d22..0863e5dd1 100644 --- a/crypto/src/crypto/signers/Ed448Signer.cs +++ b/crypto/src/crypto/signers/Ed448Signer.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; @@ -82,18 +81,13 @@ namespace Org.BouncyCastle.Crypto.Signers private class Buffer : MemoryStream { - private readonly object lockObject = new object(); - - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx) { - lock (lockObject) + lock (this) { #if PORTABLE - byte[] buf = ToArray(); - int count = buf.Length; + byte[] buf = ToArray(); + int count = buf.Length; #else byte[] buf = GetBuffer(); int count = (int)Position; @@ -105,12 +99,9 @@ namespace Org.BouncyCastle.Crypto.Signers } } - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] internal bool VerifySignature(Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] signature) { - lock (lockObject) + lock (this) { #if PORTABLE byte[] buf = ToArray(); @@ -126,18 +117,16 @@ namespace Org.BouncyCastle.Crypto.Signers } } - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] internal void Reset() { - lock (lockObject) + lock (this) { + long count = Position; #if PORTABLE this.Position = 0L; Streams.WriteZeroes(this, count); #else - Array.Clear(GetBuffer(), 0, (int)Position); + Array.Clear(GetBuffer(), 0, (int)count); #endif this.Position = 0L; } diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs index b86d0855c..8f451f9e8 100644 --- a/crypto/src/crypto/signers/Ed448phSigner.cs +++ b/crypto/src/crypto/signers/Ed448phSigner.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math.EC.Rfc8032; 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/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs index 59d52265b..7b922352d 100644 --- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs @@ -22,6 +22,12 @@ namespace Org.BouncyCastle.Crypto.Tls protected DHPrivateKeyParameters mDHAgreePrivateKey; protected DHPublicKeyParameters mDHAgreePublicKey; + [Obsolete("Use constructor that takes a TlsDHVerifier")] + public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) + : this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsDHVerifier(), dhParameters) + { + } + public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters) : base(keyExchange, supportedSignatureAlgorithms) { diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs index 402c74720..5007d7daa 100644 --- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs @@ -13,6 +13,12 @@ namespace Org.BouncyCastle.Crypto.Tls { protected TlsSignerCredentials mServerCredentials = null; + [Obsolete("Use constructor that takes a TlsDHVerifier")] + public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters) + : this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsDHVerifier(), dhParameters) + { + } + public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters) : base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters) { diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs index 36ef09e85..31f4c002d 100644 --- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs +++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs @@ -36,6 +36,15 @@ namespace Org.BouncyCastle.Crypto.Tls protected TlsEncryptionCredentials mServerCredentials = null; protected byte[] mPremasterSecret; + [Obsolete("Use constructor that takes a TlsDHVerifier")] + public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity, + TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves, + byte[] clientECPointFormats, byte[] serverECPointFormats) + : this(keyExchange, supportedSignatureAlgorithms, pskIdentity, pskIdentityManager, new DefaultTlsDHVerifier(), + dhParameters, namedCurves, clientECPointFormats, serverECPointFormats) + { + } + public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity, TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves, byte[] clientECPointFormats, byte[] serverECPointFormats) diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs index 9db3a24c6..d8db2527a 100644 --- a/crypto/src/math/ec/rfc7748/X25519.cs +++ b/crypto/src/math/ec/rfc7748/X25519.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; -using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc7748 { @@ -19,8 +20,15 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 private static readonly int[] PsubS_x = { 0x03D48290, 0x02C7804D, 0x01207816, 0x028F5A68, 0x00881ED4, 0x00A2B71D, 0x0217D1B7, 0x014CB523, 0x0088EC1A, 0x0042A264 }; + private static readonly object precompLock = new object(); private static int[] precompBase = null; + public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) + { + ScalarMult(k, kOff, u, uOff, r, rOff); + return !Arrays.AreAllZeroes(r, rOff, PointSize); + } + private static uint Decode32(byte[] bs, int off) { uint n = bs[off]; @@ -57,12 +65,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 X25519Field.Mul(z, A, z); } - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] public static void Precompute() { - lock (typeof(X25519)) + lock (precompLock) { if (precompBase != null) return; diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs index cf581e9fc..63d34d1cf 100644 --- a/crypto/src/math/ec/rfc7748/X448.cs +++ b/crypto/src/math/ec/rfc7748/X448.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; -using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Math.EC.Rfc7748 { @@ -22,8 +23,15 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 0x0643ACE1U, 0x03F1BD65U, 0x084C1F82U, 0x0954459DU, 0x081B9672U, 0x0DD1031CU, 0x0EB7BDACU, 0x03881AFFU, 0x0423ACF0U, 0x05013244U, 0x0F0FAB72U }; + private static readonly object precompLock = new object(); private static uint[] precompBase = null; + public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff) + { + ScalarMult(k, kOff, u, uOff, r, rOff); + return !Arrays.AreAllZeroes(r, rOff, PointSize); + } + private static uint Decode32(byte[] bs, int off) { uint n = bs[off]; @@ -61,12 +69,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 X448Field.Mul(z, A, z); } - // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do - // Not available in lower .net standard versions - //[MethodImpl(MethodImplOptions.Synchronized)] public static void Precompute() { - lock (typeof(X448)) + lock (precompLock) { if (precompBase != null) return; @@ -76,8 +81,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 uint[] xs = precompBase; uint[] zs = new uint[X448Field.Size * 445]; - uint[] x = X448Field.Create(); x[0] = 5; - uint[] z = X448Field.Create(); z[0] = 1; + uint[] x = X448Field.Create(); x[0] = 5; + uint[] z = X448Field.Create(); z[0] = 1; uint[] n = X448Field.Create(); uint[] d = X448Field.Create(); @@ -86,10 +91,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 X448Field.Add(x, z, n); X448Field.Sub(x, z, d); - uint[] c = X448Field.Create(); X448Field.Copy(d, 0, c, 0); + uint[] c = X448Field.Create(); X448Field.Copy(d, 0, c, 0); int off = 0; - for (; ; ) + for (;;) { X448Field.Copy(n, 0, xs, off); @@ -112,7 +117,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748 uint[] u = X448Field.Create(); X448Field.Inv(c, u); - for (; ; ) + for (;;) { X448Field.Copy(xs, off, x, 0); diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs index 1154a1021..403f11f50 100644 --- a/crypto/src/math/ec/rfc8032/Ed25519.cs +++ b/crypto/src/math/ec/rfc8032/Ed25519.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; @@ -61,6 +60,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 private const int PrecompPoints = 1 << (PrecompTeeth - 1); private const int PrecompMask = PrecompPoints - 1; + private static readonly object precompLock = new object(); // TODO[ed25519] Convert to PointPrecomp private static PointExt[] precompBaseTable = null; private static int[] precompBase = null; @@ -631,10 +631,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 X25519Field.Zero(p.t); } - //[MethodImpl(MethodImplOptions.Synchronized)] public static void Precompute() { - lock (typeof(Ed25519)) + lock (precompLock) { if (precompBase != null) return; @@ -679,7 +678,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 PointDouble(p); } } - } + } PointExt[] points = new PointExt[PrecompPoints]; int k = 0; diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs index 12f69b676..10ebe8f15 100644 --- a/crypto/src/math/ec/rfc8032/Ed448.cs +++ b/crypto/src/math/ec/rfc8032/Ed448.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.Runtime.CompilerServices; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; @@ -70,6 +69,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 private const int PrecompPoints = 1 << (PrecompTeeth - 1); private const int PrecompMask = PrecompPoints - 1; + private static readonly object precompLock = new object(); // TODO[ed448] Convert to PointPrecomp private static PointExt[] precompBaseTable = null; private static uint[] precompBase = null; @@ -463,12 +463,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 X448Field.Mul(p.y, r.y, D); X448Field.Mul(C, D, E); X448Field.Mul(E, -C_d, E); - // X448Field.Apm(B, E, F, G); + //X448Field.Apm(B, E, F, G); X448Field.Add(B, E, f); X448Field.Sub(B, E, g); X448Field.Add(r.x, r.y, E); X448Field.Mul(H, E, H); - // X448Field.Apm(D, C, B, E); + //X448Field.Apm(D, C, B, E); X448Field.Add(D, C, b); X448Field.Sub(D, C, e); X448Field.Carry(b); @@ -495,13 +495,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 X448Field.Mul(p.y, r.y, D); X448Field.Mul(C, D, E); X448Field.Mul(E, -C_d, E); - // X448Field.Apm(B, E, F, G); + //X448Field.Apm(B, E, F, G); X448Field.Add(B, E, F); X448Field.Sub(B, E, G); X448Field.Add(p.x, p.y, B); X448Field.Add(r.x, r.y, E); X448Field.Mul(B, E, H); - // X448Field.Apm(D, C, B, E); + //X448Field.Apm(D, C, B, E); X448Field.Add(D, C, B); X448Field.Sub(D, C, E); X448Field.Carry(B); @@ -592,10 +592,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 X448Field.One(p.z); } - //[MethodImpl(MethodImplOptions.Synchronized)] public static void Precompute() { - lock (typeof(Ed448)) + lock (precompLock) { if (precompBase != null) return; @@ -631,7 +630,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 PointDouble(p); } } - } + } PointExt[] points = new PointExt[PrecompPoints]; int k = 0; @@ -657,8 +656,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 X448Field.Mul(q.x, q.z, q.x); X448Field.Mul(q.y, q.z, q.y); - // X448Field.Normalize(q.x); - // X448Field.Normalize(q.y); + //X448Field.Normalize(q.x); + //X448Field.Normalize(q.y); X448Field.Copy(q.x, 0, precompBase, off); off += X448Field.Size; X448Field.Copy(q.y, 0, precompBase, off); off += X448Field.Size; @@ -734,7 +733,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 x21 += x31 * L4_6; // x21:55/53 x22 += x31 * L4_7; // x22:57/53 - // x30 += (x29 >> 28); x29 &= M28UL; + //x30 += (x29 >> 28); x29 &= M28UL; x14 += x30 * L4_0; // x14:54/-- x15 += x30 * L4_1; // x15:54/53 x16 += x30 * L4_2; // x16:56/-- @@ -754,7 +753,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 x19 += x29 * L4_6; // x19:57/52 x20 += x29 * L4_7; // x20:58/52 - // x28 += (x27 >> 28); x27 &= M28UL; + //x28 += (x27 >> 28); x27 &= M28UL; x12 += x28 * L4_0; // x12:54/-- x13 += x28 * L4_1; // x13:54/53 x14 += x28 * L4_2; // x14:56/-- @@ -774,7 +773,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 x17 += x27 * L4_6; // x17:58/56 x18 += x27 * L4_7; // x18:59/-- - // x26 += (x25 >> 28); x25 &= M28UL; + //x26 += (x25 >> 28); x25 &= M28UL; x10 += x26 * L4_0; // x10:54/-- x11 += x26 * L4_1; // x11:54/53 x12 += x26 * L4_2; // x12:56/-- @@ -951,7 +950,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 Encode56(x10 | (x11 << 28), r, 35); Encode56(x12 | (x13 << 28), r, 42); Encode56(x14 | (x15 << 28), r, 49); - // r[ScalarBytes - 1] = 0; + //r[ScalarBytes - 1] = 0; return r; } diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs index 039aa5893..1a93cc78d 100644 --- a/crypto/src/openpgp/PgpUtilities.cs +++ b/crypto/src/openpgp/PgpUtilities.cs @@ -367,7 +367,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp byte[] buffer) { PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator(); - Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, buffer); + Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, Arrays.Clone(buffer)); PipeFileContents(file, pOut, buffer.Length); } diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs index 52760f89b..7db264232 100644 --- a/crypto/src/pkcs/Pkcs12Store.cs +++ b/crypto/src/pkcs/Pkcs12Store.cs @@ -367,6 +367,10 @@ namespace Org.BouncyCastle.Pkcs keyCerts[name] = certEntry; keys[name] = unmarkedKeyEntry; } + else + { + keys["unmarked"] = unmarkedKeyEntry; + } } else { 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; + } } } diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index 3df908240..a9a574dbf 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -11,6 +11,16 @@ namespace Org.BouncyCastle.Utilities public static readonly byte[] EmptyBytes = new byte[0]; public static readonly int[] EmptyInts = new int[0]; + public static bool AreAllZeroes(byte[] buf, int off, int len) + { + uint bits = 0; + for (int i = 0; i < len; ++i) + { + bits |= buf[off + i]; + } + return bits == 0; + } + public static bool AreEqual( bool[] a, bool[] b) |