Skip to content

Commit

Permalink
Add public API to enable the obf/deobf of a Dax.Metadata.Model obje…
Browse files Browse the repository at this point in the history
…ct (#16)

Introduce a public API to facilitate obfuscation and deobfuscation of a `Dax.Metadata.Model` object, eliminating the need for the VPAX file stream.
  • Loading branch information
albertospelta authored Mar 5, 2024
1 parent 99c237b commit ce325ac
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 30 deletions.
35 changes: 27 additions & 8 deletions src/Dax.Vpax.Obfuscator/IVpaxObfuscator.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
using Dax.Vpax.Obfuscator.Common;
using Dax.Metadata;
using Dax.Vpax.Obfuscator.Common;

namespace Dax.Vpax.Obfuscator;

public interface IVpaxObfuscator
{
/// <summary>
/// Obfuscate the DaxModel.json file and delete all other contents from the provided VPAX stream.
/// Obfuscate the DaxModel.json file and delete all other contents from the <paramref name="stream"/>.
/// </summary>
/// <param name="stream">The VPAX stream</param>
/// <returns>The obfuscation dictionary</returns>
/// <returns>The obfuscation dictionary generated from the obfuscation process</returns>
ObfuscationDictionary Obfuscate(Stream stream);

/// <summary>
/// Obfuscate the DaxModel.json file and delete all other contents from the provided VPAX stream.
/// Obfuscate the <paramref name="model"/>.
/// </summary>
/// <returns>The obfuscation dictionary generated from the obfuscation process</returns>
ObfuscationDictionary Obfuscate(Model model);

/// <summary>
/// Incrementally obfuscate the DaxModel.json file and delete all other contents from the <paramref name="stream"/>.
/// </summary>
/// <remarks>
/// This method updates the obfuscation dictionary to changes applied since a previous obfuscation.
/// </remarks>
/// <param name="stream">The VPAX stream</param>
/// <param name="dictionary">The obfuscation dictionary generated from a previous obfuscation</param>
/// <returns>The obfuscation dictionary updated to changes applied since a previous obfuscation.</returns>
/// <returns>The obfuscation <paramref name="dictionary"/> updated to changes applied since a previous obfuscation.</returns>
ObfuscationDictionary Obfuscate(Stream stream, ObfuscationDictionary dictionary);

/// <summary>
/// Incrementally obfuscate the <paramref name="model"/>.
/// </summary>
/// <param name="stream">The VPAX stream</param>
/// <param name="dictionary">The obfuscation dictionary generated from a previous obfuscation</param>
/// <returns>The obfuscation <paramref name="dictionary"/> updated to changes applied since a previous obfuscation.</returns>
ObfuscationDictionary Obfuscate(Model model, ObfuscationDictionary dictionary);

/// <summary>
/// Deobfuscate the DaxModel.json file using the provided obfuscation dictionary.
/// </summary>
/// <param name="stream">The VPAX stream</param>
/// <param name="dictionary">The obfuscation dictionary</param>
void Deobfuscate(Stream stream, ObfuscationDictionary dictionary);

/// <summary>
/// Deobfuscate the <paramref name="model"/> using the provided obfuscation dictionary.
/// </summary>
/// <param name="stream">The VPAX stream</param>
/// <param name="dictionary">The obfuscation dictionary</param>
void Deobfuscate(Model model, ObfuscationDictionary dictionary);
}
56 changes: 34 additions & 22 deletions src/Dax.Vpax.Obfuscator/VpaxObfuscator.cs
Original file line number Diff line number Diff line change
@@ -1,54 +1,66 @@
using System.IO.Packaging;
using Dax.Metadata;
using Dax.Vpax.Obfuscator.Common;
using Dax.Vpax.Tools;

namespace Dax.Vpax.Obfuscator;

public sealed class VpaxObfuscator : IVpaxObfuscator
{
/// <inheritdoc/>
public ObfuscationDictionary Obfuscate(Stream stream)
=> ObfuscateImpl(stream, dictionary: null);

/// <inheritdoc/>
public ObfuscationDictionary Obfuscate(Stream stream, ObfuscationDictionary dictionary)
=> ObfuscateImpl(stream, dictionary ?? throw new ArgumentNullException(nameof(dictionary)));

/// <inheritdoc/>
public void Deobfuscate(Stream stream, ObfuscationDictionary dictionary)
=> DeobfuscateImpl(stream, dictionary);
public ObfuscationDictionary Obfuscate(Stream stream) => ObfuscateImpl(stream, dictionary: null);
public ObfuscationDictionary Obfuscate(Model model) => ObfuscateImpl(model, dictionary: null);
public ObfuscationDictionary Obfuscate(Stream stream, ObfuscationDictionary dictionary) => ObfuscateImpl(stream, dictionary ?? throw new ArgumentNullException(nameof(dictionary)));
public ObfuscationDictionary Obfuscate(Model model, ObfuscationDictionary dictionary) => ObfuscateImpl(model, dictionary ?? throw new ArgumentNullException(nameof(dictionary)));
public void Deobfuscate(Stream stream, ObfuscationDictionary dictionary) => DeobfuscateImpl(stream, dictionary);
public void Deobfuscate(Model model, ObfuscationDictionary dictionary) => DeobfuscateImpl(model, dictionary);

private static ObfuscationDictionary ObfuscateImpl(Stream stream, ObfuscationDictionary? dictionary)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));

