Browse Source

add the hashed-next-key to the contact data, shown & stored

starred-projects
Trent Larson 9 months ago
parent
commit
934664b9c9
  1. 4
      project.task.yaml
  2. 3
      src/db/tables/contacts.ts
  3. 16
      src/libs/crypto/index.ts
  4. 16
      src/views/ContactQRScanShowView.vue
  5. 5
      src/views/ContactsView.vue
  6. 13
      src/views/ImportDerivedAccountView.vue

4
project.task.yaml

@ -6,8 +6,6 @@ tasks:
- fix maskable icon - fix maskable icon
- 04 generate & store next public key hash, and give to contacts for storage
- .5 If notifications are not enabled, add message to front page with link/button to enable - .5 If notifications are not enabled, add message to front page with link/button to enable
- Release Minimum Viable Product : - Release Minimum Viable Product :
@ -32,7 +30,7 @@ tasks:
- record donations vs gives - record donations vs gives
- make server endpoint for full English description of limits - make server endpoint for full English description of limits
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too) - make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
- 02 watch for the service worker activation before showing the button to turn on notifications
- 01 server - show all claim details when issued by the issuer - 01 server - show all claim details when issued by the issuer
- bug - got error adding on Firefox user #0 as contact for themselves - bug - got error adding on Firefox user #0 as contact for themselves
- bug (that is hard to reproduce) - back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity - bug (that is hard to reproduce) - back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity

3
src/db/tables/contacts.ts

@ -1,11 +1,12 @@
export interface Contact { export interface Contact {
did: string; did: string;
name?: string; name?: string;
nextPublicKeyHashBase64?: string; // base64-encoded SHA256 hash of next public key
publicKeyBase64?: string; publicKeyBase64?: string;
seesMe?: boolean; seesMe?: boolean;
registered?: boolean; registered?: boolean;
} }
export const ContactSchema = { export const ContactSchema = {
contacts: "&did, name", // no need to key by publicKeyBase64, registered, seesMe contacts: "&did, name", // no need to key by other things
}; };

16
src/libs/crypto/index.ts

@ -173,3 +173,19 @@ export const getContactPayloadFromJwtUrl = (jwtUrlText: string) => {
return jwt.payload; return jwt.payload;
}; };
export const nextDerivationPath = (origDerivPath: string) => {
let lastStr = origDerivPath.split("/").slice(-1)[0];
if (lastStr.endsWith("'")) {
lastStr = lastStr.slice(0, -1);
}
const lastNum = parseInt(lastStr, 10);
const newLastNum = lastNum + 1;
const newLastStr = newLastNum.toString() + (lastStr.endsWith("'") ? "'" : "");
const newDerivPath = origDerivPath
.split("/")
.slice(0, -1)
.concat([newLastStr])
.join("/");
return newDerivPath;
};

16
src/views/ContactQRScanShowView.vue

@ -58,16 +58,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import * as didJwt from "did-jwt";
import { sha256 } from "ethereum-cryptography/sha256.js";
import QRCodeVue3 from "qr-code-generator-vue3"; import QRCodeVue3 from "qr-code-generator-vue3";
import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { QrcodeStream } from "vue-qrcode-reader"; import { QrcodeStream } from "vue-qrcode-reader";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { accountsDB, db } from "@/db/index"; import { accountsDB, db } from "@/db/index";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import * as R from "ramda"; import { deriveAddress, nextDerivationPath, SimpleSigner } from "@/libs/crypto";
import { SimpleSigner } from "@/libs/crypto";
import * as didJwt from "did-jwt";
import QuickNav from "@/components/QuickNav.vue"; import QuickNav from "@/components/QuickNav.vue";
import { Account } from "@/db/tables/accounts"; import { Account } from "@/db/tables/accounts";
import { import {
@ -131,6 +132,14 @@ export default class ContactQRScanShow extends Vue {
const identity = await this.getIdentity(this.activeDid); const identity = await this.getIdentity(this.activeDid);
const publicKeyHex = identity.keys[0].publicKeyHex; const publicKeyHex = identity.keys[0].publicKeyHex;
const publicEncKey = Buffer.from(publicKeyHex, "hex").toString("base64"); const publicEncKey = Buffer.from(publicKeyHex, "hex").toString("base64");
const newDerivPath = nextDerivationPath(account.derivationPath);
const nextPublicHex = deriveAddress(account.mnemonic, newDerivPath)[2];
const nextPublicEncKey = Buffer.from(nextPublicHex, "hex");
const nextPublicEncKeyHash = sha256(nextPublicEncKey);
const nextPublicEncKeyHashBase64 =
Buffer.from(nextPublicEncKeyHash).toString("base64");
const contactInfo = { const contactInfo = {
iat: Date.now(), iat: Date.now(),
iss: this.activeDid, iss: this.activeDid,
@ -139,6 +148,7 @@ export default class ContactQRScanShow extends Vue {
(settings?.firstName || "") + (settings?.firstName || "") +
(settings?.lastName ? ` ${settings.lastName}` : ""), // deprecated, pre v 0.1.3 (settings?.lastName ? ` ${settings.lastName}` : ""), // deprecated, pre v 0.1.3
publicEncKey, publicEncKey,
nextPublicEncKeyHash: nextPublicEncKeyHashBase64,
}, },
}; };

5
src/views/ContactsView.vue

@ -109,6 +109,10 @@
<div class="text-sm truncate" v-if="contact.publicKeyBase64"> <div class="text-sm truncate" v-if="contact.publicKeyBase64">
Public Key (base 64): {{ contact.publicKeyBase64 }} Public Key (base 64): {{ contact.publicKeyBase64 }}
</div> </div>
<div class="text-sm truncate" v-if="contact.nextPublicKeyHashBase64">
Next Public Key Hash (base 64):
{{ contact.nextPublicKeyHashBase64 }}
</div>
<div id="ContactActions" class="flex gap-1.5 mt-2"> <div id="ContactActions" class="flex gap-1.5 mt-2">
<div v-if="activeDid"> <div v-if="activeDid">
@ -530,6 +534,7 @@ export default class ContactsView extends Vue {
return this.addContact({ return this.addContact({
did: payload.iss, did: payload.iss,
name: payload.own.name, name: payload.own.name,
nextPublicKeyHashBase64: payload.own.nextPublicEncKeyHash,
publicKeyBase64: payload.own.publicEncKey, publicKeyBase64: payload.own.publicEncKey,
} as Contact); } as Contact);
} }

13
src/views/ImportDerivedAccountView.vue

@ -72,6 +72,7 @@ import {
DEFAULT_ROOT_DERIVATION_PATH, DEFAULT_ROOT_DERIVATION_PATH,
deriveAddress, deriveAddress,
newIdentifier, newIdentifier,
nextDerivationPath,
} from "../libs/crypto"; } from "../libs/crypto";
import { accountsDB, db } from "@/db/index"; import { accountsDB, db } from "@/db/index";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
@ -121,17 +122,7 @@ export default class ImportAccountView extends Vue {
} }
}); });
// increment the last number in that max derivation path // increment the last number in that max derivation path
let lastStr = accountWithMaxDeriv.derivationPath.split("/").slice(-1)[0]; const newDerivPath = nextDerivationPath(accountWithMaxDeriv.derivationPath);
if (lastStr.endsWith("'")) {
lastStr = lastStr.slice(0, -1);
}
const lastNum = parseInt(lastStr, 10);
const newLastNum = lastNum + 1;
const newDerivPath = accountWithMaxDeriv.derivationPath
.split("/")
.slice(0, -1)
.concat([newLastNum.toString() + "'"])
.join("/");
const mne: string = accountWithMaxDeriv.mnemonic; const mne: string = accountWithMaxDeriv.mnemonic;

Loading…
Cancel
Save