2 // System.Security.SecureString class
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Globalization;
32 using System.Runtime.InteropServices;
33 using System.Runtime.ConstrainedExecution;
34 using System.Security.Cryptography;
35 using System.Security.Permissions;
37 using Mono.Security.Cryptography;
39 namespace System.Security {
41 [MonoTODO ("current version ISN'T encrypted")]
42 public sealed class SecureString : CriticalFinalizerObject, IDisposable {
44 static private SymmetricAlgorithm _cipher;
45 static private int _blockSize;
48 private bool _disposed;
49 private bool _readonly;
50 private byte[] _enc; // encrypted (permanent buffer)
51 private char[] _dec; // decrypted (temporary buffer)
52 private byte[] _iv; // initialization vector
54 static SecureString ()
56 _cipher = SymmetricAlgorithm.Create ();
57 _cipher.Mode = CipherMode.CBC;
58 _cipher.Padding = PaddingMode.PKCS7;
59 _blockSize = _cipher.BlockSize << 3; // in bytes
62 public SecureString ()
64 _iv = KeyBuilder.IV (_blockSize);
66 Alloc (_blockSize >> 1, false);
69 [CLSCompliant (false)]
70 public unsafe SecureString (char* value, int length)
73 throw new ArgumentNullException ("value");
75 _iv = KeyBuilder.IV (_blockSize);
76 Alloc (length, false);
77 for (_length=1; _length <= length; _length++)
78 _dec [_length] = *value++;
87 throw new ObjectDisposedException ("SecureString");
92 public void AppendChar (char c)
95 throw new ObjectDisposedException ("SecureString");
97 throw new InvalidOperationException (Locale.GetText (
98 "SecureString is read-only."));
100 if (_length == 65535)
101 throw new ArgumentOutOfRangeException ("length", "> 65536");
105 if (_length >= _dec.Length) {
106 Alloc (_length + 1, true);
108 _dec [_length++] = c;
112 Array.Clear (_dec, 0, _dec.Length);
121 throw new ObjectDisposedException ("SecureString");
123 throw new InvalidOperationException (Locale.GetText (
124 "SecureString is read-only."));
127 Array.Clear (_dec, 0, _dec.Length); // should be empty
128 Array.Clear (_enc, 0, _enc.Length);
129 // return to default sizes
130 _dec = new char [_blockSize >> 1];
131 _enc = new byte [_blockSize];
134 _iv = KeyBuilder.IV (_blockSize);
137 public SecureString Copy ()
139 SecureString ss = new SecureString ();
142 ss._dec = (char[]) _dec.Clone ();
143 Array.Clear (_dec, 0, _dec.Length);
144 ss._enc = new byte [_dec.Length >> 1];
148 Array.Clear (_dec, 0, _dec.Length);
150 Array.Clear (ss._dec, 0, ss._dec.Length);
155 public void Dispose ()
158 Array.Clear (_enc, 0, _enc.Length);
159 Array.Clear (_dec, 0, _dec.Length);
166 public void InsertAt (int index, char c)
169 throw new ObjectDisposedException ("SecureString");
170 if ((index < 0) || (index >= _length))
171 throw new ArgumentOutOfRangeException ("index", "< 0 || > length");
173 throw new InvalidOperationException (Locale.GetText (
174 "SecureString is read-only."));
183 Array.Clear (_dec, 0, _dec.Length);
189 public bool IsReadOnly ()
192 throw new ObjectDisposedException ("SecureString");
196 public void MakeReadOnly ()
201 public void RemoveAt (int index)
204 throw new ObjectDisposedException ("SecureString");
205 if ((index < 0) || (index >= _length))
206 throw new ArgumentOutOfRangeException ("index", "< 0 || > length");
208 throw new InvalidOperationException (Locale.GetText (
209 "SecureString is read-only."));
214 Buffer.BlockCopy (_dec, index, _dec, index - 1, _dec.Length - index);
219 Array.Clear (_dec, 0, _dec.Length);
225 public void SetAt (int index, char c)
228 throw new ObjectDisposedException ("SecureString");
229 if ((index < 0) || (index >= _length))
230 throw new ArgumentOutOfRangeException ("index", "< 0 || > length");
232 throw new InvalidOperationException (Locale.GetText (
233 "SecureString is read-only."));
242 Array.Clear (_dec, 0, _dec.Length);
248 // internal/private stuff
250 // note: realloc only work for bigger buffers. Clear will
251 // reset buffers to default (and small) size.
252 private void Alloc (int length, bool realloc)
254 if ((length < 0) || (length > 65536))
255 throw new ArgumentOutOfRangeException ("length", "< 0 || > 65536");
257 int size = (((length * 2) / _blockSize) + 1) * _blockSize;
259 char[] dec = new char [size >> 1];
260 byte[] enc = new byte [size];
264 Array.Copy (_dec, 0, dec, 0, _dec.Length);
265 Array.Clear (_dec, 0, _dec.Length);
268 Array.Copy (_enc, 0, enc, 0, _enc.Length);
269 Array.Clear (_enc, 0, _enc.Length);
277 [MonoTODO ("no decryption - data is only copied")]
278 private void Decrypt ()
280 Buffer.BlockCopy (_enc, 0, _dec, 0, _enc.Length);
283 [MonoTODO ("no encryption - data is only copied")]
284 private void Encrypt ()
286 Buffer.BlockCopy (_dec, 0, _enc, 0, _enc.Length);
287 Array.Clear (_dec, 0, _dec.Length);
290 // dangerous method (put a LinkDemand on it)
291 internal byte[] GetBuffer ()
293 byte[] secret = null;
296 secret = (byte[]) _dec.Clone ();
299 Array.Clear (_dec, 0, _dec.Length);
301 // NOTE: CALLER IS RESPONSIBLE TO ZEROIZE THE DATA