Как расшифровать ключ, зашифрованный с помощью пакета натрия R в Python?

У меня есть следующие функции 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)

Опубликуйте непродуктивные тестовые данные: ключ, открытый текст и зашифрованный текст, сгенерированные кодом R, а также ваш последний код Python.

Topaco 30.05.2024 07:30

Вам будет легче помочь, если вы включите простой воспроизводимый пример с примерами ввода и желаемым результатом, который можно использовать для тестирования и проверки возможных решений. Непонятно, что именно вы передаете этой функции. Какой результат вы получили от своего кода Python?

MrFlick 30.05.2024 17:01

@MrFlick Я добавил воспроизводимый пример! Мой код на Python не стоит того, чтобы делиться им, потому что это всего лишь неудачные попытки ChatGPT понять, как натрия шифрует сообщение.

Ekapunk 30.05.2024 17:34

В вашем примере отсутствуют зашифрованный текст и nonce. Они необходимы для проверки функции дешифрования Python! Кроме того, SO не является службой доставки кода. Поэтому вам следует опубликовать свой код Python, а также указать, какую библиотеку Python следует использовать.

Topaco 30.05.2024 17:44

Вы можете увидеть закодированный nonce, напечатав encripted_message$nonce в R, но дайте мне секунду, и я введу явную строку в примере. Я действительно не знаю, какую библиотеку Python следует использовать, но все же добавлю одну из неудачных попыток чатгптса в Python.

Ekapunk 30.05.2024 17:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
119
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Код 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 и noncebase64 декодируются для преобразования их обратно в исходный байтовый формат. Ключ получается с использованием SHA256, чтобы соответствовать методу получения ключа, используемому в коде R (sha256(charToRaw(password))). Объект SecretBox создается с использованием производного ключа, предоставляя методы шифрования и дешифрования с использованием схемы XSalsa20-Poly1305. Nonce и зашифрованный ключ доступа объединяются, поскольку PyNaCl требует, чтобы nonce был префиксом ciphertext для расшифровки. Затем метод decrypt объекта SecretBox используется для расшифровки объединенного nonce и зашифрованного ключа доступа. Результат декодируется из байтов в строку, закодированную UTF-8, в результате чего получается исходное сообщение. Эта функция Python теперь должна правильно расшифровывать сообщение, зашифрованное с помощью пакета натрия R, сохраняя согласованность с методами шифрования и дешифрования, используемыми в R.

Другие вопросы по теме

Похожие вопросы

К чему относится ошибка «модуль langchain» не имеет атрибута «verbose»?
Почему VS Code показывает встроенные комментарии как часть переменных среды из файла .env?
Как избежать или обойти еженедельный повторный ввод учетных данных для Interactive Broker Gateway (IBGW), чтобы поддерживать соединение?
Оптимизация размещения узлов в 2D-сетке для соответствия определенным геодезическим расстояниям
Проблемы с потоками и горячими клавишами при использовании Pynput в Python (бесконечный цикл и скорость реагирования)
Полярный контурный график с нерегулярными «ячейками»
Почему распаковка списка при индексации является синтаксической ошибкой в ​​Python 3.8, но не в Python 3.12?
Python TypeError: невозможно объединить объект типа '<class 'str'>'; действительны только объекты Series и DataFrame
Установка правильной версии драйвера Chrome для Chrome в Docker
Pandas: Доступ к результатам в виде столбцов из «groupby» и «agg»?