public void SignMessage(SipMessageWriter writer)
            {
                outSnum++;
                int srand2 = Environment.TickCount;

                InitializeThreadStaticVars();

                int length = SignatureBuffer.Generate(scheme, srand2, outSnum, targetname, writer, ref bytes1);

                if (bytes2.Length < maxSignatureSize)
                {
                    bytes2 = new byte[maxSignatureSize];
                }

                secBufferDesc1.Buffers[0].SetBuffer(BufferType.SECBUFFER_DATA, bytes1, 0, length);
                secBufferDesc1.Buffers[1].SetBuffer(BufferType.SECBUFFER_TOKEN, bytes2);

                var result = Sspi.SafeMakeSignature(contextHandle, ref secBufferDesc1, 100);

                Tracer.WriteInformation("Signature: " + result.ToString());

                if (Sspi.Succeeded(result))
                {
                    writer.WriteAuthenticationInfo(true, scheme, targetname, realm, Opaque, outSnum, srand2,
                                                   new ArraySegment <byte>(bytes2, 0, secBufferDesc1.Buffers[1].Size));

                    if (writer.IsResponse && writer.StatusCode >= 200 && writer.StatusCode <= 299)
                    {
                        if (writer.Method == Methods.Registerm && writer.Expires != int.MinValue)
                        {
                            idleTime = DateTime.UtcNow.AddSeconds(writer.Expires + 30);
                            idleTimeUpdatedByExpires = true;
                        }
                    }
                    else
                    {
                        // TODO: INVITE Session-Expires
                    }
                }
            }
            public bool VerifySignature(SipMessageReader reader, Credentials credentials)
            {
                bool result = false;

                InitializeThreadStaticVars();

                int length = SignatureBuffer.Generate(scheme, credentials.Crand, credentials.Cnum, targetname, reader, ref bytes1);

                secBufferDesc1.Buffers[0].SetBuffer(BufferType.SECBUFFER_DATA, bytes1, 0, length);

                if (bytes2.Length < credentials.Response.Length / 2)
                {
                    bytes2 = new byte[credentials.Response.Length];
                }

                if (HexEncoding.TryParseHex(credentials.Response.ToArraySegment(), bytes2) >= 0)
                {
                    secBufferDesc1.Buffers[1].SetBuffer(BufferType.SECBUFFER_TOKEN, bytes2, 0, credentials.Response.Length / 2);

                    var result2 = Sspi.SafeVerifySignature(contextHandle, ref secBufferDesc1, 100);

                    Tracer.WriteInformation("VerifySignature: " + result2.ToString());

                    result = Sspi.Succeeded(result2);
                }

                {
                    //if (auth.Cnum > _LastCnum + SlidingWindowSize || auth.Cnum < _LastCnum - SlidingWindowSize || auth.Cnum == 0)
                    //    // cnum в не скользящего окна
                    //    throw new AuthenticationManager.MessageDiscardException();

                    //// индекс верхней границы скользящего окна
                    //int index = auth.Cnum >= SlidingWindowSize ? (auth.Cnum - SlidingWindowSize) % SlidingWindowSize : auth.Cnum - 1;
                    //if (auth.Cnum > _LastCnum)
                    //{
                    //    // индекс нижней границы скользящего окна
                    //    int lindex = _LastCnum >= SlidingWindowSize ? (_LastCnum - SlidingWindowSize + 1) % SlidingWindowSize : _LastCnum;

                    //    // смещение скользящего окна
                    //    if (lindex > index)
                    //    {
                    //        while (lindex < SlidingWindowSize)
                    //            _SlidingWindow[lindex++] = false;
                    //        lindex = 0;
                    //    }

                    //    while (lindex < index)
                    //        _SlidingWindow[lindex++] = false;

                    //    _LastCnum = auth.Cnum;
                    //}
                    //else
                    //{
                    //    if (_SlidingWindow[index] == true)
                    //        // дублирование cnum
                    //        throw new AuthenticationManager.MessageDiscardException();
                    //}

                    //_SlidingWindow[index] = true;

                    // удаление обработанного поля заголовка
                    //message.Header.Headers[message.Header.FindHeaderIndex(auth_name, auth_index)].IsRemoved = true;


                    //message.Verified = true;
                }

                if (idleTimeUpdatedByExpires == false)
                {
                    idleTime = DateTime.UtcNow.AddMinutes(IdleMinutes);
                }

                return(result);
            }