Skip to content

Commit

Permalink
fix(view-state): crypto
Browse files Browse the repository at this point in the history
  • Loading branch information
ido-pluto committed Dec 26, 2023
1 parent df2665e commit 811da77
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
6 changes: 0 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
"@astro-utils/context": "0.0.1",
"await-lock": "^2.2.2",
"cookie": "^0.5.0",
"cryptr": "^6.3.0",
"csrf": "^3.1.0",
"deepmerge": "^4.3.1",
"jsonwebtoken": "^9.0.0",
Expand Down
29 changes: 22 additions & 7 deletions packages/forms/src/components-control/form-utils/view-state.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import {AstroGlobal} from 'astro';
import Cryptr from 'cryptr';
import superjson from 'superjson';
import {parseFormData} from '../../form-tools/post.js';
import {FormsSettings, getFormOptions} from '../../settings.js';
import {BindForm} from './bind-form.js';
import snappy from 'snappy';
import {getSomeProps} from '../props-utils.js';
import crypto from 'crypto';

const CRYPTO_ALGORITHM = 'aes-256-gcm';

export default class ViewStateManager {
private readonly _FORM_OPTIONS: FormsSettings;
private readonly _cryptr: Cryptr;
private _VALID_KEY: string;

get filedName() {
if (!this._FORM_OPTIONS.forms) {
Expand All @@ -33,8 +35,12 @@ export default class ViewStateManager {
if (!this._FORM_OPTIONS.secret) {
throw new Error('Secret not set in form options');
}
this._initKey();
}

this._cryptr = new Cryptr(this._FORM_OPTIONS.secret, {'encoding': 'base64'});
private _initKey() {
const repeat = Math.ceil(this._FORM_OPTIONS.secret.length / 32);
this._VALID_KEY = this._FORM_OPTIONS.secret.repeat(repeat).slice(0, 32);
}

private async _extractStateFromForm() {
Expand All @@ -46,9 +52,13 @@ export default class ViewStateManager {
try {
const state = await this._extractStateFromForm();
if(state == null) return;

const data = this._cryptr.decrypt(state);
const uncompress = await snappy.uncompress(Buffer.from(data, 'base64'));

const [iv, content] = state.split('.');

const decipher = crypto.createDecipheriv(CRYPTO_ALGORITHM, this._VALID_KEY, Buffer.from(iv, 'base64'));
const decrypted = Buffer.concat([decipher.update(Buffer.from(content, 'base64')), decipher.final()]);

const uncompress = await snappy.uncompress(decrypted);
return superjson.parse(uncompress.toString());
} catch (error: any) {
this._FORM_OPTIONS.logs?.('warn', `ViewStateManager: ${error.message}`);
Expand Down Expand Up @@ -76,6 +86,11 @@ export default class ViewStateManager {

const stringify = superjson.stringify(data);
const compress = await snappy.compress(stringify, {});
return this._cryptr.encrypt(compress.toString('base64'));

const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(CRYPTO_ALGORITHM, this._VALID_KEY, iv);
const encrypted = Buffer.concat([cipher.update(compress), cipher.final()]);

return `${iv.toString('base64')}.${encrypted.toString('base64')}`;
}
}

0 comments on commit 811da77

Please sign in to comment.