Android DES加解密的两种实现方式 - Java DES与Android DES不兼容问题

本文介绍了一种在Android环境中使用DES算法进行文件加解密的方法。提供了两种不同的实现方式:一种支持任意长度的密钥,另一种则限定密钥长度为8位。通过示例代码展示了如何同步和异步地加密及解密文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【方式一】用于加密的秘钥长度不限


import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

/**
 * 加解密所用秘钥长度不限
 * Created by xwc on 2017/8/1.
 */
public class AndroidDESOne {

    private static SecretKey key;
    private static byte[] iv = {1,2,3,4,5,6,7,8};


    /**
     * 生成密钥key对象
     * @param keyStr 密钥字符串
     * @return 密钥对象
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     * @throws Exception
     */
    private static SecretKey keyGenerator(String keyStr) throws Exception {
//        byte input[] = HexStr2Bytes(keyStr);
        DESKeySpec desKey = new DESKeySpec(keyStr.getBytes());
        //创建一个密匙工厂,然后用它把DESKeySpec转换成
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        return securekey;
    }


    /**
     * 同步解析Adjust广告配置文件
     * @param context
     */
    private static void decryptDesSync(Context context, String assetsFileName){

        Map<String, String> map = new HashMap<>();

        String savePath = context.getExternalCacheDir().getPath()+ File.separator + "Cache.csv";
        Log.i("CSV", "savePath\n" + savePath);
        File saveFile = new File(savePath);

        InputStream encryptIn = null;
        OutputStream decryptOut = null;
        CipherOutputStream decryptCOS = null;

        try {
            IvParameterSpec zeroIv = new IvParameterSpec(iv);
//          IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
//            SecretKeySpec key = new SecretKeySpec(SecretKey.getBytes(), "DES");
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);

            // 把解密后的数据保存至制定文件
            encryptIn = context.getAssets().open(assetsFileName);
            decryptOut = new FileOutputStream(saveFile);
            decryptCOS = new CipherOutputStream(decryptOut, cipher);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = encryptIn.read(buffer)) >= 0) {
                decryptCOS.write(buffer, 0, length);
            }

            // 直接读取解密后的数据
//            InputStream in = context.getAssets().open(secretFileName);
//            CipherInputStream cin = new CipherInputStream(in, cipher);
//            BufferedReader reader = new BufferedReader(new InputStreamReader(cin));
//            String line = null;
//            while ((line = reader.readLine()) != null) {
//                System.out.println(line);
//            }

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {

                if(encryptIn != null){
                    encryptIn.close();
                }

                if(decryptOut != null){
                    decryptOut.close();
                }

                if(decryptCOS != null){
                    decryptCOS.close();
                }

                if(saveFile.exists()){
                    saveFile.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 异步解密文件
     * @param context
     * @param assetsFileName assets目录下DES加密后的文件
     */
    private static void decryptDesAsync(final Context context, final String assetsFileName){

        new Thread(new Runnable() {
            @Override
            public void run() {
                decryptDesSync(context, assetsFileName);
            }
        }).start();
    }


    /**
     * 初始化秘钥
     * @param pkg
     */
    private static void initSecretKey(String pkg){
        try {
            key = keyGenerator(str2HexStr(pkg)); // new String(pkg.getBytes())
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(">>> initSecretKey Exception");
        }
    }


    /**
     * 文件file进行加密并保存目标文件destFile中
     * @param file   要加密的文件 如c:/test/srcFile.txt
     * @param destFile 加密后存放的文件名 如c:/加密后文件.txt
     */
    private static void encrypt(String file, String destFile) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(iv);
//        IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
//        SecretKeySpec key = new SecretKeySpec(SecretKey.getBytes(), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);

        InputStream is = new FileInputStream(file);
        OutputStream out = new FileOutputStream(destFile);
        CipherInputStream cis = new CipherInputStream(is, cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = cis.read(buffer)) > 0) {
            out.write(buffer, 0, r);
        }
        cis.close();
        is.close();
        out.close();
    }


    /**
     * 文件采用DES算法解密文件
     * @param file 已加密的文件 如c:/加密后文件.txt
     *         * @param destFile
     *         解密后存放的文件名 如c:/ test/解密后文件.txt
     */
    private static void decrypt(String file, String dest) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(iv);
//      IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
//        SecretKeySpec key = new SecretKeySpec(SecretKey.getBytes(), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);

        InputStream is = new FileInputStream(file);
        OutputStream out = new FileOutputStream(dest);
        CipherOutputStream cos = new CipherOutputStream(out, cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = is.read(buffer)) >= 0) {
            System.out.println();
            cos.write(buffer, 0, r);
        }
        cos.close();
        out.close();
        is.close();
    }

    /**
     * 字符串转换成十六进制字符串
     * @param str 待转换的ASCII字符串
     * @return String 每个Byte之间空格分隔,如: [61 6C 6B]
     */
    private static String str2HexStr(String str){
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;

        for (int i = 0; i < bs.length; i++)
        {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
            sb.append(' ');
        }
        return sb.toString().trim();
    }

    // 从十六进制字符串到字节数组转换
    public static byte[] HexStr2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }

    private static int parse(char c) {
        if (c >= 'a') return (c - 'a' + 10) & 0x0f;
        if (c >= 'A') return (c - 'A' + 10) & 0x0f;
        return (c - '0') & 0x0f;
    }

    public static void main(String[] args) throws Exception {
        initSecretKey("com.yifan");
        encrypt("E:\\test.csv", "E:\\adjust"); //加密
        System.out.println("加密完成");
        decrypt("E:\\adjust", "E:\\adjust.csv"); //解密
        System.out.println("解密完成");
    }
}

