VmpcRandomGenerator
using Org.BouncyCastle.Crypto.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Prng
{
public sealed class VmpcRandomGenerator : IRandomGenerator
{
private readonly byte[] P = new byte[256] {
187,
44,
98,
127,
181,
170,
212,
13,
129,
254,
178,
130,
203,
160,
161,
8,
24,
113,
86,
232,
73,
2,
16,
196,
222,
53,
165,
236,
128,
18,
184,
105,
218,
47,
117,
204,
162,
9,
54,
3,
97,
45,
253,
224,
221,
5,
67,
144,
173,
200,
225,
175,
87,
155,
76,
216,
81,
174,
80,
133,
60,
10,
228,
243,
156,
38,
35,
83,
201,
131,
151,
70,
177,
153,
100,
49,
119,
213,
29,
214,
120,
189,
94,
176,
138,
34,
56,
248,
104,
43,
42,
197,
211,
247,
188,
111,
223,
4,
229,
149,
62,
37,
134,
166,
11,
143,
241,
36,
14,
215,
64,
179,
207,
126,
6,
21,
154,
77,
28,
163,
219,
50,
146,
88,
17,
39,
244,
89,
208,
78,
106,
23,
91,
172,
byte.MaxValue,
7,
192,
101,
121,
252,
199,
205,
118,
66,
93,
231,
58,
52,
122,
48,
40,
15,
115,
1,
249,
209,
210,
25,
233,
145,
185,
90,
237,
65,
109,
180,
195,
158,
191,
99,
250,
31,
51,
96,
71,
137,
240,
150,
26,
95,
147,
61,
55,
75,
217,
168,
193,
27,
246,
57,
139,
183,
12,
32,
206,
136,
110,
182,
116,
142,
141,
22,
41,
242,
135,
245,
235,
112,
227,
251,
85,
159,
198,
68,
74,
69,
125,
226,
107,
92,
108,
102,
169,
140,
238,
132,
19,
167,
30,
157,
220,
103,
72,
186,
46,
230,
164,
171,
124,
148,
0,
33,
239,
234,
190,
202,
114,
79,
82,
152,
63,
194,
20,
123,
59,
84
};
private byte s = 190;
private byte n;
public void AddSeedMaterial(byte[] seed)
{
if (seed != null)
AddSeedMaterial(seed.AsSpan());
}
public void AddSeedMaterial(ReadOnlySpan<byte> seed)
{
for (int i = 0; i < seed.Length; i++) {
byte b = P[n];
s = P[(s + b + seed[i]) & 255];
P[n] = P[s];
P[s] = b;
n++;
}
}
public unsafe void AddSeedMaterial(long seed)
{
Span<byte> span = new Span<byte>(stackalloc byte[8], 8);
Pack.UInt64_To_BE((ulong)seed, span);
AddSeedMaterial(span);
}
public void NextBytes(byte[] bytes)
{
NextBytes(bytes, 0, bytes.Length);
}
public void NextBytes(byte[] bytes, int start, int len)
{
NextBytes(bytes.AsSpan(start, len));
}
public void NextBytes(Span<byte> bytes)
{
lock (P) {
for (int i = 0; i < bytes.Length; i++) {
byte b = P[n];
s = P[(s + b) & 255];
byte b2 = P[s];
bytes[i] = P[(P[b2] + 1) & 255];
P[s] = b;
P[n] = b2;
n++;
}
}
}
}
}