Ключи API пользователя должны использовать填充 OAEP

Небольшая проблема и, возможно, более серьёзная:

В документации не упоминается обязательный параметр nonce:

  def require_params
    %i[public_key nonce scopes client_id application_name].each { |p| params.require(p) }
  end

Теперь более сложная проблема. Discourse вызывает метод public_encrypt без аргументов:

Это означает, что аргумент padding по умолчанию принимает значение PKCS1_PADDING. Согласно документации Ruby:

Шифрует string с помощью открытого ключа. По умолчанию padding равен PKCS1_PADDING, который считается небезопасным, но сохраняется для обратной совместимости.

К сожалению, Node v20.14.0 (текущая LTS) возвращает ошибку, если попытаться вызвать crypto.privateDecrypt с RSA_PKCS1_PADDING:

function decryptData(data: string, privateKey: string) {
  const buffer = Buffer.from(data, "base64");
  const decrypted = crypto.privateDecrypt(
    {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_PADDING,
    },
    buffer
  );
  return decrypted.toString("utf8");
}

TypeError: RSA_PKCS1_PADDING больше не поддерживается для расшифровки с закрытым ключом; это можно отменить с помощью флага --security-revert=CVE-2023-46809

Возможное решение для Node-приложений — запуск Node с небезопасным флагом:

node --security-revert=CVE-2023-46809 

Исправление на стороне Discourse было бы простым, но, по всей видимости, это нарушит работу множества существующих интеграций:

public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@payload = Base64.encode64(public_key.public_encrypt(@payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))
3 лайка

@simon Да, это определённо вызывает проблемы с Node v22. Было бы здорово не откатывать исправления безопасности. Было бы неплохо добавить флаг в вызов API или настройку сайта в Discourse, чтобы выбрать нужный отступ. (Таким образом, пользователи смогут сохранить текущий параметр по умолчанию, если захотят.)

1 лайк

Примерно следуя инструкциям здесь с использованием NodeRSA, всё работает

Это выглядит как довольно простое дополнение?

Я понимаю, что OAEP рекомендуется для новых приложений, так как он устойчив к атакам CCA и Блейхенбаха. То, что Node вынуждает нас к этому, немного огорчает, но, полагаю, это вопрос «общего блага».

Меня крайне беспокоит идея сделать это ещё одним переключателем, который должен анализировать администратор Discourse — это настоящий кошмар.

Вместо этого нам нужно исправить Discourse Hub, чтобы он одновременно поддерживал новые и старые версии, и добавить в наш API сигнал, указывающий «версию» открытого ключа.

Это сложное изменение, затрагивающее множество систем. Предложенное вами решение создаст проблему, так как Discourse Hub перестанет работать для администраторов, которые переключатся в этот режим.

3 лайка

Спасибо за дополнительный контекст.

Для ясности: у меня возникают проблемы с этим при локальной разработке. Однако при подключении к нашим ресурсам, развернутым на экземплярах AWS EC2, этой проблемы нет. Я предполагаю, что их версия Node имеет какие-то скрытые кастомизации или особенности версионирования, из-за которых в библиотеке криптографии этой проблемы нет.

Вступаю в разговор без подготовки, но эта ошибка кажется некорректной. Это не функция, которая была удалена в Node, а проблема с некоторыми установками OpenSSL. Согласно документации Node:

Использование crypto.constants.RSA_PKCS1_PADDING в crypto.privateDecrypt() требует, чтобы OpenSSL поддерживал неявное отклонение (rsa_pkcs1_implicit_rejection).

См. также [Bug]: RSA_PKCS1_PADDING is no longer supported for private decryption · Issue #487 · bropat/eufy-security-client · GitHub

При локальном тестировании у меня это работает: An example of RSA Encryption implemented in Node.js · GitHub, даже когда я переключаюсь на использование crypto.constants.RSA_PKCS1_PADDING для отступов как при шифровании, так и при расшифровке. У меня OpenSSL 3.4.0 и Node 23.6.1.

Сложность использования настройки сайта заключается в том, что клиенты не будут знать, какой тип отступов поддерживает конкретный экземпляр. Это усложняет понимание совместимости между экземплярами/сервисами.

Я думаю, нам следует уточнить существующую реализацию, то есть явно указать, что мы используем RSA_PKCS1_PADDING, а затем подумать о модернизации. Возможно, нам потребуется ввести версионирование для этой конечной точки, чтобы клиенты могли корректно использовать нужный тип отступов до и после указанной версии.

2 лайка

Для контекста: это не запрос функции от меня, а лишь наблюдение, которое я сделал в июне прошлого года.

2 лайка

PSA: это сделано в соответствии с

2 лайка