Skip to content

crypto: add keyObject.asymmetricKeyDetails for asymmetric keys - #36188

Closed
panva wants to merge 4 commits into
nodejs:masterfrom
panva:keyobject-details
Closed

crypto: add keyObject.asymmetricKeyDetails for asymmetric keys#36188
panva wants to merge 4 commits into
nodejs:masterfrom
panva:keyobject-details

Conversation

@panva

@panvapanva commented Nov 20, 2020

Copy link
Copy Markdown
Member

This API exposes key details. It is conceptually different from the
previously discussed keyObject.fields property since it does not give
access to information that could compromise the security of the key, and
the obtained information cannot be used to uniquely identify a key.

The intended purpose is to determine "security properties" of keys, e.g.
to generate a new key pair with the same parameters, or to decide
whether a key is secure enough.

This replaces and closes#30045

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-botnodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. labels Nov 20, 2020
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/crypto
  • @nodejs/quic

Comment threadsrc/crypto/crypto_keys.cc Outdated
Comment threadlib/internal/crypto/keys.js Outdated
@tniessen

Copy link
Copy Markdown
Member

This seems to be a replacement for #30045 (which I'm fine with, I barely had time for any OSS recently), but it doesn't solve the problems mentioned there. For example, publicExponent is not guaranteed to fit into a 53-bit integer.

@panva

panva commented Nov 20, 2020

Copy link
Copy Markdown
MemberAuthor

But it doesn't solve the problems mentioned there. For example, publicExponent is not guaranteed to fit into a 53-bit integer.

It uses the same internals as key.algorithm.publicExponent of crypto.webcrypto.CryptoKey. So it will be undefined if it doesn't fit.

The alternative would be to return the same way as webcrypto input for rsa keygen (a Uint8Array)

Comment threadlib/internal/crypto/keys.js Outdated
Comment threaddoc/api/crypto.md Outdated
@tniessen

Copy link
Copy Markdown
Member

It uses the same internals as key.algorithm.publicExponent of crypto.webcrypto.CryptoKey. So it will be undefined if it doesn't fit.

Admittedly, this is an unlikely scenario, but still one that could occur, and I don't think we should design an API that we won't be able to patch later to support larger exponents. I know we had countless discussions about how to represent big integers in JavaScript, and I think I am leaning towards using JS BigInt values. They are terrible for cryptography, but Buffers and strings and numbers aren't much better.

Let's face it, JavaScript is not great for cryptography. Secure memory management is virtually impossible, and BigInt arithmetic will absolutely introduce side-channel vulnerabilities when used on any sensitive data. However, BigInts are probably still the most JavaScriptish way of representing these numbers, even if WebCrypto deviated from this idea and defined BigInteger to be an Uint8Array.

@panva

Copy link
Copy Markdown
MemberAuthor

@tniessen it would be great if there was an effort to come to a consensus, i don't care one way or the other. The need for this API is clear and the topic was stalled for months. I took your PR as a reference and used the already existing internals after @jasnell's refactoring so that you don't have to worry about rebasing your PR and adjusting to refactored crypto.

@panva

panva commented Nov 30, 2020

Copy link
Copy Markdown
MemberAuthor

@tniessen 5cc9cf0 makes publicExponent a bigint, the other properties do not require this treatment. With that I believe we can move forward, ✅, and 🚢

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollinamcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Nov 30, 2020
@github-actionsgithub-actionsBot removed the request-ci Add this label to start a Jenkins CI on a PR. label Nov 30, 2020
@nodejs-github-bot

This comment has been minimized.

@tniessentniessen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @panva, and thank you for picking this up!

Are all properties compatible with generateKeyPair? Can users call generateKeyPairSync(key.asymmetricKeyType, key.asymmetricKeyDetails)?

Comment threadtest/parallel/test-crypto-keygen.js Outdated
Comment threaddoc/api/crypto.md Outdated
@panva

panva commented Nov 30, 2020

Copy link
Copy Markdown
MemberAuthor

@tniessen

Are all properties compatible with generateKeyPair?

Did not consider this a goal of this PR. But let's see.

  • RSA - it could if we stuck with number instead bigint, a follow up could be planned for making generateKeyPair accept a bigint.
  • EC - yes
  • DH - no, the underlying function returns empty, so missing primeLength or group or prime, could be planned for a followup. I checked with your original PR, it also did not handle DH key details.
  • ed25519, ed448, x25519, x448 - yes, as those do not have any options.

