@owlmeans/basic-keys 0.1.18-rc.46 → 0.1.18-rc.48

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.
Files changed (55) hide show
  1. package/README.md +12 -12
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/basic-keys/SKILL.md +13 -13
  4. package/build/auth/types.d.ts +10 -0
  5. package/build/auth/types.d.ts.map +1 -0
  6. package/build/auth/types.js +2 -0
  7. package/build/auth/types.js.map +1 -0
  8. package/build/auth.d.ts +3 -4
  9. package/build/auth.d.ts.map +1 -1
  10. package/build/auth.js +43 -39
  11. package/build/auth.js.map +1 -1
  12. package/build/helper/types.d.ts +11 -0
  13. package/build/helper/types.d.ts.map +1 -0
  14. package/build/helper/types.js +2 -0
  15. package/build/helper/types.js.map +1 -0
  16. package/build/helper.d.ts +4 -1
  17. package/build/helper.d.ts.map +1 -1
  18. package/build/helper.js +21 -15
  19. package/build/helper.js.map +1 -1
  20. package/build/index.d.ts +2 -0
  21. package/build/index.d.ts.map +1 -1
  22. package/build/index.js.map +1 -1
  23. package/build/keypair.js +2 -2
  24. package/build/keypair.js.map +1 -1
  25. package/build/model.d.ts +2 -2
  26. package/build/model.d.ts.map +1 -1
  27. package/build/model.js +16 -16
  28. package/build/model.js.map +1 -1
  29. package/build/plugins/ed25519.js +3 -3
  30. package/build/plugins/ed25519.js.map +1 -1
  31. package/build/plugins/xchacha.js +2 -2
  32. package/build/plugins/xchacha.js.map +1 -1
  33. package/build/utils/types.d.ts +16 -0
  34. package/build/utils/types.d.ts.map +1 -0
  35. package/build/utils/types.js +2 -0
  36. package/build/utils/types.js.map +1 -0
  37. package/build/utils.d.ts +3 -4
  38. package/build/utils.d.ts.map +1 -1
  39. package/build/utils.js +26 -22
  40. package/build/utils.js.map +1 -1
  41. package/package.json +9 -9
  42. package/src/auth/types.ts +17 -0
  43. package/src/auth.ts +51 -44
  44. package/src/helper/types.ts +11 -0
  45. package/src/helper.ts +26 -16
  46. package/src/index.ts +2 -0
  47. package/src/keypair.ts +2 -2
  48. package/src/model.ts +17 -17
  49. package/src/plugins/ed25519.ts +3 -3
  50. package/src/plugins/xchacha.ts +2 -2
  51. package/src/utils/types.ts +15 -0
  52. package/src/utils.ts +28 -21
  53. package/tests/auth.spec.ts +5 -5
  54. package/tests/keys.spec.ts +3 -3
  55. package/tests/known-answers.spec.ts +68 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":""}
package/build/utils.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- export declare const toAddress: (publicKey: Uint8Array) => Uint8Array;
2
- export declare const prepareKey: (key: string) => Uint8Array;
3
- export declare const prepareData: (data: unknown) => Uint8Array;
4
- export declare const assertType: (type?: string) => void;
1
+ import type { KeyUtils } from './utils/types.js';
2
+ export declare const createKeyUtils: () => KeyUtils;
3
+ export declare const keyUtils: KeyUtils;
5
4
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,SAAS,cAAe,UAAU,KAAG,UACP,CAAA;AAE3C,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,UACrB,CAAA;AAEpB,eAAO,MAAM,WAAW,SAAU,OAAO,KAAG,UAiB3C,CAAA;AAED,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,IAI1C,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEhD,eAAO,MAAM,cAAc,QAAO,QAiCjC,CAAA;AAED,eAAO,MAAM,QAAQ,UAAmB,CAAA"}
package/build/utils.js CHANGED
@@ -1,29 +1,33 @@
1
- import { keccak_256 } from '@noble/hashes/sha3';
1
+ import { keccak_256 } from '@noble/hashes/sha3.js';
2
2
  import { base64, utf8 } from '@scure/base';
