Skip to content

Commit

Permalink
Merge pull request #232 from ArweaveTeam/chore/maintenance-202409
Browse files Browse the repository at this point in the history
Chore/maintenance 202409
  • Loading branch information
rosmcmahon authored Sep 29, 2024
2 parents f1e0208 + bd95f0c commit 33e9177
Show file tree
Hide file tree
Showing 8 changed files with 1,067 additions and 3,537 deletions.
4,496 changes: 991 additions & 3,505 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "arweave",
"version": "1.15.1",
"version": "1.15.3",
"description": "Arweave JS client library",
"main": "./node/index.js",
"react-native": "./node/index.js",
Expand Down Expand Up @@ -70,7 +70,7 @@
"@types/base64-js": "^1.3.0",
"@types/chai": "^4.3.1",
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.18",
"@types/node": "^20.16.5",
"buffer": "^6.0.3",
"chai": "^4.3.6",
"crypto-browserify": "^3.12.0",
Expand All @@ -87,7 +87,7 @@
"ts-loader": "^9.3.0",
"ts-node": "^10.8.0",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.7.2",
"typescript": "^5.6.2",
"webpack": "^5.72.1",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^4.9.2"
Expand Down
19 changes: 13 additions & 6 deletions src/common/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ export default class Api {
} else if (responseType === "text") {
await decodeText();
} else if (responseType === "webstream") {
response.data = addAsyncIterator(res.body as ReadableStream) as T;
response.data = addAsyncIterator(
res.body as AsyncIterableReadableStream
) as T;
} else {
/** axios defaults to JSON, and then text, we mimic the behaviour */
try {
Expand All @@ -158,18 +160,23 @@ export default class Api {
* [Symbol.AsyncIterator] is needed to use `for-await` on the returned ReadableStream (web stream).
* Feature is available in nodejs, and should be available in browsers eventually.
*/
const addAsyncIterator = (body: ReadableStream) => {
type AsyncIterableReadableStream = ReadableStream<Uint8Array> &
AsyncIterable<Uint8Array>;
// | ReadableStream<Uint8Array>

const addAsyncIterator = (
body: ReadableStream<Uint8Array>
): AsyncIterableReadableStream => {
const bodyWithIter = body as ReadableStream<Uint8Array> &
AsyncIterable<Uint8Array>;
if (typeof bodyWithIter[Symbol.asyncIterator] === "undefined") {
bodyWithIter[Symbol.asyncIterator] = webIiterator<Uint8Array>(body);
return bodyWithIter;
}
return body;
return bodyWithIter;
};

const webIiterator = function <T>(stream: ReadableStream) {
return async function* iteratorGenerator<T>() {
const webIiterator = function <T>(stream: ReadableStream<T>) {
return async function* iteratorGenerator(): AsyncIterableIterator<T> {
const reader = stream.getReader(); //lock
try {
while (true) {
Expand Down
42 changes: 30 additions & 12 deletions src/common/lib/crypto/node-driver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JWKInterface } from "../wallet";
import CryptoInterface, { SignatureOptions } from "./crypto-interface";
import { pemTojwk, jwkTopem } from "./pem";
import * as crypto from "crypto";
import * as crypto from "node:crypto";

export default class NodeCryptoDriver implements CryptoInterface {
public readonly keyLength = 4096;
Expand Down Expand Up @@ -63,23 +63,41 @@ export default class NodeCryptoDriver implements CryptoInterface {
signature: Uint8Array
): Promise<boolean> {
return new Promise((resolve, reject) => {
const publicKey = {
const publicJwk = {
kty: "RSA",
e: "AQAB",
n: publicModulus,
};

const pem = this.jwkToPem(publicKey);

resolve(
crypto.createVerify(this.hashAlgorithm).update(data).verify(
{
key: pem,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
signature
)
const pem = this.jwkToPem(publicJwk); //?
const keyObject = crypto.createPublicKey({
key: pem,
format: "pem",
});

const verify = crypto.createVerify(this.hashAlgorithm);
verify.update(data);
const verifyResult = verify.verify(
{
key: keyObject,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
signature
);

if (!verifyResult) {
const details = {
asymmetricKeyType: keyObject.asymmetricKeyType,
modulusLength: keyObject.asymmetricKeyDetails?.modulusLength,
};
console.warn(
"Transaction Verification Failed! \n" +
`Details: ${JSON.stringify(details, null, 2)} \n` +
"N.B. ArweaveJS is only guaranteed to verify txs created using ArweaveJS."
);
}

resolve(verifyResult);
});
}

Expand Down
32 changes: 25 additions & 7 deletions src/common/lib/crypto/webcrypto-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,40 @@ export default class WebCryptoDriver implements CryptoInterface {

// 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:
Math.ceil(
((key.algorithm as RsaHashedKeyGenParams).modulusLength - 1) / 8
) -
digest.byteLength -
2,
saltLength: saltLengthN,
},
key,
signature,
data
);

return salt0 || salt32 || saltN;
const result = salt0 || salt32 || saltN;

if (!result) {
const details = {
algorithm: key.algorithm.name,
modulusLength: (key.algorithm as RsaHashedKeyAlgorithm).modulusLength,
keyUsages: key.usages,
saltLengthsAttempted: `0, 32, ${saltLengthN}`,
};
console.warn(
"Transaction Verification Failed! \n",
`Details: ${JSON.stringify(details, null, 2)} \n`,
"N.B. ArweaveJS is only guaranteed to verify txs created using ArweaveJS."
);
}

return result;
}

private async jwkToCryptoKey(jwk: JWKInterface): Promise<CryptoKey> {
Expand Down
1 change: 1 addition & 0 deletions src/common/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default class Transactions {
return new Transaction(attributes);
}

/** @deprecated use GQL https://gql-guide.arweave.net */
public async search(tagName: string, tagValue: string): Promise<string[]> {
return this.api
.post(`arql`, {
Expand Down
2 changes: 1 addition & 1 deletion test/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from "chai";
import {} from "mocha";
import "mocha";
import { arweaveInstance } from "./_arweave";
const arweave = arweaveInstance();

Expand Down
6 changes: 3 additions & 3 deletions test/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ describe("Wallets and keys", function () {
const addressB = await arweave.wallets.jwkToAddress(walletB);

expect(addressA).to.be.a("string");

expect(addressA).to.match(digestRegex);

expect(addressB).to.match(digestRegex);

expect(addressA).to.not.equal(addressB);

expect(arweave.utils.b64UrlToBuffer(walletA.n).byteLength).eq(4096 / 8);
expect(arweave.utils.b64UrlToBuffer(walletB.n).byteLength).eq(4096 / 8);
});

it("should get wallet info", async function () {
Expand Down

0 comments on commit 33e9177

Please sign in to comment.