英文:
Any .NET MD5 library (Nuget) for Blazor (WebAssembly)?
问题
.NET有MD5类。然而,在Blazor中不可用:
我找不到任何第三方库,可能是因为它在.NET中受支持,所以没有人制作它。是否有任何替代方案?(如果您想知道,我不需要它来哈希密码,而是为了Gravatar,所以必须是MD5)。
我知道有一个解决方法,那就是使用JavaScript,但如果可能的话,我不想使用JS互操作(https://stackoverflow.com/questions/1655769/fastest-md5-implementation-in-javascript)。
英文:
I know .NET has MD5 class. However it's not available in Blazor:
I can't find any 3rd-party library maybe because it's supported in .NET so nobody makes it. Is there any alternative? (I don't need it for hashing password in case you want to know, it's for Gravatar so it must be MD5).
I know there's a workaround that is to use Javascript instead but I want to not using JS interop if possible (https://stackoverflow.com/questions/1655769/fastest-md5-implementation-in-javascript)
答案1
得分: 1
以下是代码的翻译部分:
有趣的问题。首先是代码。这不是我的代码,但我稍微修改了它,以更符合System.Security.Cryptography.MD5类。
public static class MD5
{
public static byte[] ComputeHash(byte[] input)
{
uint num = 1732584193u;
uint num2 = 4023233417u;
uint num3 = 2562383102u;
uint num4 = 271733878u;
int num5 = (56 - (input.Length + 1) % 64) % 64;
byte[] array = new byte[input.Length + 1 + num5 + 8];
Array.Copy(input, array, input.Length);
array[input.Length] = 128;
Array.Copy(BitConverter.GetBytes(input.Length * 8), 0, array, array.Length - 8, 4);
for (int i = 0; i < array.Length / 64; i++)
{
uint[] array2 = new uint[16];
for (int j = 0; j < 16; j++)
{
array2[j] = BitConverter.ToUInt32(array, i * 64 + j * 4);
}
uint num6 = num;
uint num7 = num2;
uint num8 = num3;
uint num9 = num4;
uint num10 = 0u;
uint num11 = 0u;
uint num12 = 0u;
while (true)
{
switch (num12)
{
case 0u:
case 1u:
case 2u:
case 3u:
case 4u:
case 5u:
case 6u:
case 7u:
case 8u:
case 9u:
case 10u:
case 11u:
case 12u:
case 13u:
case 14u:
case 15u:
num10 = num7 & num8 | ~num7 & num9;
num11 = num12;
goto IL_0138;
case 16u:
case 17u:
case 18u:
case 19u:
case 20u:
case 21u:
case 22u:
case 23u:
case 24u:
case 25u:
case 26u:
case 27u:
case 28u:
case 29u:
case 30u:
case 31u:
case 32u:
case 33u:
case 34u:
case 35u:
case 36u:
case 37u:
case 38u:
case 39u:
case 40u:
case 41u:
case 42u:
case 43u:
case 44u:
case 45u:
case 46u:
case 47u:
case 48u:
case 49u:
case 50u:
case 51u:
case 52u:
case 53u:
case 54u:
case 55u:
case 56u:
case 57u:
case 58u:
case 59u:
case 60u:
case 61u:
case 62u:
case 63u:
if (num12 >= 16 && num12 <= 31)
{
num10 = num9 & num7 | ~num9 & num8;
num11 = (5 * num12 + 1) % 16u;
}
else if (num12 >= 32 && num12 <= 47)
{
num10 = num7 ^ num8 ^ num9;
num11 = (3 * num12 + 5) % 16u;
}
else if (num12 >= 48)
{
num10 = num8 ^ (num7 | ~num9);
num11 = 7 * num12 % 16u;
}
goto IL_0138;
}
break;
IL_0138:
uint num13 = num9;
num9 = num8;
num8 = num7;
num7 += leftRotate(num6 + num10 + K[num12] + array2[num11], s[num12]);
num6 = num13;
num12++;
}
num += num6;
num2 += num7;
num3 += num8;
num4 += num9;
}
var hashBytes = new byte[16];
BitConverter.GetBytes(num).CopyTo(hashBytes, 0);
BitConverter.GetBytes(num2).CopyTo(hashBytes, 4);
BitConverter.GetBytes(num3).CopyTo(hashBytes, 8);
BitConverter.GetBytes(num4).CopyTo(hashBytes, 12);
return hashBytes;
}
public static string ComputeHashString(byte[] input) => string.Join("", ComputeHash(input).Select(o => o.ToString("x2")));
private static int[] s = new int[64]
{
7, 12, 17, 22, 7, 12, 17, 22, 7, 12,
17, 22, 7, 12, 17, 22, 5, 9, 14, 20,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9,
14, 20, 4, 11, 16, 23, 4, 11, 16, 23,
4, 11, 16, 23, 4, 11, 16, 23, 6, 10,
15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
6, 10, 15, 21
};
private static uint[] K = new uint[64]
{
3614090360u, 3905402710u, 606105819u, 3250441966u, 4118548399u, 1200080426u, 2821735955u, 4249261313u, 1770035416u, 2336552879u,
4294925233u, 2304563134u, 1804603682u, 4254626195u, 2792965006u, 1236535329u, 4129170786u, 3225465664u, 643717713u, 3921069994
<details>
<summary>英文:</summary>
Interesting question. First the code. This is not mine but I did modify it slightly to align more with the System.Security.Cryptography.MD5 class.
```cs
public static class MD5
{
public static byte[] ComputeHash(byte[] input)
{
uint num = 1732584193u;
uint num2 = 4023233417u;
uint num3 = 2562383102u;
uint num4 = 271733878u;
int num5 = (56 - (input.Length + 1) % 64) % 64;
byte[] array = new byte[input.Length + 1 + num5 + 8];
Array.Copy(input, array, input.Length);
array[input.Length] = 128;
Array.Copy(BitConverter.GetBytes(input.Length * 8), 0, array, array.Length - 8, 4);
for (int i = 0; i < array.Length / 64; i++)
{
uint[] array2 = new uint[16];
for (int j = 0; j < 16; j++)
{
array2[j] = BitConverter.ToUInt32(array, i * 64 + j * 4);
}
uint num6 = num;
uint num7 = num2;
uint num8 = num3;
uint num9 = num4;
uint num10 = 0u;
uint num11 = 0u;
uint num12 = 0u;
while (true)
{
switch (num12)
{
case 0u:
case 1u:
case 2u:
case 3u:
case 4u:
case 5u:
case 6u:
case 7u:
case 8u:
case 9u:
case 10u:
case 11u:
case 12u:
case 13u:
case 14u:
case 15u:
num10 = num7 & num8 | ~num7 & num9;
num11 = num12;
goto IL_0138;
case 16u:
case 17u:
case 18u:
case 19u:
case 20u:
case 21u:
case 22u:
case 23u:
case 24u:
case 25u:
case 26u:
case 27u:
case 28u:
case 29u:
case 30u:
case 31u:
case 32u:
case 33u:
case 34u:
case 35u:
case 36u:
case 37u:
case 38u:
case 39u:
case 40u:
case 41u:
case 42u:
case 43u:
case 44u:
case 45u:
case 46u:
case 47u:
case 48u:
case 49u:
case 50u:
case 51u:
case 52u:
case 53u:
case 54u:
case 55u:
case 56u:
case 57u:
case 58u:
case 59u:
case 60u:
case 61u:
case 62u:
case 63u:
if (num12 >= 16 && num12 <= 31)
{
num10 = num9 & num7 | ~num9 & num8;
num11 = (5 * num12 + 1) % 16u;
}
else if (num12 >= 32 && num12 <= 47)
{
num10 = num7 ^ num8 ^ num9;
num11 = (3 * num12 + 5) % 16u;
}
else if (num12 >= 48)
{
num10 = num8 ^ (num7 | ~num9);
num11 = 7 * num12 % 16u;
}
goto IL_0138;
}
break;
IL_0138:
uint num13 = num9;
num9 = num8;
num8 = num7;
num7 += leftRotate(num6 + num10 + K[num12] + array2[num11], s[num12]);
num6 = num13;
num12++;
}
num += num6;
num2 += num7;
num3 += num8;
num4 += num9;
}
var hashBytes = new byte[16];
BitConverter.GetBytes(num).CopyTo(hashBytes, 0);
BitConverter.GetBytes(num2).CopyTo(hashBytes, 4);
BitConverter.GetBytes(num3).CopyTo(hashBytes, 8);
BitConverter.GetBytes(num4).CopyTo(hashBytes, 12);
return hashBytes;
}
public static string ComputeHashString(byte[] input) => string.Join("", ComputeHash(input).Select(o => o.ToString("x2")));
private static int[] s = new int[64]
{
7, 12, 17, 22, 7, 12, 17, 22, 7, 12,
17, 22, 7, 12, 17, 22, 5, 9, 14, 20,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9,
14, 20, 4, 11, 16, 23, 4, 11, 16, 23,
4, 11, 16, 23, 4, 11, 16, 23, 6, 10,
15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
6, 10, 15, 21
};
private static uint[] K = new uint[64]
{
3614090360u, 3905402710u, 606105819u, 3250441966u, 4118548399u, 1200080426u, 2821735955u, 4249261313u, 1770035416u, 2336552879u,
4294925233u, 2304563134u, 1804603682u, 4254626195u, 2792965006u, 1236535329u, 4129170786u, 3225465664u, 643717713u, 3921069994u,
3593408605u, 38016083u, 3634488961u, 3889429448u, 568446438u, 3275163606u, 4107603335u, 1163531501u, 2850285829u, 4243563512u,
1735328473u, 2368359562u, 4294588738u, 2272392833u, 1839030562u, 4259657740u, 2763975236u, 1272893353u, 4139469664u, 3200236656u,
681279174u, 3936430074u, 3572445317u, 76029189u, 3654602809u, 3873151461u, 530742520u, 3299628645u, 4096336452u, 1126891415u,
2878612391u, 4237533241u, 1700485571u, 2399980690u, 4293915773u, 2240044497u, 1873313359u, 4264355552u, 2734768916u, 1309151649u,
4149444226u, 3174756917u, 718787259u, 3951481745u
};
private static uint leftRotate(uint x, int c)
{
return x << c | x >> 32 - c;
}
}
Example use that should return the same output as the System.Security.Cryptography.MD5 version.
var hashBytes = MD5.ComputeHash(Encoding.UTF8.GetBytes("apples"));
Test I ran to compare the two MD5 methods. Used a .Net 8 console app so System.Security.Cryptography.MD5 would be available for the test.
var testStringBytes = Encoding.UTF8.GetBytes("apples");
// This MD5 (pure C#)
var applesMD51 = MD5.ComputeHash(testStringBytes);
var applesMD51String = string.Join("", applesMD51.Select(o => o.ToString("x2")));
Console.WriteLine(applesMD51String);
// output: "daeccf0ad3c1fc8c8015205c332f5b42"
// System.Security.Cryptography.MD5
using var x = System.Security.Cryptography.MD5.Create();
var applesMD52 = x.ComputeHash(testStringBytes);
var applesMD52String = string.Join("", applesMD52.Select(o => o.ToString("x2")));
Console.WriteLine(applesMD52String);
// output: "daeccf0ad3c1fc8c8015205c332f5b42"
That code was found in a popular open source Blazor UI framework Radzen.Blazor. If you are using Radzen, it is Radzen.MD5.
I did find it interesting that the System.Security.Cryptography classes SHA256 and SHA512 work in Blazor WASM but its MD5 class does not. Probably because they want to retire it but I can see uses for backwards compatibility with older stuff.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论