Beispiel #1
0
 private byte GetByte()
 {
     if (index >= chunk.Length)
     {
         hmac.Initialize();
         aValue = hmac.ComputeHash(aValue);
         aValue.CopyTo((Array)buffer, 0);
         seed.CopyTo((Array)buffer, aValue.Length);
         hmac.Initialize();
         chunk = hmac.ComputeHash(buffer);
         index = 0;
     }
     ++position;
     return(chunk[index++]);
 }
Beispiel #2
0
 private void ComputeHmac(byte[] input, byte[] output)
 {
     _hmacAlgorithm.Initialize();
     _hmacAlgorithm.TransformBlock(input, 0, input.Length, input, 0);
     _hmacAlgorithm.TransformFinalBlock(Array.Empty <byte>(), 0, 0);
     Array.Copy(_hmacAlgorithm.Hash !, output, output.Length);
 }
 void ComputeHmac(byte[] input, byte[] output)
 {
     _hmacAlgorithm.Initialize();
     _hmacAlgorithm.TransformBlock(input, 0, input.Length, input, 0);
     _hmacAlgorithm.TransformFinalBlock(new byte[0], 0, 0);
     Array.Copy(_hmacAlgorithm.Hash, output, output.Length);
 }
Beispiel #4
0
        private static byte[] GenerateMAC(CipherSuite cipherSuite, Record record, UInt64 seqNum, KeyedHashAlgorithm hasher)
        {
            BulkCipherAlgorithmType cipherType = cipherSuite.BulkCipherAlgorithm.Type;

            if (cipherType == BulkCipherAlgorithmType.Stream || cipherType == BulkCipherAlgorithmType.Block)
            {
                byte[] additional = GetAdditionalBytes(seqNum, (byte)record.Type, record.Version, record.Fragment.Length);

                byte[] data = new byte[additional.Length + record.Fragment.Length];
                Buffer.BlockCopy(additional, 0, data, 0, additional.Length);
                Buffer.BlockCopy(record.Fragment, 0, data, additional.Length, record.Fragment.Length);
                Log.Trace("MAC data bytes: " + BitConverter.ToString(data));

                // Calculate the MAC of the packet
                hasher.Initialize();
                var MAC = hasher.ComputeHash(data);

                /* Add MAC to the end of the fragment */
                byte[] fragment = new byte[record.Fragment.Length + MAC.Length];
                Buffer.BlockCopy(record.Fragment, 0, fragment, 0, record.Fragment.Length);
                Buffer.BlockCopy(MAC, 0, fragment, record.Fragment.Length, MAC.Length);
                record.Fragment = fragment;

                return(MAC);
            }

            return(new byte[0]);
        }
 byte GetByte()
 {
     if (index >= chunk.Length)
     {
         // Calculate A(i) = HMAC_SHA1(secret, A(i-1)).
         hmac.Initialize();
         this.aValue = hmac.ComputeHash(this.aValue);
         // Calculate P_SHA1(secret, seed)[j] = HMAC_SHA1(secret, A(j+1) || seed).
         this.aValue.CopyTo(buffer, 0);
         this.seed.CopyTo(buffer, this.aValue.Length);
         hmac.Initialize();
         this.chunk = hmac.ComputeHash(buffer);
         index      = 0;
     }
     position++;
     return(chunk[index++]);
 }
 private byte GetByte()
 {
     if (_index >= _chunk.Length)
     {
         // Calculate A(i) = HMAC_SHA1(secret, A(i-1)).
         _hmac.Initialize();
         _aValue = _hmac.ComputeHash(_aValue);
         // Calculate P_SHA1(secret, seed)[j] = HMAC_SHA1(secret, A(j+1) || seed).
         _aValue.CopyTo(_buffer, 0);
         _seed.CopyTo(_buffer, _aValue.Length);
         _hmac.Initialize();
         _chunk = _hmac.ComputeHash(_buffer);
         _index = 0;
     }
     _position++;
     return(_chunk[_index++]);
 }
Beispiel #7
0
        /// <summary>
        /// Initializes the asymmetric key.
        /// </summary>
        protected void InitializeHashKey()
        {
            if (!IsHashKeyInitialized)
            {
                if (KeyStorage.KeyLocationExists(KeyLocation))
                {
                    DecryptHashKey(
                        KeyStorage.GetKey(KeyLocation));
                }
                else
                {
                    KeyStorage.PutKey(EncryptHashKey(), KeyLocation);
                }

                IsHashKeyInitialized = true;
            }

            _hashAlgorithm.Initialize();
        }
        public override byte[] GetBytes(int count)
        {
            byte[] ret = new byte[count];

            int filled = 0;

            while (filled < count)
            {
                if (filled + _Hash.Length < count)
                {
                    /* Copy current hash into results */
                    Array.Copy(_Hash, 0, ret, filled, _Hash.Length);
                    filled += _Hash.Length;

                    _hmac.Initialize();
                    _Ai = _hmac.ComputeHash(_Ai);

                    /* Calculate the next hash */
                    _hmac.Initialize();
                    _hmac.TransformBlock(_Ai, 0, _Ai.Length, _Ai, 0);
                    _hmac.TransformFinalBlock(_seed, 0, _seed.Length);
                    _Hash = _hmac.Hash;
                }
                else
                {
                    /* Count how many bytes to consume */
                    int consumed = count - filled;

                    /* Make a partial copy of the current hash */
                    Array.Copy(_Hash, 0, ret, filled, consumed);
                    filled += consumed;

                    /* Remove read bytes from the current hash */
                    byte[] tmp = new byte[_Hash.Length - consumed];
                    Array.Copy(_Hash, consumed, tmp, 0, tmp.Length);
                    _Hash = tmp;
                }
            }

            return(ret);
        }
Beispiel #9
0
        /// <summary>
        /// Creates a SSLv3 message authentification code for the passed buffer.
        /// </summary>
        private static byte[] CreateMAC(EProtocol protocol, KeyedHashAlgorithm hasher, ulong seqNum, ERecordType recordType, byte[] buffer, int offset)
        {
            int bufferLengthTransformed = buffer.Length - offset;

            // hash seq_num, fragment type, fragment length
            byte[] infoPad = CreateMACInfoPad(seqNum, (byte)recordType, protocol, bufferLengthTransformed);
            // hash(MAC_write_secret + pad_2 + hash(MAC_write_secret + pad_1 + seq_num + record_type + length + content));
            hasher.Initialize();
            hasher.TransformBlock(infoPad, 0, infoPad.Length, infoPad, 0);
            hasher.TransformFinalBlock(buffer, offset, bufferLengthTransformed);
            return(hasher.Hash);
        }
Beispiel #10
0
            public byte[] GetDerivedKey(int derivedKeySize)
            {
                int offset   = 0;
                int required = derivedKeySize / 8;

                byte[] a      = nonce;
                byte[] buffer = new byte[required];

                while (required > 0)
                {
                    hmac.Initialize();
                    hmac.TransformFinalBlock(a, 0, a.Length);
                    a = hmac.Hash;
                    hmac.Initialize();
                    hmac.TransformBlock(a, 0, a.Length, a, 0);
                    hmac.TransformFinalBlock(nonce, 0, nonce.Length);
                    int tocpy = required < hmac.Hash.Length ? required : hmac.Hash.Length;
                    Array.Copy(hmac.Hash, 0, buffer, offset, tocpy);
                    offset   += tocpy;
                    required -= tocpy;
                }

                return(buffer);
            }
Beispiel #11
0
        private void SendServerFinished(INetState ns, byte[] allHandshakes)
        {
            KeyedHashAlgorithm verify = CipherSuite.GetHMAC(_MasterSecret);

            verify.Initialize();
            verify.TransformBlock(allHandshakes, 0, allHandshakes.Length, allHandshakes, 0);
            if (ns.Https.Protocol == EProtocol.SSLv30)
            {
                verify.TransformFinalBlock(SslBlocks.SenderServer, 0, SslBlocks.SenderServer.Length);
                Send(ns, new HttpSmsgFinished(ns.Https, verify.Hash));
            }
            else
            {
                throw new HttpsException($"Unknown protocol {ns.Https.Protocol}");
            }
        }
Beispiel #12
0
            public Transform(BlockCipherCTRHMAC <TCiper, THMAC> owner, byte[] key, byte[] iv, byte[] aad, byte[] tag, bool isEncrypt)
            {
                byte[] cipherKey = new byte[owner.SymmetricAlgorithmInstance.KeySize / 8];
                byte[] hmacKey   = new byte[key.Length - cipherKey.Length];
                Buffer.BlockCopy(key, 0, cipherKey, 0, cipherKey.Length);
                Buffer.BlockCopy(key, cipherKey.Length, hmacKey, 0, hmacKey.Length);
                _tag         = tag;
                _encryptMode = isEncrypt;

                _ct      = owner.SymmetricAlgorithmInstance.CreateEncryptor(cipherKey, null);
                _cipher  = new byte[iv.Length];
                _pos     = 0;
                _mac     = new THMAC();
                _mac.Key = hmacKey;
                _mac.Initialize();
                _counter = (byte[])iv.Clone();
            }
