< Summary

Information
Class: Renci.SshNet.Common.DerData
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Common\DerData.cs
Line coverage
62%
Covered lines: 136
Uncovered lines: 82
Coverable lines: 218
Total lines: 432
Line coverage: 62.3%
Branch coverage
52%
Covered branches: 24
Total branches: 46
Branch coverage: 52.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_IsEndOfData()100%1100%
.ctor()100%1100%
.ctor(...)100%2100%
Encode()100%1100%
ReadBigInteger()50%277.77%
ReadInteger()0%60%
ReadOctetString()50%277.77%
ReadBitString()50%277.77%
ReadObject()50%277.77%
Write(...)0%20%
Write(...)100%10%
Write(...)100%10%
Write(...)100%1100%
Write(...)100%8100%
Write(...)100%1100%
WriteBitstring(...)100%10%
WriteObjectIdentifier(...)100%10%
WriteNull()100%1100%
GetLength(...)16.66%622.22%
ReadLength()70%1073.91%
WriteBytes(...)100%1100%
ReadByte()50%266.66%
ReadBytes(...)50%277.77%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Common\DerData.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3
 4namespace Renci.SshNet.Common
 5{
 6    /// <summary>
 7    /// Base class for DER encoded data.
 8    /// </summary>
 9    public class DerData
 10    {
 11        private const byte Constructed = 0x20;
 12
 13        private const byte Boolean = 0x01;
 14        private const byte Integer = 0x02;
 15        private const byte BITSTRING = 0x03;
 16        private const byte Octetstring = 0x04;
 17        private const byte Null = 0x05;
 18        private const byte Objectidentifier = 0x06;
 19        private const byte Sequence = 0x10;
 20
 21        private readonly List<byte> _data;
 22        private readonly int _lastIndex;
 23        private int _readerIndex;
 24
 25        /// <summary>
 26        /// Gets a value indicating whether end of data is reached.
 27        /// </summary>
 28        /// <value>
 29        /// <see langword="true"/> if end of data is reached; otherwise, <see langword="false"/>.
 30        /// </value>
 31        public bool IsEndOfData
 32        {
 33            get
 449134            {
 449135                return _readerIndex >= _lastIndex;
 449136            }
 37        }
 38
 39        /// <summary>
 40        /// Initializes a new instance of the <see cref="DerData"/> class.
 41        /// </summary>
 381242        public DerData()
 381243        {
 381244            _data = new List<byte>();
 381245        }
 46
 47        /// <summary>
 48        /// Initializes a new instance of the <see cref="DerData"/> class.
 49        /// </summary>
 50        /// <param name="data">DER encoded data.</param>
 51        /// <param name="construct">its a construct.</param>
 55652        public DerData(byte[] data, bool construct = false)
 55653        {
 55654            _data = new List<byte>(data);
 55655            if (construct)
 3856            {
 3857                _lastIndex = _readerIndex + data.Length;
 3858            }
 59            else
 51860            {
 51861                _ = ReadByte(); // skip dataType
 51862                var length = ReadLength();
 51863                _lastIndex = _readerIndex + length;
 51864            }
 55665        }
 66
 67        /// <summary>
 68        /// Encodes written data as DER byte array.
 69        /// </summary>
 70        /// <returns>DER Encoded array.</returns>
 71        public byte[] Encode()
 381272        {
 381273            var length = _data.Count;
 381274            var lengthBytes = GetLength(length);
 75
 381276            _data.InsertRange(0, lengthBytes);
 381277            _data.Insert(0, Constructed | Sequence);
 78
 381279            return _data.ToArray();
 381280        }
 81
 82        /// <summary>
 83        /// Reads next mpint data type from internal buffer.
 84        /// </summary>
 85        /// <returns>mpint read.</returns>
 86        public BigInteger ReadBigInteger()
 451087        {
 451088            var type = ReadByte();
 451089            if (type != Integer)
 090            {
 091                throw new InvalidOperationException(string.Format("Invalid data type, INTEGER(02) is expected, but was {
 92            }
 93
 451094            var length = ReadLength();
 95
 451096            var data = ReadBytes(length);
 97
 451098            return new BigInteger(data.Reverse());
 451099        }
 100
 101        /// <summary>
 102        /// Reads next int data type from internal buffer.
 103        /// </summary>
 104        /// <returns>int read.</returns>
 105        public int ReadInteger()
 0106        {
 0107            var type = ReadByte();
 0108            if (type != Integer)
 0109            {
 0110                throw new InvalidOperationException(string.Format("Invalid data type, INTEGER(02) is expected, but was {
 111            }
 112
 0113            var length = ReadLength();
 114
 0115            var data = ReadBytes(length);
 116
 0117            if (length > 4)
 0118            {
 0119                throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes");
 120            }
 121
 0122            var result = 0;
 0123            var shift = (length - 1) * 8;
 0124            for (var i = 0; i < length; i++)
 0125            {
 0126                result |= data[i] << shift;
 0127                shift -= 8;
 0128            }
 129
 0130            return result;
 0131        }
 132
 133        /// <summary>
 134        /// Reads next octetstring data type from internal buffer.
 135        /// </summary>
 136        /// <returns>data read.</returns>
 137        public byte[] ReadOctetString()
 19138        {
 19139            var type = ReadByte();
 19140            if (type != Octetstring)
 0141            {
 0142                throw new InvalidOperationException(string.Format("Invalid data type, OCTETSTRING(04) is expected, but w
 143            }
 144
 19145            var length = ReadLength();
 19146            var data = ReadBytes(length);
 19147            return data;
 19148        }
 149
 150        /// <summary>
 151        /// Reads next bitstring data type from internal buffer.
 152        /// </summary>
 153        /// <returns>data read.</returns>
 154        public byte[] ReadBitString()
 19155        {
 19156            var type = ReadByte();
 19157            if (type != BITSTRING)
 0158            {
 0159                throw new InvalidOperationException(string.Format("Invalid data type, BITSTRING(03) is expected, but was
 160            }
 161
 19162            var length = ReadLength();
 19163            var data = ReadBytes(length);
 19164            return data;
 19165        }
 166
 167        /// <summary>
 168        /// Reads next object data type from internal buffer.
 169        /// </summary>
 170        /// <returns>data read.</returns>
 171        public byte[] ReadObject()
 19172        {
 19173            var type = ReadByte();
 19174            if (type != Objectidentifier)
 0175            {
 0176                throw new InvalidOperationException(string.Format("Invalid data type, OBJECT(06) is expected, but was {0
 177            }
 178
 19179            var length = ReadLength();
 19180            var data = ReadBytes(length);
 19181            return data;
 19182        }
 183
 184        /// <summary>
 185        /// Writes BOOLEAN data into internal buffer.
 186        /// </summary>
 187        /// <param name="data">UInt32 data to write.</param>
 188        public void Write(bool data)
 0189        {
 0190            _data.Add(Boolean);
 0191            _data.Add(1);
 0192            _data.Add((byte)(data ? 1 : 0));
 0193        }
 194
 195        /// <summary>
 196        /// Writes UInt32 data into internal buffer.
 197        /// </summary>
 198        /// <param name="data">UInt32 data to write.</param>
 199        public void Write(uint data)
 0200        {
 0201            var bytes = Pack.UInt32ToBigEndian(data);
 0202            _data.Add(Integer);
 0203            var length = GetLength(bytes.Length);
 0204            WriteBytes(length);
 0205            WriteBytes(bytes);
 0206        }
 207
 208        /// <summary>
 209        /// Writes INTEGER data into internal buffer.
 210        /// </summary>
 211        /// <param name="data">BigInteger data to write.</param>
 212        public void Write(BigInteger data)
 0213        {
 0214            var bytes = data.ToByteArray().Reverse();
 0215            _data.Add(Integer);
 0216            var length = GetLength(bytes.Length);
 0217            WriteBytes(length);
 0218            WriteBytes(bytes);
 0219        }
 220
 221        /// <summary>
 222        /// Writes OCTETSTRING data into internal buffer.
 223        /// </summary>
 224        /// <param name="data">The data.</param>
 225        public void Write(byte[] data)
 1906226        {
 1906227            _data.Add(Octetstring);
 1906228            var length = GetLength(data.Length);
 1906229            WriteBytes(length);
 1906230            WriteBytes(data);
 1906231        }
 232
 233        /// <summary>
 234        /// Writes OBJECTIDENTIFIER data into internal buffer.
 235        /// </summary>
 236        /// <param name="identifier">The identifier.</param>
 237        public void Write(ObjectIdentifier identifier)
 1906238        {
 1906239            var temp = new ulong[identifier.Identifiers.Length - 1];
 1906240            temp[0] = (identifier.Identifiers[0] * 40) + identifier.Identifiers[1];
 1906241            Buffer.BlockCopy(identifier.Identifiers, 2 * sizeof(ulong), temp, 1 * sizeof(ulong), (identifier.Identifiers
 1906242            var bytes = new List<byte>();
 36100243            foreach (var subidentifier in temp)
 15191244            {
 15191245                var item = subidentifier;
 15191246                var buffer = new byte[8];
 15191247                var bufferIndex = buffer.Length - 1;
 248
 15191249                var current = (byte)(item & 0x7F);
 250                do
 17078251                {
 17078252                    buffer[bufferIndex] = current;
 17078253                    if (bufferIndex < buffer.Length - 1)
 1887254                    {
 1887255                        buffer[bufferIndex] |= 0x80;
 1887256                    }
 257
 17078258                    item >>= 7;
 17078259                    current = (byte)(item & 0x7F);
 17078260                    bufferIndex--;
 17078261                }
 17078262                while (current > 0);
 263
 64538264                for (var i = bufferIndex + 1; i < buffer.Length; i++)
 17078265                {
 17078266                    bytes.Add(buffer[i]);
 17078267                }
 15191268            }
 269
 1906270            _data.Add(Objectidentifier);
 1906271            var length = GetLength(bytes.Count);
 1906272            WriteBytes(length);
 1906273            WriteBytes(bytes);
 1906274        }
 275
 276        /// <summary>
 277        /// Writes DerData data into internal buffer.
 278        /// </summary>
 279        /// <param name="data">DerData data to write.</param>
 280        public void Write(DerData data)
 1906281        {
 1906282            var bytes = data.Encode();
 1906283            _data.AddRange(bytes);
 1906284        }
 285
 286        /// <summary>
 287        /// Writes BITSTRING data into internal buffer.
 288        /// </summary>
 289        /// <param name="data">The data.</param>
 290        public void WriteBitstring(byte[] data)
 0291        {
 0292            _data.Add(BITSTRING);
 0293            var length = GetLength(data.Length);
 0294            WriteBytes(length);
 0295            WriteBytes(data);
 0296        }
 297
 298        /// <summary>
 299        /// Writes OBJECTIDENTIFIER data into internal buffer.
 300        /// </summary>
 301        /// <param name="bytes">The bytes.</param>
 302        public void WriteObjectIdentifier(byte[] bytes)
 0303        {
 0304            _data.Add(Objectidentifier);
 0305            var length = GetLength(bytes.Length);
 0306            WriteBytes(length);
 0307            WriteBytes(bytes);
 0308        }
 309
 310        /// <summary>
 311        /// Writes NULL data into internal buffer.
 312        /// </summary>
 313        public void WriteNull()
 1906314        {
 1906315            _data.Add(Null);
 1906316            _data.Add(0);
 1906317        }
 318
 319        private static byte[] GetLength(int length)
 7624320        {
 7624321            if (length > 127)
 0322            {
 0323                var size = 1;
 0324                var val = length;
 325
 0326                while ((val >>= 8) != 0)
 0327                {
 0328                    size++;
 0329                }
 330
 0331                var data = new byte[size];
 0332                data[0] = (byte)(size | 0x80);
 333
 0334                for (int i = (size - 1) * 8, j = 1; i >= 0; i -= 8, j++)
 0335                {
 0336                    data[j] = (byte)(length >> i);
 0337                }
 338
 0339                return data;
 340            }
 341
 7624342            return new[] { (byte) length };
 7624343        }
 344
 345        /// <summary>
 346        /// Gets Data Length.
 347        /// </summary>
 348        /// <returns>
 349        /// The length.
 350        /// </returns>
 351        public int ReadLength()
 5123352        {
 5123353            int length = ReadByte();
 354
 5123355            if (length == 0x80)
 0356            {
 0357                throw new NotSupportedException("Indefinite-length encoding is not supported.");
 358            }
 359
 5123360            if (length > 127)
 4001361            {
 4001362                var size = length & 0x7f;
 363
 364                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
 4001365                if (size > 4)
 0366                {
 0367                    throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 byt
 368                }
 369
 4001370                length = 0;
 18986371                for (var i = 0; i < size; i++)
 5492372                {
 5492373                    int next = ReadByte();
 374
 5492375                    length = (length << 8) + next;
 5492376                }
 377
 4001378                if (length < 0)
 0379                {
 0380                    throw new InvalidOperationException("Corrupted data - negative length found");
 381                }
 4001382            }
 383
 5123384            return length;
 5123385        }
 386
 387        /// <summary>
 388        /// Write Byte data into internal buffer.
 389        /// </summary>
 390        /// <param name="data">The data to write.</param>
 391        public void WriteBytes(IEnumerable<byte> data)
 7624392        {
 7624393            _data.AddRange(data);
 7624394        }
 395
 396        /// <summary>
 397        /// Reads Byte data into internal buffer.
 398        /// </summary>
 399        /// <returns>
 400        /// The data read.
 401        /// </returns>
 402        public byte ReadByte()
 15738403        {
 15738404            if (_readerIndex > _data.Count)
 0405            {
 0406                throw new InvalidOperationException("Read out of boundaries.");
 407            }
 408
 15738409            return _data[_readerIndex++];
 15738410        }
 411
 412        /// <summary>
 413        /// Reads lengths Bytes data into internal buffer.
 414        /// </summary>
 415        /// <returns>
 416        /// The data read.
 417        /// </returns>
 418        /// <param name="length">amount of data to read.</param>
 419        public byte[] ReadBytes(int length)
 4605420        {
 4605421            if (_readerIndex + length > _data.Count)
 0422            {
 0423                throw new InvalidOperationException("Read out of boundaries.");
 424            }
 425
 4605426            var result = new byte[length];
 4605427            _data.CopyTo(_readerIndex, result, 0, length);
 4605428            _readerIndex += length;
 4605429            return result;
 4605430        }
 431    }
 432}