Übersetzung vorschlagen
 
Andere Vorschläge:

progress indicator
Keine anderen Vorschläge
MSDN Magazin > Home > Ausgaben > 2009 > MSDN Magazin August 2009 >  Security Briefs: Kryptografische Flexibilität
Inhalt anzeigen:  Englisch mit deutscher ÜbersetzungInhalt anzeigen: Englisch mit deutscher Übersetzung
Dies sind maschinell übersetzte Inhalte, die von den Mitgliedern der Community bearbeitet werden können. Sie können die Übersetzung verbessern, indem Sie auf den jeweils zum Satz gehörenden Link "Bearbeiten" klicken.Mithilfe des Dropdown-Steuerelements "Inhalt anzeigen" links oben auf der Seite können Sie zudem bestimmen, ob nur der englische Originaltext, nur die deutsche Übersetzung oder beides nebeneinander angezeigt werden.
Security Briefs
Cryptographic Agility
Bryan Sullivan
Throughout history, people have used various forms of ciphers to conceal information from their adversaries. Julius Caesar used a three-place shift cipher (the letter A is converted to D, B is converted to E, and so on) to communicate battle plans. During World War II, the German navy used a significantly more advanced system—the Enigma machine—to encrypt messages sent to their U-boats. Today, we use even more sophisticated encryption mechanisms as part of the public key infrastructure that helps us perform secure transactions on the Internet.
But for as long as cryptographers have been making secret codes, cryptanalysts have been trying to break them and steal information, and sometimes the code breakers succeed. Cryptographic algorithms once considered secure are broken and rendered useless. Sometimes subtle flaws are found in the algorithms, and sometimes it is simply a matter of attackers having access to more computing power to perform brute-force attacks.
Recently, security researchers have demonstrated weaknesses in the MD5 hash algorithm as the result of collisions; that is, they have shown that two messages can have the same computed MD5 hash value. They have created a proof-of-concept attack against this weakness targeted at the public key infrastructures that protect e-commerce transactions on the Web. By purchasing a specially crafted Web site certificate from a certificate authority (CA) that uses MD5 to sign its certificates, the researchers were able to create a rogue CA certificate that could effectively be used to impersonate potentially any site on the Internet. They concluded that MD5 is not appropriate for signing digital certificates and that a stronger alternative, such as one of the SHA-2 algorithms, should be used. (If you're interested in learning more about this research, you can read the white paper.)
These findings are certainly cause for concern, but they are not a huge surprise. Theoretical MD5 weaknesses have been demonstrated for years, and the use of MD5 in Microsoft products has been banned by the Microsoft SDL cryptographic standards since 2005. Other once-popular algorithms, such as SHA-1 and RC2, have been similarly banned. Figure 1 shows a complete list of the cryptographic algorithms banned or approved by the SDL. The list of SDL-approved algorithms is current as of this writing, but this list is reviewed and updated annually as part of the SDL update process.
Figure 1 SDL-Approved Cryptographic Algorithms
Algorithm Type Banned (algorithms to be replaced in existing code or used only for decryption) Acceptable (algorithms acceptable for existing code, except sensitive data) Recommended (algorithms for new code)
Symmetric Block DES, DESX, RC2, SKIPJACK 3DES (2 or 3 key) AES (>=128 bit)
Symmetric Stream SEAL, CYLINK_MEK, RC4 (<128bit) RC4 (>= 128bit) None, block cipher is preferred
Asymmetric RSA (<2048 bit), Diffie-Hellman (<2048 bit) RSA (>=2048bit ), Diffie-Hellman (>=2048bit) RSA (>=2048bit), Diffie-Hellman (>=2048bit), ECC (>=256bit)
Hash (includes HMAC usage) SHA-0 (SHA), SHA-1, MD2, MD4, MD5 SHA-2 SHA-2 (includes: SHA-256, SHA-384, SHA-512)
HMAC Key Lengths <112bit >= 112bit >= 128bit
Even if you follow these standards in your own code, using only the most secure algorithms and the longest key lengths, there's no guarantee that the code you write today will remain secure. In fact, it will probably not remain secure if history is any guide.

Planning for Future Exploits
You can address this unpleasant scenario reactively by going through your old applications' code bases, picking out instantiations of vulnerable algorithms, replacing them with new algorithms, rebuilding the applications, running them through regression tests, and then issuing patches or service packs to your users. This is not only a lot of work for you, but it still leaves your users at risk until you can get the fixes shipped.
A better alternative is to plan for this scenario from the beginning. Rather than hard-coding specific cryptographic algorithms into your code, use one of the crypto-agility features built into the Microsoft .NET Framework. Let's take a look at a few C# code snippets, starting with the least agile example:
private static byte[] computeHash(byte[] buffer)
{
   using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
   {
      return md5.ComputeHash(buffer);
   }
}
This code is completely nonagile. It is tied to a specific algorithm (MD5) as well as a specific implementation of that algorithm, the MD5CryptoServiceProvider class. Modifying this application to use a secure hashing algorithm would require changing code and issuing a patch. Here's a little better example:
private static byte[] computeHash(byte[] buffer)
{
   string md5Impl = ConfigurationManager.AppSettings["md5Impl"];
   if (md5Impl == null)
      md5Impl = String.Empty;

   using (MD5 md5 = MD5.Create(md5Impl))
   {
      return md5.ComputeHash(buffer);
   }
}
This function uses the System.Configuration.Configuration Manager class to retrieve a custom app setting (the "md5Impl" setting) from the application's configuration file. In this case, the setting is used to store the strong name of the algorithm implementation class you want to use. The code passes the retrieved value of this setting to the static function MD5.Create to create an instance of the desired class. (System.Security.Cryptography.MD5 is an abstract base class from which all implementations of the MD5 algorithm must derive.) For example, if the application setting for md5Impl was set to the string "System.Security.Cryptography.MD5Cng, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", MD5.Create would create an instance of the MD5Cng class.
This approach solves only half of our crypto-agility problem, so it really is no solution at all. We can now specify an implementation of the MD5 algorithm without having to change any source code, which might prove useful if a flaw is discovered in a specific implementation, like MD5Cng, but we're still tied to the use of MD5 in general. To solve this problem, we keep abstracting upward:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MD5"))
   {
      return hash.ComputeHash(buffer);
   }
}
At first glance, this code snippet does not look substantially different from the first example. It looks like we've once again hard-coded the MD5 algorithm into the application via the call to HashAlgorithm.Create("MD5"). Surprisingly though, this code is substantially more cryptographically agile than both of the other examples. While the default behavior of the method call HashAlgorithm.Create("MD5")—as of .NET 3.5—is to create an instance of the MD5CryptoServiceProvider class, the runtime behavior can be customized by making a change to the machine.config file.
Let's change the behavior of this code to create an instance of the SHA512algorithm instead of MD5. To do this, we need to add two elements to the machine.config file: a <cryptoClass> element to map a friendly algorithm name to the algorithm implementation class we want; and a <nameEntry> element to map the old, deprecated algorithm's friendly name to the new friendly name.
<configuration>
  <mscorlib>
    <cryptographySettings>
      <cryptoNameMapping>
        <cryptoClasses>
          <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
          	Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        </cryptoClasses>
        <nameEntry name="MD5" class="MyPreferredHash"/>
      </cryptoNameMapping>
    </cryptographySettings>
  </mscorlib>