【方式一】用于加密的秘钥实际最长为8位,不足自动补充


import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.Key;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.SecretKeySpec;

/**
 * 加解密所用秘钥真实长度为最长8位,不够就用0补
 * Created by xwc on 2017/8/1.
 */

public class AndroidDESTwo {

    private Key mKey; // 加密解密的key
    private Cipher mDecryptCipher; // 解密的密码
    private Cipher mEncryptCipher; // 加密的密码
    private Context context;

    public AndroidDESTwo(String key) throws Exception {
        initKey(key);
        initCipher();
    }

    public AndroidDESTwo(Context context, String key) throws Exception {
        this.context = context;
        initKey(key);
        initCipher();
    }

    /**
     * 创建一个加密解密的key
     * @param keyRule
     */
    public void initKey(String keyRule) {
        byte[] keyByte = keyRule.getBytes();
        // 创建一个空的八位数组,默认情况下为0
        byte[] byteTemp = new byte[8];
        // 将用户指定的规则转换成八位数组
        for (int i = 0; i < byteTemp.length && i < keyByte.length; i++) {
            byteTemp[i] = keyByte[i];
        }
        mKey = new SecretKeySpec(byteTemp, "DES");
    }

    /***
     * 初始化加载密码
     * @throws Exception
     */
    private void initCipher() throws Exception {
        mEncryptCipher = Cipher.getInstance("DES");
        mEncryptCipher.init(Cipher.ENCRYPT_MODE, mKey);

        mDecryptCipher = Cipher.getInstance("DES");
        mDecryptCipher.init(Cipher.DECRYPT_MODE, mKey);
    }

    /**
     * 加密文件
     * @param filePath 需要加密的文件路径
     * @param savePath 加密后保存的位置
     * @throws FileNotFoundException
     */
    public void encryptFile(String filePath, String savePath) throws FileNotFoundException {
        encryptFile(new FileInputStream(filePath), savePath);
    }

    /**
     * 加密文件
     * @param in
     * @param savePath 加密后保存的位置
     */
    public void encryptFile(InputStream in, String savePath) {
        if (in == null) {
            System.out.println("inputstream is null");
            return;
        }
        try {
            CipherInputStream cin = new CipherInputStream(in, mEncryptCipher);
            OutputStream os = new FileOutputStream(savePath);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = cin.read(bytes)) > 0) {
                os.write(bytes, 0, len);
                os.flush();
            }
            os.close();
            cin.close();
            in.close();
            System.out.println("加密成功");
        } catch (Exception e) {
            System.out.println("加密失败");
            e.printStackTrace();
        }
    }

    /**
     * 同步解密文件
     * @param context
     * @param assetsFileName assets目录下DES加密后的文件
     */
    public void decryptDesSync(Context context, String assetsFileName) {

        try {
            InputStream in = context.getAssets().open(assetsFileName);
            CipherInputStream cin = new CipherInputStream(in, mDecryptCipher);
            BufferedReader reader = new BufferedReader(new InputStreamReader(cin));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
            cin.close();
            in.close();
            System.out.println("解密成功");
        } catch (Exception e) {
            System.out.println("解密失败");
            e.printStackTrace();
        }
    }

    /**
     * 异步解密文件
     * @param context
     * @param assetsFileName assets目录下DES加密后的文件
     */
    public void decryptDesAsync(final Context context, final String assetsFileName){

        new Thread(new Runnable() {
            @Override
            public void run() {
                decryptDesSync(context, assetsFileName);
            }
        }).start();
    }

    /**
     * 解密文件
     * @param filePath 文件路径
     * @throws Exception
     */
    public void decryptFile(String filePath) throws Exception {
        decryptFile(new FileInputStream(filePath));
    }

    /**
     * 解密文件
     * @param in
     */
    public void decryptFile(InputStream in) {
        if (in == null) {
            System.out.println("inputstream is null");
            return;
        }
        try {
            CipherInputStream cin = new CipherInputStream(in, mDecryptCipher);
            BufferedReader reader = new BufferedReader(new InputStreamReader(cin));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
            cin.close();
            in.close();
            System.out.println("解密成功");
        } catch (Exception e) {
            System.out.println("解密失败");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        AndroidDESTwo fileDES = new AndroidDESTwo("com.xwc.des");
        fileDES.encryptFile("D:/encrypt.txt", "D:/decrypt");  //加密
        fileDES.decryptFile("D:/decrypt"); //解密
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值