How to design a secure external interface? Check the signature and find out

In job interviews, we are often asked, how to design a secure external interface? In fact, you can answer this point by adding and verifying signatures, which will make your interface more secure. Next, this article will work with you to learn the addition and verification of signatures. From theory to practice, come on~

  • Cryptography related concepts
  • Concept of signature verification
  • Why is it necessary to add and verify signatures
  • Introduction to encryption algorithm
  • API related to signature verification
  • Implementation of signature verification code

This article has been included in personal github. If the article is useful, you can give it to a star:

https://github.com/whx123/JavaHome

Cryptography related concepts

Plaintext, ciphertext, key, encryption and decryption

  • Plaintext: refers to information / data that has not been encrypted.
  • Ciphertext: after the plaintext is encrypted by the encryption algorithm, it will become ciphertext to ensure data security.
  • Key: a parameter that is input in the algorithm of converting plaintext to ciphertext or ciphertext to plaintext. The key is divided into symmetric key and asymmetric key.
  • Encryption: the process of transforming plaintext into ciphertext.
  • Decryption: the process of restoring ciphertext to plaintext.

Symmetric encryption, asymmetric encryption

  • Symmetric encryption: an encryption algorithm that uses the same key for encryption and decryption.  

  • Asymmetric encryption: asymmetric encryption algorithm requires two keys (public key and private key). The public key and the private key exist in pairs. If the public key is used to encrypt the data, only the corresponding private key can be decrypted.

 

 

 

What is a public or private key?

  • The public key and private key exist in pairs. If the public key is used to encrypt the data, only the corresponding private key can be used to decrypt.
  • In fact, the public key is the public secret key, and the private key is the secret key you need to keep privately.
  • Asymmetric encryption algorithm needs a pair of public and private keys~

Suppose you have a file, you encrypt it with the letter A, and only the letter b can decrypt it; Or if you encrypt with b and only a can decrypt, then a and b are a pair of public and private keys. If key a is public, you should keep key b privately. At this time, key a is the public key and key b is the private key. On the contrary, if b is public, a must keep it. At this time, secret key b is the public key and secret key a is the private key.

Concept of signature verification

  • "Signature": use the Hash function to generate a message summary from the original message, and then encrypt the summary with the private key to obtain the corresponding digital signature of the message. Generally speaking, the requesting party will send the "digital signature and original message" to the receiving party.

  • "Signature verification": after receiving the original message and digital signature, the receiver uses "the same Hash function" to generate summary A from the message. In addition, decrypt the digital signature with the public key provided by the other party to obtain Abstract B. compare whether A and B are the same, and you can know whether the message has been tampered with.

 

 

Why do I need to sign for verification

In the last section, we already know the concept of signature addition and signature verification. Then, why do we need signature addition and signature verification? Some friends may think that we should use "public key encryption and private key decryption"?

Next, let's give a demo.

Suppose there is company A now, which needs to access the transfer system of company C. At the beginning, company C sent its public key to company A and collected its private key. When the merchant on the side of company A initiates the transfer, company A first encrypts the request message with the public key of company C. when the encrypted message reaches the transfer system of company C, company C will uncover the message with its own private key. Assuming that the encrypted message is obtained by the intermediary Actor during transmission, he is also depressed because he has no private key and can't eat swan meat. Originally, I wanted to modify the message and transfer one hundred million to my account. Ha ha. This implementation seems seamless and stable.

 

 

However, at the beginning, when company C sends the public key to company A, it is obtained by the intermediary Actor, and there is A problem with maozi.

The intermediary Actor intercepted C's public key. He sent his public key to company A. a mistakenly thought that this was the public key of company C. When a initiates the transfer, he encrypts the request message with the Actor's public key. When the encrypted message is transmitted, the Actor intercepts it again. At this time, he decrypts the message with his own private key, then modifies the message (transfer one hundred million to himself), encrypts it with C's public key and sends it to company C. After receiving the message, company C continues to decrypt it with his own private key. Finally, did the transfer account of company a lose 100 million~

 

 

How does company C distinguish whether the message comes from A or has been modified by an intermediary? In order to show the identity and authenticity of the message, it is necessary to "add signature and verify signature"!

Company A also sends its public key to company C, and the private key is kept by itself. When initiating the transfer, first sign the request message with your own private key, and then get your own digital signature. Then send the digital signature and request message to company C. After receiving the message, company C takes A's public key for signature verification. If the original message is inconsistent with the summary of the digital signature, it means that the message has been tampered with~

Some friends may have questions. Suppose A is intercepted by the intermediary Actor when sending his public key to company C. Uh huh, let's simulate A wave of actors and intercept the public key to see what the actors can do ~ ha ha

Suppose the Actor intercepts the public key of A and then intercepts the message from A to C. After intercepting the message, the first thing he wants to do must be to modify the message content. However, it is not allowed to modify the original message only, because company C will not be able to check and sign it. However, it seems that the digital signature cannot be solved, because the message digest algorithm (hash algorithm) cannot be solved inversely and only plays the role of verification

Therefore, the public key and private key are used for encryption and encryption, and "signature addition and signature verification are used to prove identity" to avoid being tampered with.

Introduction to common encryption related algorithms

  • Message digest algorithm
  • Symmetric encryption algorithm
  • Asymmetric encryption algorithm
  • State secret algorithm

Message digest algorithm:

  • The same plaintext data will get the same ciphertext result value through the same message digest algorithm.
  • After the data is processed by the message summary algorithm, the summary result value obtained cannot be restored to the data before processing.
  • Data summarization algorithm is also called Hash algorithm or Hash algorithm.
  • Message digest algorithm is generally used for signature verification.

Message Digest algorithms are mainly divided into three categories: MD (Message Digest algorithm), SHA (Secure Hash Algorithm) and MAC (Message Authentication Code algorithm).

MD family algorithm

MD (Message Digest) family, including MD2, MD4 and MD5.

  • The result of MD2, MD4 and MD5 calculation is a 128 bit (i.e. 16 byte) hash value, which is used to ensure the integrity and consistency of information transmission.
  • MD2's algorithm is slow but relatively safe. MD4's speed is fast, but its security decreases. MD5 is safer and faster than MD4.
  • MD5 is widely used in data integrity verification, data (message) summary, data encryption and so on.
  • MD5 can be cracked. For data requiring high security, experts generally recommend using other algorithms, such as SHA-2. In 2004, it was confirmed that MD5 algorithm can not prevent collision attacks, so it is not suitable for security authentication, such as SSL public key authentication or digital signature.

For example, let's see how to get the MD5 value of a string:

public class MD5Test {

    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "123";
        byte[] result = getMD5Bytes(s.getBytes());
        StringBuilder stringBuilder = new StringBuilder();
        for (byte temp : result) {
            if (temp >= 0 && temp < 16) {
                stringBuilder.append("0");
            }
            stringBuilder.append(Integer.toHexString(temp & 0xff));
        }
        System.out.println(s + ",MD5 After encryption:" + stringBuilder.toString());
    }

    private static byte[] getMD5Bytes(byte[] content) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            return md5.digest(content);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}

Operation results:

123,MD5 After encryption:202cb962ac59075b964b07152d234b70

ShA family algorithm

Sha (Secure Hash Algorithm), including SHA-0, SHA-1, SHA-2(SHA-256,SHA-512,SHA-224,SHA-384, etc.), SHA-3. It is implemented on the basis of MD algorithm. The difference from MD algorithm is "summary length". Sha algorithm has "longer length and higher security".

  • The security of NSA-0 will be reduced soon after it is released because it contains an error.
  • SHA-1 is widely used in many security protocols, including TLS, GnuPG, SSH, S/MIME and IPsec. It is the successor of MD5.
  • SHA-512, SHA-256, SHA-224. Its algorithm is basically similar to SHA-1, and there is no obvious weakness at present.
  • SHA-3 was officially released in 2015. Due to the successful cracking of MD5 and the theoretical cracking method of SHA-0 and SHA-1, SHA-3 came into being. Different from the previous algorithm, it is an alternative encrypted hash algorithm.

SHA-1, SHA-2(SHA-256,SHA-512,SHA-224,SHA-384) and other algorithms are commonly used. Let's see the comparison with MD5

Algorithm type Summary length (bits) Maximum input message length (bits) Collision attack (bits) Performance example (MiB/s)
MD5 128 infinite ≤ 18 (collision found) 335
SHA-1 160 2^64 − 1 < 63 (collision found) 192
SHA-224 224 2^64 − 1 112 139
SHA-256 256 2^64 − 1 128 139
SHA-384 384 2^128 − 1 192 154
SHA-512 512 2^128 − 1 256 154

MAC algorithm family

MAC algorithm MAC (Message Authentication Code algorithm) is a Hash function with a key. Enter the key and message, and output a message summary. It integrates MD and SHA two series of message summarization algorithms.

  • MD series algorithms: HmacMD2, HmacMD4 and HmacMD5;
  • SHA series algorithms: HmacSHA1, HmacSHA224, HmacSHA256, HmacSHA384 and HmacSHA512.

