@aztec/key-store 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a
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/dest/key_store.d.ts +5 -5
- package/dest/key_store.d.ts.map +1 -1
- package/dest/key_store.js +36 -27
- package/package.json +5 -5
- package/src/key_store.ts +40 -25
package/dest/key_store.d.ts
CHANGED
|
@@ -84,13 +84,13 @@ export declare class KeyStore {
|
|
|
84
84
|
*/
|
|
85
85
|
getAppOutgoingViewingSecretKey(account: AztecAddress, app: AztecAddress): Promise<Fr>;
|
|
86
86
|
/**
|
|
87
|
-
* Retrieves the sk_m corresponding to the pk_m.
|
|
88
|
-
* @throws If the provided
|
|
89
|
-
* @param
|
|
87
|
+
* Retrieves the sk_m corresponding to the given pk_m hash.
|
|
88
|
+
* @throws If the provided hash is not associated with any of the registered accounts.
|
|
89
|
+
* @param pkMHash - The master public key hash to get secret key for.
|
|
90
90
|
* @returns A Promise that resolves to sk_m.
|
|
91
91
|
* @dev Used when feeding the sk_m to the kernel circuit for keys verification.
|
|
92
92
|
*/
|
|
93
|
-
getMasterSecretKey(
|
|
93
|
+
getMasterSecretKey(pkMHash: Fr): Promise<GrumpkinScalar>;
|
|
94
94
|
/**
|
|
95
95
|
* Checks whether a given account has a key matching the provided master public key hash.
|
|
96
96
|
* @param account - The account address to check.
|
|
@@ -106,4 +106,4 @@ export declare class KeyStore {
|
|
|
106
106
|
*/
|
|
107
107
|
getKeyPrefixAndAccount(value: Bufferable): Promise<[KeyPrefix, AztecAddress]>;
|
|
108
108
|
}
|
|
109
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
109
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMva2V5X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0sbUNBQW1DLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssVUFBVSxFQUFxQixNQUFNLDZCQUE2QixDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDOUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDNUQsT0FBTyxFQUVMLEtBQUssU0FBUyxFQUNkLEtBQUssU0FBUyxFQUtmLE1BQU0sb0JBQW9CLENBQUM7QUFPNUI7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQUNuQixnQkFBdUIsY0FBYyxLQUFLO0lBSTFDLFlBQVksUUFBUSxFQUFFLGlCQUFpQixFQUd0QztJQUVEOzs7T0FHRztJQUNJLGFBQWEsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDLENBSS9DO0lBRUQ7Ozs7O09BS0c7SUFDVSxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsY0FBYyxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0ErQ3hGO0lBRUQ7OztPQUdHO0lBQ1UsV0FBVyxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUtsRDtJQUVELGdFQUFnRTtJQUNuRCxVQUFVLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRS9EO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksdUJBQXVCLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQTBDeEc7SUFFRDs7Ozs7T0FLRztJQUNVLDJCQUEyQixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFsRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBUXhGO0lBRUQ7Ozs7O09BS0c7SUFDVSxpQ0FBaUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FReEY7SUFFRDs7Ozs7T0FLRztJQUNVLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQVFoRjtJQUVEOzs7OztPQUtHO0lBQ1UsaUNBQWlDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBUTdGO0lBRUQ7Ozs7OztPQU1HO0lBQ1UsOEJBQThCLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0Fhakc7SUFFRDs7Ozs7O09BTUc7SUFDSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0E2QjlEO0lBRUQ7Ozs7O09BS0c7SUFDSSxhQUFhLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FXekU7SUFFRDs7Ozs7T0FLRztJQUNVLHNCQUFzQixDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBY3pGO0NBQ0YifQ==
|
package/dest/key_store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key_store.d.ts","sourceRoot":"","sources":["../src/key_store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,cAAc,EAAS,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"key_store.d.ts","sourceRoot":"","sources":["../src/key_store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,cAAc,EAAS,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,6BAA6B,CAAC;AACjF,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,SAAS,EAKf,MAAM,oBAAoB,CAAC;AAO5B;;GAEG;AACH,qBAAa,QAAQ;;IACnB,gBAAuB,cAAc,KAAK;IAI1C,YAAY,QAAQ,EAAE,iBAAiB,EAGtC;IAED;;;OAGG;IACI,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAI/C;IAED;;;;;OAKG;IACU,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CA+CxF;IAED;;;OAGG;IACU,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAKlD;IAED,gEAAgE;IACnD,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/D;IAED;;;;;;OAMG;IACI,uBAAuB,CAAC,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0CxG;IAED;;;;;OAKG;IACU,2BAA2B,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQlF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQxF;IAED;;;;;OAKG;IACU,yBAAyB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAQhF;IAED;;;;;OAKG;IACU,iCAAiC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAQ7F;IAED;;;;;;OAMG;IACU,8BAA8B,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,CAajG;IAED;;;;;;OAMG;IACI,kBAAkB,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CA6B9D;IAED;;;;;OAKG;IACI,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAWzE;IAED;;;;;OAKG;IACU,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAczF;CACF"}
|
package/dest/key_store.js
CHANGED
|
@@ -7,7 +7,7 @@ import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
|
7
7
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
8
|
import { CompleteAddress } from '@aztec/stdlib/contract';
|
|
9
9
|
import { KeyValidationRequest } from '@aztec/stdlib/kernel';
|
|
10
|
-
import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecretKey } from '@aztec/stdlib/keys';
|
|
10
|
+
import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecretKey, hashPublicKey } from '@aztec/stdlib/keys';
|
|
11
11
|
/** Maps a key prefix to the storage suffix for the corresponding master secret key. */ function secretKeyStorageSuffix(prefix) {
|
|
12
12
|
return prefix === 'n' ? 'nhk_m' : `${prefix}sk_m`;
|
|
13
13
|
}
|
|
@@ -35,30 +35,32 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
|
|
|
35
35
|
* @param partialAddress - The partial address of the account.
|
|
36
36
|
* @returns The account's complete address.
|
|
37
37
|
*/ async addAccount(sk, partialAddress) {
|
|
38
|
-
const { masterNullifierHidingKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, publicKeys } = await deriveKeys(sk);
|
|
39
|
-
const completeAddress = await CompleteAddress.
|
|
38
|
+
const { masterNullifierHidingKey, masterIncomingViewingSecretKey, masterOutgoingViewingSecretKey, masterTaggingSecretKey, masterNullifierPublicKey, masterOutgoingViewingPublicKey, masterTaggingPublicKey, publicKeys } = await deriveKeys(sk);
|
|
39
|
+
const completeAddress = await CompleteAddress.fromPublicKeysAndPartialAddress(publicKeys, partialAddress);
|
|
40
40
|
const { address: account } = completeAddress;
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
41
|
+
// The kernel cannot check that nhpk/ovpk/tpk are on-curve or non-infinity, so the PXE/key-store
|
|
42
|
+
// must guarantee it before persistence. By design, the above derivation produces points that are on
|
|
43
|
+
// the curve and not at infinity.
|
|
44
|
+
// The npk/ovpk/tpk hashes are already in publicKeys; ivpk_m_hash is computed for indexing.
|
|
45
|
+
const masterIncomingViewingPublicKeyHash = await hashPublicKey(publicKeys.ivpkM);
|
|
46
|
+
// The Message Signing and Fallback Keys don't have a derivation path yet, so we just use the default values for their hashes.
|
|
47
|
+
// So we avoid storing them persistently. The default hash is still required for address derivation
|
|
46
48
|
await this.#db.transactionAsync(async ()=>{
|
|
47
49
|
// Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
|
|
48
50
|
await this.#keys.set(`${account.toString()}-ivsk_m`, masterIncomingViewingSecretKey.toBuffer());
|
|
49
51
|
await this.#keys.set(`${account.toString()}-ovsk_m`, masterOutgoingViewingSecretKey.toBuffer());
|
|
50
52
|
await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
|
|
51
53
|
await this.#keys.set(`${account.toString()}-nhk_m`, masterNullifierHidingKey.toBuffer());
|
|
52
|
-
await this.#keys.set(`${account.toString()}-npk_m`,
|
|
53
|
-
await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.
|
|
54
|
-
await this.#keys.set(`${account.toString()}-ovpk_m`,
|
|
55
|
-
await this.#keys.set(`${account.toString()}-tpk_m`,
|
|
54
|
+
await this.#keys.set(`${account.toString()}-npk_m`, masterNullifierPublicKey.toBuffer());
|
|
55
|
+
await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.ivpkM.toBuffer());
|
|
56
|
+
await this.#keys.set(`${account.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer());
|
|
57
|
+
await this.#keys.set(`${account.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer());
|
|
56
58
|
// We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
|
|
57
59
|
// using the #getKeyPrefixAndAccount function later on
|
|
58
|
-
await this.#keys.set(`${account.toString()}-npk_m_hash`,
|
|
60
|
+
await this.#keys.set(`${account.toString()}-npk_m_hash`, publicKeys.npkMHash.toBuffer());
|
|
59
61
|
await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
|
|
60
|
-
await this.#keys.set(`${account.toString()}-ovpk_m_hash`,
|
|
61
|
-
await this.#keys.set(`${account.toString()}-tpk_m_hash`,
|
|
62
|
+
await this.#keys.set(`${account.toString()}-ovpk_m_hash`, publicKeys.ovpkMHash.toBuffer());
|
|
63
|
+
await this.#keys.set(`${account.toString()}-tpk_m_hash`, publicKeys.tpkMHash.toBuffer());
|
|
62
64
|
});
|
|
63
65
|
// At last, we return the newly derived account address
|
|
64
66
|
return completeAddress;
|
|
@@ -84,7 +86,9 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
|
|
|
84
86
|
*/ getKeyValidationRequest(pkMHash, contractAddress) {
|
|
85
87
|
return this.#db.transactionAsync(async ()=>{
|
|
86
88
|
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
|
|
87
|
-
//
|
|
89
|
+
// Load the stored master public key point. The returned KVR carries only the hash, but we
|
|
90
|
+
// use the point here as a witness for two integrity checks below: (1) it matches the supplied
|
|
91
|
+
// hash, and (2) it matches the value derived from the stored secret key.
|
|
88
92
|
const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
|
|
89
93
|
if (!pkMBuffer) {
|
|
90
94
|
throw new Error(`Could not find ${keyPrefix}pk_m for account ${account.toString()} whose address was successfully obtained with ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
|
|
@@ -98,7 +102,7 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
|
|
|
98
102
|
}
|
|
99
103
|
const skM = GrumpkinScalar.fromBuffer(skMBuffer);
|
|
100
104
|
// The remaining awaits are non-DB computations. They are safe because no further IDB operations follow them.
|
|
101
|
-
const computedPkMHash = await pkM
|
|
105
|
+
const computedPkMHash = await hashPublicKey(pkM);
|
|
102
106
|
if (!computedPkMHash.equals(pkMHash)) {
|
|
103
107
|
throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
|
|
104
108
|
}
|
|
@@ -107,7 +111,7 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
|
|
|
107
111
|
throw new Error(`Could not derive ${keyPrefix}pkM from ${keyPrefix}skM.`);
|
|
108
112
|
}
|
|
109
113
|
const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix);
|
|
110
|
-
return new KeyValidationRequest(
|
|
114
|
+
return new KeyValidationRequest(pkMHash, skApp);
|
|
111
115
|
});
|
|
112
116
|
}
|
|
113
117
|
/**
|
|
@@ -189,24 +193,29 @@ import { KEY_PREFIXES, computeAppSecretKey, deriveKeys, derivePublicKeyFromSecre
|
|
|
189
193
|
], DomainSeparator.OVSK_M);
|
|
190
194
|
}
|
|
191
195
|
/**
|
|
192
|
-
* Retrieves the sk_m corresponding to the pk_m.
|
|
193
|
-
* @throws If the provided
|
|
194
|
-
* @param
|
|
196
|
+
* Retrieves the sk_m corresponding to the given pk_m hash.
|
|
197
|
+
* @throws If the provided hash is not associated with any of the registered accounts.
|
|
198
|
+
* @param pkMHash - The master public key hash to get secret key for.
|
|
195
199
|
* @returns A Promise that resolves to sk_m.
|
|
196
200
|
* @dev Used when feeding the sk_m to the kernel circuit for keys verification.
|
|
197
|
-
*/ getMasterSecretKey(
|
|
201
|
+
*/ getMasterSecretKey(pkMHash) {
|
|
198
202
|
return this.#db.transactionAsync(async ()=>{
|
|
199
|
-
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(
|
|
203
|
+
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
|
|
200
204
|
const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
|
|
201
205
|
const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
|
|
202
206
|
if (!secretKeyBuffer) {
|
|
203
|
-
throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}
|
|
207
|
+
throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()}. This should not happen.`);
|
|
204
208
|
}
|
|
205
209
|
const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
|
|
206
210
|
// Non-DB computation — safe because no further IDB operations follow.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
// Integrity check: confirm the stored secret key still derives the requested hash. The check
|
|
212
|
+
// is hash-based rather than point-equal because the on-disk identifier is `pk_m_hash`;
|
|
213
|
+
// cryptographic collision resistance of `hashPublicKey` makes this equivalent to a
|
|
214
|
+
// direct point comparison in practice.
|
|
215
|
+
const derivedPkM = await derivePublicKeyFromSecretKey(skM);
|
|
216
|
+
const derivedPkMHash = await hashPublicKey(derivedPkM);
|
|
217
|
+
if (!derivedPkMHash.equals(pkMHash)) {
|
|
218
|
+
throw new Error(`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()} in secret keys buffer.`);
|
|
210
219
|
}
|
|
211
220
|
return skM;
|
|
212
221
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/key-store",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.b3d3157a",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": "./dest/index.js",
|
|
6
6
|
"typedocOptions": {
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
]
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@aztec/constants": "0.0.1-commit.
|
|
61
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
62
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
63
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
60
|
+
"@aztec/constants": "0.0.1-commit.b3d3157a",
|
|
61
|
+
"@aztec/foundation": "0.0.1-commit.b3d3157a",
|
|
62
|
+
"@aztec/kv-store": "0.0.1-commit.b3d3157a",
|
|
63
|
+
"@aztec/stdlib": "0.0.1-commit.b3d3157a",
|
|
64
64
|
"tslib": "^2.4.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
package/src/key_store.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
computeAppSecretKey,
|
|
16
16
|
deriveKeys,
|
|
17
17
|
derivePublicKeyFromSecretKey,
|
|
18
|
+
hashPublicKey,
|
|
18
19
|
} from '@aztec/stdlib/keys';
|
|
19
20
|
|
|
20
21
|
/** Maps a key prefix to the storage suffix for the corresponding master secret key. */
|
|
@@ -57,17 +58,24 @@ export class KeyStore {
|
|
|
57
58
|
masterIncomingViewingSecretKey,
|
|
58
59
|
masterOutgoingViewingSecretKey,
|
|
59
60
|
masterTaggingSecretKey,
|
|
61
|
+
masterNullifierPublicKey,
|
|
62
|
+
masterOutgoingViewingPublicKey,
|
|
63
|
+
masterTaggingPublicKey,
|
|
60
64
|
publicKeys,
|
|
61
65
|
} = await deriveKeys(sk);
|
|
62
66
|
|
|
63
|
-
const completeAddress = await CompleteAddress.
|
|
67
|
+
const completeAddress = await CompleteAddress.fromPublicKeysAndPartialAddress(publicKeys, partialAddress);
|
|
64
68
|
const { address: account } = completeAddress;
|
|
65
69
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
// The kernel cannot check that nhpk/ovpk/tpk are on-curve or non-infinity, so the PXE/key-store
|
|
71
|
+
// must guarantee it before persistence. By design, the above derivation produces points that are on
|
|
72
|
+
// the curve and not at infinity.
|
|
73
|
+
|
|
74
|
+
// The npk/ovpk/tpk hashes are already in publicKeys; ivpk_m_hash is computed for indexing.
|
|
75
|
+
const masterIncomingViewingPublicKeyHash = await hashPublicKey(publicKeys.ivpkM);
|
|
76
|
+
|
|
77
|
+
// The Message Signing and Fallback Keys don't have a derivation path yet, so we just use the default values for their hashes.
|
|
78
|
+
// So we avoid storing them persistently. The default hash is still required for address derivation
|
|
71
79
|
|
|
72
80
|
await this.#db.transactionAsync(async () => {
|
|
73
81
|
// Naming of keys is as follows ${account}-${n/iv/ov/t}${sk/pk}_m
|
|
@@ -76,17 +84,17 @@ export class KeyStore {
|
|
|
76
84
|
await this.#keys.set(`${account.toString()}-tsk_m`, masterTaggingSecretKey.toBuffer());
|
|
77
85
|
await this.#keys.set(`${account.toString()}-nhk_m`, masterNullifierHidingKey.toBuffer());
|
|
78
86
|
|
|
79
|
-
await this.#keys.set(`${account.toString()}-npk_m`,
|
|
80
|
-
await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.
|
|
81
|
-
await this.#keys.set(`${account.toString()}-ovpk_m`,
|
|
82
|
-
await this.#keys.set(`${account.toString()}-tpk_m`,
|
|
87
|
+
await this.#keys.set(`${account.toString()}-npk_m`, masterNullifierPublicKey.toBuffer());
|
|
88
|
+
await this.#keys.set(`${account.toString()}-ivpk_m`, publicKeys.ivpkM.toBuffer());
|
|
89
|
+
await this.#keys.set(`${account.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer());
|
|
90
|
+
await this.#keys.set(`${account.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer());
|
|
83
91
|
|
|
84
92
|
// We store pk_m_hash under `account-{n/iv/ov/t}pk_m_hash` key to be able to obtain address and key prefix
|
|
85
93
|
// using the #getKeyPrefixAndAccount function later on
|
|
86
|
-
await this.#keys.set(`${account.toString()}-npk_m_hash`,
|
|
94
|
+
await this.#keys.set(`${account.toString()}-npk_m_hash`, publicKeys.npkMHash.toBuffer());
|
|
87
95
|
await this.#keys.set(`${account.toString()}-ivpk_m_hash`, masterIncomingViewingPublicKeyHash.toBuffer());
|
|
88
|
-
await this.#keys.set(`${account.toString()}-ovpk_m_hash`,
|
|
89
|
-
await this.#keys.set(`${account.toString()}-tpk_m_hash`,
|
|
96
|
+
await this.#keys.set(`${account.toString()}-ovpk_m_hash`, publicKeys.ovpkMHash.toBuffer());
|
|
97
|
+
await this.#keys.set(`${account.toString()}-tpk_m_hash`, publicKeys.tpkMHash.toBuffer());
|
|
90
98
|
});
|
|
91
99
|
|
|
92
100
|
// At last, we return the newly derived account address
|
|
@@ -120,7 +128,9 @@ export class KeyStore {
|
|
|
120
128
|
return this.#db.transactionAsync(async () => {
|
|
121
129
|
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
|
|
122
130
|
|
|
123
|
-
//
|
|
131
|
+
// Load the stored master public key point. The returned KVR carries only the hash, but we
|
|
132
|
+
// use the point here as a witness for two integrity checks below: (1) it matches the supplied
|
|
133
|
+
// hash, and (2) it matches the value derived from the stored secret key.
|
|
124
134
|
const pkMBuffer = await this.#keys.getAsync(`${account.toString()}-${keyPrefix}pk_m`);
|
|
125
135
|
if (!pkMBuffer) {
|
|
126
136
|
throw new Error(
|
|
@@ -142,7 +152,7 @@ export class KeyStore {
|
|
|
142
152
|
const skM = GrumpkinScalar.fromBuffer(skMBuffer);
|
|
143
153
|
|
|
144
154
|
// The remaining awaits are non-DB computations. They are safe because no further IDB operations follow them.
|
|
145
|
-
const computedPkMHash = await pkM
|
|
155
|
+
const computedPkMHash = await hashPublicKey(pkM);
|
|
146
156
|
if (!computedPkMHash.equals(pkMHash)) {
|
|
147
157
|
throw new Error(`Could not find ${keyPrefix}pkM for ${keyPrefix}pk_m_hash ${pkMHash.toString()}.`);
|
|
148
158
|
}
|
|
@@ -154,7 +164,7 @@ export class KeyStore {
|
|
|
154
164
|
|
|
155
165
|
const skApp = await computeAppSecretKey(skM, contractAddress, keyPrefix!);
|
|
156
166
|
|
|
157
|
-
return new KeyValidationRequest(
|
|
167
|
+
return new KeyValidationRequest(pkMHash, skApp);
|
|
158
168
|
});
|
|
159
169
|
}
|
|
160
170
|
|
|
@@ -261,31 +271,36 @@ export class KeyStore {
|
|
|
261
271
|
}
|
|
262
272
|
|
|
263
273
|
/**
|
|
264
|
-
* Retrieves the sk_m corresponding to the pk_m.
|
|
265
|
-
* @throws If the provided
|
|
266
|
-
* @param
|
|
274
|
+
* Retrieves the sk_m corresponding to the given pk_m hash.
|
|
275
|
+
* @throws If the provided hash is not associated with any of the registered accounts.
|
|
276
|
+
* @param pkMHash - The master public key hash to get secret key for.
|
|
267
277
|
* @returns A Promise that resolves to sk_m.
|
|
268
278
|
* @dev Used when feeding the sk_m to the kernel circuit for keys verification.
|
|
269
279
|
*/
|
|
270
|
-
public getMasterSecretKey(
|
|
280
|
+
public getMasterSecretKey(pkMHash: Fr): Promise<GrumpkinScalar> {
|
|
271
281
|
return this.#db.transactionAsync(async () => {
|
|
272
|
-
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(
|
|
282
|
+
const [keyPrefix, account] = await this.getKeyPrefixAndAccount(pkMHash);
|
|
273
283
|
|
|
274
284
|
const skStorageSuffix = secretKeyStorageSuffix(keyPrefix);
|
|
275
285
|
const secretKeyBuffer = await this.#keys.getAsync(`${account.toString()}-${skStorageSuffix}`);
|
|
276
286
|
if (!secretKeyBuffer) {
|
|
277
287
|
throw new Error(
|
|
278
|
-
`Could not find ${skStorageSuffix} for ${keyPrefix}
|
|
288
|
+
`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()}. This should not happen.`,
|
|
279
289
|
);
|
|
280
290
|
}
|
|
281
291
|
|
|
282
292
|
const skM = GrumpkinScalar.fromBuffer(secretKeyBuffer);
|
|
283
293
|
|
|
284
294
|
// Non-DB computation — safe because no further IDB operations follow.
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
// Integrity check: confirm the stored secret key still derives the requested hash. The check
|
|
296
|
+
// is hash-based rather than point-equal because the on-disk identifier is `pk_m_hash`;
|
|
297
|
+
// cryptographic collision resistance of `hashPublicKey` makes this equivalent to a
|
|
298
|
+
// direct point comparison in practice.
|
|
299
|
+
const derivedPkM = await derivePublicKeyFromSecretKey(skM);
|
|
300
|
+
const derivedPkMHash = await hashPublicKey(derivedPkM);
|
|
301
|
+
if (!derivedPkMHash.equals(pkMHash)) {
|
|
287
302
|
throw new Error(
|
|
288
|
-
`Could not find ${skStorageSuffix} for ${keyPrefix}
|
|
303
|
+
`Could not find ${skStorageSuffix} for ${keyPrefix}pk_m_hash ${pkMHash.toString()} in secret keys buffer.`,
|
|
289
304
|
);
|
|
290
305
|
}
|
|
291
306
|
|