Beispiel #13
0
        private static void GenerateMAC(CipherSuite cipherSuite, Record record, UInt64 seqNum, KeyedHashAlgorithm hasher)
        {
            BulkCipherAlgorithmType cipherType = cipherSuite.BulkCipherAlgorithm.Type;

            if (cipherType == BulkCipherAlgorithmType.Stream || cipherType == BulkCipherAlgorithmType.Block)
            {
                byte[] additional = GetAdditionalBytes(seqNum, record.Type, record.Version, record.Fragment.Length);

                // Calculate the MAC of the packet
                hasher.Initialize();
                hasher.TransformBlock(additional, 0, additional.Length, additional, 0);
                hasher.TransformFinalBlock(record.Fragment, 0, record.Fragment.Length);
                byte[] MAC = hasher.Hash;

                /* Add MAC to the end of the fragment */
                byte[] fragment = new byte[record.Fragment.Length + MAC.Length];
                Buffer.BlockCopy(record.Fragment, 0, fragment, 0, record.Fragment.Length);
                Buffer.BlockCopy(MAC, 0, fragment, record.Fragment.Length, MAC.Length);
                record.Fragment = fragment;
            }
        }
Beispiel #14
0
        private void ReceiveClientFinished(INetState ns, HttpsReader reader)
        {
            HttpsCmsgFinished packet = new HttpsCmsgFinished(reader);

            byte[]             allHandshakes = _AllHandshakes.ToArray();
            KeyedHashAlgorithm verify        = CipherSuite.GetHMAC(_MasterSecret);

            verify.Initialize();
            verify.TransformBlock(allHandshakes, 0, allHandshakes.Length - reader.Length, allHandshakes, 0);
            if (ns.Https.Protocol == EProtocol.SSLv30)
            {
                verify.TransformFinalBlock(SslBlocks.SenderClient, 0, SslBlocks.SenderClient.Length);
                if (!ByteArrayEquality(packet.Verification, 0, verify.Hash, 0, packet.Verification.Length))
                {
                    throw new HttpsException("ClientFinished hash did not match computed hash.", reader);
                }
            }
            else
            {
                throw new HttpsException($"Unknown protocol {ns.Https.Protocol}", reader);
            }
            ns.Https.SendChangeCipherSpec(ns, 0x01);
            SendServerFinished(ns, allHandshakes);
        }
Beispiel #15
0
        public byte[] Encrypt(byte[] value, byte[] randomK)
