Java常用加密算法

一、Base64

       Base64用于网络中传输的数据进行编码,严格意义上属于编码的格式,有64个字符的对应的编码,Base64就是将内容按照该格式进行编码。可以对数据编码和解码,是可逆的,安全度较低。
Base64可以使用JDk中自带的类实现,还可以使用Bouncy Castle(简称bc)或Commons Codec(简称cc)实现。

1.1 JDK自带类实现
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Test {

    public static void main(String[] args) {
        // 原始数据
        String str = "Hello World";

        // 加密
        Base64.Encoder encoder = Base64.getEncoder();
        String encoderStr = encoder.encodeToString(str.getBytes("utf-8"));
        System.out.println("encoder: " + encoderStr);

        // 解密
        Base64.Decoder decoder = Base64.getDecoder();
        String decoderStr = new String(decoder.decode(encoderStr), "utf-8");
        System.out.println("decoder: " + decoderStr);
    }
}

二、摘要算法

       摘要算法主要分为MD,SHA和Hmac算法,摘要算法其实是用于效验数据完整性的,我们在下载某些文件时,会有MD5和SHA1值提供我们效验下载的文件是否完整,可以用于根据数据生成其唯一的摘要值,无法根据摘要值知道原数据,属于不可逆的。

2.1 MD
算法摘要长度实现方
MD2128JDK
MD5128JDK

JDK有MD2和MD5实现,使用的是MessageDigest类。(JDK没有MD4的实现)

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 原始字符
        String data = "Hello World!";
		
		// 编码
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(data.getBytes());
		
		// 转化为16进制编码
        BigInteger bigInteger = new BigInteger(1, digest);
        System.out.println("JDK MD5: " +  bigInteger.toString(16));
    }
}
2.2 SHA

安全摘要算法,常用的有如下几种:

算法摘要长度实现方
SHA-1160JDK
SHA-224224Bouncy Castle
SHA2561256JDK
SHA-384384JDK
SHA-512512JDK
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Test {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 原始字符
        String data = "Hello World!";
		
		// SHA-1 编码
        MessageDigest md = MessageDigest.getInstance("SHA");
        byte[] digest = md.digest(data.getBytes());

        BigInteger bigInteger = new BigInteger(1, digest);
        System.out.println("JDK MD5: " +  bigInteger.toString(16));
    }
}
2.3 Hmac

Hmac是一种含有密钥的摘要算法,也有简称mac,密钥不同摘要也不同。常用的有如下几种:

算法摘要长度实现方
HmacMD2128Bouncy Castle
HmacMD4128Bouncy Castle
HmacMD5128JDK
HmacSHA1160JDK
HmacSHA224224Bouncy Castle
HmacSHA256256JDK
HmacSHA384384JDK
HmacSHA512512JDK
public class Test {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
        // 原始字符
        String data = "Hello World!";

//        // 生成秘钥,也可以自定义秘钥
//        KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
//        SecretKey secretKey = keyGenerator.generateKey(); //产生密钥
//        byte[] key = secretKey.getEncoded();     //获得密钥(默认生成)

        byte[] key = new byte[]{'a','a','a','a','a','a','a','a','a','a'};  // 手动生成密钥(十位)
        SecretKey secretKey2 = new SecretKeySpec(key, "HmacMD5");   // 还原密钥
        Mac mac = Mac.getInstance(secretKey2.getAlgorithm());       // 实例化mac
        mac.init(secretKey2);                                       // 初始化mac
        byte[] hmacMD5Bytes = mac.doFinal(data.getBytes());         // 生成摘要

        BigInteger bigInteger = new BigInteger(1, hmacMD5Bytes);
        System.out.println("jdk hmacMD5: " + bigInteger.toString(16));
    }
}

三、对称加密

       严格意义上的加密算法,分为对称和非对称加密算法,所谓对称是说发送方和接收方的密钥是一样的。因为密钥一样所以安全性跟非对称比较来说就不太安全了
对称加密算法主要分为:DES , 3DES(3重DES) , AES(想要替代DES) , PBE(基于口令的对称算法)

