コード例 #1
0
        public void ShouldEncryptDecryptBackToSameValue(string label, string alphabet, string word, BitString tweak, BitString key)
        {
            var wordNumeralString = NumeralString.ToNumeralString(word, alphabet);

            var encryptResult = _subject.ProcessPayload(new FfxModeBlockCipherParameters()
            {
                Direction = BlockCipherDirections.Encrypt,
                Iv        = tweak,
                Key       = key,
                Payload   = NumeralString.ToBitString(wordNumeralString),
                Radix     = alphabet.Length
            });

            var decryptResult = _subject.ProcessPayload(new FfxModeBlockCipherParameters()
            {
                Direction = BlockCipherDirections.Decrypt,
                Iv        = tweak,
                Key       = key,
                Payload   = encryptResult.Result,
                Radix     = alphabet.Length
            });

            Assert.AreEqual(
                NumeralString.ToAlphabetString(alphabet, alphabet.Length, wordNumeralString),
                NumeralString.ToAlphabetString(alphabet, alphabet.Length, NumeralString.ToNumeralString(decryptResult.Result))
                );
        }
コード例 #2
0
        public void ShouldConvertToBitStringFromNumeralString(int[] values, string expectedHex)
        {
            _subject = new NumeralString(values);

            var result = NumeralString.ToBitString(_subject);

            Assert.AreEqual(expectedHex, result.ToHex());
        }
コード例 #3
0
 public void ShouldThrowWhenWordContainsCharactersNotWithinAlphabet(string word, string alphabet, bool shouldThrow)
 {
     if (shouldThrow)
     {
         Assert.Throws <ArgumentException>(() => NumeralString.ToNumeralString(word, alphabet));
     }
     else
     {
         Assert.DoesNotThrow(() => NumeralString.ToNumeralString(word, alphabet));
     }
 }
コード例 #4
0
        public void ShouldConvertToNumeralStringFromBitString(string hex, int[] expectedValues)
        {
            var bs = new BitString(hex);

            var result = NumeralString.ToNumeralString(bs);

            for (var i = 0; i < expectedValues.Length; i++)
            {
                Assert.AreEqual(expectedValues[i], result.Numbers[i], $"{nameof(i)}: {i}");
            }
        }
コード例 #5
0
        public void ShouldConstructWithIntssProperly(int[] values)
        {
            _subject = new NumeralString(values);

            Assert.Multiple(() =>
            {
                for (var i = 0; i < values.Length; i++)
                {
                    Assert.AreEqual(values[i], _subject.Numbers[i], $"{nameof(i)}: {i}");
                }
            });
        }
コード例 #6
0
        public void ShouldConstructWithStringProperly(string value, int[] expectedValues)
        {
            _subject = new NumeralString(value);

            Assert.Multiple(() =>
            {
                for (var i = 0; i < expectedValues.Length; i++)
                {
                    Assert.AreEqual(expectedValues[i], _subject.Numbers[i], $"{nameof(i)}: {i}");
                }
            });
        }
コード例 #7
0
        public void ShouldDecryptCorrectly(string testLabel, NumeralString payload, BitString tweak, BitString key, int radix, NumeralString cipherText)
        {
            var result = _subject.ProcessPayload(new FfxModeBlockCipherParameters()
            {
                Direction = BlockCipherDirections.Decrypt,
                Iv        = tweak,
                Key       = key,
                Payload   = NumeralString.ToBitString(cipherText),
                Radix     = radix
            });

            Assert.AreEqual(payload.ToString(), NumeralString.ToNumeralString(result.Result).ToString());
        }
コード例 #8
0
        public NumeralString Rev(NumeralString x)
        {
            // 1. For i from 1 to LEN(X), let Y[i] = X[LEN(X)+1–i].
            var result = new int[x.Numbers.Length];

            for (var i = 0; i <= x.Numbers.Length - 1; i++)
            {
                result[i] = x.Numbers[x.Numbers.Length - 1 - i];
            }

            // 2. Return Y[1..LEN(X)].
            return(new NumeralString(result));
        }
コード例 #9
0
        public BigInteger Num(int radix, NumeralString x)
        {
            // 1. Let x = 0.
            BigInteger result = 0;

            // 2. For i from 1 to LEN(X), let x = x*radix + X[i].
            for (var i = 0; i <= x.Numbers.Length - 1; i++)
            {
                result = result * radix + x.Numbers[i];
            }

            // 3. Return x.
            return(result);
        }
