Android network data transmission security -- AES encryption and decryption (ECB mode)

Introduction to AES

Advanced Encryption Standard Standard (abbreviation: AES), also known as Rijndael encryption in cryptography, is a block encryption standard adopted by the federal government of the United States. This standard is used to replace the original DES, which has been analyzed by many parties and widely used all over the world. After a five-year selection process, the advanced encryption standard was released by the National Institute of standards and Technology (NIST) in FIPS on November 26, 2001 PUB 197 and became a valid standard on May 26, 2002. In 2006, advanced encryption standard has become one of the most popular algorithms in symmetric key encryption.

Password description

Strictly speaking, AES and Rijndael encryption are not exactly the same (although they can be interchanged in practical application), because Rijndael encryption can support a wider range of blocks and key lengths: the block length of AES is fixed at 128 Bit, and the key length can be 128192 or 256 bits; The key and block length used by Rijndael can be an integer multiple of 32 bits, with 128 bits as the lower limit and 256 bits as the upper limit. The key used in the encryption process is generated by Rijndael key generation scheme. Most AES calculations are done in a special finite field. AES encryption process is in a 4 × 4, which is also called "state", and its initial value is a plaintext block (the size of an element in the matrix is a Byte in the plaintext block). (because Rijndael encryption method supports larger blocks, the number of matrix rows can be increased as appropriate) during encryption, each round of AES encryption cycle (except the last round) includes four steps: AddRoundKey - each byte in the matrix performs XOR operation with the round key; Each sub key is generated by the key generation scheme. SubBytes - replace each byte with the corresponding byte by looking up the table through the nonlinear replacement function. ShiftRows — Circularly shift each column in the matrix. MixColumns - to fully mix the operations of each straight line in the matrix. This step uses a linear transformation to mix four bytes per column. In the last encryption loop, omit the MixColumns step and replace it with another AddRoundKey.

Encryption standard

The development trend of symmetric cryptosystem will focus on block cipher. Block cipher algorithm is usually composed of key expansion algorithm and encryption (decryption) algorithm. The key expansion algorithm expands the b-byte user master key into R sub key. The encryption algorithm consists of a cryptographic weak function f and R sub key iterations r times. Chaos and key diffusion are the basic principles of block cipher algorithm design. To resist the differential and linear attacks of known plaintext, variable length key and packet are the design points of the system. AES is the 21st century encryption standard designed by NIST to replace DES. The basic requirement of AES is to adopt symmetric block cipher system, the minimum length of key is 128, 192 and 256, and the packet length is 128 bits. The algorithm should be easy to implement in various hardware and software. In 1998, NIST began the first round of AES analysis, testing and solicitation, and a total of 15 candidate algorithms were generated. The second round of AES2 analysis and testing was completed in March 1999. On October 2, 2000, the United States government officially announced the selection of Belgian Cryptologist Joan A cryptographic algorithm RIJNDAEL proposed by Daemen and Vincent Rijmen is used as AES In terms of application, although DES is fragile in security, des can still be used temporarily due to the rapid mass production of Des chips. In order to improve the security strength, three-level DES with independent key is usually used. But des will be replaced by AES sooner or later. Stream cipher system is more mature and secure than block cipher in theory, but it is not included in the next generation encryption standard. The packet length of AES encrypted data block must be 128 bits, and the key length can be any of 128 bits, 192 bits and 256 bits (it will be supplemented if the data block and key length are insufficient). AES encryption has many rounds of repetition and transformation. The general steps are as follows: 1. Key expansion; 2. Initial round Round, 3. Repeat Rounds, and each round includes: SubBytes, ShiftRows, MixColumns, AddRoundKey, 4. Final Round), the final round does not have MixColumns.

code

AESECBActivity

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import tsou.com.encryption.R;
import tsou.com.encryption.aesecb.AESUtils;

/**
 * ECB Mode self setting key
 */
