diff --git a/src/actions.ts b/src/actions.ts index 40bcadd..a12d05c 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -14,26 +14,13 @@ import {Replays} from './replays'; import {ActionError, QueryHandler, Server} from './server'; import {Session} from './user'; import { - toID, updateserver, bash, time, escapeHTML, encrypt, decrypt, makeEncryptKey, randomString, + toID, updateserver, bash, time, escapeHTML, signAsync, } from './utils'; import * as tables from './tables'; import {SQL} from './database'; import IPTools from './ip-tools'; const OAUTH_TOKEN_TIME = 2 * 7 * 24 * 60 * 60 * 1000; -const SMOGON_KEY = (() => { - let keyData; - if (!Config.smogonpath) return makeEncryptKey(randomString(), Math.random() + ""); - try { - keyData = readFileSync(Config.smogonpath, 'utf-8'); - } catch { - keyData = randomString() + "\n" + Math.random(); - writeFileSync(Config.smogonpath, keyData); - } - const [key, salt] = keyData.split('\n'); - return makeEncryptKey(key, salt); -})(); -const SMOGON_VALIDATION_PREFIX = 'valid\n'; async function getOAuthClient(clientId?: string, origin?: string) { if (!clientId) throw new ActionError("No client_id provided."); @@ -919,7 +906,7 @@ export const actions: {[k: string]: QueryHandler} = { }, // sent by ps server - 'smogon/encrypt'(params) { + async 'smogon/validate'(params) { if (this.getIp() !== Config.restartip) { throw new ActionError("Access denied."); } @@ -928,24 +915,9 @@ export const actions: {[k: string]: QueryHandler} = { throw new ActionError("Invalid PS username provided."); } return { - encrypted_username: encrypt(SMOGON_KEY, SMOGON_VALIDATION_PREFIX + params.username), + signed_username: await signAsync("RSA-SHA1", params.username, Config.privatekey), }; }, - - // sent by smogon to validate given encrypted name - 'smogon/validate'(params) { - if (this.getIp() !== Config.smogonip) { - throw new ActionError("Access denied."); - } - if (!params.encrypted_name || !toID(params.encrypted_name)) { - throw new ActionError("No encrypted name provided."); - } - const out = decrypt(SMOGON_KEY, decodeURIComponent(params.encrypted_name)); - if (!out || !out.startsWith(SMOGON_VALIDATION_PREFIX)) { - return {decrypted_name: null}; - } - return {decrypted_name: out.slice(SMOGON_VALIDATION_PREFIX.length)}; - }, }; if (Config.actions) { diff --git a/src/utils.ts b/src/utils.ts index eeb387c..66538bb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -104,49 +104,3 @@ export function escapeHTML(str: string | number) { .replace(/"/g, '"') .replace(/'/g, '''); } - -const IV_LENGTH = 16; - -const NONCE_LENGTH = 20; - -export function encrypt(key: Buffer, text: string) { - const nonce = crypto.randomBytes(NONCE_LENGTH); - const iv = Buffer.alloc(IV_LENGTH); - nonce.copy(iv); - - const cipher = crypto.createCipheriv('aes-256-ctr', key, iv); - const encrypted = cipher.update(text.toString()); - return Buffer.concat([nonce, encrypted, cipher.final()]).toString('base64'); -} - -export function decrypt(key: Buffer, text: string) { - const message = Buffer.from(text, 'base64'); - const iv = Buffer.alloc(IV_LENGTH); - message.copy(iv, 0, 0, NONCE_LENGTH); - const decipher = crypto.createDecipheriv('aes-256-ctr', key, iv); - let decrypted = decipher.update(message.slice(NONCE_LENGTH)); - try { - decrypted = Buffer.concat([decrypted, decipher.final()]); - return decrypted.toString(); - } catch (err) { - return null; - } -} - -// 32 chars - 256 bytes -export function randomString(len = 32) { - let chars = 'abcdefghijklmnopqrstuvwxyz'; - chars += chars.toUpperCase(); - chars += "1234567890"; - chars += "()-={}|!@#$%^&*?><:"; - - let key = ""; - for (let i = 0; i < len; i++) { - key += chars[Math.round(Math.random() * chars.length)]; - } - return key; -} - -export function makeEncryptKey(keyStr: string, saltStr: string) { - return crypto.pbkdf2Sync(keyStr, saltStr, 10000, keyStr.length, 'sha512'); -}