Skip to content

Commit

Permalink
Upgrade @noble/ed25519 to avoid implicit use of crypto module (#285)
Browse files Browse the repository at this point in the history
* Upgrade @noble/ed25519 to avoid implicit use of crypto module
  • Loading branch information
soerenbf authored Oct 11, 2023
1 parent d4313f3 commit 9982006
Show file tree
Hide file tree
Showing 15 changed files with 67 additions and 30 deletions.
6 changes: 5 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ module.exports = {
'import/no-unresolved': [
2,
{
ignore: ['@concordium/rust-bindings', 'grpc-api'],
ignore: [
'@concordium/rust-bindings',
'grpc-api',
'^#.+$', // ESLint resolver does not support subpath imports: https://github.com/import-js/eslint-plugin-import/issues/1868.
],
},
],
'import/no-extraneous-dependencies': [
Expand Down
4 changes: 2 additions & 2 deletions examples/cis4/registerCredential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs';
import path from 'path';
import meow from 'meow';
import { credentials } from '@grpc/grpc-js';
import * as ed25519 from '@noble/ed25519';
import * as ed25519 from '#ed25519';

import {
AccountAddress,
Expand Down Expand Up @@ -104,7 +104,7 @@ const signer = buildAccountSigner(wallet);
let holderPubKey: HexString;
if (!cli.flags.holderPubKey) {
const prv = ed25519.utils.randomPrivateKey();
const pub = Buffer.from(await ed25519.getPublicKey(prv)).toString(
const pub = Buffer.from(await ed25519.getPublicKeyAsync(prv)).toString(
'hex'
);

Expand Down
4 changes: 2 additions & 2 deletions examples/cis4/registerRevocationKeys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs';
import path from 'path';
import meow from 'meow';
import * as ed25519 from '@noble/ed25519';
import * as ed25519 from '#ed25519';
import { credentials } from '@grpc/grpc-js';

import {
Expand Down Expand Up @@ -88,7 +88,7 @@ const signer = buildAccountSigner(wallet);
let keys: HexString[] = cli.flags.keys ?? [];
if (!cli.flags.keys?.length) {
const prv = ed25519.utils.randomPrivateKey();
const pub = Buffer.from(await ed25519.getPublicKey(prv)).toString(
const pub = Buffer.from(await ed25519.getPublicKeyAsync(prv)).toString(
'hex'
);

Expand Down
8 changes: 7 additions & 1 deletion examples/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"name": "@concordium/examples",
"type": "module",
"imports": {
"#ed25519": {
"node": "./shims/ed25519.node.ts",
"default": "@noble/ed25519"
}
},
"dependencies": {
"@concordium/ccd-js-gen": "workspace:^",
"@concordium/web-sdk": "workspace:^",
"@grpc/grpc-js": "^1.3.4",
"@noble/ed25519": "^1.7.1",
"@noble/ed25519": "^2.0.0",
"buffer": "^6.0.3",
"meow": "11.0",
"node-fetch": "^3.3.2"
Expand Down
9 changes: 9 additions & 0 deletions examples/shims/ed25519.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// To add support for node versions <19.
// From https://www.npmjs.com/package/@noble/ed25519#usage
import { webcrypto } from 'node:crypto';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!globalThis.crypto) globalThis.crypto = webcrypto;

export * from '@noble/ed25519';
3 changes: 3 additions & 0 deletions packages/sdk/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const config: Config = {
moduleNameMapper: {
'^(\\.\\.?\\/.+)\\.js$': '$1', // Remap esmodule file extensions
},
transformIgnorePatterns: [
'node_modules/(?!@noble/ed25519)', // @noble/ed25519 is an ES module only
],
transform: {
'^.+\\.[jt]sx?$': [
'ts-jest',
Expand Down
8 changes: 7 additions & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
"default": "./lib/esm/pub/*.js"
}
},
"imports": {
"#ed25519": {
"node": "./src/shims/ed25519.node.ts",
"default": "@noble/ed25519"
}
},
"files": [
"/src/**/*",
"/lib/esm/**/*",
Expand Down Expand Up @@ -71,7 +77,7 @@
"dependencies": {
"@concordium/rust-bindings": "1.2.0",
"@grpc/grpc-js": "^1.9.4",
"@noble/ed25519": "^1.7.1",
"@noble/ed25519": "^2.0.0",
"@protobuf-ts/grpc-transport": "^2.9.1",
"@protobuf-ts/grpcweb-transport": "^2.9.1",
"@protobuf-ts/runtime-rpc": "^2.8.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/src/cis4/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Buffer } from 'buffer/index.js';
import { getPublicKey } from '@noble/ed25519';
import * as ed from '#ed25519';

import type { HexString } from '../types.js';
import type { CIS2 } from '../cis2/util.js';
Expand Down Expand Up @@ -287,7 +287,7 @@ export class Web3IdSigner {
*/
public static async from(privateKey: HexString): Promise<Web3IdSigner> {
const publicKey = Buffer.from(
await getPublicKey(Buffer.from(privateKey, 'hex'))
await ed.getPublicKeyAsync(Buffer.from(privateKey, 'hex'))
).toString('hex');
return new Web3IdSigner(privateKey, publicKey);
}
Expand Down
9 changes: 9 additions & 0 deletions packages/sdk/src/shims/ed25519.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// To add support for node versions <19.
// From https://www.npmjs.com/package/@noble/ed25519#usage
import { webcrypto } from 'node:crypto';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!globalThis.crypto) globalThis.crypto = webcrypto;

export * from '@noble/ed25519';
6 changes: 3 additions & 3 deletions packages/sdk/src/signHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
HexString,
JsonString,
} from './types.js';
import { sign, verify } from '@noble/ed25519';
import * as ed from '#ed25519';
import { Buffer } from 'buffer/index.js';
import * as AccountAddress from './types/AccountAddress.js';
import { sha256 } from './hash.js';
Expand Down Expand Up @@ -123,7 +123,7 @@ export const getSignature = async (
digest: ArrayBuffer,
privateKey: HexString
): Promise<Buffer> =>
Buffer.from(await sign(new Uint8Array(digest), privateKey));
Buffer.from(await ed.signAsync(new Uint8Array(digest), privateKey));

/**
* Creates an `AccountSigner` for an account which uses the first credential's first keypair.
Expand Down Expand Up @@ -345,7 +345,7 @@ export async function verifyMessageSignature(
);
}
if (
!(await verify(
!(await ed.verifyAsync(
credentialSignature[Number(keyIndex)],
digest,
credentialKeys.keys[Number(keyIndex)].verifyKey
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/src/wasm/credentialDeploymentTransactions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Buffer } from 'buffer/index.js';
import { sign } from '@noble/ed25519';
import * as ed from '#ed25519';
import * as wasm from '@concordium/rust-bindings/wallet';
import {
AttributeKey,
Expand Down Expand Up @@ -302,5 +302,5 @@ export async function signCredentialTransaction(
signingKey: HexString
): Promise<HexString> {
const digest = getCredentialDeploymentSignDigest(credDeployment);
return Buffer.from(await sign(digest, signingKey)).toString('hex');
return Buffer.from(await ed.signAsync(digest, signingKey)).toString('hex');
}
10 changes: 5 additions & 5 deletions packages/sdk/test/ci/HdWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ConcordiumHdWallet } from '../../src/wasm/HdWallet.js';
import { Buffer } from 'buffer/index.js';
export const TEST_SEED_1 =
'efa5e27326f8fa0902e647b52449bf335b7b605adc387015ec903f41d95080eb71361cbc7fb78721dcd4f3926a337340aa1406df83332c44c1cdcfe100603860';
import * as ed from '@noble/ed25519';
import * as ed from '#ed25519';

test('Mainnet signing key', () => {
const wallet = ConcordiumHdWallet.fromHex(TEST_SEED_1, 'Mainnet');
Expand All @@ -30,8 +30,8 @@ test('Mainnet public and signing key match', async () => {
const privateKey = wallet.getAccountSigningKey(0, 0, 0);
const publicKey = wallet.getAccountPublicKey(0, 0, 0);
const message = 'abcd1234abcd5678';
const signature = await ed.sign(message, privateKey.toString('hex'));
expect(await ed.verify(signature, message, publicKey)).toBeTruthy();
const signature = await ed.signAsync(message, privateKey.toString('hex'));
expect(await ed.verifyAsync(signature, message, publicKey)).toBeTruthy();
});

test('Mainnet Id Cred Sec', () => {
Expand Down Expand Up @@ -114,8 +114,8 @@ test('Testnet public and signing key match', async () => {
const privateKey = wallet.getAccountSigningKey(0, 0, 0);
const publicKey = wallet.getAccountPublicKey(0, 0, 0);
const message = 'abcd1234abcd5678';
const signature = await ed.sign(message, privateKey.toString('hex'));
expect(await ed.verify(signature, message, publicKey)).toBeTruthy();
const signature = await ed.signAsync(message, privateKey.toString('hex'));
expect(await ed.verifyAsync(signature, message, publicKey)).toBeTruthy();
});

test('Testnet Id Cred Sec', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/test/client/clientV2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
getNodeClientV2,
getNodeClientWeb,
} from './testHelpers.js';
import * as ed from '@noble/ed25519';
import * as ed from '#ed25519';
import * as expected from './resources/expectedJsons.js';

import { TextEncoder, TextDecoder } from 'util';
Expand Down Expand Up @@ -494,7 +494,7 @@ test.each([clientV2, clientWeb])('createAccount', async (client) => {
const signingKey1 =
'1053de23867e0f92a48814aabff834e2ca0b518497abaef71cad4e1be506334a';
const signature = Buffer.from(
await ed.sign(hashToSign, signingKey1)
await ed.signAsync(hashToSign, signingKey1)
).toString('hex');
const signatures: string[] = [signature];
const payload = v1.serializeCredentialDeploymentPayload(
Expand Down
6 changes: 3 additions & 3 deletions packages/sdk/test/client/credentialDeployment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
serializeCredentialDeploymentTransactionForSubmission,
} from '../../src/index.js';
import fs from 'fs';
import * as ed from '@noble/ed25519';
import * as ed from '#ed25519';

test('test deserialize credentialDeployment ', async () => {
const identityInput: IdentityInput = getIdentityInput();
Expand Down Expand Up @@ -67,10 +67,10 @@ test('test deserialize credentialDeployment ', async () => {
'fcd0e499f5dc7a989a37f8c89536e9af956170d7f502411855052ff75cfc3646';

const signature1 = Buffer.from(
await ed.sign(hashToSign, signingKey1)
await ed.signAsync(hashToSign, signingKey1)
).toString('hex');
const signature2 = Buffer.from(
await ed.sign(hashToSign, signingKey2)
await ed.signAsync(hashToSign, signingKey2)
).toString('hex');
const signatures: string[] = [signature1, signature2];

Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ __metadata:
"@concordium/ccd-js-gen": "workspace:^"
"@concordium/web-sdk": "workspace:^"
"@grpc/grpc-js": ^1.3.4
"@noble/ed25519": ^1.7.1
"@noble/ed25519": ^2.0.0
buffer: ^6.0.3
eslint: ^8.50.0
meow: 11.0
Expand Down Expand Up @@ -704,7 +704,7 @@ __metadata:
dependencies:
"@concordium/rust-bindings": 1.2.0
"@grpc/grpc-js": ^1.9.4
"@noble/ed25519": ^1.7.1
"@noble/ed25519": ^2.0.0
"@protobuf-ts/grpc-transport": ^2.9.1
"@protobuf-ts/grpcweb-transport": ^2.9.1
"@protobuf-ts/plugin": ^2.9.1
Expand Down Expand Up @@ -1281,10 +1281,10 @@ __metadata:
languageName: node
linkType: hard

"@noble/ed25519@npm:^1.7.1":
version: 1.7.1
resolution: "@noble/ed25519@npm:1.7.1"
checksum: b8e50306ac70f5cecc349111997e72e897b47a28d406b96cf95d0ebe7cbdefb8380d26117d7847d94102281db200aa3a494e520f9fc12e2f292e0762cb0fa333
"@noble/ed25519@npm:^2.0.0":
version: 2.0.0
resolution: "@noble/ed25519@npm:2.0.0"
checksum: 4404deb3ca4f7a07863a362d697dc624ff0e82083ca4e41f976f76ec6fe879363b4722529389aa1ae280fe62558d9f229c8403b0a077add8b5f1ec1290d6e2d7
languageName: node
linkType: hard

Expand Down

0 comments on commit 9982006

Please sign in to comment.