У меня есть следующие функции R, которые используют пакет sodium
R для шифрования и дешифрования ключа доступа с помощью пароля:
encrypt_access_key <- function(access_key, password) {
key <- sha256(charToRaw(password))
nonce <- random(24) # Generate a random nonce
encrypted <- data_encrypt(charToRaw(access_key), key, nonce)
list(
encrypted_access_key = base64encode(encrypted),
nonce = base64encode(nonce)
)
}
decrypt_access_key <- function(encrypted_access_key, nonce, password) {
key <- sha256(charToRaw(password))
encrypted_raw <- base64decode(encrypted_access_key)
nonce_raw <- base64decode(nonce)
rawToChar(data_decrypt(encrypted_raw, key, nonce_raw))
}
Я хочу создать функцию Python, которая имитирует функциональность функции decrypt_access_key
, но мне не удалось это сделать... Если это полезно, вот документация для функций data_encrypt
и data_decrypt
из пакета натрия: ️ 🔁 ссылка
Обновлено: Вот воспроизводимый пример
encripted_message <- encrypt_access_key("This is a hidden message", "Example123")
decrypt_access_key(encripted_message$encrypted_access_key, encripted_message$nonce, "Example123")
Нет необходимости копировать функциональность encrypt_access_key
, все, что мне нужно, это функция Python, которая может получить строку, сохраненную как encripted_message$encrypted_access_key
, и расшифровать сообщение.
Редактировать 2: Вот воспроизводимый пример с явным значением nonce и зашифрованным сообщением.
decrypt_access_key(encrypted_access_key = "QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w= = ", nonce = "LpO7fBaCs1iobxDxVmOPFycTe/BCifqh", password = "Example123")
А вот одна из неудачных попыток расшифровать сообщение с помощью Python:
import base64
from Crypto.Cipher import ChaCha20_Poly1305
from Crypto.Protocol.KDF import PBKDF2
import hashlib
def decrypt_access_key(encrypted_access_key, nonce, password):
# Decode the base64 encoded components
encrypted_access_key_bytes = base64.b64decode(encrypted_access_key)
nonce_bytes = base64.b64decode(nonce)
# Derive the key using PBKDF2
key = hashlib.pbkdf2_hmac('sha256', password.encode(), b'', 100000)
# Decrypt the access key using ChaCha20-Poly1305
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce_bytes)
decrypted = cipher.decrypt(encrypted_access_key_bytes)
return decrypted.decode('utf-8')
# Example usage
encrypted_access_key = 'QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w=='
nonce = 'LpO7fBaCs1iobxDxVmOPFycTe/BCifqh'
password = 'Example123'
decrypted_access_key = decrypt_access_key(encrypted_access_key, nonce, password)
print(decrypted_access_key)
Вам будет легче помочь, если вы включите простой воспроизводимый пример с примерами ввода и желаемым результатом, который можно использовать для тестирования и проверки возможных решений. Непонятно, что именно вы передаете этой функции. Какой результат вы получили от своего кода Python?
@MrFlick Я добавил воспроизводимый пример! Мой код на Python не стоит того, чтобы делиться им, потому что это всего лишь неудачные попытки ChatGPT понять, как натрия шифрует сообщение.
В вашем примере отсутствуют зашифрованный текст и nonce. Они необходимы для проверки функции дешифрования Python! Кроме того, SO не является службой доставки кода. Поэтому вам следует опубликовать свой код Python, а также указать, какую библиотеку Python следует использовать.
Вы можете увидеть закодированный nonce, напечатав encripted_message$nonce в R, но дайте мне секунду, и я введу явную строку в примере. Я действительно не знаю, какую библиотеку Python следует использовать, но все же добавлю одну из неудачных попыток чатгптса в Python.
Код R для шифрования извлекает ключ из пароля с использованием SHA256 и выполняет шифрование с аутентификацией с помощью SecretBox, который использует XSalsa20 и Poly1305 под капотом, см. здесь. Результат возвращает одноразовый номер (24 байта) и объединение зашифрованного текста и тега (16 байтов) отдельно.
Опубликованный код Python несовместим с SecretBox.
Возможный порт NaCl/Libsodium Python, поддерживающий SecretBox, — это PyNaCl. В отличие от библиотеки R, PyNaCl возвращает объединение nonce, зашифрованного текста и тега в результате шифрования и требует объединения nonce, зашифрованного текста и тега во время расшифровки:
import nacl.secret
import hashlib
import base64
key = hashlib.sha256(b'Example123').digest()
box = nacl.secret.SecretBox(key)
nonceB64 = 'LpO7fBaCs1iobxDxVmOPFycTe/BCifqh'
ciphertextTagB64 = 'QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w=='
nonceCiphertextTag = base64.b64decode(nonceB64) + base64.b64decode(ciphertextTagB64)
decrypted = box.decrypt(nonceCiphertextTag)
print(decrypted.decode('utf-8')) # This is a hidden message
Обратите внимание, что использование быстрого дайджеста, такого как SHA256, является уязвимостью. Безопаснее использовать надежную функцию получения ключей, хотя бы PBKDF2, а еще лучше более современные алгоритмы, упомянутые в документации Libsodium (Argon2, Scrypt), см. здесь.
Следующая функция Python расшифровывает ключ доступа, который был зашифрован с помощью пакета натрия в R. Эта функция согласуется с процессами шифрования и дешифрования, используемыми в R, обеспечивая совместимость с алгоритмом XSalsa20-Poly1305, используемым методом SecretBox из библиотеки PyNaCl. Это подчеркивает сохранение того же метода получения ключа (SHA256
), который используется в реализации R, и объединяет nonce и ciphertext
, как того требует PyNaCl
. Это должно гарантировать, что процесс расшифровки точно отражает процесс шифрования, гарантируя правильное получение исходного сообщения.
import base64
from nacl.secret import SecretBox
import hashlib
def decrypt_access_key(encrypted_access_key, nonce, password):
# Decode the base64 encoded components
encrypted_access_key_bytes = base64.b64decode(encrypted_access_key)
nonce_bytes = base64.b64decode(nonce)
# Derive the key using SHA256 (to match the R implementation)
key = hashlib.sha256(password.encode()).digest()
# Create a SecretBox with the derived key
box = SecretBox(key)
# Concatenate nonce and encrypted access key
nonce_ciphertext = nonce_bytes + encrypted_access_key_bytes
# Decrypt the access key
decrypted = box.decrypt(nonce_ciphertext)
return decrypted.decode('utf-8')
# Example usage
encrypted_access_key = 'QG42J4fSVcY9luHaXiEhQcR85isjgUlmFc97pMHIIwuxQyZzDNpz2w=='
nonce = 'LpO7fBaCs1iobxDxVmOPFycTe/BCifqh'
password = 'Example123'
decrypted_access_key = decrypt_access_key(encrypted_access_key, nonce, password)
print(decrypted_access_key) # This is a hidden message
Эта функция согласуется с процессами шифрования и дешифрования, используемыми в R, обеспечивая совместимость с алгоритмом XSalsa20-Poly1305
, используемым методом SecretBox
из библиотеки PyNaCl
. Здесь я попытался подчеркнуть сохранение того же метода получения ключа (SHA256
), который используется в реализации R, и объединяет nonce и ciphertext
, как того требует PyNaCl
. Это гарантирует, что процесс расшифровки точно отражает процесс шифрования, гарантируя правильное получение исходного сообщения.
encrypted_access_key
и nonce
base64
декодируются для преобразования их обратно в исходный байтовый формат. Ключ получается с использованием SHA256
, чтобы соответствовать методу получения ключа, используемому в коде R (sha256(charToRaw(password))
). Объект SecretBox
создается с использованием производного ключа, предоставляя методы шифрования и дешифрования с использованием схемы XSalsa20-Poly1305
. Nonce и зашифрованный ключ доступа объединяются, поскольку PyNaCl
требует, чтобы nonce был префиксом ciphertext
для расшифровки. Затем метод decrypt
объекта SecretBox
используется для расшифровки объединенного nonce
и зашифрованного ключа доступа. Результат декодируется из байтов в строку, закодированную UTF-8
, в результате чего получается исходное сообщение. Эта функция Python теперь должна правильно расшифровывать сообщение, зашифрованное с помощью пакета натрия R, сохраняя согласованность с методами шифрования и дешифрования, используемыми в R.
Опубликуйте непродуктивные тестовые данные: ключ, открытый текст и зашифрованный текст, сгенерированные кодом R, а также ваш последний код Python.