用Java进行AES加解密


=Start=

缘由:

整理记录一下用Java进行AES加解密的示例代码,方便以后快速检索和使用。

正文:

参考解答:

常规的AES加解密:

package com.ixyzero.learn.utils;

import org.apache.commons.codec.binary.Base64;

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

public class DoCipherTest {

    public static String encrypt(String key, String initVector, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string: " + Base64.encodeBase64String(encrypted));

            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String key, String initVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String key = "Bar12345Bar12345"; // 128 bit key (16 chars)
        String initVector = "RandomInitVector"; // 16 bytes IV (16 chars)

        System.out.println(decrypt(key, initVector,
                encrypt(key, initVector, "Hello World")));
    }
}

在多线程项目中使用ThreadLocal进行优化:

package com.ixyzero.learn.utils;

import org.apache.commons.codec.binary.Base64;

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

/**
 * Created by ixyzero on 2018/8/16.
 */
public class ThreadLocalCipher {

    private static String sKey="Bar12345Bar12345";
    private static String ivParameter="RandomInitVector";

    private static final ThreadLocal<Cipher> encryptCiphers = new ThreadLocal<Cipher>() {
        @Override
        protected Cipher initialValue() {
            try {
                byte[] raw = sKey.getBytes("ASCII");
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());

                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
                return cipher;
            } catch (Exception e) {
                // ugly but necessary
                throw new RuntimeException(e);
            }
        }
    };

    private static final ThreadLocal<Cipher> decryptCiphers = new ThreadLocal<Cipher>() {
        @Override
        protected Cipher initialValue() {
            try {
                byte[] raw = sKey.getBytes("ASCII");
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());

                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
                return cipher;
            } catch (Exception e) {
                // ugly but necessary
                throw new RuntimeException(e);
            }
        }
    };

    public static String encrypt(String data) {
        try {
            Cipher cipher = encryptCiphers.get();
            byte[] encrypted = cipher.doFinal(data.getBytes());
            
            System.out.println("encrypted string: " + Base64.encodeBase64String(encrypted));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String encrypted) {
        try {
            Cipher cipher = decryptCiphers.get();
            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String sourceData = "Hello World";
        String beEncrypted = encrypt(sourceData);
        String beDecrypted = decrypt(beEncrypted);

        System.out.println(beEncrypted);

        System.out.println(beDecrypted);
    }
}

 

参考链接:

=END=


《“用Java进行AES加解密”》 有 8 条评论

  1. 什么是 AES-GCM加密算法
    https://blog.csdn.net/T0mato_/article/details/53160772
    `
    GCM (Galois/Counter Mode) 指的是该对称加密采用Counter模式,并带有GMAC消息认证码。
    `
    What is the difference between CBC and GCM mode?
    https://crypto.stackexchange.com/questions/2310/what-is-the-difference-between-cbc-and-gcm-mode

    How to choose an AES encryption mode (CBC ECB CTR OCB CFB)?
    https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb
    `
    GCM与OCB (在性能和其它属性上)非常相似,但是GCM不受任何专利的限制,是最好的选择。唯一的缺点是实现非常复杂——但是如果使用库,就不必担心这个问题。
    `

  2. Java中如何对字符串用0进行前导padding
    java string format padding with 0
    https://stackoverflow.com/questions/473282/how-can-i-pad-an-integer-with-zeros-on-the-left
    https://stackoverflow.com/questions/4469717/left-padding-a-string-with-zeros
    `
    System.out.println(String.format(“%05d”, 111)); // 显示效果为 ‘00111’ 即,长度为5,用0填充不足的部分
    System.out.println(String.format(“%05d”, 111111)); // 显示效果为 ‘111111’ 即,超过的不管
    `

  3. 一场由JDK8小版本引起的血案
    https://www.cnblogs.com/steve-jiang/p/11597160.html
    Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 Download
    https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
    `
    # tree $(/usr/libexec/java_home -V)/jre/lib/security
    ├── blacklist
    ├── blacklisted.certs
    ├── cacerts
    ├── java.policy
    ├── java.security
    ├── policy
    │   ├── limited
    │   │   ├── US_export_policy.jar
    │   │   └── local_policy.jar
    │   └── unlimited
    │   ├── US_export_policy.jar
    │   └── local_policy.jar
    └── trusted.libraries
    `

  4. 用Python进行AES加解密
    AES Encrypt / Decrypt – Examples #清晰明了,nice
    https://cryptobook.nakov.com/symmetric-key-ciphers/aes-encrypt-decrypt-examples

    Popular Symmetric Algorithms 流行的对称算法
    https://cryptobook.nakov.com/symmetric-key-ciphers/popular-symmetric-algorithms
    `
    AES (Rijndael)
    Salsa20 / ChaCha20
    Other Popular Symmetric Ciphers
    Insecure Symmetric Algorithms
    Symmetric Encryption Schemes / Constructions

    Most applications today should prefer some of the above encryption schemes for symmetric encryption, instead of constructing their own encryption scheme. The above schemes are highly-secure, proven, well tested and come out-of-the box from the crypto libraries.
    目前,大多数应用程序都会选择上述加密方案中的某些方案进行对称加密,而不是自行构建加密方案。上述方案都是高度安全、经过验证和测试的,并且是加密库开箱即用的方案。

    Note that ChaCha20-Poly1305 is high-performance cipher (3 times faster than AES-128-GCM on mobile devices), so it is recommended to be used instead of AES-GCM.
    请注意,ChaCha20-Poly1305 是一种高性能密码(在移动设备上比 AES-128-GCM 快 3 倍),因此建议使用它来代替 AES-GCM。
    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注