(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / Mono.Security / Mono.Security.Cryptography / DiffieHellmanManaged.cs
blob3fae43a49268cf3aa3d7c35580e7980253949a6c
1 //
2 // DiffieHellmanManaged.cs: Implements the Diffie-Hellman key agreement algorithm
3 //
4 // Author:
5 // Pieter Philippaerts (Pieter@mentalis.org)
6 //
7 // (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
8 //
9 // References:
10 // - PKCS#3 [http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/]
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System;
35 using System.Security.Cryptography;
36 using Mono.Math;
38 namespace Mono.Security.Cryptography {
39 /// <summary>
40 /// Implements the Diffie-Hellman algorithm.
41 /// </summary>
42 public sealed class DiffieHellmanManaged : DiffieHellman {
43 /// <summary>
44 /// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
45 /// </summary>
46 /// <remarks>The default length of the shared secret is 1024 bits.</remarks>
47 public DiffieHellmanManaged() : this(1024, 160, DHKeyGeneration.Static) {}
48 /// <summary>
49 /// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
50 /// </summary>
51 /// <param name="bitLength">The length, in bits, of the public P parameter.</param>
52 /// <param name="l">The length, in bits, of the secret value X. This parameter can be set to 0 to use the default size.</param>
53 /// <param name="method">One of the <see cref="DHKeyGeneration"/> values.</param>
54 /// <remarks>The larger the bit length, the more secure the algorithm is. The default is 1024 bits. The minimum bit length is 128 bits.<br/>The size of the private value will be one fourth of the bit length specified.</remarks>
55 /// <exception cref="ArgumentException">The specified bit length is invalid.</exception>
56 public DiffieHellmanManaged(int bitLength, int l, DHKeyGeneration method) {
57 if (bitLength < 256 || l < 0)
58 throw new ArgumentException();
59 BigInteger p, g;
60 GenerateKey (bitLength, method, out p, out g);
61 Initialize(p, g, null, l, false);
63 /// <summary>
64 /// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
65 /// </summary>
66 /// <param name="p">The P parameter of the Diffie-Hellman algorithm. This is a public parameter.</param>
67 /// <param name="g">The G parameter of the Diffie-Hellman algorithm. This is a public parameter.</param>
68 /// <param name="x">The X parameter of the Diffie-Hellman algorithm. This is a private parameter. If this parameters is a null reference (<b>Nothing</b> in Visual Basic), a secret value of the default size will be generated.</param>
69 /// <exception cref="ArgumentNullException"><paramref name="p"/> or <paramref name="g"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
70 /// <exception cref="CryptographicException"><paramref name="p"/> or <paramref name="g"/> is invalid.</exception>
71 public DiffieHellmanManaged(byte[] p, byte[] g, byte[] x) {
72 if (p == null || g == null)
73 throw new ArgumentNullException();
74 if (x == null)
75 Initialize(new BigInteger(p), new BigInteger(g), null, 0, true);
76 else
77 Initialize(new BigInteger(p), new BigInteger(g), new BigInteger(x), 0, true);
79 /// <summary>
80 /// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
81 /// </summary>
82 /// <param name="p">The P parameter of the Diffie-Hellman algorithm.</param>
83 /// <param name="g">The G parameter of the Diffie-Hellman algorithm.</param>
84 /// <param name="l">The length, in bits, of the private value. If 0 is specified, the default value will be used.</param>
85 /// <exception cref="ArgumentNullException"><paramref name="p"/> or <paramref name="g"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
86 /// <exception cref="ArgumentException"><paramref name="l"/> is invalid.</exception>
87 /// <exception cref="CryptographicException"><paramref name="p"/> or <paramref name="g"/> is invalid.</exception>
88 public DiffieHellmanManaged(byte[] p, byte[] g, int l) {
89 if (p == null || g == null)
90 throw new ArgumentNullException();
91 if (l < 0)
92 throw new ArgumentException();
93 Initialize(new BigInteger(p), new BigInteger(g), null, l, true);
96 // initializes the private variables (throws CryptographicException)
97 private void Initialize(BigInteger p, BigInteger g, BigInteger x, int secretLen, bool checkInput) {
98 if (checkInput) {
99 if (!p.IsProbablePrime() || g <= 0 || g >= p || (x != null && (x <= 0 || x > p - 2)))
100 throw new CryptographicException();
102 // default is to generate a number as large as the prime this
103 // is usually overkill, but it's the most secure thing we can
104 // do if the user doesn't specify a desired secret length ...
105 if (secretLen == 0)
106 secretLen = p.BitCount();
107 m_P = p;
108 m_G = g;
109 if (x == null) {
110 BigInteger pm1 = m_P - 1;
111 for(m_X = BigInteger.GenerateRandom(secretLen); m_X >= pm1 || m_X == 0; m_X = BigInteger.GenerateRandom(secretLen)) {}
112 } else {
113 m_X = x;
116 /// <summary>
117 /// Creates the key exchange data.
118 /// </summary>
119 /// <returns>The key exchange data to be sent to the intended recipient.</returns>
120 public override byte[] CreateKeyExchange() {
121 BigInteger y = m_G.ModPow(m_X, m_P);
122 byte[] ret = y.GetBytes();
123 y.Clear();
124 return ret;
126 /// <summary>
127 /// Extracts secret information from the key exchange data.
128 /// </summary>
129 /// <param name="keyEx">The key exchange data within which the shared key is hidden.</param>
130 /// <returns>The shared key derived from the key exchange data.</returns>
131 public override byte[] DecryptKeyExchange(byte[] keyEx) {
132 BigInteger pvr = new BigInteger(keyEx);
133 BigInteger z = pvr.ModPow(m_X, m_P);
134 byte[] ret = z.GetBytes();
135 z.Clear();
136 return ret;
138 /// <summary>
139 /// Gets the name of the key exchange algorithm.
140 /// </summary>
141 /// <value>The name of the key exchange algorithm.</value>
142 public override string KeyExchangeAlgorithm {
143 get {
144 return "1.2.840.113549.1.3"; // PKCS#3 OID
147 /// <summary>
148 /// Gets the name of the signature algorithm.
149 /// </summary>
150 /// <value>The name of the signature algorithm.</value>
151 public override string SignatureAlgorithm {
152 get {
153 return null;
156 // clear keys
157 protected override void Dispose(bool disposing) {
158 if (!m_Disposed) {
159 m_P.Clear();
160 m_G.Clear();
161 m_X.Clear();
163 m_Disposed = true;
165 /// <summary>
166 /// Exports the <see cref="DHParameters"/>.
167 /// </summary>
168 /// <param name="includePrivateParameters"><b>true</b> to include private parameters; otherwise, <b>false</b>.</param>
169 /// <returns>The parameters for <see cref="DiffieHellman"/>.</returns>
170 public override DHParameters ExportParameters(bool includePrivateParameters) {
171 DHParameters ret = new DHParameters();
172 ret.P = m_P.GetBytes();
173 ret.G = m_G.GetBytes();
174 if (includePrivateParameters) {
175 ret.X = m_X.GetBytes();
177 return ret;
179 /// <summary>
180 /// Imports the specified <see cref="DHParameters"/>.
181 /// </summary>
182 /// <param name="parameters">The parameters for <see cref="DiffieHellman"/>.</param>
183 /// <exception cref="CryptographicException"><paramref name="P"/> or <paramref name="G"/> is a null reference (<b>Nothing</b> in Visual Basic) -or- <paramref name="P"/> is not a prime number.</exception>
184 public override void ImportParameters(DHParameters parameters) {
185 if (parameters.P == null)
186 throw new CryptographicException("Missing P value.");
187 if (parameters.G == null)
188 throw new CryptographicException("Missing G value.");
190 BigInteger p = new BigInteger(parameters.P), g = new BigInteger(parameters.G), x = null;
191 if (parameters.X != null) {
192 x = new BigInteger(parameters.X);
194 Initialize(p, g, x, 0, true);
196 ~DiffieHellmanManaged() {
197 Dispose(false);
200 //TODO: implement DH key generation methods
201 private void GenerateKey(int bitlen, DHKeyGeneration keygen, out BigInteger p, out BigInteger g) {
202 if (keygen == DHKeyGeneration.Static) {
203 if (bitlen == 768)
204 p = new BigInteger(m_OAKLEY768);
205 else if (bitlen == 1024)
206 p = new BigInteger(m_OAKLEY1024);
207 else if (bitlen == 1536)
208 p = new BigInteger(m_OAKLEY1536);
209 else
210 throw new ArgumentException("Invalid bit size.");
211 g = new BigInteger(22); // all OAKLEY keys use 22 as generator
212 //} else if (keygen == DHKeyGeneration.SophieGermain) {
213 // throw new NotSupportedException(); //TODO
214 //} else if (keygen == DHKeyGeneration.DSA) {
215 // 1. Let j = (p - 1)/q.
216 // 2. Set h = any integer, where 1 < h < p - 1
217 // 3. Set g = h^j mod p
218 // 4. If g = 1 go to step 2
219 // BigInteger j = (p - 1) / q;
220 } else { // random
221 p = BigInteger.GeneratePseudoPrime(bitlen);
222 g = new BigInteger(3); // always use 3 as a generator
226 private BigInteger m_P;
227 private BigInteger m_G;
228 private BigInteger m_X;
229 private bool m_Disposed;
231 private static byte[] m_OAKLEY768 = new byte[] {
232 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
233 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
234 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
235 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
236 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
237 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
238 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
239 0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
241 private static byte[] m_OAKLEY1024 = new byte[] {
242 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
243 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
244 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
245 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
246 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
247 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
248 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
249 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
250 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
251 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
252 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
254 private static byte[] m_OAKLEY1536 = new byte[] {
255 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
256 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
257 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
258 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
259 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
260 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
261 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
262 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
263 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
264 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
265 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
266 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
267 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
268 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
269 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
270 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF