@mysten/sui 1.16.2 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/cjs/bcs/bcs.d.ts +13 -0
- package/dist/cjs/bcs/bcs.js +6 -0
- package/dist/cjs/bcs/bcs.js.map +2 -2
- package/dist/cjs/bcs/index.d.ts +13 -0
- package/dist/cjs/bcs/index.js +2 -1
- package/dist/cjs/bcs/index.js.map +2 -2
- package/dist/cjs/cryptography/signature-scheme.d.ts +3 -1
- package/dist/cjs/cryptography/signature-scheme.js +4 -2
- package/dist/cjs/cryptography/signature-scheme.js.map +2 -2
- package/dist/cjs/cryptography/signature.d.ts +8 -0
- package/dist/cjs/cryptography/signature.js +5 -2
- package/dist/cjs/cryptography/signature.js.map +3 -3
- package/dist/cjs/keypairs/passkey/index.d.ts +3 -0
- package/dist/cjs/keypairs/passkey/index.js +28 -0
- package/dist/cjs/keypairs/passkey/index.js.map +7 -0
- package/dist/cjs/keypairs/passkey/keypair.d.ts +59 -0
- package/dist/cjs/keypairs/passkey/keypair.js +168 -0
- package/dist/cjs/keypairs/passkey/keypair.js.map +7 -0
- package/dist/cjs/keypairs/passkey/publickey.d.ts +72 -0
- package/dist/cjs/keypairs/passkey/publickey.js +168 -0
- package/dist/cjs/keypairs/passkey/publickey.js.map +7 -0
- package/dist/cjs/verify/verify.js +12 -9
- package/dist/cjs/verify/verify.js.map +2 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/bcs/bcs.d.ts +13 -0
- package/dist/esm/bcs/bcs.js +6 -0
- package/dist/esm/bcs/bcs.js.map +2 -2
- package/dist/esm/bcs/index.d.ts +13 -0
- package/dist/esm/bcs/index.js +3 -1
- package/dist/esm/bcs/index.js.map +2 -2
- package/dist/esm/cryptography/signature-scheme.d.ts +3 -1
- package/dist/esm/cryptography/signature-scheme.js +4 -2
- package/dist/esm/cryptography/signature-scheme.js.map +2 -2
- package/dist/esm/cryptography/signature.d.ts +8 -0
- package/dist/esm/cryptography/signature.js +3 -0
- package/dist/esm/cryptography/signature.js.map +2 -2
- package/dist/esm/keypairs/passkey/index.d.ts +3 -0
- package/dist/esm/keypairs/passkey/index.js +8 -0
- package/dist/esm/keypairs/passkey/index.js.map +7 -0
- package/dist/esm/keypairs/passkey/keypair.d.ts +59 -0
- package/dist/esm/keypairs/passkey/keypair.js +153 -0
- package/dist/esm/keypairs/passkey/keypair.js.map +7 -0
- package/dist/esm/keypairs/passkey/publickey.d.ts +72 -0
- package/dist/esm/keypairs/passkey/publickey.js +148 -0
- package/dist/esm/keypairs/passkey/publickey.js.map +7 -0
- package/dist/esm/verify/verify.js +3 -0
- package/dist/esm/verify/verify.js.map +2 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/keypairs/passkey/package.json +6 -0
- package/package.json +6 -1
- package/src/bcs/bcs.ts +6 -0
- package/src/bcs/index.ts +2 -0
- package/src/cryptography/signature-scheme.ts +9 -1
- package/src/cryptography/signature.ts +3 -0
- package/src/keypairs/passkey/index.ts +5 -0
- package/src/keypairs/passkey/keypair.ts +209 -0
- package/src/keypairs/passkey/publickey.ts +188 -0
- package/src/verify/verify.ts +3 -0
- package/src/version.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cryptography/signature.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64 } from '@mysten/bcs';\n\nimport { bcs } from '../bcs/index.js';\nimport type { MultiSigStruct } from '../multisig/publickey.js';\nimport { parseSerializedZkLoginSignature } from '../zklogin/publickey.js';\nimport type { PublicKey } from './publickey.js';\nimport type { SignatureScheme } from './signature-scheme.js';\nimport {\n\tSIGNATURE_FLAG_TO_SCHEME,\n\tSIGNATURE_SCHEME_TO_FLAG,\n\tSIGNATURE_SCHEME_TO_SIZE,\n} from './signature-scheme.js';\n\n/**\n * Pair of signature and corresponding public key\n */\nexport type SerializeSignatureInput = {\n\tsignatureScheme: SignatureScheme;\n\t/** Base64-encoded signature */\n\tsignature: Uint8Array;\n\t/** Base64-encoded public key */\n\tpublicKey?: PublicKey;\n};\n\n/**\n * Takes in a signature, its associated signing scheme and a public key, then serializes this data\n */\nexport function toSerializedSignature({\n\tsignature,\n\tsignatureScheme,\n\tpublicKey,\n}: SerializeSignatureInput): string {\n\tif (!publicKey) {\n\t\tthrow new Error('`publicKey` is required');\n\t}\n\n\tconst pubKeyBytes = publicKey.toRawBytes();\n\tconst serializedSignature = new Uint8Array(1 + signature.length + pubKeyBytes.length);\n\tserializedSignature.set([SIGNATURE_SCHEME_TO_FLAG[signatureScheme]]);\n\tserializedSignature.set(signature, 1);\n\tserializedSignature.set(pubKeyBytes, 1 + signature.length);\n\treturn toBase64(serializedSignature);\n}\n\n/**\n * Decodes a serialized signature into its constituent components: the signature scheme, the actual signature, and the public key\n */\nexport function parseSerializedSignature(serializedSignature: string) {\n\tconst bytes = fromBase64(serializedSignature);\n\n\tconst signatureScheme =\n\t\tSIGNATURE_FLAG_TO_SCHEME[bytes[0] as keyof typeof SIGNATURE_FLAG_TO_SCHEME];\n\n\tswitch (signatureScheme) {\n\t\tcase 'MultiSig':\n\t\t\tconst multisig: MultiSigStruct = bcs.MultiSig.parse(bytes.slice(1));\n\t\t\treturn {\n\t\t\t\tserializedSignature,\n\t\t\t\tsignatureScheme,\n\t\t\t\tmultisig,\n\t\t\t\tbytes,\n\t\t\t};\n\t\tcase 'ZkLogin':\n\t\t\treturn parseSerializedZkLoginSignature(serializedSignature);\n\t\tcase 'ED25519':\n\t\tcase 'Secp256k1':\n\t\tcase 'Secp256r1':\n\t\t\tconst size =\n\t\t\t\tSIGNATURE_SCHEME_TO_SIZE[signatureScheme as keyof typeof SIGNATURE_SCHEME_TO_SIZE];\n\t\t\tconst signature = bytes.slice(1, bytes.length - size);\n\t\t\tconst publicKey = bytes.slice(1 + signature.length);\n\n\t\t\treturn {\n\t\t\t\tserializedSignature,\n\t\t\t\tsignatureScheme,\n\t\t\t\tsignature,\n\t\t\t\tpublicKey,\n\t\t\t\tbytes,\n\t\t\t};\n\t\tdefault:\n\t\t\tthrow new Error('Unsupported signature scheme');\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AAGA,SAAS,YAAY,gBAAgB;AAErC,SAAS,WAAW;
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64 } from '@mysten/bcs';\n\nimport { bcs } from '../bcs/index.js';\nimport { parseSerializedPasskeySignature } from '../keypairs/passkey/publickey.js';\nimport type { MultiSigStruct } from '../multisig/publickey.js';\nimport { parseSerializedZkLoginSignature } from '../zklogin/publickey.js';\nimport type { PublicKey } from './publickey.js';\nimport type { SignatureScheme } from './signature-scheme.js';\nimport {\n\tSIGNATURE_FLAG_TO_SCHEME,\n\tSIGNATURE_SCHEME_TO_FLAG,\n\tSIGNATURE_SCHEME_TO_SIZE,\n} from './signature-scheme.js';\n\n/**\n * Pair of signature and corresponding public key\n */\nexport type SerializeSignatureInput = {\n\tsignatureScheme: SignatureScheme;\n\t/** Base64-encoded signature */\n\tsignature: Uint8Array;\n\t/** Base64-encoded public key */\n\tpublicKey?: PublicKey;\n};\n\n/**\n * Takes in a signature, its associated signing scheme and a public key, then serializes this data\n */\nexport function toSerializedSignature({\n\tsignature,\n\tsignatureScheme,\n\tpublicKey,\n}: SerializeSignatureInput): string {\n\tif (!publicKey) {\n\t\tthrow new Error('`publicKey` is required');\n\t}\n\n\tconst pubKeyBytes = publicKey.toRawBytes();\n\tconst serializedSignature = new Uint8Array(1 + signature.length + pubKeyBytes.length);\n\tserializedSignature.set([SIGNATURE_SCHEME_TO_FLAG[signatureScheme]]);\n\tserializedSignature.set(signature, 1);\n\tserializedSignature.set(pubKeyBytes, 1 + signature.length);\n\treturn toBase64(serializedSignature);\n}\n\n/**\n * Decodes a serialized signature into its constituent components: the signature scheme, the actual signature, and the public key\n */\nexport function parseSerializedSignature(serializedSignature: string) {\n\tconst bytes = fromBase64(serializedSignature);\n\n\tconst signatureScheme =\n\t\tSIGNATURE_FLAG_TO_SCHEME[bytes[0] as keyof typeof SIGNATURE_FLAG_TO_SCHEME];\n\n\tswitch (signatureScheme) {\n\t\tcase 'Passkey':\n\t\t\treturn parseSerializedPasskeySignature(serializedSignature);\n\t\tcase 'MultiSig':\n\t\t\tconst multisig: MultiSigStruct = bcs.MultiSig.parse(bytes.slice(1));\n\t\t\treturn {\n\t\t\t\tserializedSignature,\n\t\t\t\tsignatureScheme,\n\t\t\t\tmultisig,\n\t\t\t\tbytes,\n\t\t\t};\n\t\tcase 'ZkLogin':\n\t\t\treturn parseSerializedZkLoginSignature(serializedSignature);\n\t\tcase 'ED25519':\n\t\tcase 'Secp256k1':\n\t\tcase 'Secp256r1':\n\t\t\tconst size =\n\t\t\t\tSIGNATURE_SCHEME_TO_SIZE[signatureScheme as keyof typeof SIGNATURE_SCHEME_TO_SIZE];\n\t\t\tconst signature = bytes.slice(1, bytes.length - size);\n\t\t\tconst publicKey = bytes.slice(1 + signature.length);\n\n\t\t\treturn {\n\t\t\t\tserializedSignature,\n\t\t\t\tsignatureScheme,\n\t\t\t\tsignature,\n\t\t\t\tpublicKey,\n\t\t\t\tbytes,\n\t\t\t};\n\t\tdefault:\n\t\t\tthrow new Error('Unsupported signature scheme');\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,YAAY,gBAAgB;AAErC,SAAS,WAAW;AACpB,SAAS,uCAAuC;AAEhD,SAAS,uCAAuC;AAGhD;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAgBA,SAAS,sBAAsB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACD,GAAoC;AACnC,MAAI,CAAC,WAAW;AACf,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC1C;AAEA,QAAM,cAAc,UAAU,WAAW;AACzC,QAAM,sBAAsB,IAAI,WAAW,IAAI,UAAU,SAAS,YAAY,MAAM;AACpF,sBAAoB,IAAI,CAAC,yBAAyB,eAAe,CAAC,CAAC;AACnE,sBAAoB,IAAI,WAAW,CAAC;AACpC,sBAAoB,IAAI,aAAa,IAAI,UAAU,MAAM;AACzD,SAAO,SAAS,mBAAmB;AACpC;AAKO,SAAS,yBAAyB,qBAA6B;AACrE,QAAM,QAAQ,WAAW,mBAAmB;AAE5C,QAAM,kBACL,yBAAyB,MAAM,CAAC,CAA0C;AAE3E,UAAQ,iBAAiB;AAAA,IACxB,KAAK;AACJ,aAAO,gCAAgC,mBAAmB;AAAA,IAC3D,KAAK;AACJ,YAAM,WAA2B,IAAI,SAAS,MAAM,MAAM,MAAM,CAAC,CAAC;AAClE,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,KAAK;AACJ,aAAO,gCAAgC,mBAAmB;AAAA,IAC3D,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,YAAM,OACL,yBAAyB,eAAwD;AAClF,YAAM,YAAY,MAAM,MAAM,GAAG,MAAM,SAAS,IAAI;AACpD,YAAM,YAAY,MAAM,MAAM,IAAI,UAAU,MAAM;AAElD,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACC,YAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/keypairs/passkey/index.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nexport { PasskeyKeypair, BrowserPasskeyProvider } from './keypair.js';\nexport type { PasskeyProvider, BrowserPasswordProviderOptions } from './keypair.js';\nexport { PasskeyPublicKey } from './publickey.js';\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,gBAAgB,8BAA8B;AAEvD,SAAS,wBAAwB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AuthenticationCredential, RegistrationCredential } from '@simplewebauthn/typescript-types';
|
|
2
|
+
import type { IntentScope, SignatureWithBytes } from '../../cryptography/index.js';
|
|
3
|
+
import { Signer } from '../../cryptography/index.js';
|
|
4
|
+
import type { PublicKey } from '../../cryptography/publickey.js';
|
|
5
|
+
import type { SignatureScheme } from '../../cryptography/signature-scheme.js';
|
|
6
|
+
type DeepPartialConfigKeys = 'rp' | 'user' | 'authenticatorSelection';
|
|
7
|
+
type DeepPartial<T> = T extends object ? {
|
|
8
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
9
|
+
} : T;
|
|
10
|
+
export type BrowserPasswordProviderOptions = Pick<DeepPartial<PublicKeyCredentialCreationOptions>, DeepPartialConfigKeys> & Omit<Partial<PublicKeyCredentialCreationOptions>, DeepPartialConfigKeys | 'pubKeyCredParams' | 'challenge'>;
|
|
11
|
+
export interface PasskeyProvider {
|
|
12
|
+
create(): Promise<RegistrationCredential>;
|
|
13
|
+
get(challenge: Uint8Array): Promise<AuthenticationCredential>;
|
|
14
|
+
}
|
|
15
|
+
export declare class BrowserPasskeyProvider implements PasskeyProvider {
|
|
16
|
+
#private;
|
|
17
|
+
constructor(name: string, options: BrowserPasswordProviderOptions);
|
|
18
|
+
create(): Promise<RegistrationCredential>;
|
|
19
|
+
get(challenge: Uint8Array): Promise<AuthenticationCredential>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @experimental
|
|
23
|
+
* A passkey signer used for signing transactions. This is a client side implementation for [SIP-9](https://github.com/sui-foundation/sips/blob/main/sips/sip-9.md).
|
|
24
|
+
*/
|
|
25
|
+
export declare class PasskeyKeypair extends Signer {
|
|
26
|
+
private publicKey;
|
|
27
|
+
private provider;
|
|
28
|
+
/**
|
|
29
|
+
* Get the key scheme of passkey,
|
|
30
|
+
*/
|
|
31
|
+
getKeyScheme(): SignatureScheme;
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of Passkey signer. It's expected to call the static `getPasskeyInstance` method to create an instance.
|
|
34
|
+
* For example:
|
|
35
|
+
* ```
|
|
36
|
+
* const signer = await PasskeyKeypair.getPasskeyInstance();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
constructor(publicKey: Uint8Array, provider: PasskeyProvider);
|
|
40
|
+
/**
|
|
41
|
+
* Creates an instance of Passkey signer invoking the passkey from navigator.
|
|
42
|
+
*/
|
|
43
|
+
static getPasskeyInstance(provider: PasskeyProvider): Promise<PasskeyKeypair>;
|
|
44
|
+
/**
|
|
45
|
+
* Return the public key for this passkey.
|
|
46
|
+
*/
|
|
47
|
+
getPublicKey(): PublicKey;
|
|
48
|
+
/**
|
|
49
|
+
* Return the signature for the provided data (i.e. blake2b(intent_message)).
|
|
50
|
+
* This is sent to passkey as the challenge field.
|
|
51
|
+
*/
|
|
52
|
+
sign(data: Uint8Array): Promise<Uint8Array>;
|
|
53
|
+
/**
|
|
54
|
+
* This overrides the base class implementation that accepts the raw bytes and signs its
|
|
55
|
+
* digest of the intent message, then serialize it with the passkey flag.
|
|
56
|
+
*/
|
|
57
|
+
signWithIntent(bytes: Uint8Array, intent: IntentScope): Promise<SignatureWithBytes>;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
var _name, _options;
|
|
9
|
+
import { toBase64 } from "@mysten/bcs";
|
|
10
|
+
import { secp256r1 } from "@noble/curves/p256";
|
|
11
|
+
import { blake2b } from "@noble/hashes/blake2b";
|
|
12
|
+
import { randomBytes } from "@noble/hashes/utils";
|
|
13
|
+
import { PasskeyAuthenticator } from "../../bcs/bcs.js";
|
|
14
|
+
import { messageWithIntent, SIGNATURE_SCHEME_TO_FLAG, Signer } from "../../cryptography/index.js";
|
|
15
|
+
import {
|
|
16
|
+
parseDerSPKI,
|
|
17
|
+
PASSKEY_PUBLIC_KEY_SIZE,
|
|
18
|
+
PASSKEY_SIGNATURE_SIZE,
|
|
19
|
+
PasskeyPublicKey
|
|
20
|
+
} from "./publickey.js";
|
|
21
|
+
class BrowserPasskeyProvider {
|
|
22
|
+
constructor(name, options) {
|
|
23
|
+
__privateAdd(this, _name);
|
|
24
|
+
__privateAdd(this, _options);
|
|
25
|
+
__privateSet(this, _name, name);
|
|
26
|
+
__privateSet(this, _options, options);
|
|
27
|
+
}
|
|
28
|
+
async create() {
|
|
29
|
+
return await navigator.credentials.create({
|
|
30
|
+
publicKey: {
|
|
31
|
+
timeout: __privateGet(this, _options).timeout ?? 6e4,
|
|
32
|
+
...__privateGet(this, _options),
|
|
33
|
+
rp: {
|
|
34
|
+
name: __privateGet(this, _name),
|
|
35
|
+
...__privateGet(this, _options).rp
|
|
36
|
+
},
|
|
37
|
+
user: {
|
|
38
|
+
name: __privateGet(this, _name),
|
|
39
|
+
displayName: __privateGet(this, _name),
|
|
40
|
+
...__privateGet(this, _options).user,
|
|
41
|
+
id: randomBytes(10)
|
|
42
|
+
},
|
|
43
|
+
challenge: new TextEncoder().encode("Create passkey wallet on Sui"),
|
|
44
|
+
pubKeyCredParams: [{ alg: -7, type: "public-key" }],
|
|
45
|
+
authenticatorSelection: {
|
|
46
|
+
authenticatorAttachment: "cross-platform",
|
|
47
|
+
residentKey: "required",
|
|
48
|
+
requireResidentKey: true,
|
|
49
|
+
userVerification: "required",
|
|
50
|
+
...__privateGet(this, _options).authenticatorSelection
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async get(challenge) {
|
|
56
|
+
return await navigator.credentials.get({
|
|
57
|
+
publicKey: {
|
|
58
|
+
challenge,
|
|
59
|
+
userVerification: __privateGet(this, _options).authenticatorSelection?.userVerification || "required",
|
|
60
|
+
timeout: __privateGet(this, _options).timeout ?? 6e4
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
_name = new WeakMap();
|
|
66
|
+
_options = new WeakMap();
|
|
67
|
+
class PasskeyKeypair extends Signer {
|
|
68
|
+
/**
|
|
69
|
+
* Get the key scheme of passkey,
|
|
70
|
+
*/
|
|
71
|
+
getKeyScheme() {
|
|
72
|
+
return "Passkey";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Creates an instance of Passkey signer. It's expected to call the static `getPasskeyInstance` method to create an instance.
|
|
76
|
+
* For example:
|
|
77
|
+
* ```
|
|
78
|
+
* const signer = await PasskeyKeypair.getPasskeyInstance();
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
constructor(publicKey, provider) {
|
|
82
|
+
super();
|
|
83
|
+
this.publicKey = publicKey;
|
|
84
|
+
this.provider = provider;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Creates an instance of Passkey signer invoking the passkey from navigator.
|
|
88
|
+
*/
|
|
89
|
+
static async getPasskeyInstance(provider) {
|
|
90
|
+
const credential = await provider.create();
|
|
91
|
+
if (!credential.response.getPublicKey()) {
|
|
92
|
+
throw new Error("Invalid credential create response");
|
|
93
|
+
} else {
|
|
94
|
+
const derSPKI = credential.response.getPublicKey();
|
|
95
|
+
const pubkeyUncompressed = parseDerSPKI(new Uint8Array(derSPKI));
|
|
96
|
+
const pubkey = secp256r1.ProjectivePoint.fromHex(pubkeyUncompressed);
|
|
97
|
+
const pubkeyCompressed = pubkey.toRawBytes(true);
|
|
98
|
+
return new PasskeyKeypair(pubkeyCompressed, provider);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Return the public key for this passkey.
|
|
103
|
+
*/
|
|
104
|
+
getPublicKey() {
|
|
105
|
+
return new PasskeyPublicKey(this.publicKey);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Return the signature for the provided data (i.e. blake2b(intent_message)).
|
|
109
|
+
* This is sent to passkey as the challenge field.
|
|
110
|
+
*/
|
|
111
|
+
async sign(data) {
|
|
112
|
+
const credential = await this.provider.get(data);
|
|
113
|
+
const authenticatorData = new Uint8Array(credential.response.authenticatorData);
|
|
114
|
+
const clientDataJSON = new Uint8Array(credential.response.clientDataJSON);
|
|
115
|
+
const decoder = new TextDecoder();
|
|
116
|
+
const clientDataJSONString = decoder.decode(clientDataJSON);
|
|
117
|
+
const sig = secp256r1.Signature.fromDER(new Uint8Array(credential.response.signature));
|
|
118
|
+
const normalized = sig.normalizeS().toCompactRawBytes();
|
|
119
|
+
if (normalized.length !== PASSKEY_SIGNATURE_SIZE || this.publicKey.length !== PASSKEY_PUBLIC_KEY_SIZE) {
|
|
120
|
+
throw new Error("Invalid signature or public key length");
|
|
121
|
+
}
|
|
122
|
+
const arr = new Uint8Array(1 + normalized.length + this.publicKey.length);
|
|
123
|
+
arr.set([SIGNATURE_SCHEME_TO_FLAG["Secp256r1"]]);
|
|
124
|
+
arr.set(normalized, 1);
|
|
125
|
+
arr.set(this.publicKey, 1 + normalized.length);
|
|
126
|
+
return PasskeyAuthenticator.serialize({
|
|
127
|
+
authenticatorData,
|
|
128
|
+
clientDataJson: clientDataJSONString,
|
|
129
|
+
userSignature: arr
|
|
130
|
+
}).toBytes();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* This overrides the base class implementation that accepts the raw bytes and signs its
|
|
134
|
+
* digest of the intent message, then serialize it with the passkey flag.
|
|
135
|
+
*/
|
|
136
|
+
async signWithIntent(bytes, intent) {
|
|
137
|
+
const intentMessage = messageWithIntent(intent, bytes);
|
|
138
|
+
const digest = blake2b(intentMessage, { dkLen: 32 });
|
|
139
|
+
const signature = await this.sign(digest);
|
|
140
|
+
const serializedSignature = new Uint8Array(1 + signature.length);
|
|
141
|
+
serializedSignature.set([SIGNATURE_SCHEME_TO_FLAG[this.getKeyScheme()]]);
|
|
142
|
+
serializedSignature.set(signature, 1);
|
|
143
|
+
return {
|
|
144
|
+
signature: toBase64(serializedSignature),
|
|
145
|
+
bytes: toBase64(bytes)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export {
|
|
150
|
+
BrowserPasskeyProvider,
|
|
151
|
+
PasskeyKeypair
|
|
152
|
+
};
|
|
153
|
+
//# sourceMappingURL=keypair.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/keypairs/passkey/keypair.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { toBase64 } from '@mysten/bcs';\nimport { secp256r1 } from '@noble/curves/p256';\nimport { blake2b } from '@noble/hashes/blake2b';\nimport { randomBytes } from '@noble/hashes/utils';\nimport type {\n\tAuthenticationCredential,\n\tRegistrationCredential,\n} from '@simplewebauthn/typescript-types';\n\nimport { PasskeyAuthenticator } from '../../bcs/bcs.js';\nimport type { IntentScope, SignatureWithBytes } from '../../cryptography/index.js';\nimport { messageWithIntent, SIGNATURE_SCHEME_TO_FLAG, Signer } from '../../cryptography/index.js';\nimport type { PublicKey } from '../../cryptography/publickey.js';\nimport type { SignatureScheme } from '../../cryptography/signature-scheme.js';\nimport {\n\tparseDerSPKI,\n\tPASSKEY_PUBLIC_KEY_SIZE,\n\tPASSKEY_SIGNATURE_SIZE,\n\tPasskeyPublicKey,\n} from './publickey.js';\n\ntype DeepPartialConfigKeys = 'rp' | 'user' | 'authenticatorSelection';\n\ntype DeepPartial<T> = T extends object\n\t? {\n\t\t\t[P in keyof T]?: DeepPartial<T[P]>;\n\t\t}\n\t: T;\n\nexport type BrowserPasswordProviderOptions = Pick<\n\tDeepPartial<PublicKeyCredentialCreationOptions>,\n\tDeepPartialConfigKeys\n> &\n\tOmit<\n\t\tPartial<PublicKeyCredentialCreationOptions>,\n\t\tDeepPartialConfigKeys | 'pubKeyCredParams' | 'challenge'\n\t>;\n\nexport interface PasskeyProvider {\n\tcreate(): Promise<RegistrationCredential>;\n\tget(challenge: Uint8Array): Promise<AuthenticationCredential>;\n}\n\n// Default browser implementation\nexport class BrowserPasskeyProvider implements PasskeyProvider {\n\t#name: string;\n\t#options: BrowserPasswordProviderOptions;\n\n\tconstructor(name: string, options: BrowserPasswordProviderOptions) {\n\t\tthis.#name = name;\n\t\tthis.#options = options;\n\t}\n\n\tasync create(): Promise<RegistrationCredential> {\n\t\treturn (await navigator.credentials.create({\n\t\t\tpublicKey: {\n\t\t\t\ttimeout: this.#options.timeout ?? 60000,\n\t\t\t\t...this.#options,\n\t\t\t\trp: {\n\t\t\t\t\tname: this.#name,\n\t\t\t\t\t...this.#options.rp,\n\t\t\t\t},\n\t\t\t\tuser: {\n\t\t\t\t\tname: this.#name,\n\t\t\t\t\tdisplayName: this.#name,\n\t\t\t\t\t...this.#options.user,\n\t\t\t\t\tid: randomBytes(10),\n\t\t\t\t},\n\t\t\t\tchallenge: new TextEncoder().encode('Create passkey wallet on Sui'),\n\t\t\t\tpubKeyCredParams: [{ alg: -7, type: 'public-key' }],\n\t\t\t\tauthenticatorSelection: {\n\t\t\t\t\tauthenticatorAttachment: 'cross-platform',\n\t\t\t\t\tresidentKey: 'required',\n\t\t\t\t\trequireResidentKey: true,\n\t\t\t\t\tuserVerification: 'required',\n\t\t\t\t\t...this.#options.authenticatorSelection,\n\t\t\t\t},\n\t\t\t},\n\t\t})) as RegistrationCredential;\n\t}\n\n\tasync get(challenge: Uint8Array): Promise<AuthenticationCredential> {\n\t\treturn (await navigator.credentials.get({\n\t\t\tpublicKey: {\n\t\t\t\tchallenge,\n\t\t\t\tuserVerification: this.#options.authenticatorSelection?.userVerification || 'required',\n\t\t\t\ttimeout: this.#options.timeout ?? 60000,\n\t\t\t},\n\t\t})) as AuthenticationCredential;\n\t}\n}\n\n/**\n * @experimental\n * A passkey signer used for signing transactions. This is a client side implementation for [SIP-9](https://github.com/sui-foundation/sips/blob/main/sips/sip-9.md).\n */\nexport class PasskeyKeypair extends Signer {\n\tprivate publicKey: Uint8Array;\n\tprivate provider: PasskeyProvider;\n\n\t/**\n\t * Get the key scheme of passkey,\n\t */\n\tgetKeyScheme(): SignatureScheme {\n\t\treturn 'Passkey';\n\t}\n\n\t/**\n\t * Creates an instance of Passkey signer. It's expected to call the static `getPasskeyInstance` method to create an instance.\n\t * For example:\n\t * ```\n\t * const signer = await PasskeyKeypair.getPasskeyInstance();\n\t * ```\n\t */\n\tconstructor(publicKey: Uint8Array, provider: PasskeyProvider) {\n\t\tsuper();\n\t\tthis.publicKey = publicKey;\n\t\tthis.provider = provider;\n\t}\n\n\t/**\n\t * Creates an instance of Passkey signer invoking the passkey from navigator.\n\t */\n\tstatic async getPasskeyInstance(provider: PasskeyProvider): Promise<PasskeyKeypair> {\n\t\t// create a passkey secp256r1 with the provider.\n\t\tconst credential = await provider.create();\n\n\t\tif (!credential.response.getPublicKey()) {\n\t\t\tthrow new Error('Invalid credential create response');\n\t\t} else {\n\t\t\tconst derSPKI = credential.response.getPublicKey()!;\n\t\t\tconst pubkeyUncompressed = parseDerSPKI(new Uint8Array(derSPKI));\n\t\t\tconst pubkey = secp256r1.ProjectivePoint.fromHex(pubkeyUncompressed);\n\t\t\tconst pubkeyCompressed = pubkey.toRawBytes(true);\n\t\t\treturn new PasskeyKeypair(pubkeyCompressed, provider);\n\t\t}\n\t}\n\n\t/**\n\t * Return the public key for this passkey.\n\t */\n\tgetPublicKey(): PublicKey {\n\t\treturn new PasskeyPublicKey(this.publicKey);\n\t}\n\n\t/**\n\t * Return the signature for the provided data (i.e. blake2b(intent_message)).\n\t * This is sent to passkey as the challenge field.\n\t */\n\tasync sign(data: Uint8Array) {\n\t\t// sendss the passkey to sign over challenge as the data.\n\t\tconst credential = await this.provider.get(data);\n\n\t\t// parse authenticatorData (as bytes), clientDataJSON (decoded as string).\n\t\tconst authenticatorData = new Uint8Array(credential.response.authenticatorData);\n\t\tconst clientDataJSON = new Uint8Array(credential.response.clientDataJSON); // response.clientDataJSON is already UTF-8 encoded JSON\n\t\tconst decoder = new TextDecoder();\n\t\tconst clientDataJSONString: string = decoder.decode(clientDataJSON);\n\n\t\t// parse the signature from DER format, normalize and convert to compressed format (33 bytes).\n\t\tconst sig = secp256r1.Signature.fromDER(new Uint8Array(credential.response.signature));\n\t\tconst normalized = sig.normalizeS().toCompactRawBytes();\n\n\t\tif (\n\t\t\tnormalized.length !== PASSKEY_SIGNATURE_SIZE ||\n\t\t\tthis.publicKey.length !== PASSKEY_PUBLIC_KEY_SIZE\n\t\t) {\n\t\t\tthrow new Error('Invalid signature or public key length');\n\t\t}\n\n\t\t// construct userSignature as flag || sig || pubkey for the secp256r1 signature.\n\t\tconst arr = new Uint8Array(1 + normalized.length + this.publicKey.length);\n\t\tarr.set([SIGNATURE_SCHEME_TO_FLAG['Secp256r1']]);\n\t\tarr.set(normalized, 1);\n\t\tarr.set(this.publicKey, 1 + normalized.length);\n\n\t\t// serialize all fields into a passkey signature according to https://github.com/sui-foundation/sips/blob/main/sips/sip-9.md#signature-encoding\n\t\treturn PasskeyAuthenticator.serialize({\n\t\t\tauthenticatorData: authenticatorData,\n\t\t\tclientDataJson: clientDataJSONString,\n\t\t\tuserSignature: arr,\n\t\t}).toBytes();\n\t}\n\n\t/**\n\t * This overrides the base class implementation that accepts the raw bytes and signs its\n\t * digest of the intent message, then serialize it with the passkey flag.\n\t */\n\tasync signWithIntent(bytes: Uint8Array, intent: IntentScope): Promise<SignatureWithBytes> {\n\t\t// prepend it into an intent message and computes the digest.\n\t\tconst intentMessage = messageWithIntent(intent, bytes);\n\t\tconst digest = blake2b(intentMessage, { dkLen: 32 });\n\n\t\t// sign the digest.\n\t\tconst signature = await this.sign(digest);\n\n\t\t// prepend with the passkey flag.\n\t\tconst serializedSignature = new Uint8Array(1 + signature.length);\n\t\tserializedSignature.set([SIGNATURE_SCHEME_TO_FLAG[this.getKeyScheme()]]);\n\t\tserializedSignature.set(signature, 1);\n\t\treturn {\n\t\t\tsignature: toBase64(serializedSignature),\n\t\t\tbytes: toBase64(bytes),\n\t\t};\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { PublicKey } from '../../cryptography/publickey.js';
|
|
2
|
+
import type { PublicKeyInitData } from '../../cryptography/publickey.js';
|
|
3
|
+
export declare const PASSKEY_PUBLIC_KEY_SIZE = 33;
|
|
4
|
+
export declare const PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;
|
|
5
|
+
export declare const PASSKEY_SIGNATURE_SIZE = 64;
|
|
6
|
+
/** Fixed DER header for secp256r1 SubjectPublicKeyInfo
|
|
7
|
+
DER structure for P-256 SPKI:
|
|
8
|
+
30 -- SEQUENCE
|
|
9
|
+
59 -- length (89 bytes)
|
|
10
|
+
30 -- SEQUENCE
|
|
11
|
+
13 -- length (19 bytes)
|
|
12
|
+
06 -- OBJECT IDENTIFIER
|
|
13
|
+
07 -- length
|
|
14
|
+
2A 86 48 CE 3D 02 01 -- id-ecPublicKey
|
|
15
|
+
06 -- OBJECT IDENTIFIER
|
|
16
|
+
08 -- length
|
|
17
|
+
2A 86 48 CE 3D 03 01 07 -- secp256r1/prime256v1
|
|
18
|
+
03 -- BIT STRING
|
|
19
|
+
42 -- length (66 bytes)
|
|
20
|
+
00 -- padding
|
|
21
|
+
===== above bytes are considered header =====
|
|
22
|
+
04 || x || y -- uncompressed point (65 bytes: 0x04 || 32-byte x || 32-byte y)
|
|
23
|
+
*/
|
|
24
|
+
export declare const SECP256R1_SPKI_HEADER: Uint8Array;
|
|
25
|
+
/**
|
|
26
|
+
* A passkey public key
|
|
27
|
+
*/
|
|
28
|
+
export declare class PasskeyPublicKey extends PublicKey {
|
|
29
|
+
static SIZE: number;
|
|
30
|
+
private data;
|
|
31
|
+
/**
|
|
32
|
+
* Create a new PasskeyPublicKey object
|
|
33
|
+
* @param value passkey public key as buffer or base-64 encoded string
|
|
34
|
+
*/
|
|
35
|
+
constructor(value: PublicKeyInitData);
|
|
36
|
+
/**
|
|
37
|
+
* Checks if two passkey public keys are equal
|
|
38
|
+
*/
|
|
39
|
+
equals(publicKey: PasskeyPublicKey): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Return the byte array representation of the Secp256r1 public key
|
|
42
|
+
*/
|
|
43
|
+
toRawBytes(): Uint8Array;
|
|
44
|
+
/**
|
|
45
|
+
* Return the Sui address associated with this Secp256r1 public key
|
|
46
|
+
*/
|
|
47
|
+
flag(): number;
|
|
48
|
+
/**
|
|
49
|
+
* Verifies that the signature is valid for for the provided message
|
|
50
|
+
*/
|
|
51
|
+
verify(message: Uint8Array, signature: Uint8Array | string): Promise<boolean>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parses a DER SubjectPublicKeyInfo into an uncompressed public key. This also verifies
|
|
55
|
+
* that the curve used is P-256 (secp256r1).
|
|
56
|
+
*
|
|
57
|
+
* @param data: DER SubjectPublicKeyInfo
|
|
58
|
+
* @returns uncompressed public key (`0x04 || x || y`)
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseDerSPKI(derBytes: Uint8Array): Uint8Array;
|
|
61
|
+
/**
|
|
62
|
+
* Parse signature from bytes or base64 string into the following fields.
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseSerializedPasskeySignature(signature: Uint8Array | string): {
|
|
65
|
+
signatureScheme: "Passkey";
|
|
66
|
+
serializedSignature: string;
|
|
67
|
+
signature: Uint8Array;
|
|
68
|
+
authenticatorData: number[];
|
|
69
|
+
clientDataJson: string;
|
|
70
|
+
userSignature: Uint8Array;
|
|
71
|
+
publicKey: Uint8Array;
|
|
72
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { fromBase64, toBase64 } from "@mysten/bcs";
|
|
2
|
+
import { secp256r1 } from "@noble/curves/p256";
|
|
3
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
4
|
+
import { PasskeyAuthenticator } from "../../bcs/bcs.js";
|
|
5
|
+
import { bytesEqual, PublicKey } from "../../cryptography/publickey.js";
|
|
6
|
+
import { SIGNATURE_SCHEME_TO_FLAG } from "../../cryptography/signature-scheme.js";
|
|
7
|
+
const PASSKEY_PUBLIC_KEY_SIZE = 33;
|
|
8
|
+
const PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;
|
|
9
|
+
const PASSKEY_SIGNATURE_SIZE = 64;
|
|
10
|
+
const SECP256R1_SPKI_HEADER = new Uint8Array([
|
|
11
|
+
48,
|
|
12
|
+
89,
|
|
13
|
+
// SEQUENCE, length 89
|
|
14
|
+
48,
|
|
15
|
+
19,
|
|
16
|
+
// SEQUENCE, length 19
|
|
17
|
+
6,
|
|
18
|
+
7,
|
|
19
|
+
// OID, length 7
|
|
20
|
+
42,
|
|
21
|
+
134,
|
|
22
|
+
72,
|
|
23
|
+
206,
|
|
24
|
+
61,
|
|
25
|
+
2,
|
|
26
|
+
1,
|
|
27
|
+
// OID: 1.2.840.10045.2.1 (ecPublicKey)
|
|
28
|
+
6,
|
|
29
|
+
8,
|
|
30
|
+
// OID, length 8
|
|
31
|
+
42,
|
|
32
|
+
134,
|
|
33
|
+
72,
|
|
34
|
+
206,
|
|
35
|
+
61,
|
|
36
|
+
3,
|
|
37
|
+
1,
|
|
38
|
+
7,
|
|
39
|
+
// OID: 1.2.840.10045.3.1.7 (prime256v1/secp256r1)
|
|
40
|
+
3,
|
|
41
|
+
66,
|
|
42
|
+
// BIT STRING, length 66
|
|
43
|
+
0
|
|
44
|
+
// no unused bits
|
|
45
|
+
]);
|
|
46
|
+
class PasskeyPublicKey extends PublicKey {
|
|
47
|
+
/**
|
|
48
|
+
* Create a new PasskeyPublicKey object
|
|
49
|
+
* @param value passkey public key as buffer or base-64 encoded string
|
|
50
|
+
*/
|
|
51
|
+
constructor(value) {
|
|
52
|
+
super();
|
|
53
|
+
if (typeof value === "string") {
|
|
54
|
+
this.data = fromBase64(value);
|
|
55
|
+
} else if (value instanceof Uint8Array) {
|
|
56
|
+
this.data = value;
|
|
57
|
+
} else {
|
|
58
|
+
this.data = Uint8Array.from(value);
|
|
59
|
+
}
|
|
60
|
+
if (this.data.length !== PASSKEY_PUBLIC_KEY_SIZE) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Invalid public key input. Expected ${PASSKEY_PUBLIC_KEY_SIZE} bytes, got ${this.data.length}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checks if two passkey public keys are equal
|
|
68
|
+
*/
|
|
69
|
+
equals(publicKey) {
|
|
70
|
+
return super.equals(publicKey);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Return the byte array representation of the Secp256r1 public key
|
|
74
|
+
*/
|
|
75
|
+
toRawBytes() {
|
|
76
|
+
return this.data;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Return the Sui address associated with this Secp256r1 public key
|
|
80
|
+
*/
|
|
81
|
+
flag() {
|
|
82
|
+
return SIGNATURE_SCHEME_TO_FLAG["Passkey"];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Verifies that the signature is valid for for the provided message
|
|
86
|
+
*/
|
|
87
|
+
async verify(message, signature) {
|
|
88
|
+
const parsed = parseSerializedPasskeySignature(signature);
|
|
89
|
+
const clientDataJSON = JSON.parse(parsed.clientDataJson);
|
|
90
|
+
if (clientDataJSON.type !== "webauthn.get") {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const parsedChallenge = fromBase64(
|
|
94
|
+
clientDataJSON.challenge.replace(/-/g, "+").replace(/_/g, "/")
|
|
95
|
+
);
|
|
96
|
+
if (!bytesEqual(message, parsedChallenge)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const pk = parsed.userSignature.slice(1 + PASSKEY_SIGNATURE_SIZE);
|
|
100
|
+
if (!bytesEqual(this.toRawBytes(), pk)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
const payload = new Uint8Array([...parsed.authenticatorData, ...sha256(parsed.clientDataJson)]);
|
|
104
|
+
const sig = parsed.userSignature.slice(1, PASSKEY_SIGNATURE_SIZE + 1);
|
|
105
|
+
return secp256r1.verify(sig, sha256(payload), pk);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
PasskeyPublicKey.SIZE = PASSKEY_PUBLIC_KEY_SIZE;
|
|
109
|
+
function parseDerSPKI(derBytes) {
|
|
110
|
+
if (derBytes.length !== SECP256R1_SPKI_HEADER.length + PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE) {
|
|
111
|
+
throw new Error("Invalid DER length");
|
|
112
|
+
}
|
|
113
|
+
for (let i = 0; i < SECP256R1_SPKI_HEADER.length; i++) {
|
|
114
|
+
if (derBytes[i] !== SECP256R1_SPKI_HEADER[i]) {
|
|
115
|
+
throw new Error("Invalid spki header");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (derBytes[SECP256R1_SPKI_HEADER.length] !== 4) {
|
|
119
|
+
throw new Error("Invalid point marker");
|
|
120
|
+
}
|
|
121
|
+
return derBytes.slice(SECP256R1_SPKI_HEADER.length);
|
|
122
|
+
}
|
|
123
|
+
function parseSerializedPasskeySignature(signature) {
|
|
124
|
+
const bytes = typeof signature === "string" ? fromBase64(signature) : signature;
|
|
125
|
+
if (bytes[0] !== SIGNATURE_SCHEME_TO_FLAG.Passkey) {
|
|
126
|
+
throw new Error("Invalid signature scheme");
|
|
127
|
+
}
|
|
128
|
+
const dec = PasskeyAuthenticator.parse(bytes.slice(1));
|
|
129
|
+
return {
|
|
130
|
+
signatureScheme: "Passkey",
|
|
131
|
+
serializedSignature: toBase64(bytes),
|
|
132
|
+
signature: bytes,
|
|
133
|
+
authenticatorData: dec.authenticatorData,
|
|
134
|
+
clientDataJson: dec.clientDataJson,
|
|
135
|
+
userSignature: new Uint8Array(dec.userSignature),
|
|
136
|
+
publicKey: new Uint8Array(dec.userSignature.slice(1 + PASSKEY_SIGNATURE_SIZE))
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export {
|
|
140
|
+
PASSKEY_PUBLIC_KEY_SIZE,
|
|
141
|
+
PASSKEY_SIGNATURE_SIZE,
|
|
142
|
+
PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE,
|
|
143
|
+
PasskeyPublicKey,
|
|
144
|
+
SECP256R1_SPKI_HEADER,
|
|
145
|
+
parseDerSPKI,
|
|
146
|
+
parseSerializedPasskeySignature
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=publickey.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/keypairs/passkey/publickey.ts"],
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64, toBase64 } from '@mysten/bcs';\nimport { secp256r1 } from '@noble/curves/p256';\nimport { sha256 } from '@noble/hashes/sha256';\n\nimport { PasskeyAuthenticator } from '../../bcs/bcs.js';\nimport { bytesEqual, PublicKey } from '../../cryptography/publickey.js';\nimport type { PublicKeyInitData } from '../../cryptography/publickey.js';\nimport { SIGNATURE_SCHEME_TO_FLAG } from '../../cryptography/signature-scheme.js';\n\nexport const PASSKEY_PUBLIC_KEY_SIZE = 33;\nexport const PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE = 65;\nexport const PASSKEY_SIGNATURE_SIZE = 64;\n/** Fixed DER header for secp256r1 SubjectPublicKeyInfo\nDER structure for P-256 SPKI:\n30 -- SEQUENCE\n 59 -- length (89 bytes)\n 30 -- SEQUENCE\n 13 -- length (19 bytes)\n 06 -- OBJECT IDENTIFIER\n 07 -- length\n 2A 86 48 CE 3D 02 01 -- id-ecPublicKey\n 06 -- OBJECT IDENTIFIER\n 08 -- length\n 2A 86 48 CE 3D 03 01 07 -- secp256r1/prime256v1\n 03 -- BIT STRING\n 42 -- length (66 bytes)\n 00 -- padding\n\t===== above bytes are considered header =====\n 04 || x || y -- uncompressed point (65 bytes: 0x04 || 32-byte x || 32-byte y)\n*/\nexport const SECP256R1_SPKI_HEADER = new Uint8Array([\n\t0x30,\n\t0x59, // SEQUENCE, length 89\n\t0x30,\n\t0x13, // SEQUENCE, length 19\n\t0x06,\n\t0x07, // OID, length 7\n\t0x2a,\n\t0x86,\n\t0x48,\n\t0xce,\n\t0x3d,\n\t0x02,\n\t0x01, // OID: 1.2.840.10045.2.1 (ecPublicKey)\n\t0x06,\n\t0x08, // OID, length 8\n\t0x2a,\n\t0x86,\n\t0x48,\n\t0xce,\n\t0x3d,\n\t0x03,\n\t0x01,\n\t0x07, // OID: 1.2.840.10045.3.1.7 (prime256v1/secp256r1)\n\t0x03,\n\t0x42, // BIT STRING, length 66\n\t0x00, // no unused bits\n] as const);\n\n/**\n * A passkey public key\n */\nexport class PasskeyPublicKey extends PublicKey {\n\tstatic SIZE = PASSKEY_PUBLIC_KEY_SIZE;\n\tprivate data: Uint8Array;\n\n\t/**\n\t * Create a new PasskeyPublicKey object\n\t * @param value passkey public key as buffer or base-64 encoded string\n\t */\n\tconstructor(value: PublicKeyInitData) {\n\t\tsuper();\n\n\t\tif (typeof value === 'string') {\n\t\t\tthis.data = fromBase64(value);\n\t\t} else if (value instanceof Uint8Array) {\n\t\t\tthis.data = value;\n\t\t} else {\n\t\t\tthis.data = Uint8Array.from(value);\n\t\t}\n\n\t\tif (this.data.length !== PASSKEY_PUBLIC_KEY_SIZE) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid public key input. Expected ${PASSKEY_PUBLIC_KEY_SIZE} bytes, got ${this.data.length}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Checks if two passkey public keys are equal\n\t */\n\toverride equals(publicKey: PasskeyPublicKey): boolean {\n\t\treturn super.equals(publicKey);\n\t}\n\n\t/**\n\t * Return the byte array representation of the Secp256r1 public key\n\t */\n\ttoRawBytes(): Uint8Array {\n\t\treturn this.data;\n\t}\n\n\t/**\n\t * Return the Sui address associated with this Secp256r1 public key\n\t */\n\tflag(): number {\n\t\treturn SIGNATURE_SCHEME_TO_FLAG['Passkey'];\n\t}\n\n\t/**\n\t * Verifies that the signature is valid for for the provided message\n\t */\n\tasync verify(message: Uint8Array, signature: Uint8Array | string): Promise<boolean> {\n\t\tconst parsed = parseSerializedPasskeySignature(signature);\n\t\tconst clientDataJSON = JSON.parse(parsed.clientDataJson);\n\n\t\tif (clientDataJSON.type !== 'webauthn.get') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// parse challenge from base64 url\n\t\tconst parsedChallenge = fromBase64(\n\t\t\tclientDataJSON.challenge.replace(/-/g, '+').replace(/_/g, '/'),\n\t\t);\n\t\tif (!bytesEqual(message, parsedChallenge)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst pk = parsed.userSignature.slice(1 + PASSKEY_SIGNATURE_SIZE);\n\t\tif (!bytesEqual(this.toRawBytes(), pk)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst payload = new Uint8Array([...parsed.authenticatorData, ...sha256(parsed.clientDataJson)]);\n\t\tconst sig = parsed.userSignature.slice(1, PASSKEY_SIGNATURE_SIZE + 1);\n\t\treturn secp256r1.verify(sig, sha256(payload), pk);\n\t}\n}\n\n/**\n * Parses a DER SubjectPublicKeyInfo into an uncompressed public key. This also verifies\n * that the curve used is P-256 (secp256r1).\n *\n * @param data: DER SubjectPublicKeyInfo\n * @returns uncompressed public key (`0x04 || x || y`)\n */\nexport function parseDerSPKI(derBytes: Uint8Array): Uint8Array {\n\t// Verify length and header bytes are expected\n\tif (derBytes.length !== SECP256R1_SPKI_HEADER.length + PASSKEY_UNCOMPRESSED_PUBLIC_KEY_SIZE) {\n\t\tthrow new Error('Invalid DER length');\n\t}\n\tfor (let i = 0; i < SECP256R1_SPKI_HEADER.length; i++) {\n\t\tif (derBytes[i] !== SECP256R1_SPKI_HEADER[i]) {\n\t\t\tthrow new Error('Invalid spki header');\n\t\t}\n\t}\n\n\tif (derBytes[SECP256R1_SPKI_HEADER.length] !== 0x04) {\n\t\tthrow new Error('Invalid point marker');\n\t}\n\n\t// Returns the last 65 bytes `04 || x || y`\n\treturn derBytes.slice(SECP256R1_SPKI_HEADER.length);\n}\n\n/**\n * Parse signature from bytes or base64 string into the following fields.\n */\nexport function parseSerializedPasskeySignature(signature: Uint8Array | string) {\n\tconst bytes = typeof signature === 'string' ? fromBase64(signature) : signature;\n\n\tif (bytes[0] !== SIGNATURE_SCHEME_TO_FLAG.Passkey) {\n\t\tthrow new Error('Invalid signature scheme');\n\t}\n\tconst dec = PasskeyAuthenticator.parse(bytes.slice(1));\n\treturn {\n\t\tsignatureScheme: 'Passkey' as const,\n\t\tserializedSignature: toBase64(bytes),\n\t\tsignature: bytes,\n\t\tauthenticatorData: dec.authenticatorData,\n\t\tclientDataJson: dec.clientDataJson,\n\t\tuserSignature: new Uint8Array(dec.userSignature),\n\t\tpublicKey: new Uint8Array(dec.userSignature.slice(1 + PASSKEY_SIGNATURE_SIZE)),\n\t};\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { fromBase64 } from "@mysten/bcs";
|
|
2
2
|
import { parseSerializedSignature, SIGNATURE_FLAG_TO_SCHEME } from "../cryptography/index.js";
|
|
3
3
|
import { Ed25519PublicKey } from "../keypairs/ed25519/publickey.js";
|
|
4
|
+
import { PasskeyPublicKey } from "../keypairs/passkey/publickey.js";
|
|
4
5
|
import { Secp256k1PublicKey } from "../keypairs/secp256k1/publickey.js";
|
|
5
6
|
import { Secp256r1PublicKey } from "../keypairs/secp256r1/publickey.js";
|
|
6
7
|
import { MultiSigPublicKey } from "../multisig/publickey.js";
|
|
@@ -62,6 +63,8 @@ function publicKeyFromRawBytes(signatureScheme, bytes, options = {}) {
|
|
|
62
63
|
return new MultiSigPublicKey(bytes);
|
|
63
64
|
case "ZkLogin":
|
|
64
65
|
return new ZkLoginPublicIdentifier(bytes, options);
|
|
66
|
+
case "Passkey":
|
|
67
|
+
return new PasskeyPublicKey(bytes);
|
|
65
68
|
default:
|
|
66
69
|
throw new Error(`Unsupported signature scheme ${signatureScheme}`);
|
|
67
70
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/verify/verify.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64 } from '@mysten/bcs';\n\nimport type { PublicKey, SignatureFlag, SignatureScheme } from '../cryptography/index.js';\nimport { parseSerializedSignature, SIGNATURE_FLAG_TO_SCHEME } from '../cryptography/index.js';\nimport type { SuiGraphQLClient } from '../graphql/client.js';\nimport { Ed25519PublicKey } from '../keypairs/ed25519/publickey.js';\nimport { Secp256k1PublicKey } from '../keypairs/secp256k1/publickey.js';\nimport { Secp256r1PublicKey } from '../keypairs/secp256r1/publickey.js';\n// eslint-disable-next-line import/no-cycle\nimport { MultiSigPublicKey } from '../multisig/publickey.js';\nimport { ZkLoginPublicIdentifier } from '../zklogin/publickey.js';\n\nexport async function verifySignature(bytes: Uint8Array, signature: string): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature);\n\n\tif (!(await parsedSignature.publicKey.verify(bytes, parsedSignature.serializedSignature))) {\n\t\tthrow new Error(`Signature is not valid for the provided data`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nexport async function verifyPersonalMessageSignature(\n\tmessage: Uint8Array,\n\tsignature: string,\n\toptions: { client?: SuiGraphQLClient } = {},\n): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature, options);\n\n\tif (\n\t\t!(await parsedSignature.publicKey.verifyPersonalMessage(\n\t\t\tmessage,\n\t\t\tparsedSignature.serializedSignature,\n\t\t))\n\t) {\n\t\tthrow new Error(`Signature is not valid for the provided message`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nexport async function verifyTransactionSignature(\n\ttransaction: Uint8Array,\n\tsignature: string,\n\toptions: { client?: SuiGraphQLClient } = {},\n): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature, options);\n\n\tif (\n\t\t!(await parsedSignature.publicKey.verifyTransaction(\n\t\t\ttransaction,\n\t\t\tparsedSignature.serializedSignature,\n\t\t))\n\t) {\n\t\tthrow new Error(`Signature is not valid for the provided Transaction`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nfunction parseSignature(signature: string, options: { client?: SuiGraphQLClient } = {}) {\n\tconst parsedSignature = parseSerializedSignature(signature);\n\n\tif (parsedSignature.signatureScheme === 'MultiSig') {\n\t\treturn {\n\t\t\t...parsedSignature,\n\t\t\tpublicKey: new MultiSigPublicKey(parsedSignature.multisig.multisig_pk),\n\t\t};\n\t}\n\n\tconst publicKey = publicKeyFromRawBytes(\n\t\tparsedSignature.signatureScheme,\n\t\tparsedSignature.publicKey,\n\t\toptions,\n\t);\n\treturn {\n\t\t...parsedSignature,\n\t\tpublicKey,\n\t};\n}\n\nexport function publicKeyFromRawBytes(\n\tsignatureScheme: SignatureScheme,\n\tbytes: Uint8Array,\n\toptions: { client?: SuiGraphQLClient } = {},\n): PublicKey {\n\tswitch (signatureScheme) {\n\t\tcase 'ED25519':\n\t\t\treturn new Ed25519PublicKey(bytes);\n\t\tcase 'Secp256k1':\n\t\t\treturn new Secp256k1PublicKey(bytes);\n\t\tcase 'Secp256r1':\n\t\t\treturn new Secp256r1PublicKey(bytes);\n\t\tcase 'MultiSig':\n\t\t\treturn new MultiSigPublicKey(bytes);\n\t\tcase 'ZkLogin':\n\t\t\treturn new ZkLoginPublicIdentifier(bytes, options);\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported signature scheme ${signatureScheme}`);\n\t}\n}\n\nexport function publicKeyFromSuiBytes(\n\tpublicKey: string | Uint8Array,\n\toptions: { client?: SuiGraphQLClient } = {},\n) {\n\tconst bytes = typeof publicKey === 'string' ? fromBase64(publicKey) : publicKey;\n\n\tconst signatureScheme = SIGNATURE_FLAG_TO_SCHEME[bytes[0] as SignatureFlag];\n\n\treturn publicKeyFromRawBytes(signatureScheme, bytes.slice(1), options);\n}\n"],
|
|
5
|
-
"mappings": "AAGA,SAAS,kBAAkB;AAG3B,SAAS,0BAA0B,gCAAgC;AAEnE,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AAEnC,SAAS,yBAAyB;AAClC,SAAS,+BAA+B;AAExC,eAAsB,gBAAgB,OAAmB,WAAuC;AAC/F,QAAM,kBAAkB,eAAe,SAAS;AAEhD,MAAI,CAAE,MAAM,gBAAgB,UAAU,OAAO,OAAO,gBAAgB,mBAAmB,GAAI;AAC1F,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAC/D;AAEA,SAAO,gBAAgB;AACxB;AAEA,eAAsB,+BACrB,SACA,WACA,UAAyC,CAAC,GACrB;AACrB,QAAM,kBAAkB,eAAe,WAAW,OAAO;AAEzD,MACC,CAAE,MAAM,gBAAgB,UAAU;AAAA,IACjC;AAAA,IACA,gBAAgB;AAAA,EACjB,GACC;AACD,UAAM,IAAI,MAAM,iDAAiD;AAAA,EAClE;AAEA,SAAO,gBAAgB;AACxB;AAEA,eAAsB,2BACrB,aACA,WACA,UAAyC,CAAC,GACrB;AACrB,QAAM,kBAAkB,eAAe,WAAW,OAAO;AAEzD,MACC,CAAE,MAAM,gBAAgB,UAAU;AAAA,IACjC;AAAA,IACA,gBAAgB;AAAA,EACjB,GACC;AACD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACtE;AAEA,SAAO,gBAAgB;AACxB;AAEA,SAAS,eAAe,WAAmB,UAAyC,CAAC,GAAG;AACvF,QAAM,kBAAkB,yBAAyB,SAAS;AAE1D,MAAI,gBAAgB,oBAAoB,YAAY;AACnD,WAAO;AAAA,MACN,GAAG;AAAA,MACH,WAAW,IAAI,kBAAkB,gBAAgB,SAAS,WAAW;AAAA,IACtE;AAAA,EACD;AAEA,QAAM,YAAY;AAAA,IACjB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB;AAAA,EACD;AACA,SAAO;AAAA,IACN,GAAG;AAAA,IACH;AAAA,EACD;AACD;AAEO,SAAS,sBACf,iBACA,OACA,UAAyC,CAAC,GAC9B;AACZ,UAAQ,iBAAiB;AAAA,IACxB,KAAK;AACJ,aAAO,IAAI,iBAAiB,KAAK;AAAA,IAClC,KAAK;AACJ,aAAO,IAAI,mBAAmB,KAAK;AAAA,IACpC,KAAK;AACJ,aAAO,IAAI,mBAAmB,KAAK;AAAA,IACpC,KAAK;AACJ,aAAO,IAAI,kBAAkB,KAAK;AAAA,IACnC,KAAK;AACJ,aAAO,IAAI,wBAAwB,OAAO,OAAO;AAAA,IAClD;AACC,YAAM,IAAI,MAAM,gCAAgC,eAAe,EAAE;AAAA,EACnE;AACD;AAEO,SAAS,sBACf,WACA,UAAyC,CAAC,GACzC;AACD,QAAM,QAAQ,OAAO,cAAc,WAAW,WAAW,SAAS,IAAI;AAEtE,QAAM,kBAAkB,yBAAyB,MAAM,CAAC,CAAkB;AAE1E,SAAO,sBAAsB,iBAAiB,MAAM,MAAM,CAAC,GAAG,OAAO;AACtE;",
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { fromBase64 } from '@mysten/bcs';\n\nimport type { PublicKey, SignatureFlag, SignatureScheme } from '../cryptography/index.js';\nimport { parseSerializedSignature, SIGNATURE_FLAG_TO_SCHEME } from '../cryptography/index.js';\nimport type { SuiGraphQLClient } from '../graphql/client.js';\nimport { Ed25519PublicKey } from '../keypairs/ed25519/publickey.js';\nimport { PasskeyPublicKey } from '../keypairs/passkey/publickey.js';\nimport { Secp256k1PublicKey } from '../keypairs/secp256k1/publickey.js';\nimport { Secp256r1PublicKey } from '../keypairs/secp256r1/publickey.js';\n// eslint-disable-next-line import/no-cycle\nimport { MultiSigPublicKey } from '../multisig/publickey.js';\nimport { ZkLoginPublicIdentifier } from '../zklogin/publickey.js';\n\nexport async function verifySignature(bytes: Uint8Array, signature: string): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature);\n\n\tif (!(await parsedSignature.publicKey.verify(bytes, parsedSignature.serializedSignature))) {\n\t\tthrow new Error(`Signature is not valid for the provided data`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nexport async function verifyPersonalMessageSignature(\n\tmessage: Uint8Array,\n\tsignature: string,\n\toptions: { client?: SuiGraphQLClient } = {},\n): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature, options);\n\n\tif (\n\t\t!(await parsedSignature.publicKey.verifyPersonalMessage(\n\t\t\tmessage,\n\t\t\tparsedSignature.serializedSignature,\n\t\t))\n\t) {\n\t\tthrow new Error(`Signature is not valid for the provided message`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nexport async function verifyTransactionSignature(\n\ttransaction: Uint8Array,\n\tsignature: string,\n\toptions: { client?: SuiGraphQLClient } = {},\n): Promise<PublicKey> {\n\tconst parsedSignature = parseSignature(signature, options);\n\n\tif (\n\t\t!(await parsedSignature.publicKey.verifyTransaction(\n\t\t\ttransaction,\n\t\t\tparsedSignature.serializedSignature,\n\t\t))\n\t) {\n\t\tthrow new Error(`Signature is not valid for the provided Transaction`);\n\t}\n\n\treturn parsedSignature.publicKey;\n}\n\nfunction parseSignature(signature: string, options: { client?: SuiGraphQLClient } = {}) {\n\tconst parsedSignature = parseSerializedSignature(signature);\n\n\tif (parsedSignature.signatureScheme === 'MultiSig') {\n\t\treturn {\n\t\t\t...parsedSignature,\n\t\t\tpublicKey: new MultiSigPublicKey(parsedSignature.multisig.multisig_pk),\n\t\t};\n\t}\n\n\tconst publicKey = publicKeyFromRawBytes(\n\t\tparsedSignature.signatureScheme,\n\t\tparsedSignature.publicKey,\n\t\toptions,\n\t);\n\treturn {\n\t\t...parsedSignature,\n\t\tpublicKey,\n\t};\n}\n\nexport function publicKeyFromRawBytes(\n\tsignatureScheme: SignatureScheme,\n\tbytes: Uint8Array,\n\toptions: { client?: SuiGraphQLClient } = {},\n): PublicKey {\n\tswitch (signatureScheme) {\n\t\tcase 'ED25519':\n\t\t\treturn new Ed25519PublicKey(bytes);\n\t\tcase 'Secp256k1':\n\t\t\treturn new Secp256k1PublicKey(bytes);\n\t\tcase 'Secp256r1':\n\t\t\treturn new Secp256r1PublicKey(bytes);\n\t\tcase 'MultiSig':\n\t\t\treturn new MultiSigPublicKey(bytes);\n\t\tcase 'ZkLogin':\n\t\t\treturn new ZkLoginPublicIdentifier(bytes, options);\n\t\tcase 'Passkey':\n\t\t\treturn new PasskeyPublicKey(bytes);\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported signature scheme ${signatureScheme}`);\n\t}\n}\n\nexport function publicKeyFromSuiBytes(\n\tpublicKey: string | Uint8Array,\n\toptions: { client?: SuiGraphQLClient } = {},\n) {\n\tconst bytes = typeof publicKey === 'string' ? fromBase64(publicKey) : publicKey;\n\n\tconst signatureScheme = SIGNATURE_FLAG_TO_SCHEME[bytes[0] as SignatureFlag];\n\n\treturn publicKeyFromRawBytes(signatureScheme, bytes.slice(1), options);\n}\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,kBAAkB;AAG3B,SAAS,0BAA0B,gCAAgC;AAEnE,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AACnC,SAAS,0BAA0B;AAEnC,SAAS,yBAAyB;AAClC,SAAS,+BAA+B;AAExC,eAAsB,gBAAgB,OAAmB,WAAuC;AAC/F,QAAM,kBAAkB,eAAe,SAAS;AAEhD,MAAI,CAAE,MAAM,gBAAgB,UAAU,OAAO,OAAO,gBAAgB,mBAAmB,GAAI;AAC1F,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAC/D;AAEA,SAAO,gBAAgB;AACxB;AAEA,eAAsB,+BACrB,SACA,WACA,UAAyC,CAAC,GACrB;AACrB,QAAM,kBAAkB,eAAe,WAAW,OAAO;AAEzD,MACC,CAAE,MAAM,gBAAgB,UAAU;AAAA,IACjC;AAAA,IACA,gBAAgB;AAAA,EACjB,GACC;AACD,UAAM,IAAI,MAAM,iDAAiD;AAAA,EAClE;AAEA,SAAO,gBAAgB;AACxB;AAEA,eAAsB,2BACrB,aACA,WACA,UAAyC,CAAC,GACrB;AACrB,QAAM,kBAAkB,eAAe,WAAW,OAAO;AAEzD,MACC,CAAE,MAAM,gBAAgB,UAAU;AAAA,IACjC;AAAA,IACA,gBAAgB;AAAA,EACjB,GACC;AACD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACtE;AAEA,SAAO,gBAAgB;AACxB;AAEA,SAAS,eAAe,WAAmB,UAAyC,CAAC,GAAG;AACvF,QAAM,kBAAkB,yBAAyB,SAAS;AAE1D,MAAI,gBAAgB,oBAAoB,YAAY;AACnD,WAAO;AAAA,MACN,GAAG;AAAA,MACH,WAAW,IAAI,kBAAkB,gBAAgB,SAAS,WAAW;AAAA,IACtE;AAAA,EACD;AAEA,QAAM,YAAY;AAAA,IACjB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB;AAAA,EACD;AACA,SAAO;AAAA,IACN,GAAG;AAAA,IACH;AAAA,EACD;AACD;AAEO,SAAS,sBACf,iBACA,OACA,UAAyC,CAAC,GAC9B;AACZ,UAAQ,iBAAiB;AAAA,IACxB,KAAK;AACJ,aAAO,IAAI,iBAAiB,KAAK;AAAA,IAClC,KAAK;AACJ,aAAO,IAAI,mBAAmB,KAAK;AAAA,IACpC,KAAK;AACJ,aAAO,IAAI,mBAAmB,KAAK;AAAA,IACpC,KAAK;AACJ,aAAO,IAAI,kBAAkB,KAAK;AAAA,IACnC,KAAK;AACJ,aAAO,IAAI,wBAAwB,OAAO,OAAO;AAAA,IAClD,KAAK;AACJ,aAAO,IAAI,iBAAiB,KAAK;AAAA,IAClC;AACC,YAAM,IAAI,MAAM,gCAAgC,eAAe,EAAE;AAAA,EACnE;AACD;AAEO,SAAS,sBACf,WACA,UAAyC,CAAC,GACzC;AACD,QAAM,QAAQ,OAAO,cAAc,WAAW,WAAW,SAAS,IAAI;AAEtE,QAAM,kBAAkB,yBAAyB,MAAM,CAAC,CAAkB;AAE1E,SAAO,sBAAsB,iBAAiB,MAAM,MAAM,CAAC,GAAG,OAAO;AACtE;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "1.
|
|
1
|
+
export declare const PACKAGE_VERSION = "1.17.0";
|
|
2
2
|
export declare const TARGETED_RPC_VERSION = "1.40.0";
|
package/dist/esm/version.js
CHANGED
package/dist/esm/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '1.
|
|
4
|
+
"sourcesContent": ["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\n// This file is generated by genversion.mjs. Do not edit it directly.\n\nexport const PACKAGE_VERSION = '1.17.0';\nexport const TARGETED_RPC_VERSION = '1.40.0';\n"],
|
|
5
5
|
"mappings": "AAKO,MAAM,kBAAkB;AACxB,MAAM,uBAAuB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|