diff options
author | David Hook <dgh@bouncycastle.org> | 2019-01-15 08:05:41 +1100 |
---|---|---|
committer | David Hook <dgh@bouncycastle.org> | 2019-01-15 08:05:41 +1100 |
commit | 6ca2f2f9b941289f42d0ef0d2ef8f0cfa1e4ac86 (patch) | |
tree | 3c1d88a79669f1cf55de9a5731d63066f442de5c /crypto | |
parent | Merge remote-tracking branch 'origin/master' (diff) | |
download | BouncyCastle.NET-ed25519-6ca2f2f9b941289f42d0ef0d2ef8f0cfa1e4ac86.tar.xz |
refactor of PKMacBuilder
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/src/cmp/GeneralPkiMessage.cs (renamed from crypto/src/asn1/cmp/GeneralPKIMessage.cs) | 0 | ||||
-rw-r--r-- | crypto/src/cmp/ProtectedPkiMessage.cs (renamed from crypto/src/asn1/cmp/ProtectedPkiMessage.cs) | 35 | ||||
-rw-r--r-- | crypto/src/cmp/ProtectedPkiMessageBuilder.cs | 9 | ||||
-rw-r--r-- | crypto/src/crmf/CertificateRequestMessageBuilder.cs | 4 | ||||
-rw-r--r-- | crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs | 23 | ||||
-rw-r--r-- | crypto/src/crmf/IPKMacPrimitivesProvider.cs | 28 | ||||
-rw-r--r-- | crypto/src/crmf/PKMacBuilder.cs | 256 | ||||
-rw-r--r-- | crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs | 90 | ||||
-rw-r--r-- | crypto/src/crypto/operators/Asn1Mac.cs | 410 |
9 files changed, 423 insertions, 432 deletions
diff --git a/crypto/src/asn1/cmp/GeneralPKIMessage.cs b/crypto/src/cmp/GeneralPkiMessage.cs index d91b8ef7e..d91b8ef7e 100644 --- a/crypto/src/asn1/cmp/GeneralPKIMessage.cs +++ b/crypto/src/cmp/GeneralPkiMessage.cs diff --git a/crypto/src/asn1/cmp/ProtectedPkiMessage.cs b/crypto/src/cmp/ProtectedPkiMessage.cs index c39f06ad0..159f08722 100644 --- a/crypto/src/asn1/cmp/ProtectedPkiMessage.cs +++ b/crypto/src/cmp/ProtectedPkiMessage.cs @@ -3,6 +3,8 @@ using Org.BouncyCastle.X509; using System; using System.Collections.Generic; using System.Text; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; using Org.BouncyCastle.Asn1.Crmf; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Crypto; @@ -10,8 +12,9 @@ using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Crmf; -namespace Org.BouncyCastle.Asn1.Cmp +namespace Org.BouncyCastle.Cmp { public class ProtectedPkiMessage @@ -64,29 +67,31 @@ namespace Org.BouncyCastle.Asn1.Cmp return res; } - - + public bool Verify(IVerifierFactory verifierFactory) + { + IStreamCalculator streamCalculator = verifierFactory.CreateCalculator(); + + IVerifier result = (IVerifier)Process(streamCalculator); + + return result.IsVerified(pkiMessage.Protection.GetBytes()); + } - public bool Verify(IVerifierFactory verifier) + private Object Process(IStreamCalculator streamCalculator) { Asn1EncodableVector avec = new Asn1EncodableVector(); avec.Add(pkiMessage.Header); avec.Add(pkiMessage.Body); byte[] enc = new DerSequence(avec).GetDerEncoded(); - IStreamCalculator streamCalculator = verifier.CreateCalculator(); - streamCalculator.Stream.Write(enc,0,enc.Length); streamCalculator.Stream.Flush(); streamCalculator.Stream.Close(); - IVerifier result = (IVerifier) streamCalculator.GetResult(); - return result.IsVerified(pkiMessage.Protection.GetBytes()); + return streamCalculator.GetResult(); } - - public bool Verify(Asn1MacFactoryProvider asn1Factory, byte[] password) + public bool Verify(PKMacBuilder pkMacBuilder, char[] password) { if (!CmpObjectIdentifiers.passwordBasedMac.Equals(pkiMessage.Header.ProtectionAlg.Algorithm)) { @@ -95,13 +100,11 @@ namespace Org.BouncyCastle.Asn1.Cmp PbmParameter parameter = PbmParameter.GetInstance(pkiMessage.Header.ProtectionAlg.Parameters); - PkMacFactory macFactory = (PkMacFactory)asn1Factory.CreateMacFactory(parameter); - - macFactory.Password = password; - MacVerifierFactory macVerifierFactory = new MacVerifierFactory(macFactory); + pkMacBuilder.SetParameters(parameter); - return Verify(macVerifierFactory); - } + IBlockResult result = (IBlockResult)Process(pkMacBuilder.Build(password).CreateCalculator()); + return Arrays.ConstantTimeAreEqual(result.Collect(), this.pkiMessage.Protection.GetBytes()); + } } } diff --git a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs index 22a004669..e660f844a 100644 --- a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs +++ b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs @@ -1,11 +1,13 @@ using System; using System.Collections; +using Org.BouncyCastle.Asn1.Crmf; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cmp; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.X509; +using Org.BouncyCastle.Crmf; namespace Org.BouncyCastle.Cmp { @@ -153,14 +155,13 @@ namespace Org.BouncyCastle.Cmp signer.Stream.Write(encoded, 0, encoded.Length); Object result = signer.GetResult(); - if (result is DefaultSignatureResult) { - return ((DefaultSignatureResult) result).Collect(); + return ((DefaultSignatureResult)result).Collect(); } - else if (result is DefaultMacAndDigestResult) + else if (result is IBlockResult) { - return ((DefaultMacAndDigestResult) result).MacResult; + return ((IBlockResult)result).Collect(); } else if (result is byte[]) { diff --git a/crypto/src/crmf/CertificateRequestMessageBuilder.cs b/crypto/src/crmf/CertificateRequestMessageBuilder.cs index 10a575abe..384f6a965 100644 --- a/crypto/src/crmf/CertificateRequestMessageBuilder.cs +++ b/crypto/src/crmf/CertificateRequestMessageBuilder.cs @@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crmf private CertTemplateBuilder _templateBuilder; private ArrayList _controls= new ArrayList(); private ISignatureFactory _popSigner; - private PkMacFactory _pkMacBuilder; + private PKMacBuilder _pkMacBuilder; private char[] _password; private GeneralName _sender; private int _popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT; @@ -161,7 +161,7 @@ namespace Org.BouncyCastle.Crmf return this; } - public CertificateRequestMessageBuilder SetAuthInfoPKMAC(PkMacFactory pkmacFactory, char[] password) + public CertificateRequestMessageBuilder SetAuthInfoPKMAC(PKMacBuilder pkmacFactory, char[] password) { this._pkMacBuilder = pkmacFactory; this._password = password; diff --git a/crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs b/crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs new file mode 100644 index 000000000..1757d6a92 --- /dev/null +++ b/crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crmf +{ + public class DefaultPKMacPrimitivesProvider : IPKMacPrimitivesProvider + { + public IDigest CreateDigest(AlgorithmIdentifier digestAlg) + { + return DigestUtilities.GetDigest(digestAlg.Algorithm); + } + + public IMac CreateMac(AlgorithmIdentifier macAlg) + { + return MacUtilities.GetMac(macAlg.Algorithm); + } + } +} diff --git a/crypto/src/crmf/IPKMacPrimitivesProvider.cs b/crypto/src/crmf/IPKMacPrimitivesProvider.cs new file mode 100644 index 000000000..8b90be515 --- /dev/null +++ b/crypto/src/crmf/IPKMacPrimitivesProvider.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Crypto; + +namespace Org.BouncyCastle.Crmf +{ + public interface IPKMacPrimitivesProvider + { + IDigest CreateDigest(AlgorithmIdentifier digestAlg); + + IMac CreateMac(AlgorithmIdentifier macAlg); + } +} diff --git a/crypto/src/crmf/PKMacBuilder.cs b/crypto/src/crmf/PKMacBuilder.cs new file mode 100644 index 000000000..5e3a5844d --- /dev/null +++ b/crypto/src/crmf/PKMacBuilder.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Cmp; +using Org.BouncyCastle.Asn1.Iana; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.Oiw; +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Cms; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.IO; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + + +namespace Org.BouncyCastle.Crmf +{ + + class PKMacStreamCalculator : IStreamCalculator + { + private readonly MacSink _stream; + + public PKMacStreamCalculator(IMac mac) + { + _stream = new MacSink(mac); + } + + public Stream Stream + { + get { return _stream; } + } + + public object GetResult() + { + return new DefaultPKMacResult(_stream.Mac); + } + } + + class PKMacFactory : IMacFactory + { + protected readonly PbmParameter parameters; + private byte[] key; + + + public PKMacFactory(byte[] key, PbmParameter parameters) + { + this.key = Arrays.Clone(key); + + this.parameters = parameters; + } + + public virtual object AlgorithmDetails + { + get { return new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, parameters); } + } + + public virtual IStreamCalculator CreateCalculator() + { + IMac mac = MacUtilities.GetMac(parameters.Mac.Algorithm); + + mac.Init(new KeyParameter(key)); + + return new PKMacStreamCalculator(mac); + } + } + + class DefaultPKMacResult: IBlockResult + { + private readonly IMac mac; + + public DefaultPKMacResult(IMac mac) + { + this.mac = mac; + } + + public byte[] Collect() + { + byte[] res = new byte[mac.GetMacSize()]; + + mac.DoFinal(res, 0); + + return res; + } + + public int Collect(byte[] sig, int sigOff) + { + byte[] signature = Collect(); + signature.CopyTo(sig, sigOff); + return signature.Length; + } + } + + public class PKMacBuilder + { + private AlgorithmIdentifier owf; + private AlgorithmIdentifier mac; + private IPKMacPrimitivesProvider provider; + private SecureRandom random; + private PbmParameter parameters; + private int iterationCount; + private int saltLength; + private byte[] salt; + private int maxIterations; + + public PKMacBuilder() : + this(new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1), 1000, new AlgorithmIdentifier(IanaObjectIdentifiers.HmacSha1, DerNull.Instance), new DefaultPKMacPrimitivesProvider()) + { + } + + public PKMacBuilder(IPKMacPrimitivesProvider provider) : + this(new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1), 1000, new AlgorithmIdentifier(IanaObjectIdentifiers.HmacSha1, DerNull.Instance), provider) + { + } + + public PKMacBuilder(IPKMacPrimitivesProvider provider, int maxIterations) + { + this.provider = provider; + this.maxIterations = maxIterations; + } + + private PKMacBuilder(AlgorithmIdentifier digestAlgorithmIdentifier, int iterationCount, AlgorithmIdentifier macAlgorithmIdentifier, IPKMacPrimitivesProvider provider) + { + this.iterationCount = iterationCount; + this.mac = macAlgorithmIdentifier; + this.owf = digestAlgorithmIdentifier; + this.provider = provider; + } + + /** + * Set the salt length in octets. + * + * @param saltLength length in octets of the salt to be generated. + * @return the generator + */ + public PKMacBuilder SetSaltLength(int saltLength) + { + if (saltLength < 8) + { + throw new ArgumentException("salt length must be at least 8 bytes"); + } + + this.saltLength = saltLength; + + return this; + } + + public PKMacBuilder SetIterationCount(int iterationCount) + { + if (iterationCount < 100) + { + throw new ArgumentException("iteration count must be at least 100"); + } + checkIterationCountCeiling(iterationCount); + + this.iterationCount = iterationCount; + + return this; + } + + public PKMacBuilder SetParameters(PbmParameter parameters) + { + checkIterationCountCeiling(parameters.IterationCount.Value.IntValue); + + this.parameters = parameters; + + return this; + } + + public PKMacBuilder SetSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public IMacFactory Build(char[] password) + { + if (parameters != null) + { + return genCalculator(parameters, password); + } + else + { + byte[] salt = new byte[saltLength]; + + if (random == null) + { + this.random = new SecureRandom(); + } + + random.NextBytes(salt); + + return genCalculator(new PbmParameter(salt, owf, iterationCount, mac), password); + } + } + + private void checkIterationCountCeiling(int iterationCount) + { + if (maxIterations > 0 && iterationCount > maxIterations) + { + throw new ArgumentException("iteration count exceeds limit (" + iterationCount + " > " + maxIterations + ")"); + } + } + + private IMacFactory genCalculator(PbmParameter parameters, char[] password) + { + // From RFC 4211 + // + // 1. Generate a random salt value S + // + // 2. Append the salt to the pw. K = pw || salt. + // + // 3. Hash the value of K. K = HASH(K) + // + // 4. Iter = Iter - 1. If Iter is greater than zero. Goto step 3. + // + // 5. Compute an HMAC as documented in [HMAC]. + // + // MAC = HASH( K XOR opad, HASH( K XOR ipad, data) ) + // + // Where opad and ipad are defined in [HMAC]. + byte[] pw = Strings.ToUtf8ByteArray(password); + byte[] salt = parameters.Salt.GetOctets(); + byte[] K = new byte[pw.Length + salt.Length]; + + System.Array.Copy(pw, 0, K, 0, pw.Length); + System.Array.Copy(salt, 0, K, pw.Length, salt.Length); + + IDigest digest = provider.CreateDigest(parameters.Owf); + + int iter = parameters.IterationCount.Value.IntValue; + + digest.BlockUpdate(K, 0, K.Length); + + K = new byte[digest.GetDigestSize()]; + + digest.DoFinal(K, 0); + + while (--iter > 0) + { + digest.BlockUpdate(K, 0, K.Length); + + digest.DoFinal(K, 0); + } + + byte[] key = K; + + return new PKMacFactory(key, parameters); + } + } +} diff --git a/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs new file mode 100644 index 000000000..8457585ff --- /dev/null +++ b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.Crmf; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Operators; +using Org.BouncyCastle.Crypto.Paddings; + +namespace Org.BouncyCastle.Crmf +{ + public class ProofOfPossessionSigningKeyBuilder + { + private CertRequest _certRequest; + private SubjectPublicKeyInfo _pubKeyInfo; + private GeneralName _name; + private PKMacValue _publicKeyMAC; + + public ProofOfPossessionSigningKeyBuilder(CertRequest certRequest) + { + this._certRequest = certRequest; + } + + public ProofOfPossessionSigningKeyBuilder(SubjectPublicKeyInfo pubKeyInfo) + { + this._pubKeyInfo = pubKeyInfo; + } + + public ProofOfPossessionSigningKeyBuilder setSender(GeneralName name) + { + this._name = name; + + return this; + } + + public ProofOfPossessionSigningKeyBuilder setPublicKeyMac(PKMacBuilder generator, char[] password) + { + IMacFactory fact = generator.Build(password); + + IStreamCalculator calc = fact.CreateCalculator(); + byte[] d = _pubKeyInfo.GetDerEncoded(); + calc.Stream.Write(d, 0, d.Length); + calc.Stream.Flush(); + calc.Stream.Close(); + + this._publicKeyMAC = new PKMacValue( + (AlgorithmIdentifier)fact.AlgorithmDetails, + new DerBitString(((IBlockResult)calc.GetResult()).Collect())); + + return this; + } + + public PopoSigningKey build(ISignatureFactory signer) + { + if (_name != null && _publicKeyMAC != null) + { + throw new InvalidOperationException("name and publicKeyMAC cannot both be set."); + } + + PopoSigningKeyInput popo; + byte[] b; + IStreamCalculator calc = signer.CreateCalculator(); + if (_certRequest != null) + { + popo = null; + b = _certRequest.GetDerEncoded(); + calc.Stream.Write(b, 0, b.Length); + + } + else if (_name != null) + { + popo = new PopoSigningKeyInput(_name, _pubKeyInfo); + b = popo.GetDerEncoded(); + calc.Stream.Write(b, 0, b.Length); + } + else + { + popo = new PopoSigningKeyInput(_publicKeyMAC, _pubKeyInfo); + b = popo.GetDerEncoded(); + calc.Stream.Write(b, 0, b.Length); + } + + calc.Stream.Flush(); + calc.Stream.Close(); + DefaultSignatureResult res = (DefaultSignatureResult)calc.GetResult(); + return new PopoSigningKey(popo, (AlgorithmIdentifier)signer.AlgorithmDetails, new DerBitString(res.Collect())); + } + } +} diff --git a/crypto/src/crypto/operators/Asn1Mac.cs b/crypto/src/crypto/operators/Asn1Mac.cs deleted file mode 100644 index ff70e5849..000000000 --- a/crypto/src/crypto/operators/Asn1Mac.cs +++ /dev/null @@ -1,410 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Org.BouncyCastle.Asn1; -using Org.BouncyCastle.Asn1.Cmp; -using Org.BouncyCastle.Asn1.Iana; -using Org.BouncyCastle.Asn1.Nist; -using Org.BouncyCastle.Asn1.Oiw; -using Org.BouncyCastle.Asn1.Pkcs; -using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Cms; -using Org.BouncyCastle.Crypto.IO; -using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Security; -using Org.BouncyCastle.Utilities; -using Org.BouncyCastle.Utilities.Encoders; - -namespace Org.BouncyCastle.Crypto.Operators -{ - - public class DefaultMacStreamCalculator : IStreamCalculator - { - private readonly MacSink _stream; - - public DefaultMacStreamCalculator(IMac mac) - { - _stream = new MacSink(mac); - } - - public void Init(KeyParameter key) - { - _stream.Mac.Init(key); - } - - public Stream Stream - { - get { return _stream; } - } - public object GetResult() - { - byte[] res = new byte[_stream.Mac.GetMacSize()]; - _stream.Mac.DoFinal(res, 0); - return res; - } - } - - - public class DefaultMacAndDigestStreamCalculator : IStreamCalculator - { - - private readonly MacSink macSink; - private readonly DigestSink digestSink; - private readonly Stream _stream; - - - public DefaultMacAndDigestStreamCalculator(IMac imac, IDigest idigest) - { - this.macSink = new MacSink(imac); - this.digestSink = new DigestSink(idigest); - _stream = new MergedStream(macSink,digestSink); - } - - - public void Init(KeyParameter macKey) - { - this.macSink.Mac.Init(macKey); - } - - public void Init(PbmParameter parameter, byte[] password) - { - - byte[] pw = password; - byte[] salt = parameter.Salt.GetOctets(); - byte[] K = new byte[pw.Length + salt.Length]; - - System.Array.Copy(pw,K,pw.Length); - System.Array.Copy(salt,0,K,pw.Length,salt.Length); - int iter = parameter.IterationCount.Value.IntValue; - this.digestSink.Digest.Reset(); - - IDigest dig = DigestUtilities.GetDigest(digestSink.Digest.AlgorithmName); - - - - dig.BlockUpdate(K,0,K.Length); - K = new byte[dig.GetDigestSize()]; - dig.DoFinal(K, 0); - iter--; - - do - { - dig.BlockUpdate(K,0,K.Length); - dig.DoFinal(K, 0); - } while (--iter > 0); - - macSink.Mac.Init(new KeyParameter(K)); - } - - - - public Stream Stream - { - get { return _stream; } - } - - - public object GetResult() - { - byte[] macResult = new byte[macSink.Mac.GetMacSize()]; - macSink.Mac.DoFinal(macResult, 0); - byte[] digestResult = new byte[digestSink.Digest.GetByteLength()]; - digestSink.Digest.DoFinal(digestResult, 0); - return new DefaultMacAndDigestResult(digestResult, macResult); - } - - private class MergedStream : Stream - { - - private Stream aStream; - private Stream bStream; - - public MergedStream(Stream aStream, Stream bStream) - { - this.aStream = aStream; - this.bStream = bStream; - } - - public override void Flush() - { - aStream.Flush(); - bStream.Flush(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - aStream.Seek(offset, origin); - return bStream.Seek(offset, origin); - } - - public override void SetLength(long value) - { - aStream.SetLength(value); - bStream.SetLength(value); - } - - public override int Read(byte[] buffer, int offset, int count) - { - aStream.Read(buffer, offset, count); - return bStream.Read(buffer, offset, count); - } - - public override void Write(byte[] buffer, int offset, int count) - { - aStream.Write(buffer, offset, count); - bStream.Write(buffer, offset, count); - } - - public override bool CanRead - { - get { return bStream.CanRead && aStream.CanRead; } - } - public override bool CanSeek - { - get { return bStream.CanSeek && aStream.CanSeek; } - - } - public override bool CanWrite { - get { return bStream.CanWrite && aStream.CanWrite; } - - } - public override long Length { - get - { - return aStream.Length; - } - } - public override long Position - { - get { return aStream.Position; } - - set { aStream.Position = value; } - } - } - } - - public struct DefaultMacAndDigestResult - { - public DefaultMacAndDigestResult(byte[] digestResult, byte[] macResult) - { - DigestResult = digestResult; - MacResult = macResult; - } - - public byte[] DigestResult { get; } - - public byte[] MacResult { get; } - } - - public class Asn1MacFactory : IMacFactory - { - protected readonly AlgorithmIdentifier MacAlgorithmIdentifier; - - - - public Asn1MacFactory(AlgorithmIdentifier macAlgorithmIdentifier) - { - MacAlgorithmIdentifier = macAlgorithmIdentifier; - } - - - - public virtual object AlgorithmDetails - { - get { return MacAlgorithmIdentifier; } - } - - public virtual IStreamCalculator CreateCalculator() - { - IMac mac = MacUtilities.GetMac(MacAlgorithmIdentifier.Algorithm); - return new DefaultMacStreamCalculator(mac); - } - } - - - public interface IMacFactoryProvider - { - IMacFactory CreateMacFactory(AlgorithmIdentifier algorithmIdentifier); - } - - public class Asn1MacFactoryProvider : IMacFactoryProvider - { - public IMacFactory CreateMacFactory(AlgorithmIdentifier algorithmIdentifier) - { - return new Asn1MacFactory(algorithmIdentifier); - } - - public IMacFactory CreateMacFactory(AlgorithmIdentifier digestAlgorithmIdentifier, AlgorithmIdentifier macAlgorithmIdentifier) - { - return new PkMacFactory(digestAlgorithmIdentifier,macAlgorithmIdentifier); - } - - public IMacFactory CreateMacFactory(PbmParameter parameter) - { - return new PkMacFactory(parameter); - } - - } - - - - public class PkMacFactory:Asn1MacFactory - { - private readonly AlgorithmIdentifier _digestAlgorithmIdentifier; - private byte[] password; - private int iterationCount; - private byte[] salt; - - - - public PkMacFactory(SecureRandom random) : base(new AlgorithmIdentifier(IanaObjectIdentifiers.HmacSha1)) - { - this._digestAlgorithmIdentifier = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); - this.iterationCount = 1000; - this.salt = new byte[20]; - random.NextBytes(salt); - } - - public PkMacFactory(AlgorithmIdentifier digestAlgorithmIdentifier, AlgorithmIdentifier macAlgorithmIdentifier) : base(macAlgorithmIdentifier) - { - this._digestAlgorithmIdentifier = digestAlgorithmIdentifier; - } - - public PkMacFactory(PbmParameter parameter):base(parameter.Mac) - { - this._digestAlgorithmIdentifier = parameter.Owf; - this.salt = parameter.Salt.GetOctets(); - this.iterationCount = parameter.IterationCount.Value.IntValue; - } - - public override object AlgorithmDetails - { - get - { - return new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, - new PbmParameter(salt, _digestAlgorithmIdentifier, iterationCount, MacAlgorithmIdentifier)); - } - } - - - public int IterationCount - { - set { this.iterationCount = value; } - } - public byte[] Salt - { - set { this.salt = value;} - } - public byte[] Password { - set { this.password = value; } - } - - - public override IStreamCalculator CreateCalculator() - { - - DefaultMacAndDigestStreamCalculator calc = new DefaultMacAndDigestStreamCalculator( - MacUtilities.GetMac(this.MacAlgorithmIdentifier.Algorithm), - DigestUtilities.GetDigest(_digestAlgorithmIdentifier.Algorithm)); - - PbmParameter parameter = new PbmParameter(salt, _digestAlgorithmIdentifier,iterationCount,MacAlgorithmIdentifier); - calc.Init(parameter, password); - - - return calc; - } - - } - - - public class MacVerifierFactory : IVerifierFactory - { - private readonly IMacFactory _macFactory; - - - public MacVerifierFactory(IMacFactory macFactory) - { - this._macFactory = macFactory; - } - - public object AlgorithmDetails - { - get { return _macFactory.AlgorithmDetails; } - } - public IStreamCalculator CreateCalculator() - { - return new MacVerifier(_macFactory.CreateCalculator()); - } - - private class MacVerifier : IStreamCalculator - { - public IStreamCalculator _calculator; - - public MacVerifier(IStreamCalculator calculator) - { - _calculator = calculator; - } - - public Stream Stream - { - get { return _calculator.Stream; } - } - - public object GetResult() - { - object result = _calculator.GetResult(); - if (result is byte[]) - { - return new DefaultMacVerifierResult((byte[])result); - } else if (result is DefaultMacAndDigestResult) - { - return new DefaultMacVerifierResult(((DefaultMacAndDigestResult)result).MacResult); - - } - - throw new InvalidOperationException("calculator did not return byte[] or DefaultMacVerifierResult"); - } - } - - } - - - public class DefaultMacVerifierResult:IVerifier - { - private readonly byte[] _calculatedResult; - - public DefaultMacVerifierResult(byte[] calculatedResult) - { - this._calculatedResult = calculatedResult; - } - - - public bool IsVerified(byte[] data) - { - return Arrays.ConstantTimeAreEqual(_calculatedResult, data); - } - - public bool IsVerified(byte[] source, int off, int length) - { - if (_calculatedResult.Length != length) - { - return false; - } - - // - // Must be constant time. - // - int j = 0; - int nonEqual = 0; - for (int i = off; i < off + length; i++) - { - nonEqual |= (_calculatedResult[j++] ^ source[i]); - } - - return nonEqual == 0; - } - } - - -} |