</configuration>
Now, when our code makes its call to HashAlgorithm.Create("MD5"), the CLR looks in the machine.config file and sees that the string "MD5" should map to the friendly algorithm name "MyPreferredHash". It then sees that "MyPreferredHash" maps to the class SHA512CryptoServiceProvider (as defined in the assembly System.Core, with the specified version, culture, and public key token) and creates an instance of that class.
It's important to note that the algorithm remapping takes place not at compile time but at run time: it's the user's machine.config that controls the remapping, not the developer's. As a result, this technique solves our dilemma of being tied to a particular algorithm that might be broken at some time in the future. By avoiding hard-coding the cryptographic algorithm class into the application—coding only the abstract type of cryptographic algorithm, HashAlgorithm, instead—we create an application in which the end user (more specifically, someone with administrative rights to edit the machine.config file on the machine where the application is installed) can determine exactly which algorithm and implementation the application will use. An administrator might choose to replace an algorithm that was recently broken with one still considered secure (for example, replace MD5 with SHA-256) or to proactively replace a secure algorithm with an alternative with a longer bit length (replace SHA-256 with SHA-512).

Potential Problems
Modifying the machine.config file to remap the default algorithm-type strings (like "MD5" and "SHA1") might solve crypto-agility problems, but it can create compatibility problems at the same time. Making changes to machine.config affects every .NET application on the machine. Other applications installed on the machine might rely on MD5 specifically, and changing the algorithms used by these applications might break them in unexpected ways that are difficult to diagnose. As an alternative to forcing blanket changes to the entire machine, it's better to use custom, application-specific friendly names in your code and map those name entries to preferred classes in the machine.config. For example, we can change "MD5" to "MyApplicationHash" in our example:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}
We then add an entry to the machine.config file to map "MyApplicationHash" to the "MyPreferredHash" class:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
You can also map multiple friendly names to the same class; for example, you could have one friendly name for each of your applications, and in this way change the behavior of specific applications without affecting every other application on the machine:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
<nameEntry name="MyApplication2Hash" class="MyPreferredHash"/>
<nameEntry name="MyApplication3Hash" class="MyPreferredHash"/>

However, we're still not out of the woods with regard to compatibility problems in our own applications. You need to plan ahead regarding storage size, for both local variables (transient storage) and database and XML schemas (persistent storage). For example, MD5 hashes are always 128 bits in length. If you budget exactly 128 bits in your code or schema to store hash output, you will not be able to upgrade to SHA-256 (256 bit-length output) or SHA-512 (512 bit-length output).
This does beg the question of how much storage is enough. Is 512 bits enough, or should you use 1,024, 2,048, or more? I can't provide a hard rule here because every application has different requirements, but as a rule of thumb I recommend that you budget twice as much space for hashes as you currently use. For symmetric- and asymmetric-encrypted data, you might reserve an extra 10 percent of space at most. It's unlikely that new algorithms with output sizes significantly larger than existing algorithms will be widely accepted.
However, applications that store hash values or encrypted data in a persistent state (for example, in a database or file) have bigger problems than reserving enough space. If you persist data using one algorithm and then try to operate on that data later using a different algorithm, you will not get the results you expect. For example, it's a good idea to store hashes of passwords rather than the full plaintext versions. When the user tries to log on, the code can compare the hash of the password supplied by the user to the stored hash in the database. If the hashes match, the user is authentic. However, if a hash is stored in one format (say, MD5) and an application is upgraded to use another algorithm (say, SHA-256), users will never be able to log on because the SHA-256 hash value of the passwords will always be different from the MD5 hash value of those same passwords.
You can get around this issue in some cases by storing the original algorithm as metadata along with the actual data. Then, when operating on stored data, use the agility methods (or reflection) to instantiate the algorithm originally used instead of the current algorithm:
private static bool checkPassword(string password, byte[] storedHash,
   string storedHashAlgorithm)
{
   using (HashAlgorithm hash = HashAlgorithm.Create(storedHashAlgorithm))
   {
      byte[] newHash = 
         hash.ComputeHash(System.Text.Encoding.Default.GetBytes(password));
      if (newHash.Length != storedHash.Length)
         return false;
      for (int i = 0; i < newHash.Length; i++)
         if (newHash[i] != storedHash[i])
            return false;
      return true;
   }
}
Unfortunately, if you ever need to compare two stored hashes, they have to have been created using the same algorithm. There is simply no way to compare an MD5 hash to a SHA-256 hash and determine if they were both created from the same original data. There is no good crypto-agility solution for this problem, and the best advice I can offer is that you should choose the most secure algorithm currently available and then develop an upgrade plan in case that algorithm is broken later. In general, crypto agility tends to work much better for transient data than for persistent data.

