Пример #1
0
        private static string DecryptPassword(string encryptedPassword)
        {
            SymmetricAlgorithm alg = CreateCipher(Constants.SECRET_PREVIEW_HMAC_KEY);
            var TR = alg.CBCDecrypt(encryptedPassword.Base64Decode()).FromUTF8Bytes();

            return(TR);
        }
Пример #2
0
        /// <summary>
        /// Parses a string containing a token and returns the token it contains,
        /// if that token is valid.
        /// </summary>
        /// <param name="key">The shared secret key with which the token was originally signed.</param>
        /// <param name="token">The original token string representation.</param>
        public static SecurityToken FromString(string key, string token)
        {
            // Decode the incoming string and do a basic sanity check.
            byte[] RawData = token.Base64WebSafeDecode();
            if (RawData.Length < (HMAC_SIZE + 1))
            {
                throw new SecurityTokenInvalidException("String is too small to be a valid " + typeof(SecurityToken).Name);
            }

            // Recompute the HMAC using the provided key (as the key is a secret and
            // cannot be encoded into the token itself), and make sure it matches.  If
            // not, then the token is corrupt and cannot be trusted.
            byte[] RawHMAC = RawData.Skip(RawData.Length - HMAC_SIZE).ToArray();
            RawData = RawData.Take(RawData.Length - HMAC_SIZE).ToArray();
            if (RawData.GetHMACSHA1Bytes(key).Base64Encode() != RawHMAC.Base64Encode())
            {
                throw new SecurityTokenInvalidException("HMAC validation failed.");
            }

            // Extract the flags from the payload.
            SecurityTokenFlags Flags = (SecurityTokenFlags)RawData.First();

            RawData = RawData.Skip(1).ToArray();

            // If data was encrypted, decrypt it.
            SymmetricAlgorithm Alg = CreateCipher(key);

            if ((Flags & SecurityTokenFlags.EncryptedCTS) != 0)
            {
                RawData = Alg.CTSDecrypt(Alg.CTSDecrypt(RawData).Reverse().ToArray());
            }
            else if ((Flags & SecurityTokenFlags.EncryptedCBC) != 0)
            {
                RawData = Alg.CBCDecrypt(Alg.CTSDecrypt(RawData).Reverse().ToArray());
            }

            // If the data was originally deflated, decompress it.
            if ((Flags & SecurityTokenFlags.Deflated) != 0)
            {
                RawData = RawData.DeflateDecompress().ToArray();
            }

            // If the data contains an expiration date, then decode the expiration date
            // and make sure the token has not expired.
            DateTime Exp = DateTime.MaxValue;

            if ((Flags & SecurityTokenFlags.ExpireDate) != 0)
            {
                Exp = Epoch.AddSeconds(BitConverter.ToUInt32(RawData.Skip(RawData.Length - sizeof(UInt32)).EndianFlip().ToArray(), 0));
                if (Exp < DateTime.UtcNow)
                {
                    throw new SecurityTokenExpiredException("Token has expired.");
                }
                RawData = RawData.Take(RawData.Length - sizeof(UInt32)).ToArray();
            }

            // The remaining data is the key/value pair data, packed as an even number of
            // strings, each prefixed with a big-endian uint16 length specifier, followed
            // by that many bytes of UTF-8-encoded string data.  After unpacking strings,
            // rebuild the original dictionary.
            Queue <string> Values = new Queue <string>();

            while (RawData.Length > 0)
            {
                ushort StrLen = BitConverter.ToUInt16(RawData.Take(2).EndianFlip().ToArray(), 0);
                Values.Enqueue(Encoding.UTF8.GetString(RawData.Skip(2).Take(StrLen).ToArray()));
                RawData = RawData.Skip(StrLen + 2).ToArray();
            }
            Dictionary <string, string> NewData = new Dictionary <string, string>();

            while (Values.Count > 0)
            {
                NewData[Values.Dequeue()] = Values.Dequeue();
            }

            // Return a security token containing the original expiration, key, and
            // payload data.  Note that if any of the checks above fails (payload validation,
            // matching key, expiration) then an exception will be thrown instead of
            // returning any token.
            return(new SecurityToken
            {
                Expires = Exp,
                Key = key,
                Data = NewData
            });
        }