3.1 DES
密钥长度默认工作方式填充方式实现方
5656ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128NoPadding、PKCS5Padding、ISO10126PaddingJDK
6456ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128PKCS7Padding、ISO1012d2Padding、X932Padding、ZeroBytePaddingBouncy Castle
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.math.BigInteger;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";

        //生成key
        KeyGenerator keyGenerator=KeyGenerator.getInstance("DES");
        keyGenerator.init(56);      //指定key长度,同时也是密钥长度(56位)
        SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
        byte[] key = secretKey.getEncoded();  //生成key

        // key转换成密钥(自己指定字节数组时需要转换)
        DESKeySpec desKeySpec=new DESKeySpec(key);
        SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
        SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥

        // 加密
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
        cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
        byte[] result = cipher.doFinal(data.getBytes());
        BigInteger bigInteger = new BigInteger(1, result);
        System.out.println("jdkDES加密: "+ bigInteger.toString(16));  //转换为十六进制

        // 解密
        cipher.init(Cipher.DECRYPT_MODE, key2);  //相同密钥,指定为解密模式
        result = cipher.doFinal(result);   //根据加密内容解密
        System.out.println("jdkDES解密: " + new String(result));  //转换字符串
    }
}
3.2 3DES
密钥长度默认工作方式填充方式实现方
112、168168ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128NoPadding、PKCS5Padding、ISO10126PaddingJDK
128、192168ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128PKCS7Padding、ISO1012d2Padding、X932Padding、ZeroBytePaddingBouncy Castle
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.math.BigInteger;
import java.security.SecureRandom;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";

        // 生成key
        KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede");
        keyGenerator.init(112);      //3DES需要112 or 168位
        keyGenerator.init(new SecureRandom());   //或者使用这种方式默认长度,无需指定长度
        SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
        byte[] key = secretKey.getEncoded();  //生成key

        // key转换成密钥(自己指定字节数组时需要转换)
        DESedeKeySpec desKeySpec=new DESedeKeySpec(key);
        SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede");
        SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥

        //加密
        Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
        cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
        byte[] result = cipher.doFinal(data.getBytes());
        BigInteger bigInteger = new BigInteger(1, result);
        System.out.println("jdk3DES加密: " + bigInteger.toString(16));  //转换为十六进制

        //解密
        cipher.init(Cipher.DECRYPT_MODE, key2);  //相同密钥,指定为解密模式
        result = cipher.doFinal(result);   //根据加密内容解密
        System.out.println("jdk3DES解密: " + new String(result));  //转换字符串

    }
}
3.3 AES
密钥长度默认工作方式填充方式实现方
112、192、256128ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128NoPadding、PKCS5Padding、ISO10126PaddingJDK
112、192、256128ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到128、OFB、OFB8到128PKCS7Padding、ZeroBytePaddingBouncy Castle
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.Key;
import java.security.SecureRandom;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";
        
        //生成key
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(new SecureRandom());
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] key1 = secretKey.getEncoded();
        //key转换为密钥
        Key key2 = new SecretKeySpec(key1, "AES");

        //加密
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5padding");
        cipher.init(Cipher.ENCRYPT_MODE, key2);
        byte[] result = cipher.doFinal(data.getBytes());
        BigInteger bigInteger = new BigInteger(1, result);
        System.out.println("jdkAES加密: " + bigInteger.toString(16));  //转换为十六进制

        //解密
        cipher.init(Cipher.DECRYPT_MODE, key2);
        result = cipher.doFinal(result);
        System.out.println("jdkAES解密: "+new String(result));  //转换字符串
    }
}
3.4 PBE

       基于口令的对称加密算法(它其实是对之前的算法的包装,比如说MD5和DES,我这里就是的是对MD5和DES包装的PBE算法,还有其他类型的PBE),口令就是我们俗话说的密码,PBE中有一个salt(盐)的概念,盐就是干扰码

import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.Key;
import java.security.SecureRandom;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";

        //初始化盐
        SecureRandom random=new SecureRandom();
        byte[] salt = random.generateSeed(8);   // 指定为8位的盐 (盐就是干扰码,通过添加干扰码增加安全)

        // 口令和密钥
        String password = "TEST";              // 口令
        PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
        Key key = factory.generateSecret(pbeKeySpec);  // 密钥
        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 100);   // 参数规范,第一个参数是盐,第二个是迭代次数(经过散列函数多次迭代)
        Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");

        //加密
        cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
        byte[] result = cipher.doFinal(data.getBytes());
        System.out.println("jdk PBE加密: "+ Base64.getEncoder().encodeToString(result));

        //解密
        cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
        result = cipher.doFinal(result);
        System.out.println("jdk PBE解密: "+ new String(result));
    }
}

四、非对称加密

非对称算法就是发送方和接收方的密钥是不一样的,非对称相对于对称来说,有公钥和私钥的概念,基本上公钥是公开的,比如会在网络上传输,而私钥安全性要求就要高很多了,因为私钥是要保密的
基本的非对称算法有DH,RSA,ELGamal算法

4.1 DH

