| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 | 
							- [[crypto]]
 
- = Spring Security Crypto Module
 
- [[spring-security-crypto-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 {security-api-url}org/springframework/security/crypto/encrypt/Encryptors.html[`Encryptors`] class provides factory methods for constructing symmetric encryptors.
 
- This class lets you create {security-api-url}org/springframework/security/crypto/encrypt/BytesEncryptor.html[`BytesEncryptor`] instances to encrypt data in raw `byte[]` form.
 
- You can also construct {security-api-url}org/springframework/security/crypto/encrypt/TextEncryptor.html[TextEncryptor] instances to encrypt text strings.
 
- Encryptors are thread-safe.
 
- [NOTE]
 
- ====
 
- Both `BytesEncryptor` and `TextEncryptor` are interfaces. `BytesEncryptor` has multiple implementations.
 
- ====
 
- [[spring-security-crypto-encryption-bytes]]
 
- === BytesEncryptor
 
- You can use the `Encryptors.stronger` factory method to construct a `BytesEncryptor`:
 
- .BytesEncryptor
 
- ====
 
- .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 by using 256-bit AES encryption with
 
- Galois Counter Mode (GCM).
 
- It derives the secret key by 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 should not be shared.
 
- The salt is used to prevent dictionary attacks against the key in the event that your encrypted data is compromised.
 
- A 16-byte random initialization vector is also applied so that 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.
 
- You can generate such a salt by using a `KeyGenerator`:
 
- .Generating a key
 
- ====
 
- .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
 
- ----
 
- ====
 
- You can 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, use `Encryptors.stronger`.
 
- [[spring-security-crypto-encryption-text]]
 
- === TextEncryptor
 
- You can use the `Encryptors.text` factory method to construct a standard TextEncryptor:
 
- .TextEncryptor
 
- ====
 
- .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 a database.
 
- You can use the `Encryptors.queryableText` factory method to construct a "`queryable`" `TextEncryptor`:
 
- .Queryable TextEncryptor
 
- ====
 
- .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 always produces 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 {security-api-url}org/springframework/security/crypto/keygen/KeyGenerators.html[`KeyGenerators`] class provides a number of convenience factory methods for constructing different types of key generators.
 
- By using this class, you can create a {security-api-url}org/springframework/security/crypto/keygen/BytesKeyGenerator.html[`BytesKeyGenerator`] to generate `byte[]` keys.
 
- You can also construct a {security-api-url}org/springframework/security/crypto/keygen/StringKeyGenerator.html`[StringKeyGenerator]` to generate string keys.
 
- `KeyGenerators` is a thread-safe class.
 
- === BytesKeyGenerator
 
- You can use the `KeyGenerators.secureRandom` factory methods to generate a `BytesKeyGenerator` backed by a `SecureRandom` instance:
 
- .BytesKeyGenerator
 
- ====
 
- .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.
 
- A `KeyGenerators.secureRandom` variant provides control over the key length:
 
- .KeyGenerators.secureRandom
 
- ====
 
- .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
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- KeyGenerators.shared(16);
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- KeyGenerators.shared(16)
 
- ----
 
- ====
 
- === StringKeyGenerator
 
- You can use the `KeyGenerators.string` factory method to construct an 8-byte, `SecureRandom` `KeyGenerator` that hex-encodes each key as a `String`:
 
- .StringKeyGenerator
 
- ====
 
- .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(String rawPassword);
 
- boolean matches(String rawPassword, String encodedPassword);
 
- }
 
- ----
 
- ====
 
- 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, to hinder password crackers.
 
- You can tune the amount of work it does by using the `strength` parameter, which takes a value 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.
 
- The following example uses the `BCryptPasswordEncoder`:
 
- .BCryptPasswordEncoder
 
- ====
 
- .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.
 
- 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.
 
- The following system uses the `Pbkdf2PasswordEncoder`:
 
- .Pbkdf2PasswordEncoder
 
- ====
 
- .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))
 
- ----
 
- ====
 
 
  |