views:

194

answers:

4

I have a quick little app that steps through the possible symmetric encryption methods. I get them with the following line:

 private static List<Type> GetAlgorithmTypes
    {
        get { return Assembly.GetAssembly(typeof(SymmetricAlgorithm)).GetTypes().Where( type => type.IsSubclassOf(typeof(SymmetricAlgorithm))).ToList(); }
    }

As you can see when i run this, AesCryptoServiceProvider is not a member of this group, even though it inherits from AES, which does belong to SymmetricAlgorithm and shows up in my list. This wouldn't be so much of a problem, i can manually add the provider in the group if i have too, but then if i try to retrieve this type by its name:

Type t = Type.GetType("System.Security.Cryptography.AesCryptoServiceProvider");

i get a null object for AesCryptoServiceProvider, but not for any of the other items in the group.

This is really strange, and i'm wondering if anyone has any ideas. It's kinda making me need to use tripleDES because of this (since my machines are all running the FIPS compliance requirement).

Thanks for any help!

+1  A: 

I believe Type.IsSubclassOf checks only if the type is a direct subclass of the specified type. Have you tried using Type.IsAssignableFrom instead?

type => typeof(SymmetricAlgorithm).IsAssignableFrom(type)
dtb
that query just gives back:SymmetricAlgorithmIDisposableObject
Phil
+1  A: 

Are you sure the assembly with AesCryptoServiceProvider is loaded? Assembly.GetAssembly will only look in the currently loaded assembly collection.

Tejs
Good find. SymmetricAlgorithm and AES are in *mscorlib*. AesCryptoServiceProvider is in *System.Core*. So if he enumerates the types in Assembly.GetAssembly(typeof(SymmetricAlgorithm)) then AesCryptoServiceProvider will never be found.
dtb
Yes, i do have the System.Core reference in my project.
Phil
+2  A: 

SymmetricAlgorithm is in mscorlib.dll, AesCryptoServiceProvider is located in System.Core.dll

By getting the assembly based on the SymmetricAlgorithm type you are getting the mscorlib assembly which does not contain AesCryptoServiceProvider.

You might want to pinvoke CryptEnumProviders, to get a list of available CSPs, then you can use CryptoConfig.CreateFromName(...) to create an instance of that CSP.


You could try something like this, it will find the type if its assembly loaded in the current AppDomain.

var types = AppDomain.CurrentDomain.GetAssemblies()
    .Select(
        a => a.GetTypes()
            .Where( t => typeof(SymmetricAlgorithm).IsAssignableFrom(t) )
    )
joshperry
Thanks. It does seem weird that I can declare an object of type System.Security.Cryptography.AesCryptoServiceProviderbut i can't do a 'GetType' on that type. Seems like a bug to me, regardless if they come from different assemblies. But thanks for the tip about looking into pInvoke. That might be the only way to do what i want to do.
Phil
A: 

What you should do is easy to explain in Win32 API. There are following native API:

CryptEnumProviders, CryptEnumProviderTypes, CryptGetDefaultProvider

which do not much more as examine of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider. See code example from http://msdn.microsoft.com/en-us/library/aa382359(VS.85).aspx.

Every provider implement some cryptographic algorithms. This respect of CryptGetProvParam (see http://msdn.microsoft.com/en-us/library/aa380196(VS.85).aspx) and PP_ENUMALGS or PP_ENUMALGS_EX you can examine this algorithms. You don't confused that you can have many implementation of the same algorithms inside of different providers (DLLs). Different providers can hold a key on the different place (like smart card) or has some main job like RSA SChannel, but need and implement some other algorithms.

Every algorithm has identified like ALG_ID aiAlgid; where ALG_ID is unsigned int and consist from three parts like one can see in wincrypt.h:

//
// Algorithm IDs and Flags
//

// ALG_ID crackers
#define GET_ALG_CLASS(x)                (x & (7 << 13))
#define GET_ALG_TYPE(x)                 (x & (15 << 9))
#define GET_ALG_SID(x)                  (x & (511))

// Algorithm classes
// certenrolld_begin -- ALG_CLASS_*
#define ALG_CLASS_ANY                   (0)
#define ALG_CLASS_SIGNATURE             (1 << 13)
#define ALG_CLASS_MSG_ENCRYPT           (2 << 13)
#define ALG_CLASS_DATA_ENCRYPT          (3 << 13)
#define ALG_CLASS_HASH                  (4 << 13)
#define ALG_CLASS_KEY_EXCHANGE          (5 << 13)
#define ALG_CLASS_ALL                   (7 << 13)
// certenrolld_end

// Algorithm types
#define ALG_TYPE_ANY                    (0)
#define ALG_TYPE_DSS                    (1 << 9)
#define ALG_TYPE_RSA                    (2 << 9)
#define ALG_TYPE_BLOCK                  (3 << 9)
#define ALG_TYPE_STREAM                 (4 << 9)
#define ALG_TYPE_DH                     (5 << 9)
#define ALG_TYPE_SECURECHANNEL          (6 << 9)

#define CALG_AES_256            (ALG_CLASS_DATA_ENCRYPT|ALG_TYPE_BLOCK|ALG_SID_AES_256)

I included only one encrypting algorithm. So you are interesting for all algorithms with the class ALG_CLASS_DATA_ENCRYPT. You can easy find out from "ALG_ID crackers" GET_ALG_CLAS() the class part of all algorithms and filter ALG_CLASS_DATA_ENCRYPT only.

Oleg