<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.0" />

ThreefishEngine

public class ThreefishEngine : IBlockCipher
Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block sizes.
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Engines { public class ThreefishEngine : IBlockCipher { private abstract class ThreefishCipher { protected readonly ulong[] t; protected readonly ulong[] kw; protected ThreefishCipher(ulong[] kw, ulong[] t) { this.kw = kw; this.t = t; } internal abstract void EncryptBlock(ulong[] block, ulong[] outWords); internal abstract void DecryptBlock(ulong[] block, ulong[] outWords); } private sealed class Threefish256Cipher : ThreefishCipher { private const int ROTATION_0_0 = 14; private const int ROTATION_0_1 = 16; private const int ROTATION_1_0 = 52; private const int ROTATION_1_1 = 57; private const int ROTATION_2_0 = 23; private const int ROTATION_2_1 = 40; private const int ROTATION_3_0 = 5; private const int ROTATION_3_1 = 37; private const int ROTATION_4_0 = 25; private const int ROTATION_4_1 = 33; private const int ROTATION_5_0 = 46; private const int ROTATION_5_1 = 12; private const int ROTATION_6_0 = 58; private const int ROTATION_6_1 = 22; private const int ROTATION_7_0 = 32; private const int ROTATION_7_1 = 32; public Threefish256Cipher(ulong[] kw, ulong[] t) : base(kw, t) { } internal override void EncryptBlock(ulong[] block, ulong[] outWords) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD5; int[] mOD2 = MOD3; if (kw.Length != 9) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; num += kw[0]; num2 += kw[1] + t[0]; num3 += kw[2] + t[1]; num4 += kw[3]; for (int i = 1; i < 18; i += 2) { int num5 = mOD[i]; int num6 = mOD2[i]; num2 = RotlXor(num2, 14, num += num2); num4 = RotlXor(num4, 16, num3 += num4); num4 = RotlXor(num4, 52, num += num4); num2 = RotlXor(num2, 57, num3 += num2); num2 = RotlXor(num2, 23, num += num2); num4 = RotlXor(num4, 40, num3 += num4); num4 = RotlXor(num4, 5, num += num4); num2 = RotlXor(num2, 37, num3 += num2); num += kw[num5]; num2 += kw[num5 + 1] + t[num6]; num3 += kw[num5 + 2] + t[num6 + 1]; num4 += kw[num5 + 3] + (uint)i; num2 = RotlXor(num2, 25, num += num2); num4 = RotlXor(num4, 33, num3 += num4); num4 = RotlXor(num4, 46, num += num4); num2 = RotlXor(num2, 12, num3 += num2); num2 = RotlXor(num2, 58, num += num2); num4 = RotlXor(num4, 22, num3 += num4); num4 = RotlXor(num4, 32, num += num4); num2 = RotlXor(num2, 32, num3 += num2); num += kw[num5 + 1]; num2 += kw[num5 + 2] + t[num6 + 1]; num3 += kw[num5 + 3] + t[num6 + 2]; num4 += kw[num5 + 4] + (uint)i + 1; } outWords[0] = num; outWords[1] = num2; outWords[2] = num3; outWords[3] = num4; } internal override void DecryptBlock(ulong[] block, ulong[] state) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD5; int[] mOD2 = MOD3; if (kw.Length != 9) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; for (int num5 = 17; num5 >= 1; num5 -= 2) { int num6 = mOD[num5]; int num7 = mOD2[num5]; num -= kw[num6 + 1]; num2 -= kw[num6 + 2] + t[num7 + 1]; num3 -= kw[num6 + 3] + t[num7 + 2]; num4 -= kw[num6 + 4] + (uint)num5 + 1; num4 = XorRotr(num4, 32, num); num -= num4; num2 = XorRotr(num2, 32, num3); num3 -= num2; num2 = XorRotr(num2, 58, num); num -= num2; num4 = XorRotr(num4, 22, num3); num3 -= num4; num4 = XorRotr(num4, 46, num); num -= num4; num2 = XorRotr(num2, 12, num3); num3 -= num2; num2 = XorRotr(num2, 25, num); num -= num2; num4 = XorRotr(num4, 33, num3); num3 -= num4; num -= kw[num6]; num2 -= kw[num6 + 1] + t[num7]; num3 -= kw[num6 + 2] + t[num7 + 1]; num4 -= kw[num6 + 3] + (uint)num5; num4 = XorRotr(num4, 5, num); num -= num4; num2 = XorRotr(num2, 37, num3); num3 -= num2; num2 = XorRotr(num2, 23, num); num -= num2; num4 = XorRotr(num4, 40, num3); num3 -= num4; num4 = XorRotr(num4, 52, num); num -= num4; num2 = XorRotr(num2, 57, num3); num3 -= num2; num2 = XorRotr(num2, 14, num); num -= num2; num4 = XorRotr(num4, 16, num3); num3 -= num4; } num -= kw[0]; num2 -= kw[1] + t[0]; num3 -= kw[2] + t[1]; num4 -= kw[3]; state[0] = num; state[1] = num2; state[2] = num3; state[3] = num4; } } private sealed class Threefish512Cipher : ThreefishCipher { private const int ROTATION_0_0 = 46; private const int ROTATION_0_1 = 36; private const int ROTATION_0_2 = 19; private const int ROTATION_0_3 = 37; private const int ROTATION_1_0 = 33; private const int ROTATION_1_1 = 27; private const int ROTATION_1_2 = 14; private const int ROTATION_1_3 = 42; private const int ROTATION_2_0 = 17; private const int ROTATION_2_1 = 49; private const int ROTATION_2_2 = 36; private const int ROTATION_2_3 = 39; private const int ROTATION_3_0 = 44; private const int ROTATION_3_1 = 9; private const int ROTATION_3_2 = 54; private const int ROTATION_3_3 = 56; private const int ROTATION_4_0 = 39; private const int ROTATION_4_1 = 30; private const int ROTATION_4_2 = 34; private const int ROTATION_4_3 = 24; private const int ROTATION_5_0 = 13; private const int ROTATION_5_1 = 50; private const int ROTATION_5_2 = 10; private const int ROTATION_5_3 = 17; private const int ROTATION_6_0 = 25; private const int ROTATION_6_1 = 29; private const int ROTATION_6_2 = 39; private const int ROTATION_6_3 = 43; private const int ROTATION_7_0 = 8; private const int ROTATION_7_1 = 35; private const int ROTATION_7_2 = 56; private const int ROTATION_7_3 = 22; internal Threefish512Cipher(ulong[] kw, ulong[] t) : base(kw, t) { } internal override void EncryptBlock(ulong[] block, ulong[] outWords) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD9; int[] mOD2 = MOD3; if (kw.Length != 17) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; ulong num5 = block[4]; ulong num6 = block[5]; ulong num7 = block[6]; ulong num8 = block[7]; num += kw[0]; num2 += kw[1]; num3 += kw[2]; num4 += kw[3]; num5 += kw[4]; num6 += kw[5] + t[0]; num7 += kw[6] + t[1]; num8 += kw[7]; for (int i = 1; i < 18; i += 2) { int num9 = mOD[i]; int num10 = mOD2[i]; num2 = RotlXor(num2, 46, num += num2); num4 = RotlXor(num4, 36, num3 += num4); num6 = RotlXor(num6, 19, num5 += num6); num8 = RotlXor(num8, 37, num7 += num8); num2 = RotlXor(num2, 33, num3 += num2); num8 = RotlXor(num8, 27, num5 += num8); num6 = RotlXor(num6, 14, num7 += num6); num4 = RotlXor(num4, 42, num += num4); num2 = RotlXor(num2, 17, num5 += num2); num4 = RotlXor(num4, 49, num7 += num4); num6 = RotlXor(num6, 36, num += num6); num8 = RotlXor(num8, 39, num3 += num8); num2 = RotlXor(num2, 44, num7 += num2); num8 = RotlXor(num8, 9, num += num8); num6 = RotlXor(num6, 54, num3 += num6); num4 = RotlXor(num4, 56, num5 += num4); num += kw[num9]; num2 += kw[num9 + 1]; num3 += kw[num9 + 2]; num4 += kw[num9 + 3]; num5 += kw[num9 + 4]; num6 += kw[num9 + 5] + t[num10]; num7 += kw[num9 + 6] + t[num10 + 1]; num8 += kw[num9 + 7] + (uint)i; num2 = RotlXor(num2, 39, num += num2); num4 = RotlXor(num4, 30, num3 += num4); num6 = RotlXor(num6, 34, num5 += num6); num8 = RotlXor(num8, 24, num7 += num8); num2 = RotlXor(num2, 13, num3 += num2); num8 = RotlXor(num8, 50, num5 += num8); num6 = RotlXor(num6, 10, num7 += num6); num4 = RotlXor(num4, 17, num += num4); num2 = RotlXor(num2, 25, num5 += num2); num4 = RotlXor(num4, 29, num7 += num4); num6 = RotlXor(num6, 39, num += num6); num8 = RotlXor(num8, 43, num3 += num8); num2 = RotlXor(num2, 8, num7 += num2); num8 = RotlXor(num8, 35, num += num8); num6 = RotlXor(num6, 56, num3 += num6); num4 = RotlXor(num4, 22, num5 += num4); num += kw[num9 + 1]; num2 += kw[num9 + 2]; num3 += kw[num9 + 3]; num4 += kw[num9 + 4]; num5 += kw[num9 + 5]; num6 += kw[num9 + 6] + t[num10 + 1]; num7 += kw[num9 + 7] + t[num10 + 2]; num8 += kw[num9 + 8] + (uint)i + 1; } outWords[0] = num; outWords[1] = num2; outWords[2] = num3; outWords[3] = num4; outWords[4] = num5; outWords[5] = num6; outWords[6] = num7; outWords[7] = num8; } internal override void DecryptBlock(ulong[] block, ulong[] state) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD9; int[] mOD2 = MOD3; if (kw.Length != 17) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; ulong num5 = block[4]; ulong num6 = block[5]; ulong num7 = block[6]; ulong num8 = block[7]; for (int num9 = 17; num9 >= 1; num9 -= 2) { int num10 = mOD[num9]; int num11 = mOD2[num9]; num -= kw[num10 + 1]; num2 -= kw[num10 + 2]; num3 -= kw[num10 + 3]; num4 -= kw[num10 + 4]; num5 -= kw[num10 + 5]; num6 -= kw[num10 + 6] + t[num11 + 1]; num7 -= kw[num10 + 7] + t[num11 + 2]; num8 -= kw[num10 + 8] + (uint)num9 + 1; num2 = XorRotr(num2, 8, num7); num7 -= num2; num8 = XorRotr(num8, 35, num); num -= num8; num6 = XorRotr(num6, 56, num3); num3 -= num6; num4 = XorRotr(num4, 22, num5); num5 -= num4; num2 = XorRotr(num2, 25, num5); num5 -= num2; num4 = XorRotr(num4, 29, num7); num7 -= num4; num6 = XorRotr(num6, 39, num); num -= num6; num8 = XorRotr(num8, 43, num3); num3 -= num8; num2 = XorRotr(num2, 13, num3); num3 -= num2; num8 = XorRotr(num8, 50, num5); num5 -= num8; num6 = XorRotr(num6, 10, num7); num7 -= num6; num4 = XorRotr(num4, 17, num); num -= num4; num2 = XorRotr(num2, 39, num); num -= num2; num4 = XorRotr(num4, 30, num3); num3 -= num4; num6 = XorRotr(num6, 34, num5); num5 -= num6; num8 = XorRotr(num8, 24, num7); num7 -= num8; num -= kw[num10]; num2 -= kw[num10 + 1]; num3 -= kw[num10 + 2]; num4 -= kw[num10 + 3]; num5 -= kw[num10 + 4]; num6 -= kw[num10 + 5] + t[num11]; num7 -= kw[num10 + 6] + t[num11 + 1]; num8 -= kw[num10 + 7] + (uint)num9; num2 = XorRotr(num2, 44, num7); num7 -= num2; num8 = XorRotr(num8, 9, num); num -= num8; num6 = XorRotr(num6, 54, num3); num3 -= num6; num4 = XorRotr(num4, 56, num5); num5 -= num4; num2 = XorRotr(num2, 17, num5); num5 -= num2; num4 = XorRotr(num4, 49, num7); num7 -= num4; num6 = XorRotr(num6, 36, num); num -= num6; num8 = XorRotr(num8, 39, num3); num3 -= num8; num2 = XorRotr(num2, 33, num3); num3 -= num2; num8 = XorRotr(num8, 27, num5); num5 -= num8; num6 = XorRotr(num6, 14, num7); num7 -= num6; num4 = XorRotr(num4, 42, num); num -= num4; num2 = XorRotr(num2, 46, num); num -= num2; num4 = XorRotr(num4, 36, num3); num3 -= num4; num6 = XorRotr(num6, 19, num5); num5 -= num6; num8 = XorRotr(num8, 37, num7); num7 -= num8; } num -= kw[0]; num2 -= kw[1]; num3 -= kw[2]; num4 -= kw[3]; num5 -= kw[4]; num6 -= kw[5] + t[0]; num7 -= kw[6] + t[1]; num8 -= kw[7]; state[0] = num; state[1] = num2; state[2] = num3; state[3] = num4; state[4] = num5; state[5] = num6; state[6] = num7; state[7] = num8; } } private sealed class Threefish1024Cipher : ThreefishCipher { private const int ROTATION_0_0 = 24; private const int ROTATION_0_1 = 13; private const int ROTATION_0_2 = 8; private const int ROTATION_0_3 = 47; private const int ROTATION_0_4 = 8; private const int ROTATION_0_5 = 17; private const int ROTATION_0_6 = 22; private const int ROTATION_0_7 = 37; private const int ROTATION_1_0 = 38; private const int ROTATION_1_1 = 19; private const int ROTATION_1_2 = 10; private const int ROTATION_1_3 = 55; private const int ROTATION_1_4 = 49; private const int ROTATION_1_5 = 18; private const int ROTATION_1_6 = 23; private const int ROTATION_1_7 = 52; private const int ROTATION_2_0 = 33; private const int ROTATION_2_1 = 4; private const int ROTATION_2_2 = 51; private const int ROTATION_2_3 = 13; private const int ROTATION_2_4 = 34; private const int ROTATION_2_5 = 41; private const int ROTATION_2_6 = 59; private const int ROTATION_2_7 = 17; private const int ROTATION_3_0 = 5; private const int ROTATION_3_1 = 20; private const int ROTATION_3_2 = 48; private const int ROTATION_3_3 = 41; private const int ROTATION_3_4 = 47; private const int ROTATION_3_5 = 28; private const int ROTATION_3_6 = 16; private const int ROTATION_3_7 = 25; private const int ROTATION_4_0 = 41; private const int ROTATION_4_1 = 9; private const int ROTATION_4_2 = 37; private const int ROTATION_4_3 = 31; private const int ROTATION_4_4 = 12; private const int ROTATION_4_5 = 47; private const int ROTATION_4_6 = 44; private const int ROTATION_4_7 = 30; private const int ROTATION_5_0 = 16; private const int ROTATION_5_1 = 34; private const int ROTATION_5_2 = 56; private const int ROTATION_5_3 = 51; private const int ROTATION_5_4 = 4; private const int ROTATION_5_5 = 53; private const int ROTATION_5_6 = 42; private const int ROTATION_5_7 = 41; private const int ROTATION_6_0 = 31; private const int ROTATION_6_1 = 44; private const int ROTATION_6_2 = 47; private const int ROTATION_6_3 = 46; private const int ROTATION_6_4 = 19; private const int ROTATION_6_5 = 42; private const int ROTATION_6_6 = 44; private const int ROTATION_6_7 = 25; private const int ROTATION_7_0 = 9; private const int ROTATION_7_1 = 48; private const int ROTATION_7_2 = 35; private const int ROTATION_7_3 = 52; private const int ROTATION_7_4 = 23; private const int ROTATION_7_5 = 31; private const int ROTATION_7_6 = 37; private const int ROTATION_7_7 = 20; public Threefish1024Cipher(ulong[] kw, ulong[] t) : base(kw, t) { } internal override void EncryptBlock(ulong[] block, ulong[] outWords) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD17; int[] mOD2 = MOD3; if (kw.Length != 33) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; ulong num5 = block[4]; ulong num6 = block[5]; ulong num7 = block[6]; ulong num8 = block[7]; ulong num9 = block[8]; ulong num10 = block[9]; ulong num11 = block[10]; ulong num12 = block[11]; ulong num13 = block[12]; ulong num14 = block[13]; ulong num15 = block[14]; ulong num16 = block[15]; num += kw[0]; num2 += kw[1]; num3 += kw[2]; num4 += kw[3]; num5 += kw[4]; num6 += kw[5]; num7 += kw[6]; num8 += kw[7]; num9 += kw[8]; num10 += kw[9]; num11 += kw[10]; num12 += kw[11]; num13 += kw[12]; num14 += kw[13] + t[0]; num15 += kw[14] + t[1]; num16 += kw[15]; for (int i = 1; i < 20; i += 2) { int num17 = mOD[i]; int num18 = mOD2[i]; num2 = RotlXor(num2, 24, num += num2); num4 = RotlXor(num4, 13, num3 += num4); num6 = RotlXor(num6, 8, num5 += num6); num8 = RotlXor(num8, 47, num7 += num8); num10 = RotlXor(num10, 8, num9 += num10); num12 = RotlXor(num12, 17, num11 += num12); num14 = RotlXor(num14, 22, num13 += num14); num16 = RotlXor(num16, 37, num15 += num16); num10 = RotlXor(num10, 38, num += num10); num14 = RotlXor(num14, 19, num3 += num14); num12 = RotlXor(num12, 10, num7 += num12); num16 = RotlXor(num16, 55, num5 += num16); num8 = RotlXor(num8, 49, num11 += num8); num4 = RotlXor(num4, 18, num13 += num4); num6 = RotlXor(num6, 23, num15 += num6); num2 = RotlXor(num2, 52, num9 += num2); num8 = RotlXor(num8, 33, num += num8); num6 = RotlXor(num6, 4, num3 += num6); num4 = RotlXor(num4, 51, num5 += num4); num2 = RotlXor(num2, 13, num7 += num2); num16 = RotlXor(num16, 34, num13 += num16); num14 = RotlXor(num14, 41, num15 += num14); num12 = RotlXor(num12, 59, num9 += num12); num10 = RotlXor(num10, 17, num11 += num10); num16 = RotlXor(num16, 5, num += num16); num12 = RotlXor(num12, 20, num3 += num12); num14 = RotlXor(num14, 48, num7 += num14); num10 = RotlXor(num10, 41, num5 += num10); num2 = RotlXor(num2, 47, num15 += num2); num6 = RotlXor(num6, 28, num9 += num6); num4 = RotlXor(num4, 16, num11 += num4); num8 = RotlXor(num8, 25, num13 += num8); num += kw[num17]; num2 += kw[num17 + 1]; num3 += kw[num17 + 2]; num4 += kw[num17 + 3]; num5 += kw[num17 + 4]; num6 += kw[num17 + 5]; num7 += kw[num17 + 6]; num8 += kw[num17 + 7]; num9 += kw[num17 + 8]; num10 += kw[num17 + 9]; num11 += kw[num17 + 10]; num12 += kw[num17 + 11]; num13 += kw[num17 + 12]; num14 += kw[num17 + 13] + t[num18]; num15 += kw[num17 + 14] + t[num18 + 1]; num16 += kw[num17 + 15] + (uint)i; num2 = RotlXor(num2, 41, num += num2); num4 = RotlXor(num4, 9, num3 += num4); num6 = RotlXor(num6, 37, num5 += num6); num8 = RotlXor(num8, 31, num7 += num8); num10 = RotlXor(num10, 12, num9 += num10); num12 = RotlXor(num12, 47, num11 += num12); num14 = RotlXor(num14, 44, num13 += num14); num16 = RotlXor(num16, 30, num15 += num16); num10 = RotlXor(num10, 16, num += num10); num14 = RotlXor(num14, 34, num3 += num14); num12 = RotlXor(num12, 56, num7 += num12); num16 = RotlXor(num16, 51, num5 += num16); num8 = RotlXor(num8, 4, num11 += num8); num4 = RotlXor(num4, 53, num13 += num4); num6 = RotlXor(num6, 42, num15 += num6); num2 = RotlXor(num2, 41, num9 += num2); num8 = RotlXor(num8, 31, num += num8); num6 = RotlXor(num6, 44, num3 += num6); num4 = RotlXor(num4, 47, num5 += num4); num2 = RotlXor(num2, 46, num7 += num2); num16 = RotlXor(num16, 19, num13 += num16); num14 = RotlXor(num14, 42, num15 += num14); num12 = RotlXor(num12, 44, num9 += num12); num10 = RotlXor(num10, 25, num11 += num10); num16 = RotlXor(num16, 9, num += num16); num12 = RotlXor(num12, 48, num3 += num12); num14 = RotlXor(num14, 35, num7 += num14); num10 = RotlXor(num10, 52, num5 += num10); num2 = RotlXor(num2, 23, num15 += num2); num6 = RotlXor(num6, 31, num9 += num6); num4 = RotlXor(num4, 37, num11 += num4); num8 = RotlXor(num8, 20, num13 += num8); num += kw[num17 + 1]; num2 += kw[num17 + 2]; num3 += kw[num17 + 3]; num4 += kw[num17 + 4]; num5 += kw[num17 + 5]; num6 += kw[num17 + 6]; num7 += kw[num17 + 7]; num8 += kw[num17 + 8]; num9 += kw[num17 + 9]; num10 += kw[num17 + 10]; num11 += kw[num17 + 11]; num12 += kw[num17 + 12]; num13 += kw[num17 + 13]; num14 += kw[num17 + 14] + t[num18 + 1]; num15 += kw[num17 + 15] + t[num18 + 2]; num16 += kw[num17 + 16] + (uint)i + 1; } outWords[0] = num; outWords[1] = num2; outWords[2] = num3; outWords[3] = num4; outWords[4] = num5; outWords[5] = num6; outWords[6] = num7; outWords[7] = num8; outWords[8] = num9; outWords[9] = num10; outWords[10] = num11; outWords[11] = num12; outWords[12] = num13; outWords[13] = num14; outWords[14] = num15; outWords[15] = num16; } internal override void DecryptBlock(ulong[] block, ulong[] state) { ulong[] kw = base.kw; ulong[] t = base.t; int[] mOD = MOD17; int[] mOD2 = MOD3; if (kw.Length != 33) throw new ArgumentException(); if (t.Length != 5) throw new ArgumentException(); ulong num = block[0]; ulong num2 = block[1]; ulong num3 = block[2]; ulong num4 = block[3]; ulong num5 = block[4]; ulong num6 = block[5]; ulong num7 = block[6]; ulong num8 = block[7]; ulong num9 = block[8]; ulong num10 = block[9]; ulong num11 = block[10]; ulong num12 = block[11]; ulong num13 = block[12]; ulong num14 = block[13]; ulong num15 = block[14]; ulong num16 = block[15]; for (int num17 = 19; num17 >= 1; num17 -= 2) { int num18 = mOD[num17]; int num19 = mOD2[num17]; num -= kw[num18 + 1]; num2 -= kw[num18 + 2]; num3 -= kw[num18 + 3]; num4 -= kw[num18 + 4]; num5 -= kw[num18 + 5]; num6 -= kw[num18 + 6]; num7 -= kw[num18 + 7]; num8 -= kw[num18 + 8]; num9 -= kw[num18 + 9]; num10 -= kw[num18 + 10]; num11 -= kw[num18 + 11]; num12 -= kw[num18 + 12]; num13 -= kw[num18 + 13]; num14 -= kw[num18 + 14] + t[num19 + 1]; num15 -= kw[num18 + 15] + t[num19 + 2]; num16 -= kw[num18 + 16] + (uint)num17 + 1; num16 = XorRotr(num16, 9, num); num -= num16; num12 = XorRotr(num12, 48, num3); num3 -= num12; num14 = XorRotr(num14, 35, num7); num7 -= num14; num10 = XorRotr(num10, 52, num5); num5 -= num10; num2 = XorRotr(num2, 23, num15); num15 -= num2; num6 = XorRotr(num6, 31, num9); num9 -= num6; num4 = XorRotr(num4, 37, num11); num11 -= num4; num8 = XorRotr(num8, 20, num13); num13 -= num8; num8 = XorRotr(num8, 31, num); num -= num8; num6 = XorRotr(num6, 44, num3); num3 -= num6; num4 = XorRotr(num4, 47, num5); num5 -= num4; num2 = XorRotr(num2, 46, num7); num7 -= num2; num16 = XorRotr(num16, 19, num13); num13 -= num16; num14 = XorRotr(num14, 42, num15); num15 -= num14; num12 = XorRotr(num12, 44, num9); num9 -= num12; num10 = XorRotr(num10, 25, num11); num11 -= num10; num10 = XorRotr(num10, 16, num); num -= num10; num14 = XorRotr(num14, 34, num3); num3 -= num14; num12 = XorRotr(num12, 56, num7); num7 -= num12; num16 = XorRotr(num16, 51, num5); num5 -= num16; num8 = XorRotr(num8, 4, num11); num11 -= num8; num4 = XorRotr(num4, 53, num13); num13 -= num4; num6 = XorRotr(num6, 42, num15); num15 -= num6; num2 = XorRotr(num2, 41, num9); num9 -= num2; num2 = XorRotr(num2, 41, num); num -= num2; num4 = XorRotr(num4, 9, num3); num3 -= num4; num6 = XorRotr(num6, 37, num5); num5 -= num6; num8 = XorRotr(num8, 31, num7); num7 -= num8; num10 = XorRotr(num10, 12, num9); num9 -= num10; num12 = XorRotr(num12, 47, num11); num11 -= num12; num14 = XorRotr(num14, 44, num13); num13 -= num14; num16 = XorRotr(num16, 30, num15); num15 -= num16; num -= kw[num18]; num2 -= kw[num18 + 1]; num3 -= kw[num18 + 2]; num4 -= kw[num18 + 3]; num5 -= kw[num18 + 4]; num6 -= kw[num18 + 5]; num7 -= kw[num18 + 6]; num8 -= kw[num18 + 7]; num9 -= kw[num18 + 8]; num10 -= kw[num18 + 9]; num11 -= kw[num18 + 10]; num12 -= kw[num18 + 11]; num13 -= kw[num18 + 12]; num14 -= kw[num18 + 13] + t[num19]; num15 -= kw[num18 + 14] + t[num19 + 1]; num16 -= kw[num18 + 15] + (uint)num17; num16 = XorRotr(num16, 5, num); num -= num16; num12 = XorRotr(num12, 20, num3); num3 -= num12; num14 = XorRotr(num14, 48, num7); num7 -= num14; num10 = XorRotr(num10, 41, num5); num5 -= num10; num2 = XorRotr(num2, 47, num15); num15 -= num2; num6 = XorRotr(num6, 28, num9); num9 -= num6; num4 = XorRotr(num4, 16, num11); num11 -= num4; num8 = XorRotr(num8, 25, num13); num13 -= num8; num8 = XorRotr(num8, 33, num); num -= num8; num6 = XorRotr(num6, 4, num3); num3 -= num6; num4 = XorRotr(num4, 51, num5); num5 -= num4; num2 = XorRotr(num2, 13, num7); num7 -= num2; num16 = XorRotr(num16, 34, num13); num13 -= num16; num14 = XorRotr(num14, 41, num15); num15 -= num14; num12 = XorRotr(num12, 59, num9); num9 -= num12; num10 = XorRotr(num10, 17, num11); num11 -= num10; num10 = XorRotr(num10, 38, num); num -= num10; num14 = XorRotr(num14, 19, num3); num3 -= num14; num12 = XorRotr(num12, 10, num7); num7 -= num12; num16 = XorRotr(num16, 55, num5); num5 -= num16; num8 = XorRotr(num8, 49, num11); num11 -= num8; num4 = XorRotr(num4, 18, num13); num13 -= num4; num6 = XorRotr(num6, 23, num15); num15 -= num6; num2 = XorRotr(num2, 52, num9); num9 -= num2; num2 = XorRotr(num2, 24, num); num -= num2; num4 = XorRotr(num4, 13, num3); num3 -= num4; num6 = XorRotr(num6, 8, num5); num5 -= num6; num8 = XorRotr(num8, 47, num7); num7 -= num8; num10 = XorRotr(num10, 8, num9); num9 -= num10; num12 = XorRotr(num12, 17, num11); num11 -= num12; num14 = XorRotr(num14, 22, num13); num13 -= num14; num16 = XorRotr(num16, 37, num15); num15 -= num16; } num -= kw[0]; num2 -= kw[1]; num3 -= kw[2]; num4 -= kw[3]; num5 -= kw[4]; num6 -= kw[5]; num7 -= kw[6]; num8 -= kw[7]; num9 -= kw[8]; num10 -= kw[9]; num11 -= kw[10]; num12 -= kw[11]; num13 -= kw[12]; num14 -= kw[13] + t[0]; num15 -= kw[14] + t[1]; num16 -= kw[15]; state[0] = num; state[1] = num2; state[2] = num3; state[3] = num4; state[4] = num5; state[5] = num6; state[6] = num7; state[7] = num8; state[8] = num9; state[9] = num10; state[10] = num11; state[11] = num12; state[12] = num13; state[13] = num14; state[14] = num15; state[15] = num16; } } public const int BLOCKSIZE_256 = 256; public const int BLOCKSIZE_512 = 512; public const int BLOCKSIZE_1024 = 1024; private const int TWEAK_SIZE_BYTES = 16; private const int TWEAK_SIZE_WORDS = 2; private const int ROUNDS_256 = 72; private const int ROUNDS_512 = 72; private const int ROUNDS_1024 = 80; private const int MAX_ROUNDS = 80; private const ulong C_240 = 2004413935125273122; private static readonly int[] MOD9; private static readonly int[] MOD17; private static readonly int[] MOD5; private static readonly int[] MOD3; private readonly int blocksizeBytes; private readonly int blocksizeWords; private readonly ulong[] currentBlock; private readonly ulong[] t = new ulong[5]; private readonly ulong[] kw; private readonly ThreefishCipher cipher; private bool forEncryption; public virtual string AlgorithmName => "Threefish-" + (blocksizeBytes * 8).ToString(); static ThreefishEngine() { MOD9 = new int[80]; MOD17 = new int[MOD9.Length]; MOD5 = new int[MOD9.Length]; MOD3 = new int[MOD9.Length]; for (int i = 0; i < MOD9.Length; i++) { MOD17[i] = i % 17; MOD9[i] = i % 9; MOD5[i] = i % 5; MOD3[i] = i % 3; } } public ThreefishEngine(int blocksizeBits) { blocksizeBytes = blocksizeBits / 8; blocksizeWords = blocksizeBytes / 8; currentBlock = new ulong[blocksizeWords]; kw = new ulong[2 * blocksizeWords + 1]; switch (blocksizeBits) { case 256: cipher = new Threefish256Cipher(kw, t); break; case 512: cipher = new Threefish512Cipher(kw, t); break; case 1024: cipher = new Threefish1024Cipher(kw, t); break; default: throw new ArgumentException("Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits"); } } public virtual void Init(bool forEncryption, ICipherParameters parameters) { byte[] key; byte[] array; if (parameters is TweakableBlockCipherParameters) { TweakableBlockCipherParameters obj = (TweakableBlockCipherParameters)parameters; key = obj.Key.GetKey(); array = obj.Tweak; } else { if (!(parameters is KeyParameter)) throw new ArgumentException("Invalid parameter passed to Threefish init - " + Platform.GetTypeName(parameters)); key = ((KeyParameter)parameters).GetKey(); array = null; } ulong[] array2 = null; ulong[] array3 = null; int num; if (key != null) { if (key.Length != blocksizeBytes) { num = blocksizeBytes; throw new ArgumentException("Threefish key must be same size as block (" + num.ToString() + " bytes)"); } array2 = new ulong[blocksizeWords]; Pack.LE_To_UInt64(key, 0, array2); } if (array != null) { if (array.Length != 16) { num = 16; throw new ArgumentException("Threefish tweak must be " + num.ToString() + " bytes"); } array3 = new ulong[2]; Pack.LE_To_UInt64(array, 0, array3); } Init(forEncryption, array2, array3); } internal void Init(bool forEncryption, ulong[] key, ulong[] tweak) { this.forEncryption = forEncryption; if (key != null) SetKey(key); if (tweak != null) SetTweak(tweak); } private void SetKey(ulong[] key) { if (key.Length != blocksizeWords) throw new ArgumentException("Threefish key must be same size as block (" + blocksizeWords.ToString() + " words)"); ulong num = 2004413935125273122; for (int i = 0; i < blocksizeWords; i++) { kw[i] = key[i]; num ^= kw[i]; } kw[blocksizeWords] = num; Array.Copy(kw, 0, kw, blocksizeWords + 1, blocksizeWords); } private void SetTweak(ulong[] tweak) { if (tweak.Length != 2) throw new ArgumentException("Tweak must be " + 2.ToString() + " words."); t[0] = tweak[0]; t[1] = tweak[1]; t[2] = (t[0] ^ t[1]); t[3] = t[0]; t[4] = t[1]; } public virtual int GetBlockSize() { return blocksizeBytes; } public virtual int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff) { Check.DataLength(inBytes, inOff, blocksizeBytes, "input buffer too short"); Check.OutputLength(outBytes, outOff, blocksizeBytes, "output buffer too short"); Pack.LE_To_UInt64(inBytes, inOff, currentBlock); ProcessBlock(currentBlock, currentBlock); Pack.UInt64_To_LE(currentBlock, outBytes, outOff); return blocksizeBytes; } internal int ProcessBlock(ulong[] inWords, ulong[] outWords) { if (kw[blocksizeWords] == 0) throw new InvalidOperationException("Threefish engine not initialised"); if (inWords.Length != blocksizeWords) throw new DataLengthException("input buffer too short"); if (outWords.Length != blocksizeWords) throw new OutputLengthException("output buffer too short"); if (forEncryption) cipher.EncryptBlock(inWords, outWords); else cipher.DecryptBlock(inWords, outWords); return blocksizeWords; } private static ulong RotlXor(ulong x, int n, ulong xor) { return ((x << n) | (x >> 64 - n)) ^ xor; } private static ulong XorRotr(ulong x, int n, ulong xor) { ulong num = x ^ xor; return (num >> n) | (num << 64 - n); } } }