3
3
  import { plugins } from './plugins/index.js';
4
4
  import canonicalize from 'canonicalize';
5
- export const toAddress = (publicKey) => keccak_256(publicKey.slice(4)).slice(-20);
6
- export const prepareKey = (key) => base64.decode(key);
7
- export const prepareData = (data) => {
8
- if (typeof data === 'object') {
5
+ export const createKeyUtils = () => {
6
+ const toAddress = (publicKey) => keccak_256(publicKey.slice(4)).slice(-20);
7
+ const prepareKey = (key) => base64.decode(key);
8
+ const prepareData = (data) => {
9
+ if (typeof data === 'object') {
10
+ if (!(data instanceof Uint8Array)) {
11
+ data = canonicalize(data);
12
+ }
13
+ }
14
+ if (typeof data === 'string') {
15
+ data = utf8.decode(data);
16
+ }
17
+ else if (!(data instanceof Uint8Array)) {
18
+ throw new Error('basic.keys:sign-data-type');
19
+ }
9
20
  if (!(data instanceof Uint8Array)) {
10
- data = canonicalize(data);
21
+ throw new Error('basic.keys:sign-data-type');
11
22
  }
12
- }
13
- if (typeof data === 'string') {
14
- data = utf8.decode(data);
15
- }
16
- else if (!(data instanceof Uint8Array)) {
17
- throw new Error('basic.keys:sign-data-type');
18
- }
19
- if (!(data instanceof Uint8Array)) {
20
- throw new Error('basic.keys:sign-data-type');
21
- }
22
- return data;
23
- };
24
- export const assertType = (type) => {
25
- if (type == null || !(type in plugins)) {
26
- throw new Error('basic.keys:unknown-type');
27
- }
23
+ return data;
24
+ };
25
+ const assertType = (type) => {
26
+ if (type == null || !(type in plugins)) {
27
+ throw new Error('basic.keys:unknown-type');
28
+ }
29
+ };
30
+ return { toAddress, prepareKey, prepareData, assertType };
28
31
  };
32
+ export const keyUtils = createKeyUtils();
29
33
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,YAAY,MAAM,cAAc,CAAA;AAEvC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,SAAqB,EAAc,EAAE,CAC7D,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;AAE3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE,CACpD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AAEpB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAa,EAAc,EAAE;IACvD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;YAClC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC;SAAM,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAC9C,CAAC;IAED,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAC9C,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAa,EAAQ,EAAE;IAChD,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,YAAY,MAAM,cAAc,CAAA;AAGvC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAa,EAAE;IAC3C,MAAM,SAAS,GAAG,CAAC,SAAqB,EAAc,EAAE,CACtD,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;IAE3C,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE,CAC7C,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAEpB,MAAM,WAAW,GAAG,CAAC,IAAa,EAAc,EAAE;QAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;gBAClC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1B,CAAC;aAAM,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC9C,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC9C,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,MAAM,UAAU,GAAG,CAAC,IAAa,EAAQ,EAAE;QACzC,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC,CAAA;IAED,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,CAAA;AAC3D,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/basic-keys",
3
- "version": "0.1.18-rc.46",
3
+ "version": "0.1.18-rc.48",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -40,18 +40,18 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@owlmeans/dep-config": "workspace:*",
43
- "@owlmeans/test-auth": "^0.1.18-rc.44",
44
- "@types/bun": "^1.4.0",
43
+ "@owlmeans/test-auth": "^0.1.18-rc.46",
44
+ "@types/bun": "^1.4.2",
45
45
  "nodemon": "^3.1.14",
46
46
  "typescript": "^7.0.2"
47
47
  },