Alternative Usage and Syntax
Assuming that your application design allows the use of crypto agility, let's continue to look at some alternative uses and syntaxes for this technique. We've focused almost entirely on cryptographic hashing algorithms to this point in the article, but crypto agility also works for other cryptographic algorithm types. Just call the static Create method of the appropriate abstract base class: SymmetricAlgorithm for symmetric (secret-key) cryptography algorithms such as AES; AsymmetricAlgorithm for asymmetric (public key) cryptography algorithms such as RSA; KeyedHashAlgorithm for keyed hashes; and HMAC for hash-based message authentication codes.
You can also use crypto agility to replace one of the standard .NET cryptographic algorithm classes with a custom algorithm class, such as one of the algorithms developed by the CLR security team and uploaded to CodePlex. However, writing your own custom crypto libraries is highly discouraged. Your homemade algorithm consisting of an ROT13 followed by a bitwise left shift and an XOR against your cat's name might seem secure, but it will pose little challenge to an expert code breaker. Unless you are an expert in cryptography, leave algorithm design to the professionals.
Also resist the temptation to develop your own algorithms—or to revive long-dead, obscure ones, like the Vigenère cipher—even in situations where you don't need cryptographically strong protection. The issue isn't so much what you do with your cipher, but what developers who come after you will do with it. A new developer who finds your custom algorithm class in the code base years later might decide that it's just what he needs for the new product activation key generation logic.
So far we've seen one of the syntaxes for implementing cryptographically agile code, AlgorithmType.Create(algorithmName), but two other approaches are built into the .NET Framework. The first is to use the System.Security.Cryptography.CryptoConfig class:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = (HashAlgorithm)CryptoConfig.CreateFromName("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}
This code performs the same operations as our previous example using HashAlgorithm.Create("MyApplicationHash"): the CLR looks in the machine.config file for a remapping of the string "MyApplicationHash" and uses the remapped algorithm class if it finds one. Notice that we have to cast the result of CryptoConfig.CreateFromName because it has a return type of System.Object and can be used to create SymmetricAlgorithms, AsymmetricAlgorithms, or any other kind of object.
The second alternative syntax is to call the static algorithm Create method in our original example but with no parameters, like this:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      return hash.ComputeHash(buffer);
   }
}
In this code, we simply ask the framework to provide an instance of whatever the default hash algorithm implementation is. You can find the list of defaults for each of the System.Security.Cryptography abstract base classes (as of .NET 3.5) in Figure 2.
Figure 2 Default Algorithms and Implementations in the .NET Framework 3.5
Abstract Base Class Default Algorithm Default Implementation
HashAlgorithm SHA-1 SHA1CryptoServiceProvider
SymmetricAlgorithm AES (Rijndael) RijndaelManaged
AsymmetricAlgorithm RSA RSACryptoServiceProvider
KeyedHashAlgorithm SHA-1 HMACSHA1
HMAC SHA-1 HMACSHA1
For HashAlgorithm, you can see that the default algorithm is SHA-1 and the default implementation class is SHA1CryptoServiceProvider. However, we know that SHA-1 is banned by the SDL cryptographic standards. For the moment, let's ignore the fact that potential compatibility problems make it generally unwise to remap inherent algorithm names like "SHA1" and alter our machine.config to remap "SHA1" to SHA512CryptoServiceProvider:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>
Now let's insert a debug line in the computeHash function to confirm that the algorithm was remapped correctly and then run the application:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      Debug.WriteLine(hash.GetType());
      return hash.ComputeHash(buffer);
   }
}
The debug output from this method is:
System.Security.Cryptography.SHA1CryptoServiceProvider
What happened? Didn't we remap SHA1 to SHA-512? Actually, no, we didn't. We remapped only the string "SHA1" to the class SHA512CryptoServiceProvider, and we did not pass the string "SHA1" as a parameter to the call to HashAlgorithm.Create.
Even though Create appears to have no string parameters to remap, it is still possible to change the type of object that is created. You can do this because HashAlgorithm.Create() is just shortcut syntax for HashAlgorithm.Create("System.Security.Cryptography.HashAlgorithm"). Now let's add another line to the machine.config file to remap "System.Security.Cryptography.HashAlgorithm" to SHA512CryptoServiceProvider and then run the app again:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>
<nameEntry name="System.Security.Cryptography.HashAlgorithm" class="MyPreferredHash"/>
The debug output from computeHash is now exactly what we expected:
System.Security.Cryptography.SHA512CryptoServiceProvider
However, remember that remapping classes in this way can create unexpected and difficult-to-debug compatibility issues. It's preferable to use application-specific friendly names that can be remapped with less chance of causing problems.

Another Benefit of Crypto Agility
In addition to letting you replace broken algorithms on the fly without having to recompile, crypto agility can be used to improve performance. If you've ever looked at the System.Security.Cryptography namespace, you might have noticed that often several different implementation classes exist for a given algorithm. For example, there are three different implementations of SHA-512: SHA512Cng, SHA512CryptoServiceProvider, and SHA512Managed.
Of these classes, SHA512Cng usually offers the best performance. A quick test on my laptop (running Windows 7 release candidate) shows that the –Cng classes in general are about 10 percent faster than the -CryptoServiceProvider and -Managed classes. My colleagues in the Core Architecture group inform me that in some circumstances the –Cng classes can actually run 10 times faster than the others!
Clearly, using the –Cng classes is preferable, and we could set up our machine.config file to remap algorithm implementations to use those classes, but the -Cng classes are not available on every operating system. Only Windows Vista, Windows Server 2008, and Windows 7 (and later versions, presumably) support –Cng. Trying to instantiate a –Cng class on any other operating system will throw an exception.
Similarly, the –Managed family of crypto classes (AesManaged, RijndaelManaged, SHA256Managed, and so on) are not always available, but for a completely different reason. The Federal Information Processing Standard 140 (FIPS) specifies standards for cryptographic algorithms and implementations. As of this writing, both the –Cng and –CryptoServiceProvider implementation classes are FIPS-certified, but –Managed classes are not. Furthermore, you can configure a Group Policy setting that allows only FIPS-compliant algorithms to be used. Some U.S. and Canadian government agencies mandate this policy setting. If you'd like to check your machine, open the Local Group Policy Editor (gpedit.msc), navigate to the Computer Configuration/Windows Settings/Security Settings/Local Policies/Security Options node, and check the value of the setting "System Cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing". If this policy is set to Enabled, attempting to instantiate a –Managed class on that machine will throw an exception.
This leaves the –CryptoServiceProvider family of classes as the lowest common denominator guaranteed to work on all platforms, but these classes also generally have the worst performance. You can overcome this problem by implementing one of the three crypto-agility syntaxes mentioned earlier in this article and customizing the machine.config file remapping for deployed machines based on their operating system and settings. For machines running Windows Vista or later, we can remap the machine.config to prefer the –Cng implementation classes:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Cng, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
For machines running operating systems earlier than Windows Vista with FIPS compliance disabled, we can remap machine.config to prefer the –Managed classes:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Managed"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
For all other machines, we remap to the –CryptoServiceProvider classes:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
Any call to HashAlgorithm.Create("MyApplicationHash") now creates the highest-performing implementation class available for that machine. Furthermore, since the algorithms are identical, you don't need to worry about compatibility or interoperability issues. A hash created for a given input value on one machine will be the same as a hash created for that same input value on another machine, even if the implementation classes are different. This holds true for the other algorithm types as well: you can encrypt an input on one machine by using AesManaged and decrypt it successfully on a different machine by using AesCryptoServiceProvider.