public class AESECBActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText encryptionContext;
    private Button encryption;
    private TextView tvEncryption;
    private Button decode;
    private TextView tvDecode;
    private Activity mActivity;
    private Context mContext;
    private String key = "huangxiaoguo1234";//Must be 16 bits
    private byte[] encrypt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aes);
        mActivity = this;
        mContext = this;
        encryptionContext = (EditText) findViewById(R.id.et_encryption_context);
        encryption = (Button) findViewById(R.id.btn_encryption);
        tvEncryption = (TextView) findViewById(R.id.tv_encryption);
        decode = (Button) findViewById(R.id.btn_decode);
        tvDecode = (TextView) findViewById(R.id.tv_decode);
        initListener();
    }

    private void initListener() {
        encryption.setOnClickListener(this);
        decode.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_encryption://encryption
                String encryptionString = encryptionContext.getText().toString().trim();
                if (TextUtils.isEmpty(encryptionString)) {
                    Toast.makeText(mContext, "Please enter the encrypted content", Toast.LENGTH_SHORT).show();
                    return;
                }
                encrypt = AESUtils.encrypt(encryptionString.getBytes(), key.getBytes());
                tvEncryption.setText(new String(encrypt));
                break;
            case R.id.btn_decode://decrypt
                String decodeString = tvEncryption.getText().toString().trim();
                if (TextUtils.isEmpty(decodeString)) {
                    Toast.makeText(mContext, "Please encrypt first", Toast.LENGTH_SHORT).show();
                    return;
                }
                byte[] decrypt = AESUtils.decrypt(encrypt, key.getBytes());
                tvDecode.setText(new String(decrypt));
                break;
        }
    }
}

AESUtils

package tsou.com.encryption.aesecb;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES Encrypt Decrypt  
 *  
 * @author huangxiaoguo
 */  
public class AESUtils {  

    /** 
     * AES encryption 
     *  
     * @param data 
     *            Content to be encrypted 
     * @param key 
     *            secret key 
     * @return Encrypted content 
     */  
    public static byte[] encrypt(byte[] data, byte[] key) {  
        //If it is less than 16 bytes, the supplementary content is the difference  
        int len = 16 - data.length % 16;  
        for (int i = 0; i < len; i++) {  
            byte[] bytes = { (byte) len };  
            data = ArrayUtils.concat(data, bytes);  
        }  
        try {  
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);  
            return cipher.doFinal(data);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return new byte[] {};  
    }  

    /** 
     * AES decrypt 
     *  
     * @param data 
     *            Content to be decrypted 
     * @param key 
     *            secret key 
     * @return Decrypted content 
     */  
    public static byte[] decrypt(byte[] data, byte[] key) {  
        data = ArrayUtils.noPadding(data, -1);  
        try {  
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");  
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");  
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);  
            byte[] decryptData = cipher.doFinal(data);  
            int len = 2 + ByteUtils.byteToInt(decryptData[4]) + 3;  
            return ArrayUtils.noPadding(decryptData, len);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return new byte[] {};  
    }  

ArrayUtils

package tsou.com.encryption.aesecb;

/**
 * Array tool 
 *  
 * @author huangxiaoguo
 */  
public class ArrayUtils {  

    /** 
     * Merge array 
     *  
     * @param firstArray 
     *            First array 
     * @param secondArray 
     *            Second array 
     * @return Merged array 
     */  
    public static byte[] concat(byte[] firstArray, byte[] secondArray) {  
        if (firstArray == null || secondArray == null) {  
            return null;  
        }  
        byte[] bytes = new byte[firstArray.length + secondArray.length];  
        System.arraycopy(firstArray, 0, bytes, 0, firstArray.length);  
        System.arraycopy(secondArray, 0, bytes, firstArray.length,  
                secondArray.length);  
        return bytes;  
    }  

    /** 
     * Remove complement from array 
     *  
     * @param paddingBytes 
     *            Source array 
     * @param dataLength 
     *            Data length after removal of complement 
     * @return Remove the complemented array 
     */  
    public static byte[] noPadding(byte[] paddingBytes, int dataLength) {  
        if (paddingBytes == null) {  
            return null;  
        }  

        byte[] noPaddingBytes = null;  
        if (dataLength > 0) {  
            if (paddingBytes.length > dataLength) {  
                noPaddingBytes = new byte[dataLength];  
                System.arraycopy(paddingBytes, 0, noPaddingBytes, 0, dataLength);  
            } else {  
                noPaddingBytes = paddingBytes;  
            }  
        } else {  
            int index = paddingIndex(paddingBytes);  
            if (index > 0) {  
                noPaddingBytes = new byte[index];  
                System.arraycopy(paddingBytes, 0, noPaddingBytes, 0, index);  
            }  
        }  

        return noPaddingBytes;  
    }  

    /** 
     * Get the location of the replenishment 
     *  
     * @param paddingBytes 
     *            Source array 
     * @return Complementary position 
     */  
    private static int paddingIndex(byte[] paddingBytes) {  
        for (int i = paddingBytes.length - 1; i >= 0; i--) {  
            if (paddingBytes[i] != 0) {  
                return i + 1;  
            }  
        }  
        return -1;  
    }  
}

ByteUtils

package tsou.com.encryption.aesecb;

public class ByteUtils {
    public static int byteToInt(byte b) {
        return (b) & 0xff;
    }
}

Added by e11even on Mon, 10 Jan 2022 09:40:14 +0200