48
48
  "dependencies": {
49
- "@noble/ciphers": "^1.2.1",
50
- "@noble/curves": "^1.6.0",
51
- "@noble/hashes": "^1.5.0",
52
- "@owlmeans/auth": "^0.1.18-rc.38",
53
- "@scure/base": "^2.3.0",
54
- "canonicalize": "^2.0.0"
49
+ "@noble/ciphers": "^2.4.0",
50
+ "@noble/curves": "^2.4.0",
51
+ "@noble/hashes": "^2.4.0",
52
+ "@owlmeans/auth": "^0.1.18-rc.40",
53
+ "@scure/base": "^2.4.0",
54
+ "canonicalize": "^5.1.0"
55
55
  },
56
56
  "publishConfig": {
57
57
  "access": "public"
@@ -0,0 +1,17 @@
1
+ import type { AuthCredentials } from '@owlmeans/auth'
2
+ import type { KeyPairModel, PayloadSigner, PayloadVerifier, UnpackedAuthCredentials, UnsignedAuthCredentials } from '../types.js'
3
+
4
+ /** Signed authentication credentials: the signature packed into `credential` with any extras. */
5
+ export interface AuthCredentialsHelper {
6
+ /** Sign `auth` (plus canonicalized `extra`) and pack the signature into `credential`. */
7
+ packAuthCredentials: <T extends {} | undefined>(
8
+ auth: UnsignedAuthCredentials,
9
+ extra: T,
10
+ signer: KeyPairModel | PayloadSigner
11
+ ) => Promise<AuthCredentials>
12
+ /** Take packed credentials apart and, given a verifier, check the signature. */
13
+ unpackAuthCredentials: <T extends {} | undefined>(
14
+ auth: AuthCredentials,
15
+ verifier?: KeyPairModel | PayloadVerifier
16
+ ) => Promise<UnpackedAuthCredentials<T>>
17
+ }
package/src/auth.ts CHANGED
@@ -1,60 +1,67 @@
1
1
  import type { AuthCredentials } from '@owlmeans/auth'
2
2
  import type { KeyPairModel, PayloadSigner, PayloadVerifier, UnpackedAuthCredentials, UnsignedAuthCredentials } from './types.js'
3
3
  import canonicalize from 'canonicalize'
4
+ import type { AuthCredentialsHelper } from './auth/types.js'
4
5
 
5
- export const packAuthCredentials = async <T extends {} | undefined>(
6
- auth: UnsignedAuthCredentials,
7
- extra: T,
8
- signer: KeyPairModel | PayloadSigner
9
- ): Promise<AuthCredentials> => {
10
- const unsigned: UnsignedAuthCredentials = {
11
- ...auth,
12
- ...(extra == null ? {} : { credential: canonicalize(extra) as string })
13
- }
6
+ export const createAuthCredentialsHelper = (): AuthCredentialsHelper => {
7
+ const packAuthCredentials = async <T extends {} | undefined>(
8
+ auth: UnsignedAuthCredentials,
9
+ extra: T,
10
+ signer: KeyPairModel | PayloadSigner
11
+ ): Promise<AuthCredentials> => {
12
+ const unsigned: UnsignedAuthCredentials = {
13
+ ...auth,
14
+ ...(extra == null ? {} : { credential: canonicalize(extra) as string })
15
+ }
14
16
 
15
- if (typeof signer !== 'function') {
16
- const _signer = signer
17
- signer = async payload => await _signer.sign(payload)
18
- }
17
+ if (typeof signer !== 'function') {
18
+ const _signer = signer
19
+ signer = async payload => await _signer.sign(payload)
20
+ }
19
21
 
20
- const signature = await signer(unsigned)
22
+ const signature = await signer(unsigned)
21
23
 
22
- return {
23
- ...auth,
24
- credential: extra == null ? signature : canonicalize({ ...extra, signature }) as string,
24
+ return {
25
+ ...auth,
26
+ credential: extra == null ? signature : canonicalize({ ...extra, signature }) as string,
27
+ }
25
28
  }
26
- }
27
29
 
28
- export const unpackAuthCredentials = async <T extends {} | undefined>(
29
- auth: AuthCredentials,
30
- verifier?: KeyPairModel | PayloadVerifier
31
- ): Promise<UnpackedAuthCredentials<T>> => {
32
- let signature: string = ''
33
- let extras: T
34
- try {
35
- extras = JSON.parse(auth.credential)
36
- if (typeof extras === 'object' && extras != null && "signature" in extras) {
37
- signature = extras.signature as string
38
- delete extras.signature
30
+ const unpackAuthCredentials = async <T extends {} | undefined>(
31
+ auth: AuthCredentials,
32
+ verifier?: KeyPairModel | PayloadVerifier
33
+ ): Promise<UnpackedAuthCredentials<T>> => {
34
+ let signature: string = ''
35
+ let extras: T
36
+ try {
37
+ extras = JSON.parse(auth.credential)
38
+ if (typeof extras === 'object' && extras != null && "signature" in extras) {
39
+ signature = extras.signature as string
40
+ delete extras.signature
41
+ }
42
+ } catch {
43
+ signature = auth.credential
44
+ extras = undefined as T
39
45
  }
40
- } catch {
41
- signature = auth.credential
42
- extras = undefined as T
43
- }
44
- const unsigned: UnsignedAuthCredentials = {
45
- ...auth,
46
- ...(extras == null ? {} : { credential: canonicalize(extras) as string })
47
- }
48
- let isValid: boolean | undefined = undefined
46
+ const unsigned: UnsignedAuthCredentials = {
47
+ ...auth,
48
+ ...(extras == null ? {} : { credential: canonicalize(extras) as string })
49
+ }
50
+ let isValid: boolean | undefined = undefined
49
51
 
50
- if (verifier != null) {
51
- if (typeof verifier !== 'function') {
52
- const _verifier = verifier
53
- verifier = async (payload, signature) => await _verifier.verify(payload, signature)
52
+ if (verifier != null) {
53
+ if (typeof verifier !== 'function') {
54
+ const _verifier = verifier
55
+ verifier = async (payload, signature) => await _verifier.verify(payload, signature)
56
+ }
57
+
58
+ isValid = await verifier(unsigned, signature)
54
59
  }
55
60
 
56
- isValid = await verifier(unsigned, signature)
61
+ return { unsigned, signature, isValid, extras }
57
62
  }
58
63
 
59
- return { unsigned, signature, isValid, extras }
64
+ return { packAuthCredentials, unpackAuthCredentials }
60
65
  }
66
+
67
+ export const authCredentialsHelper = createAuthCredentialsHelper()
@@ -0,0 +1,11 @@
1
+ import type { KeyPairModel } from '../types.js'
2
+
3
+ /** Key models built from what a peer publishes: its public key and its address. */
4
+ export interface KeyHelper {
5
+ /**
6
+ * A verify-only key model of a public key, `<type>:<key>` or a bare key (ed25519 by default).
7
+ */
8
+ fromPubKey: (pubKey: string, type?: string) => KeyPairModel
9
+ /** Whether an address is the one the public key derives to. */
10
+ matchAddress: (address: string, pubKey: string) => boolean
11
+ }
package/src/helper.ts CHANGED
@@ -2,26 +2,36 @@ import { KeyType } from './consts.js'
2
2
  import { makeKeyPairModel } from './model.js'
3
3
  import { plugins } from './plugins/index.js'
4
4
  import type { KeyPair, KeyPairModel } from './types.js'
5
- import { prepareKey } from './utils.js'
5
+ import { keyUtils } from './utils.js'
6
+ import type { KeyHelper } from './helper/types.js'
6
7
 
7
- export const fromPubKey = (pubKey: string, type?: string): KeyPairModel => {
8
- if (type == null) {
9
- [type, pubKey] = pubKey.includes(':') ? pubKey.split(':', 2) : [KeyType.ED25519, pubKey]
10
- if (pubKey == null) {
11
- pubKey = type
12
- type = KeyType.ED25519
8
+ export const createKeyHelper = (): KeyHelper => {
9
+ const fromPubKey = (pubKey: string, type?: string): KeyPairModel => {
10
+ if (type == null) {
11
+ [type, pubKey] = pubKey.includes(':') ? pubKey.split(':', 2) : [KeyType.ED25519, pubKey]
12
+ if (pubKey == null) {
13
+ pubKey = type
14
+ type = KeyType.ED25519
15
+ }
16
+ }
17
+
18
+ const keyPair: KeyPair = {
19
+ privateKey: '',
20
+ publicKey: pubKey,
21
+ type,
22
+ address: plugins[type].toAdress(keyUtils.prepareKey(pubKey))
13
23
  }
14
- }
15
24
 
16
- const keyPair: KeyPair = {
17
- privateKey: '',
18
- publicKey: pubKey,
19
- type,
20
- address: plugins[type].toAdress(prepareKey(pubKey))
25
+ return makeKeyPairModel(keyPair)
21
26
  }
22
27
 
23
- return makeKeyPairModel(keyPair)
28
+ const matchAddress = (address: string, pubKey: string): boolean =>
29
+ address === fromPubKey(pubKey).exportAddress()
30
+
31
+ return { fromPubKey, matchAddress }
24
32
  }
25
33
 
26
- export const matchAddress = (address: string, pubKey: string): boolean =>
27
- address === fromPubKey(pubKey).exportAddress()
34
+ export const keyHelper = createKeyHelper()
35
+
36
+ /** @deprecated compat:factory-refactor — use `keyHelper.fromPubKey(…)` */
37
+ export const fromPubKey = (pubKey: string, type?: string): KeyPairModel => keyHelper.fromPubKey(pubKey, type)
package/src/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export type * from './types.js'
2
+ export type * from './helper/types.js'
3
+ export type * from './auth/types.js'
2
4
 
3
5
  export * from './consts.js'
4
6
  export * from './helper.js'
package/src/keypair.ts CHANGED
@@ -2,7 +2,7 @@ import type { KeyPair } from './types.js'
2
2
  import { base64 } from '@scure/base'
3
3
  import { KeyType } from './consts.js'
4
4
  import { plugins } from './plugins/index.js'
5
- import { assertType } from './utils.js'
5
+ import { keyUtils } from './utils.js'
6
6
 
7
7
  export const inputToKeyPair = (input?: KeyPair | string): KeyPair => {
8
8
  let type: string = KeyType.ED25519
@@ -27,7 +27,7 @@ export const inputToKeyPair = (input?: KeyPair | string): KeyPair => {
27
27
  }
28
28
  }
29
29
  if (keyPair == null) {
30
- assertType(type)
30
+ keyUtils.assertType(type)
31
31
  if (primaryKey == null) {
32
32
  primaryKey = plugins[type].random()
33
33
  }
package/src/model.ts CHANGED
@@ -1,18 +1,18 @@
1
- import type { KeyPairModel, KeyPairModelMaker } from './types.js'
1
+ import type { KeyPair, KeyPairModel } from './types.js'
2
2
  import { plugins } from './plugins/index.js'
3
3
  import { base64urlnopad, utf8 } from '@scure/base'
4
- import { assertType, prepareData, prepareKey } from './utils.js'
4
+ import { keyUtils } from './utils.js'
5
5
  import { inputToKeyPair } from './keypair.js'
6
6
 
7
- export const makeKeyPairModel: KeyPairModelMaker = input => {
7
+ export const makeKeyPairModel = (input?: KeyPair | string): KeyPairModel => {
8
8
  const keyPair = inputToKeyPair(input)
9
9
 
10
10
  const _model: KeyPairModel = {
11
11
  keyPair,
12
12
 
13
13
  sign: async (data) => {
14
- data = prepareData(data)
15
- assertType(_model.keyPair?.type)
14
+ data = keyUtils.prepareData(data)
15
+ keyUtils.assertType(_model.keyPair?.type)
16
16
 
17
17
  if (_model.keyPair == null) {
18
18
  throw new Error('basic.keys:missing-keypair')
@@ -25,14 +25,14 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
25
25
  return base64urlnopad.encode(
26
26
  plugins[_model.keyPair.type].sign(
27
27
  data as Uint8Array,
28
- prepareKey(_model.keyPair.privateKey)
28
+ keyUtils.prepareKey(_model.keyPair.privateKey)
29
29
  )
30
30
  )
31
31
  },
32
32
 
33
33
  verify: async (data, signature) => {
34
- data = prepareData(data)
35
- assertType(_model.keyPair?.type)
34
+ data = keyUtils.prepareData(data)
35
+ keyUtils.assertType(_model.keyPair?.type)
36
36
  const sig = base64urlnopad.decode(signature)
37
37
 
38
38
  if (_model.keyPair == null) {
@@ -42,12 +42,12 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
42
42
  return plugins[_model.keyPair.type].verify(
43
43
  data as Uint8Array,
44
44
  sig,
45
- prepareKey(_model.keyPair.publicKey)
45
+ keyUtils.prepareKey(_model.keyPair.publicKey)
46
46
  )
47
47
  },
48
48
 
49
49
  export: () => {
50
- assertType(_model.keyPair?.type)
50
+ keyUtils.assertType(_model.keyPair?.type)
51
51
 
52
52
  if (_model.keyPair == null) {
53
53
  throw new Error('basic.keys:missing-keypair')
@@ -57,7 +57,7 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
57
57
  },
58
58
 
59
59
  exportPublic: () => {
60
- assertType(_model.keyPair?.type)
60
+ keyUtils.assertType(_model.keyPair?.type)
61
61
 
62
62
  if (_model.keyPair == null) {
63
63
  throw new Error('basic.keys:missing-keypair')
@@ -67,7 +67,7 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
67
67
  },
68
68
 
69
69
  exportAddress: () => {
70
- assertType(_model.keyPair?.type)
70
+ keyUtils.assertType(_model.keyPair?.type)
71
71
 
72
72
  if (_model.keyPair == null) {
73
73
  throw new Error('basic.keys:missing-keypair')
@@ -77,8 +77,8 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
77
77
  },
78
78
 
79
79
  encrypt: async data => {
80
- data = prepareData(data)
81
- assertType(_model.keyPair?.type)
80
+ data = keyUtils.prepareData(data)
81
+ keyUtils.assertType(_model.keyPair?.type)
82
82
 
83
83
  if (_model.keyPair == null) {
84
84
  throw new Error('basic.keys:missing-keypair')
@@ -87,7 +87,7 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
87
87
  return base64urlnopad.encode(
88
88
  plugins[_model.keyPair.type].encrypt(
89
89
  data as Uint8Array,
90
- prepareKey(_model.keyPair.publicKey)
90
+ keyUtils.prepareKey(_model.keyPair.publicKey)
91
91
  )
92
92
  )
93
93
  },
@@ -105,7 +105,7 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
105
105
 
106
106
  dcrpt: async data => {
107
107
  data = data instanceof Uint8Array ? data : base64urlnopad.decode(data as string)
108
- assertType(_model.keyPair?.type)
108
+ keyUtils.assertType(_model.keyPair?.type)
109
109
 
110
110
  if (_model.keyPair == null) {
111
111
  throw new Error('basic.keys:missing-keypair')
@@ -113,7 +113,7 @@ export const makeKeyPairModel: KeyPairModelMaker = input => {
113
113
 
114
114
  return plugins[_model.keyPair.type].decrypt(
115
115
  data as Uint8Array,
116
- prepareKey(_model.keyPair.privateKey)
116
+ keyUtils.prepareKey(_model.keyPair.privateKey)
117
117
  )
118
118
  }
119
119
  }
@@ -1,13 +1,13 @@
1
1
  import { KeyType } from '../consts.js'
2
2
  import type { KeyPlugin } from './types.js'
3
- import { ed25519 } from '@noble/curves/ed25519'
3
+ import { ed25519 } from '@noble/curves/ed25519.js'
4
4
  import { base58 } from '@scure/base'
5
- import { keccak_256 } from '@noble/hashes/sha3'
5
+ import { keccak_256 } from '@noble/hashes/sha3.js'
6
6
 
7
7
  export const ed25519Plugin: KeyPlugin = {
8
8
  type: KeyType.ED25519,
9
9
 
10
- random: () => ed25519.utils.randomPrivateKey(),
10
+ random: () => ed25519.utils.randomSecretKey(),
11
11
 
12
12
  sign: (data, pk) => ed25519.sign(data, pk),
13
13
 
@@ -1,7 +1,7 @@
1
1
  import { KeyType } from '../consts.js'
2
2
  import type { KeyPlugin } from './types.js'
3
- import { xchacha20poly1305 } from '@noble/ciphers/chacha'
4
- import { randomBytes, managedNonce } from '@noble/ciphers/webcrypto'
3
+ import { xchacha20poly1305 } from '@noble/ciphers/chacha.js'
4
+ import { randomBytes, managedNonce } from '@noble/ciphers/utils.js'
5
5
 
6
6
 
7
7
  export const xChahaPlugin: KeyPlugin = {
@@ -0,0 +1,15 @@
1
+ /** The low-level key and payload primitives the key models and plugins share. */
2
+ export interface KeyUtils {
3
+ /** The 20-byte address of a public key: the tail of its keccak-256 digest. */
4
+ toAddress: (publicKey: Uint8Array) => Uint8Array
5
+ /** A base64-encoded key as bytes. */
6
+ prepareKey: (key: string) => Uint8Array
7
+ /**
8
+ * Bytes to sign, verify or encrypt: an object is canonicalized, a string UTF-8 encoded.
9
+ *
10
+ * @throws {Error} `basic.keys:sign-data-type` for anything else
11
+ */
12
+ prepareData: (data: unknown) => Uint8Array
13
+ /** @throws {Error} `basic.keys:unknown-type` for a key type no plugin is registered for */
14
+ assertType: (type?: string) => void
15
+ }
package/src/utils.ts CHANGED
@@ -1,35 +1,42 @@
1
- import { keccak_256 } from '@noble/hashes/sha3'
1
+ import { keccak_256 } from '@noble/hashes/sha3.js'
2
2
  import { base64, utf8 } from '@scure/base'
3
3
  import { plugins } from './plugins/index.js'
4
4
  import canonicalize from 'canonicalize'
5
+ import type { KeyUtils } from './utils/types.js'
5
6
 
6
- export const toAddress = (publicKey: Uint8Array): Uint8Array =>
7
- keccak_256(publicKey.slice(4)).slice(-20)
7
+ export const createKeyUtils = (): KeyUtils => {
8
+ const toAddress = (publicKey: Uint8Array): Uint8Array =>
9
+ keccak_256(publicKey.slice(4)).slice(-20)
8
10
 
9
- export const prepareKey = (key: string): Uint8Array =>
10
- base64.decode(key)
11
+ const prepareKey = (key: string): Uint8Array =>
12
+ base64.decode(key)
13
+
14
+ const prepareData = (data: unknown): Uint8Array => {
15
+ if (typeof data === 'object') {
16
+ if (!(data instanceof Uint8Array)) {
17
+ data = canonicalize(data)
18
+ }
19
+ }
20
+ if (typeof data === 'string') {
21
+ data = utf8.decode(data)
22
+ } else if (!(data instanceof Uint8Array)) {
23
+ throw new Error('basic.keys:sign-data-type')
24
+ }
11
25
 
12
- export const prepareData = (data: unknown): Uint8Array => {
13
- if (typeof data === 'object') {
14
26
  if (!(data instanceof Uint8Array)) {
15
- data = canonicalize(data)
27
+ throw new Error('basic.keys:sign-data-type')
16
28
  }
17
- }
18
- if (typeof data === 'string') {
19
- data = utf8.decode(data)
20
- } else if (!(data instanceof Uint8Array)) {
21
- throw new Error('basic.keys:sign-data-type')
29
+
30
+ return data
22
31
  }
23
32
 
24
- if (!(data instanceof Uint8Array)) {
25
- throw new Error('basic.keys:sign-data-type')
33
+ const assertType = (type?: string): void => {
34
+ if (type == null || !(type in plugins)) {
35
+ throw new Error('basic.keys:unknown-type')
36
+ }
26
37
  }
27
38
 
28
- return data
39
+ return { toAddress, prepareKey, prepareData, assertType }
29
40
  }
30
41
 
31
- export const assertType = (type?: string): void => {
32
- if (type == null || !(type in plugins)) {
33
- throw new Error('basic.keys:unknown-type')
34
- }
35
- }
42
+ export const keyUtils = createKeyUtils()
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
- import { packAuthCredentials, unpackAuthCredentials } from '@owlmeans/basic-keys'
2
+ import { authCredentialsHelper } from '@owlmeans/basic-keys'
3
3
  import { AuthRole, AuthenticationType } from '@owlmeans/auth'
4
4
  import type { AuthCredentials } from '@owlmeans/auth'
5
5
  import { fixtureKey } from './context.js'
@@ -15,8 +15,8 @@ const baseCreds = (): Omit<AuthCredentials, 'credential'> => ({
15
15
  describe('@owlmeans/basic-keys — packAuthCredentials round-trip', () => {
16
16
  test('signs and verifies credentials with extras attached', async () => {
17
17
  const key = fixtureKey()
18
- const signed = await packAuthCredentials(baseCreds(), { nonce: 'n-1' }, key)
19
- const result = await unpackAuthCredentials<{ nonce: string }>(signed, key)
18
+ const signed = await authCredentialsHelper.packAuthCredentials(baseCreds(), { nonce: 'n-1' }, key)
19
+ const result = await authCredentialsHelper.unpackAuthCredentials<{ nonce: string }>(signed, key)
20
20
  expect(result.isValid).toBe(true)
21
21
  expect(result.extras?.nonce).toBe('n-1')
22
22
  })
@@ -24,8 +24,8 @@ describe('@owlmeans/basic-keys — packAuthCredentials round-trip', () => {
24
24
  test('verification fails for a different keypair', async () => {
25
25
  const signing = fixtureKey('alice')
26
26
  const other = fixtureKey('bob')
27
- const signed = await packAuthCredentials(baseCreds(), { nonce: 'n-1' }, signing)
28
- const result = await unpackAuthCredentials(signed, other)
27
+ const signed = await authCredentialsHelper.packAuthCredentials(baseCreds(), { nonce: 'n-1' }, signing)
28
+ const result = await authCredentialsHelper.unpackAuthCredentials(signed, other)
29
29
  expect(result.isValid).toBe(false)
30
30
  })
31
31
  })
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
- import { fromPubKey, makeKeyPairModel, matchAddress } from '@owlmeans/basic-keys'
2
+ import { keyHelper, makeKeyPairModel } from '@owlmeans/basic-keys'
3
3
  import { fixtureKey } from './context.js'
4
4
 
5
5
  describe('@owlmeans/basic-keys — KeyPairModel sign/verify', () => {
@@ -26,13 +26,13 @@ describe('@owlmeans/basic-keys — public-key-only verification (fromPubKey)', (
26
26
  const signing = fixtureKey('peer-keys-spec')
27
27
  const sig = await signing.sign({ event: 'check' })
28
28
 
29
- const verifying = fromPubKey(signing.exportPublic())
29
+ const verifying = keyHelper.fromPubKey(signing.exportPublic())
30
30
  expect(await verifying.verify({ event: 'check' }, sig)).toBe(true)
31
31
  })
32
32
 
33
33
  test('matchAddress agrees with exportAddress() on the same keypair', () => {
34
34
  const key = fixtureKey('addr-spec')
35
- expect(matchAddress(key.exportAddress(), key.exportPublic())).toBe(true)
35
+ expect(keyHelper.matchAddress(key.exportAddress(), key.exportPublic())).toBe(true)
36
36
  })
37
37
 
38
38
  test('export() round-trips into a new model that produces the same public key', async () => {