Development Guide Table of Contents
To ensure that cryptography is safely used to protect the confidentiality and integrity of sensitive user data.
All.
DS5.18 Cryptographic key management
Initially confined to the realms of academia and the military, cryptography has become ubiquitous thanks to the Internet. Common every day uses of cryptography include mobile phones, passwords, SSL, smart cards, and DVDs. Cryptography has permeated everyday life, and is heavily used by many web applications.
Cryptography (or crypto) is one of the more advanced topics of information security, and one whose understanding requires the most schooling and experience. It is difficult to get right because there are many approaches to encryption, each with advantages and disadvantages that need to be thoroughly understood by web solution architects and developers. In addition, serious cryptography research is typically based in advanced mathematics and number theory, providing a serious barrier to entry.
The proper and accurate implementation of cryptography is extremely critical to its efficacy. A small mistake in configuration or coding will result in removing a large degree of the protection it affords and rending the crypto implementation useless against serious attacks.
A good understanding of crypto is required to be able to discern between solid products and snake oil. The inherent complexity of crypto makes it easy to fall for fantastic claims from vendors about their product. Typically, these are a breakthrough in cryptography or unbreakable or provide "military grade" security. If a vendor says "trust us, we have had experts look at this, chances are they weren't experts!
Cryptographic systems can provide one or more of the following four services. It is important to distinguish between these, as some algorithms are more suited to particular tasks, but not to others.
When analyzing your requirements and risks, you need to decide which of these four functions should be used to protect your data.
Using a cryptographic system, we can establish the identity of a remote user (or system). A typical example is the SSL certificate of a web server providing proof to the user that he or she is connected to the correct server.
The identity is not of the user, but of the cryptographic key of the user. Having a less secure key lowers the trust we can place on the identity.
The concept of non-repudiation is particularly important for financial or e-commerce applications. Often, cryptographic tools are required to prove that a unique user has made a transaction request. It must not be possible for the user to refute his or her actions.
For example, a customer may request a transfer of money from her account to be paid to another account. Later, she claims never to have made the request and demands the money be refunded to the account. If we have non-repudiation through cryptography, we can prove usually through digitally signing the transaction request, that the user authorized the transaction.
More commonly, the biggest concern will be to keep information private. Cryptographic systems were originally developed to function in this capacity. Whether it be passwords sent during a log on process, or storing confidential medical records in a database, encryption can assure that only users who have access to the appropriate key will get access to the data.
We can use cryptography to provide a means to ensure data is not viewed or altered during storage or transmission. Cryptographic hashes for example, can safeguard data by providing a secure checksum.
Various types of cryptographic systems exist that have different strengths and weaknesses. Typically, they are divided into two classes; those that are strong, but slow to run and those that are quick, but less secure. Most often a combination of the two approaches is used (e.g.: SSL), whereby we establish the connection with a secure algorithm, and then if successful, encrypt the actual transmission with the weaker, but much faster algorithm.
Symmetric Cryptography is the most traditional form of cryptography. In a symmetric cryptosystem, the involved parties share a common secret (password, pass phrase, or key). Data is encrypted and decrypted using the same key. These algorithms tend to be comparatively fast, but they cannot be used unless the involved parties have already exchanged keys. Any party possessing a specific key can create encrypted messages using that key as well as decrypt any messages encrypted with the key. In systems involving a number of users who each need to set up independent, secure communication channels symmetric cryptosystems can have practical limitations due to the requirement to securely distribute and manage large numbers of keys.
Common examples of symmetric algorithms are DES, 3DES and AES. The 56-bit keys used in DES are short enough to be easily brute-forced by modern hardware and DES should no longer be used. Triple DES (or 3DES) uses the same algorithm, applied three times with different keys giving it an effective key length of 112 bits (due to an attack that reduces the strength to the work that would be involved). Due to the problems using the DES algorithm, the United States National Institute of Standards and Technology (NIST) hosted a selection process for a new algorithm. The winning algorithm was Rijndael and the associated cryptosystem is now known as the Advanced Encryption Standard or AES. It is advisable to use AES, as DES is deprecated.
Asymmetric algorithms use two keys, one to encrypt the data, and either key to decrypt. These inter-dependent keys are generated together. One is labeled the Public key and is distributed freely. The other is labeled the Private Key and must be kept hidden.
Often referred to as Public/Private Key Cryptography, these cryptosystems can provide a number of different functions depending on how they are used.
The most common usage of asymmetric cryptography is to send messages with a guarantee of confidentiality. If User A wanted to send a message to User B, User A would get access to User Bs publicly-available Public Key. The message is then encrypted with this key and sent to User B. Because of the cryptosystems property that messages encoded with the Public Key of User B can only be decrypted with User Bs Private Key, only User B can read the message.
Another usage scenario is one where User A wants to send User B a message and wants User B to have a guarantee that the message was sent by User A. In order to accomplish this, User A would encrypt the message with their Private Key. The message can then only be decrypted using User As Public Key. This guarantees that User A created the message Because they are then only entity who had access to the Private Key required to create a message that can be decrcrypted by User As Public Key. This is essentially a digital signature guaranteeing that the message was created by User A.
A Certificate Authority (CA), whose public certificates are installed with browsers or otherwise commonly available, may also digitally sign public keys or certificates. We can authenticate remote systems or users via a mutual trust of an issuing CA. We trust their root certificates, which in turn authenticate the public certificate presented by the server.
PGP and SSL are prime examples of a systems implementing asymmetric cryptography, using RSA or other algorithms.
Hash functions take some data of an arbitrary length (and possibly a key or password) and generate a fixed-length hash based on this input. Hash functions used in cryptography have the property that it is easy to calculate the hash, but difficult or impossible to re-generate the original input if only the hash value is known. In addition, hash functions useful for cryptography have the property that it is difficult to craft an initial input such that the hash will match a specific desired value.
MD5 and SHA-1 are common hashing algorithms used today. These algorithms are considered weak (see below) and are likely to be replaced after a process similar to the AES selection. New applications should consider using SHA-256 instead of these weaker algorithms.
Lastly, we have key exchange algorithms (such as Diffie-Hellman for SSL). These allow use to safely exchange encryption keys with an unknown party.
As modern cryptography relies on being computationally expensive to break, specific standards can be set for key sizes that will provide assurance that with todays technology and understanding, it will take too long to decrypt a message by attempting all possible keys.
Therefore, we need to ensure that both the algorithm and the key size are taken into account when selecting an algorithm.
Proprietary encryption algorithms are not to be trusted as they typically rely on security through obscurity and not sound mathematics. These algorithms should be avoided if possible.
Specific algorithms to avoid:
Cryptography is a constantly changing field. As new discoveries in cryptanalysis are made, older algorithms will be found unsafe. In addition, as computing power increases the feasibility of brute force attacks will render other cryptosystems or the use of certain key lengths unsafe. Standard bodies such as NIST should be monitored for future recommendations.
Specific applications, such as banking transaction systems, may have specific requirements for algorithms and key sizes.
Assuming you have chosen an open, standard algorithm, the following recommendations should be considered when reviewing algorithms:
Symmetric:
Asymmetric:
The difficulty of cracking a 2048 bit key compared to a 1024 bit key is far, far, far, more than the twice you might expect. Dont use excessive key sizes unless you know you need them. Bruce Schneier in 2002 (see the references section) recommended the following key lengths for circa 2005 threats:
Hashes:
NIST and other standards bodies will provide up to date guidance on suggested key sizes.
Design your application to cope with new hashes and algorithms
As highlighted above, crypto relies on keys to assure a users identity, provide confidentiality and integrity as well as non-repudiation. It is vital that the keys are adequately protected. Should a key be compromised, it can no longer be trusted.
Any system that has been compromised in any way should have all its cryptographic keys replaced.
Unless you are using hardware cryptographic devices, your keys will most likely be stored as binary files on the system providing the encryption.
Can you export the private key or certificate from the store?
Storage of keys in hardware crypto devices is beyond the scope of this document. If you require this level of security, you should really be consulting with crypto specialists.
In security, we assess the level of trust we have in information. When applied to transmission of sensitive data, we need to ensure that encryption occurs before we transmit the data onto any untrusted network.
In practical terms, this means we should aim to encrypt as close to the source of the data as possible.
This can be extremely difficult without expert help. We can try to at least eliminate the most common problems:
We have the possibility to encrypt or otherwise protect data at different levels. Choosing the right place for this to occur can involve looking at both security as well as resource requirements.
Application: at this level, the actual application performs the encryption or other crypto function. This is the most desirable, but can place additional strain on resources and create unmanageable complexity. Encryption would be performed typically through an API such as the OpenSSL toolkit (www.openssl.com) or operating system provided crypto functions.
An example would be an S/MIME encrypted email, which is transmitted as encoded text within a standard email. No changes to intermediate email hosts are necessary to transmit the message because we do not require a change to the protocol itself.
Protocol: at this layer, the protocol provides the encryption service. Most commonly, this is seen in HTTPS, using SSL encryption to protect sensitive web traffic. The application no longer needs to implement secure connectivity. However, this does not mean the application has a free ride. SSL requires careful attention when used for mutual (client-side) authentication, as there are two different session keys, one for each direction. Each should be verified before transmitting sensitive data.
Attackers and penetration testers love SSL to hide malicious requests (such as injection attacks for example). Content scanners are most likely unable to decode the SSL connection, letting it pass to the vulnerable web server.
Network: below the protocol layer, we can use technologies such as Virtual Private Networks (VPN) to protect data. This has many incarnations, the most popular being IPsec (Internet Protocol v6 Security), typically implemented as a protected tunnel between two gateway routers. Neither the application nor the protocol needs to be crypto aware all traffic is encrypted regardless.
Possible issues at this level are computational and bandwidth overheads on network devices.
Todays web servers typically deal with large numbers of users. Differentiating between them is often done through cookies or other session identifiers. If these session identifiers use a predictable sequence, an attacker need only generate a value in the sequence in order to present a seemingly valid session token.
This can occur at a number of places; the network level for TCP sequence numbers, or right through to the application layer with cookies used as authenticating tokens.
Any deterministic sequence generator is likely to be vulnerable.
The only way to generate secure authentication tokens is to ensure there is no way to predict their sequence. In other words: true random numbers.
It could be argued that computers can not generate true random numbers, but using new techniques such as reading mouse movements and key strokes to improve entropy has significantly increased the randomness of random number generators. It is critical that you do not try to implement this on your own; use of existing, proven implementations is highly desirable.
Most operating systems include functions to generate random numbers that can be called from almost any programming language.
Windows & .NET: On Microsoft platforms including .NET, it is recommended to use the inbuilt CryptGenRandom function (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/cryptgenrandom.asp.
Unix: For all Unix based platforms, OpenSSL is an excellent option (http://www.openssl.org/). It features tools and API functions to generate random numbers. On some platforms, /dev/urandom is a suitable source of pseudo-random entropy.
PHP: mt_rand() uses a Mersenne Twister, but is nowhere near as good as CryptoAPIs secure random number generation options, OpenSSL, or /dev/urandom which is available on many Unix variants. mt_rand() has been noted to produce the same number on some platforms test prior to deployment. Do not use rand() as it is very weak.
Java: java.security.SecureRandom within the Java Cryptography Extension (JCE) provides secure random numbers. This should be used in preference to other random number generators.
ColdFusion: ColdFusion MX 7 leverages the JCE java.security.SecureRandom class of the underlying JVM as its pseudo random number generator (PRNG).
UUIDs (such as GUIDs and so on) are only unique if you generate them. This seems relatively straightforward. However, there are many code snippets available that contain existing UUIDS.
Cryptography is one of pillars of information security. Its usage and propagation has exploded due to the Internet and it is now included in most areas computing. Crypto can be used for:
A web application can implement cryptography at multiple layers: application, application server or runtime (such as .NET), operating system and hardware. Selecting an optimal approach requires a good understanding of application requirements, the areas of risk, and the level of security strength it might require, flexibility, cost, etc.
Although cryptography is not a panacea, the majority of security breaches do not come from brute force computation but from exploiting mistakes in implementation. The strength of a cryptographic system is measured in key length. Using a large key length and then storing the unprotected keys on the same server eliminates most of the protection benefit gained. Besides the secure storage of keys, another classic mistake is engineering custom cryptographic algorithms (to generate random session ids for example). Many web applications were successfully attacked because the developers thought they could create their crypto functions.
Our recommendation is to use proven products, tools, or packages rather than rolling your own.
http://eprint.iacr.org/2005/007.pdf
http://seclists.org/bugtraq/1999/Dec/208
http://www.schneier.com/crypto-gram-0204.html#3
http://www.schneier.com/crypto-gram.html
http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html
http://blogs.msdn.com/larryosterman/archive/2005/07/21/441417.aspx
http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
The following section describes ColdFusions cryptography features. ColdFusion MX leverages the Java Cryptography Extension (JCE) of the underlying J2EE platform for cryptography and random number generation. It provides functions for symmetric (or private-key) encryption. While it does not provide native functionality for public-key (asymmetric) encryption, it does use the Java Secure Socket Extension (JSSE) for SSL communication.
Pseudo-Random Number Generation
ColdFusion provides three functions for random number generation: rand(), randomize(), and randRange(). Function descriptions and syntax:
Rand Use to generate a pseudo-random number
rand([algorithm])
Randomize Use to seed the pseudo-random number generator (PRNG) with an integer.
randomize(number [, algorithm])
RandRange Use to generate a pseudo-random integer within the range of the specified numbers
randrange(number1, number2 [, algorithm])
The following values are the allowed algorithm parameters:
CFMX_COMPAT: (default) Invokes java.util.rand
SHA1PRNG: (recommended) Invokes java.security.SecureRandom using the Sun Java SHA-1 PRNG algorithm.
IBMSecureRandom: IBM WebSpheres JVM does not support the SHA1PRNG algorithm.
Symmetric Encryption
ColdFusion MX 7 provides six encryption functions: decrypt(), decryptBinary(), encrypt(), encryptBinary(), generateSecretKey(), and hash(). Function descriptions and syntax:
Decrypt Use to decrypt encrypted strings with specified key, algorithm, encoding, initialization vector or salt, and iterations
decrypt(encrypted_string, key[, algorithm[, encoding[, IVorSalt[, iterations]]]]))
DecryptBinary Use to decrypt encrypted binary data with specified key, algorithm, initialization vector or salt, and iterations
decryptBinary(bytes, key[, algorithm[, IVorSalt[, iterations]]])
Encrypt Use to encrypt string using specific algorithm, encoding, initialization vector or salt, and iterations
encrypt(string, key[, algorithm[, encoding[, IVorSalt[, iterations]]]]))
Read the original:
Guide to Cryptography - OWASP