1 using System.Diagnostics.Contracts;
4 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // <OWNER>[....]</OWNER>
11 // SymmetricAlgorithm.cs
14 namespace System.Security.Cryptography {
15 [System.Runtime.InteropServices.ComVisible(true)]
16 public abstract class SymmetricAlgorithm : IDisposable {
17 protected int BlockSizeValue;
18 protected int FeedbackSizeValue;
19 protected byte[] IVValue;
20 protected byte[] KeyValue;
21 protected KeySizes[] LegalBlockSizesValue;
22 protected KeySizes[] LegalKeySizesValue;
23 protected int KeySizeValue;
24 protected CipherMode ModeValue;
25 protected PaddingMode PaddingValue;
28 // protected constructors
31 protected SymmetricAlgorithm() {
32 // Default to cipher block chaining (CipherMode.CBC) and
33 // PKCS-style padding (pad n bytes with value n)
34 ModeValue = CipherMode.CBC;
35 PaddingValue = PaddingMode.PKCS7;
38 // SymmetricAlgorithm implements IDisposable
40 // To keep mscorlib compatibility with Orcas, CoreCLR's SymmetricAlgorithm has an explicit IDisposable
41 // implementation. Post-Orcas the desktop has an implicit IDispoable implementation.
43 void IDisposable.Dispose()
47 #endif // FEATURE_CORECLR
52 GC.SuppressFinalize(this);
56 (this as IDisposable).Dispose();
59 protected virtual void Dispose(bool disposing) {
61 // Note: we always want to zeroize the sensitive key material
62 if (KeyValue != null) {
63 Array.Clear(KeyValue, 0, KeyValue.Length);
66 if (IVValue != null) {
67 Array.Clear(IVValue, 0, IVValue.Length);
77 public virtual int BlockSize {
78 get { return BlockSizeValue; }
83 for (i=0; i<LegalBlockSizesValue.Length; i++) {
84 // If a cipher has only one valid key size, MinSize == MaxSize and SkipSize will be 0
85 if (LegalBlockSizesValue[i].SkipSize == 0) {
86 if (LegalBlockSizesValue[i].MinSize == value) { // assume MinSize = MaxSize
87 BlockSizeValue = value;
92 for (j = LegalBlockSizesValue[i].MinSize; j<=LegalBlockSizesValue[i].MaxSize;
93 j += LegalBlockSizesValue[i].SkipSize) {
95 if (BlockSizeValue != value) {
96 BlockSizeValue = value;
97 IVValue = null; // Wrong length now
104 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidBlockSize"));
108 public virtual int FeedbackSize {
109 get { return FeedbackSizeValue; }
111 if (value <= 0 || value > BlockSizeValue || (value % 8) != 0)
112 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidFeedbackSize"));
114 FeedbackSizeValue = value;
118 public virtual byte[] IV {
120 if (IVValue == null) GenerateIV();
121 return (byte[]) IVValue.Clone();
124 if (value == null) throw new ArgumentNullException("value");
125 Contract.EndContractBlock();
126 if (value.Length != BlockSizeValue / 8)
127 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidIVSize"));
129 IVValue = (byte[]) value.Clone();
133 public virtual byte[] Key {
135 if (KeyValue == null) GenerateKey();
136 return (byte[]) KeyValue.Clone();
139 if (value == null) throw new ArgumentNullException("value");
140 Contract.EndContractBlock();
141 if (!ValidKeySize(value.Length * 8))
142 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));
144 // must convert bytes to bits
145 KeyValue = (byte[]) value.Clone();
146 KeySizeValue = value.Length * 8;
150 public virtual KeySizes[] LegalBlockSizes {
151 get { return (KeySizes[]) LegalBlockSizesValue.Clone(); }
154 public virtual KeySizes[] LegalKeySizes {
155 get { return (KeySizes[]) LegalKeySizesValue.Clone(); }
158 public virtual int KeySize {
159 get { return KeySizeValue; }
161 if (!ValidKeySize(value))
162 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));
164 KeySizeValue = value;
169 public virtual CipherMode Mode {
170 get { return ModeValue; }
172 if ((value < CipherMode.CBC) || (CipherMode.CFB < value))
173 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidCipherMode"));
179 public virtual PaddingMode Padding {
180 get { return PaddingValue; }
182 if ((value < PaddingMode.None) || (PaddingMode.ISO10126 < value))
183 throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidPaddingMode"));
185 PaddingValue = value;
193 // The following method takes a bit length input and returns whether that length is a valid size
194 // according to LegalKeySizes
195 public bool ValidKeySize(int bitLength) {
196 KeySizes[] validSizes = this.LegalKeySizes;
199 if (validSizes == null) return false;
200 for (i=0; i< validSizes.Length; i++) {
201 if (validSizes[i].SkipSize == 0) {
202 if (validSizes[i].MinSize == bitLength) { // assume MinSize = MaxSize
206 for (j = validSizes[i].MinSize; j<= validSizes[i].MaxSize;
207 j += validSizes[i].SkipSize) {
208 if (j == bitLength) {
217 static public SymmetricAlgorithm Create() {
219 return new System.Security.Cryptography.RijndaelManaged ();
221 // use the crypto config system to return an instance of
222 // the default SymmetricAlgorithm on this machine
223 return Create("System.Security.Cryptography.SymmetricAlgorithm");
227 static public SymmetricAlgorithm Create(String algName) {
228 return (SymmetricAlgorithm) CryptoConfig.CreateFromName(algName);
231 public virtual ICryptoTransform CreateEncryptor() {
232 return CreateEncryptor(Key, IV);
235 public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
237 public virtual ICryptoTransform CreateDecryptor() {
238 return CreateDecryptor(Key, IV);
241 public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
243 public abstract void GenerateKey();
245 public abstract void GenerateIV();