SecureToken을 하나로

This commit is contained in:
2023-08-19 06:58:38 +00:00
parent 194b213f61
commit 08890309c2
+22
View File
@@ -13,6 +13,7 @@ import { BSON } from "bson";
export type SecureEncryptedToken = { export type SecureEncryptedToken = {
nonce: string; // [key, iv] = SHA512(presharedSecret + nonce) nonce: string; // [key, iv] = SHA512(presharedSecret + nonce)
encrypted: 1;
type: string; // aad[0] type: string; // aad[0]
validUntil: string; // aad[1] validUntil: string; // aad[1]
payload: string; //BASE64(AES(BSON(aad),BSON(payload))) payload: string; //BASE64(AES(BSON(aad),BSON(payload)))
@@ -20,12 +21,15 @@ export type SecureEncryptedToken = {
export type SecurePlaintextToken = { export type SecurePlaintextToken = {
nonce: string; // [key, iv] = SHA512(presharedSecret + nonce) nonce: string; // [key, iv] = SHA512(presharedSecret + nonce)
encrypted: 0;
type: string; // aad[0] type: string; // aad[0]
validUntil: string; // aad[1] validUntil: string; // aad[1]
payload: string; // JSON => aad[2] payload: string; // JSON => aad[2]
tag: string; //BASE64(AES(BSON(aad),null))) tag: string; //BASE64(AES(BSON(aad),null)))
} }
export type SecureToken = SecureEncryptedToken | SecurePlaintextToken;
const staticPresharedTokenSecret: string | undefined = process.env.PRESHARED_TOKEN_SECRET; const staticPresharedTokenSecret: string | undefined = process.env.PRESHARED_TOKEN_SECRET;
export async function generateSecureEncryptedToken<T extends object>(validUntil: Date, type: string, payload: T, presharedTokenSecret?: string): Promise<SecureEncryptedToken> { export async function generateSecureEncryptedToken<T extends object>(validUntil: Date, type: string, payload: T, presharedTokenSecret?: string): Promise<SecureEncryptedToken> {
@@ -60,6 +64,7 @@ export async function generateSecureEncryptedToken<T extends object>(validUntil:
return { return {
nonce: nonce.toString('base64'), nonce: nonce.toString('base64'),
encrypted: 1,
type, type,
validUntil: validUntilText, validUntil: validUntilText,
payload: ciphertext.toString('base64'), payload: ciphertext.toString('base64'),
@@ -73,6 +78,10 @@ export async function parseSecureEncryptedToken<T extends object>(secureToken: S
throw new Error("token expired"); throw new Error("token expired");
} }
if(!secureToken.encrypted) {
throw new Error("token is not encrypted");
}
if (!presharedTokenSecret) { if (!presharedTokenSecret) {
if (!staticPresharedTokenSecret) { if (!staticPresharedTokenSecret) {
throw new Error("PRESHARED_TOKEN_SECRET is not set"); throw new Error("PRESHARED_TOKEN_SECRET is not set");
@@ -135,6 +144,7 @@ export async function generateSecurePlaintextToken<T extends object>(validUntil:
return { return {
nonce: nonce.toString('base64'), nonce: nonce.toString('base64'),
encrypted: 0,
type, type,
validUntil: validUntilText, validUntil: validUntilText,
payload: jsonPayload, payload: jsonPayload,
@@ -150,6 +160,10 @@ export async function parseSecurePlaintextToken<T extends object>(secureToken: S
presharedTokenSecret = staticPresharedTokenSecret; presharedTokenSecret = staticPresharedTokenSecret;
} }
if (secureToken.encrypted) {
throw new Error("token is encrypted");
}
const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8'); const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8');
const secretBuffer = Buffer.alloc(secretLength + 16); const secretBuffer = Buffer.alloc(secretLength + 16);
secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8'); secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8');
@@ -170,3 +184,11 @@ export async function parseSecurePlaintextToken<T extends object>(secureToken: S
return JSON.parse(secureToken.payload); return JSON.parse(secureToken.payload);
} }
export async function parseSecureToken<T extends object>(secureToken: SecureToken, presharedTokenSecret?: string): Promise<T> {
if (secureToken.encrypted) {
return await parseSecureEncryptedToken(secureToken, presharedTokenSecret);
} else {
return await parseSecurePlaintextToken(secureToken, presharedTokenSecret);
}
}