# User API keys should use OAEP padding

**URL:** https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056
**Category:** Feature
**Tags:** user-api
**Created:** [June 1, 2024, 7:00am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056 "2024-06-01T07:00:36Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [June 1, 2024, 7:00am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/1 "2024-06-01T07:00:36Z")

</div>

A minor issue and maybe a bigger one:

There’s a required `nonce` param that’s not mentioned in the documentation:

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

```

Now the trickier issue. Discourse calls the `public_encrypt` method with no arguments:

> <https://github.com/discourse/discourse/blob/main/app/controllers/user_api_keys_controller.rb#L84>

That means the `padding` argument defaults to `PKCS1_PADDING`. From the [Ruby documentation](https://docs.ruby-lang.org/en/3.2/OpenSSL/PKey/RSA.html):

> Encrypt `string` with the public key. `padding` defaults to [`PKCS1_PADDING`](https://docs.ruby-lang.org/en/3.2/OpenSSL/PKey/RSA.html#PKCS1_PADDING), which is known to be insecure but is kept for backwards compatibility.

Unfortunately, Node v20.14.0 (the current LTS) returns an error if you attempt to call `crypto.privateDecrypt` with `RSA_PKCS1_PADDING `:

```javascript
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 is no longer supported for private decryption, this can be reverted with --security-revert=CVE-2023-46809

A possible fix for Node apps is to run Node with the insecure flag:

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

```

A fix on the Discourse end would be easy, but I suspect it would break a lot of existing integrations:

```ruby
public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@payload = Base64.encode64(public_key.public_encrypt(@payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))

```

---

<div class="post-metadata">

### Author: ![mqmenchaca](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mqmenchaca](https://meta.discourse.org/u/mqmenchaca)
#### Post date: [February 14, 2025, 10:31pm UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/2 "2025-02-14T22:31:14Z")

</div>

@simon Yes this is definitely causing problems with Node v22. It would be great to not revert security patches. It would be nice to set a flag in the API call or site setting in Discourse to choose the desired padding. (That way people can keep the existing default if they would like.)

---

<div class="post-metadata">

### Author: ![mqmenchaca](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mqmenchaca](https://meta.discourse.org/u/mqmenchaca)
#### Post date: [February 15, 2025, 1:11am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/3 "2025-02-15T01:11:33Z")

</div>

Roughly following the steps here using NodeRSA works

[https://github.com/rzcoder/node-rsa/issues/215](https://github.com/rzcoder/node-rsa/issues/215)

---

<div class="post-metadata">

### Author: ![mqmenchaca](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mqmenchaca](https://meta.discourse.org/u/mqmenchaca)
#### Post date: [February 19, 2025, 3:31pm UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/4 "2025-02-19T15:31:19Z")

</div>

This seems like a pretty simple addition?

[https://github.com/discourse/discourse/pull/31389](https://github.com/discourse/discourse/pull/31389)

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [February 24, 2025, 6:17am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/5 "2025-02-24T06:17:36Z")

</div>

I get that OAEP is recommended for new apps being CCA / Bleichenbach attack resistant. Node forcing our hand here is a bit sad, but I guess this is a “greater good” kind of thing.

I am extremely concerned about making this yet another toggle for a Discourse admin to reason about, that is a nightmare.

Instead we would need to fix Discourse Hub to support the new and old flavors concurrently, have something about our API signal the “version” of the public key.

It is a complicated change that runs through quite a few systems. The fix you proposed is a problem cause then Discourse Hub will stop working for admins that flick to that mode.

---

<div class="post-metadata">

### Author: ![mqmenchaca](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mqmenchaca](https://meta.discourse.org/u/mqmenchaca)
#### Post date: [February 24, 2025, 7:44pm UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/7 "2025-02-24T19:44:09Z")

</div>

Thanks for the added context.

To be clear, this is something I have issues it when doing local development. But when connecting to our resources deployed to AWS EC2 instances, it isn’t an issue. I’m guessing their version of Node has some behind-the-scenes customizations or versioning where the crypto library doesn’t have this problem.

---

<div class="post-metadata">

### Author: ![pmusaraj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pmusaraj/32/119489_2.png) [@pmusaraj](https://meta.discourse.org/u/pmusaraj)
#### Post date: [February 24, 2025, 10:09pm UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/8 "2025-02-24T22:09:13Z")

</div>

> [@simon](#):
>
> Unfortunately, Node v20.14.0 (the current LTS) returns an error if you attempt to call `crypto.privateDecrypt` with `RSA_PKCS1_PADDING `:

Coming in cold here but that error seems incorrect. This isn’t a feature that was removed in Node, it’s an issue with some OpenSSL installation. From [the Node docs](https://nodejs.org/api/crypto.html#cryptoprivatedecryptprivatekey-buffer):

```plaintext
Using crypto.constants.RSA_PKCS1_PADDING in crypto.privateDecrypt() requires OpenSSL to support implicit rejection (rsa_pkcs1_implicit_rejection).

```

See also [[Bug]: RSA\_PKCS1\_PADDING is no longer supported for private decryption · Issue #487 · bropat/eufy-security-client · GitHub](https://github.com/bropat/eufy-security-client/issues/487#issuecomment-2048995565)

Testing locally, this works for me: [An example of RSA Encryption implemented in Node.js · GitHub](https://gist.github.com/sohamkamani/b14a9053551dbe59c39f83e25c829ea7?permalink_comment_id=3968741) even when I switch to using `crypto.constants.RSA_PKCS1_PADDING` for the padding for both encryption and decryption. I am on OpenSSL 3.4.0 and Node 23.6.1.

> [@mqmenchaca](#):
>
> This seems like a pretty simple addition?

The tricky thing with using a site setting is that clients won’t know which padding the specific instance is supporting. That makes compatibility across instances/services harder to understand.

I think we should clarify the existing implementation, i.e. explicitly note that we are using `RSA_PKCS1_PADDING` and then think about an upgrade. Maybe we need to introduce versioning to this endpoint, so that clients can neatly use the right padding before/after said version.

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [February 24, 2025, 11:33pm UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/9 "2025-02-24T23:33:10Z")

</div>

For context, this isn’t a feature request by me, it’s just an observation I made in June of last year.

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [December 15, 2025, 6:55am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/10 "2025-12-15T06:55:45Z")

</div>

PSA: this is done as per

[https://github.com/discourse/discourse/commit/3e577b6ba8a6512f67d9df06b1b7a7d7f89809c3](https://github.com/discourse/discourse/commit/3e577b6ba8a6512f67d9df06b1b7a7d7f89809c3)

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [December 15, 2025, 6:56am UTC](https://meta.discourse.org/t/user-api-keys-should-use-oaep-padding/354056/11 "2025-12-15T06:56:02Z")

</div>


