a775477b4369ab9525044d44f2e0e0c514c61c6e
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DES.cs
1 //
2 // System.Security.Cryptography.DES
3 //
4 // Author:
5 //      Sergey Chaban (serge@wildwestsoftware.com)
6 //      Sebastien Pouliot <sebastien@ximian.com>
7 //
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
9 // (C) 2004 Novell (http://www.novell.com)
10 //
11
12 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Globalization;
37 using System.Security.Cryptography;
38
39 // References:
40 // a.   FIPS PUB 46-3: Data Encryption Standard
41 //      http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
42
43 namespace System.Security.Cryptography {
44
45 public abstract class DES : SymmetricAlgorithm {
46
47         const int blockSizeByte = 8;
48
49         public DES ()
50         {
51                 KeySizeValue = 64; 
52                 BlockSizeValue = 64; 
53                 FeedbackSizeValue = 64;
54
55                 LegalKeySizesValue = new KeySizes[1];
56                 LegalKeySizesValue[0] = new KeySizes(64, 64, 0);
57
58                 LegalBlockSizesValue = new KeySizes[1];
59                 LegalBlockSizesValue[0] = new KeySizes(64, 64, 0);
60         }
61
62         public static new DES Create () 
63         {
64                 return Create ("System.Security.Cryptography.DES");
65         }
66
67         public static new DES Create (string algo) 
68         {
69                 return (DES) CryptoConfig.CreateFromName (algo);
70         }
71
72         internal static ulong PackKey (byte[] key) 
73         {
74                 byte[] paritySetKey = new byte [blockSizeByte];
75                 // adapted from bouncycastle - see bouncycastle.txt
76                 for (int i=0; i < key.Length; i++) {
77                         byte b = key [i];
78                         paritySetKey [i] = (byte)((b & 0xfe) |
79                                 ((((b >> 1) ^ (b >> 2) ^ (b >> 3) ^ (b >> 4) ^
80                                 (b >> 5) ^ (b >> 6) ^ (b >> 7)) ^ 0x01) & 0x01));
81                 }
82
83                 ulong res = 0;
84                 for (int i = 0, sh = 8*blockSizeByte; (sh = sh - 8) >= 0; i++) {
85                         res |= (ulong) paritySetKey [i] << sh;
86                 }
87
88                 Array.Clear (paritySetKey, 0, paritySetKey.Length);
89                 return res;
90         }
91
92         // Ek(Ek(m)) = m
93         internal static readonly ulong[] weakKeys = {
94                 0x0101010101010101, /* 0000000 0000000 */
95                 0xFEFEFEFEFEFEFEFE, /* FFFFFFF FFFFFFF */
96                 0x1F1F1F1F0E0E0E0E, /* 0000000 FFFFFFF */
97                 0xE0E0E0E0F1F1F1F1  /* FFFFFFF 0000000 */
98         };
99
100         // Ek1(Ek2(m)) = m
101         internal static readonly ulong[] semiweakKeys = {
102                 0x01FE01FE01FE01FE, 0xFE01FE01FE01FE01,
103                 0x1FE01FE00EF10EF1, 0xE01FE01FF10EF10E,
104                 0x01E001E001F101F1, 0xE001E001F101F101,
105                 0x1FFE1FFE0EFE0EFE, 0xFE1FFE1FFE0EFE0E,
106                 0x011F011F010E010E, 0x1F011F010E010E01,
107                 0xE0FEE0FEF1FEF1FE, 0xFEE0FEE0FEF1FEF1
108         };
109
110         public static bool IsWeakKey (byte[] rgbKey) 
111         {
112                 if (rgbKey.Length != blockSizeByte)
113                         throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
114
115                 ulong lk = PackKey (rgbKey);
116                 foreach (ulong wk in weakKeys) {
117                         if (lk == wk)
118                                 return true;
119                 }
120                 return false;
121         }
122
123         public static bool IsSemiWeakKey (byte[] rgbKey)
124         {
125                 if (rgbKey.Length != blockSizeByte)
126                         throw new CryptographicException (Locale.GetText ("Wrong Key Length"));
127
128                 ulong lk = PackKey (rgbKey);
129                 foreach (ulong swk in semiweakKeys) {
130                         if (lk == swk)
131                                 return true;
132                 }
133                 return false;
134         }
135
136         public override byte[] Key {
137                 get {
138                         if (KeyValue == null) {
139                                 // GenerateKey is responsible to return a valid key
140                                 // e.g. no weak or semi-weak keys
141                                 GenerateKey ();
142                         }
143                         return (byte[]) KeyValue.Clone ();
144                 }
145                 set {
146                         if (value == null)
147                                 throw new ArgumentNullException ("Key");
148                         if (value.Length != blockSizeByte)
149                                 throw new ArgumentException (Locale.GetText ("Wrong Key Length"));
150                         if (IsWeakKey (value))
151                                 throw new CryptographicException (Locale.GetText ("Weak Key"));
152                         if (IsSemiWeakKey (value))
153                                 throw new CryptographicException (Locale.GetText ("Semi Weak Key"));
154
155                         KeyValue = (byte[]) value.Clone ();
156                 }
157         }
158 }
159
160 }