android对文件进行加密

android对文件进行加密最开始想的是对apk进行加密,但是搜到的资料都是对dex层面的加密,后来转念一想,apk也可以被看做是一个普通的文件,普通的文件其实是可以使用AES进行加密的(AES比DES安全性和速度要更好,属于对称性加密里面很好的了),代码如下funmain(args:Array<String>){ //key也可以采用下边的FileAESUtil.getAutoCreateAESKey()方法自动生成valkey=”asdfghjkl”valcontent=.

大家好,又见面了,我是你们的朋友全栈君。

最开始想的是对apk进行加密,但是搜到的资料都是对dex层面的加密,后来转念一想,apk也可以被看做是一个普通的文件,普通的文件其实是可以使用AES进行加密的(AES比DES安全性和速度要更好,属于对称性加密里面很好的了),代码如下

fun main(args: Array<String>) { 
   
	// key也可以采用下边的FileAESUtil.getAutoCreateAESKey()方法自动生成
    val key = "asdfghjkl"
    val content = "plugin.apk"
    val encryptMode = AESUtil.aes(content, key, Cipher.ENCRYPT_MODE)
    System.out.println("加密之后:" + encryptMode)

    // 解密
    val decryptMode = AESUtil.aes(encryptMode,key,Cipher.DECRYPT_MODE);
    System.out.println("解密之后:" + decryptMode)

    // 源文件
    val sourceFile = "F:\\app-debug.apk"
    // 加密输出的目标文件
    val targetFile = "F:\\a.apk"
    // 解密输出的目标文件
    val sourceDecryptFile = "F:\\target\\plugin.apk"

    val autoCreateKey = FileAESUtil.getAutoCreateAESKey()
    FileAESUtil.aesEncryptFile(sourceFile,targetFile,autoCreateKey);
    System.out.println("加密完成")
    FileAESUtil.aesDecryptFile(targetFile,sourceDecryptFile,autoCreateKey)
    System.out.println("解密完成")

}

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class FileAESUtil { 
   

    private static String ALGORITHM_AES = "AES";
    private static int AES_KEY_LEN = 128;


    public static byte[] getAutoCreateAESKey() throws Exception { 
   

        // 实例化一个AES加密算法的密钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_AES);
        // 初始化密钥生成器,指定密钥位数为128位
        keyGenerator.init(AES_KEY_LEN, new SecureRandom());
        // 生成一个密钥
        SecretKey secretKey = keyGenerator.generateKey();
        return secretKey.getEncoded();
    }

    /** AES加密 * * @param sourceFile 源文件 * @param encryptFile 加密文件 * @param password 密钥,128bit * @throws Exception 抛出异常 */
    public static void aesEncryptFile(String sourceFile, String encryptFile, byte[] password) throws Exception { 
   

        // 创建AES密钥
        SecretKeySpec key = new SecretKeySpec(password,  "AES");
        // 创建加密引擎(CBC模式)。Cipher类支持DES,DES3,AES和RSA加加密
        // AES:算法名称
        // CBC:工作模式
        // PKCS5Padding:明文块不满足128bits时填充方式(默认),即在明文块末尾补足相应数量的字符,
        // 且每个字节的值等于缺少的字符数。另外一种方式是ISO10126Padding,除最后一个字符值等于少的字符数
        // 其他字符填充随机数。
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, key,
                new IvParameterSpec(new byte[cipher.getBlockSize()]));
        // 原始文件流
        FileInputStream inputStream = new FileInputStream(sourceFile);
        // 加密文件流
        FileOutputStream outputStream = new FileOutputStream(encryptFile);
        // 以加密流写入文件
        CipherInputStream cipherInputStream = new CipherInputStream(inputStream, cipher);
        byte[] tmpArray = new byte[1024];
        int len;
        while((len = cipherInputStream.read(tmpArray)) != -1) { 
   

            outputStream.write(tmpArray, 0, len);
            outputStream.flush();
        }
        cipherInputStream.close();
        inputStream.close();
        outputStream.close();
    }

    /** AES解密 * * @param encryptFile 加密文件 * @param decryptFile 解密文件 * @param password 密钥,128bit * @throws Exception 抛出异常 */
    public static void aesDecryptFile(String encryptFile, String decryptFile, byte[] password) throws Exception { 
   

        // 创建AES密钥,即根据一个字节数组构造一个SecreteKey
        // 而这个SecreteKey是符合指定加密算法密钥规范
        SecretKeySpec key = new SecretKeySpec(password,   "AES");
        // 创建解密引擎(CBC模式)
        // Cipher类支持DES,DES3,AES和RSA加解密
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // 初始化解密器
        cipher.init(Cipher.DECRYPT_MODE, key,
                new IvParameterSpec(new byte[cipher.getBlockSize()]));
        // 加密文件流
        FileInputStream fileInputStream = new FileInputStream(encryptFile);
        // 解密文件流
        FileOutputStream fileOutputStream = new FileOutputStream(decryptFile);
        // 以解密流写出文件
        CipherOutputStream cipherOutputStream =
                new CipherOutputStream(fileOutputStream, cipher);
        byte[] buffer = new byte[1024];
        int len;
        while((len = fileInputStream.read(buffer)) >= 0) { 
   

            cipherOutputStream.write(buffer, 0, len);
        }
        cipherOutputStream.close();
        fileInputStream.close();
        fileOutputStream.close();
    }

}

字符串加密

