2 // Rfc2898DeriveBytes.cs: RFC2898 (PKCS#5 v2) Key derivation for Password Based Encryption
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 using Mono
.Security
.Cryptography
;
40 namespace System
.Security
.Cryptography
{
42 public class Rfc2898DeriveBytes
: DeriveBytes
{
44 private const int defaultIterations
= 1000;
46 private int _iteration
;
48 private HMACSHA1 _hmac
;
49 private byte[] _buffer
;
55 public Rfc2898DeriveBytes (string password
, byte[] salt
)
56 : this (password
, salt
, defaultIterations
) {}
58 public Rfc2898DeriveBytes (string password
, byte[] salt
, int iterations
)
61 throw new ArgumentNullException ("password");
64 IterationCount
= iterations
;
65 _hmac
= new HMACSHA1 (Encoding
.UTF8
.GetBytes (password
));
68 public Rfc2898DeriveBytes (string password
, int saltSize
)
69 : this (password
, saltSize
, defaultIterations
) {}
71 public Rfc2898DeriveBytes (string password
, int saltSize
, int iterations
)
74 throw new ArgumentNullException ("password");
76 throw new ArgumentOutOfRangeException ("invalid salt length");
78 Salt
= KeyBuilder
.Key (saltSize
);
79 IterationCount
= iterations
;
80 _hmac
= new HMACSHA1 (Encoding
.UTF8
.GetBytes (password
));
85 public int IterationCount
{
86 get { return _iteration; }
89 throw new ArgumentOutOfRangeException ("IterationCount < 1");
96 get { return (byte[]) _salt.Clone (); }
99 throw new ArgumentNullException ("Salt");
100 if (value.Length
< 8)
101 throw new ArgumentException ("Salt < 8 bytes");
103 _salt
= (byte[])value.Clone ();
109 private byte[] F (byte[] s
, int c
, int i
)
111 byte[] data
= new byte [s
.Length
+ 4];
112 Buffer
.BlockCopy (s
, 0, data
, 0, s
.Length
);
113 byte[] int4
= BitConverter
.GetBytes (i
);
114 Array
.Reverse (int4
, 0, 4);
115 Buffer
.BlockCopy (int4
, 0, data
, s
.Length
, 4);
118 byte[] u1
= _hmac
.ComputeHash (data
);
120 // so we start at j=1
121 for (int j
=1; j
< c
; j
++) {
122 byte[] un
= _hmac
.ComputeHash (data
);
124 for (int k
=0; k
< 20; k
++)
125 u1
[k
] = (byte)(u1
[k
] ^ un
[k
]);
131 public override byte[] GetBytes (int cb
)
134 throw new ArgumentOutOfRangeException ("cb");
136 int l
= cb
/ 20; // HMACSHA1 == 160 bits == 20 bytes
137 int r
= cb
% 20; // remainder
141 byte[] result
= new byte [cb
];
144 int count
= Math
.Min (20 - _pos
, cb
);
145 Buffer
.BlockCopy (_buffer
, _pos
, result
, 0, count
);
153 for (int i
=1; i
<= l
; i
++) {
154 _buffer
= F (_salt
, _iteration
, ++_f
);
155 int count
= ((i
== l
) ? r
: 20);
156 Buffer
.BlockCopy (_buffer
, _pos
, result
, rpos
, count
);
157 rpos
+= _pos
+ count
;
158 _pos
= ((count
== 20) ? 0 : count
);
164 public override void Reset ()