Darren
Darren

Reputation: 51

Obfuscation with JSON.net

I am using Json.Net for serialization and unserialization on a class. When I try to obsfucate the class in an assembly, I will not be able to unserialize the JSON string correctly. I have try using JsonProperty Attribute but it still not able to unserialize correctly.

Does anyone know how to get around this other than setting the class not to obsfucate?

Thanks in advance.

Updates:

I have created a simple class for JSON object as below:

public class JsonTestClass
{
    [JsonProperty("JsonID")]
    public int Id { get; set; }

    [JsonProperty("JsonName")]
    public string Name { get; set; }

    [JsonProperty("JsonYesNo")]
    public bool YesNo { get; set; }
}

And the code to serialize JsonTestClass objects into Json string is:

 //Serialize
 var jsonObj = new JsonTestClass()
 {
     Id = 1,
     Name = "John",
     YesNo = true,
 };

 var JsonStr = JsonConvert.SerializeObject(jsonObj);
 Trace.WriteLine(">>" + JsonStr);

And unserialize Json string to JsonTestClass is as follow:

//Unserialize
var JsonStr = "{\"JsonID\":1,\"JsonName\":\"John Abc\",\"JsonYesNo\":true}";
Trace.WriteLine("<<" + JsonStr);

var jsonObj = JsonConvert.DeserializeObject<JsonTestClass>(JsonStr);
if (jsonObj == null)
{
    Trace.WriteLine("-- JsonObj is null");
}
else
{
    Trace.WriteLine(string.Format("-- Id={0} Name={1} YesNo={2}", jsonObj.Id, jsonObj.Name, jsonObj.YesNo));
}

Everything works fine unobsfucated and the debug output for serialization is:

[64200] >>{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true} 

And debug output for deserialization is:

[64200] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true} 
[64200] -- Id=1 Name=John Abc YesNo=True 

After the assembly has been obsfucated (using SmartAssembly to obsfucate this) and using dotPeek to see the obsfucated assembly, the only one which somewhat resemble the JsonTestClass are:

namespace
{
   internal class
   {
   }
}

The debug output for serialization is:

[65956] >>{} 

The debug output for deserialization is:

[65956] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true} 
[65956] -- Id=0 Name= YesNo=False 

Hope this helps to clear things up.

Upvotes: 4

Views: 3791

Answers (3)

Rekshino
Rekshino

Reputation: 7325

Quick and easy solution is to decorate a class with [Serializable] attribute, this should remove renaming obfuscation for this class.

[Serializable]
public class JsonTestClass
{...}

Upvotes: 0

Andrew
Andrew

Reputation: 392

There are a couple of options, depending on your preference as to maintainability, security, etc.

Excluding properties from obfuscation

If it's just the type names that you're concerned about being obfuscated and not the property names, then you can decorate each property that is to be serialized with the Obfuscation attribute. (Here is the link for Dotfuscator's support for this attribute.) Basically, by excluding the property from renaming, this will allow Json.NET to easily identify the properties to set.

[Obfuscation(Exclude=true, Feature="renaming")]
public int MyProperty { get; set; }
  • Pros: Easy and straightforward
  • Cons: You lose some security by not obfuscating your property names.

Expose the private backing field for deserialization

Another way to get Json.NET to deserialize an obfuscated class is to change the target of the deserialization from the public property to the private field using the JsonProperty attribute, e.g.

[JsonProperty("a")]
private int _myField;

[JsonIgnore]
public int MyProperty
{
   get => _myField;
   set => _myField = value;
}

NOTE: If you use "MyProperty" or nameof(MyProperty) in the JsonProperty attribute, then depending on your obfuscation settings it's very possible that it will be compiled into the .dll as "MyProperty", thus reducing the overall security that you were trying to achieve with obfuscation in the first place.

NOTE 2: This solution will most likely not work when working with the MVVM design pattern. When using this pattern, a common coding practice is to utilize the property setter to raise the INotifyPropertyChanged event. However, using the JsonProperty and JsonIgnore attributes will cause Json.NET to set the value directly on the private field using reflection instead of the via the property setter. Therefore the change event will not be raised, making this a poor solution in this particular scenario.

  • Pros: You can maintain full obfuscation of your property names.
  • Cons: You need to create backing fields for every obfuscated property that you want to participate in serialization/deserialization. Also, may break the INotifyPropertyChanged functionality when using with the MVVM pattern, depending on your implementation details.

Upvotes: 1

If you are using Dotfuscator which is shipped as Community Edition with Visual Studio 15 and Visual Studio 17, you have to exclude the property names of the object you serialize from renaming. You do this in the Dotfuscator renaming tab.

After that you can serialize and deserialize like normal.

You find a detailed description here in the support corner of the Preemtive Solutions web site.

Upvotes: 1

Related Questions