Wrapping Up
Given the time and expense of recoding your application in response to a broken cryptographic algorithm, not to mention the danger to your users until you can get a new version deployed, it is wise to plan for this occurrence and write your application in a cryptographically agile fashion. The fact that you can also obtain a performance benefit from coding this way is icing on the cake.
Never hardcode specific algorithms or implementations of those algorithms into your application. Always declare cryptographic algorithms as one of the following abstract algorithm type classes: HashAlgorithm, SymmetricAlgorithm, AsymmetricAlgorithm, KeyedHashAlgorithm, or HMAC.
I believe that an FxCop rule that would verify cryptographic agility would be extremely useful. If someone writes such a rule and posts it to Codeplex or another public code repository, I will be more than happy to give them full credit in this space and on the SDL blog.
Finally, I would like to acknowledge Shawn Hernan from the SQL Server security team and Shawn Farkas from the CLR security team for their expert feedback and help in producing this article.
Send your questions and comments to briefs@microsoft.com.

Bryan Sullivan is a security program manager for the Microsoft Security Development Lifecycle team, specializing in Web application security issues. He is the author of Ajax Security (Addison-Wesley, 2007).

Security Briefs
Kryptografische Flexibilität
Bryan Sullivan
Gesamten Verlauf haben Personen verschiedene Formen der Chiffre verwendet, um Informationen aus Ihren Gegner zu verbergen. Julius Cäsar verwendet eine drei direkte UMSCHALT-Verschlüsselung (des Buchstabens A in D, B konvertiert wird, auf E-Mail konvertiert wird), kämpfen Pläne zu kommunizieren. Während World Krieg II deutsche Navy verwendet eine wesentlich komplexere System – Enigma Computer – zum Verschlüsseln von Nachrichten an Ihre U-Boote gesendet. Heute verwenden wir auch anspruchsvollere Verschlüsselungsmechanismen als Teil der Infrastruktur öffentlicher Schlüssel, der uns die sichere Transaktionen auf das Internet durchführen kann.
Aber für solange Kryptographen geheimen Codes vorgenommen haben, Cryptanalysts versucht haben, Sie unterbrechen und stehlen von Informationen und manchmal im Code Worttrennmodule erfolgreich. Kryptografische Algorithmen einmal als sicher sind unterbrochen und nutzlos gerendert. Manchmal schwierigen Mängel befinden sich in die Algorithmen, und manchmal ist es einfach eine Frage der Angreifer Zugriff auf mehr Rechenleistung Brute-Force-Angriffe durchführen.
Vor kurzem haben Sicherheitsforscher Schwächen in den MD5-Hashalgorithmus als Ergebnis des Kollisionen; demonstriertSie haben, angezeigt, dass die beiden Nachrichten gleichen berechneten MD5-Hashwert aufweisen können. Sie haben einen Prüfung des Konzepts Angriff diese Schwachstelle, die an der public Key Infrastructures, die e-Commerce-Transaktionen im Web schützen gerichtet sind, erstellt. Durch Erwerb eines speziell gestalteten Website-Zertifikats von einer Zertifizierungsstelle (CA), die MD5, verwendet um Ihre Zertifikate signieren, konnten die Forscher ein Rogue-Zertifizierungsstellenzertifikat erstellen, die effektiv verwendet werden konnte, um potenziell jeder Site im Internet zu imitieren. Diese abgeschlossen, MD5 nicht für digitale Zertifikate Signieren geeignet ist und, dass eine stärkere Alternative, z. B. die SHA-2-Algorithmen verwendet werden soll. (Wenn Sie mehr über diese Recherche interessiert sind, können Sie das Whitepaper-von lesen.)
Diese Ergebnisse werden sicherlich für Problem verursachen, aber Sie sind keine riesige Überraschung. Theoretische MD5 Schwachstellen für Jahre demonstriert haben, und die Verwendung von MD5 im Microsoft-Produkte wurde durch das Microsoft SDL kryptografischen Standards seit 2005 gesperrt wurde. Andere Algorithmen einmal beliebten wie SHA-1 und RC2, haben ebenso gesperrt wurde. Abbildung 1 zeigt eine vollständige Liste der kryptografischen Algorithmen gesperrt oder von der SDL genehmigt. Die Liste der SDL genehmigte Algorithmen ist als des Verfassens dieses Artikels aktuelle, aber dieser Liste überprüft und jährlich als Teil des SDL Update aktualisiert.
Abbildung 1 Kryptografiealgorithmen SDL genehmigt
Algorithmus-Typ Gesperrt (Algorithmen, die in vorhandenen Code ersetzt oder nur für die Entschlüsselung verwendet werden) Akzeptabel (Algorithmen für vorhandenen Code außer vertrauliche Daten zulässig) Empfohlene (Algorithmen für neuen Code)
Symmetrische blockieren DES, DESX, RC2, SKIPJACK 3DES (2 oder 3-Schlüssel) AES (> = 128 Bit)
Symmetrische Stream VERSIEGELN, CYLINK_MEK, RC4 (< 128-Bit) RC4 (> = 128 Bit) Keine, Blockverschlüsselung bevorzugte ist
Asymmetrische RSA (< 2048-Bit), Diffie-Hellman-(< 2048-Bit) RSA (> = 2048bit), Diffie-Hellman-(> = 2048bit) RSA (> = 2048bit), Diffie-Hellman-(> = 2048bit), ECC (> = 256 Bit)
Hash (einschließlich HMAC-Verwendung) SHA-0 (SHA), SHA-1, MD2, MD4, MD5 SHA-2 SHA-2 (enthält: SHA-256, SHA-384 UND SHA-512)
Längen der HMAC-Schlüssel < 112 Bit > = 112 Bit > = 128-Bit
Auch wenn Sie diese Standards in Ihrem eigenen Code folgen, ist nur die sichersten Algorithmen und die längsten Schlüssellängen keine Garantie dafür, dass der heute geschriebenen Code sicher bleiben. In der Tat bleibt wahrscheinlich nicht es sicher, wenn Verlauf jeder Führungslinie ist.

