This is the 73rd original article without water, if you want to get more original good articles, please search the public account to follow us. This article was first published in the front blog of the cloud: Sensitive data encryption scheme and implementation

preface

Now is the era of big data, need to collect a large amount of personal information for statistics. On the one hand, it brings us convenience. On the other hand, some personal information and data are inadvertently leaked and used by illegal elements for promotion and black industry.

On May 25, 2018, the European Union imposed the General Data Protection Regulation (GDPR). The Regulation is an EU law regulating data protection and privacy for all INDIVIDUALS in the EU. This means that personal data must be stored using pseudonyms or anonymization, and the highest possible privacy Settings are used by default to avoid data leakage.

I believe that we do not want to let themselves outside “naked running”. Therefore, front-end developers should try to avoid plaintext transmission of users’ personal data and reduce the risk of information leakage as much as possible.

Now, if you look at this, you might say, well, now you’re using HTTPS, the data is encrypted in transit, so there’s no need for encryption on the front end. Instead, I can use the Google plugin to capture the personal information in an HTTPS request before you send it, as I’ll demonstrate below. So front-end data encryption is still necessary.

Data Leakage mode

  • Man-in-the-middle attack

    Man-in-the-middle attack is a common attack mode. The detailed process can be seen here. The process is that the middleman hijacks the client – server session by means of DNS spoofing.

    The information between the client and server goes through a middleman, who can obtain and forward the information between the two. Under HTTP, front-end data encryption still does not prevent data leakage because middlemen can forge keys. In order to avoid man-in-the-middle attack, we generally use HTTPS for transmission.

  • Google plug-in

    HTTPS prevents data from being hijacked in transit, but the data can still be leaked out of the Google plugin before HTTPS is sent.

    Because Google plug-in can capture all requests in the Network, user information can still be obtained if there are malicious codes in some plug-ins. The following is a demonstration for you.

    So light uses HTTPS, and some sensitive information is not secure if it is transmitted in plain text. It would be better to encrypt data on the basis of HTTPS.

Introduction to Encryption Algorithms

  • Symmetric encryption

    Symmetric encryption algorithm, also known as shared key encryption algorithm. In symmetric encryption algorithms, only one key is used, and both sender and receiver use this key to encrypt and decrypt data.

    This requires that both encryption and decryption parties must know the encryption key beforehand. Its advantages are open algorithm, small amount of computation, fast encryption speed, high encryption efficiency; The downside is that once the key is compromised, the data can be cracked. It is not recommended to use it alone. According to different implementation mechanisms, common algorithms mainly include AES, ChaCha20, 3DES, etc.

  • Asymmetric encryption

    Asymmetric encryption algorithm, also known as public key encryption algorithm. It requires two keys. One is called a public key, or public key. The other is called a private key.

    They’re paired, like a key and a lock. Because encryption and decryption use two different keys, this algorithm is called an asymmetric encryption algorithm. Its advantages are complex algorithm strength and high security. The disadvantage is that encryption and decryption speed is not as fast as symmetric encryption algorithm. Common algorithms mainly include RSA and Elgamal.

  • Hash algorithm

    The hash algorithm, also known as hash function or hash function, compresses the message or data into a summary, making the data quantity smaller and fixing the format of the data into a value of a specific length. It is generally used to verify the integrity of data. Usually, we can verify MD5 to determine whether the downloaded data is complete. Common algorithms include MD4, MD5, AND SHA.

Implementation scheme

  • Scheme 1: If symmetric encryption is used, both the server and client must know the key. The server would have to send the key to the client, which is not secure, so symmetric encryption alone would not work.

  • Scheme 2: If asymmetric encryption is used, the data on the client is encrypted through the public key, the server is decrypted through the private key, and the data sent by the client is encrypted without any problem. When the client receives the data, the server encrypts it with the public key and the client decrypts it with the private key. Therefore, this scheme requires two sets of public and private keys, which need to generate their own keys on the client and server sides.

  • Scheme three: if the combination of symmetric encryption and asymmetric encryption. The client needs to generate a symmetrically encrypted key 1, encrypt the transmitted content symmetrically with the key 1, and send the key 1 and the public key asymmetrically to the server. The server decrypts the symmetrically encrypted key 1 using the private key, and then decrypts the content using the key 1. This is the client-side to server-side process. If the server needs to send data to the client, the response data needs to be encrypted with the symmetric encryption key 1. Then the client receives the ciphertext and decrypts it using the key 1 of the client to complete the encrypted transmission.

  • Summary: The above is just a list of common encryption schemes. Generally speaking, scheme 2 is relatively simple, but it needs to maintain two sets of public key and private key. When the public key changes, it must notify each other, which has poor flexibility. Compared with scheme 2, key 1 can be changed at any time and the server does not need to be notified. Therefore, scheme 3 has better flexibility and security. In addition, scheme 3 encrypts the contents symmetrically, which is faster than asymmetric encryption when there is a large amount of data. Therefore, this paper adopts scheme three to achieve the code.

Code implementation

  • The following is the specific code implementation (using the login interface as an example), the main purpose is to convert the plaintext personal information into ciphertext transmission. The symmetric encryption library uses AES and the asymmetric encryption library uses RSA.

  • Client:

    • AES library (AES-JS) : github.com/ricmoo/aes-…

    • RSA library (jsencrypt) : github.com/travist/jse…

    • Specific code to achieve the login interface

      • The client needs to randomly generate an aesKey and request a publicKey from the server when the page is loaded

        let aesKey = [1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16]; // randomly generated
        let publicKey = ""; // The public key is obtained from the server
        
        // When the page is loaded, get the public key
        window.onload = () = > {
          axios({
            method: "GET".headers: { "content-type": "application/x-www-form-urlencoded" },
            url: "http://localhost:3000/getPub",
          })
            .then(function (result) {
              publicKey = result.data.data; // Get the public key
            })
            .catch(function (error) {
              console.log(error);
            });
        };
        Copy the code
      • Aes encryption and decryption methods

        /** * AES encryption method *@param {string} Text Indicates the character string * to be encrypted@param {array} Key Encryption key */
        function aesEncrypt(text, key) {
          const textBytes = aesjs.utils.utf8.toBytes(text); // Convert a string to binary data
        
          // CTR-counter encryption mode is used here. There are other modes to choose from, please refer to aes encryption library for details
          const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
        
          const encryptedBytes = aesCtr.encrypt(textBytes); // Encrypt
          const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); // Convert binary data to hex
        
          return encryptedHex;
        }
        
        /** * AES decryption method *@param {string} EncryptedHex Encrypts the string *@param {array} Key Encryption key */
        function aesDecrypt(encryptedHex, key) {
          const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex); // Convert hexadecimal data to binary
          const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
        
          const decryptedBytes = aesCtr.decrypt(encryptedBytes); // Decrypt
          const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes); // Convert binary data to utF-8 strings
        
          return decryptedText;
        }
        Copy the code
      • Login request

        /** * login interface */
        function submitFn() {
          const userName = document.querySelector("#userName").value;
          const password = document.querySelector("#password").value;
          const data = {
            userName,
            password,
          };
        
          const text = JSON.stringify(data);
          const sendData = aesEncrypt(text, aesKey); // Convert the data to a string for encryption
          console.log("Send data", text);
        
          const encrypt = new JSEncrypt();
          encrypt.setPublicKey(publicKey);
          const encrypted = encrypt.encrypt(aesKey.toString()); // Encrypt the aesKey asymmetrically
        
          const url = "http://localhost:3000/login";
          const params = { id: 0.data: { param1: sendData, param2: encrypted } };
        
          axios({
            method: "POST".headers: { "content-type": "application/x-www-form-urlencoded" },
            url: url,
            data: JSON.stringify(params),
          })
            .then(function (result) {
              const reciveData = aesDecrypt(result.data.data, aesKey); // Decrypt with aesKey
              console.log("Receive data", reciveData);
            })
            .catch(function (error) {
              console.log("error", error);
            });
        }
        Copy the code
  • Server (Node) :

    • AES library (AES-JS) : github.com/ricmoo/aes-…

    • RSA library (Node-RSA) : github.com/rzcoder/nod…

    • Specific code to achieve the login interface

      • Reference cryptographic library

        const http = require("http");
        const aesjs = require("aes-js");
        const NodeRSA = require("node-rsa");
        const rsaKey = new NodeRSA({ b: 1024 }); // The size of the key is 1024 bits
        let aesKey = null; // Used to save the aesKey of the client
        let privateKey = ""; // Saves the public key of the server
        
        rsaKey.setOptions({ encryptionScheme: "pkcs1" }); // Set the encryption mode
        Copy the code
      • Implementing the Login interface

        http
          .createServer((request, response) = > {
            response.setHeader("Access-Control-Allow-Origin"."*");
            response.setHeader("Access-Control-Allow-Headers"."Content-Type");
            response.setHeader("Content-Type"."application/json");
            switch (request.method) {
              case "GET":
                if (request.url === "/getPub") {
                  const publicKey = rsaKey.exportKey("public");
                  privateKey = rsaKey.exportKey("private");
                  response.writeHead(200);
                  response.end(JSON.stringify({ result: true.data: publicKey })); // Send the public key to the client
                  return;
                }
                break;
              case "POST":
                if (request.url === "/login") {
                  let str = "";
                  request.on("data".function (chunk) {
                    str += chunk;
                  });
                  request.on("end".function () {
                    const params = JSON.parse(str);
                    const reciveData = decrypt(params.data);
                    console.log("reciveData", reciveData);
                    // After a series of processing
        
                    response.writeHead(200);
                    response.end(
                      JSON.stringify({
                        result: true.data: aesEncrypt(
                          JSON.stringify({ userId: 123.address: "Hangzhou" }), // This data will be encrypted
                          aesKey
                        ),
                      })
                    );
                  });
                  return;
                }
                break;
              default:
                break;
            }
            response.writeHead(404);
            response.end();
          })
          .listen(3000);
        Copy the code
      • Encryption and decryption methods

        function decrypt({ param1, param2 }) {
          const decrypted = rsaKey.decrypt(param2, "utf8"); // Decrypt to get an aesKey
          aesKey = decrypted.split(",").map((item) = > {
            return +item;
          });
        
          return aesDecrypt(param1, aesKey);
        }
        
        /** * AES decryption method *@param {string} EncryptedHex Encrypts the string *@param {array} Key Encryption key */
        function aesDecrypt(encryptedHex, key) {
          const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex); // Convert hexadecimal to binary
          const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5)); // CTR-counter encryption mode is used here. There are other modes to choose from, please refer to aes encryption library for details
        
          const decryptedBytes = aesCtr.decrypt(encryptedBytes); // Decrypt
          const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes); // Convert binary data to a string
        
          return decryptedText;
        }
        
        /** * AES encryption method *@param {string} Text Indicates the character string * to be encrypted@param {array} Key Encryption key */
        function aesEncrypt(text, key) {
          const textBytes = aesjs.utils.utf8.toBytes(text); // Convert a string to binary data
          const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
        
          const encryptedBytes = aesCtr.encrypt(textBytes); / / encryption
          const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); // Convert binary data to hex
        
          return encryptedHex;
        }
        Copy the code
  • Complete sample code

