Asymmetric data encryption is implemented using JsENCRYPT and AXIOS

This is the 8th day of my participation in Gwen Challenge

background

You do not want the data sent by the application to be seen in Devtools. This prevents the interface from being stripped down by peers and then used maliciously

To avoid this problem, the first thought is to encrypt the transmitted data once and let the back end decrypt and process it

Although the JS source code is open to the browser, it is not difficult to locate the object code without the source map after being obfuscated by the build tool

The expected encrypted transmission is as follows

Description of encryption scheme

Symmetric encryption

Symmetric encryption means that both sides have the same secret key and both sides know how to encrypt and decrypt the ciphertext.

This is all well and good, but the problem is getting both parties to know the key.

Because the data is transmitted through the network, if the secret key is transmitted through the network, once the secret key is captured, there is no encryption significance

Asymmetric encryption

There are public and private keys:

  • Public key The owner can know that data can be encrypted with a public key, but data must be decrypted using a private key
  • The private key is known only to the party that distributes the public key

This encryption method can perfectly solve the problems of symmetric encryption

By comparison, the asymmetric encryption scheme with good confidentiality is selected as the encryption scheme

RSA symmetric encryption algorithm is used in this paper

Public and Private Key Generation

According to baidu experience, generate a 1024 bit secret key

Git Bash is recommended for Windows

The private key

openssl genrsa -out rsa_1024_priv.pem 1024
Copy the code
Click to view generating private key
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQC0YiWffUFPnr2OyfcaM8QLkdq30VQxjIctZJX/CnYn7NorwCyK
iBX3hULSUrBxBACZBtfeGtpT+I9yn3+6s4kClZiJNOOP8bvJab4fboLUtJt9XciK
ENRxHVcnrYMrM+0diXGH/COjeA7ym/L2M/eX1fxpZjTByaJdx0FZAlrD4wIDAQAB
AoGBAKarxU2vw4gZCdeE3/BzAmMaWrjcD2pVCZY0ya/Fb9WGMTSZtc4u3fU+Sbbi
tqtGYnMC8rUDpNZP5eOoYrIVL7MJFj7n5DIT6TJOxWRavWsei812pQlc6ccR/VEH
o0nN5JQRZH8DC+CE86QddOW7VfnRMIP4A7j8UEEiRxsPITExAkEA4N10W/HA7lYE
WKSRES4/gAJHg7cqS2dAWIovX/JtxzUyK2q50rWjbgbXXOGriIp3cRJeH2Jmi6tm
jQQ+ldWAqwJBAM1b/9cRLWJ6fPdDIjbrc9IQE6C5HYI0FsHuyCn3zUKnD1+hc7k5
+BrSpyG5VzdPH3WOhm6GJ5TCf/LlxvvIeakCQQCEO1Ywt2KYBTc7FVNFgifPVAfP
+gdCHi6lomUni/1oVuzwwSsTMMMxcY51zTM88Qg6Eu4MkKXy3lFI/cT8AXhPAkEA
vy4q27muGsQVmsvxClfgl2tIGpS7l/+OQDVgO1Hq0WZdtZXE+mexRqdd2NOHEoKi
svpgxHw4VRFNtH+d48EbIQJBAMcLRGOuUrPhyYXmvEvvGGqcFH7zwjoyYlQQYR3a
IeAC4Mo/vDo7agLXvlRFXgPWMXAJqzjVhZ+xmew4hUqe5HY=
-----END RSA PRIVATE KEY-----

Copy the code

The public key

openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
Copy the code
Click to view the generated public key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0YiWffUFPnr2OyfcaM8QLkdq3
0VQxjIctZJX/CnYn7NorwCyKiBX3hULSUrBxBACZBtfeGtpT+I9yn3+6s4kClZiJ
NOOP8bvJab4fboLUtJt9XciKENRxHVcnrYMrM+0diXGH/COjeA7ym/L2M/eX1fxp
ZjTByaJdx0FZAlrD4wIDAQAB
-----END PUBLIC KEY-----

Copy the code

jsencrypt

  • jsencrypt
  • nodejs-jsencrypt

RSA encryption solution using Javascript

use

Install dependencies

# web
npm i jsencrypt

# node
npm i nodejs-jsencrypt
Copy the code

The introduction of

// web
import JSEncrypt from 'jsencrypt'

// node
const { JSEncrypt } = require('nodejs-jsencrypt')
Copy the code

