pythonhacktoberfeststeamauthenticationauthenticatorsteam-authenticatorsteam-clientsteam-guard-codessteam-websteamworksvalvewebapi
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.7 KiB
146 lines
4.7 KiB
"""
|
|
All function in this module take and return :class:`bytes`
|
|
"""
|
|
import hashlib
|
|
import sys
|
|
from base64 import b64decode
|
|
from os import urandom as random_bytes
|
|
from struct import pack
|
|
|
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.primitives.padding import PKCS7
|
|
from cryptography.hazmat.primitives.asymmetric import rsa, padding
|
|
from cryptography.hazmat.primitives.hmac import HMAC
|
|
from cryptography.hazmat.primitives.serialization import load_der_public_key
|
|
|
|
|
|
class UniverseKey(object):
|
|
"""Public keys for Universes"""
|
|
|
|
Public = load_der_public_key(b64decode("""
|
|
MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDf7BrWLBBmLBc1OhSwfFkRf53T
|
|
2Ct64+AVzRkeRuh7h3SiGEYxqQMUeYKO6UWiSRKpI2hzic9pobFhRr3Bvr/WARvY
|
|
gdTckPv+T1JzZsuVcNfFjrocejN1oWI0Rrtgt4Bo+hOneoo3S57G9F1fOpn5nsQ6
|
|
6WOiu4gZKODnFMBCiQIBEQ==
|
|
"""))
|
|
|
|
BS = 16
|
|
pad = lambda s: s + (BS - len(s) % BS) * pack('B', BS - len(s) % BS)
|
|
|
|
if sys.version_info < (3,):
|
|
unpad = lambda s: s[0:-ord(s[-1])]
|
|
else:
|
|
unpad = lambda s: s[0:-s[-1]]
|
|
|
|
|
|
def generate_session_key(hmac_secret=b''):
|
|
"""
|
|
:param hmac_secret: optional HMAC
|
|
:type hmac_secret: :class:`bytes`
|
|
:return: (session_key, encrypted_session_key) tuple
|
|
:rtype: :class:`tuple`
|
|
"""
|
|
session_key = random_bytes(32)
|
|
encrypted_session_key = UniverseKey.Public.encrypt(
|
|
session_key + hmac_secret,
|
|
padding.OAEP(
|
|
mgf=padding.MGF1(algorithm=hashes.SHA1()),
|
|
algorithm=hashes.SHA256(),
|
|
label=None
|
|
)
|
|
)
|
|
|
|
return (session_key, encrypted_session_key)
|
|
|
|
def symmetric_encrypt(message, key):
|
|
iv = random_bytes(BS)
|
|
return symmetric_encrypt_with_iv(message, key, iv)
|
|
|
|
def symmetric_encrypt_ecb(message, key):
|
|
padder = PKCS7(algorithms.AES.block_size).padder()
|
|
plaintext = padder.update(message)
|
|
plaintext += padder.finalize()
|
|
encryptor = Cipher(algorithms.AES(key), modes.ECB()).encryptor()
|
|
cyphertext = encryptor.update(plaintext)
|
|
cyphertext += encryptor.finalize()
|
|
return cyphertext
|
|
|
|
def symmetric_encrypt_HMAC(message, key, hmac_secret):
|
|
prefix = random_bytes(3)
|
|
hmac = hmac_sha1(hmac_secret, prefix + message)
|
|
iv = hmac[:13] + prefix
|
|
return symmetric_encrypt_with_iv(message, key, iv)
|
|
|
|
def symmetric_encrypt_iv(iv, key):
|
|
encryptor = Cipher(algorithms.AES(key), modes.ECB()).encryptor()
|
|
cyphertext = encryptor.update(iv)
|
|
cyphertext += encryptor.finalize()
|
|
return cyphertext
|
|
|
|
def symmetric_encrypt_with_iv(message, key, iv):
|
|
encrypted_iv = symmetric_encrypt_iv(iv, key)
|
|
padder = PKCS7(algorithms.AES.block_size).padder()
|
|
plaintext = padder.update(message)
|
|
plaintext += padder.finalize()
|
|
encryptor = Cipher(algorithms.AES(key), modes.CBC(iv)).encryptor()
|
|
cyphertext = encryptor.update(plaintext)
|
|
cyphertext += encryptor.finalize()
|
|
return encrypted_iv + cyphertext
|
|
|
|
def symmetric_decrypt(cyphertext, key):
|
|
iv = symmetric_decrypt_iv(cyphertext, key)
|
|
return symmetric_decrypt_with_iv(cyphertext, key, iv)
|
|
|
|
def symmetric_decrypt_ecb(cyphertext, key):
|
|
decryptor = Cipher(algorithms.AES(key), modes.ECB()).decryptor()
|
|
plaintext = decryptor.update(cyphertext)
|
|
plaintext += decryptor.finalize()
|
|
unpadder = PKCS7(algorithms.AES.block_size).unpadder()
|
|
message = unpadder.update(plaintext)
|
|
message += unpadder.finalize()
|
|
return message
|
|
|
|
def symmetric_decrypt_HMAC(cyphertext, key, hmac_secret):
|
|
""":raises: :class:`RuntimeError` when HMAC verification fails"""
|
|
iv = symmetric_decrypt_iv(cyphertext, key)
|
|
message = symmetric_decrypt_with_iv(cyphertext, key, iv)
|
|
|
|
hmac = hmac_sha1(hmac_secret, iv[-3:] + message)
|
|
|
|
if iv[:13] != hmac[:13]:
|
|
raise RuntimeError("Unable to decrypt message. HMAC does not match.")
|
|
|
|
return message
|
|
|
|
def symmetric_decrypt_iv(cyphertext, key):
|
|
decryptor = Cipher(algorithms.AES(key), modes.ECB()).decryptor()
|
|
iv = decryptor.update(cyphertext[:BS])
|
|
iv += decryptor.finalize()
|
|
return iv
|
|
|
|
def symmetric_decrypt_with_iv(cyphertext, key, iv):
|
|
decryptor = Cipher(algorithms.AES(key), modes.CBC(iv)).decryptor()
|
|
plaintext = decryptor.update(cyphertext[BS:])
|
|
plaintext += decryptor.finalize()
|
|
unpadder = PKCS7(algorithms.AES.block_size).unpadder()
|
|
message = unpadder.update(plaintext)
|
|
message += unpadder.finalize()
|
|
return message
|
|
|
|
def hmac_sha1(secret, data):
|
|
h = HMAC(secret, hashes.SHA1())
|
|
h.update(data)
|
|
return h.finalize()
|
|
|
|
def sha1_hash(data):
|
|
return hashlib.sha1(data).digest()
|
|
|
|
def rsa_publickey(mod, exp):
|
|
return rsa.RSAPublicNumbers(e=exp, n=mod).public_key()
|
|
|
|
def pkcs1v15_encrypt(key, message):
|
|
key.encrypt(
|
|
message,
|
|
padding.PKCS1v15,
|
|
)
|
|
|