ghostbytes 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ghostbytes/__init__.py +3 -0
- ghostbytes/__main__.py +9 -0
- ghostbytes/crypto/config.py +155 -0
- ghostbytes/crypto/crypto.py +162 -0
- ghostbytes/crypto/crypto.pyi +149 -0
- ghostbytes/crypto/kyber.py +257 -0
- ghostbytes/crypto/oaep_extension.py +125 -0
- ghostbytes/crypto/primitives.py +360 -0
- ghostbytes/error.py +177 -0
- ghostbytes/gui/gui.py +2809 -0
- ghostbytes/gui/theme.py +95 -0
- ghostbytes/gui/wrappers.py +566 -0
- ghostbytes/img/icon.ico +0 -0
- ghostbytes/img/icon.png +0 -0
- ghostbytes/tools/benchmark.py +218 -0
- ghostbytes/tools/rand.py +118 -0
- ghostbytes/tools/shred.py +384 -0
- ghostbytes/tools/tools.pyi +67 -0
- ghostbytes-1.0.0.dist-info/METADATA +182 -0
- ghostbytes-1.0.0.dist-info/RECORD +22 -0
- ghostbytes-1.0.0.dist-info/WHEEL +4 -0
- ghostbytes-1.0.0.dist-info/entry_points.txt +3 -0
ghostbytes/__init__.py
ADDED
ghostbytes/__main__.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
config.py
|
|
3
|
+
|
|
4
|
+
Defines encryption configuration used by Ghostbytes:
|
|
5
|
+
which cipher, hash function, KDF parameters, and random source to use,
|
|
6
|
+
plus helper functions (import, export, and generate configuration)
|
|
7
|
+
to save / load configurations to / from a config file.
|
|
8
|
+
|
|
9
|
+
See docs/confguration.md
|
|
10
|
+
"""
|
|
11
|
+
import base64
|
|
12
|
+
import configparser
|
|
13
|
+
from hashlib import md5
|
|
14
|
+
from Crypto.Hash import SHA3_512, SHA3_256, SHA512, SHA256, BLAKE2b, BLAKE2s
|
|
15
|
+
from ghostbytes.error import invalid_configuration
|
|
16
|
+
|
|
17
|
+
AVAIL_HASH = [SHA3_512, SHA3_256, SHA512, SHA256, BLAKE2b, BLAKE2s, md5]
|
|
18
|
+
AVAIL_HASH_STR = [
|
|
19
|
+
"sha3_512",
|
|
20
|
+
"sha3_256",
|
|
21
|
+
"sha512",
|
|
22
|
+
"sha256",
|
|
23
|
+
"blake2b",
|
|
24
|
+
"blake2s",
|
|
25
|
+
"md5"]
|
|
26
|
+
AVAIL_ALG = ["aes", "rsa-oaep", "extended_oaep", "ML-KEM-768", "ML-KEM-1024"]
|
|
27
|
+
AVAIL_RANDOM_STR = [
|
|
28
|
+
"os.urandom",
|
|
29
|
+
"cryptodome_random",
|
|
30
|
+
"random lib (python)",
|
|
31
|
+
"secrets_random",
|
|
32
|
+
"/dev/urandom (*nux only)",
|
|
33
|
+
"/dev/random (*nux only)",
|
|
34
|
+
"/dev/urandom (dd, out file only) (*nux only)",
|
|
35
|
+
"/dev/random (dd, out file only) (*nux only)",
|
|
36
|
+
]
|
|
37
|
+
ENCRYPTED_SUFFIX = ".enc"
|
|
38
|
+
RSA_KEY_OUT_FORMAT = ["PEM", "DER", "OpenSSH"]
|
|
39
|
+
COMMON_RSA_SIZE = [2048, 4096, 8192]
|
|
40
|
+
RSA_SIZE_WARNING_THRESHOLD = 4096
|
|
41
|
+
|
|
42
|
+
OVERWRITE_OPTIONS = [
|
|
43
|
+
'random',
|
|
44
|
+
'zero',
|
|
45
|
+
'one',
|
|
46
|
+
'gutmann'
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
RANDOM_SALT_SIZE = 64
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class CryptoConfig:
|
|
53
|
+
"""
|
|
54
|
+
Holds cryptographic parameters used to encrypt / decrypt a file.
|
|
55
|
+
|
|
56
|
+
An instance can be created via `CryptoConfig()`, randomised via
|
|
57
|
+
`CryptoConfig.generate_random_salt()`, or restored from disk via
|
|
58
|
+
`CryptoConfig.import_file(path)`. Use `export_file(path)` to persist it.
|
|
59
|
+
|
|
60
|
+
Fields such as `algorithm`, `store_iv`, `mac_len`, and all kdf parameters must
|
|
61
|
+
remain the identical between encryptor and decryptor to allow ciphertext
|
|
62
|
+
to be successfully decrypted.
|
|
63
|
+
|
|
64
|
+
It is also recommended to use a DIFFERERNT SALT per encryption pair to prevent
|
|
65
|
+
rainbow table attacks. Use `export_file` and `import_file` to ensure the
|
|
66
|
+
cryptographic configurations are the same.
|
|
67
|
+
"""
|
|
68
|
+
algorithm = AVAIL_ALG[0]
|
|
69
|
+
|
|
70
|
+
store_iv = "append" # or "prepend"
|
|
71
|
+
mac_len = 16
|
|
72
|
+
kdf_salt = b"CHANGE_ME_F1L3_3NCRYP710N_53CR37_54L7_70_3N5UR3_R4ND0MN355"
|
|
73
|
+
kdf_time_cost = 16
|
|
74
|
+
kdf_memory_cost = 128 * 1024 # 128 MB, times 1024 to get KB
|
|
75
|
+
kdf_parallelism = 8
|
|
76
|
+
|
|
77
|
+
hash_func = AVAIL_HASH[0]
|
|
78
|
+
rand_func = AVAIL_RANDOM_STR[0]
|
|
79
|
+
|
|
80
|
+
def generate_random_salt(self, length=64):
|
|
81
|
+
"""Generate and store a new KDF salt using this config's random source."""
|
|
82
|
+
|
|
83
|
+
# Imports random within the function prevents cross-import error
|
|
84
|
+
from ghostbytes.tools.rand import random
|
|
85
|
+
|
|
86
|
+
self.kdf_salt = random(self.rand_func, length)
|
|
87
|
+
return self.kdf_salt
|
|
88
|
+
|
|
89
|
+
def export_file(self, path):
|
|
90
|
+
"""Exports the current `CryptoConfig` state to a `.conf` file"""
|
|
91
|
+
parser = configparser.ConfigParser()
|
|
92
|
+
parser["CryptoConfig"] = {
|
|
93
|
+
"algorithm": self.algorithm,
|
|
94
|
+
"store_iv": self.store_iv,
|
|
95
|
+
"mac_len": str(self.mac_len),
|
|
96
|
+
"kdf_salt": base64.b64encode(self.kdf_salt).decode("ascii"),
|
|
97
|
+
"kdf_time_cost": str(self.kdf_time_cost),
|
|
98
|
+
"kdf_memory_cost": str(self.kdf_memory_cost),
|
|
99
|
+
"kdf_parallelism": str(self.kdf_parallelism),
|
|
100
|
+
"hash_func": AVAIL_HASH_STR[AVAIL_HASH.index(self.hash_func)],
|
|
101
|
+
"rand_func": self.rand_func,
|
|
102
|
+
}
|
|
103
|
+
with open(path, "w", encoding="utf-8") as file:
|
|
104
|
+
parser.write(file)
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def import_file(cls, path):
|
|
108
|
+
"""Imports the previous `CryptoConfig` state through a `.conf` file"""
|
|
109
|
+
parser = configparser.ConfigParser()
|
|
110
|
+
try:
|
|
111
|
+
if not parser.read(
|
|
112
|
+
path,
|
|
113
|
+
encoding="utf-8") or "CryptoConfig" not in parser:
|
|
114
|
+
raise invalid_configuration("missing CryptoConfig section")
|
|
115
|
+
except (OSError, UnicodeDecodeError, configparser.Error) as exc:
|
|
116
|
+
raise invalid_configuration("file could not be read") from exc
|
|
117
|
+
|
|
118
|
+
values = parser["CryptoConfig"]
|
|
119
|
+
try:
|
|
120
|
+
algorithm = values["algorithm"]
|
|
121
|
+
store_iv = values["store_iv"]
|
|
122
|
+
mac_len = values.getint("mac_len")
|
|
123
|
+
kdf_salt = base64.b64decode(values["kdf_salt"], validate=True)
|
|
124
|
+
kdf_time_cost = values.getint("kdf_time_cost")
|
|
125
|
+
kdf_memory_cost = values.getint("kdf_memory_cost")
|
|
126
|
+
kdf_parallelism = values.getint("kdf_parallelism")
|
|
127
|
+
hash_name = values["hash_func"]
|
|
128
|
+
rand_func = values["rand_func"]
|
|
129
|
+
except (KeyError, ValueError) as e:
|
|
130
|
+
raise invalid_configuration(
|
|
131
|
+
"one or more values are malformed") from e
|
|
132
|
+
|
|
133
|
+
if algorithm not in AVAIL_ALG:
|
|
134
|
+
raise invalid_configuration("unsupported algorithm")
|
|
135
|
+
if store_iv not in ("append", "prepend"):
|
|
136
|
+
raise invalid_configuration("invalid IV storage mode")
|
|
137
|
+
if not 4 <= mac_len <= 16:
|
|
138
|
+
raise invalid_configuration(
|
|
139
|
+
"MAC length must be between 4 and 16 bytes")
|
|
140
|
+
if not kdf_salt or kdf_time_cost < 1 or kdf_memory_cost < 1 or kdf_parallelism < 1:
|
|
141
|
+
raise invalid_configuration("invalid KDF settings")
|
|
142
|
+
if hash_name not in AVAIL_HASH_STR or rand_func not in AVAIL_RANDOM_STR:
|
|
143
|
+
raise invalid_configuration("unsupported hash or random function")
|
|
144
|
+
|
|
145
|
+
config = cls()
|
|
146
|
+
config.algorithm = algorithm
|
|
147
|
+
config.store_iv = store_iv
|
|
148
|
+
config.mac_len = mac_len
|
|
149
|
+
config.kdf_salt = kdf_salt
|
|
150
|
+
config.kdf_time_cost = kdf_time_cost
|
|
151
|
+
config.kdf_memory_cost = kdf_memory_cost
|
|
152
|
+
config.kdf_parallelism = kdf_parallelism
|
|
153
|
+
config.hash_func = AVAIL_HASH[AVAIL_HASH_STR.index(hash_name)]
|
|
154
|
+
config.rand_func = rand_func
|
|
155
|
+
return config
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""
|
|
2
|
+
crypto.py
|
|
3
|
+
|
|
4
|
+
This is the main module provides a unified interface for encryption and decryption
|
|
5
|
+
using symmetric, asymmetric, and post-quantum cryptographic algorithms.
|
|
6
|
+
|
|
7
|
+
Supported algorithms are defined in `./config.py`
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
from Crypto.PublicKey import RSA as _rsa
|
|
13
|
+
from ghostbytes.crypto.kyber import kyber_decrypt, kyber_encrypt
|
|
14
|
+
from ghostbytes.crypto.oaep_extension import oaep_extended_decrypt, oaep_extended_encrypt
|
|
15
|
+
from ghostbytes.crypto.config import CryptoConfig
|
|
16
|
+
from ghostbytes.error import algorithm_not_supported, parameter_not_exist, \
|
|
17
|
+
keyfile_cannot_crypt, keyfile_passphrase_incorrect, invalid_keyfile, \
|
|
18
|
+
invalid_configuration_type
|
|
19
|
+
from ghostbytes.crypto.primitives import derive_key, \
|
|
20
|
+
aes_decrypt, aes_encrypt, rsa_oaep_decrypt, rsa_oaep_encrypt
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def encrypt(
|
|
24
|
+
config,
|
|
25
|
+
key,
|
|
26
|
+
plaintext,
|
|
27
|
+
rsa_passphrase=None
|
|
28
|
+
):
|
|
29
|
+
"""
|
|
30
|
+
Encrypts plaintext using the specified algorithm in `CryptoConfig`
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
config: Cryptographic configuration for the operation, includes the algorithm,
|
|
34
|
+
KDF parameters, and all necessary configuration to complete the operation.
|
|
35
|
+
key: Encryption key or key material. The expected format depends on the algorithm.
|
|
36
|
+
For symmetric encryption, key is typically a password or other secret key material.
|
|
37
|
+
plaintext: ata to encrypt. Must be provided as bytes.
|
|
38
|
+
rsa_passphrase: Optional passphrase used to decrypt a password-protected RSA keyfile
|
|
39
|
+
Must be provided as bytes.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
bytes: The encrypted ciphertext
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
TypeError: If config args is not an instance of CryptoConfig.
|
|
46
|
+
CryptoError: Cryptographic errors likely raised due to invalid keys, malformed
|
|
47
|
+
ciphertext, invalid cryptographic parameters, or failures during
|
|
48
|
+
the underlying encryption/decryption operation.
|
|
49
|
+
GeneralError: Incorrect Usage of the function that are not cryptography-related.
|
|
50
|
+
"""
|
|
51
|
+
_must_be_valid("config", config)
|
|
52
|
+
_must_be_valid("key", key)
|
|
53
|
+
_must_be_valid("plaintext", plaintext)
|
|
54
|
+
|
|
55
|
+
if not isinstance(config, CryptoConfig):
|
|
56
|
+
raise invalid_configuration_type()
|
|
57
|
+
|
|
58
|
+
algorithm = config.algorithm
|
|
59
|
+
if algorithm == "aes":
|
|
60
|
+
raw_key = derive_key(config, key)
|
|
61
|
+
return aes_encrypt(config, raw_key, plaintext)
|
|
62
|
+
|
|
63
|
+
if algorithm == "extended_oaep":
|
|
64
|
+
try:
|
|
65
|
+
rsa_key = _rsa.import_key(key, rsa_passphrase)
|
|
66
|
+
except (ValueError, TypeError, IndexError) as e:
|
|
67
|
+
if rsa_passphrase is not None:
|
|
68
|
+
raise keyfile_passphrase_incorrect() from e
|
|
69
|
+
raise invalid_keyfile() from e
|
|
70
|
+
if not rsa_key.can_encrypt():
|
|
71
|
+
raise keyfile_cannot_crypt("encrypt")
|
|
72
|
+
|
|
73
|
+
return oaep_extended_encrypt(config, rsa_key, plaintext)
|
|
74
|
+
|
|
75
|
+
if algorithm == "rsa-oaep":
|
|
76
|
+
try:
|
|
77
|
+
rsa_key = _rsa.import_key(key, rsa_passphrase)
|
|
78
|
+
except (ValueError, TypeError, IndexError) as e:
|
|
79
|
+
if rsa_passphrase is not None:
|
|
80
|
+
raise keyfile_passphrase_incorrect() from e
|
|
81
|
+
raise invalid_keyfile() from e
|
|
82
|
+
if not rsa_key.can_encrypt():
|
|
83
|
+
raise keyfile_cannot_crypt("encrypt")
|
|
84
|
+
|
|
85
|
+
return rsa_oaep_encrypt(config, rsa_key, plaintext)
|
|
86
|
+
if re.search(r"^ML-KEM-(768|1024)$", algorithm):
|
|
87
|
+
return kyber_encrypt(config, key, plaintext, rsa_passphrase)
|
|
88
|
+
raise algorithm_not_supported()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def decrypt(
|
|
92
|
+
config,
|
|
93
|
+
key,
|
|
94
|
+
ciphertext,
|
|
95
|
+
rsa_passphrase=None
|
|
96
|
+
):
|
|
97
|
+
"""
|
|
98
|
+
Decrypts ciphertext using the specified algorithm in `CryptoConfig`
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
config: Cryptographic configuration for the operation, includes the algorithm,
|
|
102
|
+
KDF parameters, and all necessary configuration to complete the operation.
|
|
103
|
+
key: Encryption key or key material. The expected format depends on the algorithm.
|
|
104
|
+
For symmetric encryption, key is typically a password or other secret key material.
|
|
105
|
+
ciphertext: Encrypted data to decrypt. Must be provided as bytes.
|
|
106
|
+
rsa_passphrase: Optional passphrase used to decrypt a password-protected RSA keyfile
|
|
107
|
+
Must be provided as bytes.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
bytes: The encrypted ciphertext
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
TypeError: If config args is not an instance of CryptoConfig.
|
|
114
|
+
CryptoError: Cryptographic errors likely raised due to invalid keys, malformed
|
|
115
|
+
ciphertext, invalid cryptographic parameters, or failures during
|
|
116
|
+
the underlying encryption/decryption operation.
|
|
117
|
+
GeneralError: Incorrect Usage of the function that are not cryptography-related.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
if not isinstance(config, CryptoConfig):
|
|
121
|
+
raise invalid_configuration_type()
|
|
122
|
+
|
|
123
|
+
_must_be_valid("config", config)
|
|
124
|
+
_must_be_valid("key", key)
|
|
125
|
+
_must_be_valid("ciphertext", ciphertext)
|
|
126
|
+
|
|
127
|
+
algorithm = config.algorithm
|
|
128
|
+
if algorithm == "aes":
|
|
129
|
+
raw_key = derive_key(config, key)
|
|
130
|
+
return aes_decrypt(config, raw_key, ciphertext)
|
|
131
|
+
|
|
132
|
+
if algorithm == "extended_oaep":
|
|
133
|
+
try:
|
|
134
|
+
rsa_key = _rsa.import_key(key, rsa_passphrase)
|
|
135
|
+
except (ValueError, TypeError, IndexError) as e:
|
|
136
|
+
if rsa_passphrase is not None:
|
|
137
|
+
raise keyfile_passphrase_incorrect() from e
|
|
138
|
+
raise invalid_keyfile() from e
|
|
139
|
+
if not rsa_key.has_private():
|
|
140
|
+
raise keyfile_cannot_crypt("decrypt")
|
|
141
|
+
|
|
142
|
+
return oaep_extended_decrypt(config, rsa_key, ciphertext)
|
|
143
|
+
|
|
144
|
+
if algorithm == "rsa-oaep":
|
|
145
|
+
try:
|
|
146
|
+
rsa_key = _rsa.import_key(key, rsa_passphrase)
|
|
147
|
+
except (ValueError, TypeError, IndexError) as e:
|
|
148
|
+
if rsa_passphrase is not None:
|
|
149
|
+
raise keyfile_passphrase_incorrect() from e
|
|
150
|
+
raise invalid_keyfile() from e
|
|
151
|
+
if not rsa_key.has_private():
|
|
152
|
+
raise keyfile_cannot_crypt("decrypt")
|
|
153
|
+
|
|
154
|
+
return rsa_oaep_decrypt(config, rsa_key, ciphertext)
|
|
155
|
+
if re.search(r"^ML-KEM-(768|1024)$", algorithm):
|
|
156
|
+
return kyber_decrypt(config, key, ciphertext, rsa_passphrase)
|
|
157
|
+
raise algorithm_not_supported()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _must_be_valid(name, param):
|
|
161
|
+
if param is None:
|
|
162
|
+
raise parameter_not_exist(name)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
from typing import Literal, TypeAlias
|
|
2
|
+
|
|
3
|
+
from Crypto.PublicKey.RSA import RsaKey
|
|
4
|
+
|
|
5
|
+
from ghostbytes.crypto.config import (
|
|
6
|
+
AVAIL_ALG,
|
|
7
|
+
AVAIL_HASH,
|
|
8
|
+
AVAIL_HASH_STR,
|
|
9
|
+
AVAIL_RANDOM_STR,
|
|
10
|
+
COMMON_RSA_SIZE,
|
|
11
|
+
ENCRYPTED_SUFFIX,
|
|
12
|
+
OVERWRITE_OPTIONS,
|
|
13
|
+
RANDOM_SALT_SIZE,
|
|
14
|
+
RSA_KEY_OUT_FORMAT,
|
|
15
|
+
RSA_SIZE_WARNING_THRESHOLD,
|
|
16
|
+
CryptoConfig,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Public configuration values
|
|
21
|
+
Algorithm: TypeAlias = Literal[
|
|
22
|
+
"aes",
|
|
23
|
+
"rsa-oaep",
|
|
24
|
+
"extended_oaep",
|
|
25
|
+
"ML-KEM-768",
|
|
26
|
+
"ML-KEM-1024",
|
|
27
|
+
]
|
|
28
|
+
HashName: TypeAlias = Literal[
|
|
29
|
+
"sha3_512",
|
|
30
|
+
"sha3_256",
|
|
31
|
+
"sha512",
|
|
32
|
+
"sha256",
|
|
33
|
+
"blake2b",
|
|
34
|
+
"blake2s",
|
|
35
|
+
"md5",
|
|
36
|
+
]
|
|
37
|
+
KeyEncoding: TypeAlias = Literal["PEM", "DER", "OpenSSH"]
|
|
38
|
+
MLKEMEncoding: TypeAlias = Literal["PEM", "DER"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# crypto.py
|
|
42
|
+
def encrypt(
|
|
43
|
+
config: CryptoConfig,
|
|
44
|
+
key: bytes,
|
|
45
|
+
plaintext: bytes,
|
|
46
|
+
rsa_passphrase: str | bytes | None = None,
|
|
47
|
+
) -> bytes: ...
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def decrypt(
|
|
51
|
+
config: CryptoConfig,
|
|
52
|
+
key: bytes,
|
|
53
|
+
ciphertext: bytes,
|
|
54
|
+
rsa_passphrase: str | bytes | None = None,
|
|
55
|
+
) -> bytes: ...
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# primitives.py
|
|
59
|
+
def aes_encrypt(config: CryptoConfig, key: bytes, plaintext: bytes) -> bytes: ...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def aes_decrypt(config: CryptoConfig, key: bytes, ciphertext: bytes) -> bytes: ...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def derive_key(config: CryptoConfig, secret: bytes) -> bytes: ...
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def rsa_oaep_encrypt(
|
|
69
|
+
config: CryptoConfig,
|
|
70
|
+
key: RsaKey,
|
|
71
|
+
plaintext: bytes,
|
|
72
|
+
) -> bytes: ...
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def rsa_oaep_decrypt(
|
|
76
|
+
config: CryptoConfig,
|
|
77
|
+
key: RsaKey,
|
|
78
|
+
ciphertext: bytes,
|
|
79
|
+
) -> bytes: ...
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def genrsa(
|
|
83
|
+
length: int,
|
|
84
|
+
exp: int,
|
|
85
|
+
passphrase: str | bytes | None,
|
|
86
|
+
out_format: KeyEncoding = "PEM",
|
|
87
|
+
) -> tuple[bytes, bytes]: ...
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def verify_rsa(
|
|
91
|
+
public_key: bytes,
|
|
92
|
+
private_key: bytes,
|
|
93
|
+
passphrase: str | bytes | None = None,
|
|
94
|
+
) -> bool: ...
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def detect_key_format(key_bytes: bytes) -> Literal["PEM", "DER"]: ...
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def keytype(
|
|
101
|
+
key_bytes: bytes,
|
|
102
|
+
passphrase: str | bytes | None = None,
|
|
103
|
+
) -> Literal["RSA", "ML-KEM"]: ...
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# oaep_extension.py
|
|
107
|
+
def oaep_extended_encrypt(
|
|
108
|
+
config: CryptoConfig,
|
|
109
|
+
rsa: RsaKey,
|
|
110
|
+
plaintext: bytes,
|
|
111
|
+
) -> bytes: ...
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def oaep_extended_decrypt(
|
|
115
|
+
config: CryptoConfig,
|
|
116
|
+
rsa: RsaKey,
|
|
117
|
+
ciphertext: bytes,
|
|
118
|
+
) -> bytes: ...
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# kyber.py
|
|
122
|
+
def genkey(
|
|
123
|
+
alg: Literal["ML-KEM-768", "ML-KEM-1024"],
|
|
124
|
+
encoding: MLKEMEncoding,
|
|
125
|
+
passphrase: bytes | None = None,
|
|
126
|
+
) -> tuple[bytes, bytes]: ...
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def verify_key(
|
|
130
|
+
pubkey: bytes,
|
|
131
|
+
privkey: bytes,
|
|
132
|
+
passphrase: str | bytes | None = None,
|
|
133
|
+
) -> bool: ...
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def kyber_encrypt(
|
|
137
|
+
config: CryptoConfig,
|
|
138
|
+
pubkey: bytes,
|
|
139
|
+
plaintext: bytes,
|
|
140
|
+
passphrase: str | bytes | None = None,
|
|
141
|
+
) -> bytes: ...
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def kyber_decrypt(
|
|
145
|
+
config: CryptoConfig,
|
|
146
|
+
privkey: bytes,
|
|
147
|
+
ciphertext: bytes,
|
|
148
|
+
passphrase: str | bytes | None = None,
|
|
149
|
+
) -> bytes: ...
|