Planung für zukünftige nutzt
Sie können dieses unangenehmen Szenario reaktiv adressieren, indem über der alten AnwendungenCode basieren, Kommissionierliste, Instanziierungen von gefährdeten Algorithmen, ersetzen neue Algorithmen, Neuerstellen der Anwendungen, über Regressionstests ausführen und dann Patches oder Servicepacks für Ihre Benutzer ausgeben. Dies ist nicht nur viel Arbeit für Sie, aber es weiterhin Ihre Benutzer gefährdet bleibt, bis Sie die Updates geliefert bekommen.
Eine bessere Alternative besteht darin zu für dieses Szenario vom Anfang zu planen. Statt bestimmte kryptografische Algorithmen in Ihrem Code fest zu programmieren, verwenden Sie eine der in Microsoft .NET Framework integrierten Funktionen für kryptografische Flexibilität. Betrachten wir nun ein paar C#-Codeausschnitten, beginnend mit mindestens agile Beispiel:
private static byte[] computeHash(byte[] buffer)
{
   using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
   {
      return md5.ComputeHash(buffer);
   }
}
Dieser Code ist vollständig nonagile. Es ist an einen bestimmten Algorithmus (MD5) sowie einer bestimmten Implementierung der Algorithmus, der MD5CryptoServiceProvider-Klasse gebunden. Ändern dieser Anwendung mit einen sicheren Hashalgorithmus müsste Code ändern und einen Patch ausstellen. Hier ist ein wenig besseres Beispiel:
private static byte[] computeHash(byte[] buffer)
{
   string md5Impl = ConfigurationManager.AppSettings["md5Impl"];
   if (md5Impl == null)
      md5Impl = String.Empty;

   using (MD5 md5 = MD5.Create(md5Impl))
   {
      return md5.ComputeHash(buffer);
   }
}
Diese Funktion verwendet die System.Configuration.Configuration Manager-Klasse um eine benutzerdefinierte Anwendung-Einstellung (die "md5Impl" Abrufenfestlegen) aus der Konfigurationsdatei der Anwendung. In diesem Fall ist die Einstellung verwendet, um der starke Name der Implementierungsklasse Algorithmus zu speichern, Sie verwenden möchten. Der Code übergibt den abgerufenen Wert dieser Einstellung an die statische Funktion MD5.Create zum Erstellen einer Instanz der gewünschten Klasse. (System.Security.Cryptography.MD5 ist eine abstrakte Basisklasse, von der alle, die Implementierungen der MD5-Algorithmus abgeleitet werden muss.) Beispielsweise, wenn die Anwendungseinstellung der für md5Impl auf die Zeichenfolge festgelegt wurde "System.Security.Cryptography.MD5Cng System.Core, Version = 3.5.0.0, Culture = Neutral, PublicKeyToken = b77a5c561934e089", MD5.Create würde eine Instanz der MD5Cng-Klasse erstellen.
Dieser Ansatz löst nur die Hälfte der unsere Problem Crypto-Flexibilität, daher ist es wirklich keine Lösung überhaupt. Wir können nun eine Implementierung von MD5-Algorithmus angeben, ohne jeden Quellcode ändern, die nützlich erweisen kann, wenn ein Fehler, in einer bestimmten Implementierung wie MD5Cng erkannt wird, aber wir die Verwendung von MD5 weiterhin im Allgemeinen gebunden sind. Um dieses Problem zu lösen, behalten wir nach oben Abstraktion:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MD5"))
   {
      return hash.ComputeHash(buffer);
   }
}
Sieht auf den ersten Blick nicht dieser Codeausschnitt erheblich unterscheidet das erste Beispiel aus. Anscheinend möchten wir noch einmal den MD5-Algorithmus in der Anwendung über den Aufruf von HashAlgorithm.Create("MD5") hartcodiert haben. Erstaunlich Obwohl dieser Code erheblich mehr kryptografisch agile als beide die anderen Beispiele ist. Während das standardmäßige Verhalten der Methode rufen Sie HashAlgorithm.Create ("MD5") – als von .NET 3.5 – ist die Erstellung eine Instanz der MD5CryptoServiceProvider-Klasse das Laufzeitverhalten durch eine Änderung der Datei machine.config angepasst werden kann.
Das Verhalten der dieser Code eine Instanz der SHA512algorithm anstelle von MD5 erstellen wir ändern. Zu diesem Zweck müssen wir zwei Elemente in der Datei machine.config hinzufügen: CryptoClass <->Element der Algorithmus Implementierungsklasse einem angezeigten Algorithmusnamen zugeordnet werden soll;und < NameEntry >Element, das der neue angezeigte Name der alte, veraltete Algorithmus angezeigte Namen zuzuordnen.
<configuration>
  <mscorlib>
    <cryptographySettings>
      <cryptoNameMapping>
        <cryptoClasses>
          <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
          	Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        </cryptoClasses>
        <nameEntry name="MD5" class="MyPreferredHash"/>
      </cryptoNameMapping>
    </cryptographySettings>
  </mscorlib>
</configuration>
Jetzt, wenn unser Code den Aufruf HashAlgorithm.Create("MD5") vornimmt, die CLR sucht in der Datei machine.config und, sieht die Zeichenfolge "MD5"sollte die angezeigten Algorithmusnamen "MyPreferredHash" zuordnen. Anschließend sieht die "MyPreferredHash"ist die SHA512CryptoServiceProvider-Klasse (wie in der Assembly System.Core, mit der angegebenen Version, Kultur und öffentliches Schlüsseltoken definiert) zugeordnet, und erstellt eine Instanz der Klasse.
Es ist wichtig zu beachten, dass der Algorithmus Neuzuordnung nicht am Kompilierzeit aber zur Laufzeit stattfindet: Es ist Datei machine.config des Benutzers, der steuert die Neuzuordnung, nicht des Entwicklers. Demzufolge löst dieses Verfahren unsere Dilemma der an einen bestimmten Algorithmus, der zu einem Zeitpunkt in der Zukunft fehlerhafte möglicherweise gebunden wird. Durch hart codierte kryptografischen Algorithmus-Klasse in der Anwendung zu vermeiden, codieren stattdessen nur den abstrakten Typ der kryptografischen Algorithmus, HashAlgorithm, – wir erstellen eine Anwendung, in dem der Endbenutzer (genauer gesagt, eine Person mit Administratorrechten zum Bearbeiten der Datei machine.config-Datei auf dem Computer, in denen die Anwendung installiert) feststellen können, genau welche Algorithmus und die Implementierung die Anwendung verwendet. Ein Administrator möglicherweise auswählen, um einen Algorithmus zu ersetzen, der mit einem noch als sicher vor kurzem aufgelöst wurde (z. B. MD5 mit SHA-256 ersetzen) oder um einen sicheren Algorithmus durch Alternative mit einer längeren Bitlänge (ersetzen Sie SHA-256 mit SHA-512) proaktiv zu ersetzen.

