private void HashObject(JObject obj, JObject salts = null) { byte[][] hashList = new byte[obj.Count][]; int i = 0; foreach ((string key, JToken value) in obj) { if (!salts.IsNullOrEmpty() && !salts.ContainsKey(key)) { IDictionary additionalExceptionData = new Dictionary <string, object> { { "missingKey", key } }; throw new BadRequestException( "The provided JSON defines an object which is different from the Salts object. Please check the JSON or the salt data.", additionalExceptionData); } ObjectHashImplementation jKeyHash = new ObjectHashImplementation(); jKeyHash.HashString(key); // TODO: check if acceptable // object keys are not salted, i don't see a big issue alternative would be jKeyHash.HashString(SALT + o.Key); but its quite difficult for an user to store the salts for object keys ObjectHashImplementation jValHash = new ObjectHashImplementation(); jValHash.HashJToken(value, salts.IsNullOrEmpty() ? null : salts[key]); // merge both hashes (of key and value) hashList[i] = jKeyHash.Hash.Concat(jValHash.Hash).ToArray(); i++; } // objects should always be sorted HashListOfHashes(hashList, 'd', true); }
private void AddTaggedByteArray(char tag, byte[] byteArray, JToken salt = null) { // copying of byteArrays is quite ugly but there is no nicer way in C# to join two byte arrays byte[] merged = new byte[byteArray.Length + 1]; byteArray.CopyTo(merged, 1); merged[0] = (byte)tag; byte[] tempHash = _digester.ComputeHash(merged); if (salt != null) { // validate the salt is hex and block size long HexConverter.ValidateStringIsHexAndBlockLength(salt); // hash salt to equally distribute randomness ObjectHashImplementation jKeyHash = new ObjectHashImplementation(); jKeyHash.HashString((string)salt); // merge salt and object hash as list byte[][] hashList = new byte[2][]; hashList[0] = jKeyHash.Hash; hashList[1] = tempHash; HashListOfHashes(hashList, 'l'); } else { Hash = tempHash; } }
private static (JToken json, JToken salts) RecursiveRedactDataAndSalts(JToken json, JToken redactSettings, JToken salts = null) { // ReSharper disable once SwitchStatementMissingSomeCases switch (redactSettings.Type) { case JTokenType.Boolean: if (!(bool)redactSettings) { return(json, salts); } ObjectHashImplementation objectHash = new ObjectHashImplementation(); objectHash.HashJToken(json, salts); return("**REDACTED**" + objectHash.HashAsString(), "**REDACTED**"); case JTokenType.Object: try { return(RedactObject((JObject)json, (JObject)redactSettings, salts.IsNullOrEmpty() ? null : (JObject)salts)); } catch (InvalidCastException e) { throw new BadRequestException( "The provided JSON does not contain an object -> {} where the redact settings require one. Please check the JSON data or the redact settings.", e); } case JTokenType.Array: try { return(RedactArray((JArray)json, (JArray)redactSettings, salts.IsNullOrEmpty() ? null : (JArray)salts)); } catch (InvalidCastException e) { throw new BadRequestException( "The provided JSON does not contain an array -> [] where the redact settings require one. Please check the JSON data or the redact settings", e); } case JTokenType.Null: { return(json, salts); } default: throw new BadRequestException( "The redact setting JSON is invalid. It can only contain a nested JSON, arrays and the data type Boolean."); } }
private void HashArray(JArray array, JArray salts = null) { if (!salts.IsNullOrEmpty() && salts.Count != array.Count) { throw new BadRequestException( "The corresponding JSON object contains an array that is different in size from the Salts array. They need to be equally long."); } byte[][] hashList = new byte[array.Count][]; for (int i = 0; i < array.Count; i++) { ObjectHashImplementation aElementHash = new ObjectHashImplementation(); aElementHash.HashJToken(array[i], salts.IsNullOrEmpty() ? null : salts[i]); hashList[i] = aElementHash.Hash; } // sorting arrays can be needed, but the default should be not to sort arrays HashListOfHashes(hashList, 'l', Globals.SORT_ARRAY); }
// ReSharper disable once UnusedMember.Global public int CompareTo(ObjectHashImplementation other) { return(string.Compare(HashAsString(), other.HashAsString(), Globals.STRING_COMPARE_METHOD)); }