var model = VpaxTools.ImportVpax(stream, importDatabase: false).DaxModel
?? throw new InvalidOperationException($"The VPAX package does not contain a {VpaxFormat.DAXMODEL} file.");
var model = GetModel(stream);
var result = ObfuscateImpl(model, dictionary);

ZeroOutPackage(stream); // Zero out the package to remove all contents before writing the obfuscated DaxModel.json
VpaxTools.ExportVpax(stream, model, viewVpa: null, database: null);

return result;
}

// Zero out the package to remove all contents before writing the obfuscated DaxModel.json
ZeroOutPackage(stream);
private static ObfuscationDictionary ObfuscateImpl(Model model, ObfuscationDictionary? dictionary)
{
if (model == null) throw new ArgumentNullException(nameof(model));

var obfuscator = new DaxModelObfuscator(model, dictionary);
obfuscator.Obfuscate();
var texts = obfuscator.Texts.Select((t) => new ObfuscationText(t.Value, t.ObfuscatedValue)).ToArray();
var result = new ObfuscationDictionary(id: model.ObfuscatorDictionaryId, texts);

VpaxTools.ExportVpax(stream, model, viewVpa: null, database: null);
return result;
var texts = obfuscator.Texts.Select((t) => new ObfuscationText(t.Value, t.ObfuscatedValue)).ToArray();
return new ObfuscationDictionary(id: model.ObfuscatorDictionaryId, texts);
}

private static void DeobfuscateImpl(Stream stream, ObfuscationDictionary dictionary)
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
if (dictionary == null) throw new ArgumentNullException(nameof(dictionary));

var model = VpaxTools.ImportVpax(stream, importDatabase: false).DaxModel
?? throw new InvalidOperationException($"The VPAX package does not contain a {VpaxFormat.DAXMODEL} file.");
var model = GetModel(stream);
DeobfuscateImpl(model, dictionary);
VpaxTools.ExportVpax(stream, model, viewVpa: null, database: null);
}

private static void DeobfuscateImpl(Model model, ObfuscationDictionary dictionary)
{
if (model == null) throw new ArgumentNullException(nameof(model));
if (dictionary == null) throw new ArgumentNullException(nameof(dictionary));

var deobfuscator = new DaxModelDeobfuscator(model, dictionary);
deobfuscator.Deobfuscate();
}

VpaxTools.ExportVpax(stream, model, viewVpa: null, database: null);
private static Model GetModel(Stream stream)
{
var model = VpaxTools.ImportVpax(stream, importDatabase: false).DaxModel;
return model ?? throw new InvalidOperationException($"The VPAX package does not contain a {VpaxFormat.DAXMODEL} file.");
}

private static void ZeroOutPackage(Stream stream)
Expand Down

0 comments on commit ce325ac

Please sign in to comment.