android接口加密实现方案

转载请注明出处:https://blog.csdn.net/u011038298/article/details/87921272

Fiddler抓包工具配置

android接口如何防抓取

Windows下使用OpenSSL生成RSA证书

1.程序主类

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.EditText;

/**
 * 实现方案/思路:
 * Android端的加密需要4步:
 * 1.随机生成AES密钥
 * 2.根据AES秘钥对数据进行加密
 * 3.使用RSA公钥加密刚刚生成的AES密钥
 * 4.将AES加密过的数据  和  被RSA加密过的AES秘钥  传给服务端
 * <p>
 * 服务端的解密只需3步:
 * 1.获取到客户端传过来的数据
 * 2.使用RSA私钥解密从客户端拿到的“被RSA加密过的AES秘钥”
 * 3.再使用解密出来的AES秘钥来解密被AES加密过的数据
 * <p>
 * 这里需要理解的地方:
 * 1.RSA是公开秘钥系统的代表,可以通过OpenSSL生成RSA证书,拿到公钥和私钥。
 * 2.RSA的公钥用来加密,私钥用来解密。可以这样理解:客户端锁了门,钥匙在服务端那里。
 * 3.RSA加/解密速度慢,不适合大量的数据进行加/解密,它是不对称加密方式。
 * 4.AES加密速度很快,它是对称密码方式,即加密和解密使用同一个密钥的加密方式。
 * <p>
 * 理解了以上之后,我们就很容易想到使用RSA+AES相结合的方式,发挥它们共同的优点来实现一种新的数据加密方案
 */

public class MainActivity extends AppCompatActivity {

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

        /**
         * 账号密码的输入框
         */
        EditText etId = findViewById(R.id.etId);
        EditText etPassword = findViewById(R.id.etPassword);
        etId.setText("admin");
        etPassword.setText("test123456");

        // 客户端加密
        clientEncryption(etId.getText().toString(), etPassword.getText().toString());
    }

    /**
     * 客户端加密账号和密码,并传值给服务端
     * id:账号
     * password:密码
     */
    private void clientEncryption(String id, String password) {
        /**
         * 客户端随机生成一个AES秘钥
         */
        String key = AESUtils.getRandomKey();

        /**
         * 经过客户端加密过后的:账号和密码字符串
         */
        String encryptId = AESUtils.encrypt(id, key);
        String encryptPassword = AESUtils.encrypt(password, key);

        /**
         * 根据RSA的公钥,先对随机产生的AES秘钥进行加密
         */
        String encryptKey = "";
        try {
            encryptKey = RSAUtils.encryptByPublicKey(key, RSAUtils.loadPublicKey(RSAUtils.rsa_public_key));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 传值给服务端,并且服务端进行解密
        serverDecryption(encryptId, encryptPassword, encryptKey);
    }

    /**
     * 服务端解密来自客户端的账号和密码
     * encryptId:加密过的账号
     * encryptPassword:加密过的密码
     * encryptKey:加密过的AES密钥
     */
    private void serverDecryption(String encryptId, String encryptPassword, String encryptKey) {
        /**
         * 根据RSA的私钥进行解密,拿到AES的秘钥
         */
        String decryptKey = "";
        try {
            decryptKey = RSAUtils.decryptByPrivateKey(encryptKey, RSAUtils.loadPrivateKey(RSAUtils.private_key));
        } catch (Exception e) {
            e.printStackTrace();
        }

        /**
         * 根据AES秘钥对账号和密码进行AES解密,拿到原文
         */
        String decryptId = AESUtils.decrypt(encryptId, decryptKey);
        String decryptPassword = AESUtils.decrypt(encryptPassword, decryptKey);

        Log.i("TAG", "服务端解密出来的数据,账号:" + decryptId + "  密码:" + decryptPassword);
    }

}

2.RSA加/解密的工具类

import android.util.Base64;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;

public class RSAUtils {

