Java使用Cipher类实现加密,包括DES,DES3,AES和RSA加密

先看一个简单加密, 解密实现

1.1 加密

/**
 * content: 加密内容
 * slatKey: 加密的盐,16位字符串
 * vectorKey: 加密的向量,16位字符串
 */
public String encrypt(String content, String slatKey, String vectorKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
    IvParameterSpec iv = new IvParameterSpec(vectorKey.getBytes());
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
    byte[] encrypted = cipher.doFinal(content.getBytes());
    return Base64.encodeBase64String(encrypted);
}

1.2 解密

/**
 * content: 解密内容(base64编码格式)
 * slatKey: 加密时使用的盐,16位字符串
 * vectorKey: 加密时使用的向量,16位字符串
 */
public String decrypt(String base64Content, String slatKey, String vectorKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");
    IvParameterSpec iv = new IvParameterSpec(vectorKey.getBytes());
    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
    byte[] content = Base64.decodeBase64(base64Content);
    byte[] encrypted = cipher.doFinal(content);
    return new String(encrypted);
}

1.3 代码解释

上面简单实现了AES(“AES/CBC/PKCS5Padding”)的加密和解密。可以看到代码中主要的是cipher对象,并有以下调用

(1)新建Cipher对象时需要传入一个参数"AES/CBC/PKCS5Padding"
(2)cipher对象使用之前还需要初始化,共三个参数(“加密模式或者解密模式”,“密匙”,“向量”)
(3)调用数据转换:cipher.doFinal(content),其中content是一个byte数组

实际上Cipher类实现了多种加密算法,在创建Cipher对象时,传入不同的参数就可以进行不同的加密算法。而这些算法不同的地方只是创建密匙的方法不同而已。

如传入“AES/CBC/NoPadding”可进行AES加密,传入"DESede/CBC/NoPadding"可进行DES3加密。具体的后面会介绍到。

要参考Java自带的加密算法,可以参考JDK文档的附录:https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html

二. Java的Cipher类

2.1 Cipher类提供了加密和解密的功能

该项目使用Cipher类完成aes,des,des3和rsa加密.

获取Cipher类的对象:Cipher cipher = Cipher.getInstance(“DES/CBC/PKCS5Padding”); 参数按"算法/模式/填充模式",有以下的参数

  • AES/CBC/NoPadding (128)
  • AES/CBC/PKCS5Padding (128)
  • AES/ECB/NoPadding (128)
  • AES/ECB/PKCS5Padding (128)
  • DES/CBC/NoPadding (56)
  • DES/CBC/PKCS5Padding (56)
  • DES/ECB/NoPadding (56)
  • DES/ECB/PKCS5Padding (56)
  • DESede/CBC/NoPadding (168)
  • DESede/CBC/PKCS5Padding (168)
  • DESede/ECB/NoPadding (168)
  • DESede/ECB/PKCS5Padding (168)
  • RSA/ECB/PKCS1Padding (1024, 2048)
  • RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
  • RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
    (1)加密算法有:AES,DES,DESede(DES3)和RSA 四种
    (2) 模式有CBC(有向量模式)和ECB(无向量模式),向量模式可以简单理解为偏移量,使用CBC模式需要定义一个IvParameterSpec对象
    (3) 填充模式:
  • NoPadding: 加密内容不足8位用0补足8位, Cipher类不提供补位功能,需自己实现代码给加密内容添加0, 如{65,65,65,0,0,0,0,0}
  • PKCS5Padding: 加密内容不足8位用余位数补足8位, 如{65,65,65,5,5,5,5,5}或{97,97,97,97,97,97,2,2}; 刚好8位补8位8

2.2 Cipher对象需要初始化

init(int opmode, Key key, AlgorithmParameterSpec params)
(1)opmode :Cipher.ENCRYPT_MODE(加密模式)和 Cipher.DECRYPT_MODE(解密模式)
(2)key :密匙,使用传入的盐构造出一个密匙,可以使用SecretKeySpec、KeyGenerator和KeyPairGenerator创建密匙,其中

  • SecretKeySpec和KeyGenerator支持AES,DES,DESede三种加密算法创建密匙
  • KeyPairGenerator支持RSA加密算法创建密匙
    (3)params :使用CBC模式时必须传入该参数,该项目使用IvParameterSpec创建iv 对象

