diff --git a/src/main/java/com/monkeyk/sos/infrastructure/PKCEUtils.java b/src/main/java/com/monkeyk/sos/infrastructure/PKCEUtils.java new file mode 100644 index 0000000..4bceb20 --- /dev/null +++ b/src/main/java/com/monkeyk/sos/infrastructure/PKCEUtils.java @@ -0,0 +1,56 @@ +package com.monkeyk.sos.infrastructure; + +import org.apache.commons.lang3.RandomStringUtils; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +/** + * 2023/10/16 22:45 + *
+ * PKCE tool: + * + * @author Shengzhao Li + * @since 3.0.0 + */ +public abstract class PKCEUtils { + + private static final String ALG = "SHA-256"; + + + private PKCEUtils() { + } + + /** + * 随机生成32的 code_verifier + * + * @return code_verifier + */ + public static String generateCodeVerifier() { + // 1. 随机生成code_verifier + String codeVerifierVal = RandomStringUtils.random(32, true, true); + //2. 对 code_verifier 进行base64 encode + return Base64.getEncoder().encodeToString(codeVerifierVal.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 根据指定的 code_verifier 计算 code_challenge + * + * @param codeVerifier code_verifier + * @return code_challenge + */ + public static String generateCodeChallenge(String codeVerifier) { + MessageDigest md; + try { + md = MessageDigest.getInstance(ALG); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("JDK not found alg: '" + ALG + "' ??", e); + } + byte[] digest = md.digest(codeVerifier.getBytes(StandardCharsets.US_ASCII)); + return Base64.getUrlEncoder().withoutPadding().encodeToString(digest); + } + + +} diff --git a/src/test/java/com/monkeyk/sos/infrastructure/PKCEUtilsTest.java b/src/test/java/com/monkeyk/sos/infrastructure/PKCEUtilsTest.java new file mode 100644 index 0000000..6080855 --- /dev/null +++ b/src/test/java/com/monkeyk/sos/infrastructure/PKCEUtilsTest.java @@ -0,0 +1,65 @@ +package com.monkeyk.sos.infrastructure; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.Base64; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * 2023/10/16 22:53 + * + * @author Shengzhao Li + * @since 3.0.0 + */ +class PKCEUtilsTest { + + + @Test + void generateCodeVerifier() { + + String verifier = PKCEUtils.generateCodeVerifier(); + assertNotNull(verifier); + assertTrue(verifier.length() >= 32); + } + + + @Test + void generateCodeChallenge() { + + String verifier = PKCEUtils.generateCodeVerifier(); + assertNotNull(verifier); + + String challenge = PKCEUtils.generateCodeChallenge(verifier); + assertNotNull(challenge); + + } + + + /** + * PKCE 需要的参数生成测试 + * code_challenge_method : S256 (alg: SHA-256) 固定值 + * code_verifier : 随机生成且base64 encode的值 (推荐随机值至少32位) + * code_challenge : 对 code_verifier 使用指定算法进行计算(digest)并base encode的值 + * + * @throws Exception e + */ + @Test + void pkceFlow() { + + // 1. 随机生成code_verifier + String codeVerifier = PKCEUtils.generateCodeVerifier(); +// System.out.println("code_verifier -> " + codeVerifier); + + //2. 按指定算法计算 挑战码 code_challenge + String codeChallenge = PKCEUtils.generateCodeChallenge(codeVerifier); + + assertNotNull(codeChallenge); +// System.out.println("code_challenge -> " + codeChallenge); + } + + +} \ No newline at end of file