using System; using System.Collections.Generic; using System.Text; namespace MakeMasterKeyForCtr3rd { class Program { const int TABLE_SIZE = 0x100; const uint BYTE_BITS = 8; const uint POLY_MASK = 0xedba6320; static readonly uint[] CRC_TABLE = CreateCrc32Table(); static uint[] CreateCrc32Table() { uint[] table = new uint[TABLE_SIZE]; uint crc; for ( uint ui = 0; ui < TABLE_SIZE; ui++ ) { crc = ui; for ( uint uj = BYTE_BITS; uj > 0; uj-- ) { if ( (crc & 1) == 1 ) { crc = (crc >> 1) ^ POLY_MASK; } else { crc = crc >> 1; } } table[ui] = crc; } return table; } static uint CalculateCrc32(byte[] src, int len) { uint crc = 0xffffffff; int index = 0; while ( len != 0 ) { crc = ((crc >> 8) & 0xffffffff) ^ CRC_TABLE[(crc ^ src[index]) & 0xff]; index++; len--; } return crc; } static uint MakeMasterKeyOld(byte[] src) { uint masterKey; masterKey = ((CalculateCrc32(src, src.Length) ^ 0xaaaa) + 5719) % 100000; return masterKey; } /// /// Main 関数 /// static int Main(string[] args) { uint masterKey; // 引数の数チェック if ( args.Length != 2 ) { Console.Write("Invalid Argument!\n\n"); ShowUsage(); return -1; } // 引数の文字数チェック if ( (args[0].Length != 4) || ((args[1].Length != 8) && (args[1].Length != 10)) ) { Console.Write("Invalid Argument!\n\n"); ShowUsage(); return -1; } // 引数の数値チェック { long tmp; if ( !long.TryParse(args[0], out tmp) || !long.TryParse(args[1], out tmp) ) { Console.Write("Invalid Argument!\n\n"); ShowUsage(); return -1; } } // フォーマットの分岐 if ( args[1].Length == 8 ) { // 入力データの作成(旧フォーマット) byte[] inputData = System.Text.Encoding.ASCII.GetBytes(args[0] + args[1].Substring(4, 4)); masterKey = MakeMasterKeyOld(inputData); } else { // 入力データの作成(新フォーマット) byte[] inputData = System.Text.Encoding.ASCII.GetBytes(args[0] + args[1]); byte[] keyData; String region = args[1].Substring(0, 1); // リージョンチェック if ( (region != REGION.JPN) && (region != REGION.USZ) && (region != REGION.EUR) && (region != REGION.KOR) && (region != REGION.EX_JPN) ) { Console.Write("Unsupported Region!\n\n"); return -1; } // バージョンチェック if ( args[1].Substring(1, 1) == HMAC_OLD_KEY.VERSION ) { // 旧仕様 if ( (region == REGION.KOR) || (region == REGION.EX_JPN) ) { Console.Write("Unsupported Version!\n\n"); return -1; } switch ( region ) { case REGION.JPN: keyData = HMAC_OLD_KEY.JPN; break; case REGION.USZ: keyData = HMAC_OLD_KEY.USZ; break; case REGION.EUR: keyData = HMAC_OLD_KEY.EUR; break; default: // 到達することはないけどビルドエラー対策 Console.Write("Unsupported Region!\n\n"); return -1; } } else { // 新仕様 int keyVersion = int.Parse(args[1].Substring(1, 2)); if ( (HMAC_NEW_KEY.VERSION_MIN <= keyVersion) && (keyVersion <= HMAC_NEW_KEY.VERSION_MAX) ) { switch ( region ) { case REGION.JPN: keyData = HMAC_NEW_KEY.JPN[keyVersion - HMAC_NEW_KEY.VERSION_MIN]; break; case REGION.USZ: keyData = HMAC_NEW_KEY.USZ[keyVersion - HMAC_NEW_KEY.VERSION_MIN]; break; case REGION.EUR: keyData = HMAC_NEW_KEY.EUR[keyVersion - HMAC_NEW_KEY.VERSION_MIN]; break; case REGION.KOR: keyData = HMAC_NEW_KEY.KOR[keyVersion - HMAC_NEW_KEY.VERSION_MIN]; break; case REGION.EX_JPN: keyData = HMAC_NEW_KEY.JPN[keyVersion - HMAC_NEW_KEY.VERSION_MIN]; break; default: // 到達することはないけどビルドエラー対策 Console.Write("Unsupported Region!\n\n"); return -1; } } else { Console.Write("Unsupported Version!\n\n"); return -1; } } { // HAMC-SHA256 の計算 System.Security.Cryptography.HMACSHA256 hmac = new System.Security.Cryptography.HMACSHA256(keyData); byte[] result = hmac.ComputeHash(inputData); // 先頭 4 バイトをリトルエンディアンで数値化 masterKey = (result[3] & (uint)0xff) << 24 | (result[2] & (uint)0xff) << 16 | (result[1] & (uint)0xff) << 8 | result[0] & (uint)0xff; // 10進 5 桁にまるめる masterKey = masterKey % 100000; } } // 結果出力 Console.Write("Master Key = {0:D5}\n", masterKey); // 正常終了 return 0; } static void ShowUsage() { Console.Write("---- MakeMasterKeyForCtr - Feb. 10, 2015 ----\n"); Console.Write("\n"); Console.Write("Usage: MakeMasterKeyForCtr [date] [code]\n"); Console.Write("\n"); Console.Write("Example: date = Sep. 8 code = 12345678\n"); Console.Write(" > MakeMasterKeyForCtr 0908 12345678\n"); Console.Write("\n"); Console.Write("Example: date = Nov. 12 code = 10123 45678\n"); Console.Write(" > MakeMasterKeyForCtr 1112 1012345678\n"); } } }