Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: add keyObject.asymmetricKeyDetails for asymmetric keys #36188

Closed
wants to merge 4 commits into from

Conversation

panva
Copy link
Member

@panva panva commented Nov 20, 2020

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-bot nodejs-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
Collaborator

Review requested:

  • @nodejs/crypto
  • @nodejs/quic

src/crypto/crypto_keys.cc Outdated Show resolved Hide resolved
lib/internal/crypto/keys.js Outdated Show resolved Hide resolved
@tniessen
Copy link
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
Copy link
Member Author

panva commented Nov 20, 2020

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)

doc/api/crypto.md Outdated Show resolved Hide resolved
@tniessen
Copy link
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
Member Author

panva commented Nov 30, 2020

@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
Copy link
Member Author

panva commented Nov 30, 2020

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

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Nov 30, 2020
@github-actions github-actions bot 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.

Copy link
Member

@tniessen tniessen left a comment

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)?

test/parallel/test-crypto-keygen.js Show resolved Hide resolved
doc/api/crypto.md Show resolved Hide resolved
@panva
Copy link
Member Author

panva commented Nov 30, 2020

@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
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 :)

Copy link
Member

@tniessen tniessen left a comment

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.

@Trott Trott added the semver-minor PRs that contain new features and should be released in the next minor version. label Dec 2, 2020
@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 2, 2020
@github-actions github-actions bot 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.

closes nodejs#30045
@panva panva marked this pull request as ready for review January 13, 2021 14:35
@panva panva 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.

@panva panva 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
Member Author

panva commented Jan 14, 2021

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

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

@tniessen tniessen left a comment

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
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.)

lib/internal/crypto/util.js Outdated Show resolved Hide resolved
doc/api/crypto.md Show resolved Hide resolved
src/crypto/crypto_keys.cc Outdated Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@panva panva 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
Collaborator

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@panva
Copy link
Member Author

panva commented Jan 14, 2021

Landed in 1772ae7

@panva panva 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>
@ruyadorno ruyadorno mentioned this pull request Jan 22, 2021
@panva panva deleted the keyobject-details branch October 13, 2022 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. crypto Issues and PRs related to the crypto subsystem. semver-minor PRs 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