jam.utils¶
utils
¶
Various utilities that help with authorization.
Modules:
| Name | Description |
|---|---|
aes |
|
await_maybe |
|
basic_auth |
|
config_maker |
|
ed |
|
otp_keys |
|
rsa |
|
salt_hash |
Utilities for secure password hashing and verification. Uses PBKDF2-HMAC-SHA256 with salt and constant-time comparison. |
symmetric |
|
xchacha20poly1305 |
|
xor |
|
Functions:
| Name | Description |
|---|---|
basic_auth_decode |
Decodes basic auth token to login and password. |
basic_auth_encode |
Encodes the login and password in a basic auth token. |
check_password |
Verifies a password by recalculating the hash and comparing it to the stored hash. |
deserialize_hash |
Splits a stored string into salt and hash. |
generate_aes_key |
Generate a new AES key. |
generate_ecdsa_p384_keypair |
Generate ECDSA P-384 key pair. |
generate_ed25519_keypair |
Generate Ed25519 key. |
generate_otp_key |
Generate generic OTP secret key. |
generate_rsa_key_pair |
RSA key generation utility. |
generate_symmetric_key |
Generate a N-byte symmetric key. |
hash_password |
Hashes a password with a salt using PBKDF2-HMAC-SHA256. |
otp_key_from_string |
Generate OTP-valid key from string. |
serialize_hash |
Combines salt and hash into a single string for database storage. |
xor_my_data |
Encrypts a string using a secret key with the XOR cipher. |
basic_auth_decode
¶
basic_auth_decode(data: str) -> tuple[str, str]
Decodes basic auth token to login and password.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
Decoded data |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If incorrect format |
Example
login, password = basic_auth_decode(header) print(login, password) admin qwerty1234
basic_auth_encode
¶
basic_auth_encode(login: str, password: str) -> str
Encodes the login and password in a basic auth token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
login
|
str
|
Login |
required |
password
|
str
|
Password |
required |
Example
>>> header = basic_auth_encode("admin", "qwerty1234")
>>> print(header)
YWRtaW46cXdlcnR5MTIzNA==
check_password
¶
check_password(
password: str,
salt_hex: str,
hash_hex: str,
iterations: int = 100000,
) -> bool
Verifies a password by recalculating the hash and comparing it to the stored hash.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
password
|
str
|
Password to verify. |
required |
salt_hex
|
str
|
Hex representation of the salt. |
required |
hash_hex
|
str
|
Hex representation of the stored hash. |
required |
iterations
|
int
|
Number of PBKDF2 iterations, must match the hashing call. |
100000
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if the password is correct, False otherwise. |
Example
>>> salt, hash_ = hash_password("my_password")
>>> check_password("my_password", salt, hash_)
True
>>> check_password("wrong_password", salt, hash_)
False
# Using custom iterations
>>> salt, hash_ = hash_password("my_password", iterations=150_000)
>>> check_password("my_password", salt, hash_, iterations=150_000)
True
deserialize_hash
¶
deserialize_hash(data: str) -> tuple[str, str]
Splits a stored string into salt and hash.
Example
>>> salt, hash_ = deserialize_hash("abcdef1234$9876543210")
>>> isinstance(salt, str)
True
>>> isinstance(hash_, str)
True
generate_ecdsa_p384_keypair
¶
generate_ecdsa_p384_keypair() -> dict[str, str]
Generate ECDSA P-384 key pair.
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
dict[str, str]: {'private': KEY, 'public': KEY} |
generate_ed25519_keypair
¶
generate_ed25519_keypair() -> dict[str, str]
Generate Ed25519 key.
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
dict[str, str]: {'private': KEY, 'public': KEY} |
generate_otp_key
¶
generate_otp_key(entropy_bits: int = 128) -> str
Generate generic OTP secret key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entropy_bits
|
int
|
Entropy bits to key |
128
|
Returns:
| Type | Description |
|---|---|
str
|
str |
generate_rsa_key_pair
¶
generate_rsa_key_pair(
key_size: int = 2048,
) -> dict[str, str]
RSA key generation utility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_size
|
int
|
Size of RSA key |
2048
|
Returns:
| Type | Description |
|---|---|
dict
|
with public and private keys in format: |
{
"public": "some_key",
"private": "key"
}
generate_symmetric_key
¶
generate_symmetric_key(n: int = 32) -> str
Generate a N-byte symmetric key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Bytes for key |
32
|
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Key |
hash_password
¶
hash_password(
password: str,
salt: bytes | None = None,
iterations: int = 100000,
salt_size: int = 16,
) -> tuple[str, str]
Hashes a password with a salt using PBKDF2-HMAC-SHA256.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
password
|
str
|
Password to hash. |
required |
salt
|
bytes | None
|
Salt. If None, a random salt is generated. |
None
|
iterations
|
int
|
Number of PBKDF2 iterations. |
100000
|
salt_size
|
int
|
Size of the random salt in bytes. |
16
|
Returns:
| Type | Description |
|---|---|
tuple[str, str]
|
tuple[str, str]: (hex_salt, hex_hash) |
Example
>>> salt, hash_ = hash_password("my_password")
>>> isinstance(salt, str)
True
>>> isinstance(hash_, str)
True
# Using custom iterations and salt size
>>> salt, hash_ = hash_password("my_password", iterations=150_000, salt_size=24)
otp_key_from_string
¶
otp_key_from_string(s: str) -> str
Generate OTP-valid key from string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
str
|
String for key |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bytes |
str
|
OTP key |
Example
>>> from jam.utils import otp_key_from_string
>>> user_email: str = "some.email@mail.com"
>>> key = otp_key_from_string(user_email)
>>> print(key)
'O54O6YRKTH3IPNEBIUMKMK3FZ35OF6Q5'
serialize_hash
¶
serialize_hash(salt_hex: str, hash_hex: str) -> str
Combines salt and hash into a single string for database storage.
Example
>>> salt, hash_ = hash_password("my_password")
>>> serialized = serialize_hash(salt, hash_)
>>> isinstance(serialized, str)
True
xor_my_data
¶
xor_my_data(data: str, key: str) -> str
Encrypts a string using a secret key with the XOR cipher.
This function performs an XOR operation on each byte of the input data with the corresponding byte of the key. If the key is shorter than the data, it wraps around and continues from the beginning of the key. If you need to decrypt data, use the same function with the same secret key. XOR is a symmetric operation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
str
|
The plain text string to be encrypted. |
required |
key
|
str
|
The secret key used for encryption. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The encrypted data represented as a hexadecimal string. |
Example
>>> encrypted = xor_my_data("Hello, World!", "secretkey")
>>> print(encrypted)
<...encrypted hex string...>