https://100100e.tistory.com/317

 

Https는 공개키? 대칭키? 비대칭키?

공개키와 비대칭키를 혼용해서 쓰는 걸로 알고 있고 두 개 다 같은 말이라고 생각하고 글을 쓰겠다. Https 관련 글들을 보면 공개키를 통해 평문을 암호화 복호화한다고 되어있고 어느 글들은 공

100100e.tistory.com

이분이 그림도 그려놓고 아주 잘 설명해놓으셨다.

 

대칭키 방식

  • A<->B 통신시 암호화를 위해 대칭키를 사용할 수 있다.
  • 암호화, 복호화에 필요한 키가 동일하여 대칭키라 불린다.
  • 암호화하여서 보낸 패킷을 중간에 가로채도 알아볼수없다.
  • 하지만 키 자체가 한번은 통신으로 이동해야 하기 때문에 그중에 탈취되면 원본을 알아볼수 있게 된다.
  • AES256

비대칭키 방식

  • 서버에서 public key, private key를 발급한다. 둘은 소수를 이용해서 어쩌고 만든다.
  • private key는 암호화, public key는 복호화에 사용된다.
  • 클라이언트에게 public key를 건네준다.
  • 서버에 데이터(ex. 로그인 중 password)를 전송시 public key를 이용해 암호화하여 송신한다.
  • 제3자가 public key를 탈취했다하더라도 복호화에 사용할 수 없으므로 원본 password는 알아낼수없다.
  • 서버에선 전송받은 데이터를 private key를 이용해 복호화한다. (ex. password 원본으로 변경하여 DB에서 조회한다)
  • 대칭키 방식에 비해 암,복호화 속도가 느리다.
  • RSA

인증서

  • public key를 내가 정말 Request를 보내고자하는 서버로부터 발급받으면 상관없지만
    3자가 서버인척하고 private key, public key를 발급후 public key를 내주면 그걸로 암호화한 데이터를 3자에게 보내게 되고 3자는 private key를 이용해 복호화하여 원본데이터를 알아낼 수 있다. (password)
  • 강력한 RSA를 이용해서 암호화한 데이터를 보냈다고 방심하지만 결국 public key 자체부터가 썩은 것이다.
  • 이를 방지하고자 서버는 CA기관에 public key를 위탁하고 클라이언트는 CA로부터 public key를 받게된다.
  • 내가 집에서 만든 서버로 RSA를 구현해서 클라이언트에게 전달해준다면 그건 곧 사설인증서가 되는거고
    클라이언트쪽에선 브라우저에 warning이라는 문구가 뜨면서 신뢰할 수 없는데 괜찮겠냐는 메시지가 뜬다.

TLS

  • 비대칭키 방식을 이용해서 쭉 모든 통신을 하면 좋겠지만 암,복호화 속도가 대칭키에 비해 낮다.
    그 한계를 어떻게 극복하냐면
  • public key를 받은 후 클라이언트는 대칭key를 서버에 암호화하여 전송한다. (세션키 라고불린다)
  • 서버는 private key를 이용해 클라이언트로부터 전달받은 대칭key를 복호화하여 저장한다.
  • 이제 대칭키를 서로 알게되었으니 패킷을 대칭key를 이용해 암호화 통신한다.
    대칭키 방식의 취약점이 키가 탈취되면 끝장난다는 것인데
    처음에 public key로 암호화하여 전송하였으니 제3자가 알아낼 수가 없다.
  • 이렇게 비대칭키 방식+대칭키 방식을 장점을 버무려서 사용하는 방식이 TLS이고 SSL이라고도 불린다.

HTTPS

  • 기존 HTTP는 패킷이 암호화되어있지 않기 때문에 wireshark같은 툴로도 훔쳐서 안의 내용을 보기가 쉽다.
  • TLS 보안방식을 적용시켜서 HTTP 패킷 자체를 암호화하면 HTTPS라고 불리는 것이다.
  • 제대로된 HTTPS 통신 서버를 만드려면 CA기관에 돈주고 public key를 줘야하기도 하고
    패킷을 받을 때마다 복호화해야하기 때문에 비용이 든다.
  • 사용자 password같은 민감한 정보를 제외하고 나머지 내용은 까봐도 별 의미없다고 생각되면 그냥 HTTP 통신을 사용하고, 그 패킷 안의 일부 민감한 정보만 RSA를 이용해 암,복호화 할 수 있다.
  • 별 의미없다고 생각되는 내용일지라도 패킷이 훤히 들여다보인다면 고수에게 기가 막힌 방식으로 서버가 공격받을 수 있다. 괜히 HTTPS를 사용하는게 아니다.

