Use encrypted endpoint

This commit is contained in:
2025-07-21 18:44:22 -07:00
parent cb9d9fe02d
commit f3bc9a9570
6 changed files with 92 additions and 9 deletions

4
src/enums/Keys.ts Normal file
View File

@@ -0,0 +1,4 @@
export enum Keys {
SERVER_RECEIVE_TRANSFER_KEY = '',
SERVER_SEND_TRANSFER_KEY = ''
}

View File

@@ -2,15 +2,34 @@ import { useEffect, useState } from 'react'
import './Leaderboards.css'
import axios from 'axios'
import { LeaderboardEntry } from '../types/LeaderboardEntry'
import { app } from '@tauri-apps/api'
import { platform } from '@tauri-apps/plugin-os'
import { decrypt, encrypt } from '../util/Encryption'
export default function Leaderboards() {
export default function Leaderboards () {
const [leaderboardData, setLeaderboardData] = useState<LeaderboardEntry[]>([])
function refresh() {
async function refresh () {
setLeaderboardData([])
const launcherVersion = await app.getVersion()
axios
.get('https://berrydash.lncvrt.xyz/database/getTopPlayersAPI.php')
.then(res => setLeaderboardData(res.data))
.post(
'https://berrydash.lncvrt.xyz/database/getTopPlayers.php',
{
[encrypt('type')]: encrypt('0')
},
{
headers: {
Requester: 'BerryDashLauncher',
LauncherVersion: launcherVersion,
ClientPlatform: platform()
}
}
)
.then(res => {
const decrypted = decrypt(res.data)
setLeaderboardData(JSON.parse(decrypted))
})
.catch(e => console.error('Error fetching leaderboard data:', e))
}
@@ -22,15 +41,19 @@ export default function Leaderboards() {
<div className='mx-4 mt-4'>
<div className='flex justify-between items-center mb-4'>
<p className='text-3xl'>Leaderboards</p>
<button className='button text-3xl' onClick={refresh}>Refresh</button>
<button className='button text-3xl' onClick={refresh}>
Refresh
</button>
</div>
<div className='leaderboard-container'>
<div className='leaderboard-scroll'>
{leaderboardData.length ? (
leaderboardData.map((entry, i) => (
<div key={entry.username} className='leaderboard-entry'>
<p>#{i + 1} {entry.username}</p>
<p className='score'>{entry.scoreFormatted}</p>
<p>
#{i + 1} {entry.username}
</p>
<p className='score'>{entry.value}</p>
</div>
))
) : (

View File

@@ -1,5 +1,9 @@
export interface LeaderboardEntry {
username: string
score: bigint
scoreFormatted: string
userid: bigint
value: bigint
icon: number
overlay: number
birdColor: number[]
overlayColor: number[]
}

40
src/util/Encryption.ts Normal file
View File

@@ -0,0 +1,40 @@
import CryptoJS from 'crypto-js'
import { Keys } from '../enums/Keys'
export function encrypt (plainText: string): string {
const iv = CryptoJS.lib.WordArray.random(16)
const encrypted = CryptoJS.AES.encrypt(
plainText,
CryptoJS.enc.Utf8.parse(Keys.SERVER_SEND_TRANSFER_KEY),
{
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
)
const combined = iv.concat(encrypted.ciphertext)
return CryptoJS.enc.Base64.stringify(combined)
}
export function decrypt (dataB64: string): string {
const data = CryptoJS.enc.Base64.parse(dataB64)
const iv = CryptoJS.lib.WordArray.create(data.words.slice(0, 4), 16)
const ciphertext = CryptoJS.lib.WordArray.create(
data.words.slice(4),
data.sigBytes - 16
)
const cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext })
const decrypted = CryptoJS.AES.decrypt(
cipherParams,
CryptoJS.enc.Utf8.parse(Keys.SERVER_RECEIVE_TRANSFER_KEY),
{
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
)
const result = decrypted.toString(CryptoJS.enc.Utf8)
if (!result) throw new Error(encrypt('-997'))
return result
}