Initial commit
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / tripledes.cs
1 using System.Diagnostics.Contracts;
2 // ==++==
3 // 
4 //   Copyright (c) Microsoft Corporation.  All rights reserved.
5 // 
6 // ==--==
7 // <OWNER>[....]</OWNER>
8 // 
9
10 //
11 // TripleDES.cs
12 //
13
14 namespace System.Security.Cryptography {
15 [System.Runtime.InteropServices.ComVisible(true)]
16     public abstract class TripleDES : SymmetricAlgorithm
17     {
18         private static  KeySizes[] s_legalBlockSizes = {
19             new KeySizes(64, 64, 0)
20         };
21
22         private static  KeySizes[] s_legalKeySizes = {
23             new KeySizes(2*64, 3*64, 64)
24         };
25       
26         //
27         // protected constructors
28         //
29     
30         protected TripleDES() {
31             KeySizeValue = 3*64;
32             BlockSizeValue = 64;
33             FeedbackSizeValue = BlockSizeValue;
34             LegalBlockSizesValue = s_legalBlockSizes;
35             LegalKeySizesValue = s_legalKeySizes;
36         }
37     
38         //
39         // public properties
40         //
41
42         public override byte[] Key {
43             get { 
44                 if (KeyValue == null) {
45                     // Never hand back a weak key
46                     do {
47                         GenerateKey();
48                     } while (IsWeakKey(KeyValue));
49                 }
50                 return (byte[]) KeyValue.Clone(); 
51             }
52             set {
53                 if (value == null) throw new ArgumentNullException("value");
54                 Contract.EndContractBlock();
55                 if (!ValidKeySize(value.Length * 8)) { // must convert bytes to bits
56                     throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));
57                 }
58                 if (IsWeakKey(value)) {
59                     throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKey_Weak"),"TripleDES");
60                 }
61                 KeyValue = (byte[]) value.Clone();
62                 KeySizeValue = value.Length * 8;
63             }
64         }
65         
66         //
67         // public methods
68         //
69
70         new static public TripleDES Create() {
71             return Create("System.Security.Cryptography.TripleDES");
72         }
73
74         new static public TripleDES Create(String str) {
75             return (TripleDES) CryptoConfig.CreateFromName(str);
76         }
77
78         public static bool IsWeakKey(byte[] rgbKey) {
79             // All we have to check for here is (a) we're in 3-key mode (192 bits), and
80             // (b) either K1 == K2 or K2 == K3
81             if (!IsLegalKeySize(rgbKey)) {
82                 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));
83             }
84             byte[] rgbOddParityKey = Utils.FixupKeyParity(rgbKey);
85             if (EqualBytes(rgbOddParityKey,0,8,8)) return(true);
86             if ((rgbOddParityKey.Length == 24) && EqualBytes(rgbOddParityKey,8,16,8)) return(true);
87             return(false);
88         }
89     
90         //
91         // private methods
92         //
93
94         private static bool EqualBytes(byte[] rgbKey, int start1, int start2, int count) {
95             if (start1 < 0) throw new ArgumentOutOfRangeException("start1", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
96             if (start2 < 0) throw new ArgumentOutOfRangeException("start2", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
97             if ((start1+count) > rgbKey.Length) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
98             if ((start2+count) > rgbKey.Length) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"));
99             Contract.EndContractBlock();
100             for (int i = 0; i < count; i++) {
101                 if (rgbKey[start1+i] != rgbKey[start2+i]) return(false);
102             }
103             return(true);
104         }
105
106         private static bool IsLegalKeySize(byte[] rgbKey) {
107             if (rgbKey != null && ((rgbKey.Length == 16) || (rgbKey.Length == 24))) 
108                 return(true);
109             return(false);
110         }
111     }
112 }