This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Security 6.4.1!

Spring Security Crypto Module

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.

Encryptors

The Encryptors class provides factory methods for constructing symmetric encryptors. This class lets you create BytesEncryptor instances to encrypt data in raw byte[] form. You can also construct TextEncryptor instances to encrypt text strings. Encryptors are thread-safe.

Both BytesEncryptor and TextEncryptor are interfaces. BytesEncryptor has multiple implementations.

BytesEncryptor

You can use the Encryptors.stronger factory method to construct a BytesEncryptor:

BytesEncryptor
  • Java

  • Kotlin

Encryptors.stronger("password", "salt");
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

  • Kotlin

String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
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 authenticated and does not provide any guarantees about the authenticity of the data. For a more secure alternative, use Encryptors.stronger.

TextEncryptor

You can use the Encryptors.text factory method to construct a standard TextEncryptor:

TextEncryptor
  • Java

  • Kotlin

Encryptors.text("password", "salt");
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.

Key Generators

The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators. By using this class, you can create a BytesKeyGenerator to generate byte[] keys. You can also construct a 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

  • Kotlin

BytesKeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();
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

  • Kotlin

KeyGenerators.secureRandom(16);
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

  • Kotlin

KeyGenerators.shared(16);
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

  • Kotlin

KeyGenerators.string();
KeyGenerators.string()

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:

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, 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

  • Kotlin

// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// 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

  • Kotlin

// Create an encoder with all the defaults
Pbkdf2PasswordEncoder encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Create an encoder with all the defaults
val encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))