Android AES暗号化と復号化

 AES アルゴリズムの正式名は、Advanced Encryption Standard です。個人情報の漏洩を防ぐことを主な役割とする代表的な「対称暗号アルゴリズム」です。

1. キー

平文の暗号化と復号化に同じキーを使用する必要があるため、このキーは AES アルゴリズムの暗号化と復号化の基礎となります

AES は、128 ビット、192 ビット、256 ビットの 3 つのキー長をサポートします。

2.充填

AES アルゴリズムが平文を暗号化する場合、平文全体を 1 つの暗号文に暗号化するのではなく、平文を独立した平文ブロックに分割します。各平文ブロックの長さは 128 ビットです。つまり、各平文ブロックの長さは 16 ビットです。 (1 バイトあたり 8 ビット)。

塗りつぶしモード:

1. NoPadding:パディングは実行されませんが、プレーンテキストは 16 バイトの整数倍でなければなりません。

2. PKCS5Padding (デフォルト): 平文ブロックが 16 バイト (128 ビット) 未満の場合、対応する数の文字が平文ブロックの末尾に追加され、各バイトの値は不足している文字数と等しくなります。

たとえば、平文: {1,a,3,c,5,k,6,8,l,o}、6 バイトが欠落している場合、補数は {1,a,3,c,5,k,6 になります。 ,8 ,l,o, 6,6,6,6,6,6 }

3. ISO10126Padding: 平文ブロックが 16 バイト未満の場合、平文ブロックの末尾に対応するバイト数を追加します。最後の文字の値は欠落している単語の数に等しく、他の文字は乱数で埋められます。 。

たとえば、プレーン テキスト: {1,a,3,c,5,k,6,8,l,o}、6 バイトが不足している場合は、{ 1 ,a,3,c, 5 , k,6,8,l,o, 2,i,9,q,7,6 }。

3. モード

AES 暗号化アルゴリズムは、さまざまな動作モードを提供します。

1. ECB モード (デフォルト): 電子コードブック ブック モード

2. CBCモード:Cipher Block Chainingモード(Cipher Block Chaining)

3. CTRモード:電卓モード(カウンター)

4. CFBモード:Cipher FeedBackモード(Cipher FeedBack)

5. OFBモード:アウトプットフィードバックモード(Output FeedBack)

4. AES-CBC モードの暗号化と復号化

1. 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. 暗号化および復号化コード:

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.AesActivity コード:

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. 結果グラフ

おすすめ

転載: blog.csdn.net/weixin_58159075/article/details/131912096