React로 보안 키패드 만들기

0

보안이 중요한 애플리케이션에서 입력값을 안전하게 처리하기 위해 보안 키패드를 구현하는 방법은 필수적입니다. 특히 React와 같은 현대적인 프론트엔드 프레임워크를 사용한다면, 효율적이고 간단하게 보안 기능을 구현할 수 있습니다. 이번 글에서는 React로 보안 키패드를 만드는 방법과 함께, 입력값을 암호화하여 안전하게 전송하는 방법까지 알아보겠습니다.

1. 프로젝트 설정

먼저, 새로운 React 프로젝트를 생성하고 필요한 패키지를 설치합니다. 다음 명령어를 사용하여 React 프로젝트를 생성합니다.

npx create-react-app secure-keypad
cd secure-keypad
npm install styled-components node-rsa

`styled-components`는 스타일을 쉽게 관리하기 위해 사용하며, `node-rsa`는 RSA 암호화를 위해 사용합니다.

2. 기본 구조 작성

`App.js` 파일을 수정하여 키패드 컴포넌트를 추가합니다. 이 예제에서는 숫자 키패드를 구현하고, 입력값을 마스킹하여 화면에 표시합니다.

import React, { useState } from 'react';
import styled from 'styled-components';

const KeypadContainer = styled.div`
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 200px;
  margin: 0 auto;
`;

const KeyButton = styled.button`
  padding: 20px;
  font-size: 18px;
  cursor: pointer;
`;

const Display = styled.div`
  margin-bottom: 10px;
  padding: 10px;
  border: 1px solid #ccc;
  text-align: center;
  font-size: 24px;
`;

function App() {
  const [input, setInput] = useState('');

  const handleButtonClick = (value) => {
    setInput(prev => prev + value);
  };

  const handleClear = () => {
    setInput('');
  };

  return (
    <div>
      <Display>{'*'.repeat(input.length)}</Display>
      <KeypadContainer>
        {[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].map(number => (
          <KeyButton key={number} onClick={() => handleButtonClick(number)}>
            {number}
          </KeyButton>
        ))}
        <KeyButton onClick={handleClear}>Clear</KeyButton>
      </KeypadContainer>
    </div>
  );
}

export default App;

3. 랜덤화된 키패드 배열

키패드의 숫자를 랜덤하게 배열하여 보안성을 높입니다.

function App() {
  const [input, setInput] = useState('');
  const [keypadNumbers, setKeypadNumbers] = useState(shuffleArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]));

  function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }

  const handleButtonClick = (value) => {
    setInput(prev => prev + value);
  };

  const handleClear = () => {
    setInput('');
  };

  return (
    <div>
      <Display>{'*'.repeat(input.length)}</Display>
      <KeypadContainer>
        {keypadNumbers.map(number => (
          <KeyButton key={number} onClick={() => handleButtonClick(number)}>
            {number}
          </KeyButton>
        ))}
        <KeyButton onClick={handleClear}>Clear</KeyButton>
      </KeypadContainer>
    </div>
  );
}

4. 입력값 암호화

입력값을 암호화하여 서버에 전송합니다. RSA 암호화를 위해 `node-rsa` 라이브러리를 사용합니다.

import NodeRSA from 'node-rsa';

// RSA 공개 키 (미리 생성된 공개 키를 여기에 넣습니다)
const publicKey = '-----BEGIN PUBLIC KEY-----\n...your public key here...\n-----END PUBLIC KEY-----';

function App() {
  const [input, setInput] = useState('');
  const [keypadNumbers, setKeypadNumbers] = useState(shuffleArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]));

  function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }

  const handleButtonClick = (value) => {
    setInput(prev => prev + value);
  };

  const handleClear = () => {
    setInput('');
  };

  const handleSubmit = () => {
    const key = new NodeRSA(publicKey);
    const encrypted = key.encrypt(input, 'base64');
    console.log('Encrypted:', encrypted);

    fetch('/api/submit', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ data: encrypted })
    });
  };

  return (
    <div>
      <Display>{'*'.repeat(input.length)}</Display>
      <KeypadContainer>
        {keypadNumbers.map(number => (
          <KeyButton key={number} onClick={() => handleButtonClick(number)}>
            {number}
          </KeyButton>
        ))}
        <KeyButton onClick={handleClear}>Clear</KeyButton>
      </KeypadContainer>
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

export default App;

5. 서버 측 복호화

서버에서 데이터를 복호화합니다. 서버는 개인 키를 사용하여 클라이언트에서 전송된 암호화된 데이터를 복호화합니다.

// 서버 코드 (Node.js/Express 예시)
const express = require('express');
const bodyParser = require('body-parser');
const NodeRSA = require('node-rsa');

const app = express();
app.use(bodyParser.json());

// 미리 생성된 개인 키를 여기에 넣습니다.
const privateKey = '-----BEGIN PRIVATE KEY-----\n...your private key here...\n-----END PRIVATE KEY-----';
const key = new NodeRSA(privateKey);

app.post('/api/submit', (req, res) => {
  const { data } = req.body;
  const decrypted = key.decrypt(data, 'utf8');
  console.log('Decrypted:', decrypted);

  res.send('Data received and decrypted');
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

요약

  • RSA 키 쌍을 생성하고, 공개 키는 클라이언트에, 개인 키는 서버에 저장합니다.
  • 클라이언트에서 입력값을 RSA 공개 키로 암호화하여 서버에 전송합니다.
  • 서버에서 RSA 개인 키로 데이터를 복호화합니다.

이 방법을 통해 입력값을 안전하게 암호화하고 전송할 수 있습니다. 필요에 따라 RSA 키 길이를 더 길게 설정하여 보안성을 강화할 수 있습니다.

결론

이번 글에서는 React에서 보안 키패드를 구현하고 입력값을 안전하게 암호화하여 전송하는 방법을 다뤘습니다. 이를 통해 보안이 중요한 애플리케이션에서 사용자 데이터를 보호할 수 있습니다.

Leave a Reply