Skip to content

Commit

Permalink
finalize rsa tests, use new rsa module all around
Browse files Browse the repository at this point in the history
  • Loading branch information
samantehrani committed Jan 18, 2025
1 parent a8eaaac commit c25c4e7
Show file tree
Hide file tree
Showing 20 changed files with 103 additions and 185 deletions.
5 changes: 4 additions & 1 deletion src/common/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as ArweaveUtils from "./lib/utils";
import Silo from "./silo";
import Chunks from "./chunks";
import Blocks from "./blocks";
import { PrivateKey, PublicKey, fromJWK } from "./lib/crypto/keys";
import { KeyType, PrivateKey, PublicKey, fromJWK } from "./lib/crypto/keys";

export interface Config {
api: ApiConfig;
Expand Down Expand Up @@ -108,6 +108,9 @@ export default class Arweave {
}
transaction.owner = await pk.identifier()
.then(id => ArweaveUtils.bufferTob64Url(id));
if (pk.type === KeyType.EC_SECP256K1) {
transaction.owner = "";
}
}

if (attributes.last_tx == undefined) {
Expand Down
23 changes: 17 additions & 6 deletions src/common/lib/crypto/keys/rsa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { KeyType, PublicKey, PrivateKey, getInitializationOptions, getSigningPar
import { b64UrlToBuffer, bufferTob64Url } from "../../utils";

export class RSAPrivateKey extends PrivateKey {
static usages: Array<KeyUsage> = ["sign"];
static usages: Array<KeyUsage> = ["sign", "verify"];
static async new({driver = crypto.subtle, type = KeyType.RSA_65537, modulusLength}: {driver?: SubtleCrypto, type?: KeyType, modulusLength?: number} = {driver: crypto.subtle, type: KeyType.RSA_65537}): Promise<RSAPrivateKey> {
if (modulusLength !== undefined) {
if (modulusLength < 32 * 8 || modulusLength > 512 * 8) {
Expand All @@ -23,7 +23,7 @@ export class RSAPrivateKey extends PrivateKey {
}

static async deserialize({driver = crypto.subtle, format, keyData, type}: {driver?: SubtleCrypto, format: "jwk" | "raw" | "pkcs8" | "spki", keyData: JsonWebKey | Uint8Array, type: KeyType}): Promise<RSAPrivateKey> {
const key = await driver.importKey(format as any, keyData as any, getInitializationOptions(type), true, RSAPrivateKey.usages);
const key = await driver.importKey(format as any, keyData as any, getInitializationOptions(type), true, ["sign"]);
return new RSAPrivateKey({driver, type, key});
}

Expand Down Expand Up @@ -79,7 +79,11 @@ export class RSAPrivateKey extends PrivateKey {
public async serialize({format}: SerializationParams): Promise<JsonWebKey | Uint8Array> {
switch (format) {
case "jwk":
return this.driver.exportKey("jwk", this.key);
let jwk = await this.driver.exportKey("jwk", this.key);
delete jwk.ext;
delete jwk.key_ops;
delete jwk.alg;
return jwk;
default:
throw new Error(`Format ${format} no suppoerted`);
}
Expand All @@ -100,15 +104,19 @@ export class RSAPublicKey extends PublicKey {
}

static async deserialize({driver = crypto.subtle, format, keyData, type}: {driver?: SubtleCrypto, format: "jwk" | "raw" | "pkcs8" | "spki", keyData: JsonWebKey | ArrayBuffer, type: KeyType}): Promise<RSAPublicKey> {
let k: JsonWebKey;
if (format === "raw") {
keyData = {
k = {
kty: "RSA",
e: "AQAB",
n: bufferTob64Url(keyData as Uint8Array),
key_ops: RSAPublicKey.usages
};
format = "jwk";
} else {
k = {...keyData as JsonWebKey, key_ops: RSAPublicKey.usages};
}
const key = await driver.importKey(format as any, keyData as any, getInitializationOptions(type), true, RSAPublicKey.usages);
const key = await driver.importKey(format as any, k as any, getInitializationOptions(type), true, RSAPublicKey.usages);
return new RSAPublicKey({driver, type, key});
}

Expand All @@ -118,7 +126,7 @@ export class RSAPublicKey extends PublicKey {
let result = false;
for (let s of [0, 32, maxSaltSize(this.key)]) {
if (result = await this.driver.verify(
{name: "RSA-PSS", saltLength: s},
{...getSigningParameters(this.type) as RsaPssParams, saltLength: s},
this.key,
signature,
payload
Expand All @@ -139,6 +147,9 @@ export class RSAPublicKey extends PublicKey {
const jwk = await this.driver.exportKey("jwk", this.key);
switch(format) {
case "jwk":
delete jwk.key_ops;
delete jwk.ext;
delete jwk.alg;
return jwk;
case "raw":
return b64UrlToBuffer(jwk.n!);
Expand Down
13 changes: 6 additions & 7 deletions src/common/lib/crypto/keys/secp256k1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class SECP256k1PrivateKey extends PrivateKey {
if (isDigest == false) {
digest = new Uint8Array(await crypto.subtle.digest("SHA-256", payload));
} else if (digest.byteLength !== ByteLens.MSG_HASH) {
Promise.reject(`Invalid digest size ${digest.byteLength}`);
return Promise.reject(`Invalid digest size ${digest.byteLength}`);
}
const[signature, recovery]: SignatureAndRecovery = this.driver.sign(this.key, digest);
const recovarableSignature = new Uint8Array(ByteLens.ECDSA_SIG_RECOVERABLE);
Expand Down Expand Up @@ -132,13 +132,13 @@ export class SECP256k1PublicKey extends PublicKey {
driver = (await ENGINE);
}
if (signature.byteLength !== ByteLens.ECDSA_SIG_RECOVERABLE) {
Promise.reject(`Invaldi signature length $${signature.byteLength} needs to by ${ByteLens.ECDSA_SIG_RECOVERABLE}`);
return Promise.reject(`Invaldi signature length ${signature.byteLength} needs to by ${ByteLens.ECDSA_SIG_RECOVERABLE}`);
}
let digest = payload;
if (isDigest === false) {
digest = new Uint8Array(await crypto.subtle.digest("SHA-256", payload));
} else if (digest.byteLength !== ByteLens.MSG_HASH) {
Promise.reject(`Invalid digest size ${digest.byteLength}`);
return Promise.reject(`Invalid digest size ${digest.byteLength}`);
}
const compactSignature = signature.slice(0, ByteLens.ECDSA_SIG_COMPACT);
const recoveryId = signature[signature.byteLength - 1];
Expand All @@ -163,14 +163,14 @@ export class SECP256k1PublicKey extends PublicKey {

public async verify({payload, signature, isDigest = false}: VerifyingParams): Promise<boolean> {
if (signature.byteLength !== ByteLens.ECDSA_SIG_RECOVERABLE) {
Promise.reject(`Invaldi signature length $${signature.byteLength} needs to by ${ByteLens.ECDSA_SIG_RECOVERABLE}`);
return Promise.reject(`Invaldi signature length ${signature.byteLength} needs to by ${ByteLens.ECDSA_SIG_RECOVERABLE}`);
}
const compactSignature = signature.slice(0, ByteLens.ECDSA_SIG_COMPACT);
let digest = payload;
if (isDigest === false) {
digest = new Uint8Array(await crypto.subtle.digest("SHA-256", payload));
} else if (digest.byteLength !== ByteLens.MSG_HASH) {
Promise.reject(`Invalid digest size ${digest.byteLength}`);
return Promise.reject(`Invalid digest size ${digest.byteLength}`);
}
return this.driver.verify(compactSignature, digest, this.key);
}
Expand Down Expand Up @@ -203,7 +203,6 @@ export class SECP256k1PublicKey extends PublicKey {
}

public async identifier(): Promise<Uint8Array> {
const raw = await this.serialize({format: "raw"});
return new Uint8Array([KeyTypeByte[KeyType.EC_SECP256K1], ...raw, 0]);
return new Uint8Array([...await this.serialize({format: "raw"})]);
}
}
2 changes: 0 additions & 2 deletions src/common/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,10 @@ export default class Transaction
tag.get("value", { decode: true, string: false }),
]);
let hashList: Array<any> = [ArweaveUtils.stringToBuffer(this.format.toString())];

// ECDSA should not have owner field in the signature
if (this.owner !== "") {
hashList.push(this.get("owner", { decode: true, string: false }));
}

hashList = [...hashList,
this.get("target", { decode: true, string: false }),
ArweaveUtils.stringToBuffer(this.quantity),
Expand Down
16 changes: 12 additions & 4 deletions src/common/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import * as ArweaveUtils from "./lib/utils";
import "arconnect";
import { fromJWK } from "./lib/crypto/keys";

export interface KeyGenerationParams<T extends KeyType = KeyType> {
type: T
}

export default class Wallets {
private api: Api;
Expand Down Expand Up @@ -43,7 +46,10 @@ export default class Wallets {
});
}

public async generateWallet({type = KeyType.RSA_65537}: {type: KeyType} = {type: KeyType.RSA_65537}): Promise<PrivateKey> {
// public async generateKey({type}: SerializationParams<"jwk">): Promise<JsonWebKey>;
public async generateKey({type}: KeyGenerationParams<KeyType.EC_SECP256K1>): Promise<SECP256k1PrivateKey>;
public async generateKey({type}: KeyGenerationParams<KeyType.RSA_65537>): Promise<RSAPrivateKey>;
public async generateKey({type = KeyType.RSA_65537}: KeyGenerationParams): Promise<PrivateKey> {
switch(type) {
case KeyType.RSA_65537:
return RSAPrivateKey.new();
Expand All @@ -54,12 +60,14 @@ export default class Wallets {
}
}

public generate() {
return this.crypto.generateJWK();
public async generate() {
return this.generateKey({type: KeyType.RSA_65537})
.then(k => k.serialize({format: "jwk"}))
.then(jwk => jwk as JWKInterface);
}

public async jwkToAddress(
jwk?: JWKInterface | "use_wallet"
jwk?: JWKInterface | "use_wallet" | PrivateKey | PublicKey
): Promise<string> {
return this.getAddress(jwk);
}
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/RustCrypto-k256/msg.bin

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/RustCrypto-k256/pk.json

This file was deleted.

Binary file removed test/fixtures/RustCrypto-k256/sig.bin
Binary file not shown.
1 change: 0 additions & 1 deletion test/fixtures/RustCrypto-k256/sk.json

This file was deleted.

53 changes: 0 additions & 53 deletions test/fixtures/RustCrypto-k256/src.rs

This file was deleted.

Binary file removed test/fixtures/erlang/bad/msg.bin
Binary file not shown.
1 change: 0 additions & 1 deletion test/fixtures/erlang/bad/pk.json

This file was deleted.

Binary file removed test/fixtures/erlang/bad/sig.bin
Binary file not shown.
1 change: 0 additions & 1 deletion test/fixtures/erlang/bad/sk.json

This file was deleted.

Binary file modified test/fixtures/erlang/msg.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion test/fixtures/erlang/pk.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"crv":"secp256k1","kty":"EC","x":"sE7eeHycqkEg8hO-dBE97M37DcxhZVY5Qb5aXTh6mUQ","y":"8m-Z0exgmm9YWbcIDl1MhxxX5xj6aUkXV6usKECghWg"}
{"kty":"EC","crv":"secp256k1","x":"l_Kr2lNxtAekWHlQ1nfMaHwKRuP_Gzd9_4RFHmFejgA","y":"XWTfbtSexI6qSYA8zQjJeFA6bQc6KP4eiiqpqhX7rUo"}
Binary file modified test/fixtures/erlang/sig.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion test/fixtures/erlang/sk.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"crv":"secp256k1","d":"ehs4HqZTA6zO_DojYYTVIKtAXMIoTwqxoebybJFv9zU","kty":"EC"}
{"kty":"EC","crv":"secp256k1","d":"j0qcQaZZv-YmxsnUlfUtbgvcmpYlCQFjfA6T9An25qQ","x":"l_Kr2lNxtAekWHlQ1nfMaHwKRuP_Gzd9_4RFHmFejgA","y":"XWTfbtSexI6qSYA8zQjJeFA6bQc6KP4eiiqpqhX7rUo"}
69 changes: 0 additions & 69 deletions test/fixtures/erlang/src.erl

This file was deleted.

Loading

0 comments on commit c25c4e7

Please sign in to comment.