    // 使用OpenSSL生成的RSA私钥 (存放于服务端)
    public final static String private_key = "MIICXQIBAAKBgQDOwViN4uF/aPIBxwzKytEGiYhQA19srihpYfqPFQSiTGR2N0Hp" +
            "igwanfKNk33cyHTBIcAUUnDiScHXptC8RoSgIS7O9iDUzN/TOV1DkDIzuQ8ySpG1" +
            "n/4fospFKrNs+j5cXbm8sMMDG9GvnI9svi3wW1+pnrFvXWXjxi0oZ+lkHwIDAQAB" +
            "AoGAaK6gRYagIcBi999ubKbv2l18NPbgM8iiEWlYUWWU6Q/AtdIYf0Q0CK38Bw6s" +
            "ZULhSn/qHt/247vwd12wxgL2Vqw9JlGVfESMXbOq4juHEXqNdDgC/H/Tx771uLgp" +
            "dEIEjVHyXwfbuVd16GKP205FisJP5+Rr13IzkdAYz1WdKOECQQDnQrAqHmrNICOB" +
            "DwsF37gnx+gCVhbj+FB0m/y+p6eG0x1VZwcYSf+lH8ac6ktQBOQK2JL5NTOb4arc" +
            "oMVyIPY3AkEA5N+OUdX2EqFZV53Ha1/56WRufDUaySq8mM567O6PGEhlFESw+vEE" +
            "651AIOUax2qqBrh6feTRwEoorrVzSCUNWQJAHaCBiSPUcusHIWWX9+ytXwtRQdtd" +
            "m18Yj5fcTWCVKcSqIWLNmeMBCVqEy12IwHuf63PLgHm8XuAOT62ZHgHzCQJBAMVK" +
            "6PYmiL66k7dxbSxkSZwlVRCA/pwW2QioRVLkujlmfqugIyfOiD1LCrLQi+sHSZYN" +
            "hJntm9o0kyk3hS7VsdECQQClqdqDmCY0LXGLl4LChtsWvieHhy2QE81kd6zxb5MB" +
            "U/387n/UfGD448/nJ19dmDeq+XNIb1nK9cOMvTPb1OYA";

    // 使用OpenSSL生成的RSA公钥 (存放于客户端)
    public final static String rsa_public_key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOwViN4uF/aPIBxwzKytEGiYhQ" +
            "A19srihpYfqPFQSiTGR2N0HpigwanfKNk33cyHTBIcAUUnDiScHXptC8RoSgIS7O" +
            "9iDUzN/TOV1DkDIzuQ8ySpG1n/4fospFKrNs+j5cXbm8sMMDG9GvnI9svi3wW1+p" +
            "nrFvXWXjxi0oZ+lkHwIDAQAB";

    /**
     * 通过公钥加密
     *
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
            throws Exception {
        // 模长
        int key_len = publicKey.getModulus().bitLength() / 8;
        // 加密数据长度 <= 模长-11
        String[] array = splitString(data, key_len - 11);
        String mi = "";
        // 如果明文长度大于模长-11则要分组加密
        for (String s : array) {
            mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));
        }
        return mi;
    }

    /**********************************************************************************************/

    private static final String ALGORITHM = "RSA";
    private static final String TRANSFORMATION = "RSA";

