/// <summary> /// Validate PDU against given MAC. /// </summary> /// <param name="pduBytes">PDU encoded as byte array</param> /// <param name="mac">MAC</param> /// <param name="key">message key</param> /// <returns>true if MAC is valid</returns> public static bool ValidateMac(byte[] pduBytes, ImprintTag mac, byte[] key) { if (pduBytes == null) { throw new ArgumentNullException(nameof(pduBytes)); } if (mac == null) { throw new ArgumentNullException(nameof(mac)); } if (pduBytes.Length < mac.Value.Algorithm.Length) { Logger.Warn("PDU MAC validation failed. PDU bytes array is too short to contain given MAC."); return(false); } DataHash calculatedMac = CalcMacValue(pduBytes, mac.Value.Algorithm, key); if (!calculatedMac.Equals(mac.Value)) { Logger.Warn("PDU MAC validation failed. Calculated MAC and given MAC do not match."); return(false); } return(true); }
public void TestDataHashEquals() { DataHash dataHash = new DataHash(new byte[] { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }); Assert.IsTrue( dataHash.Equals(new DataHash(new byte[] { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 })), "Hash should be equal to itself"); Assert.IsFalse( dataHash.Equals( new ChildDataHash(new byte[] { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }))); Assert.IsFalse(dataHash.Equals(null), "Hash should not equal to null"); Assert.IsFalse(dataHash.Equals(new object()), "Hash should not equal to empty object"); Assert.AreEqual( new DataHash(HashAlgorithm.Sha2256, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }), dataHash, "Hash should be equal to similar hash algorithm and value"); Assert.AreEqual("SHA-256:[0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20]", dataHash.ToString(), "Hash string representation should be in correct format"); }
/// <summary> /// Validate mac attached to PDU. /// </summary> /// <param name="pduBytes">PDU encoded as byte array</param> /// <param name="mac">MAC</param> /// <param name="key">message key</param> /// <returns>true if MAC is valid</returns> public static bool ValidateMac(byte[] pduBytes, ImprintTag mac, byte[] key) { if (pduBytes == null) { throw new ArgumentNullException(nameof(pduBytes)); } if (mac == null) { throw new ArgumentNullException(nameof(mac)); } if (pduBytes.Length < 1) { Logger.Warn("PDU MAC validation failed. PDU bytes array is empty."); return(false); } // We will use only header and payload for mac calculation. // It is assumed that mac tag is the last one. HashAlgorithm hashAlgorithm = mac.Value.Algorithm; int macTagLength = 3 + hashAlgorithm.Length; // tlv-8 header bytes + algorithm type byte + algorithm value bool tlv16 = (pduBytes[0] & Constants.Tlv.Tlv16Flag) != 0; int startFrom = tlv16 ? 4 : 2; int calcDataLength = pduBytes.Length - startFrom - macTagLength; if (calcDataLength < 0) { Logger.Warn("PDU MAC validation failed. PDU bytes array is too short to contain given MAC."); return(false); } byte[] target = new byte[calcDataLength]; Array.Copy(pduBytes, startFrom, target, 0, target.Length); DataHash calculatedMac = CalculateMac(hashAlgorithm, key, target); if (!calculatedMac.Equals(mac.Value)) { Logger.Warn("PDU MAC validation failed. Calculated MAC and given MAC do no match."); return(false); } return(true); }