From 79f19be90414f828827860d547be1f50cca9ece2 Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Sat, 1 Apr 2017 15:37:21 +0300 Subject: [PATCH] tmp --- dotnet/WhiteRabbit/MD5Digest.cs | 321 +++++++++++++----- dotnet/WhiteRabbit/Phrase.cs | 49 --- dotnet/WhiteRabbit/PhrasesChunk.cs | 69 ++++ dotnet/WhiteRabbit/PhrasesHashesChunk.cs | 12 + .../PrecomputedPermutationsGenerator.cs | 16 +- dotnet/WhiteRabbit/Program.cs | 6 + dotnet/WhiteRabbit/StringsProcessor.cs | 32 +- dotnet/WhiteRabbit/WhiteRabbit.csproj | 3 +- rust/.gitignore | 10 + rust/Cargo.toml | 5 + rust/src/main.rs | 3 + 11 files changed, 376 insertions(+), 150 deletions(-) delete mode 100644 dotnet/WhiteRabbit/Phrase.cs create mode 100644 dotnet/WhiteRabbit/PhrasesChunk.cs create mode 100644 dotnet/WhiteRabbit/PhrasesHashesChunk.cs create mode 100644 rust/.gitignore create mode 100644 rust/Cargo.toml create mode 100644 rust/src/main.rs diff --git a/dotnet/WhiteRabbit/MD5Digest.cs b/dotnet/WhiteRabbit/MD5Digest.cs index d1c19b5..2c50827 100644 --- a/dotnet/WhiteRabbit/MD5Digest.cs +++ b/dotnet/WhiteRabbit/MD5Digest.cs @@ -1,8 +1,6 @@ namespace WhiteRabbit { - using System; - using System.Linq; - using System.Reflection; + using System.Numerics; /** * Code taken from BouncyCastle and optimized for specific constraints (e.g. input is always larger than 4 bytes and smaller than 52 bytes). @@ -13,89 +11,240 @@ */ internal static class MD5Digest { - public static unsafe uint[] Compute(Phrase input) + private static readonly Vector K1 = new Vector(0xd76aa478); + private static readonly Vector K2 = new Vector(0xe8c7b756); + private static readonly Vector K3 = new Vector(0x242070db); + private static readonly Vector K4 = new Vector(0xc1bdceee); + private static readonly Vector K5 = new Vector(0xf57c0faf); + private static readonly Vector K6 = new Vector(0x4787c62a); + private static readonly Vector K7 = new Vector(0xa8304613); + private static readonly Vector K8 = new Vector(0xfd469501); + private static readonly Vector K9 = new Vector(0x698098d8); + private static readonly Vector K10 = new Vector(0x8b44f7af); + private static readonly Vector K11 = new Vector(0xffff5bb1); + private static readonly Vector K12 = new Vector(0x895cd7be); + private static readonly Vector K13 = new Vector(0x6b901122); + private static readonly Vector K14 = new Vector(0xfd987193); + private static readonly Vector K15 = new Vector(0xa679438e); + private static readonly Vector K16 = new Vector(0x49b40821); + + private static readonly Vector K17 = new Vector(0xf61e2562); + private static readonly Vector K18 = new Vector(0xc040b340); + private static readonly Vector K19 = new Vector(0x265e5a51); + private static readonly Vector K20 = new Vector(0xe9b6c7aa); + private static readonly Vector K21 = new Vector(0xd62f105d); + private static readonly Vector K22 = new Vector(0x2441453); + private static readonly Vector K23 = new Vector(0xd8a1e681); + private static readonly Vector K24 = new Vector(0xe7d3fbc8); + private static readonly Vector K25 = new Vector(0x21e1cde6); + private static readonly Vector K26 = new Vector(0xc33707d6); + private static readonly Vector K27 = new Vector(0xf4d50d87); + private static readonly Vector K28 = new Vector(0x455a14ed); + private static readonly Vector K29 = new Vector(0xa9e3e905); + private static readonly Vector K30 = new Vector(0xfcefa3f8); + private static readonly Vector K31 = new Vector(0x676f02d9); + private static readonly Vector K32 = new Vector(0x8d2a4c8a); + + private static readonly Vector K33 = new Vector(0xfffa3942); + private static readonly Vector K34 = new Vector(0x8771f681); + private static readonly Vector K35 = new Vector(0x6d9d6122); + private static readonly Vector K36 = new Vector(0xfde5380c); + private static readonly Vector K37 = new Vector(0xa4beea44); + private static readonly Vector K38 = new Vector(0x4bdecfa9); + private static readonly Vector K39 = new Vector(0xf6bb4b60); + private static readonly Vector K40 = new Vector(0xbebfbc70); + private static readonly Vector K41 = new Vector(0x289b7ec6); + private static readonly Vector K42 = new Vector(0xeaa127fa); + private static readonly Vector K43 = new Vector(0xd4ef3085); + private static readonly Vector K44 = new Vector(0x4881d05); + private static readonly Vector K45 = new Vector(0xd9d4d039); + private static readonly Vector K46 = new Vector(0xe6db99e5); + private static readonly Vector K47 = new Vector(0x1fa27cf8); + private static readonly Vector K48 = new Vector(0xc4ac5665); + + private static readonly Vector K49 = new Vector(0xf4292244); + private static readonly Vector K50 = new Vector(0x432aff97); + private static readonly Vector K51 = new Vector(0xab9423a7); + private static readonly Vector K52 = new Vector(0xfc93a039); + private static readonly Vector K53 = new Vector(0x655b59c3); + private static readonly Vector K54 = new Vector(0x8f0ccc92); + private static readonly Vector K55 = new Vector(0xffeff47d); + private static readonly Vector K56 = new Vector(0x85845dd1); + private static readonly Vector K57 = new Vector(0x6fa87e4f); + private static readonly Vector K58 = new Vector(0xfe2ce6e0); + private static readonly Vector K59 = new Vector(0xa3014314); + private static readonly Vector K60 = new Vector(0x4e0811a1); + private static readonly Vector K61 = new Vector(0xf7537e82); + private static readonly Vector K62 = new Vector(0xbd3af235); + private static readonly Vector K63 = new Vector(0x2ad7d2bb); + private static readonly Vector K64 = new Vector(0xeb86d391); + + private static readonly Vector A0 = new Vector(0x67452301); + private static readonly Vector B0 = new Vector(0xefcdab89); + private static readonly Vector C0 = new Vector(0x98badcfe); + private static readonly Vector D0 = new Vector(0x10325476); + + public static unsafe PhrasesHashesChunk Compute(PhrasesChunk input) { - var xUints = stackalloc uint[8]; // it seems that alignment helps - *(long*)xUints = *(long*)input.Buffer; - *(long*)(xUints + 2) = *(long*)(input.Buffer + 8); - *(long*)(xUints + 4) = *(long*)(input.Buffer + 16); - *(long*)(xUints + 6) = *(long*)(input.Buffer + 24); - ((byte*)xUints)[31] = 0; - ((byte*)xUints)[input.Buffer[31]] = 128; - xUints[7] = (uint)(input.Buffer[31] << 3); - - uint a = 0x67452301; - uint b = 0xefcdab89; - uint c = 0x98badcfe; - uint d = 0x10325476; - - a = LeftRotate(xUints[0] + 0xd76aa478 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; - d = LeftRotate(xUints[1] + 0xe8c7b756 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; - c = LeftRotate(xUints[2] + 0x242070db + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; - b = LeftRotate(xUints[3] + 0xc1bdceee + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; - a = LeftRotate(xUints[4] + 0xf57c0faf + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; - d = LeftRotate(xUints[5] + 0x4787c62a + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; - c = LeftRotate(xUints[6] + 0xa8304613 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; - b = LeftRotate(0xfd469501 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; - a = LeftRotate(0x698098d8 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; - d = LeftRotate(0x8b44f7af + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; - c = LeftRotate(0xffff5bb1 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; - b = LeftRotate(0x895cd7be + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; - a = LeftRotate(0x6b901122 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; - d = LeftRotate(0xfd987193 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; - c = LeftRotate(xUints[7] + 0xa679438e + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; - b = LeftRotate(0x49b40821 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; - - a = LeftRotate(xUints[1] + 0xf61e2562 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; - d = LeftRotate(xUints[6] + 0xc040b340 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; - c = LeftRotate(0x265e5a51 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; - b = LeftRotate(xUints[0] + 0xe9b6c7aa + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; - a = LeftRotate(xUints[5] + 0xd62f105d + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; - d = LeftRotate(0x2441453 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; - c = LeftRotate(0xd8a1e681 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; - b = LeftRotate(xUints[4] + 0xe7d3fbc8 + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; - a = LeftRotate(0x21e1cde6 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; - d = LeftRotate(xUints[7] + 0xc33707d6 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; - c = LeftRotate(xUints[3] + 0xf4d50d87 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; - b = LeftRotate(0x455a14ed + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; - a = LeftRotate(0xa9e3e905 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; - d = LeftRotate(xUints[2] + 0xfcefa3f8 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; - c = LeftRotate(0x676f02d9 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; - b = LeftRotate(0x8d2a4c8a + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; - - a = LeftRotate(xUints[5] + 0xfffa3942 + a + (b ^ c ^ d), 4, 32 - 4) + b; - d = LeftRotate(0x8771f681 + d + (a ^ b ^ c), 11, 32 - 11) + a; - c = LeftRotate(0x6d9d6122 + c + (d ^ a ^ b), 16, 32 - 16) + d; - b = LeftRotate(xUints[7] + 0xfde5380c + b + (c ^ d ^ a), 23, 32 - 23) + c; - a = LeftRotate(xUints[1] + 0xa4beea44 + a + (b ^ c ^ d), 4, 32 - 4) + b; - d = LeftRotate(xUints[4] + 0x4bdecfa9 + d + (a ^ b ^ c), 11, 32 - 11) + a; - c = LeftRotate(0xf6bb4b60 + c + (d ^ a ^ b), 16, 32 - 16) + d; - b = LeftRotate(0xbebfbc70 + b + (c ^ d ^ a), 23, 32 - 23) + c; - a = LeftRotate(0x289b7ec6 + a + (b ^ c ^ d), 4, 32 - 4) + b; - d = LeftRotate(xUints[0] + 0xeaa127fa + d + (a ^ b ^ c), 11, 32 - 11) + a; - c = LeftRotate(xUints[3] + 0xd4ef3085 + c + (d ^ a ^ b), 16, 32 - 16) + d; - b = LeftRotate(xUints[6] + 0x4881d05 + b + (c ^ d ^ a), 23, 32 - 23) + c; - a = LeftRotate(0xd9d4d039 + a + (b ^ c ^ d), 4, 32 - 4) + b; - d = LeftRotate(0xe6db99e5 + d + (a ^ b ^ c), 11, 32 - 11) + a; - c = LeftRotate(0x1fa27cf8 + c + (d ^ a ^ b), 16, 32 - 16) + d; - b = LeftRotate(xUints[2] + 0xc4ac5665 + b + (c ^ d ^ a), 23, 32 - 23) + c; - - a = LeftRotate(xUints[0] + 0xf4292244 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; - d = LeftRotate(0x432aff97 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; - c = LeftRotate(xUints[7] + 0xab9423a7 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; - b = LeftRotate(xUints[5] + 0xfc93a039 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; - a = LeftRotate(0x655b59c3 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; - d = LeftRotate(xUints[3] + 0x8f0ccc92 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; - c = LeftRotate(0xffeff47d + c + (a ^ (d | ~b)), 15, 32 - 15) + d; - b = LeftRotate(xUints[1] + 0x85845dd1 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; - a = LeftRotate(0x6fa87e4f + a + (c ^ (b | ~d)), 6, 32 - 6) + b; - d = LeftRotate(0xfe2ce6e0 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; - c = LeftRotate(xUints[6] + 0xa3014314 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; - b = LeftRotate(0x4e0811a1 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; - a = LeftRotate(xUints[4] + 0xf7537e82 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; - d = LeftRotate(0xbd3af235 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; - c = LeftRotate(xUints[2] + 0x2ad7d2bb + c + (a ^ (d | ~b)), 15, 32 - 15) + d; - b = LeftRotate(0xeb86d391 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; + var initialUints = stackalloc uint[32]; + *(long*)(initialUints + 0 * 2) = *(long*)(input.Buffers + 0 * 8); + *(long*)(initialUints + 1 * 2) = *(long*)(input.Buffers + 1 * 8); + *(long*)(initialUints + 2 * 2) = *(long*)(input.Buffers + 2 * 8); + *(long*)(initialUints + 3 * 2) = *(long*)(input.Buffers + 3 * 8); + *(long*)(initialUints + 4 * 2) = *(long*)(input.Buffers + 4 * 8); + *(long*)(initialUints + 5 * 2) = *(long*)(input.Buffers + 5 * 8); + *(long*)(initialUints + 6 * 2) = *(long*)(input.Buffers + 6 * 8); + *(long*)(initialUints + 7 * 2) = *(long*)(input.Buffers + 7 * 8); + *(long*)(initialUints + 8 * 2) = *(long*)(input.Buffers + 8 * 8); + *(long*)(initialUints + 9 * 2) = *(long*)(input.Buffers + 9 * 8); + *(long*)(initialUints + 10 * 2) = *(long*)(input.Buffers + 10 * 8); + *(long*)(initialUints + 11 * 2) = *(long*)(input.Buffers + 11 * 8); + *(long*)(initialUints + 12 * 2) = *(long*)(input.Buffers + 12 * 8); + *(long*)(initialUints + 13 * 2) = *(long*)(input.Buffers + 13 * 8); + *(long*)(initialUints + 14 * 2) = *(long*)(input.Buffers + 14 * 8); + *(long*)(initialUints + 15 * 2) = *(long*)(input.Buffers + 15 * 8); + + ((byte*)initialUints)[31 + 0 * 32] = 0; + ((byte*)initialUints)[31 + 1 * 32] = 0; + ((byte*)initialUints)[31 + 2 * 32] = 0; + ((byte*)initialUints)[31 + 3 * 32] = 0; + ((byte*)initialUints)[0 * 32 + input.Buffers[31 + 0 * 32]] = 128; + ((byte*)initialUints)[1 * 32 + input.Buffers[31 + 1 * 32]] = 128; + ((byte*)initialUints)[2 * 32 + input.Buffers[31 + 2 * 32]] = 128; + ((byte*)initialUints)[3 * 32 + input.Buffers[31 + 3 * 32]] = 128; + initialUints[7 + 0 * 8] = (uint)(input.Buffers[31 + 0 * 32] << 3); + initialUints[7 + 1 * 8] = (uint)(input.Buffers[31 + 1 * 32] << 3); + initialUints[7 + 2 * 8] = (uint)(input.Buffers[31 + 2 * 32] << 3); + initialUints[7 + 3 * 8] = (uint)(input.Buffers[31 + 3 * 32] << 3); + + var message0 = new Vector(new uint[] { + initialUints[0 + 0 * 8], + initialUints[0 + 1 * 8], + initialUints[0 + 2 * 8], + initialUints[0 + 3 * 8], + }); + + var message1 = new Vector(new uint[] { + initialUints[1 + 0 * 8], + initialUints[1 + 1 * 8], + initialUints[1 + 2 * 8], + initialUints[1 + 3 * 8], + }); + + var message2 = new Vector(new uint[] { + initialUints[2 + 0 * 8], + initialUints[2 + 1 * 8], + initialUints[2 + 2 * 8], + initialUints[2 + 3 * 8], + }); + + var message3 = new Vector(new uint[] { + initialUints[3 + 0 * 8], + initialUints[3 + 1 * 8], + initialUints[3 + 2 * 8], + initialUints[3 + 3 * 8], + }); + + var message4 = new Vector(new uint[] { + initialUints[4 + 0 * 8], + initialUints[4 + 1 * 8], + initialUints[4 + 2 * 8], + initialUints[4 + 3 * 8], + }); + + var message5 = new Vector(new uint[] { + initialUints[5 + 0 * 8], + initialUints[5 + 1 * 8], + initialUints[5 + 2 * 8], + initialUints[5 + 3 * 8], + }); + + var message6 = new Vector(new uint[] { + initialUints[6 + 0 * 8], + initialUints[6 + 1 * 8], + initialUints[6 + 2 * 8], + initialUints[6 + 3 * 8], + }); + + var message7 = new Vector(new uint[] { + initialUints[7 + 0 * 8], + initialUints[7 + 1 * 8], + initialUints[7 + 2 * 8], + initialUints[7 + 3 * 8], + }); + + var a = A0; + var b = B0; + var c = C0; + var d = D0; + + a = LeftRotate(message0 + K1 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; + d = LeftRotate(message1 + K2 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; + c = LeftRotate(message2 + K3 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; + b = LeftRotate(message3 + K4 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; + a = LeftRotate(message4 + K5 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; + d = LeftRotate(message5 + K6 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; + c = LeftRotate(message6 + K7 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; + b = LeftRotate(K8 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; + a = LeftRotate(K9 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; + d = LeftRotate(K10 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; + c = LeftRotate(K11 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; + b = LeftRotate(K12 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; + a = LeftRotate(K13 + a + ((b & c) | (~b & d)), 7, 32 - 7) + b; + d = LeftRotate(K14 + d + ((a & b) | (~a & c)), 12, 32 - 12) + a; + c = LeftRotate(message7 + K15 + c + ((d & a) | (~d & b)), 17, 32 - 17) + d; + b = LeftRotate(K16 + b + ((c & d) | (~c & a)), 22, 32 - 22) + c; + + a = LeftRotate(message1 + K17 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; + d = LeftRotate(message6 + K18 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; + c = LeftRotate(K19 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; + b = LeftRotate(message0 + K20 + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; + a = LeftRotate(message5 + K21 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; + d = LeftRotate(K22 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; + c = LeftRotate(K23 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; + b = LeftRotate(message4 + K24 + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; + a = LeftRotate(K25 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; + d = LeftRotate(message7 + K26 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; + c = LeftRotate(message3 + K27 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; + b = LeftRotate(K28 + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; + a = LeftRotate(K29 + a + ((b & d) | (c & ~d)), 5, 32 - 5) + b; + d = LeftRotate(message2 + K30 + d + ((a & c) | (b & ~c)), 9, 32 - 9) + a; + c = LeftRotate(K31 + c + ((d & b) | (a & ~b)), 14, 32 - 14) + d; + b = LeftRotate(K32 + b + ((c & a) | (d & ~a)), 20, 32 - 20) + c; + + a = LeftRotate(message5 + K33 + a + (b ^ c ^ d), 4, 32 - 4) + b; + d = LeftRotate(K34 + d + (a ^ b ^ c), 11, 32 - 11) + a; + c = LeftRotate(K35 + c + (d ^ a ^ b), 16, 32 - 16) + d; + b = LeftRotate(message7 + K36 + b + (c ^ d ^ a), 23, 32 - 23) + c; + a = LeftRotate(message1 + K37 + a + (b ^ c ^ d), 4, 32 - 4) + b; + d = LeftRotate(message4 + K38 + d + (a ^ b ^ c), 11, 32 - 11) + a; + c = LeftRotate(K39 + c + (d ^ a ^ b), 16, 32 - 16) + d; + b = LeftRotate(K40 + b + (c ^ d ^ a), 23, 32 - 23) + c; + a = LeftRotate(K41 + a + (b ^ c ^ d), 4, 32 - 4) + b; + d = LeftRotate(message0 + K42 + d + (a ^ b ^ c), 11, 32 - 11) + a; + c = LeftRotate(message3 + K43 + c + (d ^ a ^ b), 16, 32 - 16) + d; + b = LeftRotate(message6 + K44 + b + (c ^ d ^ a), 23, 32 - 23) + c; + a = LeftRotate(K45 + a + (b ^ c ^ d), 4, 32 - 4) + b; + d = LeftRotate(K46 + d + (a ^ b ^ c), 11, 32 - 11) + a; + c = LeftRotate(K47 + c + (d ^ a ^ b), 16, 32 - 16) + d; + b = LeftRotate(message2 + K48 + b + (c ^ d ^ a), 23, 32 - 23) + c; + + a = LeftRotate(message0 + K49 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; + d = LeftRotate(K50 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; + c = LeftRotate(message7 + K51 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; + b = LeftRotate(message5 + K52 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; + a = LeftRotate(K53 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; + d = LeftRotate(message3 + K54 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; + c = LeftRotate(K55 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; + b = LeftRotate(message1 + K56 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; + a = LeftRotate(K57 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; + d = LeftRotate(K58 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; + c = LeftRotate(message6 + K59 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; + b = LeftRotate(K60 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; + a = LeftRotate(message4 + K61 + a + (c ^ (b | ~d)), 6, 32 - 6) + b; + d = LeftRotate(K62 + d + (b ^ (a | ~c)), 10, 32 - 10) + a; + c = LeftRotate(message2 + K63 + c + (a ^ (d | ~b)), 15, 32 - 15) + d; + b = LeftRotate(K64 + b + (d ^ (c | ~a)), 21, 32 - 21) + c; return new[] { @@ -106,7 +255,7 @@ }; } - private static uint LeftRotate(uint x, int left, int right) + private static uint LeftRotate(Vector x, int left, int right) { return (x << left) | (x >> right); } diff --git a/dotnet/WhiteRabbit/Phrase.cs b/dotnet/WhiteRabbit/Phrase.cs deleted file mode 100644 index c5635e1..0000000 --- a/dotnet/WhiteRabbit/Phrase.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace WhiteRabbit -{ - internal unsafe struct Phrase - { - public fixed byte Buffer[32]; - - public Phrase(byte[][] words, int numberOfCharacters) - { - fixed (byte* bufferPointer = this.Buffer) - { - var length = numberOfCharacters + words.Length - 1; - - byte* end = bufferPointer + length; - byte[] currentWord = words[0]; - var j = 0; - var wordIndex = 0; - for (var currentPointer = bufferPointer; currentPointer < end; currentPointer++) - { - if (j >= currentWord.Length) - { - j = 0; - wordIndex++; - currentWord = words[wordIndex]; - } - - *currentPointer = currentWord[j]; - j++; - } - - bufferPointer[31] = (byte)length; - } - } - - public byte[] GetBytes() - { - fixed(byte* bufferPointer = this.Buffer) - { - var length = bufferPointer[31]; - var result = new byte[length]; - for (var i = 0; i < length; i++) - { - result[i] = bufferPointer[i]; - } - - return result; - } - } - } -} diff --git a/dotnet/WhiteRabbit/PhrasesChunk.cs b/dotnet/WhiteRabbit/PhrasesChunk.cs new file mode 100644 index 0000000..861cd86 --- /dev/null +++ b/dotnet/WhiteRabbit/PhrasesChunk.cs @@ -0,0 +1,69 @@ +namespace WhiteRabbit +{ + using System.Diagnostics; + + internal unsafe struct PhrasesChunk + { + public fixed byte Buffers[4 * 32]; + + public PhrasesChunk(byte[][] words0, byte[][] words1, byte[][] words2, byte[][] words3, int numberOfCharacters) + { + Debug.Assert(numberOfCharacters <= 28); + + fixed (byte* bufferPointer = this.Buffers) + { + WriteWordsToBuffer(bufferPointer + 0 * 32, words0, numberOfCharacters); + WriteWordsToBuffer(bufferPointer + 1 * 32, words1, numberOfCharacters); + WriteWordsToBuffer(bufferPointer + 2 * 32, words2, numberOfCharacters); + WriteWordsToBuffer(bufferPointer + 3 * 32, words3, numberOfCharacters); + } + } + + public byte[] GetBytes(int wordIndex) + { + Debug.Assert(wordIndex >= 0); + Debug.Assert(wordIndex < 4); + + fixed (byte* bufferPointer = this.Buffers) + { + return ReadBytesFromBuffer(bufferPointer + wordIndex * 32); + } + } + + private static void WriteWordsToBuffer(byte* bufferPointer, byte[][] words, int numberOfCharacters) + { + var length = numberOfCharacters + words.Length - 1; + + byte* end = bufferPointer + length; + byte[] currentWord = words[0]; + var j = 0; + var wordIndex = 0; + for (var currentPointer = bufferPointer; currentPointer < end; currentPointer++) + { + if (j >= currentWord.Length) + { + j = 0; + wordIndex++; + currentWord = words[wordIndex]; + } + + *currentPointer = currentWord[j]; + j++; + } + + bufferPointer[31] = (byte)length; + } + + private static byte[] ReadBytesFromBuffer(byte* bufferPointer) + { + var length = bufferPointer[31]; + var result = new byte[length]; + for (var i = 0; i < length; i++) + { + result[i] = bufferPointer[i]; + } + + return result; + } + } +} diff --git a/dotnet/WhiteRabbit/PhrasesHashesChunk.cs b/dotnet/WhiteRabbit/PhrasesHashesChunk.cs new file mode 100644 index 0000000..0b5bf7f --- /dev/null +++ b/dotnet/WhiteRabbit/PhrasesHashesChunk.cs @@ -0,0 +1,12 @@ +namespace WhiteRabbit +{ + using System.Numerics; + + internal class PhrasesHashesChunk + { + public Vector Hash0 { get; } + public Vector Hash1 { get; } + public Vector Hash2 { get; } + public Vector Hash3 { get; } + } +} diff --git a/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs b/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs index 78e7b93..269a30e 100644 --- a/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs +++ b/dotnet/WhiteRabbit/PrecomputedPermutationsGenerator.cs @@ -17,14 +17,22 @@ PermutationsGenerator.HamiltonianPermutations(7).ToArray(), }; - public static IEnumerable HamiltonianPermutations(int n) + // for MD5 SIMD optimization and code simplicity reasons, number of permutations should divide by 4 + public static PermutationsGenerator.Permutation[] HamiltonianPermutations(int n) { - if (n > 9) + return Permutations[n]; + } + + private static PermutationsGenerator.Permutation[] GeneratePermutations(int n) + { + var result = PermutationsGenerator.HamiltonianPermutations(n).ToList(); + if (result.Count == 0) { - return PermutationsGenerator.HamiltonianPermutations(n); + return result.ToArray(); } - return Permutations[n]; + var extra = (4 - (result.Count % 4)) % 4; + return result.Concat(Enumerable.Repeat(result[0], extra)).ToArray(); } } } diff --git a/dotnet/WhiteRabbit/Program.cs b/dotnet/WhiteRabbit/Program.cs index 0c34d8a..cd20bc9 100644 --- a/dotnet/WhiteRabbit/Program.cs +++ b/dotnet/WhiteRabbit/Program.cs @@ -42,6 +42,12 @@ if (IntPtr.Size != 8) { Console.WriteLine("Only 64-bit systems are supported due to MD5Digest optimizations"); + return; + } + + if (Vector.Count != 4) + { + Console.WriteLine("Only 128-bit SSE systems are supported due to MD5Digest optimizations"); } var expectedHashesAsVectors = ConfigurationManager.AppSettings["ExpectedHashes"] diff --git a/dotnet/WhiteRabbit/StringsProcessor.cs b/dotnet/WhiteRabbit/StringsProcessor.cs index e96385e..bb43199 100644 --- a/dotnet/WhiteRabbit/StringsProcessor.cs +++ b/dotnet/WhiteRabbit/StringsProcessor.cs @@ -62,23 +62,35 @@ return sums .Select(this.ConvertVectorsToWords) .SelectMany(Flattener.Flatten) - .SelectMany(GeneratePermutations) + .SelectMany(GeneratePermutationsChunked) .Select(this.ConvertWordsToPhrase); } - private static IEnumerable GeneratePermutations(T[] original) + private static IEnumerable GeneratePermutationsChunked(T[] original) { var length = original.Length; - foreach (var permutation in PrecomputedPermutationsGenerator.HamiltonianPermutations(length)) + var permutations = PrecomputedPermutationsGenerator.HamiltonianPermutations(length); + for (var i = 0; i < permutations.Length; i += 4) { - var result = new T[length]; - for (var i = 0; i < length; i++) + yield return new[] { - result[i] = original[permutation[i]]; - } + GetPermutedArray(original, permutations[i]), + GetPermutedArray(original, permutations[i + 1]), + GetPermutedArray(original, permutations[i + 2]), + GetPermutedArray(original, permutations[i + 3]), + }; + } + } - yield return result; + private static T[] GetPermutedArray(T[] original, PermutationsGenerator.Permutation permutation) + { + var length = original.Length; + var result = new T[length]; + for (var i = 0; i < length; i++) + { + result[i] = original[permutation[i]]; } + return result; } private byte[][][] ConvertVectorsToWords(int[] vectors) @@ -93,9 +105,9 @@ return words; } - private unsafe Phrase ConvertWordsToPhrase(byte[][] words) + private unsafe PhrasesChunk ConvertWordsToPhrase(byte[][][] words) { - return new Phrase(words, this.NumberOfCharacters); + return new PhrasesChunk(words[0], words[1], words[2], words[3], this.NumberOfCharacters); } } } diff --git a/dotnet/WhiteRabbit/WhiteRabbit.csproj b/dotnet/WhiteRabbit/WhiteRabbit.csproj index 39ab4e4..574acd2 100644 --- a/dotnet/WhiteRabbit/WhiteRabbit.csproj +++ b/dotnet/WhiteRabbit/WhiteRabbit.csproj @@ -60,7 +60,8 @@ - + + diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 0000000..50281a4 --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1,10 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..eade6ea --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,5 @@ +[package] + +name = "trustpilot_challenge" +version = "0.0.1" +authors = [ "penartur " ] \ No newline at end of file diff --git a/rust/src/main.rs b/rust/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/rust/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +}