Cifrado y descifrado AES de Android

 El nombre completo del algoritmo AES es Estándar de cifrado avanzado. Se trata de un típico "algoritmo de cifrado simétrico" cuya función principal es garantizar que no se filtre información privada.

1. Clave

La clave es la base para el cifrado y descifrado del algoritmo AES, porque requiere el uso de la misma clave para el cifrado y descifrado de texto sin formato .

AES admite tres longitudes de clave: 128 bits, 192 bits y 256 bits.

2. Llenado

Cuando el algoritmo AES cifra texto sin formato, no cifra todo el texto sin formato en un fragmento de texto cifrado, sino que lo divide en un bloque de texto sin formato independiente. Cada bloque de texto sin formato tiene una longitud de 128 bits, lo que significa que cada bloque de texto sin formato tiene una longitud de 16 bits. Bytes (8 bits por byte).

Modo de llenado:

1. NoPadding: no se realiza ningún relleno, pero el texto sin formato debe ser un múltiplo entero de 16 bytes.

2. PKCS5Padding (predeterminado): si el bloque de texto sin formato tiene menos de 16 bytes (128 bits), el número correspondiente de caracteres se agrega al final del bloque de texto sin formato y el valor de cada byte es igual al número de caracteres que faltan.

Por ejemplo, texto plano: {1,a,3,c,5,k,6,8,l,o}, si faltan 6 bytes, el complemento es {1,a,3,c,5,k,6 ,8 ,l,o, 6,6,6,6,6,6 }

3. Relleno ISO10126: si el bloque de texto sin formato tiene menos de 16 bytes, el número correspondiente de bytes se agrega al final del bloque de texto sin formato, el valor del último carácter es igual al número de palabras que faltan y los demás caracteres se rellenan de forma aleatoria. números.

Por ejemplo, texto sin formato: {1,a,3,c,5,k,6,8,l,o}, si faltan 6 bytes, se puede complementar como {1,a,3,c,5 , k ,6, 8,l,o, 2,i,9,q,7,6 }.

3. Modo

El algoritmo de cifrado AES proporciona diferentes modos de trabajo:

1. Modo ECB (predeterminado): modo Libro de códigos electrónico

2. Modo CBC: Modo de encadenamiento de bloques de cifrado (encadenamiento de bloques de cifrado)

3. Modo CTR: Modo Calculadora (Contador)

4. Modo CFB: modo Cipher FeedBack (Cipher FeedBack)

5. Modo OFB: modo Output FeedBack (Output FeedBack)

4. Cifrado y descifrado en modo AES-CBC

1. Diseño aes_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".AesActivity">

    <EditText
        android:id="@+id/etData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/aesEncryption"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="AES加密" />

    <TextView
        android:id="@+id/tvEncryption"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:gravity="center" />

    <Button
        android:id="@+id/aesDecrypt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="AES解密" />

    <TextView
        android:id="@+id/tvDecrypt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:gravity="center" />
    
</LinearLayout>

2. Código de cifrado y descifrado:

Cree una clase AesUtils:

public class AesUtils {

    private static final String SHA1PRNG = "SHA1PRNG";   // SHA1PRNG 强随机种子算法
    private static final String AES = "AES";   //AES 加密
    private static final String CIPHERMODE = "AES/CBC/PKCS5Padding"; //AES算法/CBC模式/PKCS5Padding填充模式 

    /**
     * 加密
     */
    public static String encrypt(String key, String cleartext) {
        if (TextUtils.isEmpty(cleartext)) {
            return cleartext;
        }
        try {
            byte[] result = encrypt(key, cleartext.getBytes());
            return parseByte2HexStr(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
    * 加密
    */
    public static byte[] encrypt(String key, byte[] clear) throws Exception {
        byte[] raw = getRawKey(key.getBytes());
        SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
        Cipher cipher = Cipher.getInstance(CIPHERMODE);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new         
        byte[cipher.getBlockSize()]));
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    /**
     * 解密
     */
    public static String decrypt(String key, String encrypted) {
        if (TextUtils.isEmpty(encrypted)) {
            return encrypted;
        }
        try {
            byte[] enc = parseHexStr2Byte(encrypted);
            byte[] result = decrypt(key, enc);
            return new String(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     */
    public static byte[] decrypt(String key, byte[] encrypted) throws Exception {
        byte[] raw = getRawKey(key.getBytes());
        SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
        Cipher cipher = Cipher.getInstance(CIPHERMODE);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new 
        byte[cipher.getBlockSize()]));
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }



    /**
     * 处理密钥
     */
    @SuppressLint("DeletedProvider")
    public static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance(AES);
        //for android
        SecureRandom sr = null;
        // 在4.2以上版本中,SecureRandom获取方式发生了改变
        if (android.os.Build.VERSION.SDK_INT >= 17) {
            sr = SecureRandom.getInstance(SHA1PRNG, new CryptoProvider());
        } else {
            sr = SecureRandom.getInstance(SHA1PRNG);
        }
        
        sr.setSeed(seed);
        kgen.init(128, sr); //128bits,192bits,256bits
        //AES中128位密钥,加密轮次为10轮;192位密钥,加密轮次为12轮;256位密钥,加密轮次为14轮。
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    

    /**
     * 将二进制转换成16进制
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
                    16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

 


 public static class CryptoProvider extends Provider {
        public CryptoProvider() {
            super("Crypto", 1.0, "HARMONY(SHA1 digest;SecureRandom;SHA1withDSA signature)");
            put("SecureRandom.SHA1PRNG", "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl");
            put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
        }
    }
}

3. Código de actividad Aes:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class AesActivity extends AppCompatActivity implements View.OnClickListener {

    //AES加密
    private Button aesEncryption;
    private TextView tvEncryption;
    //AES解密
    private Button aesDecrypt;
    private TextView tvDecrypt;
    //输入框
    private EditText etData;

    //加密解密的key
    String key = "1234567890";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aes);

        initView();
    }

    private void initView() {
        aesEncryption = findViewById(R.id.aesEncryption);
        aesDecrypt = findViewById(R.id.aesDecrypt);
        tvEncryption = findViewById(R.id.tvEncryption);
        tvDecrypt = findViewById(R.id.tvDecrypt);
        etData = findViewById(R.id.etData);

        aesEncryption.setOnClickListener(this);
        aesDecrypt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //要加密的字符串
        String encryptData = etData.getText().toString();
        switch (v.getId()) {
            case R.id.aesEncryption://加密
                tvEncryption.setText(AesUtils.encrypt(key, encryptData));
                break;
            case R.id.aesDecrypt://解密
                tvDecrypt.setText(AesUtils.decrypt(key, tvEncryption.getText().toString()));
                break;
            default:
                break;
        }
    }
}

5. Cuadro de resultados

Supongo que te gusta

Origin blog.csdn.net/weixin_58159075/article/details/131912096
Recomendado
Clasificación