icynet-auth-server/src/modules/utility/services/token.service.ts

98 lines
2.5 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import * as crypto from 'crypto';
import { ConfigurationService } from 'src/modules/config/config.service';
import { v4 } from 'uuid';
import * as CSRF from 'csrf';
import { Request } from 'express';
const IV_LENGTH = 16;
const ALGORITHM = 'aes-256-cbc';
@Injectable()
export class TokenService {
public csrf = new CSRF({
saltLength: 16,
secretLength: 32,
});
constructor(private config: ConfigurationService) {}
public verifyCSRF(req: Request, token?: string): boolean {
return this.csrf.verify(req.cookies.XSRF, token || req.body._csrf);
}
public generateString(length: number): string {
return crypto.randomBytes(length).toString('hex').slice(0, length);
}
public generateSecret(): string {
return crypto.randomBytes(256 / 8).toString('hex');
}
public insecureHash(input: string): string {
return crypto.createHash('md5').update(input).digest('hex');
}
public createUUID(): string {
return v4();
}
// https://stackoverflow.com/q/52212430
/**
* Symmetric encryption function
* @param text String to encrypt
* @param key Encryption key
* @returns Encrypted text
*/
public encrypt(text: string, key: string): string {
const iv = crypto.randomBytes(IV_LENGTH);
const cipher = crypto.createCipheriv(
ALGORITHM,
Buffer.from(key, 'hex'),
iv,
);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
}
/**
* Symmetric decryption function
* @param text Encrypted string
* @param key Decryption key
* @returns Decrypted text
*/
public decrypt(text: string, key: string): string {
const [iv, encryptedText] = text
.split(':')
.map((part) => Buffer.from(part, 'hex'));
const decipher = crypto.createDecipheriv(
ALGORITHM,
Buffer.from(key, 'hex'),
iv,
);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
public async encryptChallenge(
challenge: Record<string, any>,
): Promise<string> {
return this.encrypt(
JSON.stringify(challenge),
this.config.get<string>('app.challenge_secret'),
);
}
public async decryptChallenge(
challenge: string,
): Promise<Record<string, any>> {
return JSON.parse(
this.decrypt(challenge, this.config.get<string>('app.challenge_secret')),
);
}
}