Контрольная сумма изменена при создании с тем же объектом - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть алгоритм для генерации и возврата контрольной суммы при вызове операции обновления.Во втором обновлении необходимо отправить заданную контрольную сумму, которая является доказательством того, что объект точно такой же.В противном случае исключение - throw.

Вот мой класс, используемый для управления контрольной суммой:

public class TokenUpdate
{
    internal readonly DateTime expireDateTime;
    private static readonly Object locker = new Object();
    internal readonly byte[] _dataTokenKey;

    public TokenUpdate(object insuranceAgreement, DateTime newExpireDateTime)
    {
        expireDateTime = newExpireDateTime;
        _dataTokenKey = GetSignedToken(insuranceAgreement);

    }

    public TokenUpdate(byte[] dataTokenKey, DateTime newExpireDateTime)
    {
        expireDateTime = newExpireDateTime;
        _dataTokenKey = dataTokenKey;

    }
    public bool IsExpired
    {
        get
        {
            return !(expireDateTime > DateTime.Now);
        }
    }

    public byte[] GetSignedToken(object insuranceAgreement)
    {
        byte[] tokenKey;

        byte[] tokenData;

        // serialize data in byte[]
        using (var ms = new MemoryStream())
        {
            using (var writer = new BinaryWriter(ms))
            {
                writer.Write(ObjectToByteArray(insuranceAgreement));
                tokenData = ms.ToArray();
            }
        }


        using (var sha1 = new SHA256Managed())
        {
            tokenKey = sha1.ComputeHash(tokenData);
        }


        return tokenKey;
    }

    public string GetTokenString()
    {
        byte[] tokenData;

        // serialize data in byte[]
        using (var ms = new MemoryStream())
        {
            using (var writer = new BinaryWriter(ms))
            {
                writer.Write(expireDateTime.Ticks);
                tokenData = ms.ToArray();
            }
        }


        return Convert.ToBase64String(tokenData.Concat(_dataTokenKey).ToArray());
    }

    public static TokenUpdate BuildToken(object insuranceAgreement, DateTime expireDateTime)
    {
        if (insuranceAgreement == null)
        {
            return null;
        }

        return new TokenUpdate(insuranceAgreement, expireDateTime);
    }

    public static bool AreEqual(TokenUpdate token, object toCompare)
    {
        var compareToken = new TokenUpdate(toCompare, DateTime.Now);


        return token._dataTokenKey.SequenceEqual(compareToken._dataTokenKey);
    }

    public static TokenUpdate GetTokenFromString(string tokenString)
    {
        TokenUpdate returnedToken = null;
        byte[] buffer;
        try
        {
            buffer = Convert.FromBase64String(tokenString);
        }
        catch (FormatException)
        {
            return null;
        }

        if (buffer.Length != 40)
        {
            return null;
        }

        var data = buffer.Take(buffer.Length - 32).ToArray();
        var sig = buffer.Skip(data.Length).Take(32).ToArray();
        using (var ms = new MemoryStream(data))
        using (var reader = new BinaryReader(ms))
        {
            var ticks = reader.ReadInt64();
            var expires = new DateTime(ticks);
            returnedToken = new TokenUpdate(sig, expires);
        }

        return returnedToken;
    }

    internal static byte[] ObjectToByteArray(object objectToSerialize)
    {
        if (objectToSerialize == null)
        {
            return null;
        }

        MemoryStream fs = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();
        try
        {
            //Here's the core functionality! One Line!
            //To be thread-safe we lock the object
            lock (locker)
            {
                formatter.Serialize(fs, objectToSerialize);
            }
            return fs.ToArray();
        }
        catch (SerializationException se)
        {
            throw;
        }
        finally
        {
            fs.Close();
        }
    }
}

С некоторым модульным тестом все в порядке, но выполнение некоторого стресс-теста показывает нам, что вВ 30% случаев второе обновление отклонено, потому что сравнение контрольной суммы, отправленной с данными, сгенерированными из данных в базе данных, не удается.

Я проверил, и я почти уверен, что нет внутреннего обновлениямежду двумя другими.

Мне интересно, связан ли алгоритм хеширования с классом SHA256Managed, относящимся к mac-адресу системы datetime?Это может вызвать проблему, потому что мы сбалансированы по нагрузке.

...