2.3 加密或解密

byte[] b = cipher.doFinal(content);
返回结果为byte数组,如果直接使用 new String(b) 封装成字符串,则会出现乱码

三. 创建密匙

创建密匙主要使用SecretKeySpec、KeyGenerator和KeyPairGenerator三个类来创建密匙。

3.1 SecretKeySpec类

SecretKeySpec类支持创建密匙的加密算法(ASE,DES,DES3)

Algorithm NameDescription
AESConstructs secret keys for use with the AES algorithm.
ARCFOURConstructs secret keys for use with the ARCFOUR algorithm.
DESConstructs secret keys for use with the DES algorithm.
DESedeConstructs secret keys for use with the DESede(Triple-DES) algorithm.
PBEWith< digest>And< encryption >
PBEWith< prf>And< encryption>
Secret-key factory for use with PKCS5 password-based encryption, where < digest> is a message digest, < prf> is a pseudo-random function, and < encryption> is an encryption algorithm.
Examples:
* PBEWithMD5AndDES(PKCS #5, 1.5),
* PBEWithHmacSHA256AndAES_128(PKCS # 5, 2.0)
Note: These all use only the low order 8 bits of each password character.
PBKDF2With< prf>Password-based key-derivation algorithm found in PKCS #5 2.0 using the specified pseudo-random function (< prf>). Example : PBKDF2WithHmacSHA256.
SecretKey secretKey = new SecretKeySpec(slatKey.getBytes(), "AES");

但需要注意的是不同的加密算法的byte数组的长度是不同的,创建密匙前最好先检测下byte数组的长度。各加密算法的密匙长度如下:

加密算法密匙长度向量长度
AES1616
DES88
DES3248

3.2 KeyGenerator类

KeyGenerator类支持创建密匙的加密算法(ASE,DES,DES3)

Algorithm NameDescription
AESKey generator for use with the AES algorithm.
ARCFOURKey generator for use with the ARCFOUR(RC4) algorithm.
BlowfishKey generator for use with the Blowfish algorithm.
DESKey generator for use with the DES algorithm.
DESedeKey generator for use with the DESede(triple-DES) algorithm.
HmacMD5Key generator for use with the HmacMD5 algorithm.
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512
Key generator for use with the various flavors of the HmacSHA algorithm.
RC2Key generator for use with the RC2 algorithm.
/**
     * 获取加密的密匙,传入的slatKey可以是任意长度的,作为SecureRandom的随机种子,
     * 而在KeyGenerator初始化时设置密匙的长度128bit(16位byte)
     */
    private static Key getSlatKey(String slatKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(slatKey.getBytes());
        kgen.init(128, random);
        Key key = kgen.generateKey();
        return key;
    }

KeyGenerator对象在初始化需要传入一个随机源。一般使用的都是SecureRandom类来创建随机源,此时传入的盐只作为SecureRandom类的随机种子,种子相同,产生的随机数也相同;
盐的长度不再受限制了,但KeyGenerator对象则必须指定长度。

3.3 KeyPairGenerator 类

RSA加密算法使用的密匙是包含公匙和私匙两种,一般情况下,有使用公匙加密,则用私匙解密;使用私匙加密,则使用公匙解密。可以使用KeyPairGenerator类来创建RSA加密算法的密匙

KeyPairGenerator类支持创建密匙的加密算法(RSA)

Algorithm NameDescription
DiffieHellmanGenerates keyPairs for the Diffie-Hellman KeyAgreement algorithm.
Note: key.getAlgorithm() will return “DH” instead of “DiffieHellman”.
DSAGenerates keyPairs for the Digital Signature algorithm.
RSAGenerates keyPairs for the RSA algorithm (Signature/Cipher).
ECGenerates keyPairs for the Elliptic Curve algorithm.
/**
     * 根据slatKey获取公匙,传入的slatKey作为SecureRandom的随机种子
     * 若使用new SecureRandom()创建公匙,则需要记录下私匙,解密时使用
     */
    private static byte[] getPublicKey(String slatKey) throws Exception {
        KeyPairGenerator keyPairGenerator  = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(slatKey.getBytes());
        keyPairGenerator.initialize(1024, random);//or 2048
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair.getPublic().getEncoded();
    }
    
    /**
     * 根据slatKey获取私匙,传入的slatKey作为SecureRandom的随机种子
     */
    private static byte[] getPrivateKey(String slatKey) throws Exception {
        KeyPairGenerator keyPairGenerator  = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(slatKey.getBytes());
        keyPairGenerator.initialize(1024, random);// or 2048
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair.getPrivate().getEncoded();
    }

同上,传入的盐只作为SecureRandom类的随机种子,盐相同,产生的keyPair的公匙和私匙也是同一对。
也可以不设置SecureRandom类的随机种子,直接使用new SecureRandom()创建一个新对象,此时就必须记录下公匙和私匙,在解密时使用。

四. 对加密结果进行一层包装

4.1 针对1.3返回结果返回字符串乱码的问题,一般对byte数组进行处理

有两种处理方式:转换为base64的字符串或转换为16进制的字符串

4.2 转换为base64

使用apache下的Base64类进行封装即可,Base64.encodeBase64String(result); 结果形如 qPba5V+b0Ox3Um…
jar包下载:https://mvnrepository.com/artifact/commons-codec/commons-codec

4.3 转换为16进制

编码实现,即编码实现将2进制转换为16进制

/**
 * 16进制工具类
 */
public class HexUtil {
    private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

    /**
     * 十六进制转化为二进制
     */
    public static byte[] hexStrToByteArray(String hexString) {
        if (hexString == null) {
            return null;
        }
        if (hexString.length() == 0) {
            return new byte[0];
        }
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < byteArray.length; i++) {
            String subStr = hexString.substring(2 * i, 2 * i + 2);
            byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
        }
        return byteArray;
    }

    /**
     * 二进制转化为十六进制
     */
    public static String byteArrayToHexStr(byte[] byteArray) {
        if (byteArray == null) {
            return null;
        }
        char[] hexChars = new char[byteArray.length * 2];
        for (int j = 0; j < byteArray.length; j++) {
            int v = byteArray[j] & 0xFF;
            hexChars[j * 2] = HEX_CHARS[v >>> 4];
            hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F];
        }
        return new String(hexChars);
    }
}

