Add signature checking to requests

This commit is contained in:
Lncvrt committed 2026-02-28 12:57:10 -07:00
1 parent fbf87dceba
commit 6b7b2b198a
10 files changed
+118 -40

No files matched your search

+19 -9
View File
@@ -2,12 +2,13 @@
import { useCallback, useEffect, useState } from 'react'
import { BirdColor } from '@/types/BerryDash/BirdColor'
import axios from 'axios'
import { GetIconForUser } from '@/lib/BerryDash'
import Image from 'next/image'
import './styles.css'
import { useRouter } from 'next/navigation'
import { platform } from '@tauri-apps/plugin-os'
import { fetch } from '@tauri-apps/plugin-http'
import { verifySignature } from '@/lib/Util'
interface BaseEntry {
id: number
@@ -90,11 +91,16 @@ export default function BerryDashLeaderboards () {
const Refresh = useCallback(async () => {
try {
if (selected == 3 || selected == 4) {
const result = await axios.get(
const response = await fetch(
'https://games.lncvrt.xyz/api/berrydash/account?username='
)
if (result.data.success) {
let accounts = result.data.data as Account[]
const signature = response.headers.get('x-signature') ?? ''
const data = await response.json()
if (
(await verifySignature(JSON.stringify(data), signature)) &&
data.success
) {
let accounts = data.data as Account[]
accounts = accounts.map(acc => {
const xp = calculateXP(
@@ -114,9 +120,9 @@ export default function BerryDashLeaderboards () {
accounts.sort((a, b) => (b.xp > a.xp ? 1 : b.xp < a.xp ? -1 : 0))
setEntries(accounts)
}
} else console.log('Failed')
} else {
const result = await axios.get(
const response = await fetch(
'https://games.lncvrt.xyz/api/berrydash/leaderboard/' +
(selected == 0
? 'score'
@@ -128,9 +134,13 @@ export default function BerryDashLeaderboards () {
? 'legacy'
: 'total')
)
if (result.data.success) {
setEntries(result.data.data as LeaderboardEntry[])
}
const signature = response.headers.get('x-signature') ?? ''
const data = await response.json()
if (
(await verifySignature(JSON.stringify(data), signature)) &&
data.success
)
setEntries(data.data as LeaderboardEntry[])
}
} catch {
setEntries([])
+30 -10
View File
@@ -15,7 +15,6 @@ import {
import { VersionsConfig } from '@/types/VersionsConfig'
import { NormalConfig } from '@/types/NormalConfig'
import { app } from '@tauri-apps/api'
import axios from 'axios'
import { openUrl } from '@tauri-apps/plugin-opener'
import { GlobalProvider } from './GlobalProvider'
import { Roboto } from 'next/font/google'
@@ -36,6 +35,8 @@ import VersionsDownloadPopup from '@/componets/popups/VersionsDownload'
import GamesDownloadPopup from '@/componets/popups/GamesDownload'
import DownloadsPopup from '@/componets/popups/Downloads'
import VersionVersionPopup from '@/componets/popups/VersionVersion'
import { fetch } from '@tauri-apps/plugin-http'
import { verifySignature } from '@/lib/Util'
const roboto = Roboto({
subsets: ['latin']
@@ -252,11 +253,18 @@ export default function RootLayout ({
setVersion(client)
if (process.env.NODE_ENV === 'production') {
try {
const response = await axios.get(
const response = await fetch(
'https://games.lncvrt.xyz/api/launcher/latest'
)
if (response.data !== client) {
setOutdated(true)
const signature = response.headers.get('x-signature') ?? ''
const data = await response.text()
if (await verifySignature(data, signature)) {
if (data !== client) {
setOutdated(true)
return
}
} else {
setLoadingText('Failed to check latest version.')
return
}
} catch {
@@ -265,10 +273,17 @@ export default function RootLayout ({
}
}
try {
const res = await axios.get(
const response = await fetch(
`https://games.lncvrt.xyz/api/launcher/versions?platform=${platform()}&arch=${arch()}`
)
setServerVersionList(res.data)
const signature = response.headers.get('x-signature') ?? ''
const data = await response.json()
if (await verifySignature(JSON.stringify(data), signature)) {
setServerVersionList(data)
} else {
setLoadingText('Failed to download versions list.')
return
}
} catch {
setLoadingText('Failed to download versions list.')
return
@@ -348,13 +363,18 @@ export default function RootLayout ({
prev.map(d => (d.version === versionId ? { ...d, queued: false } : d))
)
const downloadInfoRequest = await axios.get(
const downloadInfoRequest = await fetch(
'https://games.lncvrt.xyz/api/launcher/download?gameId=' +
info.id +
'&downloadId=' +
info.download
)
if (!downloadInfoRequest.data.success) {
const signature = downloadInfoRequest.headers.get('x-signature') ?? ''
const data = await downloadInfoRequest.json()
if (
!(await verifySignature(JSON.stringify(data), signature)) ||
!data.success
) {
setDownloadProgress(prev =>
prev.map(d =>
d.version === versionId
@@ -371,10 +391,10 @@ export default function RootLayout ({
}
const res = await invoke<string>('download', {
url: downloadInfoRequest.data.data.url,
url: data.data.url,
name: info.id,
executable: info.executable,
hash: downloadInfoRequest.data.data.hash
hash: data.data.hash
})
if (res === '1') {
+14
View File
@@ -2,6 +2,7 @@ import { message } from '@tauri-apps/plugin-dialog'
import { BaseDirectory, exists, stat } from '@tauri-apps/plugin-fs'
import { openPath } from '@tauri-apps/plugin-opener'
import { join, appLocalDataDir } from '@tauri-apps/api/path'
import { invoke } from '@tauri-apps/api/core'
export const openFolder = async (name: string) => {
const relativePath = await join('game', name)
@@ -48,3 +49,16 @@ export const formatEtaSmart = (seconds: number) => {
const h = Math.floor((seconds % 86400) / 3600)
return `${d}d ${h}h`
}
export const verifySignature = async (body: string, signature: string) => {
try {
const result = await invoke<boolean>('verify_signature', {
body: body ?? '',
signature: signature ?? '',
publicKey: process.env.NEXT_PUBLIC_PUBLIC_SIGNING_KEY ?? ''
})
return Boolean(result)
} catch {
return false
}
}