对称加密、消息摘要的JDK实现

现代密码的主要实现
  • 对称加密

对称加密算法有加密和解密两个过程,而且加密和解密使用的是相同一把秘钥,对称加密算法主要是DES和AES两种,其中AES算法更加安全。
在JDK中,DES与AES算法都提供了实现。

  • 消息摘要(散列函数)

此类加密算法与对称加密有所不同,此类算法通常是将原文加密后生成一个固定长度的密文,注意,这里是固定长度的,也就是不管原文有多长,密文总是固定长度的,这里是和对称加密算法有区别的。同时此类加密算法是不可逆的,也就是无法解密。消息摘要类算法主要有 MD5,SHA1,SHA256,SHA512等。

  • Base64

Base64算法不是一种加密算法,而是一种可读性算法,用于将非字符编码类型的字节,转为0-63内的ASCII编码,由A-Z,a-z,0-9, + /这64个字符填充。Base64算法原理是 将带转码的原文按字节拆成多个组,每个组有3个字节,不够的用等号填充。
然后将每个组的3个字节,拆成4个字节,3 * 8 = 4 * 6,拆成4个字节后,每个字节还少2位,此时需要在最高位补0,这样,整个字节的长度就能控制在0-63之间。

JDK 实现DES与AES的对称加密算法

  • DES算法
public class DESUtil {  
    private static final String ALGORITHM = "DES";
    private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding";
  
    public static String encrypt(String data, String key) throws Exception {  
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);  
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);  
        byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));  
        return Base64.getEncoder().encodeToString(encryptedBytes);  
    }  
  
    public static String decrypt(String data, String key) throws Exception {  
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);  
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);  
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(data));  
        return new String(decryptedBytes, "UTF-8");  
    }

    public static void main(String[] args) throws Exception {
        String s = "Hello World!";
        String secretKey = "12345678";
        String encrypt = encrypt(s, secretKey);
        System.out.println("加密后:" + encrypt);
        System.out.println("解密后:" + decrypt(encrypt,secretKey));
    }

}
  • AES算法
public class AESUtil {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
  
    public static String encrypt(String data, String key) throws Exception {  
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);  
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);  
        byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));  
        return Base64.getEncoder().encodeToString(encryptedBytes);  
    }  
  
    public static String decrypt(String data, String key) throws Exception {  
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);  
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);  
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(data));  
        return new String(decryptedBytes, "UTF-8");  
    }

    public static void main(String[] args) throws Exception {
        String s = "Hello World!Hello World!Hello World!Hello World!Hello World!";
        String secretKey = "1234567812345679";
        String encrypt = encrypt(s, secretKey);
        System.out.println("加密后:" + encrypt);
        System.out.println("解密后:" + decrypt(encrypt,secretKey));
    }

}
  • 加密模式与填充规则

除了基本的加密算法外,JDK中还实现了加密模式与填充模式,加密模式有两种,分别是 ECB与CBC,前者是块加密,每个块使用相同的秘钥,而CBC是每个块使用不同的秘钥,还需要用到IV向量。填充模式也有两种,为NoPadding和PKCS5Padding。NoPadding不填充,但是对原文的长度有要求,字节数必须是8的倍数。而PKCS5Padding为当原文长度不够时,会自动填充字节。

两种算法的对比:

  1. DES与AES都属于对称加密算法,加解密需要使用同一把秘钥。
  2. DES算法的秘钥长度为8个字节,而AES算法的秘钥长度为16个字节。
  3. 两种算法通常需要结合Base64编码实现。
  4. AES算法更加安全。

JDK实现 MD5、SHA1、SHA256、SHA512算法

    @Test
    public void testHash() throws Exception {
        String s = "Hello World!";
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        byte[] digest = md5.digest(s.getBytes(StandardCharsets.UTF_8));
        print("md5", digest);

        //SHA-1算法
        MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
        byte[] sha1Digest = sha1.digest(s.getBytes(StandardCharsets.UTF_8));
        print("sha1", sha1Digest);

        //SHA-256算法
        MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
        byte[] sha256Digest = sha256.digest(s.getBytes(StandardCharsets.UTF_8));
        print("sha256", sha256Digest);

        //SHA-512算法
        MessageDigest sha512 = MessageDigest.getInstance("SHA-512");
        byte[] sha512Digest = sha512.digest(s.getBytes(StandardCharsets.UTF_8));
        print("sha512", sha512Digest);

    }

    private void print(String type, byte[] digest) {
        String s = "";
        for (byte b : digest) {
            s = s + String.format("%02x", b);
        }
        System.out.println(type + "(" + s.length() + ")" + " ==> " + s);
    }

通过运行程序发现,此类算法的结果确实和原文长度无关,且无法解密。

JDK实现非对称加密算法

持续更新中…

你可能感兴趣的:(密码学,java,开发语言)