DerData.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace Renci.SshNet.Common
  6. {
  7. /// <summary>
  8. /// Base class for DER encoded data.
  9. /// </summary>
  10. public class DerData
  11. {
  12. private const byte CONSTRUCTED = 0x20;
  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 EXTERNAL = 0x08;
  20. private const byte ENUMERATED = 0x0a;
  21. private const byte SEQUENCE = 0x10;
  22. private const byte SEQUENCEOF = 0x10; // for completeness
  23. private const byte SET = 0x11;
  24. private const byte SETOF = 0x11; // for completeness
  25. private const byte NUMERICSTRING = 0x12;
  26. private const byte PRINTABLESTRING = 0x13;
  27. private const byte T61STRING = 0x14;
  28. private const byte VIDEOTEXSTRING = 0x15;
  29. private const byte IA5STRING = 0x16;
  30. private const byte UTCTIME = 0x17;
  31. private const byte GENERALIZEDTIME = 0x18;
  32. private const byte GRAPHICSTRING = 0x19;
  33. private const byte VISIBLESTRING = 0x1a;
  34. private const byte GENERALSTRING = 0x1b;
  35. private const byte UNIVERSALSTRING = 0x1c;
  36. private const byte BMPSTRING = 0x1e;
  37. private const byte UTF8STRING = 0x0c;
  38. private const byte APPLICATION = 0x40;
  39. private const byte TAGGED = 0x80;
  40. private List<byte> _data;
  41. private int _readerIndex = 0;
  42. private int _lastIndex;
  43. /// <summary>
  44. /// Gets a value indicating whether end of data is reached.
  45. /// </summary>
  46. /// <value>
  47. /// <c>true</c> if end of data is reached; otherwise, <c>false</c>.
  48. /// </value>
  49. public bool IsEndOfData
  50. {
  51. get
  52. {
  53. return this._readerIndex >= this._lastIndex;
  54. }
  55. }
  56. /// <summary>
  57. /// Initializes a new instance of the <see cref="DerData"/> class.
  58. /// </summary>
  59. public DerData()
  60. {
  61. this._data = new List<byte>();
  62. }
  63. /// <summary>
  64. /// Initializes a new instance of the <see cref="DerData"/> class.
  65. /// </summary>
  66. /// <param name="data">DER encoded data.</param>
  67. public DerData(byte[] data)
  68. {
  69. this._data = new List<byte>(data);
  70. var dataType = this.ReadByte();
  71. var length = this.ReadLength();
  72. this._lastIndex = this._readerIndex + length;
  73. }
  74. /// <summary>
  75. /// Encodes written data as DER byte array.
  76. /// </summary>
  77. /// <returns></returns>
  78. public byte[] Encode()
  79. {
  80. var length = this._data.Count();
  81. var lengthBytes = this.GetLength(length);
  82. this._data.InsertRange(0, lengthBytes);
  83. this._data.Insert(0, CONSTRUCTED | SEQUENCE);
  84. return this._data.ToArray();
  85. }
  86. /// <summary>
  87. /// Reads next mpint data type from internal buffer.
  88. /// </summary>
  89. /// <returns>mpint read.</returns>
  90. public BigInteger ReadBigInteger()
  91. {
  92. var type = this.ReadByte();
  93. if (type != INTEGER)
  94. throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
  95. var length = this.ReadLength();
  96. var data = this.ReadBytes(length);
  97. return new BigInteger(data.Reverse().ToArray());
  98. }
  99. /// <summary>
  100. /// Reads next int data type from internal buffer.
  101. /// </summary>
  102. /// <returns>int read.</returns>
  103. public int ReadInteger()
  104. {
  105. var type = this.ReadByte();
  106. if (type != INTEGER)
  107. throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
  108. var length = this.ReadLength();
  109. var data = this.ReadBytes(length);
  110. if (length > 4)
  111. throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes");
  112. var result = 0;
  113. var shift = (length - 1) * 8;
  114. for (int i = 0; i < length; i++)
  115. {
  116. result |= data[i] << shift;
  117. shift -= 8;
  118. }
  119. //return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
  120. return result;
  121. }
  122. /// <summary>
  123. /// Writes UInt32 data into internal buffer.
  124. /// </summary>
  125. /// <param name="data">UInt32 data to write.</param>
  126. public void Write(UInt32 data)
  127. {
  128. var bytes = data.GetBytes();
  129. this._data.Add(INTEGER);
  130. var length = this.GetLength(bytes.Length);
  131. this.WriteBytes(length);
  132. this.WriteBytes(bytes);
  133. }
  134. /// <summary>
  135. /// Writes BigInteger data into internal buffer.
  136. /// </summary>
  137. /// <param name="data">BigInteger data to write.</param>
  138. public void Write(BigInteger data)
  139. {
  140. var bytes = data.ToByteArray().Reverse().ToList();
  141. this._data.Add(INTEGER);
  142. var length = this.GetLength(bytes.Count);
  143. this.WriteBytes(length);
  144. this.WriteBytes(bytes);
  145. }
  146. /// <summary>
  147. /// Writes DerData data into internal buffer.
  148. /// </summary>
  149. /// <param name="data">DerData data to write.</param>
  150. public void Write(DerData data)
  151. {
  152. throw new NotImplementedException();
  153. }
  154. private byte[] GetLength(int length)
  155. {
  156. if (length > 127)
  157. {
  158. int size = 1;
  159. int val = length;
  160. while ((val >>= 8) != 0)
  161. size++;
  162. var data = new byte[size];
  163. data[0] = (byte)(size | 0x80);
  164. for (int i = (size - 1) * 8, j = 1; i >= 0; i -= 8, j++)
  165. {
  166. data[j] = (byte)(length >> i);
  167. }
  168. return data;
  169. }
  170. else
  171. {
  172. return new byte[] { (byte)length };
  173. }
  174. }
  175. private int ReadLength()
  176. {
  177. int length = this.ReadByte();
  178. if (length == 0x80)
  179. {
  180. throw new NotSupportedException("Indefinite-length encoding is not supported.");
  181. }
  182. if (length > 127)
  183. {
  184. int size = length & 0x7f;
  185. // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
  186. if (size > 4)
  187. throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 bytes.", size));
  188. length = 0;
  189. for (int i = 0; i < size; i++)
  190. {
  191. int next = this.ReadByte();
  192. length = (length << 8) + next;
  193. }
  194. if (length < 0)
  195. throw new InvalidOperationException("Corrupted data - negative length found");
  196. //if (length >= limit) // after all we must have read at least 1 byte
  197. // throw new IOException("Corrupted stream - out of bounds length found");
  198. }
  199. return length;
  200. }
  201. private void WriteBytes(IEnumerable<byte> data)
  202. {
  203. this._data.AddRange(data);
  204. }
  205. private byte ReadByte()
  206. {
  207. if (this._readerIndex > this._data.Count)
  208. throw new InvalidOperationException("Read out of boundaries.");
  209. return this._data[this._readerIndex++];
  210. }
  211. private byte[] ReadBytes(int length)
  212. {
  213. if (this._readerIndex + length > this._data.Count)
  214. throw new InvalidOperationException("Read out of boundaries.");
  215. var result = new byte[length];
  216. this._data.CopyTo(this._readerIndex, result, 0, length);
  217. this._readerIndex += length;
  218. return result;
  219. }
  220. }
  221. }