diff --git a/core-java-modules/core-java-security-3/README.md b/core-java-modules/core-java-security-3/README.md new file mode 100644 index 0000000000..4585b6cc86 --- /dev/null +++ b/core-java-modules/core-java-security-3/README.md @@ -0,0 +1,8 @@ +## Core Java Security + +This module contains articles about core Java Security + +### Relevant Articles: + +- [Secret Key and String Conversion in Java](https://www.baeldung.com/secret-key-and-string-conversion-in-java/) +- More articles: [[<-- prev]](/core-java-modules/core-java-security-2) diff --git a/core-java-modules/core-java-security-3/pom.xml b/core-java-modules/core-java-security-3/pom.xml new file mode 100644 index 0000000000..2520cee7f8 --- /dev/null +++ b/core-java-modules/core-java-security-3/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + core-java-security-2 + 0.1.0-SNAPSHOT + core-java-security-2 + jar + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + + + + + + 1.60 + 1.11 + + 3.18.0 + 2.3.1 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtil.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtil.java new file mode 100644 index 0000000000..8fdf682666 --- /dev/null +++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtil.java @@ -0,0 +1,53 @@ +package com.baeldung.secretkeyandstringconversion; + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Base64; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +public class ConversionClassUtil { + + /* Generating Secret key */ + + // Generating Secret Key using KeyGenerator class with 256 + public static SecretKey generateKey(int n) throws NoSuchAlgorithmException { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + keyGenerator.init(n); + SecretKey originalKey = keyGenerator.generateKey(); + return originalKey; + } + + // Generating Secret Key using password and salt + public static SecretKey getKeyFromPassword(String password, String salt) + throws NoSuchAlgorithmException, InvalidKeySpecException { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256); + SecretKey originalKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); + return originalKey; + } + + /* Converting Secret key into String */ + public static String convertSecretKeyToString(SecretKey secretKey) throws NoSuchAlgorithmException { + // Converting the Secret Key into byte array + byte[] rawData = secretKey.getEncoded(); + // Getting String - Base64 encoded version of the Secret Key + String encodedKey = Base64.getEncoder().encodeToString(rawData); + return encodedKey; + } + + /* Converting String into Secret key into */ + public static SecretKey convertStringToSecretKeyto(String encodedKey) { + // Decoding the Base64 encoded string into byte array + byte[] decodedKey = Base64.getDecoder().decode(encodedKey); + // Rebuilding the Secret Key using SecretKeySpec Class + SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); + return originalKey; + } + +} diff --git a/core-java-modules/core-java-security-3/src/test/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtilUnitTest.java b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtilUnitTest.java new file mode 100644 index 0000000000..7a912dbf26 --- /dev/null +++ b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/secretkeyandstringconversion/ConversionClassUtilUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.secretkeyandstringconversion; + +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.SecretKey; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ConversionClassUtilUnitTest { + + @Test + void givenPasswordAndSalt_whenCreateSecreKeyCheckConversion_thenSuccess() + throws NoSuchAlgorithmException, InvalidKeySpecException { + // given + String password = "Baeldung@2021"; + String salt = "@$#baelDunG@#^$*"; + + // when + SecretKey encodedKey = ConversionClassUtil.getKeyFromPassword(password, salt); + String encodedString = ConversionClassUtil.convertSecretKeyToString(encodedKey); + SecretKey decodeKey = ConversionClassUtil.convertStringToSecretKeyto(encodedString); + + // then + Assertions.assertEquals(encodedKey, decodeKey); + } + + @Test + void givenSize_whenCreateSecreKeyCheckConversion_thenSuccess() + throws NoSuchAlgorithmException, InvalidKeySpecException { + // given + int size = 256; + + // when + SecretKey encodedKey = ConversionClassUtil.generateKey(size); + String encodedString = ConversionClassUtil.convertSecretKeyToString(encodedKey); + SecretKey decodeKey = ConversionClassUtil.convertStringToSecretKeyto(encodedString); + + // then + Assertions.assertEquals(encodedKey, decodeKey); + } + +} diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/config/MaxHTTPHeaderSizeConfig.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/config/MaxHTTPHeaderSizeConfig.java new file mode 100644 index 0000000000..0a71f914db --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/config/MaxHTTPHeaderSizeConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.sampleapp.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@ComponentScan({ "com.baeldung.sampleapp.web" }) +public class MaxHTTPHeaderSizeConfig implements WebMvcConfigurer { + + public MaxHTTPHeaderSizeConfig() { + super(); + } + +} diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MaxHttpHeaderSizeController.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MaxHttpHeaderSizeController.java new file mode 100644 index 0000000000..0c55f88fa1 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/sampleapp/web/controller/MaxHttpHeaderSizeController.java @@ -0,0 +1,17 @@ +package com.baeldung.sampleapp.web.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(value = "/request-header-test") +public class MaxHttpHeaderSizeController { + + @GetMapping + public boolean testMaxHTTPHeaderSize(@RequestHeader(value = "token") String token) { + return true; + } + +} diff --git a/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerIntegrationTest.java b/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerIntegrationTest.java new file mode 100644 index 0000000000..9b839f34a0 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerIntegrationTest.java @@ -0,0 +1,48 @@ +package com.baeldung.web.controller; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.sampleapp.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WebConfig.class) +@WebAppConfiguration +public class MaxHttpHeaderSizeControllerIntegrationTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void givenTokenWithLessThan8KBLegth_whenSendGetRequest_thenReturnsOK() throws Exception { + mockMvc.perform(get("/request-header-test").contentType(MediaType.APPLICATION_JSON_VALUE) + .with(httpBasic("user", "password")).header("token", "token")).andExpect(status().isOk()); + } + + @Test + public void givenTokenIsMissingInHeade_whenSendGetRequest_thenThrowsBadRequest() throws Exception { + mockMvc.perform(get("/request-header-test").contentType(MediaType.APPLICATION_JSON_VALUE) + .with(httpBasic("user", "password"))).andExpect(status().isBadRequest()); + } + +} diff --git a/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerLiveTest.java b/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerLiveTest.java new file mode 100644 index 0000000000..9c7e7c9029 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/test/java/com/baeldung/web/controller/MaxHttpHeaderSizeControllerLiveTest.java @@ -0,0 +1,53 @@ +package com.baeldung.web.controller; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import com.baeldung.sampleapp.config.MaxHTTPHeaderSizeConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { MaxHTTPHeaderSizeConfig.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +// Start MaxHttpHeaderSizeController Spring Boot App(MainApplication) first +public class MaxHttpHeaderSizeControllerLiveTest { + + @Test(expected = HttpClientErrorException.class) + public void givenTokenWithGreaterThan8KBLegth_whenSendGetRequest_thenThrowsBadRequest() throws Exception { + final String url = "http://localhost:8080/request-header-test"; + HttpHeaders headers = new HttpHeaders(); + headers.set("token", readRandomStringFromFile()); + + HttpEntity entity = new HttpEntity(headers); + final ResponseEntity response = new RestTemplate().exchange(url, HttpMethod.GET, entity, String.class); + } + + static String readRandomStringFromFile() throws IOException { + BufferedReader reader = new BufferedReader(new FileReader("src/test/resources/randomSringForheader.txt")); + StringBuilder stringBuilder = new StringBuilder(); + String line = null; + String ls = System.getProperty("line.separator"); + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append(ls); + } + stringBuilder.deleteCharAt(stringBuilder.length() - 1); + reader.close(); + String content = stringBuilder.toString(); + return content; + } + +} diff --git a/spring-boot-modules/spring-boot-runtime/src/test/resources/randomSringForheader.txt b/spring-boot-modules/spring-boot-runtime/src/test/resources/randomSringForheader.txt new file mode 100644 index 0000000000..444be3479e --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/test/resources/randomSringForheader.txt @@ -0,0 +1 @@ +eyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxgeyJraWQiOiIyMTM1MGE2NC02YTYxLTRiNmYtYjIyZS1lYTNkOTNiY2YyMTQiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0NjE3Zjk4NC1mY2VlLTRmNTctYTg3Yi1jNTcyOTA2ODk3NzkiLCJpc3MiOiJodHRwczovL2FwaS50ZXNjby5jb20vaWRlbnRpdHkvdjQvaXNzdWUtdG9rZW4iLCJzdWIiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJpYXQiOjE2MjE4Mzk4NDcsIm5iZiI6MTYyMTgzOTg0NywiZXhwIjoxNjIxODQzNDQ3LCJzY29wZSI6ImludGVybmFsIHB1YmxpYyIsImNvbmZpZGVuY2VfbGV2ZWwiOjEyLCJjbGllbnRfaWQiOiI2ZTg5Y2M0Yi0xMDlkLTQwNjAtOTBlNC04ZTMyZTgzNTQzYmYiLCJ0b2tlbl90eXBlIjoiYmVhcmVyIn0.QylY2akATMYkwcBWDQsfUAcY4y27mgKz1NIG78oNjUqCEskMDjWTPM6ZS5neE7CUso72p1ud8BDl8B0SIiRTlCVoaZxVZzUqOlM1ZJQKah-w9KFtZ48cdS_qKYxa2gp82suF-Q-lbWwPAqS-AYTcFaNMqsVlsCDCtOVoB-ALpa5mh0z6tQkqjU7uhsWut3fkKLmMym8x8ejnDth2QdjGIvSXHbYWRH0kYPFDZKS6jHsFOzGGiCHfn201UQLEVLbwL7knyQ8qQ5wolwdNymr364s1CT0A9VHIAfLVSscVIV0ae3rUoqUtjKrbSfXfntIpRyUm66INAbBgyFiWh3yRxg \ No newline at end of file