@novasamatech/host-papp 0.5.1 → 0.5.3-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/dist/crypto.d.ts CHANGED
@@ -11,11 +11,6 @@ export declare const SsPubKey: Codec<SsPublicKey>;
11
11
  export declare const EncrPubKey: Codec<EncrPublicKey>;
12
12
  export declare function stringToBytes(str: string): Uint8Array<ArrayBuffer>;
13
13
  export declare function bytesToString(bytes: Uint8Array): string;
14
- export declare function createSsSecret(entropy: Uint8Array): SsSecret;
15
- export declare function createSsDerivation(secret: SsSecret, derivation: string): SsSecret;
16
- export declare function getSsPub(secret: SsSecret): SsPublicKey;
17
- export declare function signWithSsSecret(secret: SsSecret, message: Uint8Array): Uint8Array<ArrayBufferLike>;
18
- export declare function verifyWithSsSecret(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
19
14
  export type DerivedSr25519Account = {
20
15
  secret: SsSecret;
21
16
  publicKey: SsPublicKey;
package/dist/crypto.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { p256 } from '@noble/curves/nist.js';
2
+ import { createSr25519Secret, deriveSr25519PublicKey, signWithSr25519Secret, verifySr25519Signature, } from '@novasamatech/statement-store';
2
3
  import { entropyToMiniSecret, mnemonicToEntropy } from '@polkadot-labs/hdkd-helpers';
3
- import { HDKD as sr25519HDKD, getPublicKey as sr25519GetPublicKey, secretFromSeed as sr25519SecretFromSeed, sign as sr25519Sign, verify as sr25519Verify, } from '@scure/sr25519';
4
- import { Bytes, str } from 'scale-ts';
4
+ import { Bytes } from 'scale-ts';
5
5
  // schemas
6
6
  export function BrandedBytesCodec(length) {
7
7
  return Bytes(length);
@@ -17,57 +17,16 @@ export function stringToBytes(str) {
17
17
  export function bytesToString(bytes) {
18
18
  return textDecoder.decode(bytes);
19
19
  }
20
- function parseDerivations(derivationsStr) {
21
- const DERIVATION_RE = /(\/{1,2})([^/]+)/g;
22
- const derivations = [];
23
- for (const [, type, code] of derivationsStr.matchAll(DERIVATION_RE)) {
24
- if (code) {
25
- derivations.push([type === '//' ? 'hard' : 'soft', code]);
26
- }
27
- }
28
- return derivations;
29
- }
30
- function createChainCode(derivation) {
31
- const chainCode = new Uint8Array(32);
32
- chainCode.set(str.enc(derivation));
33
- return chainCode;
34
- }
35
- // statement store key pair
36
- export function createSsSecret(entropy) {
37
- const miniSecret = entropyToMiniSecret(entropy);
38
- return sr25519SecretFromSeed(miniSecret);
39
- }
40
- export function createSsDerivation(secret, derivation) {
41
- const derivations = parseDerivations(derivation);
42
- return derivations.reduce((secret, [type, derivation]) => {
43
- const chainCode = createChainCode(derivation);
44
- switch (type) {
45
- case 'hard':
46
- return sr25519HDKD.secretHard(secret, chainCode);
47
- case 'soft':
48
- return sr25519HDKD.secretSoft(secret, chainCode);
49
- }
50
- }, secret);
51
- }
52
- export function getSsPub(secret) {
53
- return sr25519GetPublicKey(secret);
54
- }
55
- export function signWithSsSecret(secret, message) {
56
- return sr25519Sign(secret, message);
57
- }
58
- export function verifyWithSsSecret(message, signature, publicKey) {
59
- return sr25519Verify(message, signature, publicKey);
60
- }
61
20
  export function deriveSr25519Account(mnemonic, derivation) {
62
21
  const entropy = mnemonicToEntropy(mnemonic);
63
- const secret = createSsDerivation(createSsSecret(entropy), derivation);
64
- const publicKey = getSsPub(secret);
22
+ const secret = createSr25519Secret(entropy, derivation);
23
+ const publicKey = deriveSr25519PublicKey(secret);
65
24
  return {
66
25
  secret,
67
26
  publicKey,
68
27
  entropy,
69
- sign: message => signWithSsSecret(secret, message),
70
- verify: (message, signature) => verifyWithSsSecret(message, signature, publicKey),
28
+ sign: message => signWithSr25519Secret(secret, message),
29
+ verify: (message, signature) => verifySr25519Signature(message, signature, publicKey),
71
30
  };
72
31
  }
73
32
  // encryption key pair
@@ -1,7 +1,7 @@
1
1
  import type { LazyClient } from '@novasamatech/statement-store';
2
2
  import type { ResultAsync } from 'neverthrow';
3
3
  import type { DerivedSr25519Account } from '../../crypto.js';
4
- export declare function createAliceVerifier(): DerivedSr25519Account;
4
+ export declare function createSudoAliceVerifier(): DerivedSr25519Account;
5
5
  export declare const createAttestationService: (lazyClient: LazyClient) => {
6
6
  claimUsername(): string;
7
7
  grantVerifierAllowance(verifier: DerivedSr25519Account): ResultAsync<void, Error>;
@@ -10,7 +10,7 @@ import { member_from_entropy, sign } from 'verifiablejs/bundler';
10
10
  import { deriveSr25519Account, getEncrPub, stringToBytes } from '../../crypto.js';
11
11
  import { toError } from '../../helpers/utils.js';
12
12
  const accountId = AccountId();
13
- export function createAliceVerifier() {
13
+ export function createSudoAliceVerifier() {
14
14
  return deriveSr25519Account('bottom drive obey lake curtain smoke basket hold race lonely fit walk', '//Alice');
15
15
  }
16
16
  export const createAttestationService = (lazyClient) => {
@@ -1,3 +1,4 @@
1
+ import { enumValue } from '@novasamatech/scale';
1
2
  import { createAccountId, createEncryption, createLocalSessionAccount, createRemoteSessionAccount, khash, } from '@novasamatech/statement-store';
2
3
  import { mergeUint8, toHex } from '@polkadot-api/utils';
3
4
  import { generateMnemonic } from '@polkadot-labs/hdkd-helpers';
@@ -7,7 +8,7 @@ import { AbortError } from '../../helpers/abortError.js';
7
8
  import { createState, readonly } from '../../helpers/state.js';
8
9
  import { toError } from '../../helpers/utils.js';
9
10
  import { createStoredUserSession } from '../userSessionRepository.js';
10
- import { createAliceVerifier, createAttestationService } from './attestationService.js';
11
+ import { createAttestationService, createSudoAliceVerifier } from './attestationService.js';
11
12
  import { HandshakeData, HandshakeResponsePayload, HandshakeResponseSensitiveData } from './scale/handshake.js';
12
13
  export function createAuth({ metadata, statementStore, ssoSessionRepository, userSecretRepository, lazyClient, }) {
13
14
  const attestationStatus = createState({ step: 'none' });
@@ -16,7 +17,7 @@ export function createAuth({ metadata, statementStore, ssoSessionRepository, use
16
17
  let abort = null;
17
18
  function attestAccount(account, signal) {
18
19
  const attestationService = createAttestationService(lazyClient);
19
- const verifier = createAliceVerifier();
20
+ const verifier = createSudoAliceVerifier();
20
21
  const username = attestationService.claimUsername();
21
22
  attestationStatus.write({ step: 'attestation', username });
22
23
  return attestationService
@@ -115,18 +116,12 @@ export function createAuth({ metadata, statementStore, ssoSessionRepository, use
115
116
  return authModule;
116
117
  }
117
118
  const createHandshakeTopic = fromThrowable((account, encrPublicKey) => khash(account.accountId, mergeUint8([encrPublicKey, stringToBytes('topic')])), toError);
118
- const createHandshakePayloadV1 = fromThrowable(({ encrPublicKey, ssPublicKey, metadata, }) => HandshakeData.enc({
119
- tag: 'v1',
120
- value: [ssPublicKey, encrPublicKey, metadata],
121
- }), toError);
119
+ const createHandshakePayloadV1 = fromThrowable(({ encrPublicKey, ssPublicKey, metadata, }) => HandshakeData.enc(enumValue('v1', [ssPublicKey, encrPublicKey, metadata])), toError);
122
120
  function parseHandshakePayload(payload) {
123
121
  const decoded = HandshakeResponsePayload.dec(payload);
124
122
  switch (decoded.tag) {
125
123
  case 'v1':
126
- return {
127
- encrypted: decoded.value[0],
128
- tmpKey: decoded.value[1],
129
- };
124
+ return decoded.value;
130
125
  default:
131
126
  throw new Error('Unsupported handshake payload version');
132
127
  }
@@ -4,6 +4,9 @@ export declare const HandshakeData: import("scale-ts").Codec<{
4
4
  }>;
5
5
  export declare const HandshakeResponsePayload: import("scale-ts").Codec<{
6
6
  tag: "v1";
7
- value: [Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>];
7
+ value: {
8
+ encrypted: Uint8Array<ArrayBufferLike>;
9
+ tmpKey: Uint8Array<ArrayBufferLike>;
10
+ };
8
11
  }>;
9
12
  export declare const HandshakeResponseSensitiveData: import("scale-ts").Codec<[Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>]>;
@@ -1,10 +1,10 @@
1
- import { Bytes, Enum, Tuple, str } from 'scale-ts';
1
+ import { Enum } from '@novasamatech/scale';
2
+ import { Bytes, Struct, Tuple, str } from 'scale-ts';
2
3
  import { EncrPubKey, SsPubKey } from '../../../crypto.js';
3
4
  export const HandshakeData = Enum({
4
5
  v1: Tuple(SsPubKey, EncrPubKey, str),
5
6
  });
6
7
  export const HandshakeResponsePayload = Enum({
7
- // [encrypted, tmp_key]
8
- v1: Tuple(Bytes(), Bytes(65)),
8
+ v1: Struct({ encrypted: Bytes(), tmpKey: Bytes(65) }),
9
9
  });
10
10
  export const HandshakeResponseSensitiveData = Tuple(Bytes(65), Bytes(32));
@@ -1,20 +1,20 @@
1
+ import { Hex } from '@novasamatech/scale';
1
2
  import { Option, Struct, Vector, bool, str, u32 } from 'scale-ts';
2
- import { hexCodec } from './hex.js';
3
3
  export const SignPayloadRequestCodec = Struct({
4
4
  address: str,
5
- blockHash: hexCodec,
6
- blockNumber: hexCodec,
7
- era: hexCodec,
8
- genesisHash: hexCodec,
9
- method: hexCodec,
10
- nonce: hexCodec,
11
- specVersion: hexCodec,
12
- tip: hexCodec,
13
- transactionVersion: hexCodec,
5
+ blockHash: Hex(),
6
+ blockNumber: Hex(),
7
+ era: Hex(),
8
+ genesisHash: Hex(),
9
+ method: Hex(),
10
+ nonce: Hex(),
11
+ specVersion: Hex(),
12
+ tip: Hex(),
13
+ transactionVersion: Hex(),
14
14
  signedExtensions: Vector(str),
15
15
  version: u32,
16
- assetId: Option(hexCodec),
17
- metadataHash: Option(hexCodec),
16
+ assetId: Option(Hex()),
17
+ metadataHash: Option(Hex()),
18
18
  mode: Option(u32),
19
19
  withSignedTransaction: Option(bool),
20
20
  });
@@ -1,3 +1,4 @@
1
+ import { enumValue } from '@novasamatech/scale';
1
2
  import { createSession } from '@novasamatech/statement-store';
2
3
  import { fieldListView } from '@novasamatech/storage-adapter';
3
4
  import { AccountId } from '@polkadot-api/substrate-bindings';
@@ -31,39 +32,23 @@ export function createUserSession({ userSession, statementStore, encryption, sto
31
32
  const messageId = nanoid();
32
33
  const request = session.request(RemoteMessageCodec, {
33
34
  messageId,
34
- data: {
35
- tag: 'v1',
36
- value: {
37
- tag: 'SignRequest',
38
- value: payload,
39
- },
40
- },
35
+ data: enumValue('v1', enumValue('SignRequest', payload)),
41
36
  });
42
37
  const responseFilter = (message) => {
43
- return (message.data.tag === 'v1' &&
38
+ if (message.data.tag === 'v1' &&
44
39
  message.data.value.tag === 'SignResponse' &&
45
- message.data.value.value.respondingTo === messageId);
40
+ message.data.value.value.respondingTo === messageId) {
41
+ return message.data.value.value.payload;
42
+ }
46
43
  };
47
44
  return request
48
45
  .andThen(() => session.waitForRequestMessage(RemoteMessageCodec, responseFilter))
49
46
  .andThen(message => {
50
- const { data } = message.payload;
51
- switch (data.tag) {
52
- case 'v1': {
53
- switch (data.value.tag) {
54
- case 'SignResponse':
55
- if (data.value.value.payload.success) {
56
- return ok(data.value.value.payload.value);
57
- }
58
- else {
59
- return err(new Error(data.value.value.payload.value));
60
- }
61
- default:
62
- return err(new Error(`Incorrect sign response: ${data.value.tag}`));
63
- }
64
- }
65
- default:
66
- return err(new Error(`Unsupported message version ${data.tag}`));
47
+ if (message.success) {
48
+ return ok(message.value);
49
+ }
50
+ else {
51
+ return err(new Error(message.value));
67
52
  }
68
53
  });
69
54
  },
@@ -71,13 +56,7 @@ export function createUserSession({ userSession, statementStore, encryption, sto
71
56
  return session
72
57
  .submitRequestMessage(RemoteMessageCodec, {
73
58
  messageId: nanoid(),
74
- data: {
75
- tag: 'v1',
76
- value: {
77
- tag: 'Disconnected',
78
- value: undefined,
79
- },
80
- },
59
+ data: enumValue('v1', enumValue('Disconnected', undefined)),
81
60
  })
82
61
  .map(() => undefined);
83
62
  },
@@ -85,17 +64,18 @@ export function createUserSession({ userSession, statementStore, encryption, sto
85
64
  return session.subscribe(RemoteMessageCodec, messages => {
86
65
  processedMessages.read().andThen(processed => {
87
66
  const results = messages.map(message => {
88
- if (message.type === 'request') {
89
- const isMessageProcessed = processed.includes(message.payload.messageId);
67
+ if (message.type === 'request' && message.payload.status === 'parsed') {
68
+ const payload = message.payload;
69
+ const isMessageProcessed = processed.includes(payload.value.messageId);
90
70
  if (isMessageProcessed) {
91
71
  return okAsync({ processed: false });
92
72
  }
93
- return callback(message.payload)
73
+ return callback(payload.value)
94
74
  .orTee(error => {
95
- console.error('Error while processing sso messsage:', error);
75
+ console.error('Error while processing sso message:', error);
96
76
  })
97
77
  .orElse(() => okAsync(false))
98
- .map(processed => (processed ? { processed, message: message.payload } : { processed }));
78
+ .map(processed => (processed ? { processed, message: payload.value } : { processed }));
99
79
  }
100
80
  return okAsync({ processed: false });
101
81
  });
@@ -1,35 +1,16 @@
1
- import { getStatementSigner, statementCodec } from '@polkadot-api/sdk-statement';
2
- import { err, errAsync, fromThrowable, ok, okAsync } from 'neverthrow';
3
- import { compact } from 'scale-ts';
4
- import { getSsPub, signWithSsSecret, verifyWithSsSecret } from '../crypto.js';
5
- import { toError } from '../helpers/utils.js';
6
- const verify = fromThrowable(verifyWithSsSecret, toError);
1
+ import { createSr25519Prover } from '@novasamatech/statement-store';
2
+ import { err, ok } from 'neverthrow';
7
3
  export function createSsoStatementProver(userSession, userSecretRepository) {
8
- const secret = userSecretRepository
4
+ const prover = userSecretRepository
9
5
  .read(userSession.id)
10
6
  .andThen(secrets => (secrets ? ok(secrets) : err(new Error(`Secrets for session ${userSession.id} not found.`))))
11
- .map(x => x.ssSecret);
7
+ .map(x => createSr25519Prover(x.ssSecret));
12
8
  return {
13
9
  generateMessageProof(statement) {
14
- return secret.map(secret => {
15
- const signer = getStatementSigner(getSsPub(secret), 'sr25519', data => signWithSsSecret(secret, data));
16
- return signer.sign(statement);
17
- });
10
+ return prover.andThen(prover => prover.generateMessageProof(statement));
18
11
  },
19
12
  verifyMessageProof(statement) {
20
- const { proof, ...unsigned } = statement;
21
- if (!proof) {
22
- // TODO should we pass check when proof is not presented?
23
- return okAsync(true);
24
- }
25
- const encoded = statementCodec.enc(unsigned);
26
- const compactLen = compact.enc(compact.dec(encoded)).length;
27
- switch (proof.type) {
28
- case 'sr25519':
29
- return verify(encoded.slice(compactLen), proof.value.signature.asBytes(), proof.value.signer.asBytes()).asyncAndThen(x => okAsync(x));
30
- default:
31
- return errAsync(new Error(`Proof type ${proof.type} is not supported.`));
32
- }
13
+ return prover.andThen(prover => prover.verifyMessageProof(statement));
33
14
  },
34
15
  };
35
16
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-papp",
3
3
  "type": "module",
4
- "version": "0.5.1",
4
+ "version": "0.5.3-0",
5
5
  "description": "Polkadot app integration",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -28,9 +28,11 @@
28
28
  "@noble/ciphers": "2.1.1",
29
29
  "@noble/curves": "2.0.1",
30
30
  "@noble/hashes": "2.0.1",
31
- "@novasamatech/host-api": "0.5.1",
32
- "@novasamatech/statement-store": "0.5.1",
33
- "@novasamatech/storage-adapter": "0.5.1",
31
+ "@novasamatech/host-api": "0.5.3-0",
32
+ "@novasamatech/scale": "0.5.3-0",
33
+ "@novasamatech/statement-store": "0.5.3-0",
34
+ "@novasamatech/storage-adapter": "0.5.3-0",
35
+ "@polkadot-api/utils": "0.2.0",
34
36
  "@polkadot-api/substrate-bindings": "^0.16.5",
35
37
  "@polkadot-labs/hdkd-helpers": "^0.0.27",
36
38
  "@scure/sr25519": "1.0.0",