2019-06-18 22:55:32 -04:00
/ *
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Copyright ( C ) 2015 - 2019 Project Meteor Dev Team
This file is part of Project Meteor Server .
Project Meteor Server is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Project Meteor Server is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server . If not , see < https : www . gnu . org / licenses / > .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* /
2015-08-26 13:38:58 -04:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2016-03-05 18:02:37 -05:00
using System.Security.Cryptography ;
2015-08-26 13:38:58 -04:00
using System.Text ;
2019-06-19 00:05:18 -04:00
using Meteor.Common ;
using Meteor.Lobby.DataObjects ;
using Meteor.Lobby.Packets ;
using Meteor.Lobby.Packets.Receive ;
namespace Meteor.Lobby
2015-08-26 13:38:58 -04:00
{
class PacketProcessor
{
2016-06-14 21:29:10 +01:00
public void ProcessPacket ( ClientConnection client , BasePacket packet )
2015-08-26 13:38:58 -04:00
{
if ( ( packet . header . packetSize = = 0x288 ) & & ( packet . data [ 0x34 ] = = 'T' ) ) //Test Ticket Data
{
2016-06-14 21:29:10 +01:00
packet . DebugPrintPacket ( ) ;
2015-08-26 13:38:58 -04:00
//Crypto handshake
ProcessStartSession ( client , packet ) ;
return ;
}
2016-02-16 23:35:21 -05:00
2016-06-14 21:29:10 +01:00
BasePacket . DecryptPacket ( client . blowfish , ref packet ) ;
2015-08-26 13:38:58 -04:00
2016-06-14 21:29:10 +01:00
packet . DebugPrintPacket ( ) ;
2015-08-26 13:38:58 -04:00
2016-06-14 21:29:10 +01:00
List < SubPacket > subPackets = packet . GetSubpackets ( ) ;
2015-08-26 13:38:58 -04:00
foreach ( SubPacket subpacket in subPackets )
2015-09-13 18:21:28 -04:00
{
2016-06-14 21:29:10 +01:00
subpacket . DebugPrintSubPacket ( ) ;
2016-02-16 23:35:21 -05:00
if ( subpacket . header . type = = 3 )
2015-08-26 13:38:58 -04:00
{
2016-02-16 23:35:21 -05:00
switch ( subpacket . gameMessage . opcode )
{
case 0x03 :
ProcessGetCharacters ( client , subpacket ) ;
break ;
case 0x04 :
ProcessSelectCharacter ( client , subpacket ) ;
break ;
case 0x05 :
ProcessSessionAcknowledgement ( client , subpacket ) ;
break ;
case 0x0B :
ProcessModifyCharacter ( client , subpacket ) ;
break ;
case 0x0F :
2015-09-02 14:07:45 -04:00
//Mod Retainers
2016-02-16 23:35:21 -05:00
default :
2016-06-14 05:09:30 +01:00
Program . Log . Debug ( "Unknown command 0x{0:X} received." , subpacket . gameMessage . opcode ) ;
2016-02-16 23:35:21 -05:00
break ;
}
2015-08-26 13:38:58 -04:00
}
}
}
private void ProcessStartSession ( ClientConnection client , BasePacket packet )
{
2016-03-05 18:02:37 -05:00
SecurityHandshakePacket securityHandshake = new SecurityHandshakePacket ( packet . data ) ;
2015-08-26 13:38:58 -04:00
2016-03-05 18:02:37 -05:00
byte [ ] blowfishKey = GenerateKey ( securityHandshake . ticketPhrase , securityHandshake . clientNumber ) ;
2015-08-26 13:38:58 -04:00
client . blowfish = new Blowfish ( blowfishKey ) ;
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "SecCNum: 0x{0:X}" , securityHandshake . clientNumber ) ;
2015-08-26 13:38:58 -04:00
//Respond with acknowledgment
BasePacket outgoingPacket = new BasePacket ( HardCoded_Packets . g_secureConnectionAcknowledgment ) ;
2016-06-14 21:29:10 +01:00
BasePacket . EncryptPacket ( client . blowfish , outgoingPacket ) ;
client . QueuePacket ( outgoingPacket ) ;
2015-08-26 13:38:58 -04:00
}
private void ProcessSessionAcknowledgement ( ClientConnection client , SubPacket packet )
{
2016-06-14 21:29:10 +01:00
packet . DebugPrintSubPacket ( ) ;
2016-02-18 23:55:03 -05:00
SessionPacket sessionPacket = new SessionPacket ( packet . data ) ;
2015-08-27 10:19:00 -04:00
String clientVersion = sessionPacket . version ;
2015-08-26 13:38:58 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "Got acknowledgment for secure session." ) ;
Program . Log . Info ( "CLIENT VERSION: {0}" , clientVersion ) ;
2015-08-26 13:38:58 -04:00
2016-06-14 21:29:10 +01:00
uint userId = Database . GetUserIdFromSession ( sessionPacket . session ) ;
2015-08-27 10:19:00 -04:00
client . currentUserId = userId ;
2015-09-13 18:21:28 -04:00
client . currentSessionToken = sessionPacket . session ; ;
2015-08-26 13:38:58 -04:00
2015-08-27 10:19:00 -04:00
if ( userId = = 0 )
{
2017-06-29 11:38:28 -04:00
ErrorPacket errorPacket = new ErrorPacket ( sessionPacket . sequence , 0 , 0 , 13001 , "Your session has expired, please login again." ) ;
SubPacket subpacket = errorPacket . BuildPacket ( ) ;
subpacket . SetTargetId ( 0xe0006868 ) ;
BasePacket errorBasePacket = BasePacket . CreatePacket ( subpacket , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , errorBasePacket ) ;
client . QueuePacket ( errorBasePacket ) ;
Program . Log . Info ( "Invalid session, kicking..." ) ;
return ;
2015-08-27 10:19:00 -04:00
}
2015-08-26 13:38:58 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "USER ID: {0}" , userId ) ;
2015-09-13 18:21:28 -04:00
List < Account > accountList = new List < Account > ( ) ;
Account defaultAccount = new Account ( ) ;
defaultAccount . id = 1 ;
defaultAccount . name = "FINAL FANTASY XIV" ;
accountList . Add ( defaultAccount ) ;
AccountListPacket listPacket = new AccountListPacket ( 1 , accountList ) ;
2016-06-14 21:29:10 +01:00
BasePacket basePacket = BasePacket . CreatePacket ( listPacket . BuildPackets ( ) , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-08-26 13:38:58 -04:00
}
private void ProcessGetCharacters ( ClientConnection client , SubPacket packet )
{
2016-06-14 21:29:10 +01:00
Program . Log . Info ( "{0} => Get characters" , client . currentUserId = = 0 ? client . GetAddress ( ) : "User " + client . currentUserId ) ;
2015-09-02 14:07:45 -04:00
2016-06-14 21:29:10 +01:00
SendWorldList ( client , packet ) ;
SendImportList ( client , packet ) ;
SendRetainerList ( client , packet ) ;
SendCharacterList ( client , packet ) ;
2015-09-10 00:52:31 -04:00
2015-08-26 13:38:58 -04:00
}
private void ProcessSelectCharacter ( ClientConnection client , SubPacket packet )
{
2016-02-18 23:55:03 -05:00
SelectCharacterPacket selectCharRequest = new SelectCharacterPacket ( packet . data ) ;
2015-09-13 18:21:28 -04:00
2016-06-14 21:29:10 +01:00
Program . Log . Info ( "{0} => Select character id {1}" , client . currentUserId = = 0 ? client . GetAddress ( ) : "User " + client . currentUserId , selectCharRequest . characterId ) ;
2015-08-26 13:38:58 -04:00
2016-06-14 21:29:10 +01:00
Character chara = Database . GetCharacter ( client . currentUserId , selectCharRequest . characterId ) ;
2015-09-13 18:21:28 -04:00
World world = null ;
2015-08-26 13:38:58 -04:00
2015-09-13 18:21:28 -04:00
if ( chara ! = null )
2016-06-14 21:29:10 +01:00
world = Database . GetServer ( chara . serverId ) ;
2015-08-26 13:38:58 -04:00
2015-09-13 18:21:28 -04:00
if ( world = = null )
2015-08-26 13:38:58 -04:00
{
2016-06-14 21:29:10 +01:00
ErrorPacket errorPacket = new ErrorPacket ( selectCharRequest . sequence , 0 , 0 , 13001 , "World Does not exist or is inactive." ) ;
SubPacket subpacket = errorPacket . BuildPacket ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subpacket , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-13 18:21:28 -04:00
return ;
2015-08-26 13:38:58 -04:00
}
2015-09-13 18:21:28 -04:00
SelectCharacterConfirmPacket connectCharacter = new SelectCharacterConfirmPacket ( selectCharRequest . sequence , selectCharRequest . characterId , client . currentSessionToken , world . address , world . port , selectCharRequest . ticket ) ;
2016-06-14 21:29:10 +01:00
BasePacket outgoingPacket = BasePacket . CreatePacket ( connectCharacter . BuildPackets ( ) , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , outgoingPacket ) ;
client . QueuePacket ( outgoingPacket ) ;
2015-08-26 13:38:58 -04:00
}
private void ProcessModifyCharacter ( ClientConnection client , SubPacket packet )
{
2016-02-18 23:55:03 -05:00
CharacterModifyPacket charaReq = new CharacterModifyPacket ( packet . data ) ;
2015-08-26 13:38:58 -04:00
var slot = charaReq . slot ;
var name = charaReq . characterName ;
var worldId = charaReq . worldId ;
2015-09-08 00:42:02 -04:00
uint pid = 0 , cid = 0 ;
2015-09-13 11:30:33 -04:00
//Get world from new char instance
2015-09-09 00:08:46 -04:00
if ( worldId = = 0 )
worldId = client . newCharaWorldId ;
2015-09-08 00:42:02 -04:00
2016-06-14 22:54:02 +01:00
//Check if this character exists, Get world from there
2015-09-13 11:30:33 -04:00
if ( worldId = = 0 & & charaReq . characterId ! = 0 )
{
2016-06-14 21:29:10 +01:00
Character chara = Database . GetCharacter ( client . currentUserId , charaReq . characterId ) ;
2015-09-13 11:30:33 -04:00
if ( chara ! = null )
worldId = chara . serverId ;
}
2015-09-09 00:08:46 -04:00
string worldName = null ;
2016-06-14 21:29:10 +01:00
World world = Database . GetServer ( worldId ) ;
2015-09-08 00:42:02 -04:00
if ( world ! = null )
worldName = world . name ;
if ( worldName = = null )
{
2016-06-14 21:29:10 +01:00
ErrorPacket errorPacket = new ErrorPacket ( charaReq . sequence , 0 , 0 , 13001 , "World Does not exist or is inactive." ) ;
SubPacket subpacket = errorPacket . BuildPacket ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subpacket , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-08 00:42:02 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Error; invalid server id: \"{1}\"" , client . currentUserId , worldId ) ;
2015-09-08 00:42:02 -04:00
return ;
}
2015-09-13 11:30:33 -04:00
bool alreadyTaken ;
2016-02-20 00:11:51 -05:00
switch ( charaReq . command )
2015-08-26 13:38:58 -04:00
{
case 0x01 : //Reserve
2015-09-08 00:42:02 -04:00
2016-06-14 21:29:10 +01:00
alreadyTaken = Database . ReserveCharacter ( client . currentUserId , slot , worldId , name , out pid , out cid ) ;
2015-08-27 10:19:00 -04:00
if ( alreadyTaken )
2015-09-02 14:07:45 -04:00
{
2015-09-09 00:08:46 -04:00
ErrorPacket errorPacket = new ErrorPacket ( charaReq . sequence , 1003 , 0 , 13005 , "" ) ; //BDB - Chara Name Used, //1003 - Bad Word
2016-06-14 21:29:10 +01:00
SubPacket subpacket = errorPacket . BuildPacket ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subpacket , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-02 14:07:45 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Error; name taken: \"{1}\"" , client . currentUserId , charaReq . characterName ) ;
2015-09-02 14:07:45 -04:00
return ;
2015-09-08 19:39:52 -04:00
}
2015-09-09 00:08:46 -04:00
else
{
pid = 0 ;
client . newCharaCid = cid ;
client . newCharaSlot = slot ;
client . newCharaWorldId = worldId ;
client . newCharaName = name ;
}
2015-08-26 13:38:58 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Character reserved \"{1}\"" , client . currentUserId , name ) ;
2015-08-26 13:38:58 -04:00
break ;
case 0x02 : //Make
2016-06-14 21:29:10 +01:00
CharaInfo info = CharaInfo . GetFromNewCharRequest ( charaReq . characterInfoEncoded ) ;
2015-09-09 00:08:46 -04:00
2016-02-20 11:20:59 -05:00
//Set Initial Appearance (items will be loaded in by map server)
2016-03-20 11:49:09 -04:00
uint [ ] classAppearance = CharacterCreatorUtils . GetEquipmentForClass ( info . currentClass ) ;
2016-02-20 00:11:51 -05:00
info . weapon1 = classAppearance [ 0 ] ;
info . weapon2 = classAppearance [ 1 ] ;
2016-02-20 11:20:59 -05:00
info . head = classAppearance [ 7 ] ;
2016-03-20 11:49:09 -04:00
if ( classAppearance [ 8 ] ! = 0 )
info . body = classAppearance [ 8 ] ;
else
info . body = CharacterCreatorUtils . GetUndershirtForTribe ( info . tribe ) ;
2016-02-20 11:20:59 -05:00
info . legs = classAppearance [ 9 ] ;
info . hands = classAppearance [ 10 ] ;
info . feet = classAppearance [ 11 ] ;
info . belt = classAppearance [ 12 ] ;
2016-02-20 00:11:51 -05:00
//Set Initial Position
switch ( info . initialTown )
{
2016-03-05 18:02:37 -05:00
case 1 : //ocn0Battle02 (Limsa)
2016-02-20 00:11:51 -05:00
info . zoneId = 193 ;
info . x = 0.016f ;
info . y = 10.35f ;
info . z = - 36.91f ;
2016-04-17 19:09:01 -04:00
info . rot = 0.025f ;
2016-02-20 00:11:51 -05:00
break ;
2016-03-05 18:02:37 -05:00
case 2 : //fst0Battle03 (Gridania)
2016-02-20 00:11:51 -05:00
info . zoneId = 166 ;
2016-04-17 19:09:01 -04:00
info . x = 369.5434f ;
info . y = 4.21f ;
info . z = - 706.1074f ;
info . rot = - 1.26721f ;
2016-02-20 00:11:51 -05:00
break ;
2016-03-05 18:02:37 -05:00
case 3 : //wil0Battle01 (Ul'dah)
2016-02-20 00:11:51 -05:00
info . zoneId = 184 ;
2016-04-17 19:09:01 -04:00
info . x = 5.364327f ;
info . y = 196.0f ;
info . z = 133.6561f ;
info . rot = - 2.849384f ;
2016-02-20 00:11:51 -05:00
break ;
}
2016-06-14 21:29:10 +01:00
Database . MakeCharacter ( client . currentUserId , client . newCharaCid , info ) ;
2015-09-07 23:43:23 -04:00
2015-09-09 00:08:46 -04:00
pid = 1 ;
cid = client . newCharaCid ;
2015-09-13 11:30:33 -04:00
name = client . newCharaName ;
2015-08-26 13:38:58 -04:00
2016-06-14 21:29:10 +01:00
Program . Log . Info ( "User {0} => Character Created \"{1}\"" , client . currentUserId , name ) ;
2015-08-26 13:38:58 -04:00
break ;
case 0x03 : //Rename
2015-09-13 11:30:33 -04:00
2016-06-14 21:29:10 +01:00
alreadyTaken = Database . RenameCharacter ( client . currentUserId , charaReq . characterId , worldId , charaReq . characterName ) ;
2015-09-13 11:30:33 -04:00
if ( alreadyTaken )
{
ErrorPacket errorPacket = new ErrorPacket ( charaReq . sequence , 1003 , 0 , 13005 , "" ) ; //BDB - Chara Name Used, //1003 - Bad Word
2016-06-14 21:29:10 +01:00
SubPacket subpacket = errorPacket . BuildPacket ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subpacket , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-13 11:30:33 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Error; name taken: \"{1}\"" , client . currentUserId , charaReq . characterName ) ;
2015-09-13 11:30:33 -04:00
return ;
}
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Character renamed \"{1}\"" , client . currentUserId , name ) ;
2015-08-26 13:38:58 -04:00
break ;
case 0x04 : //Delete
2016-06-14 21:29:10 +01:00
Database . DeleteCharacter ( charaReq . characterId , charaReq . characterName ) ;
2015-09-13 11:30:33 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Character deleted \"{1}\"" , client . currentUserId , name ) ;
2015-08-26 13:38:58 -04:00
break ;
case 0x06 : //Rename Retainer
2015-09-07 23:43:23 -04:00
2016-06-14 05:09:30 +01:00
Program . Log . Info ( "User {0} => Retainer renamed \"{1}\"" , client . currentUserId , name ) ;
2015-08-26 13:38:58 -04:00
break ;
2015-09-08 00:42:02 -04:00
}
2016-02-20 00:11:51 -05:00
CharaCreatorPacket charaCreator = new CharaCreatorPacket ( charaReq . sequence , charaReq . command , pid , cid , 1 , name , worldName ) ;
2016-06-14 21:29:10 +01:00
BasePacket charaCreatorPacket = BasePacket . CreatePacket ( charaCreator . BuildPacket ( ) , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , charaCreatorPacket ) ;
client . QueuePacket ( charaCreatorPacket ) ;
2015-09-08 00:42:02 -04:00
2015-09-03 22:20:53 -04:00
}
2016-06-14 21:29:10 +01:00
private void SendWorldList ( ClientConnection client , SubPacket packet )
2015-09-03 22:20:53 -04:00
{
2016-06-14 21:29:10 +01:00
List < World > serverList = Database . GetServers ( ) ;
2015-09-13 11:30:33 -04:00
WorldListPacket worldlistPacket = new WorldListPacket ( 0 , serverList ) ;
2016-06-14 21:29:10 +01:00
List < SubPacket > subPackets = worldlistPacket . BuildPackets ( ) ;
2015-09-03 22:20:53 -04:00
2016-06-14 21:29:10 +01:00
BasePacket basePacket = BasePacket . CreatePacket ( subPackets , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-03 23:07:56 -04:00
2015-08-26 13:38:58 -04:00
}
2016-06-14 21:29:10 +01:00
private void SendImportList ( ClientConnection client , SubPacket packet )
2015-09-02 14:07:45 -04:00
{
2016-06-14 21:29:10 +01:00
List < String > names = Database . GetReservedNames ( client . currentUserId ) ;
2015-09-02 14:07:45 -04:00
2015-09-13 11:30:33 -04:00
ImportListPacket importListPacket = new ImportListPacket ( 0 , names ) ;
2016-06-14 21:29:10 +01:00
List < SubPacket > subPackets = importListPacket . BuildPackets ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subPackets , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-03 22:20:53 -04:00
}
2016-06-14 21:29:10 +01:00
private void SendRetainerList ( ClientConnection client , SubPacket packet )
2015-09-03 22:20:53 -04:00
{
2016-06-14 21:29:10 +01:00
List < Retainer > retainers = Database . GetRetainers ( client . currentUserId ) ;
2015-09-10 00:52:31 -04:00
2015-09-13 11:30:33 -04:00
RetainerListPacket retainerListPacket = new RetainerListPacket ( 0 , retainers ) ;
2016-06-14 21:29:10 +01:00
List < SubPacket > subPackets = retainerListPacket . BuildPackets ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subPackets , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-03 22:20:53 -04:00
}
2015-09-03 01:02:55 -04:00
2016-06-14 21:29:10 +01:00
private void SendCharacterList ( ClientConnection client , SubPacket packet )
2015-09-03 22:20:53 -04:00
{
2016-06-14 21:29:10 +01:00
List < Character > characterList = Database . GetCharacters ( client . currentUserId ) ;
2015-09-07 12:12:08 -04:00
2015-09-13 11:30:33 -04:00
if ( characterList . Count > 8 )
2016-06-12 20:12:59 +01:00
Program . Log . Error ( "Warning, got more than 8 characters. List truncated, check DB for issues." ) ;
2015-09-13 11:30:33 -04:00
CharacterListPacket characterlistPacket = new CharacterListPacket ( 0 , characterList ) ;
2016-06-14 21:29:10 +01:00
List < SubPacket > subPackets = characterlistPacket . BuildPackets ( ) ;
BasePacket basePacket = BasePacket . CreatePacket ( subPackets , true , false ) ;
BasePacket . EncryptPacket ( client . blowfish , basePacket ) ;
client . QueuePacket ( basePacket ) ;
2015-09-02 14:07:45 -04:00
}
2016-03-05 18:02:37 -05:00
private byte [ ] GenerateKey ( string ticketPhrase , uint clientNumber )
{
byte [ ] key ;
using ( MemoryStream memStream = new MemoryStream ( 0x2C ) )
{
using ( BinaryWriter binWriter = new BinaryWriter ( memStream ) )
{
binWriter . Write ( ( Byte ) 0x78 ) ;
binWriter . Write ( ( Byte ) 0x56 ) ;
binWriter . Write ( ( Byte ) 0x34 ) ;
binWriter . Write ( ( Byte ) 0x12 ) ;
binWriter . Write ( ( UInt32 ) clientNumber ) ;
binWriter . Write ( ( Byte ) 0xE8 ) ;
binWriter . Write ( ( Byte ) 0x03 ) ;
binWriter . Write ( ( Byte ) 0x00 ) ;
binWriter . Write ( ( Byte ) 0x00 ) ;
binWriter . Write ( Encoding . ASCII . GetBytes ( ticketPhrase ) , 0 , Encoding . ASCII . GetByteCount ( ticketPhrase ) > = 0x20 ? 0x20 : Encoding . ASCII . GetByteCount ( ticketPhrase ) ) ;
}
byte [ ] nonMD5edKey = memStream . GetBuffer ( ) ;
using ( MD5 md5Hash = MD5 . Create ( ) )
{
key = md5Hash . ComputeHash ( nonMD5edKey ) ;
}
}
return key ;
}
2015-08-26 13:38:58 -04:00
}
}