    /**
     * 从文件中输入流中加载公钥
     *
     * @param in 公钥输入流
     * @throws Exception 加载公钥时产生的异常
     */
    public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                if (readLine.charAt(0) == '-') {
                    continue;
                } else {
                    sb.append(readLine);
                    sb.append('\r');
                }
            }
            return loadPublicKey(sb.toString());
        } catch (IOException e) {
            throw new Exception("公钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("公钥输入流为空");
        }
    }

    /**
     * 从字符串中加载公钥
     *
     * @param publicKeyStr 公钥数据字符串
     * @return
     * @throws Exception 加载公钥时产生的异常
     */
    public static RSAPublicKey loadPublicKey(String publicKeyStr)
            throws Exception {
        try {
            byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("公钥非法");
        } catch (NullPointerException e) {
            throw new Exception("公钥数据为空");
        }
    }

    /**
     * 从文件中加载私钥
     *
     * @param in 私钥输入流
     * @return
     * @throws Exception
     */
    public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                if (readLine.charAt(0) == '-') {
                    continue;
                } else {
                    sb.append(readLine);
                    sb.append('\r');
                }
            }
            return loadPrivateKey(sb.toString());
        } catch (IOException e) {
            throw new Exception("私钥数据读取错误");
        } catch (NullPointerException e) {
            throw new Exception("私钥输入流为空");
        }
    }

    /**
     * 从字符串中加载私钥
     *
     * @param privateKeyStr 私钥字符串
     * @return
     * @throws Exception
     * @desc
     */
    public static RSAPrivateKey loadPrivateKey(String privateKeyStr)
            throws Exception {
        try {
            byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }
    }

    /**
     * 公钥加密
     *
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     * @desc
     */
    public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)
            throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥加密
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     * @desc
     */
    public static byte[] encryptByPrivateKey(byte[] data,
                                             RSAPrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }


    /**
     * 私钥加密
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     * @desc
     */
    public static String encryptByPrivateKey(String data,
                                             RSAPrivateKey privateKey) throws Exception {
        // 模长
        int key_len = privateKey.getModulus().bitLength() / 8;
        // 加密数据长度 <= 模长-11
        String[] datas = splitString(data, key_len - 11);
        String mi = "";
        // 如果明文长度大于模长-11则要分组加密
        for (String s : datas) {
            mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));
        }
        return mi;
    }

    /**
     * 私钥解密
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data,
                                             RSAPrivateKey privateKey) throws Exception {
        // 模长
        int key_len = privateKey.getModulus().bitLength() / 8;
        byte[] bytes = data.getBytes();
        byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
        // 如果密文长度大于模长则要分组解密
        String ming = "";
        byte[][] arrays = splitArray(bcd, key_len);
        for (byte[] arr : arrays) {
            ming += new String(decryptByPrivateKey(arr, privateKey));
        }
        return ming;
    }

    /**
     * 私钥解密
     *
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     * @desc
     */
    public static byte[] decryptByPrivateKey(byte[] data,
                                             RSAPrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公钥解密
     *
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     * @desc
     */
    public static String decryptByPublicKey(String data,
                                            RSAPublicKey publicKey) throws Exception {
        // 模长
        int key_len = publicKey.getModulus().bitLength() / 8;
        byte[] bytes = data.getBytes();
        byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
        // 如果密文长度大于模长则要分组解密
        String ming = "";
        byte[][] arrays = splitArray(bcd, key_len);
        for (byte[] arr : arrays) {
            ming += new String(decryptByPublicKey(arr, publicKey));
        }
        return ming;
    }

    /**
     * 公钥解密
     *
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     * @desc
     */
    public static byte[] decryptByPublicKey(byte[] data,
                                            RSAPublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * ASCII码转BCD码
     */
    private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
        byte[] bcd = new byte[asc_len / 2];
        int j = 0;
        for (int i = 0; i < (asc_len + 1) / 2; i++) {
            bcd[i] = asc_to_bcd(ascii[j++]);
            bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
        }
        return bcd;
    }

    private static byte asc_to_bcd(byte asc) {
        byte bcd;

        if ((asc >= '0') && (asc <= '9'))
            bcd = (byte) (asc - '0');
        else if ((asc >= 'A') && (asc <= 'F'))
            bcd = (byte) (asc - 'A' + 10);
        else if ((asc >= 'a') && (asc <= 'f'))
            bcd = (byte) (asc - 'a' + 10);
        else
            bcd = (byte) (asc - 48);
        return bcd;
    }

    /**
     * BCD转字符串
     */
    private static String bcd2Str(byte[] bytes) {
        char temp[] = new char[bytes.length * 2], val;

        for (int i = 0; i < bytes.length; i++) {
            val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
            temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

            val = (char) (bytes[i] & 0x0f);
            temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
        }
        return new String(temp);
    }

    /**
     * 拆分字符串
     */
    private static String[] splitString(String string, int len) {
        int x = string.length() / len;
        int y = string.length() % len;
        int z = 0;
        if (y != 0) {
            z = 1;
        }
        String[] strings = new String[x + z];
        String str = "";
        for (int i = 0; i < x + z; i++) {
            if (i == x + z - 1 && y != 0) {
                str = string.substring(i * len, i * len + y);
            } else {
                str = string.substring(i * len, i * len + len);
            }
            strings[i] = str;
        }
        return strings;
    }

    /**
     * 拆分数组
     */
    private static byte[][] splitArray(byte[] data, int len) {
        int x = data.length / len;
        int y = data.length % len;
        int z = 0;
        if (y != 0) {
            z = 1;
        }
        byte[][] arrays = new byte[x + z][];
        byte[] arr;
        for (int i = 0; i < x + z; i++) {
            arr = new byte[len];
            if (i == x + z - 1 && y != 0) {
                System.arraycopy(data, i * len, arr, 0, y);
            } else {
                System.arraycopy(data, i * len, arr, 0, len);
            }
            arrays[i] = arr;
        }
        return arrays;
    }

}