基于交换交换的非对称算法,发送方需要得到接收方的key构建本地密钥,而接收方也需要得到发送方的key构建自己本地的密钥。

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Objects;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";

        //初始化发送方密钥
        KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH");
        senderKeyPairGenerator.initialize(512);   //密钥长度
        KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
        byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();  //发送方key,需传递给接收方(网络,文件)

        //初始化接收方密钥
        KeyFactory factory=KeyFactory.getInstance("DH");
        X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc);  //根据从发送方得到的key解析
        PublicKey receiverPublicKey=factory.generatePublic(x509EncodedKeySpec);
        DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams();
        KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH");
        receiverKeyPairGenerator.initialize(dhParameterSpec);
        KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
        PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();
        byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
        
        //密钥构建
        KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH");
        receiverKeyAgreement.init(receiverPrivateKey);
        receiverKeyAgreement.doPhase(receiverPublicKey, true);
        SecretKey receiverDESKey=receiverKeyAgreement.generateSecret("DES");  //发送发密钥(公钥)
        KeyFactory senderKeyFactory=KeyFactory.getInstance("DH");
        x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc);
        PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec);
        KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH");
        senderKeyAgreement.init(senderKeyPair.getPrivate());
        senderKeyAgreement.doPhase(senderPublicKey, true);
        SecretKey senderDESKey=senderKeyAgreement.generateSecret("DES");        //接收方密钥(私钥)
        if(Objects.equals(receiverDESKey, senderDESKey)){
            System.out.println("双方密钥相同");
        }
        //加密
        Cipher cipher=Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, senderDESKey);
        byte[] result = cipher.doFinal(data.getBytes());
        String encode = Base64.getEncoder().encodeToString(result);
        System.out.println("jdk DH加密: "+ encode);

        //解密
        cipher.init(Cipher.DECRYPT_MODE, receiverDESKey);
        result=cipher.doFinal(result);
        System.out.println("jdk DH解密: " + new String(result));

    }
}
4.2 RSA

RSA相较于DH算法的实现简单,适用范围较广,公钥和私钥的创建较简单,而且支持公钥加密,私钥解密或者是私钥加密,公钥解密两种方式。

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class Test {

    public static void main(String[] args) throws Exception {
        // 原始字符
        String data = "Hello World!";

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(512);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey=(RSAPublicKey) keyPair.getPublic();           //公钥
        RSAPrivateKey rsaPrivateKey=(RSAPrivateKey) keyPair.getPrivate();       //私钥
        System.out.println("public key:"+ Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));
        System.out.println("private key:" + Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded()));

        //私钥加密,公钥解密--加密
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
        KeyFactory keyFactory=KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher=Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(data.getBytes());
        System.out.println("RSA私钥加密,公钥解密--加密:"+Base64.getEncoder().encodeToString(result));

        //私钥加密,公钥解密--解密
        X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
        keyFactory=KeyFactory.getInstance("RSA");
        PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
        cipher=Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE,publicKey);
        result = cipher.doFinal(result);
        System.out.println("RSA私钥加密,公钥解密--解密:"+new String(result));
		
        //公钥加密,私钥解密--加密
        x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
        keyFactory=KeyFactory.getInstance("RSA");
        publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
        cipher=Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        result = cipher.doFinal(data.getBytes());
        System.out.println("RSA公钥加密,私钥解密--加密:"+Base64.getEncoder().encodeToString(result));

        //公钥加密,私钥解密--解密
        pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
        keyFactory=KeyFactory.getInstance("RSA");
        privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        cipher=Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        result=cipher.doFinal(result);
        System.out.println("RSA公钥加密,私钥解密--解密:"+new String(result));
    }
}

五、keyGenerator,KeyPairGenerator,SecretKeyFactory的区别

Java加密的常用的加密算法类型有三种:

  • 【1】单向加密:也就是不可逆的加密,例如MD5,SHA,HMAC
  • 【2】对称加密:也就是加密方和解密方利用同一个秘钥对数据进行加密和解密,例如DES,PBE等等
  • 【3】非对称加密:非对称加密分为公钥和秘钥,二者是非对称的,例如用私钥加密的内容需要使用公钥来>解密,使用公钥加密的内容需要用私钥来解密,DSA,RSA…

而keyGenerator,KeyPairGenerator,SecretKeyFactory的三种使用方法刚好和这三种加密算法类型对上:

  • 【1】keyGenerator:秘钥生成器,也就是更具算法类型随机生成一个秘钥,例如HMAC,所以这个大部分用在非可逆的算法中
  • 【2】SecretKeyFactory:秘密秘钥工厂,言外之意就是需要根据一个秘密(password)去生成一个秘钥,例如DES,PBE,所以大部分使用在对称加密中
  • 【3】KeyPairGenerator:秘钥对生成器,也就是可以生成一对秘钥,也就是公钥和私钥,所以大部分使用在非对称加密中
  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书香水墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值