public void Initialise()
            {
                SHA1Hasher.TryGetHashAndReset(Flusher, out _);
                SHA256Hasher.TryGetHashAndReset(Flusher, out _);
                NextOffsetToHash = 0;

                BlockHashesReleaser.Dispose();
                BlockHashesReleaser = default;
                BlockHashes         = default;
                Manager             = null;
                PieceIndex          = -1;
            }
Example #2
0
        private bool VerifyData(ReadOnlySpan <byte> data)
        {
            Oid hashAlgorithmId = TokenInfo.HashAlgorithmId;
            HashAlgorithmName hashAlgorithmName = PkcsHelpers.GetDigestAlgorithm(hashAlgorithmId);

            using (IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithmName))
            {
                hasher.AppendData(data);

                // SHA-2-512 is the biggest hash we currently know about.
                Span <byte> stackSpan = stackalloc byte[512 / 8];

                if (hasher.TryGetHashAndReset(stackSpan, out int bytesWritten))
                {
                    return(VerifyHash(stackSpan.Slice(0, bytesWritten), hashAlgorithmId.Value));
                }

                // Something we understood, but is bigger than 512-bit.
                // Allocate at runtime, trip in a debug build so we can re-evaluate this.
                Debug.Fail(
                    $"TryGetHashAndReset did not fit in {stackSpan.Length} for hash {hashAlgorithmId.Value}");

                return(VerifyHash(hasher.GetHashAndReset(), hashAlgorithmId.Value));
            }
        }
        private static void VerifyIncrementalResult_Span(HashAlgorithm referenceAlgorithm, IncrementalHash incrementalHash)
        {
            int referenceHashLength;

            byte[] referenceHash = new byte[1];
            while (!referenceAlgorithm.TryComputeHash(s_inputBytes, referenceHash, out referenceHashLength))
            {
                referenceHash = new byte[referenceHash.Length * 2];
            }

            const int StepA    = 13;
            const int StepB    = 7;
            int       position = 0;

            while (position < s_inputBytes.Length - StepA)
            {
                incrementalHash.AppendData(new ReadOnlySpan <byte>(s_inputBytes, position, StepA));
                position += StepA;
            }

            incrementalHash.AppendData(new ReadOnlySpan <byte>(s_inputBytes, position, s_inputBytes.Length - position));

            byte[] incrementalA = new byte[referenceHashLength];
            int    bytesWritten;

            Assert.True(incrementalHash.TryGetHashAndReset(incrementalA, out bytesWritten));
            Assert.Equal(referenceHashLength, bytesWritten);
            Assert.Equal <byte>(new Span <byte>(referenceHash, 0, referenceHashLength).ToArray(), new Span <byte>(incrementalA).Slice(0, bytesWritten).ToArray());

            // Now try again, verifying both immune to step size behaviors, and that GetHashAndReset resets.
            position = 0;

            while (position < s_inputBytes.Length - StepB)
            {
                incrementalHash.AppendData(new ReadOnlySpan <byte>(s_inputBytes, position, StepB));
                position += StepB;
            }

            incrementalHash.AppendData(new ReadOnlySpan <byte>(s_inputBytes, position, s_inputBytes.Length - position));

            byte[] incrementalB = new byte[referenceHashLength];
            Assert.True(incrementalHash.TryGetHashAndReset(incrementalB, out bytesWritten));
            Assert.Equal(referenceHashLength, bytesWritten);
            Assert.Equal <byte>(new Span <byte>(referenceHash, 0, referenceHashLength).ToArray(), incrementalB);
        }
 public static void VerifyTrivialHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm)
 {
     using (referenceAlgorithm)
         using (IncrementalHash incrementalHash = IncrementalHash.CreateHash(hashAlgorithm))
         {
             byte[] referenceHash     = referenceAlgorithm.ComputeHash(Array.Empty <byte>());
             byte[] incrementalResult = new byte[referenceHash.Length];
             Assert.True(incrementalHash.TryGetHashAndReset(incrementalResult, out int bytesWritten));
             Assert.Equal(referenceHash.Length, bytesWritten);
             Assert.Equal(referenceHash, incrementalResult);
         }
 }
