【Android】Android加密和解密方式

【Android】Android加密和解密方式一、不可逆加密不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。如信息摘要(MessageDigest)和安全散列(SecureHash)算法属于此类,常见的算法包括MD5、SHA1、PBKDF2、bcrypt等。特点:使用MD5和SHA进行加解密://MD5加密privatestaticStringt

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

一、不可逆加密

不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。
如信息摘要(Message Digest)和安全散列(Secure Hash)算法属于此类,常见的算法包括 MD5、SHA1、PBKDF2、bcrypt 等。
特点:
使用MD5和SHA进行加解密:

// MD5加密
private static String toMd5(String str) { 
   

    // 实例化一个指定摘要算法为MD5的MessageDigest对象
 MessageDigest algorithm;
    try { 
   
        algorithm = MessageDigest.getInstance("MD5");
        // 重置摘要以供再次使用
 algorithm.reset();
        // 使用bytes更新摘要
 algorithm.update(str.getBytes());
        // 使用指定的byte数组对摘要进行最后更新,然后完成摘要计算
 return toHexString(algorithm.digest(), "");
    } catch (NoSuchAlgorithmException e) { 
   
        e.printStackTrace();
    }

    return null;
}

// SHA加密
private static String toSHA(String str) { 
   
    // 实例化一个指定摘要算法为SHA的MessageDigest对象
 MessageDigest algorithm;
    try { 
   
        algorithm = MessageDigest.getInstance("SHA");
        // 重置摘要以供再次使用
 algorithm.reset();
        // 使用bytes更新摘要
 algorithm.update(str.getBytes());
        // 使用指定的byte数组对摘要进行最后更新,然后完成摘要计算
 return toHexString(algorithm.digest(), "");
    } catch (NoSuchAlgorithmException e) { 
   
        e.printStackTrace();
    }

    return null;
}

// 将字符串中的每个字符转换为十六进制
private static String toHexString(byte[] bytes, String separtor) { 
   
    StringBuilder hexString = new StringBuilder();
    for (byte b : bytes) { 
   
        String hex = Integer.toHexString(0xff & b);
        if (hex.length() == 1) { 
   
            hexString.append("0");
        }
        hexString.append(hex).append(separtor);
    }
    return hexString.toString();
}

二、可逆加密

算法加密

基于算法的加密算法,也被称为古典加密算法,如 HTTP 认证中的 base64,是一种基于64个基本字符,加密后的内容只包含这64个字符,加密后长度会变大。它是最简单的一种算法,一般用于加密URL.
下图为Base64编码表

Base64加解密相关代码

// 需要引入包:java.util.Base64 
// Base64加密
private static String encode(String str) { 
   
    byte[] encodeBytes = Base64.getEncoder().encode(str.getBytes());
    return new String(encodeBytes);
}

// Base64解密
private static String decode(String str) { 
   
    byte[] decodeBytes = Base64.getDecoder().decode(str.getBytes());
    return new String(decodeBytes);
}

对称加密

对称加密:加密和解密的密钥一样。常见的对称加密算法有 DES、3DES、AES。这三者的关系可以理解为迭代和替代。3DES是对DES的发展,AES是为了替代DES.
DES加解密相关代码

public class DESUtil { 
   
    // 初始化向量
 private static byte[] iv = { 
    'a', 'b', 'c', 'd', 'e', 1, 2, '*' };

    // DES加密
 // encryptText为原文
 // encryptKey为密匙
 private static String encryptDES(String encryptText, String encryptKey)
            throws Exception { 
   
        // 实例化IvParameterSpec对象,使用指定的初始化向量
 IvParameterSpec spec = new IvParameterSpec(iv);
        // 实例化SecretKeySpec类,根据字节数组来构造SecretKeySpec
 SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
        // 创建密码器
 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        // 用密码初始化Cipher对象
 cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        // 执行加密操作
 byte[] encryptData = cipher.doFinal(encryptText.getBytes());
        // 返回加密后的数据
 return Base64.getEncoder().encodeToString(encryptData);
    }

    // 解密
 private static String decryptDES(String decryptString, String decryptKey)
            throws Exception { 
   
        // 先使用Base64解密
 byte[] base64byte = Base64.getDecoder().decode(decryptString);
        // 实例化IvParameterSpec对象,使用指定的初始化向量
 IvParameterSpec spec = new IvParameterSpec(iv);
        // 实例化SecretKeySpec类,根据字节数组来构造SecretKeySpec
 SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(), "DES");
        // 创建密码器
 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        // 用密码初始化Cipher对象
 cipher.init(Cipher.DECRYPT_MODE, key, spec);
        // 获取解密后的数据
 byte decryptedData[] = cipher.doFinal(base64byte);
        // 将解密后数据转换为字符串输出
 return new String(decryptedData);
    }

}