Demonstration effect

conclusion

This paper mainly introduces some front-end security knowledge and the implementation of specific encryption scheme. In order to protect the privacy of customer data, whether HTTP or HTTPS, ciphertext transmission is recommended, so that the attackers increase the difficulty of the attack. Of course, data encryption and decryption will also bring a certain performance cost, which needs to be measured by each developer.

reference

After reading this article, my grandmother understood how HTTPS works

Man-in-the-middle attack

Recommended reading

Brief analysis of vue-Router source code and dynamic routing permission allocation

Write high quality maintainable code: comments at a glance

, recruiting

ZooTeam, a young passionate and creative front-end team, belongs to the PRODUCT R&D department of ZooTeam, based in picturesque Hangzhou. The team now has more than 40 front-end partners, with an average age of 27, and nearly 30% of them are full-stack engineers, no problem in the youth storm group. The members consist of “old” soldiers from Alibaba and netease, as well as fresh graduates from Zhejiang University, University of Science and Technology of China, Hangzhou Electric And other universities. In addition to daily business docking, the team also carried out technical exploration and practice in material system, engineering platform, building platform, performance experience, cloud application, data analysis and visualization, promoted and implemented a series of internal technical products, and continued to explore the new boundary of front-end technology system.

If you want to change what’s been bothering you, you want to start bothering you. If you want to change, you’ve been told you need more ideas, but you don’t have a solution. If you want change, you have the power to make it happen, but you don’t need it. If you want to change what you want to accomplish, you need a team to support you, but you don’t have the position to lead people. If you want to change the pace, it will be “5 years and 3 years of experience”; If you want to change the original savvy is good, but there is always a layer of fuzzy window… If you believe in the power of believing, believing that ordinary people can achieve extraordinary things, believing that you can meet a better version of yourself. If you want to be a part of the process of growing a front end team with deep business understanding, sound technology systems, technology value creation, and impact spillover as your business takes off, I think we should talk. Any time, waiting for you to write something and send it to [email protected]