import java.security.Provider;
/** * Implementation of Provider for SecureRandom. The implementation supports the * "SHA1PRNG" algorithm described in JavaTM Cryptography Architecture, API * Specification & Reference */
public final class CryptoProvider extends Provider { 
   
    /** * Creates a Provider and puts parameters */
    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");
    }
}


import android.annotation.SuppressLint;
import android.os.Build;

import androidx.annotation.IntDef;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;



/** * AES 工具类 */
public class AESUtil { 
   
    private final static String SHA1PRNG = "SHA1PRNG";

    @IntDef({ 
   Cipher.ENCRYPT_MODE, Cipher.DECRYPT_MODE})
    @interface AESType { 
   }

    /** * Aes加密/解密 * * @param content 字符串 * @param password 密钥 * @param type 加密:{@link Cipher#ENCRYPT_MODE},解密:{@link Cipher#DECRYPT_MODE} * @return 加密/解密结果字符串 */
    public static String aes(String content, String password, @AESType int type) { 
   
        try { 
   
            KeyGenerator generator = KeyGenerator.getInstance("AES");

            SecureRandom secureRandom;
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
   
                secureRandom = SecureRandom.getInstance(SHA1PRNG, new CryptoProvider());
            } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
   
                secureRandom = SecureRandom.getInstance(SHA1PRNG, "Crypto");
            } else { 
   
                secureRandom = SecureRandom.getInstance(SHA1PRNG);
            }
            secureRandom.setSeed(password.getBytes());
            generator.init(128, secureRandom);
            SecretKey secretKey = generator.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            @SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance("AES");
            cipher.init(type, key);

            if (type == Cipher.ENCRYPT_MODE) { 
   
                byte[] byteContent = content.getBytes("utf-8");
                return parseByte2HexStr(cipher.doFinal(byteContent));
            } else { 
   
                byte[] byteContent = parseHexStr2Byte(content);
                return new String(cipher.doFinal(byteContent));
            }
        } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException |
                UnsupportedEncodingException | InvalidKeyException | NoSuchPaddingException |
                NoSuchProviderException e) { 
   
            e.printStackTrace();
        }
        return null;
    }

    /** * 二进位组转十六进制字符串 * * @param buf 二进位组 * @return 十六进制字符串 */
    public static String parseByte2HexStr(byte buf[]) { 
   
        StringBuilder sb = new StringBuilder();
        for (byte b : buf) { 
   
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) { 
   
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /** * 十六进制字符串转二进位组 * * @param hexStr 十六进制字符串 * @return 二进位组 */
    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;
    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/145699.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 粒子群算法matlab代码(注释很详细哦,图像也美美哒,任意维度)[通俗易懂]

    粒子群算法matlab代码(注释很详细哦,图像也美美哒,任意维度)[通俗易懂]整个程序分为5个脚本pso1_mian.m:主程序,在此脚本内设置参数。pso1_im.m:画出函数图像(仅1维和2维)pso1_in.m:初始化pso1_in2.m:迭代寻优并输出结果另外还有一个目标函数,单独为一个脚本。推荐的测试函数—>这里先上运行结果图下面是源码1.pso1_mian.m这里的目标函数用函数句柄的形式调用(第15行)%%粒子群算法%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%pso1_im

    2022年5月1日
    76
  • Docker镜像相关命令

    Docker镜像相关命令1、查看docker版本 docker version 2、列出本地主机上的镜像: docker images REPOSITORY:表示镜像的仓库源 TAG:镜像的标签 IMAGE ID:镜像ID CREATED:镜像创建时间 SIZE:镜像大小3、查询镜像 docker search 镜像名称…

    2022年6月13日
    30
  • Java–Java版本和JDK版本「建议收藏」

    Java–Java版本和JDK版本「建议收藏」对于Java初学者,经常会听到同事,或看到网上Java版本和JDK版本不一的叫法,不明白这两者到底什么关系?其实博主当年初学Java时也有这样的困惑,今天我们就来好好探讨一下,如有不对之处,请加以指正,不喜勿喷,谢谢!Java版本叫法:Java6、Java8、Java11、Java13(当前最新版本Java17)等这一类“JavaX”的Java版本名称同时又会听到,看到JDK版本叫法:JDK1.6、JDK1.8等这种“J…

    2025年11月26日
    4
  • 递归算法浅谈

    递归算法浅谈

    2021年12月4日
    47
  • C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解

    C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解最近要做一个大数据dataTable循环操作,开始发现运用foreach,进行大数据循环,并做了一些逻辑处理。在循环中耗费的时间过长。后来换成使用Parallel.ForEach来进行循环。一开始认为, 数据比较大时,Parallel.ForEach肯定比 ForEach效率高,后来发现,其实并不是这样。我用了1000万次循环测试:{CSDN:CODE:2601125}

    2022年7月19日
    23
  • Windows 10配置远程开机[通俗易懂]

    Windows 10配置远程开机[通俗易懂]简介最近有个需求,在外边或者是上班的时候想从家里的电脑拿点资料,虽然家里的路由器有公网IP地址,但是电脑总不能一直开着吧,然后就想到可以远程通过网卡唤醒电脑。前提条件拥有一个公网IP(一般可以找运营商申请),如果拥有的公网IP是动态的话,需要绑定DDNS域名,DDNS域名可以自行注册。 电脑主板支持网络唤醒功能。配置方法主板开启网络唤醒功能,如图:设置网络适配器支持唤醒…

    2022年5月5日
    163

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号