From 6ca2f2f9b941289f42d0ef0d2ef8f0cfa1e4ac86 Mon Sep 17 00:00:00 2001 From: David Hook Date: Tue, 15 Jan 2019 08:05:41 +1100 Subject: refactor of PKMacBuilder --- crypto/src/asn1/cmp/GeneralPKIMessage.cs | 49 --- crypto/src/asn1/cmp/ProtectedPkiMessage.cs | 107 ------ crypto/src/cmp/GeneralPkiMessage.cs | 49 +++ crypto/src/cmp/ProtectedPkiMessage.cs | 110 ++++++ crypto/src/cmp/ProtectedPkiMessageBuilder.cs | 9 +- .../src/crmf/CertificateRequestMessageBuilder.cs | 4 +- crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs | 23 ++ crypto/src/crmf/IPKMacPrimitivesProvider.cs | 28 ++ crypto/src/crmf/PKMacBuilder.cs | 256 +++++++++++++ .../src/crmf/ProofOfPossessionSigningKeyBuilder.cs | 90 +++++ crypto/src/crypto/operators/Asn1Mac.cs | 410 --------------------- 11 files changed, 563 insertions(+), 572 deletions(-) delete mode 100644 crypto/src/asn1/cmp/GeneralPKIMessage.cs delete mode 100644 crypto/src/asn1/cmp/ProtectedPkiMessage.cs create mode 100644 crypto/src/cmp/GeneralPkiMessage.cs create mode 100644 crypto/src/cmp/ProtectedPkiMessage.cs create mode 100644 crypto/src/crmf/DefaultPKMacPrimitivesProvider.cs create mode 100644 crypto/src/crmf/IPKMacPrimitivesProvider.cs create mode 100644 crypto/src/crmf/PKMacBuilder.cs create mode 100644 crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs delete mode 100644 crypto/src/crypto/operators/Asn1Mac.cs diff --git a/crypto/src/asn1/cmp/GeneralPKIMessage.cs b/crypto/src/asn1/cmp/GeneralPKIMessage.cs deleted file mode 100644 index d91b8ef7e..000000000 --- a/crypto/src/asn1/cmp/GeneralPKIMessage.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Org.BouncyCastle.Asn1.Cmp -{ - public class GeneralPKIMessage - { - private readonly PkiMessage pkiMessage; - - private static PkiMessage parseBytes(byte[] encoding) - { - return PkiMessage.GetInstance(Asn1Object.FromByteArray(encoding)); - } - - public GeneralPKIMessage(PkiMessage pkiMessage) - { - this.pkiMessage = pkiMessage; - } - - public GeneralPKIMessage(byte[] encoding) : this(parseBytes(encoding)) - { - } - - public PkiHeader Header { - get { - return pkiMessage.Header; - } - } - - public PkiBody Body - { - get - { - return pkiMessage.Body; - } - } - - public bool HasProtection - { - get { return pkiMessage.Protection != null; } - } - - public PkiMessage ToAsn1Structure() - { - return pkiMessage; - } - } -} diff --git a/crypto/src/asn1/cmp/ProtectedPkiMessage.cs b/crypto/src/asn1/cmp/ProtectedPkiMessage.cs deleted file mode 100644 index c39f06ad0..000000000 --- a/crypto/src/asn1/cmp/ProtectedPkiMessage.cs +++ /dev/null @@ -1,107 +0,0 @@ -using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.X509; -using System; -using System.Collections.Generic; -using System.Text; -using Org.BouncyCastle.Asn1.Crmf; -using Org.BouncyCastle.Asn1.Pkcs; -using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Operators; -using Org.BouncyCastle.Crypto.Paddings; -using Org.BouncyCastle.Utilities; -using Org.BouncyCastle.Utilities.Encoders; - -namespace Org.BouncyCastle.Asn1.Cmp -{ - - public class ProtectedPkiMessage - { - private PkiMessage pkiMessage; - - - public ProtectedPkiMessage(GeneralPKIMessage pkiMessage) - { - - if (!pkiMessage.HasProtection) - { - throw new ArgumentException("pki message not protected"); - } - - this.pkiMessage = pkiMessage.ToAsn1Structure(); - } - - public ProtectedPkiMessage(PkiMessage pkiMessage) - { - if (pkiMessage.Header.ProtectionAlg == null) - { - throw new ArgumentException("pki message not protected"); - } - - this.pkiMessage = pkiMessage; - } - - public PkiHeader Header { get { return pkiMessage.Header; } } - public PkiBody Body { get { return pkiMessage.Body; } } - - public PkiMessage ToAsn1Message() { return pkiMessage; } - - public bool HasPasswordBasedMacProtected { get { return Header.ProtectionAlg.Algorithm.Equals(CmpObjectIdentifiers.passwordBasedMac); } } - - public X509Certificate[] GetCertificates() - { - CmpCertificate[] certs = pkiMessage.GetExtraCerts(); - - if (certs == null) - { - return new X509Certificate[0]; - } - - X509Certificate[] res = new X509Certificate[certs.Length]; - for (int t=0; t 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; - } - } - - -} -- cgit 1.4.1