change directory

This commit is contained in:
haerong22
2021-09-13 10:51:59 +09:00
parent 59642a8198
commit 98c7aedc01
72 changed files with 1 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
package com.example.httpencryption;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan(basePackages = {"com.example.httpencryption.common"})
@SpringBootApplication
public class HttpEncryptionApplication {
public static void main(String[] args) {
SpringApplication.run(HttpEncryptionApplication.class, args);
}
}

View File

@@ -0,0 +1,28 @@
package com.example.httpencryption.common;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@WebFilter("/*")
public class HttpEncryptionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
RequestDecryptWrapper requestDecryptWrapper = new RequestDecryptWrapper(httpServletRequest);
ResponseEncryptWrapper responseEncryptWrapper = new ResponseEncryptWrapper(httpServletResponse);
chain.doFilter(requestDecryptWrapper, responseEncryptWrapper);
httpServletResponse.getOutputStream().write(responseEncryptWrapper.encryptResponse());
}
}

View File

@@ -0,0 +1,72 @@
package com.example.httpencryption.common;
import com.example.httpencryption.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.util.ObjectUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@Slf4j
public class RequestDecryptWrapper extends HttpServletRequestWrapper {
private final Charset encoding;
private String decodingBody;
private byte[] rawData;
public RequestDecryptWrapper(HttpServletRequest request) {
super(request);
String charEncoding = request.getCharacterEncoding();
this.encoding = ObjectUtils.isEmpty(charEncoding) ? StandardCharsets.UTF_8 : Charset.forName(charEncoding);
try {
InputStream inputStream = request.getInputStream();
rawData = IOUtils.toByteArray(inputStream);
if (ObjectUtils.isEmpty(rawData)) {
return;
}
AESUtil aesUtil = new AESUtil();
this.decodingBody = aesUtil.decrypt(new String(rawData, StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decodingBody == null ? "".getBytes(encoding) : decodingBody.getBytes(encoding));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}

View File

@@ -0,0 +1,46 @@
package com.example.httpencryption.common;
import com.example.httpencryption.utils.AESUtil;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ResponseEncryptWrapper extends HttpServletResponseWrapper {
private final ByteArrayOutputStream output;
public ResponseEncryptWrapper(HttpServletResponse response) {
super(response);
output = new ByteArrayOutputStream();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener listener) {
}
@Override
public void write(int b) throws IOException {
output.write(b);
}
};
}
public byte[] encryptResponse() {
String responseMessage = new String(output.toByteArray(), StandardCharsets.UTF_8);
AESUtil aesUtil = new AESUtil();
return aesUtil.encrypt(responseMessage).getBytes(StandardCharsets.UTF_8);
}
}

View File

@@ -0,0 +1,29 @@
package com.example.httpencryption.controller;
import com.example.httpencryption.dto.TestDto;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@RestController
public class TestController {
@CrossOrigin
@PostMapping("/")
public TestDto hello(HttpServletRequest request, @RequestBody TestDto dto) throws IOException {
ServletInputStream inputStream = request.getInputStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
String s = new String(bytes, StandardCharsets.UTF_8);
System.out.println("s = " + s);
return dto;
}
}

View File

@@ -0,0 +1,14 @@
package com.example.httpencryption.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDto {
private String username;
private int age;
}

View File

@@ -0,0 +1,68 @@
package com.example.httpencryption.utils;
import org.springframework.util.Base64Utils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
public class AESUtil {
private final String ALGORITHM = "AES/CBC/PKCS5PADDING";
private final String KEY = "example";
private String iv;
public String encrypt(String data) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, createKeySpec(), createIvSpec());
byte[] encryptData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return iv + Base64Utils.encodeToString(encryptData);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException("encrypt fail : " + e.getMessage());
}
}
public String decrypt(String data) {
String ivStr = data.substring(0,16);
String content = data.substring(16);
byte[] dataBytes = Base64Utils.decodeFromString(content);
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, createKeySpec(), new IvParameterSpec(ivStr.getBytes(StandardCharsets.UTF_8)));
byte[] original = cipher.doFinal(dataBytes);
return new String(original, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException("decrypt fail : " + e.getMessage());
}
}
private IvParameterSpec createIvSpec() {
try {
String iv = StringUtil.randomStr(16);
this.iv = iv;
return new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException("createIvSpec fail : " + e.getMessage());
}
}
private Key createKeySpec() {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(KEY.getBytes(StandardCharsets.UTF_8));
return new SecretKeySpec(hashBytes, "AES");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("createKeySpec fail : " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,28 @@
package com.example.httpencryption.utils;
import java.util.Random;
public class StringUtil {
public static String randomStr(int length) {
Random random = new Random();
StringBuilder str = new StringBuilder();
for (int i = 0; i < length; i++) {
int choice = random.nextInt(3);
switch(choice) {
case 0:
str.append((char)(random.nextInt(25)+97));
break;
case 1:
str.append((char)(random.nextInt(25) +65));
break;
case 2:
str.append((char)(random.nextInt(10) +48));
break;
default:
break;
}
}
return str.toString();
}
}

View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="form">
<div>
<span>이름</span> <input name="username" type="text"/>
</div>
<div>
<span>나이</span> <input name="age" type="text"/>
</div>
<div>
<button type="button" onclick="btn()">등록</button>
</div>
</form>
</body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
const btn = () => {
const key = "example";
const sha256 = CryptoJS.SHA256(key);
const url = "http://localhost:8080"
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: encrypt(sha256)
})
.then(resp => resp.text())
.then(data => {
console.log(data);
decrypt(data, sha256);
});
}
const encrypt = (sha256) => {
let form = document.querySelector('#form');
let formData = new FormData(form);
let obj = {};
for (let key of formData.keys()) {
obj[key] = formData.get(key);
}
let iv = Math.random().toString(36).substring(2, 10) + Math.random().toString(36).substring(2, 10);
let string = CryptoJS.AES.encrypt(
JSON.stringify(obj),
sha256,
{
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
},
).toString();
return iv + string;
}
const decrypt = (data, sha256) => {
const iv = data.substring(0, 16);
const content = data.substring(16);
let result = CryptoJS.AES.decrypt(
content,
sha256,
{
iv: CryptoJS.enc.Utf8.parse(iv),
padding: CryptoJS.pad.Pkcs7,
}
).toString(CryptoJS.enc.Utf8);
console.log(JSON.parse(result));
}
</script>
</html>

View File

@@ -0,0 +1,13 @@
package com.example.httpencryption;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class HttpEncryptionApplicationTests {
@Test
void contextLoads() {
}
}

View File

@@ -0,0 +1,33 @@
package com.example.httpencryption.utils;
import com.example.httpencryption.dto.TestDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import java.security.NoSuchAlgorithmException;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AESUtilTest {
AESUtil util = new AESUtil();
@Test
void encryptTest() throws JsonProcessingException, NoSuchAlgorithmException {
ObjectMapper objectMapper = new ObjectMapper();
TestDto testDto = new TestDto("", 20);
String data = objectMapper.writeValueAsString(testDto);
System.out.println("data = " + data);
String encrypt = util.encrypt(data);
System.out.println("encrypt = " + encrypt);
String decrypt = util.decrypt(encrypt);
System.out.println("decrypt = " + decrypt);
TestDto origin = objectMapper.readValue(decrypt, TestDto.class);
assertEquals(testDto.getUsername(), origin.getUsername());
assertEquals(testDto.getAge(), origin.getAge());
}
}