Move PBKDF2 to new module, add some new Interop methods
[NovacoinLibrary.git] / Novacoin / Interop.cs
1 \feffusing System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace Novacoin
7 {
8     public class InteropException : Exception
9     {
10         public InteropException()
11         {
12         }
13
14         public InteropException(string message)
15             : base(message)
16         {
17         }
18
19         public InteropException(string message, Exception inner)
20             : base(message, inner)
21         {
22         }
23     }
24
25     public class Interop
26     {
27         public static byte[] ReverseIfLE(byte[] source)
28         {
29             if (BitConverter.IsLittleEndian)
30             {
31                 Array.Reverse(source);
32             }
33
34             return source;
35         }
36
37         public static byte[] LEBytes(uint[] values)
38         {
39             if (BitConverter.IsLittleEndian)
40             {
41                 byte[] result = new byte[values.Length * sizeof(uint)];
42                 Buffer.BlockCopy(values, 0, result, 0, result.Length);
43
44                 return result;
45             }
46             else
47             {
48                 List<byte> result = new List<byte>();
49
50                 foreach (uint i in values)
51                 {
52                     result.AddRange(LEBytes(i));
53                 }
54
55                 return result.ToArray();
56             }
57         }
58
59         public static uint[] ToUInt32Array(byte[] bytes)
60         {
61             if (BitConverter.IsLittleEndian)
62             {
63                 uint[] result = new uint[bytes.Length / sizeof(uint)];
64                 Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);
65
66                 return result;
67             }
68             else
69             {
70                 List<uint> result = new List<uint>();
71
72                 for (int i = 0; i < bytes.Length; i += 4)
73                 {
74                     result.Add(LEBytesToUInt32(bytes.Skip(i).Take(4).ToArray()));
75                 }
76
77                 return result.ToArray();
78             }
79         }
80
81         public static byte[] LEBytes(ushort n)
82         {
83             byte[] resultBytes = BitConverter.GetBytes(n);
84
85             if (!BitConverter.IsLittleEndian)
86             {
87                 // Reverse array if we are on big-endian machine
88                 Array.Reverse(resultBytes);
89             }
90
91             return resultBytes;
92         }
93
94         public static byte[] LEBytes(uint n)
95         {
96             byte[] resultBytes = BitConverter.GetBytes(n);
97
98             if (!BitConverter.IsLittleEndian)
99             {
100                 // Reverse array if we are on big-endian machine
101                 Array.Reverse(resultBytes);
102             }
103
104             return resultBytes;
105         }
106
107         public static byte[] LEBytes(ulong n)
108         {
109             byte[] resultBytes = BitConverter.GetBytes(n);
110
111             if (!BitConverter.IsLittleEndian)
112             {
113                 // Reverse array if we are on big-endian machine
114                 Array.Reverse(resultBytes);
115             }
116
117             return resultBytes;
118         }
119
120         public static byte[] BEBytes(ushort n)
121         {
122             byte[] resultBytes = BitConverter.GetBytes(n);
123
124             if (BitConverter.IsLittleEndian)
125             {
126                 // Reverse array if we are on little-endian machine
127                 Array.Reverse(resultBytes);
128             }
129
130             return resultBytes;
131         }
132
133         public static byte[] BEBytes(uint n)
134         {
135             byte[] resultBytes = BitConverter.GetBytes(n);
136
137             if (BitConverter.IsLittleEndian)
138             {
139                 // Reverse array if we are on little-endian machine
140                 Array.Reverse(resultBytes);
141             }
142
143             return resultBytes;
144         }
145
146         public static byte[] BEBytes(ulong n)
147         {
148             byte[] resultBytes = BitConverter.GetBytes(n);
149
150             if (BitConverter.IsLittleEndian)
151             {
152                 // Reverse array if we are on little-endian machine
153                 Array.Reverse(resultBytes);
154             }
155
156             return resultBytes;
157         }
158
159         public static ushort LEBytesToUInt16(byte[] bytes)
160         {
161             if (bytes.Length != sizeof(ushort))
162             {
163                 throw new InteropException("Array size doesn't match the ushort data type.");
164             }
165
166             if (!BitConverter.IsLittleEndian)
167             {
168                 // Reverse array if we are on big-endian machine
169                 Array.Reverse(bytes);
170             }
171
172             return BitConverter.ToUInt16(bytes, 0);
173         }
174
175         public static uint LEBytesToUInt32(byte[] bytes)
176         {
177             if (bytes.Length != sizeof(uint))
178             {
179                 throw new InteropException("Array size doesn't match the uint data type.");
180             }
181
182             if (!BitConverter.IsLittleEndian)
183             {
184                 // Reverse array if we are on big-endian machine
185                 Array.Reverse(bytes);
186             }
187
188             return BitConverter.ToUInt32(bytes, 0);
189         }
190
191         public static ulong LEBytesToUInt64(byte[] bytes)
192         {
193             if (bytes.Length != sizeof(ulong))
194             {
195                 throw new InteropException("Array size doesn't match the ulong data type.");
196             }
197
198             if (!BitConverter.IsLittleEndian)
199             {
200                 // Reverse array if we are on big-endian machine
201                 Array.Reverse(bytes);
202             }
203
204             return BitConverter.ToUInt64(bytes, 0);
205         }
206
207         public static ushort BEBytesToUInt16(byte[] bytes)
208         {
209             if (bytes.Length != sizeof(ushort))
210             {
211                 throw new InteropException("Array size doesn't match the ushort data type.");
212             }
213
214             if (BitConverter.IsLittleEndian)
215             {
216                 // Reverse array if we are on little-endian machine
217                 Array.Reverse(bytes);
218             }
219
220             return BitConverter.ToUInt16(bytes, 0);
221         }
222
223         public static uint BEBytesToUInt32(byte[] bytes)
224         {
225             if (bytes.Length != sizeof(uint))
226             {
227                 throw new InteropException("Array size doesn't match the uint data type.");
228             }
229
230             if (BitConverter.IsLittleEndian)
231             {
232                 // Reverse array if we are on little-endian machine
233                 Array.Reverse(bytes);
234             }
235
236             return BitConverter.ToUInt32(bytes, 0);
237         }
238
239         public static ulong BEBytesToUInt64(byte[] bytes)
240         {
241             if (bytes.Length != sizeof(ulong))
242             {
243                 throw new InteropException("Array size doesn't match the ulong data type.");
244             }
245
246             if (BitConverter.IsLittleEndian)
247             {
248                 // Reverse array if we are on little-endian machine
249                 Array.Reverse(bytes);
250             }
251
252             return BitConverter.ToUInt64(bytes, 0);
253         }
254
255         public static IEnumerable<byte> ParseHex(string hex)
256         {
257             return Enumerable.Range(0, hex.Length)
258                              .Where(x => x % 2 == 0)
259                              .Select(x => Convert.ToByte(hex.Substring(x, 2), 16));
260         }
261
262         public static string ToHex(IEnumerable<byte> bytes)
263         {
264             StringBuilder sb = new StringBuilder();
265             foreach (byte b in bytes)
266             {
267                 sb.AppendFormat("{0:x2}", b);
268             }
269             return sb.ToString();
270         }
271
272         public static void UInt16ToBE(ushort n, byte[] bs)
273         {
274             bs[0] = (byte)(n >> 8);
275             bs[1] = (byte)(n);
276         }
277
278         public static ushort BEToUInt16(byte[] bs)
279         {
280             ushort n = (ushort)(bs[0] << 8);
281             n |= (ushort)bs[1];
282             return n;
283         }
284
285         public static ushort BEToUInt16(byte[] bs, int off)
286         {
287             ushort n = (ushort)(bs[off] << 8);
288             n |= (ushort)bs[++off];
289             return n;
290         }
291
292         public static void UInt16ToLE(ushort n, byte[] bs)
293         {
294             bs[0] = (byte)(n);
295             bs[1] = (byte)(n >> 8);
296         }
297
298         public static void UInt16ToLE(ushort n, byte[] bs, int off)
299         {
300             bs[off] = (byte)(n);
301             bs[++off] = (byte)(n >> 8);
302         }
303
304         public static ushort LEToUInt16(byte[] bs)
305         {
306             ushort n = (ushort)bs[0];
307             n |= (ushort)(bs[1] << 8);
308             return n;
309         }
310
311         public static ushort LEToUInt16(byte[] bs, int off)
312         {
313             ushort n = (ushort)bs[off];
314             n |= (ushort)(bs[++off] << 8);
315             return n;
316         }
317
318         public static void UInt32ToBE(uint n, byte[] bs)
319         {
320             bs[0] = (byte)(n >> 24);
321             bs[1] = (byte)(n >> 16);
322             bs[2] = (byte)(n >> 8);
323             bs[3] = (byte)(n);
324         }
325
326         public static void UInt32ToBE(uint n, byte[] bs, int off)
327         {
328             bs[off] = (byte)(n >> 24);
329             bs[++off] = (byte)(n >> 16);
330             bs[++off] = (byte)(n >> 8);
331             bs[++off] = (byte)(n);
332         }
333
334         public static uint BEToUInt32(byte[] bs)
335         {
336             uint n = (uint)bs[0] << 24;
337             n |= (uint)bs[1] << 16;
338             n |= (uint)bs[2] << 8;
339             n |= (uint)bs[3];
340             return n;
341         }
342
343         public static uint BEToUInt32(byte[] bs, int off)
344         {
345             uint n = (uint)bs[off] << 24;
346             n |= (uint)bs[++off] << 16;
347             n |= (uint)bs[++off] << 8;
348             n |= (uint)bs[++off];
349             return n;
350         }
351
352         public static ulong BEToUInt64(byte[] bs)
353         {
354             uint hi = BEToUInt32(bs);
355             uint lo = BEToUInt32(bs, 4);
356             return ((ulong)hi << 32) | (ulong)lo;
357         }
358
359         public static ulong BEToUInt64(byte[] bs, int off)
360         {
361             uint hi = BEToUInt32(bs, off);
362             uint lo = BEToUInt32(bs, off + 4);
363             return ((ulong)hi << 32) | (ulong)lo;
364         }
365
366         public static void UInt64ToBE(ulong n, byte[] bs)
367         {
368             UInt32ToBE((uint)(n >> 32), bs);
369             UInt32ToBE((uint)(n), bs, 4);
370         }
371
372         public static void UInt64ToBE(ulong n, byte[] bs, int off)
373         {
374             UInt32ToBE((uint)(n >> 32), bs, off);
375             UInt32ToBE((uint)(n), bs, off + 4);
376         }
377
378         public static void UInt32ToLE(uint n, byte[] bs)
379         {
380             bs[0] = (byte)(n);
381             bs[1] = (byte)(n >> 8);
382             bs[2] = (byte)(n >> 16);
383             bs[3] = (byte)(n >> 24);
384         }
385
386         public static void UInt32ToLE(uint n, byte[] bs, int off)
387         {
388             bs[off] = (byte)(n);
389             bs[++off] = (byte)(n >> 8);
390             bs[++off] = (byte)(n >> 16);
391             bs[++off] = (byte)(n >> 24);
392         }
393
394         public static uint LEToUInt32(byte[] bs)
395         {
396             uint n = (uint)bs[0];
397             n |= (uint)bs[1] << 8;
398             n |= (uint)bs[2] << 16;
399             n |= (uint)bs[3] << 24;
400             return n;
401         }
402
403         public static uint LEToUInt32(byte[] bs, int off)
404         {
405             uint n = (uint)bs[off];
406             n |= (uint)bs[++off] << 8;
407             n |= (uint)bs[++off] << 16;
408             n |= (uint)bs[++off] << 24;
409             return n;
410         }
411
412         public static ulong LEToUInt64(byte[] bs)
413         {
414             uint lo = LEToUInt32(bs);
415             uint hi = LEToUInt32(bs, 4);
416             return ((ulong)hi << 32) | (ulong)lo;
417         }
418
419         public static ulong LEToUInt64(byte[] bs, int off)
420         {
421             uint lo = LEToUInt32(bs, off);
422             uint hi = LEToUInt32(bs, off + 4);
423             return ((ulong)hi << 32) | (ulong)lo;
424         }
425
426         public static void UInt64ToLE(ulong n, byte[] bs)
427         {
428             UInt32ToLE((uint)(n), bs);
429             UInt32ToLE((uint)(n >> 32), bs, 4);
430         }
431
432         public static void UInt64ToLE(ulong n, byte[] bs, int off)
433         {
434             UInt32ToLE((uint)(n), bs, off);
435             UInt32ToLE((uint)(n >> 32), bs, off + 4);
436         }
437
438     }
439 }