예제 #1
0
        public void GenerateSessionKey(byte[] clientSalt, byte[] serverSalt)
        {
            var hmac          = new HMACSHA1(SecureRemotePassword.SessionKey);
            var wow           = Encoding.ASCII.GetBytes("WoW\0");
            var wowSessionKey = new byte[0x28];

            hmac.TransformBlock(wow, 0, wow.Length, wow, 0);
            hmac.TransformBlock(clientSalt, 0, clientSalt.Length, clientSalt, 0);
            hmac.TransformFinalBlock(serverSalt, 0, serverSalt.Length);

            Buffer.BlockCopy(hmac.Hash, 0, wowSessionKey, 0, hmac.Hash.Length);

            hmac.Initialize();
            hmac.TransformBlock(wow, 0, wow.Length, wow, 0);
            hmac.TransformBlock(serverSalt, 0, serverSalt.Length, serverSalt, 0);
            hmac.TransformFinalBlock(clientSalt, 0, clientSalt.Length);

            Buffer.BlockCopy(hmac.Hash, 0, wowSessionKey, hmac.Hash.Length, hmac.Hash.Length);

            GameAccount.SessionKey = wowSessionKey.ToHexString();

            // Update SessionKey in database
            DB.Auth.Update(GameAccount, "SessionKey");
        }
예제 #2
0
파일: Message.cs 프로젝트: sjl421/Pyrolite
 /// <summary>
 /// returns the hmac of the data and the annotation chunk values (except HMAC chunk itself)
 /// </summary>
 public byte[] hmac(byte[] key)
 {
     using (HMACSHA1 hmac = new HMACSHA1(key)) {
         hmac.TransformBlock(this.data, 0, this.data.Length, this.data, 0);
         foreach (var e in this.annotations.OrderBy(a => a.Key))
         {
             if (e.Key != "HMAC")
             {
                 hmac.TransformBlock(e.Value, 0, e.Value.Length, e.Value, 0);
             }
         }
         hmac.TransformFinalBlock(this.data, 0, 0);
         return(hmac.Hash);
     }
 }
예제 #3
0
        /// <summary>
        /// Performs an encryption using AES/CBC/PKCS7 with an input byte array and key, with a IV (comprised of random bytes and the HMAC-SHA1 of the random bytes and plaintext) prepended using AES/ECB/None
        /// </summary>
        public static byte[] SymmetricEncryptWithHMACIV(byte[] input, byte[] key, byte[] hmacSecret)
        {
            // IV is HMAC-SHA1(Random(3) + Plaintext) + Random(3). (Same random values for both)
            var iv     = new byte[16];
            var random = GenerateRandomBlock(3);

            Array.Copy(random, 0, iv, iv.Length - random.Length, random.Length);

            using (var hmac = new HMACSHA1(hmacSecret))
            {
                hmac.TransformBlock(random, 0, random.Length, null, 0);
                hmac.TransformFinalBlock(input, 0, input.Length);
                Array.Copy(hmac.Hash, iv, iv.Length - random.Length);
            }

            return(SymmetricEncryptWithIV(input, key, iv));
        }
예제 #4
0
 public byte[] pyrohmac(byte[] data, IDictionary <string, byte[]> annotations)
 {
     using (HMACSHA1 hmac = new HMACSHA1(Config.HMAC_KEY)) {
         hmac.TransformBlock(data, 0, data.Length, data, 0);
         if (annotations != null)
         {
             foreach (var e in annotations)
             {
                 if (e.Key != "HMAC")
                 {
                     hmac.TransformBlock(e.Value, 0, e.Value.Length, e.Value, 0);
                 }
             }
         }
         hmac.TransformFinalBlock(data, 0, 0);
         return(hmac.Hash);
     }
 }
예제 #5
0
        /// <summary>
        /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream.
        /// </summary>
        public byte[] GetAuthCode()
        {
            // We usually don't get advance notice of final block. Hash requres a TransformFinal.
            if (!_finalised)
            {
                byte[] dummy = new byte[0];
#if NET45
                _hmacsha1.TransformFinalBlock(dummy, 0, 0);
#elif NETSTANDARD1_3
                _hmacsha1.AppendData(dummy);
#endif
                _finalised = true;
            }
#if NET45
            return(_hmacsha1.Hash);
#elif NETSTANDARD1_3
            return(_hmacsha1.GetHashAndReset());
#endif
        }
예제 #6
0
        /// <summary>
        /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream.
        /// </summary>
        public byte[] GetAuthCode()
        {
            // We usually don't get advance notice of final block. Hash requres a TransformFinal.
            if (!_finalised)
            {
                var dummy = new byte[0];

#if !OS_WINDOWS
                incrementalHash.AppendData(dummy, 0, 0);
#else
                _hmacsha1.TransformFinalBlock(dummy, 0, 0);
#endif
                _finalised = true;
            }
#if !OS_WINDOWS
            byte[] incrementalA = incrementalHash.GetHashAndReset();
            return(incrementalA);
#else
            return(_hmacsha1.Hash);
#endif
        }
예제 #7
0
        private int ReadTransformOneBlock(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new NotSupportedException();
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // Determine if this is the final block
            if ((bytesToRead == bytesRemaining) &&
                (_length > 0) &&
                (_totalBytesXferred + last == _length))
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
                counterOut = _xform.TransformFinalBlock(counter,
                                                        0,
                                                        BLOCK_SIZE_IN_BYTES);
                _finalBlock = true;
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0);  // offset
            }

            XorInPlace(buffer, offset, bytesToRead);
            return(bytesToRead);
        }
예제 #8
0
        // This function is defined as follow :
        // Func (S, i) = HMAC(S || i) | HMAC2(S || i) | ... | HMAC(iterations) (S || i)
        // where i is the block number.
        private byte[] Func()
        {
            byte[] INT_block = Int(m_block);

            m_hmacsha1.TransformBlock(m_salt, 0, m_salt.Length, m_salt, 0);
            m_hmacsha1.TransformFinalBlock(INT_block, 0, INT_block.Length);
            byte[] temp = m_hmacsha1.Hash;
            m_hmacsha1.Initialize();

            byte[] ret = temp;
            for (int i = 2; i <= m_iterations; i++)
            {
                temp = m_hmacsha1.ComputeHash(temp);
                for (int j = 0; j < BlockSize; j++)
                {
                    ret[j] ^= temp[j];
                }
            }

            // increment the block count.
            m_block++;
            return(ret);
        }
