Les clés API utilisateur devraient utiliser un padding OAEP

Un problème mineur et peut-être un plus gros :

Il y a un paramètre nonce requis qui n’est pas mentionné dans la documentation :

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

Maintenant, le problème le plus délicat. Discourse appelle la méthode public_encrypt sans arguments :

Cela signifie que l’argument padding prend par défaut PKCS1_PADDING. D’après la documentation Ruby :

Crypte string avec la clé publique. padding prend par défaut PKCS1_PADDING, qui est connu pour être non sécurisé mais est conservé pour des raisons de compatibilité ascendante.

Malheureusement, Node v20.14.0 (l’actuel LTS) renvoie une erreur si vous tentez d’appeler crypto.privateDecrypt avec 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 n’est plus pris en charge pour le déchiffrement privé, cela peut être rétabli avec --security-revert=CVE-2023-46809

Une solution possible pour les applications Node est d’exécuter Node avec le drapeau non sécurisé :

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

Une correction du côté de Discourse serait facile, mais je soupçonne que cela casserait de nombreuses intégrations existantes :

public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@payload = Base64.encode64(public_key.public_encrypt(@payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))
3 « J'aime »

@simon Oui, cela cause définitivement des problèmes avec Node v22. Ce serait formidable de ne pas avoir à annuler les correctifs de sécurité. Il serait agréable de définir un indicateur dans l’appel API ou un paramètre de site dans Discourse pour choisir le remplissage souhaité. (De cette façon, les gens peuvent conserver la valeur par défaut existante s’ils le souhaitent.)

1 « J'aime »

Cela fonctionne à peu près en suivant les étapes ici :

Cela semble être un ajout assez simple ?

Je comprends que OAEP est recommandé pour les nouvelles applications résistantes aux attaques CCA / Bleichenbach. Le fait que Node nous y oblige est un peu triste, mais je suppose que c’est une question de « bien commun ».

Je suis extrêmement préoccupé par le fait d’en faire un autre interrupteur que les administrateurs de Discourse devront comprendre, c’est un cauchemar.

Au lieu de cela, nous devrions corriger Discourse Hub pour qu’il prenne en charge les anciennes et les nouvelles versions simultanément, et que quelque chose dans notre API signale la « version » de la clé publique.

C’est un changement compliqué qui touche plusieurs systèmes. La solution que vous avez proposée pose un problème car Discourse Hub cessera alors de fonctionner pour les administrateurs qui basculent vers ce mode.

3 « J'aime »

Merci pour le contexte supplémentaire.

Pour être clair, c’est quelque chose avec lequel j’ai des problèmes lors du développement local. Mais lorsque je me connecte à nos ressources déployées sur des instances EC2 d’AWS, ce n’est pas un problème. Je suppose que leur version de Node a des personnalisations ou une gestion de version en coulisses où la bibliothèque crypto n’a pas ce problème.

J’arrive sans contexte, mais cette erreur me semble incorrecte. Ce n’est pas une fonctionnalité qui a été supprimée dans Node, c’est un problème avec certaines installations OpenSSL. D’après la documentation Node :

L'utilisation de crypto.constants.RSA_PKCS1_PADDING dans crypto.privateDecrypt() nécessite qu'OpenSSL prenne en charge le rejet implicite (rsa_pkcs1_implicit_rejection).

Voir aussi [Bug]: RSA_PKCS1_PADDING is no longer supported for private decryption · Issue #487 · bropat/eufy-security-client · GitHub

En testant localement, cela fonctionne pour moi : An example of RSA Encryption implemented in Node.js · GitHub même lorsque je passe à l’utilisation de crypto.constants.RSA_PKCS1_PADDING pour le padding du chiffrement et du déchiffrement. Je suis sur OpenSSL 3.4.0 et Node 23.6.1.

La chose délicate avec l’utilisation d’un paramètre de site est que les clients ne sauront pas quel padding l’instance spécifique prend en charge. Cela rend la compatibilité entre les instances/services plus difficile à comprendre.

Je pense que nous devrions clarifier l’implémentation existante, c’est-à-dire noter explicitement que nous utilisons RSA_PKCS1_PADDING et ensuite réfléchir à une mise à niveau. Peut-être devons-nous introduire une version de cet endpoint, afin que les clients puissent utiliser proprement le bon padding avant/après ladite version.

2 « J'aime »

Pour contexte, ce n’est pas une demande de fonctionnalité de ma part, c’est simplement une observation que j’ai faite en juin de l’année dernière.

2 « J'aime »