Symmetric encryption algorithm

The encryption algorithm that uses the "same key" for encryption and decryption is the symmetric encryption algorithm. Common symmetric encryption algorithms include AES, 3DES, DES, RC5, RC6, etc.

DES

Data Encryption Standard (DES) is a symmetric Key encryption block cipher algorithm. There are three entry parameters of DES algorithm: Key, data and Mode.

  • Key: 7 bytes, 56 bits in total, which is the working key of DES algorithm;
  • Data: 8 bytes and 64 bits, which are the data to be encrypted or decrypted;
  • Mode: encryption or decryption.

3DES

Triple Data Encryption Algorithm, also known as 3DES (Triple DES), is a symmetric key encryption block password, which is equivalent to applying the triple data encryption standard (DES) algorithm to each data block.

AES

AES, Advanced Encryption Standard, also known as Rijndael encryption in cryptography, is a block encryption standard adopted by the federal government of the United States.

  • The symmetric block cipher system is adopted. The key length is 128 bits, 192 bits and 256 bits, and the packet length is 128 bits
  • Compared with DES, AES has better security, efficiency and flexibility.

Asymmetric encryption algorithm

Asymmetric encryption algorithm requires two keys: public key and private key. The public key and the private key exist in pairs. If the data is encrypted with the public key, only the corresponding private key can be decrypted. The main asymmetric encryption algorithms are RSA, Elgamal, DSA, D-H and ECC.

RSA algorithm

  • RSA encryption algorithm is an asymmetric encryption algorithm, which is widely used in encryption and digital signature
  • RSA algorithm principle: the factorization of the product of two large prime numbers is extremely difficult, so the product can be disclosed as an encryption key.
  • RSA is the most widely studied public key algorithm. From its proposal to now, it has experienced the test of various attacks. It is generally considered to be one of the best public key schemes at present.

DSA

  • DSA(Digital Signature Algorithm) is also an asymmetric encryption algorithm.
  • The difference between DSA and RSA is that DSA is only used for digital signature and cannot be used for data encryption and decryption. Its security is equivalent to RSA, but its performance is better than RSA.

ECC algorithm

  • ECC (Elliptic Curves Cryptography), based on elliptic curve encryption.
  • The main advantage of Ecc is that in some cases, it uses smaller keys than other methods, such as RSA encryption algorithm, which provides an equivalent or higher level of security.
  • One of its disadvantages is that the implementation of encryption and decryption takes longer than other mechanisms (compared with RSA algorithm, this algorithm consumes a lot of CPU).

State secret algorithm

State secret is the domestic cryptographic algorithm recognized by the state cryptographic Bureau. In order to ensure the security of commercial passwords, the state commercial password management office has formulated a series of password standards, namely SM1, SM2, SM3, SM4 and other national secret algorithms.

SM1

  • SM1 is a symmetric encryption algorithm with encryption strength of 128 bits, which is implemented based on hardware.
  • The encryption strength and performance of SM1 are equivalent to AES.

SM2

  • SM2 mainly includes three parts: signature algorithm, key exchange algorithm and encryption algorithm
  • SM2 is used to replace RSA encryption algorithm. It is based on ECC and has low efficiency.

SM3

  • SM3, the domestic message digest algorithm.
  • It is suitable for digital signature and verification in commercial cryptographic applications, generation and verification of message authentication code and generation of random number.

SM4

  • SM4 is a grouping algorithm for WLAN products.
  • The packet length of the algorithm is 128 bits and the key length is 128 bits.
  • Both encryption algorithm and key expansion algorithm adopt 32 rounds of nonlinear iterative structure.
  • The structure of the decryption algorithm is the same as that of the encryption algorithm, but the use order of the round key is opposite. The decryption round key is the reverse order of the encryption round key.
  • Its function is similar to DES of international algorithm.

Java API related to signature verification

This section first introduces the API used for signature verification~

API related to endorsement

- java.security.Signature.getInstance(String algorithm); //Initialize the signature object according to the corresponding algorithm
- KeyFactory.getInstance(String algorithm);// According to the corresponding algorithm,generate KeyFactory object
- KeyFactory.generatePrivate(KeySpec keySpec); //Generate private key
- java.security.Signature.initSign(PrivateKey privateKey) //Initialize the signing object by the private key
- java.security.Signature.update(byte[] data)  //Update the original message to the signature object
- java.security.Signature.sign();//Countersign