AES加解密相关代码

public class AESUtil { 
   
    // 采用对称分组密码体制,密钥长度的最少支持为128、192、256
 String key = "abcdefghijklmnop";
    // 初始化向量参数,AES 为16bytes. DES 为8bytes, 16*8=128
 String initVector = "0000000000000000";
    IvParameterSpec iv;
    SecretKeySpec skeySpec;
    Cipher cipher;

    private static class HOLDER { 
   
        private static AESUtil instance = new AESUtil();
    }

    public static AESUtil getInstance() { 
   
        return HOLDER.instance;
    }

    private AESUtil() { 
   
        try { 
   
            iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            // 这是CBC模式
 // cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
 // 默认就是ECB模式
 cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
        } catch (NoSuchAlgorithmException e) { 
   
            e.printStackTrace();
        } catch (NoSuchPaddingException e) { 
   
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) { 
   
            e.printStackTrace();
        }
    }

    public String encrypt(String value) { 
   
        try { 
   
            // CBC模式需要传入向量,ECB模式不需要
 // cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
 cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            return Base64.encodeToString(encrypted, Base64.DEFAULT);
        } catch (Exception e) { 
   
            e.printStackTrace();
        }
        return null;
    }

    public String decrypt(String encrypted) { 
   
        try { 
   
            // CBC模式需要传入向量,ECB模式不需要
 // cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
 cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] original = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT));
            return new String(original);
        } catch (Exception ex) { 
   
            ex.printStackTrace();
        }
        return null;
    }

非对称加密