Public key encryption method

// The above is automatically generated
const pubKey = 'Public key generated above'

function publicEncrypt(str){
    const encrypt = new JSEncrypt()
    encrypt.setPublicKey(pubKey)
    return encrypt.encrypt(str)
}
Copy the code

Private key decryption method

const privKey = 'private key generated above'

function privDecrypt(str) {
    const encrypt = new JSEncrypt()
    encrypt.setPrivateKey(privKey)
    return encrypt.decrypt(str)
}
Copy the code

You can see that the API is pretty neat

Use the sample

let str = publicEncrypt('hello world')
console.log(str)
console.log(privDecrypt(str))
Copy the code

Incorporate Axios practices

Axios configuration

npm i axios
Copy the code

The encryption logic is put into the Axios request interceptor, the original content is processed with json.stringify and then encrypted, and the encrypted content is passed using the value attribute, as shown below

import axios from "axios";

// Introduce the encryption method you just wrote
import { publicEncrypt } from "./utils/crypto";

const http = axios;
http.defaults.baseURL = '/api'
http.defaults.headers = {
  "content-Type": "application/json"
};

// Request interceptor
http.interceptors.request.use(
  config= > {
    // Operate config before sending
    // Encrypt the data passed
    config.data = {
      value:publicEncrypt(JSON.stringify(config.data))
    }
    return config;
  },
  err= > {
    // Processing error
    return Promise.reject(err); }); http.interceptors.response.use(response= > {
    // Return before operation
    return response.data;
  },
  err= > {
    return Promise.reject(err); });export default http;
Copy the code

Server-side decryption sample code

Node.js is written directly using the HTTP module, and Express is written using the HTTP module.

  1. Decrypt the received content
  2. The decrypted content is returned directly

HTTP module example

The data event is used in conjunction with the End event to receive the passed data and then decrypt it back

const http = require('http')

// Introduce decryption methods
const { privDecrypt } = require('./utils/crypto')

const server = http.createServer((req, res) = > {
    res.setHeader('content-type'.'application/json')
    let buffer = Buffer.alloc(0)

    // Receive the passed data
    req.on('data'.(chunk) = >{
        buffer = Buffer.concat([buffer, chunk])
    })
    req.on('end'.() = >{
        try {
            // Decrypt the passed data
            const data = privDecrypt(JSON.parse(buffer.toString('utf-8')).value)
            res.end(data)
        } catch (error) {
            console.log(error);
            res.end('error')}})})/ / start
server.listen(3000.err= > {
    console.log(`listen 3000 success`);
})
Copy the code

Express sample

Configure a front-facing * route, decrypt the passed content, and then rebind it to req.body for subsequent use by other routes

const express = require('express')
const { privDecrypt } = require('./utils/crypto')

const server = express()

server.use(express.urlencoded({ extended: false }))
server.use(express.json({ strict: true }))

// The first route to enter
server.route(The '*').all((req, res, next) = > {
    console.log(`${req.method}--${req.url}`)
    req.body = JSON.parse(privDecrypt(req.body.value))
    next()
})

server.post('/test/demo'.(req,res) = >{
    // Return directly to the actual content
    res.json(req.body)
})

/ / start
server.listen(3000.err= > {
    console.log(`listen 3000 success`);
})
Copy the code

Front-end code examples

Vite was used as a development preview tool

Vite. Config. js configuration: only request proxy is made, solving the development cross-domain problem

export default {
    server: {
        proxy: {
            '/api': {
                target: 'http://localhost:3000'.changeOrigin: true.rewrite: (path) = > path.replace(/^\/api/.' ')},}}}Copy the code

page

<body>
    <button id="send">send</button>
    <hr>
    <h2></h2>
    <textarea id="receive" placeholder="Received Contents"></textarea>
    <script type="module" src="./index.js"></script>
</body>
Copy the code

logic

import $http from './http'
const $send = document.getElementById('send')
const $receive = document.getElementById('receive')

$send.addEventListener('click'.function(){
    // Send a random content
    $http.post('/test/demo', {name:'xm'.age: ~ ~ (Math.random()*1000)
    }).then((res) = >[
        updateReceive(res)
    ])
})

function updateReceive(data){
    $receive.value = data instanceof Object?JSON.stringify(data):data
}
Copy the code

The results

page

Sending network Requests

Request response Content

Work done, access is very simple

Complete sample code repository

Welcome to comment and exchange