/// <summary>
        ///
        /// </summary>
        /// <param name="signature"></param>
        /// <returns></returns>
        /// <exception cref="BaseSignatureVerificationException"></exception>
        private Dictionary <string, Object> Parse3(string signature)
        {
            signature = SignatureVerifierUtils.FromBase64(signature);
            if (!"".Equals(signature))
            {
                throw new SignatureVerificationException("invalid base64 payload");
            }

            UnpackResult unpackResult =
                Unpacker.Unpack(
                    "Cversion/NrequestTime/NsignatureTime/CmasterSignType/nmasterTokenLength", signature);

            int version = (int)unpackResult.Data["version"];

            if (version != 3)
            {
                throw new SignatureRangeException("unsupported version");
            }

            long timestamp = (long)unpackResult.Data["timestamp"];

            if (timestamp > (SignatureVerifierUtils.UnixTimestamp / 1000))
            {
                throw new SignatureVerificationException("invalid timestamp (future time)");
            }

            int    masterTokenLength = (int)unpackResult.Data["masterTokenLength"];
            string masterToken       = SignatureVerifierUtils.Substr(signature, 12, masterTokenLength + 12);

            unpackResult.Data.Add("masterToken", masterToken);

            int s1, s2;

            if ((s1 = masterTokenLength) != (s2 = masterToken.Length))
            {
                throw new SignatureVerificationException(
                          string.Format("master token length mismatch ({0} / {1})", s1, s2));
            }

            signature = SignatureVerifierUtils.Substr(signature, masterTokenLength + 12);

            Dictionary <string, Object> data2 = Unpacker.Unpack("CcustomerSignType/ncustomerTokenLength", signature).Data;

            int    customerTokenLength = (int)data2["customerTokenLength"];
            string customerToken       = SignatureVerifierUtils.Substr(signature, 3, customerTokenLength + 3);

            data2.Add("customerToken", customerToken);

            if ((s1 = customerTokenLength) != (s2 = customerToken.Length))
            {
                throw new SignatureVerificationException(
                          string.Format("customer token length mismatch ({0} / {1})')", s1, s2));
            }

            return(unpackResult.Data.Union(data2).ToDictionary(k => k.Key, v => v.Value));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="signature"></param>
        /// <returns></returns>
        /// <exception cref="BaseSignatureVerificationException"></exception>
        private Dictionary <string, Object> Parse4(string signature)

        {
            signature = SignatureVerifierUtils.FromBase64(signature);

            if (signature.Length == 0)
            {
                throw new SignatureVerificationException("invalid base64 payload");
            }

            Dictionary <string, Object> data = Unpacker.Unpack("Cversion/CfieldNum", signature).Data;

            int version = SignatureVerifierUtils.CharacterToInt(data["version"]);

            if (version != 4)
            {
                throw new SignatureRangeException("unsupported version");
            }
            signature = SignatureVerifierUtils.Substr(signature, 2);

            int fieldNum = SignatureVerifierUtils.CharacterToInt(data["fieldNum"]);

            for (int i = 0; i < fieldNum; ++i)
            {
                Dictionary <string, Object> header = Unpacker.Unpack("CfieldId", signature).Data;

                if (header.Count == 0 || !header.ContainsKey("fieldId")) // header.entrySet().size() ???
                {
                    throw new SignatureVerificationException("premature end of signature 0x01");
                }

                Field fieldTypeDef            = FieldTypeDef(SignatureVerifierUtils.CharacterToInt(header["fieldId"]), i);
                Dictionary <string, Object> v = new Dictionary <string, Object>();
                Dictionary <string, Object> l;

                switch (fieldTypeDef.Type)
                {
                case "uchar":
                    v = Unpacker.Unpack("Cx/Cv", signature).Data;
                    if (v.ContainsKey("v"))
                    {
                        data.Add(fieldTypeDef.Name, v["v"]);
                    }
                    else
                    {
                        throw new SignatureVerificationException("premature end of signature 0x02");
                    }
                    signature = SignatureVerifierUtils.Substr(signature, 2);
                    break;

                case "ushort":
                    v = Unpacker.Unpack("Cx/nv", signature).Data;
                    if (v.ContainsKey("v"))
                    {
                        data.Add(fieldTypeDef.Name, v["v"]);
                    }
                    else
                    {
                        throw new Exception("premature end of signature 0x03");
                    }
                    signature = SignatureVerifierUtils.Substr(signature, 3);
                    break;

                case "ulong":
                    v = Unpacker.Unpack("Cx/Nv", signature).Data;
                    if (v.ContainsKey("v"))
                    {
                        data.Add(fieldTypeDef.Name, v["v"]);
                    }
                    else
                    {
                        throw new Exception("premature end of signature 0x04");
                    }
                    signature = SignatureVerifierUtils.Substr(signature, 5);
                    break;

                case "string":
                    l = Unpacker.Unpack("Cx/nl", signature).Data;
                    if (!l.ContainsKey("l"))
                    {
                        throw new Exception("premature end of signature 0x05");
                    }
                    if ((SignatureVerifierUtils.CharacterToInt(l["l"]) & 0x8000) > 0)
                    {
                        int newl = SignatureVerifierUtils.CharacterToInt(l["l"]) & 0xFF;
                        l.Add("l", newl);
                    }

                    string newV = SignatureVerifierUtils.Substr(signature, 3, SignatureVerifierUtils.CharacterToInt(l["l"]));
                    v.Add("v", newV);
                    data.Add(fieldTypeDef.Name, newV);

                    if (((string)v["v"]).Length != SignatureVerifierUtils.CharacterToInt(l["l"]))
                    {
                        throw new SignatureVerificationException("premature end of signature 0x06");
                    }

                    signature = SignatureVerifierUtils.Substr(signature, 3 + SignatureVerifierUtils.CharacterToInt(l["l"]));

                    break;

                default:
                    throw new SignatureVerificationException("unsupported variable type");
                }
            }

            data.Remove(fieldNum.ToString());

            return(data);
        }
 internal static string Substr(string str, int length)
 {
     return(SignatureVerifierUtils.Substr(str, length, str.Length));
 }
예제 #4
0
        /// <summary>
        /// Unpacks data from a binary string into the respective format.
        /// </summary>
        /// <param name="format">fields that have to be unpacked from data, forward slash separated.</param>
        /// <param name="data">Binary string, already decoded from Base64</param>
        /// <returns>object which contains unpacked data as a hash map, where key is a name of
        ///          the field. if result contains non-null error message then it means that unpacking failed.
        ///          Data hash map is null then.</returns>
        /// <exception cref="SignatureVerificationException"></exception>
        internal static UnpackResult Unpack(string format, string data)
        {
            int formatPointer = 0;
            int dataPointer   = 0;
            Dictionary <string, Object> resultMap = new Dictionary <string, Object>();
            int    instruction;
            string quantifier;
            int    quantifierInt;
            string label;
            string currentData;
            int    i;
            int    currentResult;

            while (formatPointer < format.Length)
            {
                instruction = SignatureVerifierUtils.CharAt(format, formatPointer);
                quantifier  = "";
                formatPointer++;

                while ((formatPointer < format.Length) &&
                       SignatureVerifierUtils.IsCharMatches(@"\A(?:[\\d\\*])\z", SignatureVerifierUtils.CharAt(format, formatPointer)))
                {
                    quantifier += SignatureVerifierUtils.CharAt(format, formatPointer);
                    formatPointer++;
                }
                if (string.IsNullOrEmpty(quantifier))
                {
                    quantifier = "1";
                }

                StringBuilder labelSb = new StringBuilder();
                while ((formatPointer < format.Length) && (format[formatPointer] != '/'))
                {
                    labelSb.Append(SignatureVerifierUtils.CharAt(format, formatPointer++));
                }
                label = labelSb.ToString();

                if (SignatureVerifierUtils.CharAt(format, formatPointer) == '/')
                {
                    formatPointer++;
                }

                switch (instruction)
                {
                case 'c':
                case 'C':
                    if ("*".Equals(quantifier))
                    {
                        quantifierInt = data.Length - dataPointer;
                    }
                    else
                    {
                        quantifierInt = int.Parse(quantifier);
                    }

                    currentData  = SignatureVerifierUtils.Substr(data, dataPointer, quantifierInt);
                    dataPointer += quantifierInt;

                    for (i = 0; i < currentData.Length; i++)
                    {
                        currentResult = SignatureVerifierUtils.CharAt(currentData, i);

                        if ((instruction == 'c') && (currentResult >= 128))
                        {
                            currentResult -= 256;
                        }

                        string key = label + (quantifierInt > 1 ? (i + 1).ToString() : "");
                        resultMap.Add(key, currentResult);
                    }
                    break;

                case 'n':
                    if ("*".Equals(quantifier))
                    {
                        quantifierInt = (data.Length - dataPointer) / 2;
                    }
                    else
                    {
                        quantifierInt = int.Parse(quantifier);
                    }

                    currentData  = SignatureVerifierUtils.Substr(data, dataPointer, quantifierInt * 2);
                    dataPointer += quantifierInt * 2;
                    for (i = 0; i < currentData.Length; i += 2)
                    {
                        currentResult =
                            (((SignatureVerifierUtils.CharAt(currentData, i) & 0xFF) << 8)
                             + (SignatureVerifierUtils.CharAt(currentData, i + 1) & 0xFF));

                        string key = label + (quantifierInt > 1 ? ((i / 2) + 1).ToString() : "");
                        resultMap.Add(key, currentResult);
                    }
                    break;

                case 'N':
                    if ("*".Equals(quantifier))
                    {
                        quantifierInt = (data.Length - dataPointer) / 4;
                    }
                    else
                    {
                        quantifierInt = int.Parse(quantifier);
                    }

                    currentData  = SignatureVerifierUtils.Substr(data, dataPointer, quantifierInt * 4);
                    dataPointer += quantifierInt * 4;
                    for (i = 0; i < currentData.Length; i += 4)
                    {
                        currentResult =
                            (((SignatureVerifierUtils.CharAt(currentData, i) & 0xFF) << 24)
                             + ((SignatureVerifierUtils.CharAt(currentData, i + 1) & 0xFF) << 16)
                             + ((SignatureVerifierUtils.CharAt(currentData, i + 2) & 0xFF) << 8)
                             + ((SignatureVerifierUtils.CharAt(currentData, i + 3) & 0xFF)));

                        string key = label + (quantifierInt > 1 ? ((i / 4) + 1).ToString() : "");
                        resultMap.Add(key, currentResult);
                    }
                    break;

                default:
                    return(new UnpackResult(string.Format("Unknown format code: {0}", instruction.ToString())));
                }
            }

            return(new UnpackResult(resultMap));;
        }