Spring Security 加密模块

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

Spring Security Crypto 模块提供对对称加密、密钥生成和密码编码的支持。该代码作为核心模块的一部分发布,但与任何其他 Spring Security(或Spring)代码没有依赖关系。

加密器(Encryptor)

Encryptors 类提供了构建对称加密器的工厂方法。该类允许你创建 BytesEncryptor 实例,以原始 byte[] 形式加密数据。你也可以构建 TextEncryptor 实例来加密文本字符串。加密器是线程安全的。

BytesEncryptorTextEncryptor 都是接口。BytesEncryptor 有多个实现。

BytesEncryptor

你可以使用 Encryptors.stronger 工厂方法来构造一个 BytesEncryptor

BytesEncryptor
  • Java

  • Kotlin

Encryptors.stronger("password", "salt");
Encryptors.stronger("password", "salt")

stronger 加密方法通过使用256位AES加密和伽罗瓦计数模式(GCM)创建一个加密器。它通过使用PKCS #5的PBKDF2(基于密码的密钥衍生函数#2)来获得秘密密钥。这种方法需要Java 6。用于生成 SecretKey 的密码应该保存在一个安全的地方,不应该被共享。盐是用来防止在你的加密数据被破坏的情况下对密钥进行字典攻击。一个16字节的随机初始化向量也被应用,以便每个加密信息是唯一的。

提供的盐应该是十六进制编码的字符串形式,是随机的,并且至少有8个字节的长度。你可以通过使用 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

你也可以使用标准的加密方法,即256位AES的密码块链(CBC)模式。这种模式没有经过 认证,不提供任何关于数据真实性的保证。对于一个更安全的替代品,请使用 Encryptors.stronger

TextEncryptor

你可以使用 Encryptors.text 工厂方法来构建一个标准的 TextEncryptor

TextEncryptor
  • Java

  • Kotlin

Encryptors.text("password", "salt");
Encryptors.text("password", "salt")

TextEncryptor 使用一个标准的 BytesEncryptor 来加密文本数据。加密后的结果以十六进制编码的字符串形式返回,以便于存储在文件系统或数据库中。

Key 生成器(Generator)

KeyGenerators 类提供了许多方便的工厂方法,用于构造不同类型的密钥生成器。通过使用这个类,你可以创建一个 BytesKeyGenerator 来生成 byte[] key。你也可以构造一个 StringKeyGenerator 来生成字符串密钥。 KeyGenerators 是一个线程安全的类。

BytesKeyGenerator

你可以使用 KeyGenerators.secureRandom 工厂方法来生成一个由 SecureRandom 实例支持的 BytesKeyGenerator

BytesKeyGenerator
  • Java

  • Kotlin

BytesKeyGenerator generator = KeyGenerators.secureRandom();
byte[] key = generator.generateKey();
val generator = KeyGenerators.secureRandom()
val key = generator.generateKey()

默认的密钥长度是8字节。一个 KeyGenerators.secureRandom 的变体提供了对密钥长度的控制。

KeyGenerators.secureRandom
  • Java

  • Kotlin

KeyGenerators.secureRandom(16);
KeyGenerators.secureRandom(16)

使用 KeyGenerators.shared 工厂方法来构建一个 BytesKeyGenerator,在每次调用时总是返回相同的密钥。

KeyGenerators.shared
  • Java

  • Kotlin

KeyGenerators.shared(16);
KeyGenerators.shared(16)

StringKeyGenerator

你可以使用 KeyGenerators.string 工厂方法来构建一个8字节的 SecureRandom KeyGenerator,将每个密钥以十六进制编码为一个字符串。

StringKeyGenerator
  • Java

  • Kotlin

KeyGenerators.string();
KeyGenerators.string()

密码编码

spring-security-crypto 模块的 password 包提供对密码编码的支持。 PasswordEncoder 是中心服务接口,有以下签名。

public interface PasswordEncoder {
	String encode(CharSequence rawPassword);

	boolean matches(CharSequence rawPassword, String encodedPassword);

	default boolean upgradeEncoding(String encodedPassword) {
		return false;
	}
}

如果 rawPassword 一旦被编码,就等于 encodedPassword,则 matches 方法返回true。这个方法被设计用来支持基于密码的认证方案。

BCryptPasswordEncoder 的实现使用广泛支持的 “bcrypt” 算法对密码进行散列。Bcrypt使用一个随机的16字节的盐值,并且是一个故意的慢速算法,以阻碍密码破解者。你可以通过使用 strength 参数来调整它的工作量,该参数的值从4到31。该值越高,计算哈希值所需的工作量就越大。默认值是 10。你可以在你部署的系统中改变这个值而不影响现有的密码,因为这个值也存储在编码的哈希中。下面的例子使用 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))

Pbkdf2PasswordEncoder 的实现使用PBKDF2算法对密码进行散列。为了抵御密码破解,PBKDF2是一种特意设计的慢速算法,应该调整为在你的系统上验证一个密码需要0.5秒左右。下面的系统使用了 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))