@tniessen

Copy link
Copy Markdown
Member

Are all properties compatible with generateKeyPair?

Did not consider this a goal of this PR. But let's see.

It's not strictly necessary, but I think it would be great :)

  • RSA - it could if we stuck with number instead bigint, a follow up could be planned for making generateKeyPair accept a bigint.

I can do the latter.

  • DH - no, the underlying function returns empty, so missing primeLength or group or prime, could be planned for a followup. I checked with your original PR, it also did not handle DH key details.

I believe my PR is older than DH support :)

@tniessentniessen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @panva and I'm sorry I didn't have much time to work on this recently.

@TrottTrott added the semver-minor PRs that contain new features and should be released in the next minor version. label Dec 2, 2020
@mcollinamcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 2, 2020
@github-actionsgithub-actionsBot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 2, 2020
@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot

This comment has been minimized.

This API exposes key details. It is conceptually different from the
previously discussed keyObject.fields property since it does not give
access to information that could compromise the security of the key, and
the obtained information cannot be used to uniquely identify a key.
The intended purpose is to determine "security properties" of keys, e.g.
to generate a new key pair with the same parameters, or to decide
whether a key is secure enough.
closesnodejs#30045
@panva
panva marked this pull request as ready for review January 13, 2021 14:35
@panvapanva added the request-ci Add this label to start a Jenkins CI on a PR. label Jan 13, 2021
@nodejs-github-bot

This comment has been minimized.

@panvapanva removed the request-ci Add this label to start a Jenkins CI on a PR. label Jan 14, 2021
@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot

This comment has been minimized.

@panva

Copy link
Copy Markdown
MemberAuthor

@tniessen@jasnell@mcollina a re-✅ so we can land this finally 🙏

@panvapanva added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jan 14, 2021

@tniessentniessen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM apart from one concern about the return value of GetAsymmetricKeyDetail.

}

return result;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion, feel free to ignore: Out of curiosity, did you try benchmarking this versus

BigInt(`0x${Buffer.from(input).toString('hex')}`)

Or, if performance really is a concern in this code path,

BigInt(`0x${Buffer.from(input.buffer,input.byteOffset,input.byteLength).toString('hex')}`)

(I know that this is essentially the same as the existing function bigIntArrayToUnsignedInt above, I am just curious what the performance impact is.)

Comment threadlib/internal/crypto/util.js Outdated
Comment threaddoc/api/crypto.md
Comment threadsrc/crypto/crypto_keys.cc Outdated

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@panvapanva removed the c++ Issues and PRs that require attention from people who are familiar with C++. label Jan 14, 2021
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@panva

Copy link
Copy Markdown
MemberAuthor

Landed in 1772ae7

@panvapanva closed this Jan 14, 2021
panva added a commit that referenced this pull request Jan 14, 2021
This API exposes key details. It is conceptually different from the
previously discussed keyObject.fields property since it does not give
access to information that could compromise the security of the key, and
the obtained information cannot be used to uniquely identify a key.
The intended purpose is to determine "security properties" of keys, e.g.
to generate a new key pair with the same parameters, or to decide
whether a key is secure enough.
closes#30045
PR-URL: #36188
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Rich Trott <rtrott@gmail.com>
ruyadorno pushed a commit that referenced this pull request Jan 22, 2021
This patch changes GetRsaKeyDetail to work in older supported versions
of OpenSSL.
Refs: openssl/openssl#10217
PR-URL: #36877
Refs: #36188
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
ruyadorno pushed a commit that referenced this pull request Jan 22, 2021
This API exposes key details. It is conceptually different from the
previously discussed keyObject.fields property since it does not give
access to information that could compromise the security of the key, and
the obtained information cannot be used to uniquely identify a key.
The intended purpose is to determine "security properties" of keys, e.g.
to generate a new key pair with the same parameters, or to decide
whether a key is secure enough.
closes#30045
PR-URL: #36188
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@ruyadornoruyadorno mentioned this pull request Jan 22, 2021
@panva
panva deleted the keyobject-details branch October 13, 2022 09:13
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author readyPRs that have at least one approval, no pending requests for changes, and a CI started.cryptoIssues and PRs related to the crypto subsystem.semver-minorPRs that contain new features and should be released in the next minor version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@panva@nodejs-github-bot@tniessen@addaleax@richardlau@mcollina@jasnell@Trott@targos