3

I've been trying to make simple Steam bot for sending announcements to Steam group by logging in to Steam page and then sending annoucement. I got stuck in logging in. Here is what I have:

include('Math/BigInteger.php');    
include('Crypt/RSA.php');
$url = 'http://store.steampowered.com/login/getrsakey/';    // here I get public key
$data = array('username' => 'user');         // I'm sending username by POST method

$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ),
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$result = json_decode($result)

// And this is part that don't work:

$rsa = new Crypt_RSA();
$key = array(
    'n' => new Math_BigInteger($result->publickey_mod,16),
    'e' => new Math_BigInteger($result->publickey_exp,2)
);
$rsa->loadKey($key);
$password = $rsa->encrypt("password");    // encrypting password
$data = array(
    'username' => 'user',
    'password' => $password,
    'twofactorcode'=> "",
    'emailauth'=> "", 
    'loginfriendlyname'=> "", 
    'captchagid'=> "", 
    'captcha_text'=> "", 
    'emailsteamid'=> "", 
    'rsatimestamp'=> $result->timestamp, 
    'remember_login'=> "false" 
);
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ),
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);

And result is:

{"success":false}

Problem is that encrypted password does not look same as when I encrypted it with javascript functions which are used by Steam. So I tried encrypting password in javascript and then just paste it in PHP code but that didn't work either.

Any help would be appreciated.

neubert
  • 15,947
  • 24
  • 120
  • 212
typekcz
  • 113
  • 2
  • 6
  • Not a solution, but a suggestion of using a headless browser like PhantomJS through Selenium. – Artjom B. Nov 23 '14 at 15:05
  • `'e' => new Math_BigInteger($result->publickey_exp,2)` looks wrong. Are you sure about using base 2? The typical e value of 0x10001 might look like binary but it's base 16. – President James K. Polk Nov 23 '14 at 15:41
  • GregS: It is posible, because I just guessed bases :) But still I got: EŮńڬĂV¶¤¦‹ÚŢč�•‹iPץ÷"gÖ... and JS gives me iYb62dYHnhqpbBBQL5jDxZy... – typekcz Nov 23 '14 at 16:31
  • Artjom B.: Thank you for your suggestion. I'm just playing with PhantomJS and I'm already logged in! And it runs fine on OpenShift as well, which I'm using for hosting. – typekcz Nov 23 '14 at 16:36
  • 1
    The encrypted password will be different every time because of random padding. – President James K. Polk Nov 23 '14 at 16:59
  • You say JS gives you iYb62dYHnhq... What JS library are you using that is giving you that? It looks base64 encoded. Maybe Steam is expecting base64 encoded stuff? Also, by default, phpseclib uses OAEP padding. PKCS1 padding is more common. You can enable that by doing `$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1)`. You might also need to do `define('CRYPT_RSA_PKCS15_COMPAT', true)` as phpseclib implements PKCS 2.1 whereas OpenSSL (and programs that use it) do PKCS 1.5. – neubert Nov 24 '14 at 16:21
  • Does anyone know if the code below or above is functional in 2018? I ran the script below and it returns `success: false`. – PatPeter Jun 13 '18 at 01:50
  • @PatPeter Sorry, totally forgot about this question. [Here](https://gist.github.com/typekcz/833c952ce28bfee98f7374ed6ff76a3d) I have working code that I am currently using for sending group notifications. I wanted to prettify it and publish it on github as library with more features, but never had time to do so. – typekcz Jun 14 '18 at 07:46
  • Thank you so much @typekcz!!! This code is amazing. I'm actually working on creating the library that you speak of with my Git repository [SteamGroupAPI](https://github.com/PatPeter/SteamGroupAPI). Do you mind if I incorporate your code into it? What license do you want to use? – PatPeter Jun 18 '18 at 02:31
  • The license that I'm used to is [GPL-3.0](https://opensource.org/licenses/GPL-3.0). – PatPeter Jun 18 '18 at 02:39
  • I would be glad if you implement it in your library. I usualy don't care about license and use MIT, but GPL is great for this kind of project. – typekcz Jun 19 '18 at 07:03

1 Answers1

2

Originally, I came here to find answers to my own questions, but I was disappointed to see that NO ONE has officially provided an answer to this. So, after using the information here to point myself in the right direction, I've chipped away at this for about an hour now and finally got it working for myself.

In order for this to work, all you have to do is download the .zip file here: https://github.com/phpseclib/phpseclib. Extract it to your server/ application directory, and use the following code below.

<?php
include('Math/BigInteger.php');    
include('Crypt/RSA.php');
define('CRYPT_RSA_PKCS15_COMPAT', true);  // May not be necessary, but never hurts to be sure.

$url_rsa = 'https://steamcommunity.com/login/getrsakey/?username=';
$username = "";  // Insert bot's username here.
$password = "";  // Insert bot's password here.


// Skip the extra work of POST'ing the data, just GET'ing the url works fine and saves space
$result = file_get_contents($url_rsa . $username);
$result = json_decode($result);

/*if ($result->success){
    echo "Got Info!<br/><br/>";
} else if (!$result->success){            // Remove comment markers during testing
    echo "Unable to grab Info<br/><br/>"; // You can also use this to log errors to a database or email you if needed.
}*/

//echo var_dump($result);
// More testing code, just to help you see what's going on.
//echo "<br/><br/>";

$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$key = array(
    'n' => new Math_BigInteger($result->publickey_mod,16),
    'e' => new Math_BigInteger($result->publickey_exp,16) // Fixed base :)
);
$rsa->loadKey($key);
$password = base64_encode($rsa->encrypt($password)); // Steam uses Base64_Encode()

//echo "Password Encrypted: " . $password . "<br/><br/>";
// Should look like numbers and letters, any 'weird' characters shouldn't be here

$data = array(
    'username' => $username,
    'password' => $password,
    'twofactorcode'=> "",
    'emailauth'=> "", 
    'loginfriendlyname'=> "", 
    'captchagid'=> "",         // If all goes well, you shouldn't need to worry
    'captcha_text'=> "",       // about Captcha.
    'emailsteamid'=> "", 
    'rsatimestamp'=> $result->timestamp, 
    'remember_login'=> "false" 
);
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ),
);

