summary refs log tree commit diff
path: root/crypto/src/openssl/Pkcs8Generator.cs
blob: d03ea08d223ace2d678349e8c730b139490a5c53 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using System;
using System.Collections;
using System.IO;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO.Pem;

namespace Org.BouncyCastle.OpenSsl
{
	public class Pkcs8Generator
		: PemObjectGenerator
	{
		// FIXME See PbeUtilities static constructor
//		public static readonly string Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc.Id;
//		public static readonly string Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc.Id;
//		public static readonly string Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc.Id;
//
//		public static readonly string Des3Cbc = PkcsObjectIdentifiers.DesEde3Cbc.Id;

		public static readonly string PbeSha1_RC4_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id;
		public static readonly string PbeSha1_RC4_40 = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id;
		public static readonly string PbeSha1_3DES = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id;
		public static readonly string PbeSha1_2DES = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id;
		public static readonly string PbeSha1_RC2_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id;
		public static readonly string PbeSha1_RC2_40 = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id;

		private char[]					password;
		private string					algorithm;
		private int						iterationCount;
		private AsymmetricKeyParameter	privKey;
		private SecureRandom			random;

		/**
		* Constructor for an unencrypted private key PEM object.
		*
		* @param key private key to be encoded.
		*/
		public Pkcs8Generator(AsymmetricKeyParameter privKey)
		{
			this.privKey = privKey;
		}

		/**
		* Constructor for an encrypted private key PEM object.
		*
		* @param key       private key to be encoded
		* @param algorithm encryption algorithm to use
		* @param provider  provider to use
		* @throws NoSuchAlgorithmException if algorithm/mode cannot be found
		*/
		public Pkcs8Generator(AsymmetricKeyParameter privKey, string algorithm)
		{
			// TODO Check privKey.IsPrivate
			this.privKey = privKey;
			this.algorithm = algorithm;
			this.iterationCount = 2048;
		}

		public SecureRandom SecureRandom
		{
			set { this.random = value; }
		}

		public char[] Password
		{
			set { this.password = value; }
		}

		public int IterationCount
		{
			set { this.iterationCount = value; }
		}

		public PemObject Generate()
		{
			if (algorithm == null)
			{
				PrivateKeyInfo pki = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privKey);

				return new PemObject("PRIVATE KEY", pki.GetEncoded());
			}

			// TODO Theoretically, the amount of salt needed depends on the algorithm
			byte[] salt = new byte[20];
			if (random == null)
			{
				random = new SecureRandom();
			}
			random.NextBytes(salt);

			try
			{
				EncryptedPrivateKeyInfo epki = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
					algorithm, password, salt, iterationCount, privKey);
	
				return new PemObject("ENCRYPTED PRIVATE KEY", epki.GetEncoded());
			}
			catch (Exception e)
			{
				throw new PemGenerationException("Couldn't encrypt private key", e);
			}
		}
	}
}