< Summary

Information
Class: Renci.SshNet.Security.Cryptography.Ciphers.DesCipher
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Cryptography\Ciphers\DesCipher.cs
Line coverage
97%
Covered lines: 339
Uncovered lines: 10
Coverable lines: 349
Total lines: 479
Line coverage: 97.1%
Branch coverage
86%
Covered branches: 33
Total branches: 38
Branch coverage: 86.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.cctor()100%1100%
.ctor(...)100%1100%
EncryptBlock(...)66.66%663.63%
DecryptBlock(...)66.66%663.63%
GenerateWorkingKey(...)100%22100%
ValidateKey()50%266.66%
DesFunc(...)100%2100%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Cryptography\Ciphers\DesCipher.cs

#LineLine coverage
 1using System;
 2using Renci.SshNet.Common;
 3
 4namespace Renci.SshNet.Security.Cryptography.Ciphers
 5{
 6    /// <summary>
 7    /// Implements DES cipher algorithm.
 8    /// </summary>
 9    public class DesCipher : BlockCipher
 10    {
 11        private int[] _encryptionKey;
 12
 13        private int[] _decryptionKey;
 14
 415        private static readonly short[] Bytebit = { 128, 64, 32, 16, 8, 4, 2, 1 };
 16
 417        private static readonly int[] Bigbyte =
 418        {
 419            0x800000, 0x400000, 0x200000, 0x100000,
 420            0x080000, 0x040000, 0x020000, 0x010000,
 421            0x008000, 0x004000, 0x002000, 0x001000,
 422            0x000800, 0x000400, 0x000200, 0x000100,
 423            0x000080, 0x000040, 0x000020, 0x000010,
 424            0x000008, 0x000004, 0x000002, 0x000001
 425        };
 26
 27        /*
 28         * Use the key schedule specified in the Standard (ANSI X3.92-1981).
 29         */
 30
 431        private static readonly byte[] Pc1 =
 432        {
 433            56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
 434            9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
 435            62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
 436            13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
 437        };
 38
 439        private static readonly byte[] Totrot =
 440        {
 441            1, 2, 4, 6, 8, 10, 12, 14,
 442            15, 17, 19, 21, 23, 25, 27, 28
 443        };
 44
 445        private static readonly byte[] Pc2 =
 446        {
 447            13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
 448            22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
 449            40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
 450            43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
 451        };
 52
 453        private static readonly uint[] Sp1 =
 454        {
 455            0x01010400, 0x00000000, 0x00010000, 0x01010404,
 456            0x01010004, 0x00010404, 0x00000004, 0x00010000,
 457            0x00000400, 0x01010400, 0x01010404, 0x00000400,
 458            0x01000404, 0x01010004, 0x01000000, 0x00000004,
 459            0x00000404, 0x01000400, 0x01000400, 0x00010400,
 460            0x00010400, 0x01010000, 0x01010000, 0x01000404,
 461            0x00010004, 0x01000004, 0x01000004, 0x00010004,
 462            0x00000000, 0x00000404, 0x00010404, 0x01000000,
 463            0x00010000, 0x01010404, 0x00000004, 0x01010000,
 464            0x01010400, 0x01000000, 0x01000000, 0x00000400,
 465            0x01010004, 0x00010000, 0x00010400, 0x01000004,
 466            0x00000400, 0x00000004, 0x01000404, 0x00010404,
 467            0x01010404, 0x00010004, 0x01010000, 0x01000404,
 468            0x01000004, 0x00000404, 0x00010404, 0x01010400,
 469            0x00000404, 0x01000400, 0x01000400, 0x00000000,
 470            0x00010004, 0x00010400, 0x00000000, 0x01010004
 471        };
 72
 473        private static readonly uint[] Sp2 =
 474        {
 475            0x80108020, 0x80008000, 0x00008000, 0x00108020,
 476            0x00100000, 0x00000020, 0x80100020, 0x80008020,
 477            0x80000020, 0x80108020, 0x80108000, 0x80000000,
 478            0x80008000, 0x00100000, 0x00000020, 0x80100020,
 479            0x00108000, 0x00100020, 0x80008020, 0x00000000,
 480            0x80000000, 0x00008000, 0x00108020, 0x80100000,
 481            0x00100020, 0x80000020, 0x00000000, 0x00108000,
 482            0x00008020, 0x80108000, 0x80100000, 0x00008020,
 483            0x00000000, 0x00108020, 0x80100020, 0x00100000,
 484            0x80008020, 0x80100000, 0x80108000, 0x00008000,
 485            0x80100000, 0x80008000, 0x00000020, 0x80108020,
 486            0x00108020, 0x00000020, 0x00008000, 0x80000000,
 487            0x00008020, 0x80108000, 0x00100000, 0x80000020,
 488            0x00100020, 0x80008020, 0x80000020, 0x00100020,
 489            0x00108000, 0x00000000, 0x80008000, 0x00008020,
 490            0x80000000, 0x80100020, 0x80108020, 0x00108000
 491        };
 92
 493        private static readonly uint[] Sp3 =
 494        {
 495            0x00000208, 0x08020200, 0x00000000, 0x08020008,
 496            0x08000200, 0x00000000, 0x00020208, 0x08000200,
 497            0x00020008, 0x08000008, 0x08000008, 0x00020000,
 498            0x08020208, 0x00020008, 0x08020000, 0x00000208,
 499            0x08000000, 0x00000008, 0x08020200, 0x00000200,
 4100            0x00020200, 0x08020000, 0x08020008, 0x00020208,
 4101            0x08000208, 0x00020200, 0x00020000, 0x08000208,
 4102            0x00000008, 0x08020208, 0x00000200, 0x08000000,
 4103            0x08020200, 0x08000000, 0x00020008, 0x00000208,
 4104            0x00020000, 0x08020200, 0x08000200, 0x00000000,
 4105            0x00000200, 0x00020008, 0x08020208, 0x08000200,
 4106            0x08000008, 0x00000200, 0x00000000, 0x08020008,
 4107            0x08000208, 0x00020000, 0x08000000, 0x08020208,
 4108            0x00000008, 0x00020208, 0x00020200, 0x08000008,
 4109            0x08020000, 0x08000208, 0x00000208, 0x08020000,
 4110            0x00020208, 0x00000008, 0x08020008, 0x00020200
 4111        };
 112
 4113        private static readonly uint[] Sp4 =
 4114        {
 4115            0x00802001, 0x00002081, 0x00002081, 0x00000080,
 4116            0x00802080, 0x00800081, 0x00800001, 0x00002001,
 4117            0x00000000, 0x00802000, 0x00802000, 0x00802081,
 4118            0x00000081, 0x00000000, 0x00800080, 0x00800001,
 4119            0x00000001, 0x00002000, 0x00800000, 0x00802001,
 4120            0x00000080, 0x00800000, 0x00002001, 0x00002080,
 4121            0x00800081, 0x00000001, 0x00002080, 0x00800080,
 4122            0x00002000, 0x00802080, 0x00802081, 0x00000081,
 4123            0x00800080, 0x00800001, 0x00802000, 0x00802081,
 4124            0x00000081, 0x00000000, 0x00000000, 0x00802000,
 4125            0x00002080, 0x00800080, 0x00800081, 0x00000001,
 4126            0x00802001, 0x00002081, 0x00002081, 0x00000080,
 4127            0x00802081, 0x00000081, 0x00000001, 0x00002000,
 4128            0x00800001, 0x00002001, 0x00802080, 0x00800081,
 4129            0x00002001, 0x00002080, 0x00800000, 0x00802001,
 4130            0x00000080, 0x00800000, 0x00002000, 0x00802080
 4131        };
 132
 4133        private static readonly uint[] Sp5 =
 4134        {
 4135            0x00000100, 0x02080100, 0x02080000, 0x42000100,
 4136            0x00080000, 0x00000100, 0x40000000, 0x02080000,
 4137            0x40080100, 0x00080000, 0x02000100, 0x40080100,
 4138            0x42000100, 0x42080000, 0x00080100, 0x40000000,
 4139            0x02000000, 0x40080000, 0x40080000, 0x00000000,
 4140            0x40000100, 0x42080100, 0x42080100, 0x02000100,
 4141            0x42080000, 0x40000100, 0x00000000, 0x42000000,
 4142            0x02080100, 0x02000000, 0x42000000, 0x00080100,
 4143            0x00080000, 0x42000100, 0x00000100, 0x02000000,
 4144            0x40000000, 0x02080000, 0x42000100, 0x40080100,
 4145            0x02000100, 0x40000000, 0x42080000, 0x02080100,
 4146            0x40080100, 0x00000100, 0x02000000, 0x42080000,
 4147            0x42080100, 0x00080100, 0x42000000, 0x42080100,
 4148            0x02080000, 0x00000000, 0x40080000, 0x42000000,
 4149            0x00080100, 0x02000100, 0x40000100, 0x00080000,
 4150            0x00000000, 0x40080000, 0x02080100, 0x40000100
 4151        };
 152
 4153        private static readonly uint[] Sp6 =
 4154        {
 4155            0x20000010, 0x20400000, 0x00004000, 0x20404010,
 4156            0x20400000, 0x00000010, 0x20404010, 0x00400000,
 4157            0x20004000, 0x00404010, 0x00400000, 0x20000010,
 4158            0x00400010, 0x20004000, 0x20000000, 0x00004010,
 4159            0x00000000, 0x00400010, 0x20004010, 0x00004000,
 4160            0x00404000, 0x20004010, 0x00000010, 0x20400010,
 4161            0x20400010, 0x00000000, 0x00404010, 0x20404000,
 4162            0x00004010, 0x00404000, 0x20404000, 0x20000000,
 4163            0x20004000, 0x00000010, 0x20400010, 0x00404000,
 4164            0x20404010, 0x00400000, 0x00004010, 0x20000010,
 4165            0x00400000, 0x20004000, 0x20000000, 0x00004010,
 4166            0x20000010, 0x20404010, 0x00404000, 0x20400000,
 4167            0x00404010, 0x20404000, 0x00000000, 0x20400010,
 4168            0x00000010, 0x00004000, 0x20400000, 0x00404010,
 4169            0x00004000, 0x00400010, 0x20004010, 0x00000000,
 4170            0x20404000, 0x20000000, 0x00400010, 0x20004010
 4171        };
 172
 4173        private static readonly uint[] Sp7 =
 4174        {
 4175            0x00200000, 0x04200002, 0x04000802, 0x00000000,
 4176            0x00000800, 0x04000802, 0x00200802, 0x04200800,
 4177            0x04200802, 0x00200000, 0x00000000, 0x04000002,
 4178            0x00000002, 0x04000000, 0x04200002, 0x00000802,
 4179            0x04000800, 0x00200802, 0x00200002, 0x04000800,
 4180            0x04000002, 0x04200000, 0x04200800, 0x00200002,
 4181            0x04200000, 0x00000800, 0x00000802, 0x04200802,
 4182            0x00200800, 0x00000002, 0x04000000, 0x00200800,
 4183            0x04000000, 0x00200800, 0x00200000, 0x04000802,
 4184            0x04000802, 0x04200002, 0x04200002, 0x00000002,
 4185            0x00200002, 0x04000000, 0x04000800, 0x00200000,
 4186            0x04200800, 0x00000802, 0x00200802, 0x04200800,
 4187            0x00000802, 0x04000002, 0x04200802, 0x04200000,
 4188            0x00200800, 0x00000000, 0x00000002, 0x04200802,
 4189            0x00000000, 0x00200802, 0x04200000, 0x00000800,
 4190            0x04000002, 0x04000800, 0x00000800, 0x00200002
 4191        };
 192
 4193        private static readonly uint[] Sp8 =
 4194        {
 4195            0x10001040, 0x00001000, 0x00040000, 0x10041040,
 4196            0x10000000, 0x10001040, 0x00000040, 0x10000000,
 4197            0x00040040, 0x10040000, 0x10041040, 0x00041000,
 4198            0x10041000, 0x00041040, 0x00001000, 0x00000040,
 4199            0x10040000, 0x10000040, 0x10001000, 0x00001040,
 4200            0x00041000, 0x00040040, 0x10040040, 0x10041000,
 4201            0x00001040, 0x00000000, 0x00000000, 0x10040040,
 4202            0x10000040, 0x10001000, 0x00041040, 0x00040000,
 4203            0x00041040, 0x00040000, 0x10041000, 0x00001000,
 4204            0x00000040, 0x10040040, 0x00001000, 0x00041040,
 4205            0x10001000, 0x00000040, 0x10000040, 0x10040000,
 4206            0x10040040, 0x10000000, 0x00040000, 0x10001040,
 4207            0x00000000, 0x10041040, 0x00040040, 0x10000040,
 4208            0x10040000, 0x10001000, 0x10001040, 0x00000000,
 4209            0x10041040, 0x00041000, 0x00041000, 0x00001040,
 4210            0x00001040, 0x00040040, 0x10000000, 0x10041000
 4211        };
 212
 213        /// <summary>
 214        /// Initializes a new instance of the <see cref="DesCipher"/> class.
 215        /// </summary>
 216        /// <param name="key">The key.</param>
 217        /// <param name="mode">The mode.</param>
 218        /// <param name="padding">The padding.</param>
 219        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
 220        public DesCipher(byte[] key, CipherMode mode, CipherPadding padding)
 34221            : base(key, 8, mode, padding)
 34222        {
 34223        }
 224
 225        /// <summary>
 226        /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region 
 227        /// </summary>
 228        /// <param name="inputBuffer">The input data to encrypt.</param>
 229        /// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
 230        /// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
 231        /// <param name="outputBuffer">The output to which to write encrypted data.</param>
 232        /// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
 233        /// <returns>
 234        /// The number of bytes encrypted.
 235        /// </returns>
 236        public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int o
 9237        {
 9238            if ((inputOffset + BlockSize) > inputBuffer.Length)
 0239            {
 0240                throw new ArgumentException("input buffer too short");
 241            }
 242
 9243            if ((outputOffset + BlockSize) > outputBuffer.Length)
 0244            {
 0245                throw new ArgumentException("output buffer too short");
 246            }
 247
 9248            _encryptionKey ??= GenerateWorkingKey(encrypting: true, Key);
 249
 9250            DesFunc(_encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
 251
 9252            return BlockSize;
 9253        }
 254
 255        /// <summary>
 256        /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region 
 257        /// </summary>
 258        /// <param name="inputBuffer">The input data to decrypt.</param>
 259        /// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
 260        /// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
 261        /// <param name="outputBuffer">The output to which to write decrypted data.</param>
 262        /// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
 263        /// <returns>
 264        /// The number of bytes decrypted.
 265        /// </returns>
 266        public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int o
 456267        {
 456268            if ((inputOffset + BlockSize) > inputBuffer.Length)
 0269            {
 0270                throw new ArgumentException("input buffer too short");
 271            }
 272
 456273            if ((outputOffset + BlockSize) > outputBuffer.Length)
 0274            {
 0275                throw new ArgumentException("output buffer too short");
 276            }
 277
 456278            _decryptionKey ??= GenerateWorkingKey(encrypting: false, Key);
 279
 456280            DesFunc(_decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
 281
 456282            return BlockSize;
 456283        }
 284
 285        /// <summary>
 286        /// Generates the working key.
 287        /// </summary>
 288        /// <param name="encrypting">if set to <see langword="true"/> [encrypting].</param>
 289        /// <param name="key">The key.</param>
 290        /// <returns>Generated working key.</returns>
 291        protected int[] GenerateWorkingKey(bool encrypting, byte[] key)
 84292        {
 84293            ValidateKey();
 294
 84295            var newKey = new int[32];
 84296            var pc1m = new bool[56];
 84297            var pcr = new bool[56];
 298
 9576299            for (var j = 0; j < 56; j++)
 4704300            {
 4704301                int l = Pc1[j];
 302
 4704303                pc1m[j] = (key[(uint) l >> 3] & Bytebit[l & 07]) != 0;
 4704304            }
 305
 2856306            for (var i = 0; i < 16; i++)
 1344307            {
 308                int l, m;
 309
 1344310                if (encrypting)
 592311                {
 592312                    m = i << 1;
 592313                }
 314                else
 752315                {
 752316                    m = (15 - i) << 1;
 752317                }
 318
 1344319                var n = m + 1;
 1344320                newKey[m] = newKey[n] = 0;
 321
 77952322                for (var j = 0; j < 28; j++)
 37632323                {
 37632324                    l = j + Totrot[i];
 37632325                    if (l < 28)
 18144326                    {
 18144327                        pcr[j] = pc1m[l];
 18144328                    }
 329                    else
 19488330                    {
 19488331                        pcr[j] = pc1m[l - 28];
 19488332                    }
 37632333                }
 334
 77952335                for (var j = 28; j < 56; j++)
 37632336                {
 37632337                    l = j + Totrot[i];
 37632338                    if (l < 56)
 18144339                    {
 18144340                        pcr[j] = pc1m[l];
 18144341                    }
 342                    else
 19488343                    {
 19488344                        pcr[j] = pc1m[l - 28];
 19488345                    }
 37632346                }
 347
 67200348                for (var j = 0; j < 24; j++)
 32256349                {
 32256350                    if (pcr[Pc2[j]])
 15964351                    {
 15964352                        newKey[m] |= Bigbyte[j];
 15964353                    }
 354
 32256355                    if (pcr[Pc2[j + 24]])
 15360356                    {
 15360357                        newKey[n] |= Bigbyte[j];
 15360358                    }
 32256359                }
 1344360            }
 361
 362            /*
 363             * store the processed key
 364             */
 365
 2856366            for (var i = 0; i != 32; i += 2)
 1344367            {
 1344368                var i1 = newKey[i];
 1344369                var i2 = newKey[i + 1];
 370
 1344371                newKey[i] = (int) ((uint) ((i1 & 0x00fc0000) << 6) |
 1344372                                   (uint) ((i1 & 0x00000fc0) << 10) |
 1344373                                   ((uint) (i2 & 0x00fc0000) >> 10) |
 1344374                                   ((uint) (i2 & 0x00000fc0) >> 6));
 375
 1344376                newKey[i + 1] = (int) ((uint) ((i1 & 0x0003f000) << 12) |
 1344377                                       (uint) ((i1 & 0x0000003f) << 16) |
 1344378                                       ((uint) (i2 & 0x0003f000) >> 4) |
 1344379                                       (uint) (i2 & 0x0000003f));
 1344380            }
 381
 84382            return newKey;
 84383        }
 384
 385        /// <summary>
 386        /// Validates the key.
 387        /// </summary>
 388        protected virtual void ValidateKey()
 9389        {
 9390            var keySize = Key.Length * 8;
 391
 9392            if (keySize != 64)
 0393            {
 0394                throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
 395            }
 9396        }
 397
 398        /// <summary>
 399        /// Performs DES function.
 400        /// </summary>
 401        /// <param name="wKey">The w key.</param>
 402        /// <param name="input">The input.</param>
 403        /// <param name="inOff">The in off.</param>
 404        /// <param name="outBytes">The out bytes.</param>
 405        /// <param name="outOff">The out off.</param>
 406        protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
 6936407        {
 6936408            var left = Pack.BigEndianToUInt32(input, inOff);
 6936409            var right = Pack.BigEndianToUInt32(input, inOff + 4);
 410
 6936411            var work = ((left >> 4) ^ right) & 0x0f0f0f0f;
 6936412            right ^= work;
 6936413            left ^= work << 4;
 6936414            work = ((left >> 16) ^ right) & 0x0000ffff;
 6936415            right ^= work;
 6936416            left ^= work << 16;
 6936417            work = ((right >> 2) ^ left) & 0x33333333;
 6936418            left ^= work;
 6936419            right ^= work << 2;
 6936420            work = ((right >> 8) ^ left) & 0x00ff00ff;
 6936421            left ^= work;
 6936422            right ^= work << 8;
 6936423            right = (right << 1) | (right >> 31);
 6936424            work = (left ^ right) & 0xaaaaaaaa;
 6936425            left ^= work;
 6936426            right ^= work;
 6936427            left = (left << 1) | (left >> 31);
 428
 124848429            for (var round = 0; round < 8; round++)
 55488430            {
 55488431                work = (right << 28) | (right >> 4);
 55488432                work ^= (uint)wKey[(round * 4) + 0];
 55488433                var fval = Sp7[work & 0x3f];
 55488434                fval |= Sp5[(work >> 8) & 0x3f];
 55488435                fval |= Sp3[(work >> 16) & 0x3f];
 55488436                fval |= Sp1[(work >> 24) & 0x3f];
 55488437                work = right ^ (uint) wKey[(round * 4) + 1];
 55488438                fval |= Sp8[work & 0x3f];
 55488439                fval |= Sp6[(work >> 8) & 0x3f];
 55488440                fval |= Sp4[(work >> 16) & 0x3f];
 55488441                fval |= Sp2[(work >> 24) & 0x3f];
 55488442                left ^= fval;
 55488443                work = (left << 28) | (left >> 4);
 55488444                work ^= (uint)wKey[(round * 4) + 2];
 55488445                fval = Sp7[work & 0x3f];
 55488446                fval |= Sp5[(work >> 8) & 0x3f];
 55488447                fval |= Sp3[(work >> 16) & 0x3f];
 55488448                fval |= Sp1[(work >> 24) & 0x3f];
 55488449                work = left ^ (uint)wKey[(round * 4) + 3];
 55488450                fval |= Sp8[work & 0x3f];
 55488451                fval |= Sp6[(work >> 8) & 0x3f];
 55488452                fval |= Sp4[(work >> 16) & 0x3f];
 55488453                fval |= Sp2[(work >> 24) & 0x3f];
 55488454                right ^= fval;
 55488455            }
 456
 6936457            right = (right << 31) | (right >> 1);
 6936458            work = (left ^ right) & 0xaaaaaaaa;
 6936459            left ^= work;
 6936460            right ^= work;
 6936461            left = (left << 31) | (left >> 1);
 6936462            work = ((left >> 8) ^ right) & 0x00ff00ff;
 6936463            right ^= work;
 6936464            left ^= work << 8;
 6936465            work = ((left >> 2) ^ right) & 0x33333333;
 6936466            right ^= work;
 6936467            left ^= work << 2;
 6936468            work = ((right >> 16) ^ left) & 0x0000ffff;
 6936469            left ^= work;
 6936470            right ^= work << 16;
 6936471            work = ((right >> 4) ^ left) & 0x0f0f0f0f;
 6936472            left ^= work;
 6936473            right ^= work << 4;
 474
 6936475            Pack.UInt32ToBigEndian(right, outBytes, outOff);
 6936476            Pack.UInt32ToBigEndian(left, outBytes, outOff + 4);
 6936477        }
 478    }
 479}