diff --git a/package-lock.json b/package-lock.json index efae59e..8381080 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,11 +45,30 @@ "node": ">=18" } }, + "../wasm-secp256k1": { + "name": "@arweave/wasm-secp256k1", + "version": "0.0.4", + "extraneous": true, + "license": "MIT", + "devDependencies": { + "@rollup/plugin-typescript": "^12.1.2", + "@rollup/plugin-wasm": "^6.2.2", + "@rollup/pluginutils": "^5.1.4", + "@tsconfig/node22": "^22.0.0", + "@types/node": "^22.10.5", + "@types/web": "^0.0.188", + "@typescript-eslint/parser": "^8.19.0", + "eslint": "^9.17.0", + "eslint-plugin-unused-imports": "^4.1.4", + "rollup": "^4.29.1", + "tslib": "^2.8.1", + "typescript": "^5.7.2" + } + }, "node_modules/@arweave/wasm-secp256k1": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/@arweave/wasm-secp256k1/-/wasm-secp256k1-0.0.4.tgz", - "integrity": "sha512-1xvlrYe3dMgzS/vijr8ZTEIuK6jr3wOollDf7ihWNKvhtHzMFtUaCtNetytVRuM1DzCEEf+7IeAHdlGi8QYctw==", - "license": "MIT" + "integrity": "sha512-1xvlrYe3dMgzS/vijr8ZTEIuK6jr3wOollDf7ihWNKvhtHzMFtUaCtNetytVRuM1DzCEEf+7IeAHdlGi8QYctw==" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", @@ -885,7 +904,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" diff --git a/package.json b/package.json index d6cb482..6c80549 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "clean:bundle": "rimraf bundles", "clean": "npm run clean:dist && npm run clean:package && npm run clean:bundle", "prepublishOnly": "npm run clean && npm run build", - "test": "mocha --file test/shims.ts test/*.ts && echo \"NOW RUN => 'npm run test:web' <= \" ", + "test": "mocha --file src/node/shims.ts test/*.ts && echo \"NOW RUN => 'npm run test:web' <= \" ", "test:web": "npm run bundle:web && webpack --config-name web-tests && opener test/web/web.html", "prettier:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"", "prettier:write": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", diff --git a/src/common/lib/crypto/node-driver.ts b/src/common/lib/crypto/node-driver.ts index a5b4beb..d3f11d1 100644 --- a/src/common/lib/crypto/node-driver.ts +++ b/src/common/lib/crypto/node-driver.ts @@ -75,7 +75,7 @@ export default class NodeCryptoDriver implements CryptoInterface { .then( pk => pk.verify({payload: data, signature, isDigest: false }), error => { - console.log('Failed to recover EC Secp256k1 public key from signature and data!'); + console.log(`Failed to recover EC Secp256k1 public key from signature and data! ${error}`); return false; } ) diff --git a/src/common/lib/crypto/webcrypto-driver.ts b/src/common/lib/crypto/webcrypto-driver.ts index 0b736c5..51eceae 100644 --- a/src/common/lib/crypto/webcrypto-driver.ts +++ b/src/common/lib/crypto/webcrypto-driver.ts @@ -1,6 +1,8 @@ import { JWKInterface, JWKPublicInterface } from "../wallet"; import CryptoInterface, { SignatureOptions } from "./crypto-interface"; import * as ArweaveUtils from "../utils"; +import { PrivateKey, RSAPrivateKey, SECP256k1PublicKey, fromIdentifier } from "./keys"; +import { b64UrlToBuffer } from "../../lib/utils"; export default class WebCryptoDriver implements CryptoInterface { public readonly keyLength = 4096; @@ -46,10 +48,16 @@ export default class WebCryptoDriver implements CryptoInterface { } public async sign( - jwk: JWKInterface, + jwk: JWKInterface | PrivateKey, data: Uint8Array, { saltLength }: SignatureOptions = {} ): Promise { + if (jwk instanceof RSAPrivateKey) { + return jwk.sign({payload: data}, saltLength); + } else if (jwk instanceof PrivateKey) { + return jwk.sign({payload: data}); + } + let signature = await this.driver.sign( { name: "RSA-PSS", @@ -72,66 +80,26 @@ export default class WebCryptoDriver implements CryptoInterface { } public async verify( - publicModulus: string, + owner: string, data: Uint8Array, signature: Uint8Array ): Promise { - const publicKey = { - kty: "RSA", - e: "AQAB", - n: publicModulus, - }; - - const key = await this.jwkToPublicCryptoKey(publicKey); - const digest = await this.driver.digest("SHA-256", data); - - const salt0 = await this.driver.verify( - { - name: "RSA-PSS", - saltLength: 0, - }, - key, - signature, - data - ); - - const salt32 = await this.driver.verify( - { - name: "RSA-PSS", - saltLength: 32, - }, - key, - signature, - data - ); - - // saltN's salt-length is derived from a formula described here - // https://developer.mozilla.org/en-US/docs/Web/API/RsaPssParams - const saltLengthN = - Math.ceil( - ((key.algorithm as RsaHashedKeyGenParams).modulusLength - 1) / 8 - ) - - digest.byteLength - - 2; - - const saltN = await this.driver.verify( - { - name: "RSA-PSS", - saltLength: saltLengthN, - }, - key, - signature, - data - ); - - const result = salt0 || salt32 || saltN; - + if (owner === "") { + return SECP256k1PublicKey.recover({payload: data, signature, isDigest: false}) + .then( + pk => pk.verify({payload: data, signature, isDigest: false }), + error => { + console.log(`Failed to recover EC Secp256k1 public key from signature and data! ${error}`); + return false; + } + ) + } + const identifier = b64UrlToBuffer(owner); + const pk = await fromIdentifier({identifier}); + const result = await pk.verify({payload: data, signature}); if (!result) { const details = { - algorithm: key.algorithm.name, - modulusLength: (key.algorithm as RsaHashedKeyAlgorithm).modulusLength, - keyUsages: key.usages, - saltLengthsAttempted: `0, 32, ${saltLengthN}`, + asymmetricKeyType: pk.type }; console.warn( "Transaction Verification Failed! \n", diff --git a/src/node/index.ts b/src/node/index.ts index 5a5d695..9f4487b 100644 --- a/src/node/index.ts +++ b/src/node/index.ts @@ -1,5 +1,6 @@ import Arweave from "./common"; import { ApiConfig } from "./lib/api"; +import "./shims"; Arweave.init = function (apiConfig: ApiConfig = {}): Arweave { return new Arweave(apiConfig); diff --git a/test/shims.ts b/src/node/shims.ts similarity index 100% rename from test/shims.ts rename to src/node/shims.ts diff --git a/test/web/web.html b/test/web/web.html index ec480ac..07f6869 100644 --- a/test/web/web.html +++ b/test/web/web.html @@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/webpack.config.js b/webpack.config.js index b5b30db..a8bf4a6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -62,12 +62,14 @@ config.webprod = { process: require.resolve("process/browser"), crypto: require.resolve("crypto-browserify"), stream: require.resolve("stream-browserify"), + buffer: require.resolve('buffer/') }, extensions: [".ts", ".js"], }, plugins: [ new webpack.ProvidePlugin({ process: "process/browser", + Buffer: ['buffer', 'Buffer'] }), ], optimization: {