#endif
        {
            int domainLen     = (int)((_domain.Bits >> 3) + ((_domain.Bits & 7) == 0 ? 0 : 1));
            int encBlockBytes = (_symmetricAlgo == null ? 0 : _symmetricAlgo.BlockSize >> 3);
            int encKeyLen     = (_symmetricAlgo == null ? value.Length : _symmetricAlgo.KeySize >> 3);
            int encPaddingLen = 0;
            int encTotalBytes = value.Length;
            int macKeyLen     = _mac.HashSize >> 3;

            byte[] result;
            int    ridx = 0;

            if (_params.D == null)
            {
                _params.CreateNewPrivateKey();
            }
            if (_params.Q == null)
            {
                _params.CreatePublicKeyFromPrivateKey();
            }
            if (_symmetricAlgo != null)
            {
                int mod  = value.Length % encBlockBytes;
                int rmod = encBlockBytes - mod;
                if (mod == 0)
                {
                    if (!(_symmetricAlgo.Padding == PaddingMode.None || _symmetricAlgo.Padding == PaddingMode.Zeros))
                    {
                        encPaddingLen = _symmetricAlgo.BlockSize >> 3;
                    }
                }
                else
                {
                    encPaddingLen = rmod;
                }
                encTotalBytes += encPaddingLen;
            }

            // Step.1
#if !TEST
            ECKeyPair pair = new ECKeyPair(null, null, _domain);
#else
            ECKeyPair pair = new ECKeyPair(new Number(randomK, false), null, _domain);
#endif

            // Step.2
            // TODO: 点圧縮を利用しないオプションを追加する
            byte[] R = pair.ExportPublicKey(true);
            result = new byte[R.Length + encTotalBytes + macKeyLen];
            for (int i = 0; i < R.Length; i++)
            {
                result[ridx++] = R[i];
            }

            // Step.3 & 4
            // TODO: Cofactor Diffie-Hellmanプリミティブを利用するオプションを追加する
            byte[] z = _params.Q.Multiply(pair.D).Export().X.ToByteArray(domainLen, false);

            // Step.5
            byte[] K = _kdf.Calculate(z, encKeyLen + macKeyLen);

            // Step.6
            byte[] MK = new byte[macKeyLen];
            for (int i = 0; i < MK.Length; i++)
            {
                MK[i] = K[K.Length - MK.Length + i];
            }

            // Step.7
            if (_symmetricAlgo == null)
            {
                for (int i = 0; i < value.Length; i++)
                {
                    result[ridx++] = (byte)(value[i] ^ K[i]);
                }
            }
            else
            {
                byte[] EK = new byte[encKeyLen];
                for (int i = 0; i < EK.Length; i++)
                {
                    EK[i] = K[i];
                }
                using (ICryptoTransform transform = _symmetricAlgo.CreateEncryptor(EK, new byte[encBlockBytes])) {
                    int i = 0;
                    for (; i < value.Length - encBlockBytes; i += encBlockBytes)
                    {
                        transform.TransformBlock(value, i, encBlockBytes, result, ridx + i);
                    }
                    byte[] padding = transform.TransformFinalBlock(value, i, value.Length - i);
                    Buffer.BlockCopy(padding, 0, result, ridx + i, padding.Length);
                    ridx += i + padding.Length;
                }
            }

            // Step.8
            // TODO: HMAC-SHA1-80への対応
            _mac.Key = MK;
            _mac.Initialize();
            _mac.TransformBlock(result, R.Length, encTotalBytes, null, 0);
            if (_sharedInfo == null)
            {
                _mac.TransformFinalBlock(result, 0, 0);
            }
            else
            {
                _mac.TransformFinalBlock(_sharedInfo, 0, _sharedInfo.Length);
            }
            _mac.Hash.CopyTo(result, ridx);

            return(result);
        }
Beispiel #16
0
            public static byte[] ComputeCombinedKey(
                byte[] requestorEntropy,
                byte[] issuerEntropy,
                int keySizeInBits)
            {
                if (requestorEntropy == null)
                {
                    throw new ArgumentNullException(nameof(requestorEntropy));
                }
                if (issuerEntropy == null)
                {
                    throw new ArgumentNullException(nameof(issuerEntropy));
                }
                int length = ValidateKeySizeInBytes(keySizeInBits);

                byte[] numArray1 = new byte[length];
                using (KeyedHashAlgorithm keyedHashAlgorithm = NewHmacSha1KeyedHashAlgorithm())
                {
                    keyedHashAlgorithm.Key = requestorEntropy;
                    byte[] buffer1   = issuerEntropy;
                    byte[] buffer2   = new byte[keyedHashAlgorithm.HashSize / 8 + buffer1.Length];
                    byte[] numArray2 = (byte[])null;
                    try
                    {
                        int num = 0;
label_10:
                        while (num < length)
                        {
                            keyedHashAlgorithm.Initialize();
                            buffer1 = keyedHashAlgorithm.ComputeHash(buffer1);
                            buffer1.CopyTo((Array)buffer2, 0);
                            issuerEntropy.CopyTo((Array)buffer2, buffer1.Length);
                            keyedHashAlgorithm.Initialize();
                            numArray2 = keyedHashAlgorithm.ComputeHash(buffer2);
                            int index = 0;
                            while (true)
                            {
                                if (index < numArray2.Length && num < length)
                                {
                                    numArray1[num++] = numArray2[index];
                                    ++index;
                                }
                                else
                                {
                                    goto label_10;
                                }
                            }
                        }
                    }
                    catch
                    {
                        Array.Clear((Array)numArray1, 0, numArray1.Length);
                        throw;
                    }
                    finally
                    {
                        if (numArray2 != null)
                        {
                            Array.Clear((Array)numArray2, 0, numArray2.Length);
                        }
                        Array.Clear((Array)buffer2, 0, buffer2.Length);
                        keyedHashAlgorithm.Clear();
                    }
                }
                return(numArray1);
            }
