<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0-beta.98" />

PKMacBuilder

public class PKMacBuilder
using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cmp; using Org.BouncyCastle.Asn1.Iana; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crmf { public class PKMacBuilder { private AlgorithmIdentifier owf; private AlgorithmIdentifier mac; private IPKMacPrimitivesProvider provider; private SecureRandom random; private PbmParameter parameters; private int iterationCount; private int saltLength = 20; private readonly 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, AlgorithmIdentifier digestAlgorithmIdentifier, AlgorithmIdentifier macAlgorithmIdentifier) : this(digestAlgorithmIdentifier, 1000, macAlgorithmIdentifier, 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; mac = macAlgorithmIdentifier; owf = digestAlgorithmIdentifier; this.provider = provider; } 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 SetSecureRandom(SecureRandom random) { this.random = random; return this; } public PKMacBuilder SetParameters(PbmParameter parameters) { CheckIterationCountCeiling(parameters.IterationCount.IntValueExact); this.parameters = parameters; return this; } public IMacFactory Get(AlgorithmIdentifier algorithm, char[] password) { return Get(algorithm, password.AsSpan()); } public IMacFactory Get(AlgorithmIdentifier algorithm, ReadOnlySpan<char> password) { if (!CmpObjectIdentifiers.passwordBasedMac.Equals(algorithm.Algorithm)) throw new ArgumentException("protection algorithm not mac based", "algorithm"); SetParameters(PbmParameter.GetInstance(algorithm.Parameters)); return Build(password); } public IMacFactory Build(char[] password) { return Build(password.AsSpan()); } public IMacFactory Build(ReadOnlySpan<char> password) { PbmParameter pbmParameter = parameters; if (pbmParameter == null) pbmParameter = GenParameters(); return GenCalculator(pbmParameter, password); } private void CheckIterationCountCeiling(int iterationCount) { if (maxIterations > 0 && iterationCount > maxIterations) throw new ArgumentException("iteration count exceeds limit (" + iterationCount.ToString() + " > " + maxIterations.ToString() + ")"); } private IMacFactory GenCalculator(PbmParameter parameters, ReadOnlySpan<char> password) { return GenCalculator(parameters, Strings.ToUtf8ByteArray(password)); } private IMacFactory GenCalculator(PbmParameter parameters, byte[] pw) { byte[] octets = parameters.Salt.GetOctets(); byte[] array = new byte[pw.Length + octets.Length]; Array.Copy(pw, 0, array, 0, pw.Length); Array.Copy(octets, 0, array, pw.Length, octets.Length); IDigest digest = provider.CreateDigest(parameters.Owf); int num = parameters.IterationCount.IntValueExact; digest.BlockUpdate(array, 0, array.Length); array = new byte[digest.GetDigestSize()]; digest.DoFinal(array, 0); while (--num > 0) { digest.BlockUpdate(array, 0, array.Length); digest.DoFinal(array, 0); } return new PKMacFactory(array, parameters); } private PbmParameter GenParameters() { return new PbmParameter(SecureRandom.GetNextBytes(CryptoServicesRegistrar.GetSecureRandom(random), saltLength), owf, iterationCount, mac); } } }