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

feat: add validation for public key #2841

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ivaylonikolov7
Copy link
Contributor

Description:
Add validation to PublicKeys by installing a new NPM package that checks if the public key is on the curve.

Related issue(s):

#2728

Notes for reviewer:

Checklist

  • Documented (Code comments, README, etc.)
  • Tested (unit, integration, etc.) - N/A

Signed-off-by: Ivaylo Nikolov <ivaylo.nikolov@limechain.tech>
@ivaylonikolov7 ivaylonikolov7 requested a review from a team as a code owner February 3, 2025 01:09
packages/cryptography/src/EcdsaPublicKey.js Show resolved Hide resolved
it("should throw error when creating ECDSA key from invalid bytes", function () {
// Test cases with invalid byte
const invalidPrivateKeyBytes = Uint8Array.from([
0x00, 0xca, 0x35, 0x4b, 0x7c, 0xf4, 0x87, 0xd1, 0xbc, 0x43, 0x5a,
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure that padding the zero byte makes the key invalid?

Copy link
Contributor Author

@ivaylonikolov7 ivaylonikolov7 Feb 3, 2025

Choose a reason for hiding this comment

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

I copied the invalid bytes from the Java SDK tests. I think the first byte checks if the key is compressed or not (0x02 or 0x03). Therefore 0x00 making it invalid.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is really a question of convention:
048ae371ee33535a3fa40e31c20485cd8bf869c151184c56cae2775b0156eb3a4b29421847d57caf98b271ab954a42bfb1bed565a9c238b2f7b30274cbd793a163 - also a valid key.
The bad thing about conventions around this topic is that many would trim the 0x02, 0x03 prefix or the 0x04 prefix. So to do a fully invalid key check i would go with bytes which I know for sure a wrong like 1+ the maximum value of the curve which would be N.

Copy link
Contributor

Choose a reason for hiding this comment

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

This way you can validate the point verification function and will be really useful.

* @returns {boolean}
*/
static isValid(data) {
if (!data) return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this check if data is empty? If it does would make it more verbose.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also if you have this here why not have it in the other public key class as well?

Comment on lines +123 to +124
const EMPTY_BUFFER_33_BYTES = Buffer.from(new Uint8Array(33).fill(0));
const EMPTY_BUFFER_65_BYTES = Buffer.from(new Uint8Array(65).fill(0));
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need those buffers in memory to do the following checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you elaborate a little more?

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean do you need to allocate those buffers and save them in variables to do the checks? Isn't there some sort of faster check for this without having EMPTY_BUFFER_33_BYTES, EMPTY_BUFFER_65_BYTES

Comment on lines +121 to +123
const EMPTY_BUFFER = Buffer.from(new Uint8Array(33).fill(0));
const bufferData = Buffer.from(data);
if (bufferData.equals(EMPTY_BUFFER)) return true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Seem like some redundant operations to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How so?

Copy link
Contributor

Choose a reason for hiding this comment

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

if (Buffer.from(data).equals(Buffer.alloc(33))) return true;

ed25519.ExtendedPoint.fromHex(data);
return true;
} catch {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

If an error is caught wouldn't it make sense to propagate it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think considering the method's name is isValidKey you would expect it to return true or false.

Copy link
Contributor

Choose a reason for hiding this comment

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

throw new BadKeyError("invalid public key"); is thrown in another layer. The message of the error for the key parse would be useful there imho. I know you've defined it so but that error could get up there somehow

Copy link
Contributor

Choose a reason for hiding this comment

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

Since this method is created in this PR, we can ditch it and do the validation in the fromBytesRaw func. There we can throw new BadKeyError("invalid public key: ", e);, giving more info to the user as Georgi said.

packages/cryptography/src/EcdsaPublicKey.js Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants