• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

JWT secretKey ECDSA error

23.06.14 18:40 작성 조회수 373

0

[코드](https://github.com/YuYoHan/JWT)

ECDSA signing keys must be PrivateKey instances.이런 오류가 뜨는데

JwtProvider입니다.



@Slf4j
@Component
public class JwtProvider implements InitializingBean {

    private static final String AUTHORITIES_KEY = "auth";
    private final String secret;
    private final long tokenValidityInMilliseconds;
    private Key key;



    public JwtProvider(@Value("${jwt.secret_key}") String secret,
                       @Value("${jwt.access.expiration}") long tokenValidityInMilliseconds
                   ) {
        this.secret = secret;
        this.tokenValidityInMilliseconds = tokenValidityInMilliseconds * 1000;

    }

    // 여기서 InitializingBean를 상속받고 이 메소드를 오버라이드한 이유는
    // Bean이 생성이 되고 생성자를 통해서 secret 값을 Base64 Decode해서 key 변수에 할당하기 위함이다.
    @Override
    public void afterPropertiesSet() throws Exception {
        byte[] keyBytes = Decoders.BASE64.decode(secret);
        this.key = Keys.hmacShaKeyFor(keyBytes);
    }


    // 유저 정보를 가지고 AccessToken, RefreshToken을 생성하는 메서드
    public TokenDTO createToken(Authentication authentication) {

        // 권한 가져오기
        String authorities = authentication.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(","));

        long now = (new Date()).getTime();

        // Access Token 생성
        Date accessTokenExpire = new Date(now + this.tokenValidityInMilliseconds);
        String accessToken = Jwts.builder()
                .setSubject(authentication.getName())
                .claim(AUTHORITIES_KEY, authorities)
                .setExpiration(accessTokenExpire)
                .signWith(  key, SignatureAlgorithm.ES512)
                .compact();

        // Refresh Token 생성
        Date refreshTokenExpire = new Date(now + this.tokenValidityInMilliseconds + 86400);
        String refreshToken = Jwts.builder()
                .setSubject(authentication.getName())
                .claim(AUTHORITIES_KEY, authorities)
                .setExpiration(refreshTokenExpire)
                .signWith(key, SignatureAlgorithm.ES512)
                .compact();

        return TokenDTO.builder()
                .grantType("Bearer")
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .build();

    }

    // JWT 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 코드
    // 토큰으로 클레임을 만들고 이를 이용해 유저 객체를 만들어서 최종적으로 authentication 객체를 리턴
    // 인증 정보 조회
    public Authentication getAuthentication(String token) {

        // 토큰 복호화 메소드
        Claims claims = parseClaims(token);

        if(claims.get("auth") == null) {
            throw new RuntimeException("권한 정보가 없는 토큰입니다.");
        }

        // 클레임 권한 정보 가져오기
        Collection<? extends GrantedAuthority> authorities =
                Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());

        // UserDetails 객체를 만들어서 Authentication 리턴
        User principal = new User(claims.getSubject(), "", authorities);

        return new UsernamePasswordAuthenticationToken(principal, token, authorities);
    }

    private Claims parseClaims(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            return e.getClaims();
        }
    }

    // 토큰의 유효성 검증을 수행
    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
            return true;
        } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {

            log.info("잘못된 JWT 서명입니다.");
        } catch (ExpiredJwtException e) {

            log.info("만료된 JWT 토큰입니다.");
        } catch (UnsupportedJwtException e) {

            log.info("지원되지 않는 JWT 토큰입니다.");
        } catch (IllegalArgumentException e) {

            log.info("JWT 토큰이 잘못되었습니다.");
        }
        return false;
    }
}

강의랑 같은데 오류가 발생하네요 ㅠㅠ

 

답변 1

답변을 작성해보세요.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.06.16

안녕하세요, 인프런 AI 인턴이에요.

해당 오류는 ECDSA 알고리즘을 사용할 때, private key를 사용해야 한다는 것을 알려주는 오류입니다.
현재 코드에서는 secret key를 HMAC hash 알고리즘을 사용하여 생성하고 있습니다.
따라서 해당 오류가 발생하고 있는 것으로 보입니다.

만약 ECDSA 알고리즘을 사용하여 JWT에 서명하고 싶으시다면,
알고리즘을 변경하여 private key를 사용하도록 수정하셔야 합니다.
알고리즘 변경을 위해서는 관련 라이브러리를 추가하여야 하며,
아래 링크를 참고하시면 도움이 될 것입니다.

그리고, 현재 계신 상황에서는 단순히 질문 내용만 주심으로써 구체적인 도움을 받기 어려울 수 있습니다.
관련 코드 전체와 라이브러리 의존성에 대한 정보 등을 함께 기재하시면, 보다 정확한 답변을 받으실 수 있을 것입니다.

감사합니다.