Example #5
0
        public virtual bool TryGetCertHash(
            HashAlgorithmName hashAlgorithm,
            Span <byte> destination,
            out int bytesWritten)
        {
            ThrowIfInvalid();

            using (IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithm))
            {
                hasher.AppendData(Pal !.RawData);
                return(hasher.TryGetHashAndReset(destination, out bytesWritten));
            }
        }
        public static bool TryHash(IncrementalHash hasher, ReadOnlyMemory <byte> src, long startLayerLength, long endLayerLength, Span <byte> computedHash, out int written)
        {
            using var _ = MemoryPool.Default.Rent(((src.Length + 63) / 64) * 32, out Memory <byte> dest);
            while ((endLayerLength == -1 && src.Length != 32) || (endLayerLength != -1 && startLayerLength < endLayerLength))
            {
                for (int i = 0; i < src.Length / 64; i++)
                {
                    hasher.AppendData(src.Slice(i * 64, 64));
                    if (!hasher.TryGetHashAndReset(dest.Slice(i * 32, 32).Span, out written) || written != 32)
                    {
                        return(false);
                    }
                }
                if (src.Length % 64 == 32)
                {
                    hasher.AppendData(src.Slice(src.Length - 32, 32));
                    hasher.AppendData(FinalLayerHash[startLayerLength]);
                    if (!hasher.TryGetHashAndReset(dest.Slice(dest.Length - 32, 32).Span, out written) || written != 32)
                    {
                        return(false);
                    }
                }
                src               = dest;
                dest              = dest.Slice(0, ((dest.Length + 63) / 64) * 32);
                startLayerLength *= 2;
            }

            if (src.Length != 32)
            {
                throw new InvalidOperationException("Derpo");
            }

            written = 32;
            src.Span.Slice(0, written).CopyTo(computedHash);
            return(true);
        }
        public static void VerifyEmptyHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm)
        {
            using (referenceAlgorithm)
                using (IncrementalHash incrementalHash = IncrementalHash.CreateHash(hashAlgorithm))
                {
                    for (int i = 0; i < 10; i++)
                    {
                        incrementalHash.AppendData(ReadOnlySpan <byte> .Empty);
                    }

                    byte[] referenceHash     = referenceAlgorithm.ComputeHash(Array.Empty <byte>());
                    byte[] incrementalResult = new byte[referenceHash.Length];
                    Assert.True(incrementalHash.TryGetHashAndReset(incrementalResult, out int bytesWritten));
                    Assert.Equal(referenceHash.Length, bytesWritten);
                    Assert.Equal(referenceHash, incrementalResult);
                }
        }
