Browse Source

update nostr message to include signature for public key

Trent Larson 2 months ago
parent
commit
ebfcfa0a2d
  1. 9
      CHANGELOG.md
  2. 2
      README.md
  3. 4
      package-lock.json
  4. 2
      package.json
  5. 74
      src/views/NewEditProjectView.vue

9
CHANGELOG.md

@ -6,12 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.29-beta]
### Changed
- Send signed data to nostr endpoints to verify public key ownership.
### Changed in DB or environment
- Uses Endorser.ch version 4.1.1
## [0.3.28] ## [0.3.28]
### Added ### Added
- Posting to nostr apps Trustroots & TripHopping - Posting to nostr apps Trustroots & TripHopping
- Display of providers on claim view page - Display of providers on claim view page
### Changed ### Changed
- Switched BVC-meeting-ending gift to be a gift from the group. - Switched BVC-meeting-ending gift to be a gift from the group.
### Changed in DB or environment
- Requires Endorser.ch version 4.1.0
## [0.3.27] - 2024.09.22 - ee23e6f005e47f5bd6f04d804599f6395371b0e4 ## [0.3.27] - 2024.09.22 - ee23e6f005e47f5bd6f04d804599f6395371b0e4

2
README.md

@ -72,7 +72,7 @@ npm run build
* `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari` * `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari`
* Commit changes. Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, and commit. Also record what version is on production. * Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, and commit. Also record what version is on production.
* [Tag with the new version.](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) * [Tag with the new version.](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases)

4
package-lock.json