예제 #9
0
        private int ReadTransformOneBlock(byte[] buffer, int offset, int last)
        {
            if (isFinalBlock)
            {
                throw new InvalidOperationException();
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                                  ? BLOCK_SIZE_IN_BYTES
                                  : bytesRemaining;

            // update the counter
            Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // Determine if this is the final block
            if ((bytesToRead == bytesRemaining) && (totalBytesLeftToRead == 0))
            {
                hmac.TransformFinalBlock(buffer, offset, bytesToRead);
                counterOut = transform.TransformFinalBlock(counter,
                                                           0,
                                                           BLOCK_SIZE_IN_BYTES);
                isFinalBlock = true;
            }
            else
            {
                hmac.TransformBlock(buffer, offset, bytesToRead, null, 0);
                transform.TransformBlock(counter,
                                         0, // offset
                                         BLOCK_SIZE_IN_BYTES,
                                         counterOut,
                                         0); // offset
            }

            XorInPlace(buffer, offset, bytesToRead);
            return(bytesToRead);
        }
예제 #10
0
        /// <summary>
        /// Returns the SHA1 HMAC of the given <paramref name="prefix"/>, the given <paramref name="request"/>'s
        /// body, and the given <paramref name="suffix"/> (in that order).
        /// </summary>
        /// <param name="request">The current <see cref="HttpRequest"/>.</param>
        /// <param name="secret">The key data used to initialize the <see cref="HMACSHA1"/>.</param>
        /// <param name="prefix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// before the <paramref name="request"/>'s body.
        /// </param>
        /// <param name="suffix">
        /// If non-<see langword="null"/> and non-empty, additional <c>byte</c>s to include in the hashed content
        /// after the <paramref name="request"/>'s body.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> that on completion provides a <see cref="byte"/> array containing the SHA1 HMAC of
        /// the <paramref name="prefix"/>, the <paramref name="request"/>'s body, and the <paramref name="suffix"/>
        /// (in that order).
        /// </returns>
        protected virtual async Task <byte[]> ComputeRequestBodySha1HashAsync(
            HttpRequest request,
            byte[] secret,
            byte[] prefix,
            byte[] suffix)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            if (secret == null)
            {
                throw new ArgumentNullException(nameof(secret));
            }
            if (secret.Length == 0)
            {
                throw new ArgumentException(Resources.General_ArgumentCannotBeNullOrEmpty);
            }

            await WebHookHttpRequestUtilities.PrepareRequestBody(request);

            using (var hasher = new HMACSHA1(secret))
            {
                try
                {
                    if (prefix != null && prefix.Length > 0)
                    {
                        hasher.TransformBlock(
                            prefix,
                            inputOffset: 0,
                            inputCount: prefix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    // Split body into 4K chunks.
                    var buffer      = new byte[4096];
                    var inputStream = request.Body;
                    int bytesRead;
                    while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        hasher.TransformBlock(
                            buffer,
                            inputOffset: 0,
                            inputCount: bytesRead,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    if (suffix != null && suffix.Length > 0)
                    {
                        hasher.TransformBlock(
                            suffix,
                            inputOffset: 0,
                            inputCount: suffix.Length,
                            outputBuffer: null,
                            outputOffset: 0);
                    }

                    hasher.TransformFinalBlock(Array.Empty <byte>(), inputOffset: 0, inputCount: 0);

                    return(hasher.Hash);
                }
                finally
                {
                    // Reset Position because JsonInputFormatter et cetera always start from current position.
                    request.Body.Seek(0L, SeekOrigin.Begin);
                }
            }
        }
예제 #11
0
        private int ProcessOneBlockWriting(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new Exception("The final block has already been transformed.");
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);


            if (bytesToRead == (last - offset))
            {
                // We're doing the last bytes in this batch.
                //
                // For the AES encryption stream to work properly, We must transform full
                // blocks of 16 bytes each, until the very last one.  But, we don't know
                // how to recognize the "last" bytes.  The approach taken here: buffer
                // the last full or partial block of bytes in a batch.  Then at time of
                // Close(), we set the _NextXformWillBeFinal flag and flush that buffer.
                //
                // This works when the caller writes in odd-sized batches, for example
                // 5000 bytes, or in batches that are neat multiples of block-size (16).


                if (_NextXformWillBeFinal)
                {
                    //Console.WriteLine("WinZipAesCipherStream::ProcessOneBlockWriting:   _NextXformWillBeFinal = true");
                    counterOut = _xform.TransformFinalBlock(counter,
                                                            0,
                                                            BLOCK_SIZE_IN_BYTES);
                    _finalBlock = true;
                }

                else if (buffer == _PendingWriteBuffer && bytesToRead == BLOCK_SIZE_IN_BYTES)
                {
//          Console.WriteLine("POBW({0},{1,5},{2,5}): pc({4})  flushing {3} bytes ...",
//                    _NextXformWillBeFinal, offset, last, bytesToRead, _pendingCount);
                }


                else
                {
                    // NOT the final block, therefore buffer it.

//          Console.WriteLine("POBW({0},{1,5},{2,5}): pc({4})  buffering {3} more bytes ...",
//                    _NextXformWillBeFinal, offset, last, bytesToRead, _pendingCount);

                    Array.Copy(buffer, offset,
                               _PendingWriteBuffer, _pendingCount,
                               bytesToRead);

                    _pendingCount += bytesToRead;

                    // remember to decrement the nonce.
                    _nonce--;
                    return(0);
                }
            }


            if (!_finalBlock)
            {
                // Next, do the AES transform.  According to the AES/CTR method used
                // by WinZip, apply the transform to the counter, and then XOR
                // the result with the ciphertext to get the plaintext.
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0); // offset
            }


            // XOR (in place)
            //Console.Write("POBW({0},{1,5},{2,5}): ", _NextXformWillBeFinal, offset, last);
            for (int i = 0; i < bytesToRead; i++)
            {
                buffer[offset + i] = (byte)(counterOut[i] ^ buffer[offset + i]);
                //Console.Write("{0:X2} ", buffer[offset + i]);
            }
            //Console.WriteLine();

            // when encrypting, do the MAC last
            if (_finalBlock)
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
            }

            return(bytesToRead);
        }