「Signature.getInstance(String algorithm);」

  • Initialize the signature object according to the corresponding algorithm
  • The algorithm parameter can take parameters such as SHA256WithRSA or MD5WithRSA. SHA256WithRSA indicates that SHA256 algorithm is used to generate summary and RSA algorithm is used to add signature

「KeyFactory.getInstance(String algorithm);」

  • Generate the KeyFactory object according to the corresponding algorithm. For example, if your public and private keys use RSA algorithm, it will be passed into RSA

「KeyFactory.generatePrivate(KeySpec keySpec)」

  • The private key is generated and signed with the private key. Therefore, a private key object needs to be constructed through KeyFactory.

「Signature.initSign(PrivateKey privateKey)」

  • The private key is used for signing, so the private key is passed in to initialize the signing object

「Signature.update(byte[] data)」

  • Update the original message to the signature object

「java.security.Signature.sign();」

  • Add signature

API related to signature verification

- java.security.Signature.getInstance(String algorithm); //Initialize the signature object according to the corresponding algorithm
- KeyFactory.getInstance(String algorithm);// According to the corresponding algorithm,generate KeyFactory object
- KeyFactory.generatePublic(KeySpec keySpec); //Generate public key
- java.security.Signature.initVerify(publicKey); //The signature verification object is initialized by the public key
- java.security.Signature.update(byte[] data)  //Update the original message to the signature verification object
- java.security.Signature.verify(byte[] signature);//Signature verification

「Signature.getInstance(String algorithm)」

  • Initialize the signature object according to the corresponding algorithm. Note that the same algorithm parameters are required for signature verification and signature addition~

「KeyFactory.getInstance(String algorithm);」

  • Generate the KeyFactory object according to the corresponding algorithm

「KeyFactory.generatePublic(KeySpec keySpec);」

  • Generate the public key. The public key is used for signature verification. First construct a public key object through KeyFactory

「Signature.initVerify(publicKey);」

  • Public key signature verification, so pass in the public key object parameter to initialize the signature verification object

「Signature.update(byte[] data)」

  • Update the original message to the signature object

「Signature.verify(byte[] signature);」

  • Conduct signature verification

Implementation of signature verification code

After discussing the concept in the previous sections, it's time for code practice. I use SHA-256 as the summary algorithm and RSA as the signature verification algorithm, as follows:

package pattern;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * Signature verification demo
 *  @Author Little boy picking snails
 */
public class SignatureTest {
    //Public key string
    private static final String PUBLIC_KEY_STR = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaJzVjC5K6kbS2YE2fiDs6H8pB\n" +
            "JFDGEYqqJJC9I3E0Ebr5FsofdImV5eWdBSeADwcR9ppNbpORdZmcX6SipogKx9PX\n" +
            "5aAO4GPesroVeOs91xrLEGt/arteW8iSD+ZaGDUVV3+wcEdci/eCvFlc5PUuZJou\n" +
            "M2XZaDK4Fg2IRTfDXQIDAQAB";
    //Private key string
    private static final String PRIVATE_KEY_STR = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANonNWMLkrqRtLZg\n" +
            "TZ+IOzofykEkUMYRiqokkL0jcTQRuvkWyh90iZXl5Z0FJ4APBxH2mk1uk5F1mZxf\n" +
            "pKKmiArH09floA7gY96yuhV46z3XGssQa39qu15byJIP5loYNRVXf7BwR1yL94K8\n" +
            "WVzk9S5kmi4zZdloMrgWDYhFN8NdAgMBAAECgYA9bz1Bn0i68b2KfqRdgOfs/nbe\n" +
            "0XNN1DLQp2t7WDfRCg01iI1zPkZgyFVZWtI85f5/uIrLs5ArLosL1oNuqqc0nNne\n" +
            "CvJK+ZxvA98Hx3ZqYTzDnleR054YhofL5awbhSciYVic204DOG1rhSsYWMqtX7J7\n" +
            "3geoWL7TYdMfYXcCAQJBAPMMKsz6ZJh98EeQ1tDG5gpAGWFQkYNrxZDelP/LjeO0\n" +
            "TP3XkQnIpcaZoCs7V/rRGRGMWwQ2BUdc/01in89ZZ5ECQQDlx2oBc1CtOAm2UAhN\n" +
            "1xWrPkZWENQ53wTrwXO4qbTGDfBKon0AehLlGCSqxQ71aufLkNO7ZlX0IHTAlnk1\n" +
            "TvENAkAGSEQ69CXxgx/Y2beTwfBkR2/gghKg0QJUUkyLqBlMz3ZGAXJwTE1sqr/n\n" +
            "HiuSAiGhwH0ByNuuEotO1sPGukrhAkAMK26a2w+nzPL+u+hkrwKPykGRZ1zGH+Cz\n" +
            "19AYNKzFXJGgclCqiMydY5T1knBDYUEbj/UW1Mmyn1FvrciHoUG1AkAEMEIuDauz\n" +
            "JabEAU08YmZw6OoDGsukRWaPfjOEiVhH88p00veM1R37nwhoDMGyEGXVeVzNPvk7\n" +
            "cELg28MSRzCK";


