123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- [[crypto]]
- = Spring Security Crypto Module
- [[spring-security-crypto-introduction]]
- == Introduction
- The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding.
- The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code.
- [[spring-security-crypto-encryption]]
- == Encryptors
- The Encryptors class provides factory methods for constructing symmetric encryptors.
- Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form.
- You can also construct TextEncryptors to encrypt text strings.
- Encryptors are thread-safe.
- [[spring-security-crypto-encryption-bytes]]
- === BytesEncryptor
- Use the `Encryptors.stronger` factory method to construct a BytesEncryptor:
- .BytesEncryptor
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- Encryptors.stronger("password", "salt");
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- Encryptors.stronger("password", "salt")
- ----
- ======
- The "stronger" encryption method creates an encryptor using 256 bit AES encryption with
- Galois Counter Mode (GCM).
- It derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
- This method requires Java 6.
- The password used to generate the SecretKey should be kept in a secure place and not be shared.
- The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised.
- A 16-byte random initialization vector is also applied so each encrypted message is unique.
- The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length.
- Such a salt may be generated using a KeyGenerator:
- .Generating a key
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- val salt = KeyGenerators.string().generateKey() // generates a random 8-byte salt that is then hex-encoded
- ----
- ======
- Users may also use the `standard` encryption method, which is 256-bit AES in Cipher Block Chaining (CBC) Mode.
- This mode is not https://en.wikipedia.org/wiki/Authenticated_encryption[authenticated] and does not provide any
- guarantees about the authenticity of the data.
- For a more secure alternative, users should prefer `Encryptors.stronger`.
- [[spring-security-crypto-encryption-text]]
- === TextEncryptor
- Use the Encryptors.text factory method to construct a standard TextEncryptor:
- .TextEncryptor
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- Encryptors.text("password", "salt");
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- Encryptors.text("password", "salt")
- ----
- ======
- A TextEncryptor uses a standard BytesEncryptor to encrypt text data.
- Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database.
- Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor:
- .Queryable TextEncryptor
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- Encryptors.queryableText("password", "salt");
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- Encryptors.queryableText("password", "salt")
- ----
- ======
- The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling.
- The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated.
- This means the same text encrypted multiple times will always produce the same encryption result.
- This is less secure, but necessary for encrypted data that needs to be queried against.
- An example of queryable encrypted text would be an OAuth apiKey.
- [[spring-security-crypto-keygenerators]]
- == Key Generators
- The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators.
- Using this class, you can create a BytesKeyGenerator to generate byte[] keys.
- You can also construct a StringKeyGenerator to generate string keys.
- KeyGenerators are thread-safe.
- === BytesKeyGenerator
- Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance:
- .BytesKeyGenerator
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- BytesKeyGenerator generator = KeyGenerators.secureRandom();
- byte[] key = generator.generateKey();
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- val generator = KeyGenerators.secureRandom()
- val key = generator.generateKey()
- ----
- ======
- The default key length is 8 bytes.
- There is also a KeyGenerators.secureRandom variant that provides control over the key length:
- .KeyGenerators.secureRandom
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- KeyGenerators.secureRandom(16);
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- KeyGenerators.secureRandom(16)
- ----
- ======
- Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation:
- .KeyGenerators.shared
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- KeyGenerators.shared(16);
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- KeyGenerators.shared(16)
- ----
- ======
- === StringKeyGenerator
- Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String:
- .StringKeyGenerator
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- KeyGenerators.string();
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- KeyGenerators.string()
- ----
- ======
- [[spring-security-crypto-passwordencoders]]
- == Password Encoding
- The password package of the spring-security-crypto module provides support for encoding passwords.
- `PasswordEncoder` is the central service interface and has the following signature:
- [source,java]
- ----
- public interface PasswordEncoder {
- String encode(CharSequence rawPassword);
- boolean matches(CharSequence rawPassword, String encodedPassword);
- default boolean upgradeEncoding(String encodedPassword) {
- return false;
- }
- }
- ----
- The matches method returns true if the rawPassword, once encoded, equals the encodedPassword.
- This method is designed to support password-based authentication schemes.
- The `BCryptPasswordEncoder` implementation uses the widely supported "bcrypt" algorithm to hash the passwords.
- Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to hinder password crackers.
- The amount of work it does can be tuned using the "strength" parameter which takes values from 4 to 31.
- The higher the value, the more work has to be done to calculate the hash.
- The default value is 10.
- You can change this value in your deployed system without affecting existing passwords, as the value is also stored in the encoded hash.
- .BCryptPasswordEncoder
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- // Create an encoder with strength 16
- BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
- String result = encoder.encode("myPassword");
- assertTrue(encoder.matches("myPassword", result));
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- // Create an encoder with strength 16
- val encoder = BCryptPasswordEncoder(16)
- val result: String = encoder.encode("myPassword")
- assertTrue(encoder.matches("myPassword", result))
- ----
- ======
- The `Pbkdf2PasswordEncoder` implementation uses PBKDF2 algorithm to hash the passwords.
- In order to defeat password cracking PBKDF2 is a deliberately slow algorithm and should be tuned to take about .5 seconds to verify a password on your system.
- .Pbkdf2PasswordEncoder
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- // Create an encoder with all the defaults
- Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
- String result = encoder.encode("myPassword");
- assertTrue(encoder.matches("myPassword", result));
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- // Create an encoder with all the defaults
- val encoder = Pbkdf2PasswordEncoder()
- val result: String = encoder.encode("myPassword")
- assertTrue(encoder.matches("myPassword", result))
- ----
- ======
|