コード例 #10
0
        public void ShouldDecryptAlphabetStringsCorrectly(string label, string alphabet, string word, BitString tweak, BitString key, string expectedResult)
        {
            var wordNumeralString           = NumeralString.ToNumeralString(word, alphabet);
            var expectedResultNumeralString = NumeralString.ToNumeralString(expectedResult, alphabet);

            var result = _subject.ProcessPayload(new FfxModeBlockCipherParameters()
            {
                Direction = BlockCipherDirections.Decrypt,
                Iv        = tweak,
                Key       = key,
                Payload   = NumeralString.ToBitString(expectedResultNumeralString),
                Radix     = alphabet.Length
            });

            Assert.AreEqual(
                NumeralString.ToAlphabetString(alphabet, alphabet.Length, wordNumeralString),
                NumeralString.ToAlphabetString(alphabet, alphabet.Length, NumeralString.ToNumeralString(result.Result))
                );
        }
コード例 #11
0
        public void ShouldDetermineIfNumeralStringValidToAlphabet(string alphabet, int[] numbers, bool expectedOutcome)
        {
            var numeralString = new NumeralString(numbers);

            Assert.AreEqual(expectedOutcome, NumeralString.IsNumeralStringValidWithAlphabet(alphabet, numeralString));
        }
コード例 #12
0
        protected override BitString Decrypt(IFfxModeBlockCipherParameters param)
        {
            var mode = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb);

            var X = NumeralString.ToNumeralString(param.Payload);
            var n = X.Numbers.Length;

            // 1. Let u = ⌈n / 2⌉; v = n – u.
            var u = n.CeilingDivide(2);
            var v = n - u;

            // 2. Let A = X[1..u]; B = X[u + 1..n].
            var A = new NumeralString(X.Numbers.Take(u).ToArray());
            var B = new NumeralString(X.Numbers.Skip(u).Take(v).ToArray());

            // Let TL = T[0..31] and TR = T[32..63]
            var TL = param.Iv.Substring(32, 32);
            var TR = param.Iv.Substring(0, 32);

            // 4. For i from 0 to 7:
            for (var i = NumberOfRounds - 1; i >= 0; i--)
            {
                // i. If i is even, let m = u and W = TR, else let m = v and W = TL.
                //     v. If i is even, let m = u; else, let m = v.
                var m = i % 2 == 0 ? u : v;
                var W = i % 2 == 0 ? TR : TL;

                // ii. Let P = W ⊕ [i] 4 || [NUMradix(REV(B))]12 .
                var numA = new BitString(_ffInternals.Num(param.Radix, _ffInternals.Rev(A)));
                if (numA.BitLength < 12 * BitsInByte)
                {
                    var bitsToPrepend = new BitString(12 * BitsInByte - numA.BitLength);
                    numA = bitsToPrepend.ConcatenateBits(numA);
                }

                var P = W.XOR(new BitString(new byte[3]).ConcatenateBits(((byte)i).ToBitString()))
                        .ConcatenateBits(numA);

                // iii. Let S = REVB(CIPHREVB(K) REVB(P)).
                var S = _ffInternals.RevB(mode.ProcessPayload(
                                              new ModeBlockCipherParameters(
                                                  BlockCipherDirections.Encrypt,
                                                  _ffInternals.RevB(param.Key),
                                                  _ffInternals.RevB(P))).Result);

                // iv. Let y = NUM(S).
                var y = _ffInternals.Num(S);

                // v. Let c = (NUMradix (REV(B)) - y) mod radix m .
                var c = (_ffInternals.Num(param.Radix, _ffInternals.Rev(B)) - y).PosMod(BigInteger.Pow(param.Radix, m));

                // vi. Let C = REV(STRm radix(c)).
                var C = _ffInternals.Rev(_ffInternals.Str(param.Radix, m, c));

                // vii. Let B = A.
                B = A;

                // viii. Let A = C.
                A = C;
            }

            // 5. Return A || B.
            return(NumeralString.ToBitString(A)
                   .ConcatenateBits(NumeralString.ToBitString(B)));
        }
