Creating a Secure Keypad with React

0

Implementing a secure keypad to safely handle input in security-sensitive applications is essential. Especially when using modern front-end frameworks like React, security features can be efficiently and simply implemented. In this article, we will explore how to create a secure keypad in React and how to encrypt input values for safe transmission.

1. Project Setup

First, create a new React project and install the necessary packages. Use the following commands to create a React project.

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

`styled-components` is used for easy styling management, and `node-rsa` is used for RSA encryption.

2. Basic Structure

Modify the `App.js` file to add the keypad component. This example implements a numeric keypad and masks the input values on the screen.

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. Randomized Keypad Layout

Randomize the keypad numbers to enhance security.

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. Encrypting Input

Encrypt the input values before sending them to the server. Use the `node-rsa` library for RSA encryption.

import NodeRSA from 'node-rsa';

// RSA public key (insert your pre-generated public key here)
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. Decrypting on the Server

Decrypt the data on the server side. The server uses the private key to decrypt the encrypted data sent by the client.

// Server code (Node.js/Express example)
const express = require('express');
const bodyParser = require('body-parser');
const NodeRSA = require('node-rsa');

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

// Insert your pre-generated private key here
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');
});

Summary

  • Generate an RSA key pair, storing the public key on the client side and the private key on the server side.
  • Encrypt input values with the RSA public key on the client and send the encrypted data to the server.
  • Decrypt the data on the server using the RSA private key.

By following these steps, you can securely encrypt and transmit input values. Increase the RSA key length as needed to enhance security.

Conclusion

In this article, we covered how to implement a secure keypad in React and how to encrypt input values for safe transmission. This ensures that user data is protected in security-sensitive applications.

Leave a Reply