Java security invalidkeyexception invalid aes key length 64 bytes

AES256 암화코드를 사용하여 Encript 중에 오류가 발생되었다.

오류내용은 AES Key 길이 문제이다.

java.security.InvalidKeyException: Invalid AES key length: 21 bytes at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87) at com.sun.crypto.provider.GaloisCounterMode.init(GaloisCounterMode.java:298) at com.sun.crypto.provider.CipherCore.init(CipherCore.java:589) at com.sun.crypto.provider.CipherCore.init(CipherCore.java:467) at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:313) at javax.crypto.Cipher.implInit(Cipher.java:801) at javax.crypto.Cipher.chooseProvider(Cipher.java:863) at javax.crypto.Cipher.init(Cipher.java:1248) at javax.crypto.Cipher.init(Cipher.java:1185) at com.test.util.AES256Util.aesEncode(AES256Util.java:59) at ubsales.biz.login.controller.LoginController.loginMain(LoginController.java:155) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:743) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:672) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:82) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:933) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:867) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:951) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:853) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:827) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:743) at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:485) at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:410) at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:337) at org.springframework.security.web.firewall.RequestWrapper$FirewalledRequestAwareRequestDispatcher.forward(RequestWrapper.java:132) at org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure(SimpleUrlAuthenticationFailureHandler.java:65) at ubsales.core.handler.AuthenticationFailureHandler.onAuthenticationFailure(AuthenticationFailureHandler.java:54) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication(AbstractAuthenticationProcessingFilter.java:355) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:225) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:94) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)

AES 예제 코드

import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class AES256 { public static String alg = “AES/CBC/PKCS5Padding”; private final String key = “01234567890123456789012345678901”; private final String iv = key.substring(0, 16); // 16byte public String encrypt(String text) throws Exception { Cipher cipher = Cipher.getInstance(alg); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), “AES”); IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec); byte[] encrypted = cipher.doFinal(text.getBytes(“UTF-8”)); return Base64.getEncoder().encodeToString(encrypted); } public String decrypt(String cipherText) throws Exception { Cipher cipher = Cipher.getInstance(alg); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), “AES”); IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec); byte[] decodedBytes = Base64.getDecoder().decode(cipherText); byte[] decrypted = cipher.doFinal(decodedBytes); return new String(decrypted, “UTF-8”); } } import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import com.itextpdf.text.pdf.codec.Base64; public class AES256Helper { public AES256Helper(String key) { this.keySpec = new SecretKeySpec(key.getBytes(), “AES”); } public String encode(String str) throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { Cipher c = Cipher.getInstance(“AES/GCM/NoPadding”); c.init(Cipher.ENCRYPT_MODE, keySpec); // AES/ECB/PKCS5Padding byte[] encrypted = c.doFinal(str.getBytes(ComnConst.UTF_8_UPPER)); String enStr = new String(Base64.encodeBytes(encrypted)); return enStr; } public String decode(String str) throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { Cipher c = Cipher.getInstance(“AES/GCM/NoPadding”); c.init(Cipher.DECRYPT_MODE, keySpec); // AES/ECB/PKCS5Padding byte[] byteStr = Base64.decode(str); return new String(c.doFinal(byteStr),ComnConst.UTF_8_UPPER); } } public class TestAES { public static void main(String[] args) throws Exception { AES256 aes256 = new AES256(); String text = “Hello World”; String cipherText = aes256.encrypt(text); System.out.println(text); System.out.println(cipherText); System.out.println(aes256.decrypt(cipherText)); } }

[오류해결 방법]

AES 암호화 처리시 사용하는 키값의 길이는 반드시 16, 24, 32 byte 중에 하나로 고정해야한다.

[연관 자료]

  • https://perfectacle.github.io/2019/11/24/aes/
  • http://happinessoncode.com/2019/04/06/java-cipher-algorithm-mode-padding/

[REFERENCE]

Related Posts