Mögliche Probleme
Ändern der Datei machine.config die standardmäßige Algorithmustyp Zeichenfolgen (wie "MD5" neu zuordnenund "SHA1") möglicherweise Crypto Flexibilität Probleme behoben, aber Kompatibilitätsprobleme können zur gleichen Zeit erstellt. Änderungen an machine.config wirkt sich auf jede Anwendung .NET auf dem Computer. Andere Anwendungen auf dem Computer installiert möglicherweise basieren auf MD5 speziell, und ändern die von diesen Anwendungen verwendeten Algorithmen möglicherweise unterbrechen Sie auf unerwartete Weise, die nur schwer zu diagnostizieren sind. Als Alternative zu den gesamten Computer Rahmenauftrag Änderungen erzwungen ist es besser benutzerdefinierte, anwendungsspezifische Anzeigenamen im Code verwenden und bevorzugte Klassen in der Datei machine.config-Einträgen Namen zuordnen. Beispielsweise können wir "MD5" ändern.zu "MyApplicationHash"in unserem Beispiel:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}
Wir dann Hinzufügen eines Eintrags zur der Datei machine.config zuordnen "MyApplicationHash"Um die "MyPreferredHash"Klasse:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
Sie können auch mehrere Anzeigenamen auf dieselbe Klasse; zuordnenSie könnte z. B. einen angezeigten Namen für jede Ihrer Anwendungen haben und auf diese Weise das Verhalten bestimmter Anwendungen ändern, ohne jede andere Anwendung auf dem Computer:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, 
     System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
<nameEntry name="MyApplication2Hash" class="MyPreferredHash"/>
<nameEntry name="MyApplication3Hash" class="MyPreferredHash"/>

Allerdings können wir noch nicht außerhalb des Woods in Bezug auf Kompatibilitätsprobleme in eigenen Anwendungen. Sie müssen bezüglich Speichergröße für lokale Variablen (vorübergehende Speicherung) und Datenbank und XML-Schemas (permanenten Speicher) im Voraus planen. MD5-Hashwerte sind z. B. immer 128 Bits lang. Wenn Sie genau 128 Bits in Ihrem Code oder im Schema-Hashausgabe als Ergebnis speichern Budgetieren, Sie werden keine Aktualisierung auf SHA-256 (256 Bit Länge Ausgabe) oder SHA-512 (512 Bit Länge Ausgabe).
Gar nicht wieder aufhören Dies können die Frage, wie viel Speicher ausreichend ist. Ist 512 Bits genug, oder sollten Sie 1.024 oder 2.048 verwenden? Ich kann keine Festplatte Regel hier bieten, da jede Anwendung verfügt über unterschiedliche Anforderungen, jedoch als eine Faustregel Sie Budget zweimal sollten wie viel Speicherplatz für hashes, wie Sie derzeit verwenden. Für symmetrische und asymmetrische-verschlüsselt Daten können Sie eine zusätzliche 10 Prozent des Speicherplatzes höchstens reservieren. Es ist unwahrscheinlich, dass neue Algorithmen mit Ausgabe Größe erheblich größer als vorhandene Algorithmen weit akzeptiert werden.
Anwendungen, die Hashwerte oder verschlüsselte Daten in einem persistenten Zustand (z. B. in einer Datenbank oder Datei) gespeichert haben jedoch größere Probleme als ausreichend Speicherplatz reservieren. Wenn Sie beibehalten von Daten mit einem Algorithmus und versuchen Sie dann auf die Daten später mithilfe eines anderen Algorithmus angewendet werden, erhalten nicht die Ergebnisse Sie, die Sie erwarten. Beispielsweise ist es ratsam, zum Speichern von Hashes Kennwörter anstatt vollständige Klartext-Versionen. Wenn der Benutzer versucht, sich anzumelden, kann der Code den Hash des Kennworts vom Benutzer mit dem gespeicherten Hash in der Datenbank bereitgestellten vergleichen. Wenn die Hashes übereinstimmen, ist der Benutzer authentifiziert. Wenn ein Hash wird in einem Format (z. B. MD5) gespeichert, und einer Anwendung aktualisieren, um einen anderen Algorithmus (z. B. SHA-256) zu verwenden, werden Benutzer nie anmelden, da der SHA-256-Hashwert der Kennwörter immer aus dem MD5-Hashwert, der die gleichen Kennwörter abweichen wird.
Sie können um dieses Problem in einigen Fällen durch das Speichern des ursprünglichen Algorithmus als Metadaten zusammen mit den tatsächlichen Daten abrufen. Beim Betrieb auf gespeicherte Daten verwenden Sie dann die Flexibilität Methoden (oder Reflektion), um den ursprünglich verwendeten anstelle von den aktuellen Algorithmus Algorithmus instanziieren:
private static bool checkPassword(string password, byte[] storedHash,
   string storedHashAlgorithm)
{
   using (HashAlgorithm hash = HashAlgorithm.Create(storedHashAlgorithm))
   {
      byte[] newHash = 
         hash.ComputeHash(System.Text.Encoding.Default.GetBytes(password));
      if (newHash.Length != storedHash.Length)
         return false;
      for (int i = 0; i < newHash.Length; i++)
         if (newHash[i] != storedHash[i])
            return false;
      return true;
   }
}
Leider, wenn Sie zwei gespeicherten Hashwerte vergleichen müssen, müssen an mit den gleichen Algorithmus erstellt wurden. Es gibt einfach keine Möglichkeit, MD5-Hash zu einem SHA-256-Hash vergleichen und ermitteln, wenn Sie beide aus der gleichen ursprünglichen Daten erstellt wurden. Es ist keine gute Crypto Flexibilität Lösung für dieses Problem, und der beste Rat ich anbieten kann, dass Sie den sichersten derzeit verfügbaren Algorithmus wählen und Entwickeln Sie einen aktualisieren Plan Fall Algorithmus später fehlerhaft ist. Crypto Flexibilität ist im Allgemeinen besser flüchtige Daten als für persistente Daten zu arbeiten.