コード例 #13
0
        protected override BitString Encrypt(IFfxModeBlockCipherParameters param)
        {
            var mode = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb);

            var X = NumeralString.ToNumeralString(param.Payload);
            var n = X.Numbers.Length;
            var t = param.Iv.BitLength / BitsInByte;

            // 1. Let u = Floor(n/2); v = n – u.
            var u = n / 2;
            var v = n - u;

            // 2. Let A = X[1..u]; B = X[u + 1..n].
            var A = new NumeralString(X.Numbers.Take(u).ToArray());
            var B = new NumeralString(X.Numbers.Skip(u).Take(v).ToArray());

            // 3. Let b = Ceiling(Ceiling(v×LOG(radix))/8).
            var b = (int)System.Math.Ceiling(System.Math.Ceiling(v * System.Math.Log(param.Radix, 2)) / 8);

            // 4. Let d = 4*Ceiling(b/4) + 4.
            var d = 4 * b.CeilingDivide(4) + 4;

            // the number times to iterate through the concatenation of cipher iterator blocks
            var jCount = d.CeilingDivide(16);

            // 5. Let P = [1] 1 || [2] 1 || [1] 1 || [radix] 3 || [10] 1 || [u mod 256] 1 || [n] 4 || [t] 4.
            var pBytes = new byte[_engine.BlockSizeBytes];

            pBytes[0] = 0x01;
            pBytes[1] = 0x02;
            pBytes[2] = 0x01;
            // 3 bytes for radix, but radix is capped at 16 bits (2^16), so add a 0 byte
            pBytes[3] = 0x00;
            Array.Copy(BitString.To32BitString(param.Radix).GetLeastSignificantBits(16).ToBytes(), 0, pBytes, 4, 2);
            pBytes[6] = 0x0a;
            pBytes[7] = (byte)(u % 256);
            Array.Copy(BitString.To32BitString(n).ToBytes(), 0, pBytes, 8, 4);
            Array.Copy(BitString.To32BitString(t).ToBytes(), 0, pBytes, 12, 4);
            var P = new BitString(pBytes);

            // 6. For i from 0 to 9:
            for (var i = 0; i < NumberOfRounds; i++)
            {
                // i. Let Q = T || [0] (−t−b−1) mod 16 || [i] 1 || [NUMradix(B)]b.
                var numB = new BitString(_ffInternals.Num(param.Radix, B));
                if (numB.BitLength < b * BitsInByte)
                {
                    var bitsToPrepend = new BitString(b * BitsInByte - numB.BitLength);
                    numB = bitsToPrepend.ConcatenateBits(numB);
                }

                var Q = new BitString(0)
                        .ConcatenateBits(param.Iv)
                        .ConcatenateBits(new BitString((-t - b - 1).PosMod(16) * BitsInByte))
                        .ConcatenateBits(((byte)i).ToBitString())
                        .ConcatenateBits(numB.GetMostSignificantBits(b * BitsInByte));

                //     ii. Let R = PRF(P || Q).
                var R = _ffInternals.Prf(P.ConcatenateBits(Q), param.Key);

                //     iii. Let S be the first d bytes of the following string of Ceiling(d/16) blocks:
                //         R || CIPHK(R Å [1]16) || CIPHK (R Å [2]16) … CIPHK(R Å [éd/16ù–1]).
                var S = R.GetDeepCopy();
                for (var j = 1; j < jCount; j++)
                {
                    var pad = BitString.To32BitString(j).PadToModulusMsb(_engine.BlockSizeBits);
                    S = S.ConcatenateBits(
                        mode.ProcessPayload(
                            new ModeBlockCipherParameters(
                                BlockCipherDirections.Encrypt,
                                param.Key,
                                R.XOR(pad))).Result
                        );
                }
                S = S.GetMostSignificantBits(d * BitsInByte);

                //     iv. Let y = NUM(S).
                var y = _ffInternals.Num(S);

                //     v. If i is even, let m = u; else, let m = v.
                var m = i % 2 == 0 ? u : v;

                //     vi. Let c = (NUMradix (A)+y) mod radix m .
                var c = (_ffInternals.Num(param.Radix, A) + y).PosMod(BigInteger.Pow(param.Radix, m));

                //     vii. Let C = STR m radix (c).
                var C = _ffInternals.Str(param.Radix, m, c);

                //     viii. Let A = B.
                A = B;
                //     ix. Let B = C.
                B = C;
            }

            // 7. Return A || B.
            return(NumeralString.ToBitString(A)
                   .ConcatenateBits(NumeralString.ToBitString(B)));
        }
コード例 #14
0
 public void ShouldDetermineIfAlphabetValid(string alphabet, bool expectedOutcome)
 {
     Assert.AreEqual(expectedOutcome, NumeralString.IsAlphabetValid(alphabet));
 }
コード例 #15
0
 public void ShouldToAlphabetString(string alphabet, int[] numbers, string expectation)
 {
     Assert.AreEqual(expectation, NumeralString.ToAlphabetString(alphabet, alphabet.Length, new NumeralString(numbers)));
 }
コード例 #16
0
 public void ShouldArgumentOutOfRangeExceptionWithNumbersGtTwoPow16(string value)
 {
     Assert.Throws <ArgumentOutOfRangeException>(() => _subject = new NumeralString(value));
 }
コード例 #17
0
 public void ShouldArgumentExceptionWithNonNumeralOrSpaces(string value)
 {
     Assert.Throws <ArgumentException>(() => _subject = new NumeralString(value));
 }
コード例 #18
0
 public void ShouldToNumeralStringFromWord(string word, string alphabet, string expectedBaseToNumbersSeparatedBySpace)
 {
     Assert.AreEqual(expectedBaseToNumbersSeparatedBySpace, NumeralString.ToNumeralString(word, alphabet).ToString());
 }