Example #8
0
        public void SealWithMac(
            ReadOnlySpan <char> password,
            HashAlgorithmName hashAlgorithm,
            int iterationCount)
        {
            if (iterationCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(iterationCount));
            }
            if (IsSealed)
            {
                throw new InvalidOperationException(SR.Cryptography_Pkcs12_PfxIsSealed);
            }

            byte[]? rentedAuthSafe = null;
            Span <byte> authSafeSpan = default;

            byte[]? rentedMac = null;
            Span <byte> macSpan = default;
            Span <byte> salt    = stackalloc byte[0];

            try
            {
                AsnWriter contentsWriter = new AsnWriter(AsnEncodingRules.BER);

                using (IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithm))
                {
                    contentsWriter.PushSequence();
                    if (_contents != null)
                    {
                        foreach (ContentInfoAsn contentInfo in _contents)
                        {
                            contentInfo.Encode(contentsWriter);
                        }
                    }
                    contentsWriter.PopSequence();

                    rentedAuthSafe = CryptoPool.Rent(contentsWriter.GetEncodedLength());

                    if (!contentsWriter.TryEncode(rentedAuthSafe, out int written))
                    {
                        Debug.Fail("TryEncode failed with a pre-allocated buffer");
                        throw new InvalidOperationException();
                    }

                    authSafeSpan = rentedAuthSafe.AsSpan(0, written);

                    // Get an array of the proper size for the hash.
                    byte[] macKey = hasher.GetHashAndReset();
                    rentedMac = CryptoPool.Rent(macKey.Length);
                    macSpan   = rentedMac.AsSpan(0, macKey.Length);

                    // Since the biggest supported hash is SHA-2-512 (64 bytes), the
                    // 128-byte cap here shouldn't ever come into play.
                    Debug.Assert(macKey.Length <= 128);
                    salt = stackalloc byte[Math.Min(macKey.Length, 128)];
                    RandomNumberGenerator.Fill(salt);

                    Pkcs12Kdf.DeriveMacKey(
                        password,
                        hashAlgorithm,
                        iterationCount,
                        salt,
                        macKey);

                    using (IncrementalHash mac = IncrementalHash.CreateHMAC(hashAlgorithm, macKey))
                    {
                        mac.AppendData(authSafeSpan);

                        if (!mac.TryGetHashAndReset(macSpan, out int bytesWritten) || bytesWritten != macSpan.Length)
                        {
                            Debug.Fail($"TryGetHashAndReset wrote {bytesWritten} of {macSpan.Length} bytes");
                            throw new CryptographicException();
                        }
                    }
                }

                // https://tools.ietf.org/html/rfc7292#section-4
                //
                // PFX ::= SEQUENCE {
                //   version    INTEGER {v3(3)}(v3,...),
                //   authSafe   ContentInfo,
                //   macData    MacData OPTIONAL
                // }
                AsnWriter writer = new AsnWriter(AsnEncodingRules.BER);
                {
                    writer.PushSequence();

                    writer.WriteInteger(3);

                    writer.PushSequence();
                    {
                        writer.WriteObjectIdentifierForCrypto(Oids.Pkcs7Data);

                        Asn1Tag contextSpecific0 = new Asn1Tag(TagClass.ContextSpecific, 0);

                        writer.PushSequence(contextSpecific0);
                        {
                            writer.WriteOctetString(authSafeSpan);
                            writer.PopSequence(contextSpecific0);
                        }

                        writer.PopSequence();
                    }

                    // https://tools.ietf.org/html/rfc7292#section-4
                    //
                    // MacData ::= SEQUENCE {
                    //   mac        DigestInfo,
                    //   macSalt    OCTET STRING,
                    //   iterations INTEGER DEFAULT 1
                    //   -- Note: The default is for historical reasons and its use is
                    //   -- deprecated.
                    // }
                    writer.PushSequence();
                    {
                        writer.PushSequence();
                        {
                            writer.PushSequence();
                            {
                                writer.WriteObjectIdentifierForCrypto(PkcsHelpers.GetOidFromHashAlgorithm(hashAlgorithm));
                                writer.PopSequence();
                            }

                            writer.WriteOctetString(macSpan);
                            writer.PopSequence();
                        }

                        writer.WriteOctetString(salt);

                        if (iterationCount > 1)
                        {
                            writer.WriteInteger(iterationCount);
                        }

                        writer.PopSequence();
                    }

                    writer.PopSequence();
                    _sealedData = writer.Encode();
                }
            }
            finally
            {
                CryptographicOperations.ZeroMemory(macSpan);
                CryptographicOperations.ZeroMemory(authSafeSpan);

                if (rentedMac != null)
                {
                    // Already cleared
                    CryptoPool.Return(rentedMac, clearSize: 0);
                }

                if (rentedAuthSafe != null)
                {
                    // Already cleared
                    CryptoPool.Return(rentedAuthSafe, clearSize: 0);
                }
            }
        }
Example #9
0
        private static void Derive(
            ReadOnlySpan <char> password,
            HashAlgorithmName hashAlgorithm,
            int iterationCount,
            byte id,
            ReadOnlySpan <byte> salt,
            Span <byte> destination)
        {
            // https://tools.ietf.org/html/rfc7292#appendix-B.2
            Debug.Assert(iterationCount >= 1);

            if (!s_uvLookup.TryGetValue(hashAlgorithm, out Tuple <int, int>?uv))
            {
                throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name);
            }

            (int u, int v) = uv;

            Debug.Assert(v <= 1024);

            //  1. Construct a string, D (the "diversifier"), by concatenating v/8 copies of ID.
            int         vBytes = v >> 3;
            Span <byte> D      = stackalloc byte[vBytes];

            D.Fill(id);

            // 2.  Concatenate copies of the salt together to create a string S of
            // length v(ceiling(s/ v)) bits(the final copy of the salt may be
            // truncated to create S). Note that if the salt is the empty
            // string, then so is S.
            int SLen = ((salt.Length - 1 + vBytes) / vBytes) * vBytes;

            // The password is a null-terminated UTF-16BE version of the input.
            int passLen = checked ((password.Length + 1) * 2);

            // If password == default then the span represents the null string (as opposed to
            // an empty string), and the P block should then have size 0 in the next step.
            if (password == default)
            {
                passLen = 0;
            }

            // 3.  Concatenate copies of the password together to create a string P
            // of length v(ceiling(p/v)) bits (the final copy of the password
            // may be truncated to create P).  Note that if the password is the
            // empty string, then so is P.
            //
            // (The RFC quote considers the trailing '\0' to be part of the string,
            // so "empty string" from this RFC means "null string" in C#, and C#'s
            // "empty string" is not 'empty' in this context.)
            int PLen = ((passLen - 1 + vBytes) / vBytes) * vBytes;

            // 4.  Set I=S||P to be the concatenation of S and P.
            int         ILen = SLen + PLen;
            Span <byte> I    = stackalloc byte[0];

            byte[]? IRented = null;

            if (ILen <= 1024)
            {
                I = stackalloc byte[ILen];
            }
            else
            {
                IRented = CryptoPool.Rent(ILen);
                I       = IRented.AsSpan(0, ILen);
            }

            IncrementalHash hash = IncrementalHash.CreateHash(hashAlgorithm);

            try
            {
                CircularCopy(salt, I.Slice(0, SLen));
                CircularCopyUtf16BE(password, I.Slice(SLen));

                int uBytes = u >> 3;

                Span <byte> hashBuf = stackalloc byte[uBytes];
                Span <byte> bBuf    = stackalloc byte[vBytes];

                // 5.  Set c=ceiling(n/u).
                // 6.  For i=1, 2, ..., c, do the following:
                // (later we're going to start writing A_i values as output,
                // they mean "while work remains").
                while (true)
                {
                    // A.  Set A_i=H^r(D||I). (i.e., the r-th hash of D||I,
                    // H(H(H(... H(D || I))))
                    hash.AppendData(D);
                    hash.AppendData(I);

                    for (int j = iterationCount; j > 0; j--)
                    {
                        if (!hash.TryGetHashAndReset(hashBuf, out int bytesWritten) || bytesWritten != hashBuf.Length)
                        {
                            Debug.Fail($"Hash output wrote {bytesWritten} bytes when {hashBuf.Length} was expected");
                            throw new CryptographicException();
                        }

                        if (j != 1)
                        {
                            hash.AppendData(hashBuf);
                        }
                    }

                    // 7.  Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
                    // bit string, A.
                    //
                    // 8.  Use the first n bits of A as the output of this entire process.

                    if (hashBuf.Length >= destination.Length)
                    {
                        hashBuf.Slice(0, destination.Length).CopyTo(destination);
                        return;
                    }

                    hashBuf.CopyTo(destination);
                    destination = destination.Slice(hashBuf.Length);

                    // B.  Concatenate copies of A_i to create a string B of length v
                    // bits(the final copy of Ai may be truncated to create B).
                    CircularCopy(hashBuf, bBuf);

                    // C.  Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
                    // blocks, where k = ceiling(s / v) + ceiling(p / v), modify I by
                    // setting I_j = (I_j + B + 1) mod 2 ^ v for each j.
                    for (int j = (I.Length / vBytes) - 1; j >= 0; j--)
                    {
                        Span <byte> I_j = I.Slice(j * vBytes, vBytes);
                        AddPlusOne(I_j, bBuf);
                    }
                }
            }
            finally
            {
                CryptographicOperations.ZeroMemory(I);

                if (IRented != null)
                {
                    CryptoPool.Return(IRented, clearSize: 0);
                }

                hash.Dispose();
            }
        }