Alternative Verwendung und Syntax
Vorausgesetzt, dass der Anwendungsentwurf die Verwendung von Kryptografie Flexibilität ermöglicht, fahren Sie einige alternative verwendet und die Syntax für diese Technik anzusehen. Wir haben fast vollständig auf kryptografische Hashalgorithmen zu diesem Zeitpunkt im Artikel konzentriert, aber Crypto Flexibilität funktioniert auch für andere Typen kryptografischen Algorithmus. Nur rufen Sie die statische Create-Methode der entsprechenden abstrakten Basisklasse: SymmetricAlgorithm für symmetrischen (geheimen Schlüssel) Kryptografiealgorithmen wie z. B. AES;AsymmetricAlgorithm für asymmetrische (öffentliche Schlüssel) Kryptografiealgorithmen wie RSA;KeyedHashAlgorithm für verschlüsselte Hashwerte;und HMAC für Hash-based Message Authentication Codes.
Crypto Flexibilität können auch eine der standardmäßigen .NET kryptografischen Algorithmus Klassen mit einer benutzerdefinierten Algorithmus-Klasse, z. B. eines die Algorithmen von CLR-Sicherheitsteam entwickelt und auf CodePlex hochgeladen ersetzen. Schreiben eigene benutzerdefinierten Crypto Bibliotheken wird jedoch dringend abgeraten. Ihre homemade Algorithmus besteht aus einer ROT13 gefolgt von einer bitweisen Linksverschiebung und mag eine XOR gegen Ihre Katze namens sicher, aber es werden kleine Herausforderung, ein Experte Code Breaker darstellen. Wenn Sie ein Experte in Kryptografie sind, überlassen Sie den Algorithmus Entwurf der IT-Fachleute.
Auch Widerstehen Sie die Versuchung, Ihre eigenen Algorithmen entwickeln – oder um zu lange inaktiv zu beleben verdecken diejenigen wie Vigenère Cipher – auch in Situationen, in denen Sie kryptografisch starken Schutz benötigen. Das Problem ist nicht so viel Was Sie mit Ihrem Cipher, aber was Entwickler tun, kommen wird danach mit. Ein neuer Entwickler, die Ihre benutzerdefinierten Algorithmus-Klasse in den Code Basis Jahre später findet könnten beschließen, dass es ist nur was er für die neue Produktaktivierung muss Generierungslogik Schlüssel.
Bisher wir gesehen haben eine Syntax für die Implementierung kryptografisch agile Code, AlgorithmType.Create(algorithmName), aber zwei Ansätze integriert die .NET Framework. Die erste besteht darin, die System.Security.Cryptography.CryptoConfig-Klasse zu verwenden:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = (HashAlgorithm)CryptoConfig.CreateFromName("MyApplicationHash"))
   {
      return hash.ComputeHash(buffer);
   }
}
Dieser Code führt dieselben Operationen wie unserer vorherigen Beispiel mithilfe von HashAlgorithm.Create("MyApplicationHash"): Die CLR sucht in der Datei machine.config für eine Neuzuordnung der Zeichenfolge "MyApplicationHash"und der neu zugeordnete Algorithmus Klasse, wenn Sie eine findet verwendet. Beachten Sie, dass wir das Ergebnis von CryptoConfig.CreateFromName umgewandelt, da Sie einen Rückgabetyp von System.Object hat und kann zum Erstellen von SymmetricAlgorithms, AsymmetricAlgorithms oder andere Art von Objekt verwendet werden.
Die zweite alternative Syntax lautet zum Aufrufen der statischen Algorithmus erstellen-Methode in unserer ursprünglichen Beispiel jedoch ohne Parameter wie folgt:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      return hash.ComputeHash(buffer);
   }
}
In diesem Code fordern wir einfach das Framework zum Bereitstellen einer Instanz von jeweils die Hash-Algorithmus Standardimplementierung ist. Sie können die Liste der Standardwerte für die System.Security.Cryptography abstrakten Basisklassen (wie von .NET 3.5) finden Sie in Abbildung 2.
Abbildung 2 Standard Algorithmen und Implementierungen in .NET Framework 3.5
Abstrakte Basisklassen Standard-Algorithmus Standard-Implementierung
HashAlgorithm SHA-1 SHA1CryptoServiceProvider
SymmetricAlgorithm AES (Rijndael) RijndaelManaged
AsymmetricAlgorithm RSA RSACryptoServiceProvider
KeyedHashAlgorithm SHA-1 HMACSHA1
HMAC SHA-1 HMACSHA1
Für HashAlgorithm können Sie sehen, dass der Standardalgorithmus SHA-1 ist und die Standard-Implementierungsklasse SHA1CryptoServiceProvider. Allerdings wissen wir, dass SHA-1 durch die kryptografische Standards SDL verboten ist. Für den Moment einfach die Tatsache, dass potenzielle Kompatibilitätsprobleme im Allgemeinen nicht ratsam, inhärenten Algorithmusnamen wie "SHA1" ordnen machen wir ignorierenund ändern Sie unsere machine.config "SHA1" neu zuordnenUm SHA512CryptoServiceProvider:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, Culture=neutral, 
     PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>
Nun fügen Sie eine Debug-Zeile nun in der ComputeHash-Funktion, um zu bestätigen, dass der Algorithmus ordnungsgemäß zugeordnet und Sie die Anwendung führen wurde:
private static byte[] computeHash(byte[] buffer)
{
   using (HashAlgorithm hash = HashAlgorithm.Create())
   {
      Debug.WriteLine(hash.GetType());
      return hash.ComputeHash(buffer);
   }
}
Die Debugausgabe von dieser Methode lautet:
System.Security.Cryptography.SHA1CryptoServiceProvider
Was ist passiert? Haben wir SHA1, SHA-512 zuordnen? Tatsächlich hat Nein, wir. Wir nur die Zeichenfolge "SHA1" zugeordnetDie Klasse SHA512CryptoServiceProvider und wir nicht die Zeichenfolge übergeben "SHA1"als Parameter zum Aufruf von HashAlgorithm.Create.
Obwohl erstellen wird angezeigt, keine Zeichenfolgenparameter neu zuordnen, ist es dennoch möglich, den Typ des Objekts zu ändern, die erstellt wird. Dies ist möglich, da HashAlgorithm.Create() nur Verknüpfung Syntax für HashAlgorithm.Create("System.Security.Cryptography.HashAlgorithm") ist. Nun fügen Sie nun eine andere Zeile in die machine.config-Datei "System.Security.Cryptography.HashAlgorithm" neu zuordnenSHA512CryptoServiceProvider und führen Sie dann die Anwendung erneut:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="SHA1" class="MyPreferredHash"/>
<nameEntry name="System.Security.Cryptography.HashAlgorithm" class="MyPreferredHash"/>
Die Debugausgabe aus ComputeHash ist jetzt genau wie wir erwartet:
System.Security.Cryptography.SHA512CryptoServiceProvider
Beachten Sie jedoch, dass Klassen auf diese Weise Neuzuordnung unerwartete und schwierig zu debuggen Kompatibilitätsprobleme erstellen kann. Es ist vorzuziehen, verwenden anwendungsspezifische Anzeigenamen, die zugeordnet werden können mit weniger Wahrscheinlichkeit Probleme verursacht.

