mirror of
https://github.com/AssetRipper/AssetRipper.Checksum.git
synced 2026-11-13 18:06:11 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0718c9c7c0 | ||
|
|
dda1975aa8 | ||
|
|
b72e7ba10b |
No files matched your search
@@ -1,18 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.9.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace AssetRipper.Checksum.Tests;
|
||||
public partial class ReversalTests
|
||||
{
|
||||
[GeneratedRegex("[H-Wh-w]{6}[HJLN]")]
|
||||
private static partial Regex ReverseOutputRegex();
|
||||
private static partial Regex ReverseOutputRegex { get; }
|
||||
|
||||
[Test]
|
||||
public void TestReversalSymmetryAndRegexMatching()
|
||||
@@ -13,33 +13,47 @@ public partial class ReversalTests
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
uint hash = RandomHash;
|
||||
string reversed = Crc32Algorithm.ReverseAscii(hash);
|
||||
Assert.Multiple(() =>
|
||||
string reversed = Crc32Algorithm.Reverse(hash);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(Crc32Algorithm.HashAscii(reversed), Is.EqualTo(hash));
|
||||
Assert.That(ReverseOutputRegex().IsMatch(reversed));
|
||||
});
|
||||
Assert.That(ReverseOutputRegex.IsMatch(reversed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReversalLengthIsSeven()
|
||||
{
|
||||
string reversed = Crc32Algorithm.ReverseAscii(RandomHash);
|
||||
string reversed = Crc32Algorithm.Reverse(RandomHash);
|
||||
Assert.That(reversed, Has.Length.EqualTo(7));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PrefixedReversal()
|
||||
[TestCase("Prefix_")]
|
||||
public void PrefixedReversal_Ascii(string prefix)
|
||||
{
|
||||
const string prefix = "Prefix_";
|
||||
uint hash = RandomHash;
|
||||
string reversed = Crc32Algorithm.ReverseAscii(hash, prefix);
|
||||
Assert.Multiple(() =>
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(Crc32Algorithm.HashAscii(reversed), Is.EqualTo(hash));
|
||||
Assert.That(reversed, Does.StartWith(prefix));
|
||||
});
|
||||
Assert.That(reversed, Has.Length.EqualTo(7 + prefix.Length));
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("Prefix_")]
|
||||
[TestCase("\u60A8\u597D", Description = "Hello in Chinese")]
|
||||
public void PrefixedReversal_UTF8(string prefix)
|
||||
{
|
||||
uint hash = RandomHash;
|
||||
string reversed = Crc32Algorithm.ReverseUTF8(hash, prefix);
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(Crc32Algorithm.HashUTF8(reversed), Is.EqualTo(hash));
|
||||
Assert.That(reversed, Does.StartWith(prefix));
|
||||
Assert.That(reversed, Has.Length.EqualTo(7 + prefix.Length));
|
||||
}
|
||||
}
|
||||
|
||||
private static uint RandomHash => TestContext.CurrentContext.Random.NextUInt();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||
<PackageReference Include="System.IO.Hashing" Version="9.0.7" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -13,9 +13,9 @@ static partial class Crc32Algorithm
|
||||
/// </remarks>
|
||||
/// <param name="hash">A CRC32 checksum</param>
|
||||
/// <returns>An Ascii string of length 7 with that <paramref name="hash"/></returns>
|
||||
public static string ReverseAscii(uint hash)
|
||||
public static string Reverse(uint hash)
|
||||
{
|
||||
return ReverseAscii(hash, default, defaultInitialMask);
|
||||
return Reverse(hash, default, defaultInitialMask);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,10 +31,26 @@ static partial class Crc32Algorithm
|
||||
public static string ReverseAscii(uint hash, ReadOnlySpan<char> prefix)
|
||||
{
|
||||
uint reverseInitialMask = HashAscii(prefix, HHHHHHH);
|
||||
return ReverseAscii(hash, prefix, reverseInitialMask);
|
||||
return Reverse(hash, prefix, reverseInitialMask);
|
||||
}
|
||||
|
||||
private static string ReverseAscii(uint hash, ReadOnlySpan<char> prefix, uint reverseInitialMask)
|
||||
/// <summary>
|
||||
/// Find a conflicting UTF8 string with Gaussian Elimination
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The output is one-to-one and starts with <paramref name="prefix"/>. The suffix matches [H-Wh-w]{6}[HJLN] <br />
|
||||
/// Based on <see href="https://gitlab.com/-/snippets/2369762">work</see> by <see href="https://gitlab.com/lox9973">lox9973</see> licensed under MIT.
|
||||
/// </remarks>
|
||||
/// <param name="hash">A CRC32 checksum</param>
|
||||
/// <param name="prefix">A span of characters that will be prepended to the output</param>
|
||||
/// <returns>An UTF8 string of length <paramref name="prefix"/>.Length + 7 with that <paramref name="hash"/></returns>
|
||||
public static string ReverseUTF8(uint hash, ReadOnlySpan<char> prefix)
|
||||
{
|
||||
uint reverseInitialMask = HashUTF8(prefix, HHHHHHH);
|
||||
return Reverse(hash, prefix, reverseInitialMask);
|
||||
}
|
||||
|
||||
private static string Reverse(uint hash, ReadOnlySpan<char> prefix, uint reverseInitialMask)
|
||||
{
|
||||
uint b = hash ^ reverseInitialMask;
|
||||
|
||||
|
||||
@@ -72,6 +72,16 @@ public static partial class Crc32Algorithm
|
||||
return result;
|
||||
}
|
||||
|
||||
private static uint HashUTF8(ReadOnlySpan<char> str1, ReadOnlySpan<char> str2)
|
||||
{
|
||||
crc ??= new();
|
||||
crc.Reset();
|
||||
crc.UpdateUTF8(str1);
|
||||
crc.UpdateUTF8(str2);
|
||||
|
||||
return crc.FinishHash();
|
||||
}
|
||||
|
||||
public static bool MatchAscii(ReadOnlySpan<char> data, uint hash)
|
||||
{
|
||||
return HashAscii(data) == hash;
|
||||
@@ -91,6 +101,34 @@ public static partial class Crc32Algorithm
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateUTF8(this Crc32 @this, ReadOnlySpan<char> data)
|
||||
{
|
||||
int count = (int)(uint)Encoding.UTF8.GetByteCount(data);
|
||||
|
||||
byte[]? rentedArray;
|
||||
scoped Span<byte> buffer;
|
||||
if (count > 1024)
|
||||
{
|
||||
rentedArray = ArrayPool<byte>.Shared.Rent(count);
|
||||
buffer = new Span<byte>(rentedArray, 0, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
rentedArray = null;
|
||||
buffer = stackalloc byte[count];
|
||||
}
|
||||
|
||||
int encoded = Encoding.UTF8.GetBytes(data, buffer);
|
||||
Debug.Assert(encoded == count);
|
||||
|
||||
@this.Append(buffer);
|
||||
|
||||
if (rentedArray is not null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(rentedArray);
|
||||
}
|
||||
}
|
||||
|
||||
private static uint FinishHash(this Crc32 @this)
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[sizeof(uint)];
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
|
||||
<Version>1.0.0</Version>
|
||||
<Version>1.1.0</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
<Copyright>Copyright © ds5678</Copyright>
|
||||
<Authors>ds5678</Authors>
|
||||
|
||||
Reference in new issue
Block a user