2013년 9월 12일 목요일

LINE(라인) protocol analysis [3] : session key


* 2014.08.02 update *

If you need a python code right away, then please keep in touch with https://github.com/carpedm20/LINE



Finally, I want to talk about session key  and auth key.


5. Session key

At first, I tried to follow UpdateAuthToken() function because this function adds the "X-Line-Access" header to the HTTP protocol.

As I followed this function, I finally arrived to create() function which updates the old session key.

It wasn't hard to understand how this function updates authKey, but I couldn't figure out when LINE change an auth key.

It seems like LINE's session key is changed when a user change his/her mobile phone or re-install the application.

In other words, the session key won't be changed if you don't erase or change your mobile phone.

This can cause security problems if someone change the code of LINE application and distribute it to the internet...but I don't think it will happen :)

Bellow is the list of functions that I followed to find out how LINE update their authorization key.

  1. public void UpdateAuthToken(string authKey)
  2. {
  3.     if (authKey != null)
  4.     {
  5.         this._transport.AddRequestHeader("X-Line-Access", AccessTokenHelper.GetAccessToken(authKey)); // add "X-Line-Access" header to HTTP(s) protocol
  6.     }
  7. }
  8. public void UpdateAuthToken(string authKey)
  9. {
  10.     try
  11.     {
  12.         if (authKey != null)
  13.         {
  14.             this._transport.AddRequestHeader("X-Line-Access", AccessTokenHelper.GetAccessToken(authKey)); // add "X-Line-Access" header to HTTP(s) protocol
  15.         }
  16.     }
  17.     catch (Exception)
  18.     {
  19.     }
  20. }

  21. private void _addCustomHeader(HttpWebRequest httpWebRequest)
  22. {
  23.     Profile current = ProfileViewModel.GetInstance().Current;
  24.     httpWebRequest.get_Headers().set_Item("X-Line-Access", AccessTokenHelper.GetAccessToken(current.AuthKey)); // add "X-Line-Access" header to HTTP(s) protocol
  25.     httpWebRequest.get_Headers().set_Item("X-Line-Application", DeviceUtility.GetLineApplicationString());
  26.     httpWebRequest.get_Headers().set_Item("Cache-Control""no-cache");
  27.     httpWebRequest.get_Headers().set_Item("Pragma""no-cache");
  28. }
  29. public static string GetAccessToken(string authKey)
  30. {
  31.     long timestamp = (DateTime.get_UtcNow() - new DateTime(0x7b2, 110001)).get_TotalMilliseconds(); // use time stamp for making access token
  32.     return GetAccessToken(timestamp, authKey);
  33. }
  34. public static string GetAccessToken(long timestamp, string authKey)
  35. {
  36.     if (((_accessToken == "") || !_accessToken.Equals(_lastAuthToken)) || (timestamp > (_lastUpdated + 0x5265c00L)))
  37.     {
  38.         lock (_thisLock)
  39.         {
  40.             _accessToken = Generate(authKey, timestamp);
  41.             _lastUpdated = timestamp;
  42.             _lastAuthToken = authKey;
  43.         }
  44.     }
  45.     return _accessToken;
  46. }
  47. public static string Generate(string authToken, long timestamp)
  48. {
  49.     string[] strArray = authToken.Split(new char[] { ':' });
  50.     if (strArray.Length != 2)
  51.     {
  52.         throw new ArgumentException("authToken");
  53.     }
  54.     string issueTo = strArray[0]; // use previous authToken for the new authToken
  55.     string encodedSecretKey = strArray[1]// use previous authToken for the new authToken
  56.     string str3 = YamlWebToken.Create(issueTo, timestamp, encodedSecretKey);
  57.     return (issueTo + ":" + str3);
  58. }
  59. public class YamlWebToken
  60. {
  61.     // Fields
  62.     public static HmacAlgorithm DEFAULT_ALOGORITHM; // use Hmac algorith for generating token
  63.     // Methods
  64.     static YamlWebToken();
  65.     public YamlWebToken();
  66.     public static string Create(string issueTo, long timestamp, string encodedSecretKey);
  67.     public static string Create(string issuedTo, long timestamp, string encodedSecretKey, HmacAlgorithm algorithm);
  68.     // Nested Types
  69.     public class HmacAlgorithm
  70.     {
  71.         // Methods
  72.         public HmacAlgorithm(string name);
  73.         public static HMAC CreateInstance(string name, byte[] key);
  74.         // Properties
  75.         public string Name { get; set; }
  76.     }
  77. }
  78. public static string Create(string issueTo, long timestamp, string encodedSecretKey)
  79. {
  80.     return Create(issueTo, timestamp, encodedSecretKey, DEFAULT_ALOGORITHM);
  81. }
  82. public static string Create(string issuedTo, long timestamp, string encodedSecretKey, HmacAlgorithm algorithm)
  83. {
  84.     string str = "";
  85.     try
  86.     {
            // core algorithm to make new session key
  87.         string str2 = string.Format("iat: {1}\n", issuedTo, timestamp)
  88.         string str3 = Convert.ToBase64String(Encoding.get_UTF8().GetBytes(str2));
  89.         string str4 = string.Empty;
  90.         string str5 = str3 + "." + str4;
  91.         byte[] key = Convert.FromBase64String(encodedSecretKey);
  92.         string str6 = Convert.ToBase64String(HmacAlgorithm.CreateInstance(algorithm.Name, key).ComputeHash(Encoding.get_UTF8().GetBytes(str5)));
  93.         str = str5 + "." + str6; // base64(issuedTo) + '..' + Hmac(SecretKey)
  94.     }
  95.     catch (Exception)
  96.     {
  97.     }
  98.     return str;
  99. }

Anyway, I wrote an C# code that make updated session key... 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ConsoleApplication1
  6. {
  7.    
  8.     class Program
  9.     {
  10.         static void Main(string[] args)
  11.         {
  12.             String issuedTo = "1" ;
  13.             DateTime l = DateTime .UtcNow;
  14.             long timestamp = (long )((- new DateTime(1970110001)).TotalMilliseconds);
  15.             String authToken = "????" // your old session key
  16.             string[] strArray = authToken.Split(new char[] { ':' });
  17.             string issueTo = strArray[0];
  18.             string encodedSecretKey = strArray[1];
  19.             string str2 = string .Format("iat: {1}\n", issuedTo, timestamp);
  20.             string str3 = Convert .ToBase64String(Encoding.UTF8.GetBytes(str2));
  21.             string str4 = string .Empty;
  22.             string str5 = str3 + "." + str4;
  23.             byte[] key = Convert .FromBase64String(encodedSecretKey);
  24.             string str6 = Convert.ToBase64String(LINE.Service.YamlWebToken .HmacAlgorithm.CreateInstance(LINE.Service.YamlWebToken.DEFAULT_ALOGORITHM.Name, key).ComputeHash(Encoding.UTF8.GetBytes(str5)));
  25.             String str = str5 + "." + str6 // base64(issuedTo) + '..' + Hmac(SecretKey)
  26.         }
  27.     }
  28. }

댓글 없음:

댓글 쓰기