Android开发笔记之数据传输中的常见加密AES\DES\DES3\RSA

在做项目时,一些重要的数据用到了加密,记录下系统提供的这几种常见的加密数据方式的使用(不是原理):

对称加密 AES\DES\DES3

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。

AES、DES、DES3 的简单介绍

加密模式有五种:

  • 电码本模式(Electronic Codebook Book (ECB))(不需要向量)
  • 密码分组链接模式(Cipher Block Chaining (CBC))
  • 计算器模式(Counter (CTR))
  • 密码反馈模式(Cipher FeedBack (CFB))
  • 输出反馈模式(Output FeedBack (OFB))

填充方式:

  • NoPadding
  • PKCS5Padding
  • PKCS7Padding

密钥长度可以是128,192或256比特,也就是16,24或32位字节
密钥向量长度只能是8位字节

AES、DES、DES3 的使用

加密(AES、DES、DES3这三种通用):

注:这里默认使用的是填充方式pkcs5padding

    /**
     * 加解密方式
     */
    enum Encryption {
        AES,   // Key length must 16/24/32 bytes   IV length must 16 bytes
        DES,   // Key、IV  8 bytes
        DES3   // Key 16 or 24 bytes.  IV  8 bytes
    }

    /**
     * 加解密模式
     */
    enum EncryptMode {
        ECB,
        CBC,
        CTR,
        OFB,
        CFB
    }

   /**
     * 先AES 加密,再通过Base64加密
     * @param str   需要加密的字符串
     * @param strKey  加密的密钥key
     * @param strIv   加密的向量iv
     * @param mode    加密模式ECB
     *                 模式的填充方式的 PKCS5Padding
     *                 需要Padding的有:CBC(,PCBC也需要,本文未涉及该加密模式)、ECB。
                       不需要Padding的有:CFB、OFB、CTR
     * @return
     */
    public static String AesDesEncrypt(String str,String strKey,String strIv,Encryption encryption,EncryptMode mode){
        if (TextUtils.isEmpty(str) || TextUtils.isEmpty(strKey))
            return null;
        String strMode = null;
        String strEncryption = null;
        switch (encryption){
            case AES:
                strEncryption = "AES";
                break;
            case DES:
                strEncryption = "DES";
                break;
            case DES3:
                strEncryption = "DESede";
                break;
        }
        switch (mode){
            case ECB:
                return EcbEncrypt(str,strKey,strEncryption);
            case CBC:
                strMode = "CBC";
                break;
            case CTR:
                strMode = "CTR";
                break;
            case OFB:
                strMode = "OFB";
                break;
            case CFB:
                strMode = "CFB";
                break;
            default:
                return null;
        }
        if(TextUtils.isEmpty(strIv))
            return null;
        try {
            byte[] raw = strKey.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, strEncryption);
            Cipher cipher = Cipher.getInstance(String.format("%s/%s/PKCS5Padding",strEncryption,strMode));
            IvParameterSpec iv = new IvParameterSpec(strIv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encryptBytes = cipher.doFinal(str.getBytes());
            return Base64.encodeToString(encryptBytes, Base64.NO_WRAP);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * ECB方式加密
     * @return
     */
    private static String EcbEncrypt(String str,String key,String encryption){
        try {
            Cipher cipher = Cipher.getInstance(String.format("%s/ECB/pkcs5padding",encryption));
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), encryption));
            byte[] bytes = cipher.doFinal(str.getBytes("utf-8"));
            return Base64.encodeToString(bytes, Base64.NO_WRAP);   //注 Base64.DEFAULT 加密后有\n
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

解密(AES、DES、DES3这三种通用):

     /**
     * 先通过Base64解密,再AES 解密
     * @param str   需要解密的字符串
     * @param strKey  解密的密钥key
     * @param strIv   解密的向量iv
     * @param mode    解密模式ECB
     *                 模式的填充方式的 PKCS5Padding
     * @return
     */
    public static String AesDesDecrypt(String str,String strKey,String strIv,Encryption encryption,EncryptMode mode){
        if (TextUtils.isEmpty(str) || TextUtils.isEmpty(strKey))
            return null;
        String strMode = null;
        String strEncryption = null;
        switch (encryption){
            case AES:
                strEncryption = "AES";
                break;
            case DES:
                strEncryption = "DES";
                break;
            case DES3:
                strEncryption = "DESede";
                break;
        }
        switch (mode){
            case ECB:
                return EcbDecrypt(str,strKey,strEncryption);
            case CBC:
                strMode = "CBC";
                break;
            case CTR:
                strMode = "CTR";
                break;
            case OFB:
                strMode = "OFB";
                break;
            case CFB:
                strMode = "CFB";
                break;
            default:
                return null;
        }
        if(TextUtils.isEmpty(strIv))
            return null;
        try {
            byte[] raw = strKey.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, strEncryption);
            Cipher cipher = Cipher.getInstance(String.format("%s/%s/PKCS5Padding",strEncryption,strMode));
            IvParameterSpec iv = new IvParameterSpec(strIv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] decryptBytes = cipher.doFinal(Base64.decode(str.getBytes("utf-8"), Base64.NO_WRAP));
            return new String(decryptBytes, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * ECB方式解密
     * @return
     */
    private static String EcbDecrypt(String str,String key,String encryption){
        try {
            Cipher cipher = Cipher.getInstance(String.format("%s/ECB/PKCS5Padding",encryption));
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), encryption));
            byte[] bytes = cipher.doFinal(Base64.decode(str.getBytes("utf-8"), Base64.NO_WRAP));
            return new String(bytes, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

使用:

注:密钥key和向量IV随机输入的,也可以代码随机生成

    /**
     * AES 加密的密钥key 和向量 iv
     * Key 长度 16/24/32 bytes   IV 长度 16 bytes
     */
    private String AES_KEY = "adjiganaadjigana";
    private String AES_IV = "adjiganaadjigana";


    /**
     * DES 加密的密钥key 和向量 iv
     * 密钥和向量长度 必须为8
     */
    private String DES_KEY = "adjigana";
    private String DES_IV = "adjigana";

    /**
     * DES3 加密的密钥key 和向量 iv
     * key 长度 16 or 24 bytes. 必须为8
     */
    private String DES3_KEY = "asdjdsgnasgeaeesiaskdfje";
    private String DES3_IV = "adjigana";

    /**
     * 测试原数据  AES  DES  DES3
     */
    private String strTestData = "MainActivity";


        Log.e("test","-----------  :" + "加密结果 " + "                  解密结果 ");
        //Key length must 128/192/256 bits   IV length must 16 bytes
        String AesEncryptECB = EncryUtils.AesDesEncrypt(strTestData,AES_KEY,"",EncryUtils.Encryption.AES, EncryUtils.EncryptMode.ECB);
        Log.e("test","AES ----- ECB:"+ AesEncryptECB +  "   " + EncryUtils.AesDesDecrypt(AesEncryptECB,AES_KEY,"", EncryUtils.Encryption.AES,EncryUtils.EncryptMode.ECB));

        String AesEncryptCBC = EncryUtils.AesDesEncrypt(strTestData,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CBC);
        Log.e("test","AES ----- CBC:"+ AesEncryptCBC +  "   " + EncryUtils.AesDesDecrypt(AesEncryptCBC,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CBC));

        String AesEncryptCFB = EncryUtils.AesDesEncrypt(strTestData,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CFB);
        Log.e("test","AES ----- CFB:"+ AesEncryptCFB +  "   " + EncryUtils.AesDesDecrypt(AesEncryptCFB,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CFB));

        String AesEncryptCTR = EncryUtils.AesDesEncrypt(strTestData,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CTR);
        Log.e("test","AES ----- CTR:"+ AesEncryptCTR +  "   " + EncryUtils.AesDesDecrypt(AesEncryptCTR,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.CTR));

        String AesEncryptOFB = EncryUtils.AesDesEncrypt(strTestData,AES_KEY,AES_IV,EncryUtils.Encryption.AES, EncryUtils.EncryptMode.OFB);
        Log.e("test","AES ----- OFB:"+ AesEncryptOFB +  "   " + EncryUtils.AesDesDecrypt(AesEncryptOFB,AES_KEY,AES_IV, EncryUtils.Encryption.AES,EncryUtils.EncryptMode.OFB));


        String DesEncryptECB = EncryUtils.AesDesEncrypt(strTestData,DES_KEY,"",EncryUtils.Encryption.DES, EncryUtils.EncryptMode.ECB);
        Log.e("test","DES ----- ECB:"+ DesEncryptECB +  "   " + EncryUtils.AesDesDecrypt(DesEncryptECB,DES_KEY,"", EncryUtils.Encryption.DES,EncryUtils.EncryptMode.ECB));

        String DesEncryptCBC = EncryUtils.AesDesEncrypt(strTestData,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CBC);
        Log.e("test","DES ----- CBC:"+ DesEncryptCBC +  "   " + EncryUtils.AesDesDecrypt(DesEncryptCBC,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CBC));

        String DesEncryptCFB = EncryUtils.AesDesEncrypt(strTestData,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CFB);
        Log.e("test","DES ----- CFB:"+ DesEncryptCFB +  "   " + EncryUtils.AesDesDecrypt(DesEncryptCFB,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CFB));

        String DesEncryptCTR = EncryUtils.AesDesEncrypt(strTestData,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CTR);
        Log.e("test","DES ----- CTR:"+ DesEncryptCTR +  "   " + EncryUtils.AesDesDecrypt(DesEncryptCTR,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.CTR));

        String DesEncryptOFB = EncryUtils.AesDesEncrypt(strTestData,DES_KEY,DES_IV,EncryUtils.Encryption.DES, EncryUtils.EncryptMode.OFB);
        Log.e("test","DES ----- OFB:"+ DesEncryptOFB +  "   " + EncryUtils.AesDesDecrypt(DesEncryptOFB,DES_KEY,DES_IV, EncryUtils.Encryption.DES,EncryUtils.EncryptMode.OFB));


        String Des3EncryptECB = EncryUtils.AesDesEncrypt(strTestData,DES3_KEY,"",EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.ECB);
        Log.e("test","DES3----- ECB:"+ Des3EncryptECB +  "   " + EncryUtils.AesDesDecrypt(Des3EncryptECB,DES3_KEY,"", EncryUtils.Encryption.DES3,EncryUtils.EncryptMode.ECB));

        String Des3EncryptCBC = EncryUtils.AesDesEncrypt(strTestData,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CBC);
        Log.e("test","DES3----- CBC:"+ Des3EncryptCBC +  "   " + EncryUtils.AesDesDecrypt(Des3EncryptCBC,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CBC));

        String Des3EncryptCFB = EncryUtils.AesDesEncrypt(strTestData,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CFB);
        Log.e("test","DES3----- CFB:"+ Des3EncryptCFB +  "   " + EncryUtils.AesDesDecrypt(Des3EncryptCFB,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CFB));

        String Des3EncryptCTR = EncryUtils.AesDesEncrypt(strTestData,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CTR);
        Log.e("test","DES3----- CTR:"+ Des3EncryptCTR +  "   " + EncryUtils.AesDesDecrypt(Des3EncryptCTR,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.CTR));

        String Des3EncryptOFB = EncryUtils.AesDesEncrypt(strTestData,DES3_KEY,DES3_IV,EncryUtils.Encryption.DES3, EncryUtils.EncryptMode.OFB);
        Log.e("test","DES3----- OFB:"+ Des3EncryptOFB +  "   " + EncryUtils.AesDesDecrypt(Des3EncryptOFB,DES3_KEY,DES3_IV, EncryUtils.Encryption.DES3,EncryUtils.EncryptMode.OFB));


//结果打印:
-----------  :加密结果                   解密结果 
AES ----- ECB:+fm/DlMcKrTzXsI6K8K7DQ==   MainActivity
AES ----- CBC:RLUOIuFLn9Zni1hX5IsYEQ==   MainActivity
AES ----- CFB:XWAyrMAJTf85G/cbG/boWg==   MainActivity
AES ----- CTR:XWAyrMAJTf85G/cbG/boWg==   MainActivity
AES ----- OFB:XWAyrMAJTf85G/cbG/boWg==   MainActivity
DES ----- ECB:0+EYSR8mKeLmcCc/EwBnEw==   MainActivity
DES ----- CBC:wjlJm8sXFOVBdKEmYpVMdA==   MainActivity
DES ----- CFB:A7BTeblDVsLJLU0HHQV7WA==   MainActivity
DES ----- CTR:A7BTeblDVsJQ3pKy2fp7FA==   MainActivity
DES ----- OFB:A7BTeblDVsKRzzVhqB0djA==   MainActivity
DES3----- ECB:eCGQso2m9erT3oCsWQgQ8w==   MainActivity
DES3----- CBC:qHYReGQi3uTr7ZOyaxjj/w==   MainActivity
DES3----- CFB:pmtnb3L7IbrYP1bu4qdWmg==   MainActivity
DES3----- CTR:pmtnb3L7IbqzXwIZ0gzpeQ==   MainActivity
DES3----- OFB:pmtnb3L7IbrtZBB1H5No3Q==   MainActivity

非对称加密 RSA

RSA 的简单介绍(每次加密结果不一样,公私钥加解密相对应)

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。
RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

公私钥的生成

通过以下代码生成或者在这个工具网http://web.chacuo.net/netrsakeypair

    /**
     * 生成RSA key
     * 网上生成密钥对  http://web.chacuo.net/netrsakeypair
     */
    private void createRsaKey(){
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            //密钥位数
            keyPairGen.initialize(1024);
            //密钥对
            KeyPair keyPair = keyPairGen.generateKeyPair();
            // 公钥
            PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 私钥
            PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            String publicKeyString = getKeyString(publicKey);
            Log.e("test","--------- public:\n" + publicKeyString);

            String privateKeyString = getKeyString(privateKey);
            Log.e("test","--------- private:\n" + privateKeyString);

            Log.e("test","------ Public Modulus  :" + ((RSAPublicKey)publicKey).getModulus().toString(16));
            Log.e("test","------ Public Exponent :" + ((RSAPublicKey)publicKey).getPublicExponent());

            Log.e("test","------ private Modulus  :" + ((RSAPrivateKey)privateKey).getModulus().toString(16));
            Log.e("test","------ private Exponent :" + ((RSAPrivateKey)privateKey).getPrivateExponent().toString(16));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


//结果输出
--------- public:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZxEp9h5xf6tm6M3PDoY3z2iY6mN0NY1vxh6moO1TmNtyBqThoEU8mrYu/9SAqNiWxdb3s5XTXI/zPnZCuHPHpfeO2L2BuA0IU3vtKlOUaYltPURoH5rsTBOqgF+i5nZSCoP9SqLdzq7aVrpYJcqpGj2PtgOx+9NpZ9agkOFjr6wIDAQAB
--------- private:
MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBANnESn2HnF/q2bozc8OhjfPaJjqY3Q1jW/GHqag7VOY23IGpOGgRTyati7/1ICo2JbF1vezldNcj/M+dkK4c8el947YvYG4DQhTe+0qU5RpiW09RGgfmuxME6qAX6LmdlIKg/1Kot3OrtpWulglyqkaPY+2A7H702ln1qCQ4WOvrAgMBAAECgYEAoo07bWiE+bQ8whkWGLnHVHdKggMJPq0kPK6fncxsG0xoXQEL8eK5yo1Q/ADl+Zxhlo3lL6g4Bz/9vpxHGzDQAbIZmNuvbUKkNN8KfQ8wmlcmLP4f/4B8NIog4rY4n728vcra/Pgo3pUiFhsA3IIoecTDsuiIeSzr8C7khHbrdkECQQD0fFhksVvT7Qhn/Fl7Y+vS+4LMFlGSYKZC4+KJFuzcW884eb3bdduGV2fMfRlVbRMPJqP41qF/8OiSjyJXIljfAkEA5AXOoVILLsfCY9NMOrcYVNhjYDtHTY1DfQwoUQKqhLREAnPfo3yr39+kyv5mB7HbOUA4LXkzNVXNg/p4gU1ydQJBAM0DaGwnfcVcwuvP5Ilf5OTrG2dgX87LVSBKUDB9FOpD4qSNEfPyBL/Gk7gaPyAvcwgFcwK7mHnc3mnntPg0SSkCQQC4DgfwJ21nYU8DjPcnHcvCELiGYNL5QmGLeljAq0pAu9F5uVZ3fJavqrI2OIrbAzFVUQUHj6FKF+w/79l9ZapRAkEAozb1xksXzax9qTx5NTrz5brxmCq53ymf8dI0NRFF+PHM4iey50ymroJswmlU6uflej6mv6G+Klecta+u4QQRvA==
------ Public Modulus  :d9c44a7d879c5fead9ba3373c3a18df3da263a98dd0d635bf187a9a83b54e636dc81a93868114f26ad8bbff5202a3625b175bdece574d723fccf9d90ae1cf1e97de3b62f606e034214defb4a94e51a625b4f511a07e6bb1304eaa017e8b99d9482a0ff52a8b773abb695ae960972aa468f63ed80ec7ef4da59f5a8243858ebeb
------ Public Exponent :65537
------ private Modulus  :d9c44a7d879c5fead9ba3373c3a18df3da263a98dd0d635bf187a9a83b54e636dc81a93868114f26ad8bbff5202a3625b175bdece574d723fccf9d90ae1cf1e97de3b62f606e034214defb4a94e51a625b4f511a07e6bb1304eaa017e8b99d9482a0ff52a8b773abb695ae960972aa468f63ed80ec7ef4da59f5a8243858ebeb
------ private Exponent :a28d3b6d6884f9b43cc2191618b9c754774a8203093ead243cae9f9dcc6c1b4c685d010bf1e2b9ca8d50fc00e5f99c61968de52fa838073ffdbe9c471b30d001b21998dbaf6d42a434df0a7d0f309a57262cfe1fff807c348a20e2b6389fbdbcbdcadafcf828de9522161b00dc822879c4c3b2e888792cebf02ee48476eb7641

RSAUtil 完整代码

package com.ly.encrydemo;

import android.util.Base64;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import static android.util.Base64.decode;

/**
 * Created by user on 2017/3/22.
 */
public class RSAUtil {

    /**
     * RSA 加密,通过公钥加密数据,密钥从文件流读取
     * @param paramStr
     * @param inputStream
     * @return
     */
    public static String EncryptDataOfPublicKey(String paramStr,InputStream inputStream){
        try {
            byte[] paramBytes = paramStr.getBytes("utf-8");
            PublicKey publicKey = getPublicKey(inputStream);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = cipher.getBlockSize();  //获取每次加密的数据长度  官方文档 https://developer.android.google.cn/reference/javax/crypto/CipherSpi.html#engineDoFinal(byte[], int, int)
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] encryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            String str = Base64.encodeToString(encryptData, Base64.NO_WRAP);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA 加密,通过私钥加密数据,密钥从文件流读取
     * @param paramStr
     * @param inputStream
     * @return
     */
    public static String EncryptDataOfPrivateKey(String paramStr,InputStream inputStream){
        try {
            byte[] paramBytes = paramStr.getBytes("utf-8");
            PrivateKey privateKey = getPrivateKey(inputStream);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = cipher.getBlockSize();  //获取每次加密的数据长度  官方文档 https://developer.android.google.cn/reference/javax/crypto/CipherSpi.html#engineDoFinal(byte[], int, int)
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] encryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            String str = Base64.encodeToString(encryptData, Base64.NO_WRAP);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA 解密,通过公钥解密数据,密钥从文件流读取
     * @param paramStr
     * @param inputStream
     * @return
     */
    public static String DecryptDataOfPublicKey(String paramStr,InputStream inputStream){
        try {
            PublicKey publicKey = getPublicKey(inputStream);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] paramBytes = Base64.decode(paramStr,Base64.NO_WRAP);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = 128;  //每次解密的长度,每段数据加密后长度都是128
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] decryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            return new String(decryptData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * RSA 解密,通过私钥解密数据,密钥从文件流读取
     * @param paramStr
     * @param inputStream
     * @return
     */
    public static String DecryptDataOfPrivateKey(String paramStr,InputStream inputStream){
        try {
            PrivateKey privateKey = getPrivateKey(inputStream);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] paramBytes = Base64.decode(paramStr,Base64.NO_WRAP);

//            byte[] decryptData = cipher.doFinal(paramBytes);

            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = 128;  //每次解密的长度,每段数据加密后长度都是128
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] decryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            return new String(decryptData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过文件流来读取公钥
     * @param paramInputStream
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(InputStream paramInputStream) throws Exception {
        try {
            PublicKey localPublicKey = null;
            BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(paramInputStream));
            StringBuilder stringbuilder = new StringBuilder();
            do
            {
                String s = bufferedreader.readLine();
                if(s == null)
                    break;
                if(s.charAt(0) != '-')
                {
                    stringbuilder.append(s);
                    stringbuilder.append('\r');
                }
            } while(true);
            String paramString =  stringbuilder.toString();

            byte[] arrayOfByte = decode(paramString, Base64.NO_WRAP);
            localPublicKey = (RSAPublicKey) KeyFactory
                    .getInstance("RSA").generatePublic(
                            new X509EncodedKeySpec(arrayOfByte));
            return localPublicKey;
        } catch (IOException localIOException) {
            throw new Exception("公钥数据流读取错误");
        } catch (NullPointerException localNullPointerException) {

        }catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException localInvalidKeySpecException) {
            throw new Exception("公钥非法");
        }
        throw new Exception("公钥输入流为空");
    }

    /**
     * 通过文件流来读取私钥
     * @param paramInputStream
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(InputStream paramInputStream) throws Exception {
        try {
            BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(paramInputStream));
            StringBuilder stringbuilder = new StringBuilder();
            do {
                String s = bufferedreader.readLine();
                if (s == null)
                    break;
                if (s.charAt(0) != '-') {
                    stringbuilder.append(s);
                    stringbuilder.append('\r');
                }
            } while (true);
            String paramString = stringbuilder.toString();

            byte[] buffer = decode(paramString, Base64.NO_WRAP);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }
    }

    /**
     * RSA 加密,通过私钥加密数据,密钥由n e生成
     * @param paramStr
     * @param modulus
     * @param exponent
     * @return
     */
    public static String EncryptDataOfPublicKey(String paramStr,String modulus, String exponent){
        try {
            byte[] paramBytes = paramStr.getBytes("utf-8");
            PublicKey publicKey = getPublicKey(modulus,exponent);
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");  //RSA/ECB/PKCS1Padding
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = cipher.getBlockSize();  //获取每次加密的数据长度  官方文档 https://developer.android.google.cn/reference/javax/crypto/CipherSpi.html#engineDoFinal(byte[], int, int)
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] encryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            String str = Base64.encodeToString(encryptData, Base64.NO_WRAP);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * RSA 解密,通过私钥解密数据,密钥由n e生成
     * @param paramStr
     * @param modulus
     * @param exponent
     * @return
     */
    public static String DecryptDataOfPrivateKey(String paramStr,String modulus, String exponent){
        try {
            PrivateKey privateKey = getPrivateKey(modulus,exponent);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] paramBytes = Base64.decode(paramStr,Base64.NO_WRAP);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = 128;  //每次解密的长度,每段数据加密后长度都是128
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] decryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            return new String(decryptData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * RSA 加密,通过私钥加密数据,密钥由n e生成
     * @param paramStr
     * @param modulus
     * @param exponent
     * @return
     */
    public static String EncryptDataOfPrivateKey(String paramStr,String modulus, String exponent){
        try {
            byte[] paramBytes = paramStr.getBytes("utf-8");
            PrivateKey privateKey = getPrivateKey(modulus,exponent);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = cipher.getBlockSize();  //获取每次加密的数据长度  官方文档 https://developer.android.google.cn/reference/javax/crypto/CipherSpi.html#engineDoFinal(byte[], int, int)
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] encryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            String str = Base64.encodeToString(encryptData, Base64.NO_WRAP);
            return str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA 解密,通过公钥解密数据,密钥由n e生成
     * @param paramStr
     * @param modulus
     * @param exponent
     * @return
     */
    public static String DecryptDataOfPublicKey(String paramStr,String modulus, String exponent){
        try {
            PublicKey publicKey = getPublicKey(modulus,exponent);

            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPADDING");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] paramBytes = Base64.decode(paramStr,Base64.NO_WRAP);

            int i = paramBytes.length;  //数据总长度
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int len = 128;  //每次解密的长度,每段数据加密后长度都是128
            int j = 0;
            int k = 0;
            while (i - k > 0) {
                byte midBytes[];
                int l;
                if (i - k > len)
                    midBytes = cipher.doFinal(paramBytes, k, len);
                else
                    midBytes = cipher.doFinal(paramBytes, k, i - k);
                bytearrayoutputstream.write(midBytes, 0, midBytes.length);
                l = j + 1;
                k = l * len;
                j = l;
            }
            byte[] decryptData = bytearrayoutputstream.toByteArray();
            bytearrayoutputstream.close();

            return new String(decryptData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 公钥由n e生成
     * @param modulus
     * @param exponent
     * @return
     */
    private static PublicKey getPublicKey(String modulus, String exponent) throws Exception {
        return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(new BigInteger(modulus, 16), new BigInteger(exponent, 16)));
    }
    /**
     * 私钥由n e生成
     * @param modulus
     * @param exponent
     * @return
     */
    private static PrivateKey getPrivateKey(String modulus, String exponent) throws Exception {
        return KeyFactory.getInstance("RSA").generatePrivate(new RSAPrivateKeySpec(new BigInteger(modulus, 16), new BigInteger(exponent, 16)));
    }
}

RSAUtil的使用:

       private void RSAUtilTest(){
        try {
            //加密数据
            String rsaTestData = "asdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsgeasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsge";
            //公钥加密 私钥解密
            String encryptPub = RSAUtil.EncryptDataOfPublicKey(rsaTestData,mContext.getResources().openRawResource(R.raw.rsa_public_key));
            String decryptPri = RSAUtil.DecryptDataOfPrivateKey(encryptPub,mContext.getResources().openRawResource(R.raw.rsa_private_key));
            Log.e("test","----1--- : " + String.format("%s\n\r%s",encryptPub,decryptPri));

            //私钥加密 公钥解密
            String encryptPri = RSAUtil.EncryptDataOfPrivateKey(rsaTestData,mContext.getResources().openRawResource(R.raw.rsa_private_key));
            String decryptPub = RSAUtil.DecryptDataOfPublicKey(encryptPri,mContext.getResources().openRawResource(R.raw.rsa_public_key));
            Log.e("test","----2--- : " + String.format("%s\n\r%s",encryptPri,decryptPub));

            /**
             * 密钥对  M E 形式的
             */
            String publicModulus = "c1209bfb8f649d891be8f0f32e79ed227800a0a845083cf6b51a217de84e03d442e180b57ad05b155d3f1996c8fb9cb9f233e14846c02cd2991c70216d626221220a6f136936a517c3f73328ad369a12d1d13fc5af6bb2dce04530ab016f101fc90898c6a1afd944e147d16995b90a471add8ee9f8737f57f6bf2d6f52a741ef";
            String publicExponent = "010001";
            String privateExponent = "c1209bfb8f649d891be8f0f32e79ed227800a0a845083cf6b51a217de84e03d442e180b57ad05b155d3f1996c8fb9cb9f233e14846c02cd2991c70216d626221220a6f136936a517c3f73328ad369a12d1d13fc5af6bb2dce04530ab016f101fc90898c6a1afd944e147d16995b90a471add8ee9f8737f57f6bf2d6f52a741ef";
            String privateModulus = "35f8b1fec45cfef5913a311414d9f81e58e0fc04ea7dd9e3ac4ae82f329b92d05ffc7b26bc72bbf1a5847bd73ac5ae4ffcd2e8d3750a41bc7d1388769f060e9bed2669b0e5c1f62cb9e33ea663506554997dd10276902aac4affca89c066dc6fac9720715e6f85c005ec4e18fa9d9acaeb7ecf11cf71fb0c45b1110ea66ec5b1";

            //公钥加密 私钥解密
            String encryptPubME = RSAUtil.EncryptDataOfPublicKey(rsaTestData,publicModulus,publicExponent);
            String decryptPriME = RSAUtil.DecryptDataOfPrivateKey(encryptPubME,privateExponent,privateModulus);
            Log.e("test","----1 ME--- : " + String.format("%s\n\r%s",encryptPubME,decryptPriME));

            //私钥加密 公钥解密
            String encryptPriME = RSAUtil.EncryptDataOfPrivateKey(rsaTestData,privateExponent,privateModulus);
            String decryptPubME = RSAUtil.DecryptDataOfPublicKey(encryptPriME,publicModulus,publicExponent);
            Log.e("test","----2 ME--- : " + String.format("%s\n\r%s",encryptPriME,decryptPubME));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


//结果

----1--- : Ee8qnbUSj+6rXlq3rUovi+FWSvjRIAA/+lUoiggOKZvDJG8TmhtWGlh+B4u4sgR8n6HnmeD3fEeSFl8mQ+lq11NkaTPEi5enhZGjEvMgIlvsYOUlwxoRu1lXcVXsFFkAThuU418JYaLPRC5C+V1I3E4zzvrGkB4LFsPUXb+kJsMIiwE2XiVEclalTQmi86j3+ua0TWq9K6CNOHxAWBT0D/cWzSc861+7bY9j1ilXRFeRAopsPCszv3jPApKqRJNU3Ewno9FsIk3xUgLXOIEYolf/7TpPBqeF867WX01rWzQM1uh62+t1Ul1DWEvAJsGZm7cw+LGnd8jK7CGAfFlDiQ==
asdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsgeasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsge
----2--- : MpDSK3T9w4DGMDqYjDkxkQixBnZQpogMC/Eq+RCNYwla5JQrMiEOoa3TXhRbfrbyKts8Dq4C7bWuQad1Z+aLBwKHgazKMUWLwoxkZVl0+GJnqT5sCWy/inmC5HT48Q/U6OA0+JGsanQk8klwq+cgsRaEPQHJq5RyR+oeNvbSWo+IUBhEigrPUQJqnrq9wYHcMKfT1GGBXcXjOXFlEtDZukI+ds+7kLall6ovU723rXkfGUe13qJm8cUiJEhkt+O9AUs9H54RELgw3LPVhMPDaQlyLcU/dJd8sOiAsi2Xm+kZdpK90O5xYK5gkiqykuwLyJ7tYT4vM+dGLTnRZ1F82Q==
asdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsgeasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsge
----1 ME--- : Ut7TFeS8cTUN5o1AONLQV1WPS0PLHqMMhU/JOEyQ8oor5s1QKiBPC+cX5fj/dow9uiWi6e7RqRM8QNvd2Top0rLa8njPdYtIcIzcpFTWllHbi7k8k7qaMNZqTxlzcXos7SepnM5af7ZnR+wdKl6AotQhJyH5KhpnSgNrHPGWDrgZY3LOTu6Xn1JdK5/CMcJ+5XNkU0Yvjhf5RidwkrIsTqOYsG8S89Yh7a6Lkk+HaG7+5EULQp9h1YqMLG5GyLSvC8N1bZtSdiTHa5vaN86caIquDo1Dfpx/ld5seKRuX0fs7dpGIBznEbZE+seOUx9v0iepxsx9mK7JkTdtEeS2tA==
asdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsgeasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsge
----2 ME--- : noR44piyaRrvT/jDIf+7CbQeBW5jFJqdsEBP1mTGfbQjS0n5/RRBbhxta26pJd6ap6++YAHkg8OJHnyAZvMCGULq6zE6UUbuH9VVWqby+S1EL7ytHfauwUVdC2g+/ro/DBVswngl5IjG1uUexNFHQQy+HSwE0Q4aD51Ho5aqqRIyk2V1wpt57Sn1O6b99gL9Hs+KsQDTQrVQbAZGsUDHYph4AO2T8hNcQfZuLrPHqsu0pKkr5r91I09jY8VRY8O57ZqHlsaGbnzB9NFctx/BBG9SLsRYY8MJGNxmh1us+6rc+pPQ+eoM5dUAXoDKC1TUYIiV5W60mwi00PoaaiNOpg==
asdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdgasgegesgasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsgeasdegfsgeasdegfsgeasdgasgegesgasdegfsgeasdegfsge

源码资源下载-github

源码资源下载-csdn

你可能感兴趣的:(学习记录)