Skip to content

Commit 7905fc9

Browse files
Hexdump CDN hashes
1 parent 5cb017b commit 7905fc9

4 files changed

Lines changed: 145 additions & 0 deletions

File tree

src/util/Signing.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import { Config } from "@spacebar/util";
2020
import { createHmac, timingSafeEqual } from "node:crypto";
2121
import ms, { StringValue } from "ms";
22+
import { TextDecoder } from "node:util";
23+
import { ConsoleUtils } from "./util/ConsoleUtils";
24+
import { ColorUtils } from "./util/ColorUtils";
2225

2326
export class NewUrlUserSignatureData {
2427
ip?: string;
@@ -132,11 +135,14 @@ export const getUrlSignature = (data: NewUrlSignatureData): UrlSignResult => {
132135

133136
function calculateHash(request: UrlSignatureData): UrlSignResult {
134137
const { cdnSignatureKey } = Config.get().security;
138+
const newData = createHmac("sha256", cdnSignatureKey as string);
135139
const data = createHmac("sha256", cdnSignatureKey as string)
136140
.update(request.path!)
137141
.update(request.issuedAt)
138142
.update(request.expiresAt);
139143

144+
let ipData = new Int8Array();
145+
140146
if (Config.get().security.cdnSignatureIncludeIp) {
141147
if (!request.ip)
142148
console.log(
@@ -145,9 +151,11 @@ function calculateHash(request: UrlSignatureData): UrlSignResult {
145151
else {
146152
if (process.env["LOG_CDN_SIGNATURES"]) console.log("[Signing] CDN Signature IP is enabled, adding IP to hash:", request.ip);
147153
data.update(request.ip!);
154+
ipData = new Int8Array(new TextEncoder().encode(request.ip!));
148155
}
149156
}
150157

158+
let userAgentData = new Int8Array();
151159
if (Config.get().security.cdnSignatureIncludeUserAgent) {
152160
if (!request.userAgent)
153161
console.log(
@@ -156,10 +164,29 @@ function calculateHash(request: UrlSignatureData): UrlSignResult {
156164
else {
157165
if (process.env["LOG_CDN_SIGNATURES"]) console.log("[Signing] CDN Signature User-Agent is enabled, adding User-Agent to hash:", request.userAgent);
158166
data.update(request.userAgent!);
167+
userAgentData = new Int8Array(new TextEncoder().encode(request.userAgent!));
159168
}
160169
}
161170

171+
const rawData = new Int8Array([
172+
...new TextEncoder().encode(request.path!),
173+
...new TextEncoder().encode(request.issuedAt),
174+
...new TextEncoder().encode(request.expiresAt),
175+
...ipData,
176+
...userAgentData,
177+
]);
178+
if (process.env["LOG_CDN_SIGNATURES"]) {
179+
console.log("[Signing] Signature data for ", request.path!);
180+
hexdump(rawData);
181+
}
182+
newData.update(rawData);
183+
162184
const hash = data.digest("hex");
185+
const newHash = newData.digest("hex");
186+
if (process.env["LOG_CDN_SIGNATURES"]) {
187+
console.log(hash);
188+
console.log(newHash);
189+
}
163190
const result = new UrlSignResult({
164191
path: request.path,
165192
issuedAt: request.issuedAt,
@@ -257,3 +284,29 @@ export const hasValidSignature = (req: NewUrlUserSignatureData, sig: UrlSignResu
257284

258285
return isHashValid;
259286
};
287+
288+
// port of https://github.com/TheArcaneBrony/ArcaneLibs/blob/master/ArcaneLibs/Extensions/DictionaryExtensions.cs#L80
289+
function hexdump(arr: Int8Array, width: number = 32, colorize: boolean = true) {
290+
const colorizeFunc = colorize ? (val: number, str: string) => ConsoleUtils.ColoredString(str, ColorUtils.cnv8To24(val)) : (val: number, str: string) => str;
291+
for (let i = 0; i < arr.length; i += width) {
292+
const end = Math.min(i + width, arr.length);
293+
const section = arr.slice(i, end);
294+
console.log(
295+
Array.from(section)
296+
.map((x) => colorizeFunc(x, x.toString(16).toUpperCase()))
297+
.join(" ")
298+
.padEnd(3 * section.length),
299+
"|",
300+
new TextDecoder("utf-8")
301+
.decode(section)
302+
.replaceAll("\n", ".")
303+
.replaceAll("\r", ".")
304+
.replaceAll("\0", ".")
305+
.replaceAll("\t", ".")
306+
.replaceAll("\v", ".")
307+
.replaceAll("\b", ".")
308+
.replaceAll("\x07", ".") // \a
309+
.replaceAll("\f", "."),
310+
);
311+
}
312+
}

src/util/util/ColorUtils.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
3+
Copyright (C) 2023 Spacebar and Spacebar Contributors
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published
7+
by the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Affero General Public License for more details.
14+
15+
You should have received a copy of the GNU Affero General Public License
16+
along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
export class RgbValue {
20+
r: number;
21+
g: number;
22+
b: number;
23+
constructor(r: number, g: number, b: number) {
24+
this.r = r;
25+
this.g = g;
26+
this.b = b;
27+
}
28+
29+
public asHex(withSigil: boolean = true) {
30+
return `${withSigil ? "#" : ""}${this.r.toString(16).toUpperCase()}${this.g.toString(16).toUpperCase()}${this.b.toString(16).toUpperCase()}`;
31+
}
32+
33+
public asAnsiEscapeSequence() {
34+
return `\x1b[38;2;${this.r};${this.g};${this.b}m`;
35+
}
36+
}
37+
38+
export class ColorUtils {
39+
public static cnv8To24(val: number): RgbValue {
40+
return new RgbValue((val >> 5) * 32, ((val & 28) >> 2) * 32, (val & 3) * 64);
41+
}
42+
}

src/util/util/ConsoleUtils.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
3+
Copyright (C) 2026 Spacebar and Spacebar Contributors
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published
7+
by the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Affero General Public License for more details.
14+
15+
You should have received a copy of the GNU Affero General Public License
16+
along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
// Minor port of https://github.com/TheArcaneBrony/ArcaneLibs/blob/master/ArcaneLibs/ConsoleUtils.cs
20+
import { RgbValue } from "./ColorUtils";
21+
22+
export class ConsoleUtils {
23+
public static ColorSequence(rgb: RgbValue) {
24+
return rgb.asAnsiEscapeSequence();
25+
}
26+
public static SetConsoleColor(rgb: RgbValue) {
27+
console.log(rgb.asAnsiEscapeSequence());
28+
}
29+
public static ColoredString(text: string, rgb: RgbValue) {
30+
return rgb.asAnsiEscapeSequence() + text + "\x1b[0m";
31+
}
32+
}

src/util/util/Logo.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
3+
Copyright (C) 2023 Spacebar and Spacebar Contributors
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published
7+
by the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Affero General Public License for more details.
14+
15+
You should have received a copy of the GNU Affero General Public License
16+
along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
119
import { KittyLogo } from ".";
220
import { blueBright } from "picocolors";
321

0 commit comments

Comments
 (0)