Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PfxEncoder.cs
1using System;
2using System.Collections.Generic;
3using System.Security.Cryptography;
4using System.Security.Cryptography.X509Certificates;
5using System.Text;
7
9{
13 public class PfxEncoder
14 {
15 private const string bagTypes = "1.2.840.113549.1.12.10.1";
16 private static readonly RandomNumberGenerator rnd = RandomNumberGenerator.Create();
17
18 private LinkedList<DerEncoder> stack = null;
19 private DerEncoder der = null;
20 private byte[] macSalt = null;
21
25 public PfxEncoder()
26 {
27 }
28
33 public static byte[] GetRandomBytes(int NrBytes)
34 {
35 byte[] Result = new byte[NrBytes];
36
37 lock (rnd)
38 {
39 rnd.GetBytes(Result);
40 }
41
42 return Result;
43 }
44
48 public void Begin()
49 {
50 this.der = new DerEncoder();
51 this.macSalt = GetRandomBytes(8);
52
53 this.der.StartSEQUENCE(); // PFX (RFC 7292, §4)
54 this.der.INTEGER(3); // version
55 }
56
57 private void Push()
58 {
59 if (this.stack is null)
60 this.stack = new LinkedList<DerEncoder>();
61
62 this.stack.AddLast(this.der);
63 this.der = new DerEncoder();
64 }
65
66 private byte[] Pop()
67 {
68 if (this.stack is null || this.stack.Last is null)
69 throw new InvalidOperationException("Stack empty.");
70
71 byte[] Result = this.der.ToArray();
72
73 this.der = this.stack.Last.Value;
74 this.stack.RemoveLast();
75
76 return Result;
77 }
78
82 public void StartSafeContent()
83 {
84 this.der.StartSEQUENCE(); // authSafe:ContentInfo, §4.1 RFC 7292
85 this.der.OBJECT_IDENTIFIER("1.2.840.113549.1.7.1"); // PKCS#7 data
86 this.der.StartContent(Asn1TypeClass.ContextSpecific);
87 }
88
92 public void EndSafeContent()
93 {
94 this.der.EndContent(Asn1TypeClass.ContextSpecific); // End of PKCS#7 data
95 this.der.EndSEQUENCE(); // End of authSafe:ContentInfo
96 }
97
102 {
103 this.der.StartSEQUENCE(); // EncryptedData, §13 RFC 2315 (PKCS#7)
104 this.der.INTEGER(0); // version
105
106 this.der.OBJECT_IDENTIFIER("1.2.840.113549.1.7.1"); // PKCS#7 data
107 this.der.StartContent(Asn1TypeClass.ContextSpecific);
108 }
109
114 {
115 this.der.EndContent(Asn1TypeClass.ContextSpecific); // End of PKCS#7 data
116 this.der.EndSEQUENCE(); // End of authSafe:ContentInfo
117 }
118
123 public byte[] End()
124 {
125 this.AssertBegun();
126
127 if (!(this.stack is null) && !(this.stack.First is null))
128 throw new InvalidOperationException("Stack not empty.");
129
130 this.der.StartSEQUENCE(); // macData:MacData
131 this.der.StartSEQUENCE(); // mac:DigestInfo
132 // TODO
133 this.der.EndSEQUENCE(); // End of mac:DigestInfo
134
135 this.der.OCTET_STRING(this.macSalt); // macSalt
136 this.der.INTEGER(2048); // iterations
137 this.der.EndSEQUENCE(); // End of macData:MacData
138 this.der.EndSEQUENCE();
139
140 byte[] Result = this.der.ToArray();
141 this.der = null;
142
143 return Result;
144 }
145
146 private void AssertBegun()
147 {
148 if (this.der is null)
149 throw new InvalidOperationException("Encoding not begun.");
150 }
151
155 public void StartBagSet()
156 {
157 this.AssertBegun();
158 this.der.StartSEQUENCE();
159 }
160
164 public void EndBagSet()
165 {
166 this.AssertBegun();
167 this.der.EndSEQUENCE();
168 }
169
170 private void StartSafeBag(string OID)
171 {
172 this.AssertBegun();
173
174 this.der.StartSEQUENCE(); // SafeBag
175 this.der.OBJECT_IDENTIFIER(OID);
176 this.der.StartContent(Asn1TypeClass.ContextSpecific);
177 }
178
179 private void EndSafeBag()
180 {
181 this.der.EndContent(Asn1TypeClass.ContextSpecific);
182 // TODO: Attributes
183 this.der.EndSEQUENCE();
184 }
185
190 public void KeyBag(SignatureAlgorithm Algorithm)
191 {
192 this.StartSafeBag(bagTypes + ".1");
193 EncodePrivateKeyInfo(this.der, Algorithm);
194 this.EndSafeBag();
195 }
196
197 private static void EncodePrivateKeyInfo(DerEncoder Der, SignatureAlgorithm Algorithm)
198 {
199 Der.StartSEQUENCE(); // PrivateKeyInfo
200 Der.INTEGER(0); // version
201 Der.OBJECT_IDENTIFIER(Algorithm.PkiAlgorithmOID); // privateKeyAlgorithm
202 Der.StartOCTET_STRING();
203 Algorithm.ExportPrivateKey(Der); // privateKey
204 Der.EndOCTET_STRING();
205 Der.NULL(); // Attributes
206 Der.EndSEQUENCE(); // End of PrivateKeyInfo
207 }
208
214 public void ShroudedKeyBag(string Password, SignatureAlgorithm Algorithm)
215 {
216 this.ShroudedKeyBag(new PbeWithShaAnd3KeyTripleDesCbc(Password, 4096), Algorithm);
217 }
218
224 public void ShroudedKeyBag(PasswordEncryption Encryption, SignatureAlgorithm Algorithm)
225 {
226 this.StartSafeBag(bagTypes + ".2");
227
228 DerEncoder Key = new DerEncoder();
229 EncodePrivateKeyInfo(Key, Algorithm);
230 byte[] PrivateKey = Key.ToArray();
231
232 this.der.StartSEQUENCE(); // EncryptedPrivateKeyInfo
233 Encryption.EncodePkcs5AlgorithmIdentifier(this.der);
234 this.der.OCTET_STRING(Encryption.Encrypt(PrivateKey));
235 this.der.NULL(); // Attributes
236
237 this.der.EndSEQUENCE(); // End of EncryptedPrivateKeyInfo
238
239 this.EndSafeBag(); // TODO: attributes
240 }
241
247 internal static byte[] FormatPassword(string Password)
248 {
249 return Primitives.CONCAT(Encoding.BigEndianUnicode.GetBytes(Password), new byte[] { 0, 0 });
250 }
251
271 internal static byte[] PRF(HashFunction H, int r, byte[] P, byte[] S, int n, byte ID)
272 {
273 int u, v;
274
275 if ((n & 7) != 0)
276 throw new ArgumentException("Must be a factor of 8.", nameof(n));
277
278 switch (H)
279 {
280 case HashFunction.MD5:
281 u = 128;
282 v = 512;
283 break;
284
285 case HashFunction.SHA1:
286 u = 160;
287 v = 512;
288 break;
289
290 case HashFunction.SHA256:
291 u = 256;
292 v = 512;
293 break;
294
295 case HashFunction.SHA384:
296 u = 384;
297 v = 1024;
298 break;
299
300 case HashFunction.SHA512:
301 u = 512;
302 v = 1024;
303 break;
304
305 default:
306 throw new ArgumentException("Hash function not supported.", nameof(H));
307 }
308
309 int v8 = v / 8;
310 int u8 = u / 8;
311
312 byte[] D = new byte[v8];
313 int i, j, c;
314
315 for (i = 0; i < v8; i++)
316 D[i] = ID;
317
318 S = Extend(S, v);
319 P = Extend(P, v);
320
321 byte[] I = Primitives.CONCAT(S, P);
322 int i8 = I.Length;
323
324 c = (n + u - 1) / u;
325
326 byte[][] As = new byte[c][];
327
328 for (i = 0; i < c; i++)
329 {
330 As[i] = Primitives.CONCAT(D, I);
331
332 for (j = 0; j < r; j++)
333 As[i] = Hashes.ComputeHash(H, As[i]);
334
335 byte[] B = Extend(As[i], v);
336
337 for (j = 0; j < i8; j += v8)
338 AddTo(I, j, B, true);
339 }
340
341 byte[] A = Primitives.CONCAT(As);
342
343 if (A.Length != n)
344 Array.Resize(ref A, n);
345
346 return A;
347 }
348
349 private static void AddTo(byte[] Dest, int Offset, byte[] Term, bool Carry)
350 {
351 int i = Term.Length;
352 bool Carry2;
353 byte b, b2;
354
355 Offset += i;
356
357 while (--i >= 0)
358 {
359 b = Dest[--Offset];
360 b2 = b = Term[i];
361 b += b2;
362 Carry2 = b < b2;
363 if (Carry)
364 {
365 b++;
366 Carry2 |= b == 0;
367 }
368 Dest[Offset] = b;
369 Carry = Carry2;
370 }
371 }
372
373 private static byte[] Extend(byte[] Bin, int v)
374 {
375 int Len = Bin.Length;
376 int c = (v / 8) * ((Len + v - 1) / v);
377 byte[] Result = new byte[c];
378 int i, j;
379
380 for (i = 0; i < c; i += Len)
381 {
382 j = c - i;
383 if (j < Len)
384 Array.Copy(Bin, 0, Result, i, j);
385 else
386 Array.Copy(Bin, 0, Result, i, Len);
387 }
388
389 return Result;
390 }
391
396 public void CertificateBag(X509Certificate2 Certificate)
397 {
398 this.StartSafeBag(bagTypes + ".3");
399 this.der.StartSEQUENCE(); // CertBag
400 this.der.OBJECT_IDENTIFIER("1.2.840.113549.1.9.22.1"); // x509Certificate
401 this.der.OCTET_STRING(Certificate.Export(X509ContentType.Pkcs7));
402 this.der.EndSEQUENCE(); // End of CertBag
403 this.EndSafeBag();
404 }
405
406 /*/// <summary>
409 public void CrlBag()
410 {
411 this.StartSafeBag(bagTypes + ".4");
412 }*/
413
414 /*public void SecretBag()
415 {
416 this.StartSafeBag(bagTypes + ".5");
417 }*/
418
419 /*public void StartContentsBag()
420 {
421 this.StartSafeBag(bagTypes + ".6");
422 }
423
424 public void EndContentsBag()
425 {
426 this.EndSafeBag();
427 }*/
428
429 }
430}
Contains methods for simple hash calculations.
Definition: Hashes.cs:59
static byte[] ComputeHash(HashFunction Function, byte[] Data)
Computes a hash of a block of binary data.
Definition: Hashes.cs:214
Encodes data using the Distinguished Encoding Rules (DER), as defined in X.690
Definition: DerEncoder.cs:40
byte[] ToArray()
Converts the generated output to a byte arary.
Definition: DerEncoder.cs:72
void StartOCTET_STRING()
Starts a OCTET_STRING.
Definition: DerEncoder.cs:317
void EndSEQUENCE()
Ends the current SEQUENCE.
Definition: DerEncoder.cs:483
void EndContent(Asn1TypeClass Class)
Ends the current Content section.
Definition: DerEncoder.cs:545
void OBJECT_IDENTIFIER(string OID)
Encodes an OBJECT IDENTIFIER value.
Definition: DerEncoder.cs:343
void NULL()
Encodes an NULL value.
Definition: DerEncoder.cs:333
void EndOCTET_STRING()
Ends the current OCTET_STRING.
Definition: DerEncoder.cs:325
void StartContent(Asn1TypeClass Class)
Starts a content section.
Definition: DerEncoder.cs:536
void INTEGER(long Value)
Encodes an INTEGER value.
Definition: DerEncoder.cs:99
void StartSEQUENCE()
Starts a SEQUENCE.
Definition: DerEncoder.cs:465
void OCTET_STRING(byte[] Value)
Encodes an OCTET STRING value.
Definition: DerEncoder.cs:308
Abstract base class for password-based encryption algorithms
abstract void EncodePkcs5AlgorithmIdentifier(DerEncoder Der)
Encodes the AlgorithmIdentifier, as defined in PKCS#5 (RFC 2898).
abstract byte[] Encrypt(byte[] PlainText)
Encrypts data.
Encodes certificates and keys into PKCS#12 or PFX files.
Definition: PfxEncoder.cs:14
void ShroudedKeyBag(PasswordEncryption Encryption, SignatureAlgorithm Algorithm)
Encodes a ShroudedKeyBag (§4.2.2 RFC 7292, §6, RFC 5208)
Definition: PfxEncoder.cs:224
void StartSafeContent()
Starts a block of safe content, in accordance with §5 of RFC 7292.
Definition: PfxEncoder.cs:82
void Begin()
Begins PKCS#12 encoding.
Definition: PfxEncoder.cs:48
static byte[] GetRandomBytes(int NrBytes)
Gets a number of random bytes.
Definition: PfxEncoder.cs:33
void CertificateBag(X509Certificate2 Certificate)
Encodes a CertBag (§4.2.3 RFC 7292, §6, RFC 5208)
Definition: PfxEncoder.cs:396
void ShroudedKeyBag(string Password, SignatureAlgorithm Algorithm)
Encodes a ShroudedKeyBag (§4.2.2 RFC 7292, §6, RFC 5208)
Definition: PfxEncoder.cs:214
void KeyBag(SignatureAlgorithm Algorithm)
Encodes a KeyBag (§4.2.1 RFC 7292, §5, RFC 5208)
Definition: PfxEncoder.cs:190
void EndSafeContent()
Ends a block of safe content, in accordance with §5 of RFC 7292.
Definition: PfxEncoder.cs:92
byte[] End()
Ends PKCS#12 encoding and returns the encoded result.
Definition: PfxEncoder.cs:123
void StartEncryptedSafeContent()
Starts a block of encrypted safe content, in accordance with §5 of RFC 7292.
Definition: PfxEncoder.cs:101
void EndBagSet()
Ends a PKCS12BagSet
Definition: PfxEncoder.cs:164
void StartBagSet()
Starts a PKCS12BagSet
Definition: PfxEncoder.cs:155
PfxEncoder()
Encodes certificates and keys into PKCS#12 or PFX files.
Definition: PfxEncoder.cs:25
void EndEncryptedSafeContent()
Ends a block of encrypted safe content, in accordance with §5 of RFC 7292.
Definition: PfxEncoder.cs:113
Contains static functions used by different algorithms.
Definition: Primitives.cs:11
static byte[] CONCAT(params byte[][] OctetStrings)
Concatenates a series of octet strings.
Definition: Primitives.cs:17
Abstract base class for signature algorithms
abstract string PkiAlgorithmOID
Object Identity for the PKI algorithm.
abstract void ExportPrivateKey(DerEncoder Output)
Exports the private key using DER.
Asn1TypeClass
Type class
Definition: DerEncoder.cs:14
HashFunction
Hash method enumeration.
Definition: Hashes.cs:28