Nostale NodeJS cryptography

06/25/2019 08:39 emerickpw#1
Hi, I need some help.

I would like to use Nostale Cryptography, to log an account into a VPS
(I have some Jelly's, they gave me some Angel's feather every hours, that's pretty nice.

Then the point is:

I try to use NodeJS cryptography => [Only registered and activated users can see links. Click Here To Register...]

I've used the given example, but i'm a bit lost.

I can format the packet to send, according to packet logger, that's nice, but, i have still problem :

- Pipeline is not a function, i have no idea about this, can you help me ?

(PS - sry for my English ;D )
06/25/2019 18:12 Nortank#2
I think that (like me) you don't know how to code in Node.JS.

"
I would like to use Nostale Cryptography, to log an account into a VPS
"

You should use something like C++ and (still) run it on a vps. or even a raspberry pi or something like that.
06/25/2019 22:23 Cryless~#3
Quote:
Originally Posted by Nortank View Post
I think that (like me) you don't know how to code in Node.JS.

"
I would like to use Nostale Cryptography, to log an account into a VPS
"

You should use something like C++ and (still) run it on a vps. or even a raspberry pi or something like that.
Why do you reply posts you do not understand at all?
06/26/2019 10:11 emerickpw#4
Quote:
Originally Posted by Nortank View Post
I think that (like me) you don't know how to code in Node.JS.

"
I would like to use Nostale Cryptography, to log an account into a VPS
"

You should use something like C++ and (still) run it on a vps. or even a raspberry pi or something like that.
That's why I try to learn.

I solved my problem by updating NodeJS to the latest LTS version, it work perfectly, I can now receive the server's response.

Then now, how to connect(or switch) to the Channel server ?

There is my code:

Code:
'use strict'

const { pipeline } = require('stream');
const iconv = require('iconv-lite');
const net = require('net');
const nosCrypto = require('nostale-cryptography/client')

const host = 'xx.xx.xx.xx' //login server's ip
const port = 'xxxx' //Port

const socket = net.connect(port, host, () => {
  const encryptStream = nosCrypto.createCipher()
  const decryptStream = nosCrypto.createDecipher()

  const encodingStream = iconv.encodeStream('win1252'); 
  const decodingStream = iconv.decodeStream('win1252'); 

  pipeline(
    encodingStream,
    encryptStream,
    socket,
    decryptStream,
    decodingStream,
    err => {
      if (err) {
        console.error('Pipeline failed.', err);
      } else {
        console.log('Pipeline succeeded.');
      }

      console.log('Game closed because stream pipeline closed.')
    }
  )

  buildLoginPacket().then((loginPacket) => {
    console.log(loginPacket)

    encodingStream.write(loginPacket)

    decodingStream.on('data', (packet) => {
      console.log(packet)

      if (packet.startsWith('NsTeST')) {
        console.log('Login packet received')

        //send packet to channel/server ip and port, according to server response ?
        
      }else{
        console.log("This account is already connected")
      }
    })
  })
})

async function buildLoginPacket() {
  const nostalePath = './client' //Put NostaleClient.exe and NostaleClientX.exe in this folder
  const username = 'myLogin' //my login
  const password = 'myPassword' //my password
  const versionJeu = '0.9.3.3104'   //current version of nostaleClientX.exe

  const encodedUsername = iconv.encode(username, 'win1252') 
  const encodedPassword = iconv.encode(password, 'win1252') 

  const random = Math.floor(Math.random() * 9999999)
  const encryptedPassword = nosCrypto.encryptPassword(encodedPassword)
  const guid = 'xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx' // Used only by the Gameforge Client
  const version = await nosCrypto.createVersion(versionJeu)
  const checksumHash = await nosCrypto.createChecksumHash(encodedUsername, nostalePath) 

  return `NoS0575 ${random} ${username} ${encryptedPassword} ${guid} ${version} 0 ${checksumHash}`
}
How to switch from "login Server" from "Game Server?
Thank's
06/26/2019 10:39 ryuuzaki77#5
Quote:
Originally Posted by emerickpw View Post
- Pipeline is not a function, i have no idea about this, can you help me ?
Yes it was because you were using an older node version, stream pipeline was introduced with node v10:
[Only registered and activated users can see links. Click Here To Register...]


Quote:
Originally Posted by emerickpw View Post

How to switch from "login Server" from "Game Server?
You're actually on the right path : you have to split that NsTeST packet. It will be something like that
Code:
NsTeST username sessionId 79.110.84.37:4015:0:2.6.Galaxie 79.110.84.37:4016:0:2.7.Galaxie 79.110.84.37:4013:0:2.4.Galaxie 79.110.84.37:4011:4:2.2.Galaxie 79.110.84.37:4012:0:2.3.Galaxie 79.110.84.37:4014:0:2.5.Galaxie 79.110.84.37:4010:0:2.1.Galaxie 79.110.84.250:4016:0:1.7.Cosmos 79.110.84.250:4015:0:1.6.Cosmos 79.110.84.250:4014:0:1.5.Cosmos 79.110.84.250:4011:6:1.2.Cosmos 79.110.84.250:4012:0:1.3.Cosmos 79.110.84.250:4013:0:1.4.Cosmos 79.110.84.250:4010:0:1.1.Cosmos -1:-1:-1:10000.10000.4
For example :
Code:
79.110.84.37:4015:0:2.6.Galaxie
If you split this you have :
79.110.84.37 : host
4015 : port
0 : usage (recommended / full etc )
2 : server
6 : channel
Galaxie : server name

You can help yourself reading projects like this :
[Only registered and activated users can see links. Click Here To Register...]
06/26/2019 13:09 Cryless~#6
You can find more information here: [Only registered and activated users can see links. Click Here To Register...]
06/26/2019 15:39 emerickpw#7
Thank's but i'm a bit lost, i've tried lot of times, but idk how to format responses (Session, Identifier+ username , and Identifier + password) after receiving NsTeST answer from the server, and if i mus send them to the login server, or in the IP:PORT from the game's channel ?
06/26/2019 16:31 Roxeez#8
Quote:
Originally Posted by emerickpw View Post
Thank's but i'm a bit lost, i've tried lot of times, but idk how to format responses (Session, Identifier+ username , and Identifier + password) after receiving NsTeST answer from the server, and if i mus send them to the login server, or in the IP:PORT from the game's channel ?
After receiving NsTeST, disconnect from login server and connect to one of the world server (one of the ip/port received in NsTeST) then you need to send the encryption key received in NSTeST and your username/password (in 3 different packet) only the first one is a session packet and you need to use the world encryption not the login encryption (because you are connected to world server not login server obviously)
06/27/2019 13:09 emerickpw#9
Quote:
Originally Posted by Roxeez View Post
After receiving NsTeST, disconnect from login server and connect to one of the world server (one of the ip/port received in NsTeST) then you need to send the encryption key received in NSTeST and your username/password (in 3 different packet) only the first one is a session packet and you need to use the world encryption not the login encryption (because you are connected to world server not login server obviously)
Ok then i have something like that:

Code:
       
        var host = '79.110.84.xx' //Ip
        var port = 40xx //Port
        var worldSocket = new net.Socket();
        worldSocket.connect(port, host, () => {
          console.log(session)
          const encryptWorldStream = nosCrypto.createCipher(session)
          console.log("encrypt world stream " + encryptWorldStream)
          const decryptWorldStream = nosCrypto.createDecipher(session)

          const encodingStream = iconv.encodeStream('win1252'); 
          const decodingStream = iconv.decodeStream('win1252'); 

          pipeline(
            encodingStream,
            encryptWorldStream,
            worldSocket,
            decryptWorldStream,
            decodingStream,
            err => {
              if (err) {
                console.error('Pipeline failed.', err);
              } else {
                console.log('Pipeline succeeded.');
              }

              console.log('Game closed because stream pipeline closed.')
            }
          )

          buildWorldPacket(1, encryptWorldStream).then((loginPacket) => {
            console.log(loginPacket)

            encodingStream.write(loginPacket)

            decodingStream.on('data', (packet) => {
              console.log(packet)
            })
          })
          //wait1 sec
          setTimeout(() => {
            buildWorldPacket(2, session).then((loginPacket) => {
              console.log(loginPacket)


              encodingStream.write(loginPacket)

              decodingStream.on('data', (packet) => {
                console.log(packet)
              })
            })

            buildWorldPacket(3, session).then((loginPacket) => {
              console.log(loginPacket)

              encodingStream.write(loginPacket)

              decodingStream.on('data', (packet) => {
                console.log(packet)
              })
            })
          }, 1000);
        })

        

async function buildWorldPacket(packetNumber, session) {


  if (packetNumber == 1) {
    console.log("return encrypted session")
    return session
  }
  if (packetNumber == 2) {
    console.log("return username")
    return username
  }
  if (packetNumber == 3) {
    console.log("return pwd")
    return password
  }

}

Am I right ?
Because EncryptWorldSession return an object, but a string was expected :/
06/27/2019 14:22 FI0w#10
Quote:
Originally Posted by emerickpw View Post
Ok then i have something like that:

Code:
       
        var host = '79.110.84.xx' //Ip
        var port = 40xx //Port
        var worldSocket = new net.Socket();
        worldSocket.connect(port, host, () => {
          console.log(session)
          const encryptWorldStream = nosCrypto.createCipher(session)
          console.log("encrypt world stream " + encryptWorldStream)
          const decryptWorldStream = nosCrypto.createDecipher(session)

          const encodingStream = iconv.encodeStream('win1252'); 
          const decodingStream = iconv.decodeStream('win1252'); 

          pipeline(
            encodingStream,
            encryptWorldStream,
            worldSocket,
            decryptWorldStream,
            decodingStream,
            err => {
              if (err) {
                console.error('Pipeline failed.', err);
              } else {
                console.log('Pipeline succeeded.');
              }

              console.log('Game closed because stream pipeline closed.')
            }
          )

          buildWorldPacket(1, encryptWorldStream).then((loginPacket) => {
            console.log(loginPacket)

            encodingStream.write(loginPacket)

            decodingStream.on('data', (packet) => {
              console.log(packet)
            })
          })
          //wait1 sec
          setTimeout(() => {
            buildWorldPacket(2, session).then((loginPacket) => {
              console.log(loginPacket)


              encodingStream.write(loginPacket)

              decodingStream.on('data', (packet) => {
                console.log(packet)
              })
            })

            buildWorldPacket(3, session).then((loginPacket) => {
              console.log(loginPacket)

              encodingStream.write(loginPacket)

              decodingStream.on('data', (packet) => {
                console.log(packet)
              })
            })
          }, 1000);
        })

        

async function buildWorldPacket(packetNumber, session) {


  if (packetNumber == 1) {
    console.log("return encrypted session")
    return session
  }
  if (packetNumber == 2) {
    console.log("return username")
    return username
  }
  if (packetNumber == 3) {
    console.log("return pwd")
    return password
  }

}

Am I right ?
Because EncryptWorldSession return an object, but a string was expected :/
[Only registered and activated users can see links. Click Here To Register...]

This link gives you normaly all you need for the basic login into login and World server
07/31/2019 19:13 emerickpw#11
I restart this project, i can log into login Server perfectly, i get the NsTeST packet, but impossible to get any server packet.

Code:
async function worldConnect() {
  var host = '79.110.84.xx' // IP
  var port = 40xx //port

  var worldSocket = new net.Socket();
  worldSocket.connect(port, host, () => {
    const encryptWorldStream = nosCrypto.createCipher(session)
    const decryptWorldStream = nosCrypto.createDecipher(session)

    const encodingStream = iconv.encodeStream('win1252'); //encode to Win1252
    const decodingStream = iconv.decodeStream('win1252'); //encode to Win1252

    pipeline(
      encodingStream,
      encryptWorldStream,
      worldSocket,
      decryptWorldStream,
      decodingStream,
      err => {
        if (err) {
          console.error('Pipeline failed.', err);
        } else {
          console.log('Pipeline succeeded.');
        }

        console.log('Game closed because stream pipeline closed.')
      }
    )
    console.log(sessionStr)

    encodingStream.write(sessionStr)

    setTimeout(() => {
      encodingStream.write(username)
      encodingStream.write(password)
    }, 1000);

    decodingStream.on('data', (packet) => {
      console.log(packet)
    })
  })
}
If someone could tell me what i'm doing wrong and how to resolve.. many thanks !!
08/05/2019 18:54 emerickpw#12
up, anyone can help ?
09/04/2021 13:54 pnszlm#13
Another bump, as I got stuck on the same thing :/ (not receiving any response from the world server)

Code:
this.socket = net.connect(this.serverPort, this.serverAdress, () => {
      const encryptStream = nosCrypto.createCipher(+this.sessionId);
      const decryptStream = nosCrypto.createDecipher(+this.sessionId);

      this.encodingStream = iconv.encodeStream("win1252");
      const decodingStream = iconv.decodeStream("win1252");

      pipeline(
        this.encodingStream,
        encryptStream,
        this.socket,
        decryptStream,
        decodingStream,
        (err) => {
          console.log(err);
        }
      );

      decodingStream.on("data", (packet) => {
        console.log(packet);
        this.handlePacket(packet);
      });

      const encryptedSession = nosCrypto.encryptSession(+this.sessionId);

      this.socket.write(encryptedSession);
      setTimeout(() => {
        this.encodingStream.write(this.sessionName + " GF 0");
        this.encodingStream.write("thisisgfmode");
      }, 1289);
    });