- update jwt

- add security
This commit is contained in:
2024-01-04 01:15:47 +09:00
parent e41240ccb2
commit 1f2b1607c8
12 changed files with 248 additions and 20 deletions

View File

@@ -11,9 +11,9 @@ plugins {
dependencies {
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
implementation("io.jsonwebtoken:jjwt-api:0.11.2")
implementation("io.jsonwebtoken:jjwt-api:0.12.3")
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")
}

View File

@@ -29,12 +29,20 @@ public class JwtSample {
}
public static String generateToken() throws InvalidKeyException {
return Jwts.builder()
/*return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setIssuer("Elex")
.setExpiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
.claim("userId", 3)
.signWith(Keys.hmacShaKeyFor(key))
.compact();*/
return Jwts.builder()
.header().type(Header.JWT_TYPE)
.and()
.issuer("Elex")
.expiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
.claim("userId", 3)
.signWith(Keys.hmacShaKeyFor(key))
.compact();
}
@@ -53,11 +61,16 @@ public class JwtSample {
throws UnsupportedJwtException, MalformedJwtException, SignatureException, ExpiredJwtException,
MissingClaimException, IncorrectClaimException {
return Jwts.parserBuilder()
/*return Jwts.parserBuilder()
.setSigningKey(key)
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
.build()
.parseClaimsJws(parseHeader(token));
.parseClaimsJws(parseHeader(token));*/
return Jwts.parser()
.verifyWith(Keys.hmacShaKeyFor(key))
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
.build()
.parseSignedClaims(parseHeader(token));
}
/**
@@ -84,7 +97,7 @@ public class JwtSample {
final String authHeader = "Bearer " + token;
Jws<Claims> claims = parseToken(authHeader);
System.out.println(claims);
final int userId = claims.getBody().get("userId", Integer.class);
final int userId = claims.getPayload().get("userId", Integer.class);
System.out.println("User Id: " + userId);
}
}

View File

@@ -9,10 +9,14 @@ package kr.pe.elex.examples;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.CompressionAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.junit.jupiter.api.Test;
import java.security.Key;
import javax.crypto.SecretKey;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
@@ -24,23 +28,39 @@ import static org.junit.jupiter.api.Assertions.*;
class SampleTest {
@Test
void test(){
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] key = new byte[32];
new Random().nextBytes(key);
final Key signingKey = Keys.hmacShaKeyFor(key);
//final SecretKey signingKey = Keys.hmacShaKeyFor(key);
KeyPair keyPair = Jwts.SIG.RS384.keyPair().build();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String base64PublicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded());
String jwt = Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setIssuer("Elex")
.setExpiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
.header().type("JWT")
.and()
.issuer("Elex")
.expiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
.claim("userId", 3)
.signWith(signingKey)
.signWith(keyPair.getPrivate())
.compact();
System.out.println(jwt);
String issuer = Jwts.parserBuilder()
.setSigningKey(signingKey)
//.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
X509EncodedKeySpec ukeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey));
PublicKey pKey = KeyFactory.getInstance("RSA").generatePublic(ukeySpec);
Integer userId = Jwts.parser()
.verifyWith(pKey)
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
.build()
.parseClaimsJws(jwt).getBody().getIssuer();
System.out.println(issuer);
.parseSignedClaims(jwt).getPayload().get("userId", Integer.class);
System.out.println(userId);
String alg = Jwts.parser()
.verifyWith(pKey)
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
.build()
.parseSignedClaims(jwt).getHeader().getAlgorithm();
System.out.println(alg);
}
}

3
security/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Security
https://github.com/jwtk/jjwt

14
security/build.gradle.kts Normal file
View File

@@ -0,0 +1,14 @@
/*
* Examples for Java
*
* Copyright (c) 2023. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
plugins {
id("elex-java")
}
dependencies {
}

20
security/logback.xml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Examples for Java
~
~ Copyright (c) 2021. Elex. All Rights Reserved.
~ https://www.elex-project.com/
-->
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="TRACE">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024. Elex. All Rights Reesrved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class AESKeys {
public static SecretKey generateSecretKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom());
return keyGenerator.generateKey();
}
public static SecretKey generateSecretKey(char[] password, byte[] salt, int iteration) throws NoSuchAlgorithmException, InvalidKeySpecException {
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iteration);
return SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128")
.generateSecret(keySpec);
}
public static String encodeSecretKey(final SecretKey secretKey){
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
}
public static SecretKey decodeSecretKey(final String secretKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKey keySpec = new SecretKeySpec(Base64.getDecoder().decode(secretKey), "AES");
return keySpec;
}
public static IvParameterSpec generateIV(byte[] iv){
IvParameterSpec parameterSpec = new IvParameterSpec(iv);
return parameterSpec;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Examples for Java
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
@Slf4j
public class RSAKeys {
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048, new SecureRandom());
return keyPairGen.generateKeyPair();
}
public static String encodePrivateKey(final PrivateKey privateKey) {
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
public static String encodePublicKey(final PublicKey publicKey) {
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
public static PublicKey decodePublicKey(final String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
}
public static PrivateKey decodePrivateKey(final String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(privateKey));
return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
}
}

View File

@@ -0,0 +1,8 @@
/*
* Examples for Java
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024. Elex. All Rights Reesrved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import org.junit.jupiter.api.Test;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.*;
class AESKeysTest {
@Test
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKey secretKey = AESKeys.generateSecretKey();
String base64SecretKey = AESKeys.encodeSecretKey(secretKey);
SecretKey secretKey1 = AESKeys.decodeSecretKey(base64SecretKey);
assertEquals(secretKey, secretKey1);
}
@Test
void test1() throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] salt = new byte[8];
new Random().nextBytes(salt);
SecretKey secretKey = AESKeys.generateSecretKey("Hello".toCharArray(), salt, 10);
SecretKey secretKey1 = AESKeys.generateSecretKey("Hello".toCharArray(), salt, 10);
assertEquals(secretKey, secretKey1);
}
}

View File

@@ -0,0 +1,21 @@
/*
* Examples for Java
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import org.junit.jupiter.api.Test;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
class SampleTest {
@Test
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
}
}

View File

@@ -15,5 +15,5 @@ include(
"xml", "jackson", "jsoup", "markdown", "network", "httpd",
"properties", "serial-io",
"mustache", "thymeleaf", "locale", "quartz", "sysinfo",
"imaging", "stream", "sound", "midi", "gson"
"imaging", "stream", "sound", "midi", "gson", "security"
)