Verschlüsselung korrigiert

This commit is contained in:
Torsten Schulz
2024-07-21 15:12:56 +02:00
parent 597761cb15
commit 12d66d6f9c
4 changed files with 98 additions and 12 deletions

View File

@@ -1,6 +1,7 @@
import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import bcrypt from 'bcrypt';
import { encrypt, generateIv } from '../../utils/encryption.js';
const User = sequelize.define('user', {
email: {
@@ -8,9 +9,17 @@ const User = sequelize.define('user', {
allowNull: false,
unique: true,
set(value) {
this.setDataValue('email', bcrypt.hashSync(value, 10));
if (value) {
const iv = generateIv();
this.setDataValue('iv', iv.toString('hex'));
this.setDataValue('email', encrypt(value, iv));
}
}
},
iv: {
type: DataTypes.STRING,
allowNull: false
},
username: {
type: DataTypes.STRING,
allowNull: false,
@@ -19,6 +28,9 @@ const User = sequelize.define('user', {
password: {
type: DataTypes.STRING,
allowNull: false,
set(value) {
this.setDataValue('password', bcrypt.hashSync(value, 10));
}
},
registrationDate: {
type: DataTypes.DATE,
@@ -29,7 +41,7 @@ const User = sequelize.define('user', {
type: DataTypes.BOOLEAN,
defaultValue: false
},
resetToken: {
resetToken: {
type: DataTypes.UUID,
allowNull: true
},
@@ -40,7 +52,7 @@ const User = sequelize.define('user', {
}, {
tableName: 'user',
schema: 'community',
underscored: true,
underscored: true
});
export default User;

View File

@@ -2,6 +2,7 @@ import { sequelize } from '../../utils/sequelize.js';
import { DataTypes } from 'sequelize';
import User from './user.js';
import UserParamType from '../type/user_param.js';
import { encrypt, decrypt, generateIv } from '../../utils/encryption.js';
const UserParam = sequelize.define('user_param', {
userId: {
@@ -18,20 +19,52 @@ const UserParam = sequelize.define('user_param', {
references: {
model: UserParamType,
key: 'id'
},
}
},
value: {
type: DataTypes.STRING,
allowNull: false,
set(value) {
if (value) {
const iv = generateIv();
this.setDataValue('iv', iv.toString('hex'));
this.setDataValue('value', encrypt(value, iv));
}
}
},
iv: {
type: DataTypes.STRING,
allowNull: false
}
}, {
tableName: 'user_param',
schema: 'community',
underscored: true
underscored: true,
hooks: {
beforeSave: (userParam) => {
if (userParam.value && !userParam.iv) {
const iv = generateIv();
userParam.iv = iv.toString('hex');
userParam.value = encrypt(userParam.value, iv);
}
},
afterFind: (userParams) => {
if (userParams) {
if (Array.isArray(userParams)) {
userParams.forEach((userParam) => {
const iv = Buffer.from(userParam.iv, 'hex');
userParam.value = decrypt(userParam.value, iv);
});
} else {
const iv = Buffer.from(userParams.iv, 'hex');
userParams.value = decrypt(userParams.value, iv);
}
}
}
}
});
UserParam.belongsTo(User, { foreignKey: 'userId' });
UserParam.belongsTo(UserParamType, { foreignKey: 'param_type_id' });
UserParam.belongsTo(UserParamType, { foreignKey: 'paramTypeId' });
export default UserParam;

View File

@@ -8,31 +8,40 @@ import { sendAccountActivationEmail, sendPasswordResetEmail } from './emailServi
const saltRounds = 10;
export const registerUser = async ({ email, username, password, language }) => {
const [results] = await sequelize.query(
'SELECT * FROM "community"."user" WHERE pgp_sym_decrypt("email", :key) = :email',
{
replacements: { key: process.env.SECRET_KEY, email },
type: sequelize.QueryTypes.SELECT
}
);
if (results.length > 0) {
throw new Error('Email already in use');
}
const iv = generateIv();
const encryptedEmail = encrypt(email, iv);
const hashedPassword = await bcrypt.hash(password, saltRounds);
const resetToken = uuidv4();
const user = await User.create({
email,
email: encryptedEmail,
iv: iv.toString('hex'),
username,
password: hashedPassword,
resetToken: resetToken,
active: false,
registration_date: new Date()
});
const languageType = await UserParamType.findOne({ where: { description: 'language' } });
if (!languageType) {
throw new Error('Language type not found');
}
await UserParam.create({
userId: user.id,
paramTypeId: languageType.id,
value: language
});
const activationLink = `${process.env.FRONTEND_URL}/activate?token=${resetToken}`;
await sendAccountActivationEmail(email, activationLink, username, resetToken, language);
return { id: user.hashedId, username: user.username, active: user.active };
};

View File

@@ -0,0 +1,32 @@
import crypto from 'crypto';
import dotenv from 'dotenv';
dotenv.config(); // Laden der Umgebungsvariablen
const algorithm = 'aes-256-cbc';
const secretKey = process.env.SECRET_KEY;
if (!secretKey || secretKey.length !== 32) {
throw new Error('SECRET_KEY length must be 32 bytes');
}
const encrypt = (text, iv) => {
const cipher = crypto.createCipheriv(algorithm, Buffer.from(secretKey, 'utf-8'), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
};
const decrypt = (encryptedText, iv) => {
const encryptedBuffer = Buffer.from(encryptedText, 'hex');
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(secretKey, 'utf-8'), iv);
let decrypted = decipher.update(encryptedBuffer);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
};
const generateIv = () => {
return crypto.randomBytes(16);
};
export { encrypt, decrypt, generateIv };