结果形如 04A2784A45234B…

五. Java加密的代码

代码我上传到github上了,欢迎下载~~

https://github.com/caizhaokai/Java_Cipher_Encrypt


原文来自: https://www.cnblogs.com/caizhaokai/p/10944667.html 作者昵称:蔡昭凯

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AES(高级加密标准)加密代码: ```python from Crypto.Cipher import AES from Crypto.Random import get_random_bytes key = get_random_bytes(16) cipher = AES.new(key, AES.MODE_EAX) ciphertext, tag = cipher.encrypt_and_digest(data) ``` RSA(Rivest-Shamir-Adleman)加密代码: ```python from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP key = RSA.generate(2048) cipher = PKCS1_OAEP.new(key) ciphertext = cipher.encrypt(data) ``` ECC(椭圆曲线加密加密代码: ```python from tinyec import registry curve = registry.get_curve('secp256r1') public_key = curve.g * private_key shared_key = public_key * remote_private_key ``` DES(数据加密标准)加密代码: ```python from Crypto.Cipher import DES key = b'abcdefgh' cipher = DES.new(key, DES.MODE_ECB) ciphertext = cipher.encrypt(data) ``` 3DES(Triple DES加密代码: ```python from Crypto.Cipher import DES3 key = b'abcdefghabcdefghabcdefgh' cipher = DES3.new(key, DES3.MODE_ECB) ciphertext = cipher.encrypt(data) ``` Rabin加密代码: ```python from Crypto.PublicKey import Rabin from Crypto.Cipher import PKCS1_v1_5 key = Rabin.generate(2048) cipher = PKCS1_v1_5.new(key) ciphertext = cipher.encrypt(data) ``` ElGamal加密代码: ```python from Crypto.PublicKey import ElGamal from Crypto.Cipher import ElGamal from Crypto import Random key = ElGamal.generate(2048, Random.new().read) cipher = ElGamal.new(key) ciphertext = cipher.encrypt(data, 0) ``` Diffie-Hellman加密代码: ```python from Crypto.PublicKey import DH from Crypto.Hash import SHA256 key = DH.generate(2048) public_key = key.publickey() ``` 以上代码仅用于演示目的,实际使用时应该仔细考虑安全性和性能等因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值