非对称加密:加密和解密的密钥不同,通常是公钥加密私钥解密,当然也可以私钥加密公钥解密,公钥通常用来对内容加密,而私钥既可以解密也可以用来确定是否是对应的公钥加的密,防止他人用错误的公钥进行加密。
非对称加密中另外两个重要的概念是公钥和私钥。公钥对外公开,任何人均可持有和使用;私钥自行保管,其安全性是通信安危的关键。常见的算法有 RSA、DH(Diffie-Hellman)、椭圆曲线算法(Elliptic curve cryptography,ECC)。
私钥和公钥的作用一般分为两种:
公钥加密,私钥解密,主要用于通信;
私钥加密(签名),公钥解密(验证),主要用于数字签名。
RSA算法相关代码

 public class RSAUtil { 
   

    public static final String RSA = "RSA";
    public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
    // 秘钥默认长度
 public static final int DEFAULT_KEY_SIZE = 2048;
    // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密
 public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
    // 当前秘钥支持加密的最大字节数
 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;

    // 随机生成RSA密钥对,密钥长度,范围:512~2048
 public static KeyPair generateRSAKeyPair(int keyLength) { 
   
        try { 
   
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
            kpg.initialize(keyLength);
            return kpg.genKeyPair();
        } catch (NoSuchAlgorithmException e) { 
   
            e.printStackTrace();
            return null;
        }
    }

    /** * 私钥加密 * @param data 待加密数据 * @param privateKey 密钥 * @return byte[] 加密数据 */
 public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { 
   
        // 得到私钥
 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 数据加密
 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
        return cipher.doFinal(data);
    }

    // 使用私钥进行解密
 public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { 
   
        // 得到私钥
 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PrivateKey keyPrivate = kf.generatePrivate(keySpec);
        // 解密数据
 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.DECRYPT_MODE, keyPrivate);
        byte[] arr = cp.doFinal(encrypted);
        return arr;
    }

    // 用公钥对字符串进行加密
 public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { 
   
        // 得到公钥
 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 加密数据
 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
        cp.init(Cipher.ENCRYPT_MODE, keyPublic);
        return cp.doFinal(data);
    }

    /** * 公钥解密 * @param data 待解密数据 * @param publicKey 密钥 * @return byte[] 解密数据 */
 public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { 
   
        // 得到公钥
 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance(RSA);
        PublicKey keyPublic = kf.generatePublic(keySpec);
        // 数据解密
 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, keyPublic);
        return cipher.doFinal(data);
    }

    // 以下开始分段解密
 // 使用私钥分段解密
 public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception { 
   
        int splitLen = DEFAULT_SPLIT.length;
        if (splitLen <= 0) { 
   
            return decryptByPrivateKey(encrypted, privateKey);
        }
        int dataLen = encrypted.length;
        List<Byte> allBytes = new ArrayList<Byte>(1024);
        int latestStartIndex = 0;
        for (int i = 0; i < dataLen; i++) { 
   
            byte bt = encrypted[i];
            boolean isMatchSplit = false;
            if (i == dataLen - 1) { 
   
                // 到data的最后了
 byte[] part = new byte[dataLen - latestStartIndex];
                System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                byte[] decryptPart = decryptByPrivateKey(part, privateKey);
                for (byte b : decryptPart) { 
   
                    allBytes.add(b);
                }
                latestStartIndex = i + splitLen;
                i = latestStartIndex - 1;
            } else if (bt == DEFAULT_SPLIT[0]) { 
   
                // 这个是以split[0]开头
 if (splitLen > 1) { 
   
                    if (i + splitLen < dataLen) { 
   
                        // 没有超出data的范围
 for (int j = 1; j < splitLen; j++) { 
   
                            if (DEFAULT_SPLIT[j] != encrypted[i + j]) { 
   
                                break;
                            }
                            if (j == splitLen - 1) { 
   
                                // 验证到split的最后一位,都没有break,则表明已经确认是split段
 isMatchSplit = true;
                            }
                        }
                    }
                } else { 
   
                    // split只有一位,则已经匹配了
 isMatchSplit = true;
                }
            }
            if (isMatchSplit) { 
   
                byte[] part = new byte[i - latestStartIndex];
                System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                byte[] decryptPart = decryptByPrivateKey(part, privateKey);
                for (byte b : decryptPart) { 
   
                    allBytes.add(b);
                }
                latestStartIndex = i + splitLen;
                i = latestStartIndex - 1;
            }
        }
        byte[] bytes = new byte[allBytes.size()];
        { 
   
            int i = 0;
            for (Byte b : allBytes) { 
   
                bytes[i++] = b.byteValue();
            }
        }
        return bytes;
    }

    // 私钥分段加密
 public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { 
   
        int dataLen = data.length;
        if (dataLen <= DEFAULT_BUFFERSIZE) { 
   
            return encryptByPrivateKey(data, privateKey);
        }
        List<Byte> allBytes = new ArrayList<Byte>(2048);
        int bufIndex = 0;
        int subDataLoop = 0;
        byte[] buf = new byte[DEFAULT_BUFFERSIZE];
        for (int i = 0; i < dataLen; i++) { 
   
            buf[bufIndex] = data[i];
            if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { 
   
                subDataLoop++;
                if (subDataLoop != 1) { 
   
                    for (byte b : DEFAULT_SPLIT) { 
   
                        allBytes.add(b);
                    }
                }
                byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
                for (byte b : encryptBytes) { 
   
                    allBytes.add(b);
                }
                bufIndex = 0;
                if (i == dataLen - 1) { 
   
                    buf = null;
                } else { 
   
                    buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
                }
            }
        }
        byte[] bytes = new byte[allBytes.size()];
        { 
   
            int i = 0;
            for (Byte b : allBytes) { 
   
                bytes[i++] = b.byteValue();
            }
        }
        return bytes;
    }

    // 用公钥对字符串进行分段加密
 public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { 
   
        int dataLen = data.length;
        if (dataLen <= DEFAULT_BUFFERSIZE) { 
   
            return encryptByPublicKey(data, publicKey);
        }
        List<Byte> allBytes = new ArrayList<Byte>(2048);
        int bufIndex = 0;
        int subDataLoop = 0;
        byte[] buf = new byte[DEFAULT_BUFFERSIZE];
        for (int i = 0; i < dataLen; i++) { 
   
            buf[bufIndex] = data[i];
            if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { 
   
                subDataLoop++;
                if (subDataLoop != 1) { 
   
                    for (byte b : DEFAULT_SPLIT) { 
   
                        allBytes.add(b);
                    }
                }
                byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
                for (byte b : encryptBytes) { 
   
                    allBytes.add(b);
                }
                bufIndex = 0;
                if (i == dataLen - 1) { 
   
                    buf = null;
                } else { 
   
                    buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
                }
            }
        }
        byte[] bytes = new byte[allBytes.size()];
        { 
   
            int i = 0;
            for (Byte b : allBytes) { 
   
                bytes[i++] = b.byteValue();
            }
        }
        return bytes;
    }

    // 公钥分段解密
 public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { 
   
        int splitLen = DEFAULT_SPLIT.length;
        if (splitLen <= 0) { 
   
            return decryptByPublicKey(encrypted, publicKey);
        }
        int dataLen = encrypted.length;
        List<Byte> allBytes = new ArrayList<Byte>(1024);
        int latestStartIndex = 0;
        for (int i = 0; i < dataLen; i++) { 
   
            byte bt = encrypted[i];
            boolean isMatchSplit = false;
            if (i == dataLen - 1) { 
   
                // 到data的最后了
 byte[] part = new byte[dataLen - latestStartIndex];
                System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                byte[] decryptPart = decryptByPublicKey(part, publicKey);
                for (byte b : decryptPart) { 
   
                    allBytes.add(b);
                }
                latestStartIndex = i + splitLen;
                i = latestStartIndex - 1;
            } else if (bt == DEFAULT_SPLIT[0]) { 
   
                // 这个是以split[0]开头
 if (splitLen > 1) { 
   
                    if (i + splitLen < dataLen) { 
   
                        // 没有超出data的范围
 for (int j = 1; j < splitLen; j++) { 
   
                            if (DEFAULT_SPLIT[j] != encrypted[i + j]) { 
   
                                break;
                            }
                            if (j == splitLen - 1) { 
   
                                // 验证到split的最后一位,都没有break,则表明已经确认是split段
 isMatchSplit = true;
                            }
                        }
                    }
                } else { 
   
                    // split只有一位,则已经匹配了
 isMatchSplit = true;
                }
            }
            if (isMatchSplit) { 
   
                byte[] part = new byte[i - latestStartIndex];
                System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                byte[] decryptPart = decryptByPublicKey(part, publicKey);
                for (byte b : decryptPart) { 
   
                    allBytes.add(b);
                }
                latestStartIndex = i + splitLen;
                i = latestStartIndex - 1;
            }
        }
        byte[] bytes = new byte[allBytes.size()];
        { 
   
            int i = 0;
            for (Byte b : allBytes) { 
   
                bytes[i++] = b.byteValue();
            }
        }
        return bytes;
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/145283.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • stm32H747_STM32H743的cache

    stm32H747_STM32H743的cache一、H.264的来源和特点H.264是国际标准化组织(ISO)和国际电信联盟(ITU)共同提出的继MPEG4之后的新一代数字视频压缩格式,它即保留了以往压缩技术的优点和精华又具有其它压缩技术无法比拟的许多优点。 1.低码流和MPEG2和MPEG4ASP等压缩技术相比,在同等图像质量下,采用H.264技术压缩后的数据量只有MPEG2的1/8,MPEG4的1/3。 2.高

  • 使用Matlab对数据归一化

    使用Matlab对数据归一化前言在使用机器学习做分类和回归分析时,往往需要对训练和测试数据首先做归一化处理。这里就对使用MATLAB对数据进行归一化方法做一个小总结。为什么进行归一化一般做机器学习应用的时候大部分时间是花费在特征处理上,其中很关键的一步就是对特征数据进行归一化。关于为什么进行归一化处理维基百科给出的解释是:1)归一化后加快了梯度下降求最优解的速度;2)归一化有可能提高精度。具体介绍:https://w…

  • 理解图像中卷积操作的含义

    理解图像中卷积操作的含义原文地址:https://blog.csdn.net/chaipp0607/article/details/72236892?locationNum=9&amp;fps=1上文用生动的例子来解释卷积记载了卷积的含义,现在就来看看卷积在图像处理中的应用吧。(ps:本文大部分内容系转载大神的博客,现在csdn强制图片水印,实在感到很无奈!!!)数字图像处理中卷积数字图像是一个二维的离散信号,对…

  • st7789 旋转_有没有人调过 ST7789V驱动的显示屏啊「建议收藏」

    本帖最后由quanhengwen于2019-9-511:15编辑可以在显示命令之前,手工进行全屏清屏操作,可以避免初始化花屏现象。自己部分代码SPI控制的分辨率为320*240横屏显示/******************************************************************************函数说明:LCD初始化函数入口数据:无返回…

  • virsh重启虚拟机命令_vmware创建的虚拟机不见了

    virsh重启虚拟机命令_vmware创建的虚拟机不见了使用QEMU/KVM虚拟化平台启动虚拟机,通常需要手动输入一行很长的命令,里面可能有几十个参数,要想启动多个虚拟机,以及监视多个虚拟机运行状态会非常困难,这时候就需要virsh这样一个虚拟机的管理工具。由于前面的文章已经介绍了如何安装QEMU以及如何启动虚拟机,这里就直接从QEMU/KVM安装好以后的地方开始。1.安装libvirt在ubuntu系统中,使用apt-get安装的libvirt还是1…

  • virsh命令详解_1个无法解析的外部命令

    virsh命令详解_1个无法解析的外部命令virsh的详细命令解析virsh有命令模式和交互模式如果直接在vrish后面添加参数是命令模式,如果直接写virsh,就会进入交互模式virshlist 列出所有的虚拟机,虚拟机的状态有(8)种 runing是运行状态 idel是空闲状态 pause暂停状态 shutdown关闭状态 crash虚拟机崩坏状态 daying垂死状态 shutoff不运行完全关闭 pmsuspe…

发表回复

您的电子邮箱地址不会被公开。

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