예제 #12
0
        private int ProcessOneBlockWriting(byte[] buffer, int offset, int last)
        {
            if (_finalBlock)
            {
                throw new InvalidOperationException("The final block has already been transformed.");
            }

            int bytesRemaining = last - offset;
            int bytesToRead    = (bytesRemaining > BLOCK_SIZE_IN_BYTES)
                ? BLOCK_SIZE_IN_BYTES
                : bytesRemaining;

            // update the counter
            System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4);

            // We're doing the last bytes in this batch.
            //
            // For the AES encryption stream to work properly, We must transform
            // blocks of 16 bytes, via TransformBlock, until the very last one, for
            // which we call TransformFinalBlock.  But, we don't know how to
            // recognize the "last" bytes.  The approach taken here: maintain a
            // buffer, so that one full or partial block of bytes is always
            // available.  This is the _PendingWriteBuffer.  Then at time of
            // Close(), we set the _NextXformWillBeFinal flag and flush that buffer.
            //
            // This works whether the caller writes in odd-sized batches, for example
            // 5000 bytes, or in batches that are neat multiples of the blocksize (16).


            // bytesToRead is always 16 or less.  If it is exactly what remains, then we need to
            // either, if this is the final block, do the final transform, else buffer the data.
            if (bytesToRead == (last - offset))
            {
                if (_NextXformWillBeFinal)
                {
                    //Console.WriteLine("WinZipAesCipherStream::ProcessOneBlockWriting:   _NextXformWillBeFinal = true");
                    counterOut = _xform.TransformFinalBlock(counter,
                                                            0,
                                                            BLOCK_SIZE_IN_BYTES);
                    _finalBlock = true;
                }

                else if (buffer == _PendingWriteBuffer && bytesToRead == BLOCK_SIZE_IN_BYTES)
                {
                    // this happens with a Flush(), I think.
                }

                else
                {
                    // NOT the final block, therefore buffer it.

                    Array.Copy(buffer, offset,
                               _PendingWriteBuffer, _pendingCount,
                               bytesToRead);

                    _pendingCount += bytesToRead;

                    // remember to decrement the nonce.
                    _nonce--;
                    return(bytesToRead);
                }
            }

            if (!_finalBlock)
            {
                // Next, do the AES transform.  According to the AES/CTR method used
                // by WinZip, apply the transform to the counter, and then XOR
                // the result with the ciphertext to get the plaintext.
                _xform.TransformBlock(counter,
                                      0, // offset
                                      BLOCK_SIZE_IN_BYTES,
                                      counterOut,
                                      0);  // offset
            }

            // XOR (in place)
            for (int i = 0; i < bytesToRead; i++)
            {
                buffer[offset + i] = (byte)(counterOut[i] ^ buffer[offset + i]);
            }

            // when encrypting, do the MAC last
            if (_finalBlock)
            {
                _mac.TransformFinalBlock(buffer, offset, bytesToRead);
            }
            else
            {
                _mac.TransformBlock(buffer, offset, bytesToRead, null, 0);
            }

            return(bytesToRead);
        }
예제 #13
0
        /// <summary>
        /// <exception cref="IOException"/>
        /// <exception cref="SpotifyAuthenticatedException"/>
        /// <exception cref="AccessViolationException"/>
        /// </summary>
        private void Connect()
        {
            #region ClientHello Setup

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            var clientHello = new ClientHello
            {
                BuildInfo = new BuildInfo
                {
                    Platform     = Platform.Win32X86,
                    Product      = Product.Client,
                    ProductFlags = { ProductFlags.ProductFlagNone },
                    Version      = 112800721
                }
            };
            clientHello.CryptosuitesSupported.Add(Cryptosuite.Shannon);
            clientHello.LoginCryptoHello = new LoginCryptoHelloUnion
            {
                DiffieHellman = new LoginCryptoDiffieHellmanHello
                {
                    Gc = ByteString.CopyFrom(keys.PublicKeyArray()),
                    ServerKeysKnown = 1
                }
            };

            var nonce = new byte[16];
            (new Random()).NextBytes(nonce);
            clientHello.ClientNonce = ByteString.CopyFrom(nonce);
            clientHello.Padding     = ByteString.CopyFrom(new byte[1]
            {
                (byte)30
            });

            var clientHelloBytes = clientHello.ToByteArray();

            var a = conn.Result.NetworkStream;
            a.WriteByte(0x00);
            a.WriteByte(0x04);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.Flush();

            var length = 2 + 4 + clientHelloBytes.Length;
            var bytes  = BitConverter.GetBytes(length);
            a.WriteByte(bytes[0]);
            a.Write(clientHelloBytes, 0, clientHelloBytes.Length);
            a.Flush();
            var buffer = new byte[1000];
            var len    = int.Parse(a.Read(buffer, 0, buffer.Length).ToString());
            var tmp    = new byte[len];
            Array.Copy(buffer, tmp, len);

            tmp = tmp.Skip(4).ToArray();
            var accumulator = new MemoryStream();
            accumulator.WriteByte(0x00);
            accumulator.WriteByte(0x04);

            var lnarr = Utils.toByteArray(length);
            accumulator.Write(lnarr, 0, lnarr.Length);
            accumulator.Write((byte[])clientHelloBytes, 0, clientHelloBytes.Length);

            var lenArr = Utils.toByteArray(len);
            accumulator.Write(lenArr, 0, lenArr.Length);
            accumulator.Write((byte[])tmp, 0, tmp.Length);

            #endregion ClientHello Setup

            //Read APResponseMessage

            #region APResponse

            var binaryData        = accumulator.ToArray();
            var apResponseMessage = APResponseMessage.Parser.ParseFrom(tmp);
            var sharedKey         = Utils.toByteArray(keys.ComputeSharedKey(apResponseMessage
                                                                            .Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray()));

            // Check gs_signature
            var rsa        = new RSACryptoServiceProvider();
            var rsaKeyInfo = new RSAParameters
            {
                Modulus  = new BigInteger(1, serverKey).ToByteArrayUnsigned(),
                Exponent = BigInteger.ValueOf(65537).ToByteArrayUnsigned()
            };

            //Set  to the public key values.

            //Import key parameters into RSA.
            rsa.ImportParameters(rsaKeyInfo);
            var gs   = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.Gs.ToByteArray();
            var sign = apResponseMessage.Challenge.LoginCryptoChallenge.DiffieHellman.GsSignature.ToByteArray();

            if (!rsa.VerifyData(gs,
                                sign,
                                HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1))
            {
                throw new AccessViolationException("Failed to verify APResponse");
            }

            // Solve challenge
            binaryData     = accumulator.ToArray();
            using var data = new MemoryStream();
            var mac = new HMACSHA1(sharedKey);
            mac.Initialize();
            for (var i = 1; i < 6; i++)
            {
                mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
                var temp = new[] { (byte)i };
                mac.TransformBlock(temp, 0, temp.Length, null, 0);
                mac.TransformFinalBlock(new byte[0], 0, 0);
                var final = mac.Hash;
                data.Write(final, 0, final.Length);
                mac = new HMACSHA1(sharedKey);
            }

            var dataArray = data.ToArray();
            mac = new HMACSHA1(Arrays.CopyOfRange(dataArray, 0, 0x14));
            mac.TransformBlock(binaryData, 0, binaryData.Length, null, 0);
            mac.TransformFinalBlock(new byte[0], 0, 0);
            var challenge = mac.Hash;
            var clientResponsePlaintext = new ClientResponsePlaintext
            {
                LoginCryptoResponse = new LoginCryptoResponseUnion
                {
                    DiffieHellman = new LoginCryptoDiffieHellmanResponse
                    {
                        Hmac = ByteString.CopyFrom(challenge)
                    }
                },
                PowResponse    = new PoWResponseUnion(),
                CryptoResponse = new CryptoResponseUnion()
            };
            var clientResponsePlaintextBytes = clientResponsePlaintext.ToByteArray();
            len = 4 + clientResponsePlaintextBytes.Length;
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            a.WriteByte(0x00);
            var bytesb = BitConverter.GetBytes(len);
            a.WriteByte(bytesb[0]);
            a.Write(clientResponsePlaintextBytes, 0, clientResponsePlaintextBytes.Length);
            a.Flush();
            try
            {
                var scrap = new byte[4];
                conn.Result.NetworkStream.ReadTimeout = 300;
                var read = conn.Result.NetworkStream.Read(scrap, 0, scrap.Length);
                if (read == scrap.Length)
                {
                    length = (scrap[0] << 24) | (scrap[1] << 16) | (scrap[2] << 8) | (scrap[3] & 0xFF);
                    var payload = new byte[length - 4];
                    conn.Result.NetworkStream.ReadComplete(payload, 0, payload.Length);
                    var failed = APResponseMessage.Parser.ParseFrom(payload)?.LoginFailed;
                    throw new SpotifyAuthenticatedException(failed);
                }
                else if (read > 0)
                {
                    throw new Exception("Read unknown data!");
                }
            }
            catch (Exception x)
            {
                // ignored
            }
            finally
            {
                conn.Result.NetworkStream.ReadTimeout = Timeout.Infinite;
            }

            using (authLock.Lock())
            {
                sendCipher = new Shannon();
                sendCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x14, 0x34));

                recvCipher = new Shannon();
                recvCipher.key(Arrays.CopyOfRange(data.ToArray(), 0x34, 0x54));
                authLockEventWaitHandle.Set();
            }

            #endregion APResponse

            Debug.WriteLine("Connected successfully");
        }
