From d0372efadd8f2bcf8bd0d42d3592e2fa23dd0487 Mon Sep 17 00:00:00 2001 From: Rob Winch <362503+rwinch@users.noreply.github.com> Date: Mon, 15 Sep 2025 11:03:44 -0500 Subject: [PATCH] Use include-code for password4j docs This follows the new convention of using include-code going forward to ensure that the documentation compiles and is tested. This also corrected a few errors in custom params for Ballooning and PBKDF2 examples. Issue gh-17706 --- crypto/spring-security-crypto.gradle | 2 +- .../authentication/password-storage.adoc | 172 ++++-------------- docs/spring-security-docs.gradle | 1 + .../password4jargon2/Argon2UsageTests.java | 53 ++++++ .../BallooningHashingUsageTests.java | 52 ++++++ .../password4jbcrypt/BcryptUsageTests.java | 52 ++++++ .../password4jpbkdf2/Pbkdf2UsageTests.java | 52 ++++++ .../password4jscrypt/ScryptUsageTests.java | 51 ++++++ .../password4jargon2/Argon2UsageTests.kt | 51 ++++++ .../BallooningHashingUsageTests.kt | 47 +++++ .../password4jbcrypt/BcryptUsageTests.kt | 32 ++++ .../password4jpbkdf2/Pbkdf2UsageTests.kt | 32 ++++ .../password4jscrypt/ScryptUsageTests.kt | 31 ++++ 13 files changed, 487 insertions(+), 141 deletions(-) create mode 100644 docs/src/test/java/org/springframework/security/docs/features/authentication/password4jargon2/Argon2UsageTests.java create mode 100644 docs/src/test/java/org/springframework/security/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.java create mode 100644 docs/src/test/java/org/springframework/security/docs/features/authentication/password4jbcrypt/BcryptUsageTests.java create mode 100644 docs/src/test/java/org/springframework/security/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.java create mode 100644 docs/src/test/java/org/springframework/security/docs/features/authentication/password4jscrypt/ScryptUsageTests.java create mode 100644 docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jargon2/Argon2UsageTests.kt create mode 100644 docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.kt create mode 100644 docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jbcrypt/BcryptUsageTests.kt create mode 100644 docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.kt create mode 100644 docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jscrypt/ScryptUsageTests.kt diff --git a/crypto/spring-security-crypto.gradle b/crypto/spring-security-crypto.gradle index 6b2b478422..7fd438016d 100644 --- a/crypto/spring-security-crypto.gradle +++ b/crypto/spring-security-crypto.gradle @@ -8,7 +8,7 @@ dependencies { management platform(project(":spring-security-dependencies")) optional 'org.springframework:spring-core' optional 'org.bouncycastle:bcpkix-jdk18on' - optional 'com.password4j:password4j' + optional libs.com.password4j.password4j testImplementation "org.assertj:assertj-core" testImplementation "org.junit.jupiter:junit-jupiter-api" diff --git a/docs/modules/ROOT/pages/features/authentication/password-storage.adoc b/docs/modules/ROOT/pages/features/authentication/password-storage.adoc index c5158ba85a..48b6983433 100644 --- a/docs/modules/ROOT/pages/features/authentication/password-storage.adoc +++ b/docs/modules/ROOT/pages/features/authentication/password-storage.adoc @@ -483,37 +483,15 @@ This provides an alternative to Spring Security's built-in `Argon2PasswordEncode Argon2 is the winner of the https://en.wikipedia.org/wiki/Password_Hashing_Competition[Password Hashing Competition] and is recommended for new applications. This implementation leverages Password4j's Argon2 support which properly includes the salt in the output hash. +Create an encoder with default settings: + .Argon2Password4jPasswordEncoder -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -// Create an encoder with default settings -Argon2Password4jPasswordEncoder encoder = new Argon2Password4jPasswordEncoder(); -String result = encoder.encode("myPassword"); -assertTrue(encoder.matches("myPassword", result)); +include-code::./Argon2UsageTests[tag=default-params,indent=0] -// Create an encoder with custom Argon2 function -Argon2Function customArgon2 = Argon2Function.getInstance(65536, 3, 4, 32, Argon2.ID); -Argon2Password4jPasswordEncoder customEncoder = new Argon2Password4jPasswordEncoder(customArgon2); ----- +Create an encoder with custom Argon2 parameters: -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -// Create an encoder with default settings -val encoder = Argon2Password4jPasswordEncoder() -val result: String = encoder.encode("myPassword") -assertTrue(encoder.matches("myPassword", result)) - -// Create an encoder with custom Argon2 function -val customArgon2 = Argon2Function.getInstance(65536, 3, 4, 32, Argon2.ID) -val customEncoder = Argon2Password4jPasswordEncoder(customArgon2) ----- -====== +.Argon2Password4jPasswordEncoder Custom +include-code::./Argon2UsageTests[tag=custom-params,indent=0] [[password4j-bcrypt]] === BcryptPassword4jPasswordEncoder @@ -524,37 +502,15 @@ This provides an alternative to Spring Security's built-in `BCryptPasswordEncode BCrypt is a well-established password hashing algorithm that includes built-in salt generation and is resistant to rainbow table attacks. This implementation leverages Password4j's BCrypt support which properly includes the salt in the output hash. +Create an encoder with default settings: + .BcryptPassword4jPasswordEncoder -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -// Create an encoder with default settings -BcryptPassword4jPasswordEncoder encoder = new BcryptPassword4jPasswordEncoder(); -String result = encoder.encode("myPassword"); -assertTrue(encoder.matches("myPassword", result)); +include-code::./BcryptUsageTests[tag=default-params,indent=0] -// Create an encoder with custom round count -BcryptFunction customBcrypt = BcryptFunction.getInstance(12); -BcryptPassword4jPasswordEncoder customEncoder = new BcryptPassword4jPasswordEncoder(customBcrypt); ----- +Create an encoder with custom bcrypt parameters: -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -// Create an encoder with default settings -val encoder = BcryptPassword4jPasswordEncoder() -val result: String = encoder.encode("myPassword") -assertTrue(encoder.matches("myPassword", result)) - -// Create an encoder with custom round count -val customBcrypt = BcryptFunction.getInstance(12) -val customEncoder = BcryptPassword4jPasswordEncoder(customBcrypt) ----- -====== +.BcryptPassword4jPasswordEncoder Custom +include-code::./BcryptUsageTests[tag=custom-params,indent=0] [[password4j-scrypt]] === ScryptPassword4jPasswordEncoder @@ -565,37 +521,16 @@ This provides an alternative to Spring Security's built-in `SCryptPasswordEncode SCrypt is a memory-hard password hashing algorithm designed to be resistant to hardware brute-force attacks. This implementation leverages Password4j's SCrypt support which properly includes the salt in the output hash. + +Create an encoder with default settings: + .ScryptPassword4jPasswordEncoder -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -// Create an encoder with default settings -ScryptPassword4jPasswordEncoder encoder = new ScryptPassword4jPasswordEncoder(); -String result = encoder.encode("myPassword"); -assertTrue(encoder.matches("myPassword", result)); +include-code::./ScryptUsageTests[tag=default-params,indent=0] -// Create an encoder with custom SCrypt parameters -ScryptFunction customScrypt = ScryptFunction.getInstance(32768, 8, 1, 32); -ScryptPassword4jPasswordEncoder customEncoder = new ScryptPassword4jPasswordEncoder(customScrypt); ----- +Create an encoder with custom scrypt parameters: -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -// Create an encoder with default settings -val encoder = ScryptPassword4jPasswordEncoder() -val result: String = encoder.encode("myPassword") -assertTrue(encoder.matches("myPassword", result)) - -// Create an encoder with custom SCrypt parameters -val customScrypt = ScryptFunction.getInstance(32768, 8, 1, 32) -val customEncoder = ScryptPassword4jPasswordEncoder(customScrypt) ----- -====== +.ScryptPassword4jPasswordEncoder Custom +include-code::./ScryptUsageTests[tag=custom-params,indent=0] [[password4j-pbkdf2]] === Pbkdf2Password4jPasswordEncoder @@ -607,37 +542,15 @@ PBKDF2 is a key derivation function designed to be computationally expensive to This implementation handles salt management explicitly since Password4j's PBKDF2 implementation does not include the salt in the output hash. The encoded password format is: `+{salt}:{hash}+` where both salt and hash are Base64 encoded. +Create an encoder with default settings: + .Pbkdf2Password4jPasswordEncoder -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -// Create an encoder with default settings -Pbkdf2Password4jPasswordEncoder encoder = new Pbkdf2Password4jPasswordEncoder(); -String result = encoder.encode("myPassword"); -assertTrue(encoder.matches("myPassword", result)); +include-code::./Pbkdf2UsageTests[tag=default-params,indent=0] -// Create an encoder with custom PBKDF2 function and salt length -PBKDF2Function customPbkdf2 = PBKDF2Function.getInstance(Algorithm.HMAC_SHA256, 100000, 256); -Pbkdf2Password4jPasswordEncoder customEncoder = new Pbkdf2Password4jPasswordEncoder(customPbkdf2, 32); ----- +Create an encoder with custom PBKDF2 parameters: -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -// Create an encoder with default settings -val encoder = Pbkdf2Password4jPasswordEncoder() -val result: String = encoder.encode("myPassword") -assertTrue(encoder.matches("myPassword", result)) - -// Create an encoder with custom PBKDF2 function and salt length -val customPbkdf2 = PBKDF2Function.getInstance(Algorithm.HMAC_SHA256, 100000, 256) -val customEncoder = Pbkdf2Password4jPasswordEncoder(customPbkdf2, 32) ----- -====== +.Pbkdf2Password4jPasswordEncoder Custom +include-code::./Pbkdf2UsageTests[tag=custom-params,indent=0] [[password4j-ballooning]] === BalloonHashingPassword4jPasswordEncoder @@ -648,37 +561,16 @@ Balloon hashing is a memory-hard password hashing algorithm designed to be resis This implementation handles salt management explicitly since Password4j's Balloon hashing implementation does not include the salt in the output hash. The encoded password format is: `+{salt}:{hash}+` where both salt and hash are Base64 encoded. + +Create an encoder with default settings: + .BalloonHashingPassword4jPasswordEncoder -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -// Create an encoder with default settings -BalloonHashingPassword4jPasswordEncoder encoder = new BalloonHashingPassword4jPasswordEncoder(); -String result = encoder.encode("myPassword"); -assertTrue(encoder.matches("myPassword", result)); +include-code::./BallooningHashingUsageTests[tag=default-params,indent=0] -// Create an encoder with custom Balloon hashing function and salt length -BalloonHashingFunction customBalloon = BalloonHashingFunction.getInstance(1024, 3, 4, "SHA-256"); -BalloonHashingPassword4jPasswordEncoder customEncoder = new BalloonHashingPassword4jPasswordEncoder(customBalloon, 32); ----- +Create an encoder with custom parameters: -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -// Create an encoder with default settings -val encoder = BalloonHashingPassword4jPasswordEncoder() -val result: String = encoder.encode("myPassword") -assertTrue(encoder.matches("myPassword", result)) - -// Create an encoder with custom Balloon hashing function and salt length -val customBalloon = BalloonHashingFunction.getInstance(1024, 3, 4, "SHA-256") -val customEncoder = BalloonHashingPassword4jPasswordEncoder(customBalloon, 32) ----- -====== +.BalloonHashingPassword4jPasswordEncoder Custom +include-code::./BallooningHashingUsageTests[tag=custom-params,indent=0] [[authentication-password-storage-configuration]] == Password Storage Configuration diff --git a/docs/spring-security-docs.gradle b/docs/spring-security-docs.gradle index 002612d8b1..db88c19fdc 100644 --- a/docs/spring-security-docs.gradle +++ b/docs/spring-security-docs.gradle @@ -39,6 +39,7 @@ dependencies { testImplementation project(':spring-security-test') testImplementation project(':spring-security-oauth2-client') testImplementation 'com.squareup.okhttp3:mockwebserver' + testImplementation libs.com.password4j.password4j testImplementation 'com.unboundid:unboundid-ldapsdk' testImplementation libs.webauthn4j.core testImplementation 'org.jetbrains.kotlin:kotlin-reflect' diff --git a/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jargon2/Argon2UsageTests.java b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jargon2/Argon2UsageTests.java new file mode 100644 index 0000000000..be705e8b36 --- /dev/null +++ b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jargon2/Argon2UsageTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.docs.features.authentication.password4jargon2; + +import com.password4j.Argon2Function; +import com.password4j.types.Argon2; +import org.junit.jupiter.api.Test; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password4j.Argon2Password4jPasswordEncoder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +public class Argon2UsageTests { + + @Test + void defaultParams() { + // tag::default-params[] + PasswordEncoder encoder = new Argon2Password4jPasswordEncoder(); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::default-params[] + } + + @Test + void customParameters() { + // tag::custom-params[] + Argon2Function argon2Fn = Argon2Function.getInstance(65536, 3, 4, 32, + Argon2.ID); + PasswordEncoder encoder = new Argon2Password4jPasswordEncoder(argon2Fn); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::custom-params[] + } + +} diff --git a/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.java b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.java new file mode 100644 index 0000000000..ce9b22d5f0 --- /dev/null +++ b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.java @@ -0,0 +1,52 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.docs.features.authentication.password4jballooning; + +import com.password4j.BalloonHashingFunction; +import org.junit.jupiter.api.Test; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password4j.BalloonHashingPassword4jPasswordEncoder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +public class BallooningHashingUsageTests { + + @Test + void defaultParams() { + // tag::default-params[] + PasswordEncoder encoder = new BalloonHashingPassword4jPasswordEncoder(); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::default-params[] + } + + @Test + void customParameters() { + // tag::custom-params[] + BalloonHashingFunction ballooningHashingFn = + BalloonHashingFunction.getInstance("SHA-256", 1024, 3, 4, 3); + PasswordEncoder encoder = new BalloonHashingPassword4jPasswordEncoder(ballooningHashingFn); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::custom-params[] + } + +} diff --git a/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jbcrypt/BcryptUsageTests.java b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jbcrypt/BcryptUsageTests.java new file mode 100644 index 0000000000..f7921bf20d --- /dev/null +++ b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jbcrypt/BcryptUsageTests.java @@ -0,0 +1,52 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.docs.features.authentication.password4jbcrypt; + +import com.password4j.BcryptFunction; +import org.junit.jupiter.api.Test; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password4j.BcryptPassword4jPasswordEncoder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +public class BcryptUsageTests { + + @Test + void defaultParams() { + // tag::default-params[] + PasswordEncoder encoder = new BCryptPasswordEncoder(); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::default-params[] + } + + @Test + void customParameters() { + // tag::custom-params[] + BcryptFunction bcryptFn = BcryptFunction.getInstance(12); + PasswordEncoder encoder = new BcryptPassword4jPasswordEncoder(bcryptFn); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::custom-params[] + } + +} diff --git a/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.java b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.java new file mode 100644 index 0000000000..93a358b3d1 --- /dev/null +++ b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.java @@ -0,0 +1,52 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.docs.features.authentication.password4jpbkdf2; + +import com.password4j.PBKDF2Function; +import com.password4j.types.Hmac; +import org.junit.jupiter.api.Test; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password4j.Pbkdf2Password4jPasswordEncoder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +public class Pbkdf2UsageTests { + + @Test + void defaultParams() { + // tag::default-params[] + PasswordEncoder encoder = new Pbkdf2Password4jPasswordEncoder(); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::default-params[] + } + + @Test + void customParameters() { + // tag::custom-params[] + PBKDF2Function pbkdf2Fn = PBKDF2Function.getInstance(Hmac.SHA256, 100000, 256); + PasswordEncoder encoder = new Pbkdf2Password4jPasswordEncoder(pbkdf2Fn); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::custom-params[] + } + +} diff --git a/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jscrypt/ScryptUsageTests.java b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jscrypt/ScryptUsageTests.java new file mode 100644 index 0000000000..ba6cda784b --- /dev/null +++ b/docs/src/test/java/org/springframework/security/docs/features/authentication/password4jscrypt/ScryptUsageTests.java @@ -0,0 +1,51 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.docs.features.authentication.password4jscrypt; + +import com.password4j.ScryptFunction; +import org.junit.jupiter.api.Test; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password4j.ScryptPassword4jPasswordEncoder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Rob Winch + */ +public class ScryptUsageTests { + + @Test + void defaultParams() { + // tag::default-params[] + PasswordEncoder encoder = new ScryptPassword4jPasswordEncoder(); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::default-params[] + } + + @Test + void customParameters() { + // tag::custom-params[] + ScryptFunction scryptFn = ScryptFunction.getInstance(32768, 8, 1, 32); + PasswordEncoder encoder = new ScryptPassword4jPasswordEncoder(scryptFn); + String result = encoder.encode("myPassword"); + assertThat(encoder.matches("myPassword", result)).isTrue(); + // end::custom-params[] + } + +} diff --git a/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jargon2/Argon2UsageTests.kt b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jargon2/Argon2UsageTests.kt new file mode 100644 index 0000000000..a60cb45d72 --- /dev/null +++ b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jargon2/Argon2UsageTests.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.kt.docs.features.authentication.password4jargon2 + +import com.password4j.Argon2Function +import com.password4j.types.Argon2 +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.crypto.password4j.Argon2Password4jPasswordEncoder + +/** + * @author Rob Winch + */ +class Argon2UsageTests { + + @Test + fun defaultParams() { + // tag::default-params[] + val encoder: PasswordEncoder = Argon2Password4jPasswordEncoder() + val result = encoder.encode("myPassword") + assertThat(encoder.matches("myPassword", result)).isTrue() + // end::default-params[] + } + + @Test + fun customParameters() { + // tag::custom-params[] + val argon2Fn = Argon2Function.getInstance( + 65536, 3, 4, 32, + Argon2.ID + ) + val encoder: PasswordEncoder = Argon2Password4jPasswordEncoder(argon2Fn) + val result = encoder.encode("myPassword") + assertThat(encoder.matches("myPassword", result)).isTrue() + // end::custom-params[] + } +} diff --git a/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.kt b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.kt new file mode 100644 index 0000000000..4aeb1f78c6 --- /dev/null +++ b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jballooning/BallooningHashingUsageTests.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2004-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.kt.docs.features.authentication.password4jballooning + +import com.password4j.BalloonHashingFunction +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.crypto.password4j.BalloonHashingPassword4jPasswordEncoder + +/** + * @author Rob Winch + */ +class BallooningHashingUsageTests { + @Test + fun defaultParams() { + // tag::default-params[] + val encoder: PasswordEncoder = BalloonHashingPassword4jPasswordEncoder() + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::default-params[] + } + + @Test + fun customParameters() { + // tag::custom-params[] + val ballooningHashingFn = + BalloonHashingFunction.getInstance("SHA-256", 1024, 3, 4, 3) + val encoder: PasswordEncoder = BalloonHashingPassword4jPasswordEncoder(ballooningHashingFn) + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::custom-params[] + } +} diff --git a/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jbcrypt/BcryptUsageTests.kt b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jbcrypt/BcryptUsageTests.kt new file mode 100644 index 0000000000..290fb81990 --- /dev/null +++ b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jbcrypt/BcryptUsageTests.kt @@ -0,0 +1,32 @@ +package org.springframework.security.kt.docs.features.authentication.password4jbcrypt + +import com.password4j.BcryptFunction +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.crypto.password4j.BcryptPassword4jPasswordEncoder + +/** + * @author Rob Winch + */ +class BcryptUsageTests { + @Test + fun defaultParams() { + // tag::default-params[] + val encoder: PasswordEncoder = BCryptPasswordEncoder() + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::default-params[] + } + + @Test + fun customParameters() { + // tag::custom-params[] + val bcryptFunction = BcryptFunction.getInstance(12) + val encoder: PasswordEncoder = BcryptPassword4jPasswordEncoder(bcryptFunction) + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::custom-params[] + } +} diff --git a/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.kt b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.kt new file mode 100644 index 0000000000..622802031b --- /dev/null +++ b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jpbkdf2/Pbkdf2UsageTests.kt @@ -0,0 +1,32 @@ +package org.springframework.security.kt.docs.features.authentication.password4jpbkdf2 + +import com.password4j.PBKDF2Function +import com.password4j.types.Hmac +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.crypto.password4j.Pbkdf2Password4jPasswordEncoder + +/** + * @author Rob Winch + */ +class Pbkdf2UsageTests { + @Test + fun defaultParams() { + // tag::default-params[] + val encoder: PasswordEncoder = Pbkdf2Password4jPasswordEncoder() + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::default-params[] + } + + @Test + fun customParameters() { + // tag::custom-params[] + val pbkdf2Fn = PBKDF2Function.getInstance(Hmac.SHA256, 100000, 256) + val encoder: PasswordEncoder = Pbkdf2Password4jPasswordEncoder(pbkdf2Fn) + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::custom-params[] + } +} diff --git a/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jscrypt/ScryptUsageTests.kt b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jscrypt/ScryptUsageTests.kt new file mode 100644 index 0000000000..d7d2914236 --- /dev/null +++ b/docs/src/test/kotlin/org/springframework/security/kt/docs/features/authentication/password4jscrypt/ScryptUsageTests.kt @@ -0,0 +1,31 @@ +package org.springframework.security.kt.docs.features.authentication.password4jscrypt + +import com.password4j.ScryptFunction +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.crypto.password4j.ScryptPassword4jPasswordEncoder + +/** + * @author Rob Winch + */ +class ScryptUsageTests { + @Test + fun defaultParams() { + // tag::default-params[] + val encoder: PasswordEncoder = ScryptPassword4jPasswordEncoder() + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::default-params[] + } + + @Test + fun customParameters() { + // tag::custom-params[] + val scryptFn = ScryptFunction.getInstance(32768, 8, 1, 32) + val encoder: PasswordEncoder = ScryptPassword4jPasswordEncoder(scryptFn) + val result = encoder.encode("myPassword") + Assertions.assertThat(encoder.matches("myPassword", result)).isTrue() + // end::custom-params[] + } +}