Example #10
0
        internal bool VerifyMac(
            ReadOnlySpan <char> macPassword,
            ReadOnlySpan <byte> authSafeContents)
        {
            Debug.Assert(MacData.HasValue);

            HashAlgorithmName hashAlgorithm;
            int expectedOutputSize;

            string algorithmValue = MacData.Value.Mac.DigestAlgorithm.Algorithm;

            switch (algorithmValue)
            {
            case Oids.Md5:
                expectedOutputSize = 128 >> 3;
                hashAlgorithm      = HashAlgorithmName.MD5;
                break;

            case Oids.Sha1:
                expectedOutputSize = 160 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA1;
                break;

            case Oids.Sha256:
                expectedOutputSize = 256 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA256;
                break;

            case Oids.Sha384:
                expectedOutputSize = 384 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA384;
                break;

            case Oids.Sha512:
                expectedOutputSize = 512 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA512;
                break;

            default:
                throw new CryptographicException(
                          SR.Format(SR.Cryptography_UnknownHashAlgorithm, algorithmValue));
            }

            if (MacData.Value.Mac.Digest.Length != expectedOutputSize)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

#if NETCOREAPP
            Debug.Assert(expectedOutputSize <= 64); // SHA512 is the largest digest size we know about
            Span <byte> derived = stackalloc byte[expectedOutputSize];
#else
            byte[] derived = new byte[expectedOutputSize];
#endif


            int iterationCount =
                PasswordBasedEncryption.NormalizeIterationCount(MacData.Value.IterationCount);

            Pkcs12Kdf.DeriveMacKey(
                macPassword,
                hashAlgorithm,
                iterationCount,
                MacData.Value.MacSalt.Span,
                derived);

            using (IncrementalHash hmac = IncrementalHash.CreateHMAC(hashAlgorithm, derived))
            {
                hmac.AppendData(authSafeContents);

                if (!hmac.TryGetHashAndReset(derived, out int bytesWritten) || bytesWritten != expectedOutputSize)
                {
                    Debug.Fail($"TryGetHashAndReset wrote {bytesWritten} bytes when {expectedOutputSize} was expected");
                    throw new CryptographicException();
                }

                return(CryptographicOperations.FixedTimeEquals(
                           derived,
                           MacData.Value.Mac.Digest.Span));
            }
        }
Example #11
0
        public bool VerifyMac(ReadOnlySpan <char> password)
        {
            if (IntegrityMode != Pkcs12IntegrityMode.Password)
            {
                throw new InvalidOperationException(
                          SR.Format(
                              SR.Cryptography_Pkcs12_WrongModeForVerify,
                              Pkcs12IntegrityMode.Password,
                              IntegrityMode));
            }

            Debug.Assert(_decoded.MacData.HasValue);

            HashAlgorithmName hashAlgorithm;
            int expectedOutputSize;

            string algorithmValue = _decoded.MacData.Value.Mac.DigestAlgorithm.Algorithm.Value;

            switch (algorithmValue)
            {
            case Oids.Md5:
                expectedOutputSize = 128 >> 3;
                hashAlgorithm      = HashAlgorithmName.MD5;
                break;

            case Oids.Sha1:
                expectedOutputSize = 160 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA1;
                break;

            case Oids.Sha256:
                expectedOutputSize = 256 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA256;
                break;

            case Oids.Sha384:
                expectedOutputSize = 384 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA384;
                break;

            case Oids.Sha512:
                expectedOutputSize = 512 >> 3;
                hashAlgorithm      = HashAlgorithmName.SHA512;
                break;

            default:
                throw new CryptographicException(
                          SR.Format(SR.Cryptography_UnknownHashAlgorithm, algorithmValue));
            }

            if (_decoded.MacData.Value.Mac.Digest.Length != expectedOutputSize)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            // Cannot use the ArrayPool or stackalloc here because CreateHMAC needs a properly bounded array.
            byte[] derived = new byte[expectedOutputSize];

            int iterationCount =
                PasswordBasedEncryption.NormalizeIterationCount(_decoded.MacData.Value.IterationCount);

            Pkcs12Kdf.DeriveMacKey(
                password,
                hashAlgorithm,
                iterationCount,
                _decoded.MacData.Value.MacSalt.Span,
                derived);

            using (IncrementalHash hmac = IncrementalHash.CreateHMAC(hashAlgorithm, derived))
            {
                hmac.AppendData(_authSafeContents.Span);

                if (!hmac.TryGetHashAndReset(derived, out int bytesWritten) || bytesWritten != expectedOutputSize)
                {
                    Debug.Fail($"TryGetHashAndReset wrote {bytesWritten} bytes when {expectedOutputSize} was expected");
                    throw new CryptographicException();
                }

                return(CryptographicOperations.FixedTimeEquals(
                           derived,
                           _decoded.MacData.Value.Mac.Digest.Span));
            }
        }
