Skip to content

Commit

Permalink
Merge pull request #1209 from LimeChain/replace-tweetnacl-by-@noble/c…
Browse files Browse the repository at this point in the history
…urves

Replace tweetnacl by @noble/curves
  • Loading branch information
gtsonevv authored Dec 15, 2023
2 parents ecf29e2 + cd351b2 commit d594279
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 44 deletions.
8 changes: 8 additions & 0 deletions .changeset/strong-dots-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@near-js/accounts": patch
"@near-js/crypto": patch
"near-api-js": patch
"@near-js/providers": patch
---

Replace tweetnacl by @noble/curves
2 changes: 1 addition & 1 deletion packages/crypto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@near-js/utils": "workspace:*",
"bn.js": "5.2.1",
"borsh": "1.0.0",
"tweetnacl": "^1.0.1"
"@noble/curves": "1.2.0"
},
"devDependencies": {
"@types/node": "^18.11.18",
Expand Down
4 changes: 4 additions & 0 deletions packages/crypto/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
export enum KeyType {
ED25519 = 0,
}

export enum KeySize {
SECRET_KEY = 32
}
29 changes: 18 additions & 11 deletions packages/crypto/src/key_pair_ed25519.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { baseEncode, baseDecode } from '@near-js/utils';
import nacl from 'tweetnacl';
import { ed25519 } from '@noble/curves/ed25519';
import { webcrypto } from 'crypto';

import { KeyType } from './constants';
import { KeySize, KeyType } from './constants';
import { KeyPairBase, Signature } from './key_pair_base';
import { PublicKey } from './public_key';

Expand All @@ -12,17 +13,21 @@ import { PublicKey } from './public_key';
export class KeyPairEd25519 extends KeyPairBase {
readonly publicKey: PublicKey;
readonly secretKey: string;
readonly extendedSecretKey: string;

/**
* Construct an instance of key pair given a secret key.
* It's generally assumed that these are encoded in base58.
* @param {string} secretKey
* @param {string} extendedSecretKey
*/
constructor(secretKey: string) {
constructor(extendedSecretKey: string) {
super();
const keyPair = nacl.sign.keyPair.fromSecretKey(baseDecode(secretKey));
this.publicKey = new PublicKey({ keyType: KeyType.ED25519, data: keyPair.publicKey });
this.secretKey = secretKey;
const decoded = baseDecode(extendedSecretKey);
const secretKey = new Uint8Array(decoded.slice(0, KeySize.SECRET_KEY));
const publicKey = ed25519.getPublicKey(secretKey);
this.publicKey = new PublicKey({ keyType: KeyType.ED25519, data: publicKey });
this.secretKey = baseEncode(secretKey);
this.extendedSecretKey = extendedSecretKey;
}

/**
Expand All @@ -36,12 +41,14 @@ export class KeyPairEd25519 extends KeyPairBase {
* // returns [SECRET_KEY]
*/
static fromRandom() {
const newKeyPair = nacl.sign.keyPair();
return new KeyPairEd25519(baseEncode(newKeyPair.secretKey));
const secretKey = webcrypto.getRandomValues(new Uint8Array(KeySize.SECRET_KEY));
const publicKey = ed25519.getPublicKey(secretKey);
const extendedSecretKey = new Uint8Array([...secretKey, ...publicKey]);
return new KeyPairEd25519(baseEncode(extendedSecretKey));
}

sign(message: Uint8Array): Signature {
const signature = nacl.sign.detached(message, baseDecode(this.secretKey));
const signature = ed25519.sign(message, baseDecode(this.secretKey));
return { signature, publicKey: this.publicKey };
}

Expand All @@ -50,7 +57,7 @@ export class KeyPairEd25519 extends KeyPairBase {
}

toString(): string {
return `ed25519:${this.secretKey}`;
return `ed25519:${this.extendedSecretKey}`;
}

getPublicKey(): PublicKey {
Expand Down
10 changes: 5 additions & 5 deletions packages/crypto/src/public_key.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Assignable } from '@near-js/types';
import { baseEncode, baseDecode } from '@near-js/utils';
import nacl from 'tweetnacl';
import { ed25519 } from '@noble/curves/ed25519';

import { KeyType } from './constants';
import { KeySize, KeyType } from './constants';

function key_type_to_str(keyType: KeyType): string {
switch (keyType) {
Expand Down Expand Up @@ -45,8 +45,8 @@ export class PublicKey extends Assignable {
throw new Error('Invalid encoded key format, must be <curve>:<encoded key>');
}
const decodedPublicKey = baseDecode(publicKey);
if(decodedPublicKey.length !== nacl.box.publicKeyLength) {
throw new Error(`Invalid public key size (${decodedPublicKey.length}), must be ${nacl.box.publicKeyLength}`);
if(decodedPublicKey.length !== KeySize.SECRET_KEY) {
throw new Error(`Invalid public key size (${decodedPublicKey.length}), must be ${KeySize.SECRET_KEY}`);
}
return new PublicKey({ keyType, data: decodedPublicKey });
}
Expand All @@ -57,7 +57,7 @@ export class PublicKey extends Assignable {

verify(message: Uint8Array, signature: Uint8Array): boolean {
switch (this.keyType) {
case KeyType.ED25519: return nacl.sign.detached.verify(message, signature, this.data);
case KeyType.ED25519: return ed25519.verify(signature, message, this.data);
default: throw new Error(`Unknown key type ${this.keyType}`);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/near-api-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"http-errors": "^1.7.2",
"near-abi": "0.1.1",
"node-fetch": "^2.6.1",
"tweetnacl": "^1.0.1"
"@noble/curves": "1.2.0"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
Expand Down
82 changes: 56 additions & 26 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d594279

Please sign in to comment.