예제 #14
0
        public void addElement(String s)
        {
            //word=binascii.a2b_qp(qgram) # convert to binary

            String mykey = "zuxujesw";

            byte[] keyBytes = Encoding.UTF8.GetBytes(mykey);
            String hex1     = "";
            String hex2     = "";

            try {
                HMACSHA1 mac = new HMACSHA1(keyBytes);
                mac.Initialize();
                byte[] inputBytes = new byte[s.Length];
                for (var i = 0; i < s.Length; i++)
                {
                    inputBytes.SetValue(Convert.ToByte(s[i]), i);//Encoding.UTF8.GetBytes(s);
                }
                byte[] digest = mac.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
                hex1 = BitConverter.ToString(digest).Replace("-", string.Empty);
            } catch (Exception ex) {
                Console.Error.WriteLine("HMACSHA1: Hash error: " + ex.Message);
            }
            try {
                HMACMD5 mac = new HMACMD5(keyBytes);
                mac.Initialize();
                byte[] inputBytes = Encoding.UTF8.GetBytes(s);
                byte[] digest     = mac.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
                hex2 = BitConverter.ToString(digest).Replace("-", string.Empty);
            } catch (Exception ex) {
                Console.Error.WriteLine("HMACMD5: Hash error: " + ex.Message);
            }
            // convert hash key to integer
            BigInteger h1 = BigInteger.Parse(hex1, NumberStyles.AllowHexSpecifier);
            BigInteger h2 = BigInteger.Parse(hex2, NumberStyles.AllowHexSpecifier);

            for (int i = 0; i < k; i++)
            {
                BigInteger bigi = new BigInteger(i);
                //BigInteger res = h2.multiply(bigi).add(h1).mod(new BigInteger(this.bitSetSize + ""));
                BigInteger res      = (h2 * bigi + h1) % new BigInteger(this.bitSetSize);
                int        position = (int)res;
                if (!bitset.get(position))
                {
                    bitsSet++;
                }
                if (bitset.get(position))
                {
                    if (cols[position] == 0)
                    {
                        cols[position] = 1;
                    }
                    else
                    {
                        cols[position] = cols[position] + 1;
                    }
                }
                bitset.set(position);
            }
            numberOfAddedElements++;
        }