Example #12
0
        private static unsafe byte[] MacAndEncode(
            AsnWriter tmpWriter,
            ReadOnlyMemory <byte> encodedAuthSafe,
            ReadOnlySpan <char> passwordSpan)
        {
            // Windows/macOS compatibility: Use HMAC-SHA-1,
            // other algorithms may not be understood
            byte[]            macKey        = new byte[20];
            Span <byte>       macSalt       = stackalloc byte[20];
            Span <byte>       macSpan       = stackalloc byte[20];
            HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA1;

            RandomNumberGenerator.Fill(macSalt);

            fixed(byte *macKeyPtr = macKey)
            {
                Span <byte> macKeySpan = macKey;

                Pkcs12Kdf.DeriveMacKey(
                    passwordSpan,
                    hashAlgorithm,
                    s_windowsPbe.IterationCount,
                    macSalt,
                    macKeySpan);

                using (IncrementalHash mac = IncrementalHash.CreateHMAC(hashAlgorithm, macKey))
                {
                    mac.AppendData(encodedAuthSafe.Span);

                    if (!mac.TryGetHashAndReset(macSpan, out int bytesWritten) || bytesWritten != macSpan.Length)
                    {
                        Debug.Fail($"TryGetHashAndReset wrote {bytesWritten} of {macSpan.Length} bytes");
                        throw new CryptographicException();
                    }
                }

                CryptographicOperations.ZeroMemory(macKeySpan);
            }

            // https://tools.ietf.org/html/rfc7292#section-4
            //
            // PFX ::= SEQUENCE {
            //   version    INTEGER {v3(3)}(v3,...),
            //   authSafe   ContentInfo,
            //   macData    MacData OPTIONAL
            // }
            Debug.Assert(tmpWriter.GetEncodedLength() == 0);
            tmpWriter.PushSequence();

            tmpWriter.WriteInteger(3);

            tmpWriter.PushSequence();
            {
                tmpWriter.WriteObjectIdentifier(Oids.Pkcs7Data);

                tmpWriter.PushSequence(s_contextSpecific0);
                {
                    tmpWriter.WriteOctetString(encodedAuthSafe.Span);
                    tmpWriter.PopSequence(s_contextSpecific0);
                }

                tmpWriter.PopSequence();
            }

            // https://tools.ietf.org/html/rfc7292#section-4
            //
            // MacData ::= SEQUENCE {
            //   mac        DigestInfo,
            //   macSalt    OCTET STRING,
            //   iterations INTEGER DEFAULT 1
            //   -- Note: The default is for historical reasons and its use is
            //   -- deprecated.
            // }
            tmpWriter.PushSequence();
            {
                tmpWriter.PushSequence();
                {
                    tmpWriter.PushSequence();
                    {
                        tmpWriter.WriteObjectIdentifier(Oids.Sha1);
                        tmpWriter.PopSequence();
                    }

                    tmpWriter.WriteOctetString(macSpan);
                    tmpWriter.PopSequence();
                }

                tmpWriter.WriteOctetString(macSalt);
                tmpWriter.WriteInteger(s_windowsPbe.IterationCount);

                tmpWriter.PopSequence();
            }

            tmpWriter.PopSequence();
            return(tmpWriter.Encode());
        }
Example #13
0
 public void Initialise()
 {
     Hasher.TryGetHashAndReset(Flusher, out _);
     NextOffsetToHash = 0;
 }