mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
[bugfix] Fix of AES encoding, test added
This commit is contained in:
@ -1049,8 +1049,10 @@ exports.encryptPassword = async function (ctx, password) {
|
||||
const cipher = crypto.createCipheriv('aes-256-gcm', encryptionKey, initializationVector);
|
||||
const encryptedData = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]);
|
||||
const authTag = cipher.getAuthTag();
|
||||
const predicate = iterations.toString(16);
|
||||
const data = Buffer.concat([salt, initializationVector, authTag, encryptedData]).toString('hex');
|
||||
|
||||
return Buffer.concat([salt, initializationVector, authTag, Buffer.from(iterations.toString()), encryptedData]).toString('hex');
|
||||
return `${predicate}:${data}`;
|
||||
};
|
||||
exports.decryptPassword = async function (ctx, password) {
|
||||
const pbkdf2Promise = util.promisify(crypto.pbkdf2);
|
||||
@ -1060,12 +1062,12 @@ exports.decryptPassword = async function (ctx, password) {
|
||||
keyByteLength = 32,
|
||||
saltByteLength = 64,
|
||||
initializationVectorByteLength = 16,
|
||||
iterationsByteLength = 5
|
||||
} = tenAESConfig;
|
||||
|
||||
const data = Buffer.from(password, 'hex');
|
||||
const [iterations, dataHex] = password.split(':');
|
||||
const data = Buffer.from(dataHex, 'hex');
|
||||
// authTag in node.js equals 16 bytes(128 bits), see https://stackoverflow.com/questions/33976117/does-node-js-crypto-use-fixed-tag-size-with-gcm-mode
|
||||
const delta = [saltByteLength, initializationVectorByteLength, 16, iterationsByteLength];
|
||||
const delta = [saltByteLength, initializationVectorByteLength, 16];
|
||||
const pointerArray = [];
|
||||
|
||||
for (let byte = 0, i = 0; i < delta.length; i++) {
|
||||
@ -1082,13 +1084,14 @@ exports.decryptPassword = async function (ctx, password) {
|
||||
salt,
|
||||
initializationVector,
|
||||
authTag,
|
||||
iterations
|
||||
encryptedData
|
||||
] = pointerArray;
|
||||
const decryptionKey = await pbkdf2Promise(tenSecret, salt, parseInt(iterations.toString(), 10), keyByteLength, 'sha512');
|
||||
|
||||
const decryptionKey = await pbkdf2Promise(tenSecret, salt, parseInt(iterations, 16), keyByteLength, 'sha512');
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm', decryptionKey, initializationVector);
|
||||
decipher.setAuthTag(authTag);
|
||||
|
||||
return Buffer.concat([decipher.update(password, 'binary'), decipher.final()]).toString();
|
||||
return Buffer.concat([decipher.update(encryptedData, 'binary'), decipher.final()]).toString();
|
||||
};
|
||||
exports.getDateTimeTicks = function(date) {
|
||||
return BigInt(date.getTime() * 10000) + 621355968000000000n;
|
||||
@ -1242,4 +1245,4 @@ function deepMergeObjects(target, ...sources) {
|
||||
return deepMergeObjects(target, ...sources);
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
exports.deepMergeObjects = deepMergeObjects;
|
||||
exports.deepMergeObjects = deepMergeObjects;
|
||||
|
||||
30
tests/unit/utils.tests.js
Normal file
30
tests/unit/utils.tests.js
Normal file
@ -0,0 +1,30 @@
|
||||
const { describe, test, expect } = require('@jest/globals');
|
||||
const config = require('../../Common/node_modules/config');
|
||||
|
||||
const operationContext = require('../../Common/sources/operationContext');
|
||||
const utils = require('../../Common/sources/utils');
|
||||
|
||||
const ctx = new operationContext.Context();
|
||||
const minimumIterationsByteLength = 4;
|
||||
|
||||
|
||||
describe('AES encryption & decryption', function () {
|
||||
test('Iterations range', async function () {
|
||||
const configuration = config.get('aesEncrypt.config');
|
||||
const encrypted = await utils.encryptPassword(ctx, 'secretstring');
|
||||
const { iterationsByteLength = 5 } = configuration;
|
||||
|
||||
const [iterationsHex] = encrypted.split(':');
|
||||
const iterations = parseInt(iterationsHex, 16);
|
||||
|
||||
const iterationsLength = iterationsByteLength < minimumIterationsByteLength ? minimumIterationsByteLength : iterationsByteLength;
|
||||
expect(iterations).toBeGreaterThanOrEqual(Math.pow(10, iterationsLength - 1));
|
||||
expect(iterations).toBeLessThanOrEqual(Math.pow(10, iterationsLength) - 1);
|
||||
});
|
||||
|
||||
test('Correct workflow', async function () {
|
||||
const encrypted = await utils.encryptPassword(ctx, 'secretstring');
|
||||
const decrypted = await utils.decryptPassword(ctx, encrypted);
|
||||
expect(decrypted).toEqual('secretstring');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user