Beispiel #17
0
 public override void Initialize()
 {
     _base.Initialize();
 }
Beispiel #18
0
 /// <summary>
 /// Resets the internal state.
 /// </summary>
 public override void Reset() => m_keyedHashAlgorithm.Initialize();
Beispiel #19
0
        ///////////////////////////////////////////////////////////////////////

        #region IExecute Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return(ReturnCode.Error);
            }

            if (arguments == null)
            {
                result = "invalid argument list";
                return(ReturnCode.Error);
            }

            if (arguments.Count < 2)
            {
                result = "wrong # args: should be \"hash option ?arg ...?\"";
                return(ReturnCode.Error);
            }

            ReturnCode code;
            string     subCommand = arguments[1];
            bool       tried      = false;

            code = ScriptOps.TryExecuteSubCommandFromEnsemble(
                interpreter, this, clientData, arguments, true,
                false, ref subCommand, ref tried, ref result);

            if ((code != ReturnCode.Ok) || tried)
            {
                return(code);
            }

            //
            // NOTE: These algorithms are known to be supported by the
            //       framework.
            //
            //       Normal: MD5, RIPEMD160, SHA, SHA1, SHA256, SHA384, SHA512
            //
            //        Keyed: MACTripleDES
            //
            //         HMAC: HMACMD5, HMACRIPEMD160, HMACSHA1, HMACSHA256,
            //               HMACSHA384, HMACSHA512
            //
            switch (subCommand)
            {
            case "keyed":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) <= arguments.Count) &&
                            ((argumentIndex + 3) >= arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (KeyedHashAlgorithm algorithm =
                                               KeyedHashAlgorithm.Create(
                                                   arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if ((argumentIndex + 3) == arguments.Count)
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 2],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    algorithm.Key = bytes;
                                                }
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                if (isFileName)
                                                {
                                                    Stream stream = null;

                                                    try
                                                    {
                                                        code = RuntimeOps.NewStream(
                                                            interpreter,
                                                            arguments[argumentIndex + 1],
                                                            FileMode.Open, FileAccess.Read,
                                                            ref stream, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            if (raw)
                                                            {
                                                                result = new ByteList(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                            else
                                                            {
                                                                result = FormatOps.Hash(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        if (stream != null)
                                                        {
                                                            stream.Close();
                                                            stream = null;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    byte[] bytes = null;

                                                    code = StringOps.GetBytes(
                                                        encoding, arguments[argumentIndex + 1],
                                                        EncodingType.Binary, ref bytes, ref result);

                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported keyed hash algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "list":
            {
                if ((arguments.Count == 2) || (arguments.Count == 3))
                {
                    string type = null;

                    if (arguments.Count == 3)
                    {
                        type = arguments[2];
                    }

                    switch (type)
                    {
                    case null:
                    case "all":
                    {
                        StringList list = new StringList();

                        lock (syncRoot)
                        {
                            if (defaultAlgorithms != null)
                            {
                                list.AddRange(defaultAlgorithms);
                            }
                        }

                        if (keyedHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in keyedHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("keyed", hashAlgorithmName));
                            }
                        }

                        if (macHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in macHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("mac", hashAlgorithmName));
                            }
                        }

                        if (normalHashAlgorithmNames != null)
                        {
                            foreach (string hashAlgorithmName in normalHashAlgorithmNames)
                            {
                                list.Add(StringList.MakeList("normal", hashAlgorithmName));
                            }
                        }

                        result = list;
                        break;
                    }

                    case "default":
                    {
                        lock (syncRoot)
                        {
                            result = (defaultAlgorithms != null) ?
                                     new StringList(defaultAlgorithms) : null;
                        }
                        break;
                    }

                    case "keyed":
                    {
                        result = (keyedHashAlgorithmNames != null) ?
                                 new StringList(keyedHashAlgorithmNames) : null;

                        break;
                    }

                    case "mac":
                    {
                        result = (macHashAlgorithmNames != null) ?
                                 new StringList(macHashAlgorithmNames) : null;

                        break;
                    }

                    case "normal":
                    {
                        result = (normalHashAlgorithmNames != null) ?
                                 new StringList(normalHashAlgorithmNames) : null;

                        break;
                    }

                    default:
                    {
                        result = "unknown algorithm list, must be: all, default, keyed, mac, or normal";
                        code   = ReturnCode.Error;
                        break;
                    }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?type?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "mac":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) <= arguments.Count) &&
                            ((argumentIndex + 3) >= arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (HMAC algorithm = HMAC.Create(
                                               arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if ((argumentIndex + 3) == arguments.Count)
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 2],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    algorithm.Key = bytes;
                                                }
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                if (isFileName)
                                                {
                                                    Stream stream = null;

                                                    try
                                                    {
                                                        code = RuntimeOps.NewStream(
                                                            interpreter,
                                                            arguments[argumentIndex + 1],
                                                            FileMode.Open, FileAccess.Read,
                                                            ref stream, ref result);

                                                        if (code == ReturnCode.Ok)
                                                        {
                                                            if (raw)
                                                            {
                                                                result = new ByteList(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                            else
                                                            {
                                                                result = FormatOps.Hash(
                                                                    algorithm.ComputeHash(stream));
                                                            }
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        if (stream != null)
                                                        {
                                                            stream.Close();
                                                            stream = null;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    byte[] bytes = null;

                                                    code = StringOps.GetBytes(
                                                        encoding, arguments[argumentIndex + 1],
                                                        EncodingType.Binary, ref bytes, ref result);

                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported hmac algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string ?key?\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            case "normal":
            {
                if (arguments.Count >= 4)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-raw",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid, "-filename",
                                       null), /* COMPAT: Tcllib. */
                            new Option(null, OptionFlags.MustHaveEncodingValue,
                                       Index.Invalid, Index.Invalid, "-encoding",
                                       null),
                            new Option(null, OptionFlags.None,
                                       Index.Invalid, Index.Invalid,
                                       Option.EndOfOptions, null)
                        });

                    int argumentIndex = Index.Invalid;

                    code = interpreter.GetOptions(
                        options, arguments, 0, 2, Index.Invalid, false,
                        ref argumentIndex, ref result);

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) &&
                            ((argumentIndex + 2) == arguments.Count))
                        {
                            Variant value = null;
                            bool    raw   = false;

                            if (options.IsPresent("-raw"))
                            {
                                raw = true;
                            }

                            bool isFileName = false;

                            if (options.IsPresent("-filename", ref value))
                            {
                                isFileName = true;
                            }

                            Encoding encoding = null;

                            if (options.IsPresent("-encoding", ref value))
                            {
                                encoding = (Encoding)value.Value;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    using (HashAlgorithm algorithm =
                                               HashAlgorithm.Create(
                                                   arguments[argumentIndex]))
                                    {
                                        if (algorithm != null)
                                        {
                                            algorithm.Initialize();

                                            if (isFileName)
                                            {
                                                Stream stream = null;

                                                try
                                                {
                                                    code = RuntimeOps.NewStream(
                                                        interpreter,
                                                        arguments[argumentIndex + 1],
                                                        FileMode.Open, FileAccess.Read,
                                                        ref stream, ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        if (raw)
                                                        {
                                                            result = new ByteList(
                                                                algorithm.ComputeHash(stream));
                                                        }
                                                        else
                                                        {
                                                            result = FormatOps.Hash(
                                                                algorithm.ComputeHash(stream));
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (stream != null)
                                                    {
                                                        stream.Close();
                                                        stream = null;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                byte[] bytes = null;

                                                code = StringOps.GetBytes(
                                                    encoding, arguments[argumentIndex + 1],
                                                    EncodingType.Binary, ref bytes, ref result);

                                                if (code == ReturnCode.Ok)
                                                {
                                                    if (raw)
                                                    {
                                                        result = new ByteList(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                    else
                                                    {
                                                        result = FormatOps.Hash(
                                                            algorithm.ComputeHash(bytes));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "unsupported hash algorithm \"{0}\"",
                                                arguments[argumentIndex]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Engine.SetExceptionErrorCode(interpreter, e);

                                    result = e;
                                    code   = ReturnCode.Error;
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(
                                    options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = String.Format(
                                    "wrong # args: should be \"{0} {1} ?options? algorithm string\"",
                                    this.Name, subCommand);
                            }

                            code = ReturnCode.Error;
                        }
                    }
                }
                else
                {
                    result = String.Format(
                        "wrong # args: should be \"{0} {1} ?options? algorithm string\"",
                        this.Name, subCommand);

                    code = ReturnCode.Error;
                }
                break;
            }

            default:
            {
                result = ScriptOps.BadSubCommand(
                    interpreter, null, null, subCommand, this, null, null);

                code = ReturnCode.Error;
                break;
            }
            }

            return(code);
        }