@ -1,12 +1,12 @@
{ {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.28", "version": "0.3.28-beta",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.28", "version": "0.3.28-beta",
"dependencies": { "dependencies": {
"@dicebear/collection": "^5.4.1", "@dicebear/collection": "^5.4.1",
"@dicebear/core": "^5.4.1", "@dicebear/core": "^5.4.1",

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "TimeSafari", "name": "TimeSafari",
"version": "0.3.28", "version": "0.3.28-beta",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"serve": "vite preview", "serve": "vite preview",

74
src/views/NewEditProjectView.vue

@ -105,13 +105,11 @@
<span class="col-span-1 w-full flex justify-center">{{ zoneName }}</span> <span class="col-span-1 w-full flex justify-center">{{ zoneName }}</span>
</div> </div>
<div class="flex items-center mb-4"> <div
<input class="flex items-center mb-4"
type="checkbox" @click="includeLocation = !includeLocation"
class="mr-2" >
v-model="includeLocation" <input type="checkbox" class="mr-2" v-model="includeLocation" />
@click="includeLocation = !includeLocation"
/>
<label for="includeLocation">Include Location</label> <label for="includeLocation">Include Location</label>
</div> </div>
<div v-if="includeLocation" class="mb-4 aspect-video"> <div v-if="includeLocation" class="mb-4 aspect-video">
@ -149,22 +147,12 @@
v-if="showGeneralAdvanced && includeLocation" v-if="showGeneralAdvanced && includeLocation"
class="items-center mb-4" class="items-center mb-4"
> >
<div class="flex"> <div class="flex" @click="sendToTrustroots = !sendToTrustroots">
<input <input type="checkbox" class="mr-2" v-model="sendToTrustroots" />
type="checkbox"
class="mr-2"
v-model="sendToTrustroots"
@click="sendToTrustroots = !sendToTrustroots"
/>
<label>Send to Trustroots</label> <label>Send to Trustroots</label>
</div> </div>
<div class="flex"> <div class="flex" @click="sendToTripHopping = !sendToTripHopping">
<input <input type="checkbox" class="mr-2" v-model="sendToTripHopping" />
type="checkbox"
class="mr-2"
v-model="sendToTripHopping"
@click="sendToTripHopping = !sendToTripHopping"
/>
<label>Send to TripHopping</label> <label>Send to TripHopping</label>
</div> </div>
</div> </div>
@ -202,7 +190,10 @@
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
import { AxiosError, AxiosRequestHeaders } from "axios"; import { AxiosError, AxiosRequestHeaders } from "axios";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { hexToBytes } from "@noble/hashes/utils";
import type { EventTemplate, VerifiedEvent } from "nostr-tools/lib/types/core";
import { accountFromSeedWords } from "nostr-tools/nip06"; import { accountFromSeedWords } from "nostr-tools/nip06";
import { finalizeEvent, serializeEvent } from "nostr-tools/pure";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet"; import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
import { Router } from "vue-router"; import { Router } from "vue-router";
@ -456,18 +447,25 @@ export default class NewEditProjectView extends Vue {
const projectPath = encodeURIComponent(resp.data.success.handleId); const projectPath = encodeURIComponent(resp.data.success.handleId);
let signedPayload: VerifiedEvent; // sign something to prove ownership of pubkey
if (this.sendToTrustroots) { if (this.sendToTrustroots) {
signedPayload = await this.signPayload();
this.sendToNostrPartner( this.sendToNostrPartner(
"NOSTR-EVENT-TRUSTROOTS", "NOSTR-EVENT-TRUSTROOTS",
"Trustroots", "Trustroots",
resp.data.success.claimId, resp.data.success.claimId,
signedPayload,
); );
} }
if (this.sendToTripHopping) { if (this.sendToTripHopping) {
if (!signedPayload) {
signedPayload = await this.signPayload();
}
this.sendToNostrPartner( this.sendToNostrPartner(
"NOSTR-EVENT-TRIPHOPPING", "NOSTR-EVENT-TRIPHOPPING",
"TripHopping", "TripHopping",
resp.data.success.claimId, resp.data.success.claimId,
signedPayload,
); );
} }
@ -535,10 +533,38 @@ export default class NewEditProjectView extends Vue {
} }
} }
private async signPayload(): Promise<VerifiedEvent> {
const account = await getAccount(this.activeDid);
// get the last number of the derivationPath
const finalDerNum = account?.derivationPath?.split?.("/")?.reverse()[0];
// remove any trailing '
const finalDerNumNoApostrophe = finalDerNum?.replace(/'/g, "");
const accountNum = Number(finalDerNumNoApostrophe || 0);
const pubPri = accountFromSeedWords(
account?.mnemonic as string,
"",
accountNum,
);
const privateBytes = hexToBytes(pubPri?.privateKey);
// No real content is necessary, we just want something signed,
// so we might as well use nostr libs for nostr functions.
// Besides: someday we may create real content that we can relay.
const event: EventTemplate = {
kind: 30402,
tags: [[]],
content: "",
created_at: 0,
};
// Why does IntelliJ not see matching types?
const signedEvent = finalizeEvent(event, privateBytes);
return signedEvent;
}
private async sendToNostrPartner( private async sendToNostrPartner(
linkCode: string, linkCode: string,
serviceName: string, serviceName: string,
jwtId: string, jwtId: string,
signedPayload: VerifiedEvent,
) { ) {
// first, get the public key for nostr // first, get the public key for nostr
const account = await getAccount(this.activeDid); const account = await getAccount(this.activeDid);
@ -557,11 +583,15 @@ export default class NewEditProjectView extends Vue {
const trustrootsUrl = DEFAULT_PARTNER_API_SERVER + "/api/partner/link"; const trustrootsUrl = DEFAULT_PARTNER_API_SERVER + "/api/partner/link";
const timeSafariUrl = window.location.origin + "/claim/" + jwtId; const timeSafariUrl = window.location.origin + "/claim/" + jwtId;
const content = this.fullClaim.name + " - see " + timeSafariUrl; const content = this.fullClaim.name + " - see " + timeSafariUrl;
// Why does IntelliJ not see matching types?
const payload = serializeEvent(signedPayload);
const trustrootsParams = { const trustrootsParams = {
jwtId: jwtId, jwtId: jwtId,
linkCode: linkCode, linkCode: linkCode,
inputJson: JSON.stringify(content), inputJson: JSON.stringify(content),
nostrPubKeyHex: nostrPubKey, pubKeyHex: nostrPubKey,
pubKeyImage: payload,
pubKeySigHex: signedPayload.sig,
}; };
const fullTrustrootsUrl = trustrootsUrl; const fullTrustrootsUrl = trustrootsUrl;
const headers = await getHeaders(this.activeDid); const headers = await getHeaders(this.activeDid);

Loading…
Cancel
Save