Ein anderer Vorteil der Crypto Flexibilität
Zusätzlich zu dem Sie die fehlerhafte Algorithmen zur Laufzeit zu ersetzen, ohne neu kompilieren zu müssen, kann Crypto Flexibilität verwendet werden, um die Leistung zu verbessern. Wenn jemals System.Security.Cryptography-Namespace ansehen haben, möglicherweise haben Sie bemerkt, dass häufig mehrere andere Implementierungsklassen für einen bestimmten Algorithmus vorhanden sind. Es sind z. B. drei unterschiedliche Implementierungen des SHA-512: SHA512Cng, SHA512CryptoServiceProvider und SHA512Managed.
Diese Klassen bietet SHA512Cng in der Regel die beste Leistung. Ein Schnelltest auf meinem Laptop (unter Windows 7 Release Candidate) zeigt, dass die –Cng-Klassen im Allgemeinen über 10 Prozent schneller als auf-CryptoServiceProvider sind und - verwaltete Klassen. Meine Kollegen in der Gruppe Core-Architektur informiert mich, in einigen Fällen die –Cng-Klassen die tatsächlich zehnmal schneller als die anderen ausgeführt werden können!
Natürlich mithilfe der –Cng-Klassen ist vorzuziehen, und wir konnte richten Sie unsere Datei machine.config Algorithmusimplementierungen diese Klassen verwenden neu zuordnen, aber -Cng Klassen sind nicht in jedem Betriebssystem verfügbar. Nur Windows Vista, Windows Server 2008 und Windows 7 (und späteren Versionen vermutlich) –Cng unterstützt. Eine –Cng-Klasse unter jedem anderen Betriebssystem zu instanziieren versucht, wird eine Ausnahme ausgelöst.
Ebenso sind die Produktfamilie die Krypto-Klassen (AesManaged, RijndaelManaged, SHA256Managed und usw.) –Managed nicht immer verfügbar, jedoch einem völlig anderen Grund. Die FIPS Federal Information Processing Standard 140 () gibt die Standards für die kryptografische Algorithmen und Implementierungen an. Als des Verfassens dieses Artikels Implementierungsklassen der –Cng und –CryptoServiceProvider sind FIPS-zertifizierten, aber –Managed Klassen sind nicht. Darüber hinaus können Sie eine Gruppenrichtlinieneinstellung konfigurieren, die nur FIPS-konforme Algorithmen verwendet werden können. Einige US und Kanadische Regierungsbehörden Einzugsermächtigung mit dieser Richtlinieneinstellung wird. Wenn Sie Ihren Computer überprüfen, Öffnen der lokalen Gruppenrichtlinien-Editor (gpedit.msc), navigieren Sie zu den Knoten Computerkonfiguration/Windows-Einstellungen/Sicherheitseinstellungen/Lokale Richtlinien/Sicherheitsoptionen, und überprüfen den Wert der Einstellung der "Systemkryptografie: Verwenden Sie FIPS-konformen Algorithmus für Verschlüsselung, hashing und Signatur". Wenn diese Richtlinie auf aktiviert festgelegt ist, wird eine –Managed-Klasse auf dem Computer zu instanziieren versucht, eine Ausnahme ausgelöst.
Dadurch –CryptoServiceProvider Familie der Klassen als den kleinsten gemeinsamen Nenner gewährleistet, dass auf allen Plattformen lauffähig, aber diese Klassen haben auch im Allgemeinen der schlechtesten Leistung. Sie können dieses Problem umgehen, durch Implementieren eines der drei Crypto Flexibilität Syntax im zuvor erwähnten diese Artikel und Anpassen von machine.config Datei Neuzuordnung für Computer basierend auf Ihrem Betriebssystem und Einstellungen bereitgestellt. Für Computer Windows Vista oder höher, können wir der Datei machine.config bevorzugt, die –Cng Implementierungsklassen zuordnen:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Cng, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
Für Computer unter Betriebssystemen vor Windows Vista mit FIPS-Konformität deaktiviert können wir machine.config bevorzugt, die –Managed-Klassen zuordnen:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512Managed"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
Für alle anderen Computer ordnen wir die –CryptoServiceProvider-Klassen:
<cryptoClasses>
   <cryptoClass MyPreferredHash="SHA512CryptoServiceProvider, System.Core, Version=3.5.0.0, 
     Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</cryptoClasses>
<nameEntry name="MyApplicationHash" class="MyPreferredHash"/>
Jeder Aufruf von HashAlgorithm.Create("MyApplicationHash") erstellt jetzt die höchste durchführen Implementierungsklasse für diesen Computer zur Verfügung. Darüber hinaus, da die Algorithmen identisch sind, müssen Sie Kompatibilitäts- oder Interoperabilitätsprobleme kümmern. Ein Hashwert für einen bestimmten Eingabewert auf einem Computer erstellt wird von einen Hash für die gleichen Eingabewert auf einem anderen Computer erstellt identisch sein, auch wenn die Implementierungsklassen unterscheiden. Dies gilt für die anderen Algorithmus Typen sowie: können Sie eine Eingabe auf einem Computer mithilfe von AesManaged zu verschlüsseln und Entschlüsseln erfolgreich auf einem anderen Computer mithilfe von AesCryptoServiceProvider.

Zusammenfassung
Die Zeit und Kosten für die Aufzeichnung Ihrer Anwendung in Reaktion auf eine fehlerhafte kryptografischen Algorithmus ganz zu schweigen die Gefahr für Ihre Benutzer, bis Sie eine neue Version bereitgestellt, können ist es ratsam, zum Planen dieses Serienelement und Ihre Anwendung in einer kryptografisch agile Weise schreiben. Die Tatsache, dass Sie auch eine Leistungsverbesserung erhalten können, von Code auf diese Weise wird auf den Kuchen icing.
Niemals hartcodieren Algorithmen oder Implementierungen dieser Algorithmen in Ihre Anwendung. Deklarieren Sie immer kryptografische Algorithmen als eines der folgenden abstrakten Algorithmus Typ-Klassen: HashAlgorithm, SymmetricAlgorithm, AsymmetricAlgorithm, KeyedHashAlgorithm oder HMAC.
Ich glaube, dass eine FxCop-Regel, die kryptografische Flexibilität bestätigen möchten äußerst nützlich wäre. Wenn jemand eine solche Regel schreibt und CodePlex oder einem anderen öffentlichen Code Repository bucht, werden ich mehr als zufrieden, um Ihnen vollständige Gutschrift in hier und auf das in der SDL Blog von verleihen.
Schließlich möchte ich bestätigen Shawn Hernan vom SQL Server Security-Team und Shawn Farkas vom CLR Security Team für Ihr Experte Feedback und Hilfe in erzeugt in diesem Artikel.
Senden Sie Ihre Fragen und Kommentare zu briefs@microsoft.com.

Bryan Sullivan ist eine Security Programmmanager für das Microsoft Security Development Lifecycle-Team Web-Anwendung Sicherheitsprobleme spezialisiert. Er ist Autor von AJAX Security (Addison-Wesley, 2007).

Page view tracker