From 08e493dc6d9d187a41fb06a472f6583fa1c5ab5d Mon Sep 17 00:00:00 2001 From: ThePlayer372 Date: Wed, 4 Mar 2026 15:01:24 +0100 Subject: [PATCH] Add: Flask Sign Tests, Visualize Timestamp --- src/core/operations/FlaskSessionDecode.mjs | 24 ++- src/core/operations/FlaskSessionVerify.mjs | 32 +++- tests/operations/tests/FlaskSession.mjs | 202 ++++++++++++++++++++- 3 files changed, 246 insertions(+), 12 deletions(-) diff --git a/src/core/operations/FlaskSessionDecode.mjs b/src/core/operations/FlaskSessionDecode.mjs index 304b99e2..5486357e 100644 --- a/src/core/operations/FlaskSessionDecode.mjs +++ b/src/core/operations/FlaskSessionDecode.mjs @@ -22,7 +22,13 @@ class FlaskSessionDecode extends Operation { this.description = "Decodes the payload of a Flask session cookie (itsdangerous) into JSON."; this.inputType = "string"; this.outputType = "JSON"; - this.args = []; + this.args = [ + { + name: "View TimeStamp", + type: "boolean", + value: false + } + ]; } /** @@ -38,6 +44,16 @@ class FlaskSessionDecode extends Operation { } const payloadB64 = parts[0]; + const time = parts[1]; + + const timeB64 = time.replace(/-/g, "+").replace(/_/g, "/"); + const binary = fromBase64(timeB64); + const bytes = new Uint8Array(4); + for (let i = 0; i < 4; i++) { + bytes[i] = binary.charCodeAt(i); + } + const view = new DataView(bytes.buffer); + const timestamp = view.getInt32(0, false); const base64 = payloadB64.replace(/-/g, "+").replace(/_/g, "/"); const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "="); @@ -49,7 +65,11 @@ class FlaskSessionDecode extends Operation { } try { - const data = JSON.parse(payloadJson); + let data = JSON.parse(payloadJson); + + if (args[0]) { + data = {payload: data, timestamp: timestamp}; + } return data; } catch (e) { throw new OperationError("Unable to decode JSON payload: " + e.message); diff --git a/src/core/operations/FlaskSessionVerify.mjs b/src/core/operations/FlaskSessionVerify.mjs index 2399b8ae..7603ba1f 100644 --- a/src/core/operations/FlaskSessionVerify.mjs +++ b/src/core/operations/FlaskSessionVerify.mjs @@ -41,6 +41,11 @@ class FlaskSessionVerify extends Operation { name: "Algorithm", type: "option", value: ["sha1", "sha256"], + }, + { + name: "View TimeStamp", + type: "boolean", + value: true } ]; } @@ -81,6 +86,17 @@ class FlaskSessionVerify extends Operation { const base64 = payloadB64.replace(/-/g, "+").replace(/_/g, "/"); const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "="); + const time = parts[1]; + + const timeB64 = time.replace(/-/g, "+").replace(/_/g, "/"); + const binary = fromBase64(timeB64); + const bytes = new Uint8Array(4); + for (let i = 0; i < 4; i++) { + bytes[i] = binary.charCodeAt(i); + } + const view = new DataView(bytes.buffer); + const timestamp = view.getInt32(0, false); + let payloadJson; try { payloadJson = fromBase64(padded); @@ -97,10 +113,18 @@ class FlaskSessionVerify extends Operation { try { const decoded = JSON.parse(payloadJson); - return { - valid: true, - payload: decoded, - }; + if (!args[3]) { + return { + valid: true, + payload: decoded, + }; + } else { + return { + valid: true, + payload: decoded, + timestamp: timestamp + }; + } } catch (e) { throw new OperationError("Unable to decode JSON payload: " + e.message); } diff --git a/tests/operations/tests/FlaskSession.mjs b/tests/operations/tests/FlaskSession.mjs index 40271c68..7becf400 100644 --- a/tests/operations/tests/FlaskSession.mjs +++ b/tests/operations/tests/FlaskSession.mjs @@ -8,8 +8,12 @@ import TestRegister from "../../lib/TestRegister.mjs"; -const validToken = "eyJyb2xlIjoic3VwZXJ1c2VyIiwidXNlciI6ImFkbWluIn0.aZ-KEw.E_x6bOhA4GU9t72pMinJUjN-O3I"; +const validTokenSha1 = "eyJyb2xlIjoic3VwZXJ1c2VyIiwidXNlciI6ImFkbWluIn0.aZ-KEw.E_x6bOhA4GU9t72pMinJUjN-O3I"; +const validTokenSha256 = "eyJyb2xlIjoic3VwZXJ1c2VyIiwidXNlciI6ImFkbWluIn0.aab3Ew.Jsx2DOx_H9anZg0YcvhsASxQ11897EFHeQfS2oja4y8"; + const validKey = "mysecretkey"; +const wrongKey = "notTheKey"; + const outputObject = { user: "admin", role: "superuser", @@ -23,18 +27,20 @@ const outputVerify = { TestRegister.addTests([ { name: "Flask Session: Decode", - input: validToken, + input: validTokenSha1, expectedOutput: outputObject, recipeConfig: [ { op: "Flask Session Decode", - args: [], + args: [ + false + ], } ] }, { - name: "Flask Session: Verify", - input: validToken, + name: "Flask Session: Verify Sha1", + input: validTokenSha1, expectedOutput: outputVerify, recipeConfig: [ { @@ -48,9 +54,193 @@ TestRegister.addTests([ string: "cookie-session", option: "UTF8" }, - "sha1" + "sha1", + false, ], } ] }, + { + name: "Flask Session: Verify Sha256", + input: validTokenSha256, + expectedOutput: outputVerify, + recipeConfig: [ + { + op: "Flask Session Verify", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha256", + false, + ], + } + ] + }, + { + name: "Flask Session: Sign Sha1", + input: outputObject, + expectedOutput: outputVerify, + recipeConfig: [ + { + op: "Flask Session Sign", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha1" + ] + }, + { + op: "Flask Session Verify", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha1", + false, + ], + } + ] + }, + { + name: "Flask Session: Sign Sha256", + input: outputObject, + expectedOutput: outputVerify, + recipeConfig: [ + { + op: "Flask Session Sign", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha256" + ] + }, + { + op: "Flask Session Verify", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha256", + false, + ], + } + ] + }, + { + name: "Flask Session: Verify Sha1 Wrong Key", + input: validTokenSha1, + expectedOutput: "Invalid signature!", + recipeConfig: [ + { + op: "Flask Session Verify", + args: [ + { + string: wrongKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha1", + false, + ], + } + ] + }, + { + name: "Flask Session: Verify Sha256 Wrong Key", + input: validTokenSha256, + expectedOutput: "Invalid signature!", + recipeConfig: [ + { + op: "Flask Session Verify", + args: [ + { + string: wrongKey, + option: "UTF8" + }, + { + string: "cookie-session", + option: "UTF8" + }, + "sha256", + false, + ], + } + ] + }, + { + name: "Flask Session: Verify Sha1 Wrong Salt", + input: validTokenSha1, + expectedOutput: "Invalid signature!", + recipeConfig: [ + { + op: "Flask Session Verify", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "notTheSalt", + option: "UTF8" + }, + "sha1", + false, + ], + } + ] + }, + { + name: "Flask Session: Verify Sha256 Wrong Salt", + input: validTokenSha256, + expectedOutput: "Invalid signature!", + recipeConfig: [ + { + op: "Flask Session Verify", + args: [ + { + string: validKey, + option: "UTF8" + }, + { + string: "notTheSalt", + option: "UTF8" + }, + "sha256", + false, + ], + } + ] + }, + ]);