cryptography.adoc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. [[crypto]]
  2. = Spring Security Crypto Module
  3. [[spring-security-crypto-introduction]]
  4. == Introduction
  5. The Spring Security Crypto module provides support for symmetric encryption, key generation, and password encoding.
  6. The code is distributed as part of the core module but has no dependencies on any other Spring Security (or Spring) code.
  7. [[spring-security-crypto-encryption]]
  8. == Encryptors
  9. The Encryptors class provides factory methods for constructing symmetric encryptors.
  10. Using this class, you can create ByteEncryptors to encrypt data in raw byte[] form.
  11. You can also construct TextEncryptors to encrypt text strings.
  12. Encryptors are thread-safe.
  13. [[spring-security-crypto-encryption-bytes]]
  14. === BytesEncryptor
  15. Use the `Encryptors.stronger` factory method to construct a BytesEncryptor:
  16. .BytesEncryptor
  17. [tabs]
  18. ======
  19. Java::
  20. +
  21. [source,java,role="primary"]
  22. ----
  23. Encryptors.stronger("password", "salt");
  24. ----
  25. Kotlin::
  26. +
  27. [source,kotlin,role="secondary"]
  28. ----
  29. Encryptors.stronger("password", "salt")
  30. ----
  31. ======
  32. The "stronger" encryption method creates an encryptor using 256 bit AES encryption with
  33. Galois Counter Mode (GCM).
  34. It derives the secret key using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2).
  35. This method requires Java 6.
  36. The password used to generate the SecretKey should be kept in a secure place and not be shared.
  37. The salt is used to prevent dictionary attacks against the key in the event your encrypted data is compromised.
  38. A 16-byte random initialization vector is also applied so each encrypted message is unique.
  39. The provided salt should be in hex-encoded String form, be random, and be at least 8 bytes in length.
  40. Such a salt may be generated using a KeyGenerator:
  41. .Generating a key
  42. [tabs]
  43. ======
  44. Java::
  45. +
  46. [source,java,role="primary"]
  47. ----
  48. String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded
  49. ----
  50. Kotlin::
  51. +
  52. [source,kotlin,role="secondary"]
  53. ----
  54. val salt = KeyGenerators.string().generateKey() // generates a random 8-byte salt that is then hex-encoded
  55. ----
  56. ======
  57. Users may also use the `standard` encryption method, which is 256-bit AES in Cipher Block Chaining (CBC) Mode.
  58. This mode is not https://en.wikipedia.org/wiki/Authenticated_encryption[authenticated] and does not provide any
  59. guarantees about the authenticity of the data.
  60. For a more secure alternative, users should prefer `Encryptors.stronger`.
  61. [[spring-security-crypto-encryption-text]]
  62. === TextEncryptor
  63. Use the Encryptors.text factory method to construct a standard TextEncryptor:
  64. .TextEncryptor
  65. [tabs]
  66. ======
  67. Java::
  68. +
  69. [source,java,role="primary"]
  70. ----
  71. Encryptors.text("password", "salt");
  72. ----
  73. Kotlin::
  74. +
  75. [source,kotlin,role="secondary"]
  76. ----
  77. Encryptors.text("password", "salt")
  78. ----
  79. ======
  80. A TextEncryptor uses a standard BytesEncryptor to encrypt text data.
  81. Encrypted results are returned as hex-encoded strings for easy storage on the filesystem or in the database.
  82. Use the Encryptors.queryableText factory method to construct a "queryable" TextEncryptor:
  83. .Queryable TextEncryptor
  84. [tabs]
  85. ======
  86. Java::
  87. +
  88. [source,java,role="primary"]
  89. ----
  90. Encryptors.queryableText("password", "salt");
  91. ----
  92. Kotlin::
  93. +
  94. [source,kotlin,role="secondary"]
  95. ----
  96. Encryptors.queryableText("password", "salt")
  97. ----
  98. ======
  99. The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling.
  100. The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated.
  101. This means the same text encrypted multiple times will always produce the same encryption result.
  102. This is less secure, but necessary for encrypted data that needs to be queried against.
  103. An example of queryable encrypted text would be an OAuth apiKey.
  104. [[spring-security-crypto-keygenerators]]
  105. == Key Generators
  106. The KeyGenerators class provides a number of convenience factory methods for constructing different types of key generators.
  107. Using this class, you can create a BytesKeyGenerator to generate byte[] keys.
  108. You can also construct a StringKeyGenerator to generate string keys.
  109. KeyGenerators are thread-safe.
  110. === BytesKeyGenerator
  111. Use the KeyGenerators.secureRandom factory methods to generate a BytesKeyGenerator backed by a SecureRandom instance:
  112. .BytesKeyGenerator
  113. [tabs]
  114. ======
  115. Java::
  116. +
  117. [source,java,role="primary"]
  118. ----
  119. BytesKeyGenerator generator = KeyGenerators.secureRandom();
  120. byte[] key = generator.generateKey();
  121. ----
  122. Kotlin::
  123. +
  124. [source,kotlin,role="secondary"]
  125. ----
  126. val generator = KeyGenerators.secureRandom()
  127. val key = generator.generateKey()
  128. ----
  129. ======
  130. The default key length is 8 bytes.
  131. There is also a KeyGenerators.secureRandom variant that provides control over the key length:
  132. .KeyGenerators.secureRandom
  133. [tabs]
  134. ======
  135. Java::
  136. +
  137. [source,java,role="primary"]
  138. ----
  139. KeyGenerators.secureRandom(16);
  140. ----
  141. Kotlin::
  142. +
  143. [source,kotlin,role="secondary"]
  144. ----
  145. KeyGenerators.secureRandom(16)
  146. ----
  147. ======
  148. Use the KeyGenerators.shared factory method to construct a BytesKeyGenerator that always returns the same key on every invocation:
  149. .KeyGenerators.shared
  150. [tabs]
  151. ======
  152. Java::
  153. +
  154. [source,java,role="primary"]
  155. ----
  156. KeyGenerators.shared(16);
  157. ----
  158. Kotlin::
  159. +
  160. [source,kotlin,role="secondary"]
  161. ----
  162. KeyGenerators.shared(16)
  163. ----
  164. ======
  165. === StringKeyGenerator
  166. Use the KeyGenerators.string factory method to construct a 8-byte, SecureRandom KeyGenerator that hex-encodes each key as a String:
  167. .StringKeyGenerator
  168. [tabs]
  169. ======
  170. Java::
  171. +
  172. [source,java,role="primary"]
  173. ----
  174. KeyGenerators.string();
  175. ----
  176. Kotlin::
  177. +
  178. [source,kotlin,role="secondary"]
  179. ----
  180. KeyGenerators.string()
  181. ----
  182. ======
  183. [[spring-security-crypto-passwordencoders]]
  184. == Password Encoding
  185. The password package of the spring-security-crypto module provides support for encoding passwords.
  186. `PasswordEncoder` is the central service interface and has the following signature:
  187. [source,java]
  188. ----
  189. public interface PasswordEncoder {
  190. String encode(CharSequence rawPassword);
  191. boolean matches(CharSequence rawPassword, String encodedPassword);
  192. default boolean upgradeEncoding(String encodedPassword) {
  193. return false;
  194. }
  195. }
  196. ----
  197. The matches method returns true if the rawPassword, once encoded, equals the encodedPassword.
  198. This method is designed to support password-based authentication schemes.
  199. The `BCryptPasswordEncoder` implementation uses the widely supported "bcrypt" algorithm to hash the passwords.
  200. Bcrypt uses a random 16 byte salt value and is a deliberately slow algorithm, in order to hinder password crackers.
  201. The amount of work it does can be tuned using the "strength" parameter which takes values from 4 to 31.
  202. The higher the value, the more work has to be done to calculate the hash.
  203. The default value is 10.
  204. You can change this value in your deployed system without affecting existing passwords, as the value is also stored in the encoded hash.
  205. .BCryptPasswordEncoder
  206. [tabs]
  207. ======
  208. Java::
  209. +
  210. [source,java,role="primary"]
  211. ----
  212. // Create an encoder with strength 16
  213. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
  214. String result = encoder.encode("myPassword");
  215. assertTrue(encoder.matches("myPassword", result));
  216. ----
  217. Kotlin::
  218. +
  219. [source,kotlin,role="secondary"]
  220. ----
  221. // Create an encoder with strength 16
  222. val encoder = BCryptPasswordEncoder(16)
  223. val result: String = encoder.encode("myPassword")
  224. assertTrue(encoder.matches("myPassword", result))
  225. ----
  226. ======
  227. The `Pbkdf2PasswordEncoder` implementation uses PBKDF2 algorithm to hash the passwords.
  228. 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.
  229. .Pbkdf2PasswordEncoder
  230. [tabs]
  231. ======
  232. Java::
  233. +
  234. [source,java,role="primary"]
  235. ----
  236. // Create an encoder with all the defaults
  237. Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
  238. String result = encoder.encode("myPassword");
  239. assertTrue(encoder.matches("myPassword", result));
  240. ----
  241. Kotlin::
  242. +
  243. [source,kotlin,role="secondary"]
  244. ----
  245. // Create an encoder with all the defaults
  246. val encoder = Pbkdf2PasswordEncoder()
  247. val result: String = encoder.encode("myPassword")
  248. assertTrue(encoder.matches("myPassword", result))
  249. ----
  250. ======