Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ Key features
* `WebAuth <http://steam.readthedocs.io/en/latest/api/steam.webauth.html>`_ - authentication for access to ``store.steampowered.com`` and ``steamcommunity.com``

Checkout the `User guide <http://steam.readthedocs.io/en/latest/user_guide.html>`_ for examples,
or the `API Reference <http://steam.readthedocs.io/en/latest/api/index.html>`_ for details.
or the `API Reference <http://steam.readthedocs.io/en/latest/api/steam.html>`_ for details.

For questions, issues or general curiosity visit the repo at `https://github.com/ValvePython/steam <https://github.com/ValvePython/steam>`_.

Quick install
-------------

For details on require system packages, see `Full Installation <http://steam.readthedocs.io/en/latest/install.html>`_.
For system specific details, see `Install Details <http://steam.readthedocs.io/en/latest/install.html>`_.

Install latest version from PYPI

Expand Down
3 changes: 2 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ Vagrant.configure("2") do |config|
# box.vm.synced_folder "../csgo-python/csgo/", "/home/vagrant/csgo"

box.vm.provision "shell", inline: <<-SHELL
set -x
apt-get update
apt-get -y install build-essential libssl-dev libffi-dev python-dev
apt-get -y install python-pip python-virtualenv
SHELL

box.vm.provision "shell", privileged: false, inline: <<-SHELL
set -x
virtualenv -p python2 venv2
source venv2/bin/activate
pip install -r /vagrant/requirements.txt ipython
Expand Down
23 changes: 0 additions & 23 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,6 @@ Steps assume that ``python`` and ``pip`` are already installed.
in order to keep you system packages untouched.


Ubuntu/Debian
^^^^^^^^^^^^^

Replace ``python-dev`` with ``python3-dev`` for Python 3.

.. code-block:: console

$ sudo apt-get install build-essential libssl-dev libffi-dev python-dev

RHEL-based
^^^^^^^^^^

.. code-block:: console

$ sudo yum install gcc libffi-devel python-devel openssl-devel


Windows
-------

Expand All @@ -41,13 +24,7 @@ Cygwin

2. During the setup select these additional packages
- ``python3``
- ``python3-devel``
- ``python3-setuptools``
- ``gcc-core``
- ``gcc-g++``
- ``libffi6``
- ``libffi-devel``
- ``openssl-devel``

4. Install pip
- Open cygwin terminal
Expand Down
4 changes: 2 additions & 2 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Key features
* :doc:`WebAPI <api/steam.webapi>` - simple API for Steam's Web API with automatic population of interfaces
* :doc:`WebAuth <api/steam.webauth>` - authentication for access to ``store.steampowered.com`` and ``steamcommunity.com``

Checkout the :doc:`user_guide` for examples, or the :doc:`api/index` for details.
Checkout the :doc:`user_guide` for examples, or the :doc:`api/steam` for details.

For questions, issues, or general curiosity, visit the repo at `https://github.com/ValvePython/steam <https://github.com/ValvePython/steam>`_.

Quick install
=============

For details on require system packages, see :doc:`install`.
For system specific details, see :doc:`install`.

Install latest version from PYPI::

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
six>=1.10.0
cryptography>=1.3
pycryptodomex>=3.7.0
requests>=2.9.1
vdf>=2.0
gevent>=1.2.0
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

install_requires = [
'six>=1.10',
'cryptography>=1.3',
'pycryptodomex>=3.7.0',
'requests>=2.9.1',
'vdf>=2.0',
'gevent>=1.2.0',
Expand Down Expand Up @@ -50,6 +50,7 @@
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: PyPy',
],
keywords='valve steam steamid api webapi steamcommunity',
packages=['steam'] + ['steam.'+x for x in find_packages(where='steam')],
Expand Down
47 changes: 21 additions & 26 deletions steam/core/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@
from os import urandom as random_bytes
from struct import pack
from base64 import b64decode
from cryptography.hazmat.primitives.hmac import HMAC
from cryptography.hazmat.primitives.hashes import Hash, SHA1
from cryptography.hazmat.primitives.asymmetric.padding import PSS, OAEP, MGF1
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB
import cryptography.hazmat.backends
backend = cryptography.hazmat.backends.default_backend()

from Cryptodome.Hash import SHA1, HMAC
from Cryptodome.PublicKey.RSA import import_key as rsa_import_key, construct as rsa_construct
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5
from Cryptodome.Cipher import AES as AES


class UniverseKey(object):
"""Public keys for Universes"""

Public = backend.load_der_public_key(b64decode("""
Public = rsa_import_key(b64decode("""
MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDf7BrWLBBmLBc1OhSwfFkRf53T
2Ct64+AVzRkeRuh7h3SiGEYxqQMUeYKO6UWiSRKpI2hzic9pobFhRr3Bvr/WARvY
gdTckPv+T1JzZsuVcNfFjrocejN1oWI0Rrtgt4Bo+hOneoo3S57G9F1fOpn5nsQ6
Expand All @@ -42,9 +39,9 @@ def generate_session_key(hmac_secret=b''):
:rtype: :class:`tuple`
"""
session_key = random_bytes(32)
encrypted_session_key = UniverseKey.Public.encrypt(session_key + hmac_secret,
OAEP(MGF1(SHA1()), SHA1(), None)
)
encrypted_session_key = PKCS1_OAEP.new(UniverseKey.Public, SHA1)\
.encrypt(session_key + hmac_secret)

return (session_key, encrypted_session_key)

def symmetric_encrypt(message, key):
Expand All @@ -58,13 +55,11 @@ def symmetric_encrypt_HMAC(message, key, hmac_secret):
return symmetric_encrypt_with_iv(message, key, iv)

def symmetric_encrypt_iv(iv, key):
encryptor = Cipher(AES(key), ECB(), backend).encryptor()
return encryptor.update(iv) + encryptor.finalize()
return AES.new(key, AES.MODE_ECB).encrypt(iv)

def symmetric_encrypt_with_iv(message, key, iv):
encrypted_iv = symmetric_encrypt_iv(iv, key)
encryptor = Cipher(AES(key), CBC(iv), backend).encryptor()
cyphertext = encryptor.update(pad(message)) + encryptor.finalize()
cyphertext = AES.new(key, AES.MODE_CBC, iv).encrypt(pad(message))
return encrypted_iv + cyphertext

def symmetric_decrypt(cyphertext, key):
Expand All @@ -84,19 +79,19 @@ def symmetric_decrypt_HMAC(cyphertext, key, hmac_secret):
return message

def symmetric_decrypt_iv(cyphertext, key):
decryptor = Cipher(AES(key), ECB(), backend).decryptor()
return decryptor.update(cyphertext[:BS]) + decryptor.finalize()
return AES.new(key, AES.MODE_ECB).decrypt(cyphertext[:BS])

def symmetric_decrypt_with_iv(cyphertext, key, iv):
decryptor = Cipher(AES(key), CBC(iv), backend).decryptor()
return unpad(decryptor.update(cyphertext[BS:]) + decryptor.finalize())
return unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(cyphertext[BS:]))

def hmac_sha1(secret, data):
hmac = HMAC(secret, SHA1(), backend)
hmac.update(data)
return hmac.finalize()
return HMAC.new(secret, data, SHA1).digest()

def sha1_hash(data):
sha = Hash(SHA1(), backend)
sha.update(data)
return sha.finalize()
return SHA1.new(data).digest()

def rsa_publickey(mod, exp):
return rsa_construct((mod, exp))

def pkcs1v15_encrypt(key, message):
return PKCS1_v1_5.new(key).encrypt(message)
29 changes: 12 additions & 17 deletions steam/webauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,9 @@
from base64 import b64encode
import requests

from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from steam.core.crypto import backend

from steam import SteamID, webapi
from steam.util.web import make_requests_session, generate_session_id
from steam.core.crypto import rsa_publickey, pkcs1v15_encrypt

if sys.version_info < (3,):
intBase = long
Expand Down Expand Up @@ -108,12 +105,12 @@ def get_rsa_key(self, username):
"""
try:
resp = self.session.post('https://steamcommunity.com/login/getrsakey/',
timeout=15,
data={
'username': username,
'donotchache': int(time() * 1000),
},
).json()
timeout=15,
data={
'username': username,
'donotchache': int(time() * 1000),
},
).json()
except requests.exceptions.RequestException as e:
raise HTTPError(str(e))

Expand All @@ -123,17 +120,15 @@ def _load_key(self):
if not self.key:
resp = self.get_rsa_key(self.username)

nums = RSAPublicNumbers(intBase(resp['publickey_exp'], 16),
intBase(resp['publickey_mod'], 16),
)

self.key = backend.load_rsa_public_numbers(nums)
self.key = rsa_publickey(intBase(resp['publickey_mod'], 16),
intBase(resp['publickey_exp'], 16),
)
self.timestamp = resp['timestamp']

def _send_login(self, captcha='', email_code='', twofactor_code=''):
data = {
'username' : self.username,
"password": b64encode(self.key.encrypt(self.password.encode('ascii'), PKCS1v15())),
'username': self.username,
"password": b64encode(pkcs1v15_encrypt(self.key, self.password.encode('ascii'))),
"emailauth": email_code,
"emailsteamid": str(self.steam_id) if email_code else '',
"twofactorcode": twofactor_code,
Expand Down
10 changes: 6 additions & 4 deletions tests/test_core_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,20 @@ def setUp(self):
# self.assertEqual(key, expected_key)
# self.assertEqual(ekey, expected_ekey)

def test_encryption(self):
def test_encryption_legacy(self):
message = b'My secret message'
key = b'9' * 32
hmac = b'3' * 16

# legacy
cyphertext = crypto.symmetric_encrypt(message, key)
dmessage = crypto.symmetric_decrypt(cyphertext, key)

self.assertEqual(message, dmessage)

# with HMAC
def test_encryption_hmac(self):
message = b'My secret message'
key = b'9' * 32
hmac = b'3' * 16

cyphertext = crypto.symmetric_encrypt_HMAC(message, key, hmac)
dmessage = crypto.symmetric_decrypt_HMAC(cyphertext, key, hmac)

Expand Down