3.AES加/解密的工具类

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtils {

    /**
     * 随机生成一个AES密钥字符串
     *
     * @return
     */
    public static String getRandomKey() {
        return byte2hex(generateKey().getEncoded());
    }

    /**
     * 加密数据,通过String类型的密钥加密String
     *
     * @param content
     * @param key
     * @return 16进制密文字符串
     */
    public static String encrypt(String content, String key) {
        byte[] data = null;
        try {
            data = content.getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = encrypt(data, new SecretKeySpec(hex2byte(key), "AES").getEncoded());
        String result = byte2hex(data);
        return result;
    }

    /**********************************************************************************************/

    private static final String CipherMode = "AES/ECB/PKCS5Padding";

    /**
     * 生成一个AES密钥对象
     *
     * @return
     */
    public static SecretKeySpec generateKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128, new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            return key;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密字节数据
     *
     * @param content
     * @param key
     * @return
     */
    public static byte[] encrypt(byte[] content, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过byte[]类型的密钥加密String
     *
     * @param content
     * @param key
     * @return 16进制密文字符串
     */
    public static String encrypt(String content, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] data = cipher.doFinal(content.getBytes("UTF-8"));
            String result = byte2hex(data);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过byte[]类型的密钥解密byte[]
     *
     * @param content
     * @param key
     * @return
     */
    public static byte[] decrypt(byte[] content, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过String类型的密钥 解密String类型的密文
     *
     * @param content
     * @param key
     * @return
     */
    public static String decrypt(String content, String key) {
        byte[] data = null;
        try {
            data = hex2byte(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        data = decrypt(data, hex2byte(key));
        if (data == null)
            return null;
        String result = null;
        try {
            result = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 通过byte[]类型的密钥 解密String类型的密文
     *
     * @param content
     * @param key
     * @return
     */
    public static String decrypt(String content, byte[] key) {
        try {
            Cipher cipher = Cipher.getInstance(CipherMode);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] data = cipher.doFinal(hex2byte(content));
            return new String(data, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 字节数组转成16进制字符串
     *
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) { // 一个字节的数,
        StringBuffer sb = new StringBuffer(b.length * 2);
        String tmp = "";
        for (int n = 0; n < b.length; n++) {
            // 整数转成十六进制表示
            tmp = (Integer.toHexString(b[n] & 0XFF));
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString().toUpperCase(); // 转成大写
    }

    /**
     * 将hex字符串转换成字节数组
     *
     * @param inputString
     * @return
     */
    private static byte[] hex2byte(String inputString) {
        if (inputString == null || inputString.length() < 2) {
            return new byte[0];
        }
        inputString = inputString.toLowerCase();
        int l = inputString.length() / 2;
        byte[] result = new byte[l];
        for (int i = 0; i < l; ++i) {
            String tmp = inputString.substring(2 * i, 2 * i + 2);
            result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
        }
        return result;
    }

}

猜你喜欢

转载自blog.csdn.net/u011038298/article/details/87921272
今日推荐