HASH

  • Hash Function을 이용한 단방향 암호화 방식이다.
  • 보통 통신에 사용되는 암호화 방식은 주는 사람이 암호화하고 , 받는 사람이 복호화할 수 있어야 하는데 얘는 한번 암호화하면 끝이다.
  • 하지만 얘도 쓸 데가 있다.
  • 서버는 사용자의 정보 (ex. password)를 DB에 저장한다.
  • 백날 대칭키 비대칭키 이용해서 데이터를 훔쳐보지 못하게 하지만 DB에서 원본 데이터가 털려버린다면 끝이다.
  • 따라서 서버에선 복호화한 데이터(password)를 그대로 DB에 저장하고 비교하면 안된다.
  • 이때 Hash를 사용해서 password를 암호화하고 DB에 저장한다.
    서버 : password -> DB : 요상한값
  • 저장할 때(회원가입) 사용한 Hash Function이랑 조회할 때(로그인) 사용한 Hash Function만 같으면 된다.
  • 가끔 Hash Function이 내뱉는 암호화된 값이 중복된다는 문제가 있다고 한다. 이 말은 곧 정확한 password말고 다른 값들로 로그인을 할 수도 있고, 정확히 password를 입력했으나 로그인이 실패할수 있다는 말이 된다.
  • 이를 방지하기 위해 Hash Function으로 나온 값에 Salt값을 또 더해서 다시 Hash Function에 넣고 이중으로 처리하는 방식이 있다.
  • 소금을 친다.

'보안,인증' 카테고리의 다른 글

SSL 인증서  (1) 2022.04.09
OAuth2.0  (0) 2021.07.07
JWT  (0) 2021.07.07

[리소스 접근, 기능 사용]

사용자가 앱에서 페이스북, 카카오 등의 3p에 로그인 후

access_token을 발급받아서 3p 리소스에 접근하거나 기능을 사용하는 것

게시물 조회, 카카오톡 발송 등

 

[회원가입]

access_token으로 받은 고유 id를 이용해서 내 서버에 가입시키는 것

https://tansfil.tistory.com/60

1. 3p에 로그인 한다. (카카오로 로그인, 네이버로 로그인 등)

2. 발급받은 Access token을 이용해 고유 id를 갖고온다. (email address)
보통 user/me URL에 요청한다.

3. 고유 id가 내 서버 DB에 있는지 조회한다.

4. 더 갖고오고싶은 정보(nickname)를 입력받아서 user_id와 함께 DB에 집어넣고 회원가입시킨다.
이때 아이디, 비밀번호를 적지 않아도 돼서 편리하다.

5. 추후 로그인시 또 리턴받은 고유id가 DB에 있으면 바로 로그인시킨다. (세션생성, JWT 토큰 발급 등)

'보안,인증' 카테고리의 다른 글

SSL 인증서  (1) 2022.04.09
HTTPS란  (0) 2021.07.07
JWT  (0) 2021.07.07

기존 세션처럼 사용자 인증정보를 서버 메모리에 저장하지 않고

토큰에 인증 정보를 암호화시켜 포함하도록 한 인증방식

'보안,인증' 카테고리의 다른 글

SSL 인증서  (1) 2022.04.09
HTTPS란  (0) 2021.07.07
OAuth2.0  (0) 2021.07.07

1. api서버, 클라이언트랑 통신하는 서버 분리

기존 management폴더에 client폴더를 새로 파서

.git빼고 싹다 옮겨준다.

express generator를 이용해서 express앱을 생성한다. 디렉토리 명은 apiServer이다.

https://expressjs.com/ko/starter/generator.html

 

Express 애플리케이션 생성기

Express 애플리케이션 생성기 애플리케이션의 골격을 신속하게 작성하려면 애플리케이션 생성기 도구인 express를 사용하십시오. 다음의 명령을 이용해 express를 설치하십시오. $ npm install express-generator -g 다음과 같이 -h 옵션을 이용해 명령의 옵션을 표시하십시오. $ express -h Usage: express [options][dir] Options: -h, --help output usage informat

expressjs.com

생성된 apiServer의 package.json의 dependency에 있는 항목들을 설치하기 위해

npm install을 실행해준다.

일반적으로는 npm install 모듈명을 입력해서 모듈을 설치하지만 프로젝트의 루트경로에 package.json파일을 두고 
npm install 명령어를 입력하면  npm이 package.json에 명시된  dependencies부분의 모듈들을 모두 설치해 준다.
물론 package.json파일이 없는 상태에서 npm install 명령어만 입력하면 의존정보를  찾을수 없다는 오류가 난다.

 

분리한 후 디렉토리 모습

2. 서버 두개 실행시키기

루트폴더에 package.json 파일을 만든 후

