Open Danziger opened 3 months ago
New but failed attempt based on protocol.land:
import base64url from 'base64url';
// ...
async signDataItem(dataItem: DataItem): Promise<ArrayBufferLike> {
const { sub, publicKey } = await this.requireUserDataOrThrow();
const { data, tags, ...options } = dataItem;
const signFn = this.api.getSignerSignFn(sub);
const { crypto } = this;
class MySigner implements Signer {
publicKey: Buffer;
signatureType = 1;
signatureLength = 512;
ownerLength = 512;
sign = signFn;
constructor(publicKeyBuffer: Buffer) {
this.publicKey = publicKeyBuffer;
}
static async verify(pk: string, message: Uint8Array, signature: Uint8Array): Promise<boolean> {
// return await Arweave.crypto.verify(pk, message, signature);
const publicJWK: JsonWebKey = {
e: "AQAB",
ext: true,
kty: "RSA",
n: pk,
};
const cryptoKey = await crypto.subtle.importKey(
"jwk",
publicJWK,
{
name: "RSA-PSS",
hash: "SHA-256",
},
false,
["verify"],
);
return await crypto.subtle.verify({ name: "RSA-PSS" }, cryptoKey, signature, message);
}
};
const signer = new MySigner(base64url.toBuffer(publicKey));
/*
const publicJWK: JWKInterface = {
e: "AQAB",
kty: "RSA",
n: publicKey,
};
const signer = new ArweaveSigner(publicJWK);
*/
const opts: DataItemCreateOptions = {
...options,
tags: this.addCommonTags(tags),
};
const dataItemInstance = createData(data, signer, opts);
// DataItem.sign() sets the DataItem's `id` property and returns its `rawId`:
await dataItemInstance.sign(signer);
return dataItemInstance.getRaw().buffer;
}
The error is thrown from
https://github.com/warp-contracts/warp-arbundles/blob/main/src/signing/chains/ArweaveSigner.ts
Which calls:
https://github.com/ArweaveTeam/arweave-js/blob/master/src/common/lib/crypto/webcrypto-driver.ts
Which ends up executing:
private async jwkToPublicCryptoKey(
publicJwk: JWKPublicInterface
): Promise<CryptoKey> {
return this.driver.importKey(
"jwk",
publicJwk,
{
name: "RSA-PSS",
hash: {
name: "SHA-256",
},
},
false,
["verify"]
);
}
The problem seems to be that crypto.subtle.importKey
expects the n
property of the JWK object to be of type string
, but warp-arbundles
requires the publicKey
property (same as n
) to be of type Buffer
.
The verify that, update the signDataItem()
code to:
const signer: Signer = {
publicKey: toBuffer(publicKey),
signatureType: 1,
signatureLength: 512,
ownerLength: 512,
sign: this.api.getSignerSignFn(sub),
// Note we don't provide `verify` as it's not used anyway:
// verify: () => true,
};
const original = this.crypto.subtle.importKey.bind(this.crypto.subtle) as Function;
this.crypto.subtle.importKey = (...args: any[]) => {
console.log("ARGS =", args);
return original(...args);
}
const publicJwk = {
kty: "RSA",
e: "AQAB",
n: publicKey,
} as const;
this.crypto.subtle.importKey(
"jwk",
publicJwk,
{
name: "RSA-PSS",
hash: {
name: "SHA-256",
},
},
false,
["verify"]
);
You'll see two calls to importKeys
in the console, the one in the example above and the one from warp-arbundles
, which will throw an error. If we change n: publicKey
to n: toBuffer(publicKey)
, that will also throw an error.
This might be resolved if we migrate from warp-arbundles
to https://github.com/DHA-Team/arbundles
Using
signDataItem()
and then callingdataItem.isValid()
always returnsfalse
, so the following example will never submit the data item to a bundler:This issue was already present in v1.