Use encrypted endpoint
This commit is contained in:
@@ -27,9 +27,11 @@
|
|||||||
"@fortawesome/react-fontawesome": "0.2.2",
|
"@fortawesome/react-fontawesome": "0.2.2",
|
||||||
"@tailwindcss/postcss": "4.1.11",
|
"@tailwindcss/postcss": "4.1.11",
|
||||||
"@tauri-apps/cli": "2.7.0",
|
"@tauri-apps/cli": "2.7.0",
|
||||||
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/react": "19.1.8",
|
"@types/react": "19.1.8",
|
||||||
"@types/react-dom": "19.1.6",
|
"@types/react-dom": "19.1.6",
|
||||||
"@vitejs/plugin-react": "4.7.0",
|
"@vitejs/plugin-react": "4.7.0",
|
||||||
|
"crypto-js": "4.2.0",
|
||||||
"postcss": "8.5.6",
|
"postcss": "8.5.6",
|
||||||
"tailwindcss": "4.1.11",
|
"tailwindcss": "4.1.11",
|
||||||
"typescript": "5.8.3",
|
"typescript": "5.8.3",
|
||||||
|
|||||||
4
src/enums/Keys.ts
Normal file
4
src/enums/Keys.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum Keys {
|
||||||
|
SERVER_RECEIVE_TRANSFER_KEY = '',
|
||||||
|
SERVER_SEND_TRANSFER_KEY = ''
|
||||||
|
}
|
||||||
@@ -2,15 +2,34 @@ import { useEffect, useState } from 'react'
|
|||||||
import './Leaderboards.css'
|
import './Leaderboards.css'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { LeaderboardEntry } from '../types/LeaderboardEntry'
|
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[]>([])
|
const [leaderboardData, setLeaderboardData] = useState<LeaderboardEntry[]>([])
|
||||||
|
|
||||||
function refresh() {
|
async function refresh () {
|
||||||
setLeaderboardData([])
|
setLeaderboardData([])
|
||||||
|
const launcherVersion = await app.getVersion()
|
||||||
axios
|
axios
|
||||||
.get('https://berrydash.lncvrt.xyz/database/getTopPlayersAPI.php')
|
.post(
|
||||||
.then(res => setLeaderboardData(res.data))
|
'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))
|
.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='mx-4 mt-4'>
|
||||||
<div className='flex justify-between items-center mb-4'>
|
<div className='flex justify-between items-center mb-4'>
|
||||||
<p className='text-3xl'>Leaderboards</p>
|
<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>
|
||||||
<div className='leaderboard-container'>
|
<div className='leaderboard-container'>
|
||||||
<div className='leaderboard-scroll'>
|
<div className='leaderboard-scroll'>
|
||||||
{leaderboardData.length ? (
|
{leaderboardData.length ? (
|
||||||
leaderboardData.map((entry, i) => (
|
leaderboardData.map((entry, i) => (
|
||||||
<div key={entry.username} className='leaderboard-entry'>
|
<div key={entry.username} className='leaderboard-entry'>
|
||||||
<p>#{i + 1} {entry.username}</p>
|
<p>
|
||||||
<p className='score'>{entry.scoreFormatted}</p>
|
#{i + 1} {entry.username}
|
||||||
|
</p>
|
||||||
|
<p className='score'>{entry.value}</p>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
export interface LeaderboardEntry {
|
export interface LeaderboardEntry {
|
||||||
username: string
|
username: string
|
||||||
score: bigint
|
userid: bigint
|
||||||
scoreFormatted: string
|
value: bigint
|
||||||
|
icon: number
|
||||||
|
overlay: number
|
||||||
|
birdColor: number[]
|
||||||
|
overlayColor: number[]
|
||||||
}
|
}
|
||||||
|
|||||||
40
src/util/Encryption.ts
Normal file
40
src/util/Encryption.ts
Normal 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
|
||||||
|
}
|
||||||
10
yarn.lock
10
yarn.lock
@@ -779,6 +779,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.20.7"
|
"@babel/types" "^7.20.7"
|
||||||
|
|
||||||
|
"@types/crypto-js@4.2.2":
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.2.2.tgz#771c4a768d94eb5922cc202a3009558204df0cea"
|
||||||
|
integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==
|
||||||
|
|
||||||
"@types/estree@1.0.8":
|
"@types/estree@1.0.8":
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
|
||||||
@@ -862,6 +867,11 @@ convert-source-map@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
|
||||||
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
||||||
|
|
||||||
|
crypto-js@4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
|
||||||
|
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
|
||||||
|
|
||||||
csstype@^3.0.2:
|
csstype@^3.0.2:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||||
|
|||||||
Reference in New Issue
Block a user