client통신서버랑 api서버 둘다 실행시킬 수있게 scripts를 짜주고

 

concurrently 모듈을 설치해서 한번에 실행시킬 수 있게 세팅한다.

https://github.com/kimmobrunfeldt/concurrently

 

kimmobrunfeldt/concurrently

Run commands concurrently. Like `npm run watch-js & npm run watch-less` but better. - kimmobrunfeldt/concurrently

github.com

 

package.json을 세팅해놓고

> concurrently "npm:server" "npm:client"

한줄 입력시 백, 프론트 서버를 동시에 실행하도록 구현했다.

물론 포트번호를 둘이 안겹치게 바꿔야한다.

클라이언트는 3000번, api서버는 5000번을 썼다.

 

부트스트랩과 비슷한 material-UI 프레임워크를 사용했다.

https://react-bootstrap.github.io/

 

https://react-bootstrap.github.io/

React Bootstrap The most popular front-end framework Rebuilt for React. Current version: 1.0.0-beta.10

react-bootstrap.github.io

https://material-ui.com/

 

Material-UI: A popular React UI framework

React components for faster and easier web development. Build your own design system, or start with Material Design.

material-ui.com

 

터미널에 npm install @material-ui/core

 

1. 테이블 골격 만들기

<App.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import Customer from "./components/Customer";
import Table from "@material-ui/core/Table";
import TableHead from "@material-ui/core/TableHead";
import TableBody from "@material-ui/core/TableBody";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
 
const customers = [
  {
    id: 1,
    name"name1",
    birthday: "112345",
    gender: "남자",
    job: "없음"
  },
  {
    id: 2,
    name"name2",
    birthday: "112345",
    gender: "남자",
    job: "없음"
  },
  {
    id: 3,
    name"name3",
    birthday: "112345",
    gender: "여자",
    job: "없음"
  }
];
class App extends Component {
  render() {
    return (
      <Table>
        <TableHead>
          <TableRow>
            <TableCell>아이디</TableCell>
            <TableCell>이름</TableCell>
            <TableCell>생일</TableCell>
            <TableCell>성별</TableCell>
            <TableCell>직업</TableCell>
            
          </TableRow>
        </TableHead>
        <TableBody>
          {customers.map(c => {
            return (
              <Customer
                id={c.id}
                name={c.name}
                birthday={c.birthday}
                gender={c.gender}
                job={c.job}
              ></Customer>
            );
          })}
        </TableBody>
      </Table>
    );
  }
}
 
export default App;
 
cs

<Customer.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from "react";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
 
class Customer extends Component {
  render() {
    return (
      <TableRow>
        <TableCell>{this.props.id}</TableCell>
        <TableCell>{this.props.name}</TableCell>
        <TableCell>{this.props.birthday}</TableCell>
        <TableCell>{this.props.gender}</TableCell>
        <TableCell>{this.props.job}</TableCell>
      </TableRow>
    );
  }
}
 
export default Customer;
 
cs

기본 HTML 테이블에서 본거랑 비슷하게 매칭이 된다.

<table> : <Table>

<thead> : <TableHead>

<tr> : <TableRow>

<td> : <TableCell>

 

2. CSS입히기

<App.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import Customer from "./components/Customer";
import Table from "@material-ui/core/Table";
import TableHead from "@material-ui/core/TableHead";
import TableBody from "@material-ui/core/TableBody";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import { withStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
const styles = theme => ({
  root: {
    width"100%",
    marginTop: theme.spacing.unit * 3,
    overflowX: "auto"
  },
  table: {
    minWidth: 1080
  }
});
const customers = [
  {
    id: 1,
    name"name1",
    birthday: "112345",
    gender: "남자",
    job: "없음"
  },
  {
    id: 2,
    name"name2",
    birthday: "112345",
    gender: "남자",
    job: "없음"
  },
  {
    id: 3,
    name"name3",
    birthday: "112345",
    gender: "여자",
    job: "없음"
  }
];
class App extends Component {
  render() {
    const{classes}=this.props;
    return (
      <Paper className={classes.root}>
        <Table className={classes.table}>
          <TableHead>
            <TableRow>
              <TableCell>아이디</TableCell>
              <TableCell>이름</TableCell>
              <TableCell>생일</TableCell>
              <TableCell>성별</TableCell>
              <TableCell>직업</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {customers.map(c => {
              return (
                <Customer
                  id={c.id}
                  name={c.name}
                  birthday={c.birthday}
                  gender={c.gender}
                  job={c.job}
                ></Customer>
              );
            })}
          </TableBody>
        </Table>
      </Paper>
    );
  }
}
 
export default withStyles(styles)(App);
 
cs

 

+ Recent posts