    public static void main(String[] args) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidKeySpecException {
        //Original message
        String plain = "Welcome to my official account, the little boy who picks up snails";
        //Countersign
        byte[] signatureByte = sign(plain);
        System.out.println("The original message is:" + plain);
        System.out.println("Countersignature result:");
        System.out.println(new BASE64Encoder().encode(signatureByte));
        //Signature verification
        boolean verifyResult = verify(plain, signatureByte);
        System.out.println("Signature verification results:" + verifyResult);
    }

    /**
     * Signature method
     * @param plain
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws SignatureException
     */
    private static byte[] sign(String plain) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, SignatureException {
        //Obtain the signature object instance according to the corresponding algorithm
        Signature signature = Signature.getInstance("SHA256WithRSA");
        //The private key is used for obtaining and signing. The private key is generally read in the configuration file. Here, for the convenience of demonstration, the private key object is generated according to the private key string
        PrivateKey privateKey = getPriveteKey(PRIVATE_KEY_STR);
        //Initialize signature object
        signature.initSign(privateKey);
        //Update the original message to the object
        signature.update(plain.getBytes("UTF-8"));
        //Countersign
        return signature.sign();
    }

    /**
     * Signature verification method
     * @param plain
     * @param signatureByte
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws IOException
     * @throws SignatureException
     * @throws InvalidKeySpecException
     */
    private static boolean verify(String plain, byte[] signatureByte) throws NoSuchAlgorithmException, InvalidKeyException, IOException, SignatureException, InvalidKeySpecException {
        //Get public key
        PublicKey publicKey = getPublicKey(PUBLIC_KEY_STR);
        //Obtain the signature object instance according to the corresponding algorithm
        Signature signature = Signature.getInstance("SHA256WithRSA");
        //Initialize signature object
        signature.initVerify(publicKey);
        //Update the original message to the signature object
        signature.update(plain.getBytes("UTF-8"));
        //Conduct signature verification
        return signature.verify(signatureByte);
    }

    private static PublicKey getPublicKey(String publicKeyStr) throws InvalidKeySpecException, IOException {
        PublicKey publicKey = null;
        try {
            java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
                    new BASE64Decoder().decodeBuffer(publicKeyStr));
            // RSA Symmetric encryption algorithm
            java.security.KeyFactory keyFactory;
            keyFactory = java.security.KeyFactory.getInstance("RSA");
            // Generate public key object
            publicKey = keyFactory.generatePublic(bobPubKeySpec);
           } catch (NoSuchAlgorithmException e) {
             e.printStackTrace();
            }
        return publicKey;
      }

    private static PrivateKey getPriveteKey(String privateKeyStr) {
        PrivateKey privateKey = null;
        PKCS8EncodedKeySpec priPKCS8;
        try {
            priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKeyStr));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            privateKey = keyf.generatePrivate(priPKCS8);
        } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return privateKey;
    }
}
 

"Operation result:"

The original message is:Welcome to my official account, the little boy who picks up snails
 Countersignature result:
Oz15/aybGe42eGHbc+iMoSYHSCc8tfRskTVjjGSTPD4HjadL0CC5JUWNUW0WxHjUb4MvxWo2oeWE
Qw0+m61d+JgBMto/TWcVDcgwL/AbObsbWdQ6E/fVRqG13clkE8MyKsjt9Z7tcbwpycYTv0rUR4co
rndAVfBdtv5KeV+OXqM=
Signature verification results:true

Reference

[1] Wikipedia: https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5

[2] Baidu Encyclopedia: https://baike.baidu.com/

[3] Introduction to common message summarization algorithms: https://cloud.tencent.com/developer/article/1584742

[4] On seven common encryption algorithms and their implementation: https://juejin.im/post/5b48b0d7e51d4519962ea383#heading-12

[5] [error prone concept] state secret algorithm SM1 (SCB2), SM2, SM3, SM4, SM7, SM9, ZUC:https://www.jianshu.com/p/8c3657a1769f

Posted by Dragoon1 on Wed, 25 May 2022 02:45:15 +0300