$url="https://steamcommunity.com/login/dologin/";

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$result = json_decode($result);

//echo var_dump($result);
// Hopefully everything went O.K. and you should be able pull out tokens
// for usage in your application.
?>

Results should be similar to this:

{
    "success":true,
    "requires_twofactor":false,
    "login_complete":true,
    "transfer_urls":["https:\/\/store.steampowered.com\/login\/transfer","https:\/\/help.steampowered.com\/login\/transfer"],
    "transfer_parameters":{
        "steamid":"XXXXXXXXXXXXXXXXX",
        "token":"Combination of Letters and Numbers",
        "auth":"Looks like a Hash Here",
        "remember_login":false,
        "token_secure":"More Letters and Numbers"
    }
}

When creating a bot, especially one that might be entrusted with holding people's valuable items (as most bots would), it's a good idea to use a very secure password.

A good format to follow would be a password around 20 characters long, containing numbers, letters, and some symbols. A good site that generates passwords CLIENT-SIDE is http://passwordsgenerator.net. Follow the recommendations listed on the website to keep your accounts secure.

Mick Ashton
  • 356
  • 4
  • 15
  • It should also be noted that you CAN NOT use this method to log in OTHER users to websites. That violates Steam TOS and can get you in big trouble. Go here to login other users: http://stackoverflow.com/questions/18674042/steam-api-authentication – Mick Ashton Mar 12 '16 at 02:56
  • Hello Mick. I'm trying to get this code working for a project of my own that aims to archive "View Group History" from Steam. I just tried running this code but it's returning `success: false` and `The account name or password that you have entered is incorrect.` I know the account name and password are correct. Is this code still working to your knowledge? – PatPeter Jun 13 '18 at 00:28
  • [Here](https://gist.github.com/typekcz/833c952ce28bfee98f7374ed6ff76a3d) is currently working version. – typekcz Jun 14 '18 at 07:47