精华内容
下载资源
问答
  • Java AES加密Java AES加密Java AES加密Java AES加密Java AES加密Java AES加密Java AES加密
  • Java AES加密

    2016-03-25 10:13:09
    Java AES 加密

    Java AES 加密

    1. 加密
        /**
         * 
         * @description 加密
         *
         * @param content 需要加密的内容
         * @param password 加密密码
         * @return
         */
        public static byte[] encrypt(String content, String password) {
            try {
                //创建AES密钥生成器
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                //使用用户提供的随机源初始化此密钥生成器,使其具有确定的密钥长度
                keyGenerator.init(128, new SecureRandom(password.getBytes()));
                //生成一个密钥
                SecretKey secretKey = keyGenerator.generateKey();
                //编码的密钥,如果此密钥不支持编码,则返回 null
                byte[] enCodeFormat = secretKey.getEncoded();
                //根据给定的字节数组构造一个密钥
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
                // 创建密码器
                Cipher cipher = Cipher.getInstance("AES");
                byte[] byteContent = content.getBytes("utf-8");
                // 初始化
                cipher.init(Cipher.ENCRYPT_MODE, key);
                byte[] result = cipher.doFinal(byteContent);
                // 加密结果
                return result; 
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
            return null;
        }
    1. 解密
        /**
         * 
         * @description 解密
         *
         * @param content 待解密内容
         * @param password 解密密钥
         * @return
         */
        public static byte[] decryptFrom(byte[] content, String password) {
            try {
                //创建AES密钥生成器
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                //使用用户提供的随机源初始化此密钥生成器,使其具有确定的密钥长度
                keyGenerator.init(128, new SecureRandom(password.getBytes()));
                //生成一个密钥
                SecretKey secretKey = keyGenerator.generateKey();
                //编码的密钥,如果此密钥不支持编码,则返回 null
                byte[] enCodeFormat = secretKey.getEncoded();
                //根据给定的字节数组构造一个密钥
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
                // 创建密码器
                Cipher cipher = Cipher.getInstance("AES");
                // 初始化
                cipher.init(Cipher.DECRYPT_MODE, key);
                byte[] result = cipher.doFinal(content);
                // 返回结果
                return result; 
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
            return null;
        }
    1. 测试
    public static void main(String[] args) {
        String content = "7654321 ";
        String password = "a.7?6#5@4!3^1%2";
        byte[] encryptResult = encrypt(content,pa
        System.out.println(encryptResult);
        byte[] decryptResult = decryptFrom(ecryptResult, password);
        System.out.println("解密后:" + new String(decryptResult));
    }
    展开全文
  • JAVA AES 加密算法

    2020-08-29 17:17:53
    JAVA AES 加密算法 javax.crypto.Cipher AES/ECB/PKCS5Padding
  • JAVA AES 加密

    2012-02-29 09:56:53
    貌似jdk1.7与官网的JCE不是配套的,JDK1.6可以使用。如果是跨平台的,注意加密后对密文的处理。此处是转换为十六进制了,也可用Base64处理
  • java AES加密

    2016-04-12 16:56:11
    一.前言 AES(Advanced Encryption Standard),高级加密标准,是美国政府用于替换DES的一种加密算法标准,Java SDK中包含了部分AES...JDK AES加密主要是几个步骤: 1.key变换 将传入的明文key做变换,AES的key固定为

    一.前言

    AES(Advanced Encryption Standard),高级加密标准,是美国政府用于替换DES的一种加密算法标准,Java SDK中包含了部分AES的实现,但javadoc对于算法的描述非常少,本文将解释Java AES实现的使用和原理。

    二.示例代码

    三.代码分析

    JDK AES加密主要是几个步骤:

    1.key变换

    将传入的明文key做变换,AES的key固定为128bit,但变换后的key为加密位数的一倍,128bit的加密变换后key为256bit。注意加密和解密的key变换不一样。

    2.加密解密

    选择加密的模式和补齐填充方法生成加密实例,加密得到密文。

    四.密码块工作模式

    块密码工作模式(Block cipher mode of operation),是对于按块处理密码的加密方式的一种扩充,不仅仅适用于AES,包括DES, RSA等加密方法同样适用。

    名称

    英文

    全名

    方法

    优点

    缺点

    ECB

    Electronic codebook

    电子密码本

    每块独立加密

    1.分块可以并行处理

    1.同样的原文得到相同的密文,容易被攻击

    CBC

    Cipher-block chaining

    密码分组链接

    每块加密依赖于前一块的密文

    1.同样的原文得到不同的密文
    2.原文微小改动影响后面全部密文

    1.加密需要串行处理
    2.误差传递

    PCBC

    Propagating cipher-block chaining

    填充密码块链接

    CBC的扩种,较少使用

    1.同样的原文得到不同的密文
    2.互换两个邻接的密文块不会对后续块的解密造成影响

    1.加密需要串行处理

    CFB

    Cipher feedback

    密文反馈

     

     

     

    OFB

    Output feedback

    输出反馈模式

    加密后密文与原文异或XOR

     

    1.能够对密文进行校验

    CTR

    Counter mode

    计数器模式

    增加一个序列函数对所有密文快做XOR

     

     

    五.填充

    填充(Padding),是对需要按块处理的数据,当数据长度不符合块处理需求时,按照一定方法填充满块长的一种规则。

    名称

    方法

    示例

    Zero padding

    最常见的方式,全填充0x00

    AA AA AA AA 00 00 00 00

    ANSI X.923

    Zero的改进,最后一个字节为填充字节个数

    AA AA AA AA 00 00 00 04

    ISO 10126

    随机填充

    AA AA AA AA 81 A6 23 04

    PKCS7

    ANSI X.923的变体
    填充1个字符就全0x01
    填充2个字符就全0x02
    不需要填充就增加一个块,填充块长度,块长为8就填充0x08,块长为16就填充0x10

    AA AA AA AA AA AA AA 01
    AA AA AA AA 04 04 04 04
    AA AA AA AA AA AA AA AA08 08 08 08 08 08 08 08

    ISO/IEC 7816-4

    以0x80开始作为填充开始标记,后续全填充0x00

    AA AA AA AA AA AA AA 80
    AA AA AA AA 80 00 00 00

    六.JDK AES实现

    1.实现支持

    AES理论上支持128,192,256三种长度的密钥,几乎全部密码块工作模式和填充方法,但JDK 7中只实现如下四种AES加密算法:

    (1)AES/CBC/NoPadding (128)
    (2)AES/CBC/PKCS5Padding (128)
    (3)AES/ECB/NoPadding (128)
    (4)AES/ECB/PKCS5Padding (128)

    2.使用须知

    (1)缺省模式和填充为“AES/ECB/PKCS5Padding”,Cipher.getInstance(“AES”)与Cipher.getInstance(“AES/ECB/PKCS5Padding”)等效。

    (2)JDK的PKCS5Padding实际是上述的PKCS7的实现。

    (3)由于AES是按照16Byte为块进行处理,对于NoPadding而言,如果需要加密的原文长度不是16Byte的倍数,将无法处理抛出异常,其实是由用户自己选择Padding的算法。密文则必然是16Byte的倍数,否则密文肯定异常。

    (4)如果加密为PKCS5Padding,解密可以选择NoPadding,也能解密成功,内容为原文加上PKCS5Padding之后的结果。

    (5)如果原文最后一个字符为>=0x00&&<=0x10的内容,PKCS5Padding的解密将会出现异常,要么是符合PKCS5Padding,最后的内容被删除,要么不符合,则解密失败抛出异常。对此有两种思路,一是原文通过Base64编码为可见字符,二是原文自带长度使用NoPadding解密。

    展开全文
  • java aes加密

    千次阅读 2018-10-16 00:45:10
    特别注意 java使用aes 加密语js交互 key是16为才可以匹配 package com.dl.utils; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import sun....

    特别注意 java使用aes 加密语js交互 key是16为才可以匹配

    package com.dl.utils;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    public class AESCoder{
    
        public static String encrypt(String strKey, String strIn) throws Exception {
            SecretKeySpec skeySpec = getKey(strKey);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec("01Gx03Yx05WW0607".getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(strIn.getBytes());
    
            return new BASE64Encoder().encode(encrypted);
        }
    
        public static String decrypt(String strKey, String strIn) throws Exception {
            SecretKeySpec skeySpec = getKey(strKey);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec("01Gx03Yx05WW0607".getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(strIn);
    
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString;
        }
    
        private static SecretKeySpec getKey(String strKey) throws Exception {
            byte[] arrBTmp = strKey.getBytes();
            byte[] arrB = new byte[16]; // 创建一个空的16位字节数组(默认值为0)
            for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
                arrB[i] = arrBTmp[i];
            }
            SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES");
    
            return skeySpec;
        }
    
        //key 为16位  截取 key的前后 8位 为16位   code为原文
    //    public static void main(String[] args) throws Exception {
    //        String Code = "123abc";
    //        String key = "12345678@#pqweg&11";
    //        String codE;
    //        codE = AESCoder.encrypt(key, Code);
    //        System.out.println("原文:" + Code);
    //        System.out.println("密钥:" + key);
    //        System.out.println("密文:" + codE);
    //        System.out.println("解密:" + AESCoder.decrypt(key, codE));
    //    }
    }
    
    
    展开全文
  • Java AES加密解密

    2016-11-10 11:52:37
    Java AES加密解密,可以修改key值和偏移量
  • 下面小编就为大家带来一篇Java AES加密解密的简单实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Java AES加密和解密

    千次阅读 2020-06-04 09:32:19
    本文向您展示了一些Java AES加密和解密示例: AES字符串加密–(加密和解密字符串)。 AES基于密码的加密–(密钥将从给定的密码派生)。 AES文件加密。 (基于密码)。 在本文中,我们重点介绍...
    AES加密

    高级加密标准 (AES,Rijndael)是一种分组密码加密和解密算法,是全球使用最广泛的加密算法。 AES使用128、192或256位的密钥来处理128位的块。

    本文向您展示了一些Java AES加密和解密示例:

    • AES字符串加密–(加密和解密字符串)。
    • AES基于密码的加密–(密钥将从给定的密码派生)。
    • AES文件加密。 (基于密码)。

    在本文中,我们重点介绍通过Galois Counter Mode(GCM)进行的256位AES加密。

    GCM = CTR + Authentication.

    进一步阅读
    阅读本– NIST – Galois /计数器模式(GCM)的建议

    不要使用AES电子密码本(ECB)模式
    AES ECB模式或AES/ECB/PKCS5Padding (在Java中)在语义上并不安全 – ECB加密的密文可能泄漏有关纯文本的信息。 这是关于为什么不应该使用ECB加密的讨论

    1. Java和AES加密输入。

    在AES加密和解密中,我们需要以下输入:

    AES加密最佳做法
    不要重复使用具有相同密钥的IV。

    1.1 IV(初始值或初始向量),它是随机字节,通常为12个字节或16个字节。 在Java中,我们可以使用SecureRandom生成随机IV。

    // 16 bytes IV
      public static byte[] getRandomNonce() {
            byte[] nonce = new byte[16];
            new SecureRandom().nextBytes(nonce);
            return nonce;
      }
    
      // 12 bytes IV
      public static byte[] getRandomNonce() {
            byte[] nonce = new byte[12];
            new SecureRandom().nextBytes(nonce);
            return nonce;
      }

    1.2 AES密钥,即AES-128AES-256 。 在Java中,我们可以使用KeyGenerator生成AES密钥。

    // 256 bits AES secret key
        public static SecretKey getAESKey() throws NoSuchAlgorithmException {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(256, SecureRandom.getInstanceStrong());
            return keyGen.generateKey();
        }

    1.3从给定密码派生的AES密钥。 在Java中,我们可以使用SecretKeyFactoryPBKDF2WithHmacSHA256从给定的密码生成AES密钥。

    // AES key derived from a password
        public static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
                throws NoSuchAlgorithmException, InvalidKeySpecException {
    
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            // iterationCount = 65536
            // keyLength = 256
            KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
            SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            return secret;
        }

    我们使用salt来保护彩虹攻击,它也是一个随机字节,我们可以使用相同的1.1 getRandomNonce生成它。

    1.4我们将上述方法分组为一个util类,这样我们就不会一次又一次重复相同的代码。

    CryptoUtils.java
    package com.mkyong.crypto.utils;
    
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.PBEKeySpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.KeySpec;
    import java.util.ArrayList;
    import java.util.List;
    
    public class CryptoUtils {
    
        public static byte[] getRandomNonce(int numBytes) {
            byte[] nonce = new byte[numBytes];
            new SecureRandom().nextBytes(nonce);
            return nonce;
        }
    
        // AES secret key
        public static SecretKey getAESKey(int keysize) throws NoSuchAlgorithmException {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(keysize, SecureRandom.getInstanceStrong());
            return keyGen.generateKey();
        }
    
        // Password derived AES 256 bits secret key
        public static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
                throws NoSuchAlgorithmException, InvalidKeySpecException {
    
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
            // iterationCount = 65536
            // keyLength = 256
            KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
            SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            return secret;
    
        }
    
        // hex representation
        public static String hex(byte[] bytes) {
            StringBuilder result = new StringBuilder();
            for (byte b : bytes) {
                result.append(String.format("%02x", b));
            }
            return result.toString();
        }
    
        // print hex with block size split
        public static String hexWithBlockSize(byte[] bytes, int blockSize) {
    
            String hex = hex(bytes);
    
            // one hex = 2 chars
            blockSize = blockSize * 2;
    
            // better idea how to print this?
            List<String> result = new ArrayList<>();
            int index = 0;
            while (index < hex.length()) {
                result.add(hex.substring(index, Math.min(index + blockSize, hex.length())));
                index += blockSize;
            }
    
            return result.toString();
    
        }
    
    }

    2. AES加密和解密。

    AES-GSM是使用最广泛的认证密码。 本示例将在Galois计数器模式(GCM)中使用256位AES加密和解密字符串。

    AES-GCM输入:

    • AES密钥(256位)
    • IV – 96位(12字节)
    • 身份验证标签的长度(以位为单位)– 128位(16字节)

    2.1在Java中,我们使用AES/GCM/NoPadding表示AES-GCM算法。 对于加密的输出,我们将16字节的IV前缀到加密的文本(密文)之前,因为解密需要相同的IV。

    如果IV是众所周知的,可以吗?
    IV公开是可以的,唯一的秘诀就是密钥,对它保密并保密。

    本示例将使用AES加密纯文本Hello World AES-GCM ,然后将其解密回原始纯文本。

    EncryptorAesGcm.java
    package com.mkyong.crypto.encryptor;
    
    import com.mkyong.crypto.utils.CryptoUtils;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.GCMParameterSpec;
    import java.nio.ByteBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    
    /**
     * AES-GCM inputs - 12 bytes IV, need the same IV and secret keys for encryption and decryption.
     * <p>
     * The output consist of iv, encrypted content, and auth tag in the following format:
     * output = byte[] {i i i c c c c c c ...}
     * <p>
     * i = IV bytes
     * c = content bytes (encrypted content, auth tag)
     */
    public class EncryptorAesGcm {
    
        private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
        private static final int TAG_LENGTH_BIT = 128;
        private static final int IV_LENGTH_BYTE = 12;
        private static final int AES_KEY_BIT = 256;
    
        private static final Charset UTF_8 = StandardCharsets.UTF_8;
    
        // AES-GCM needs GCMParameterSpec
        public static byte[] encrypt(byte[] pText, SecretKey secret, byte[] iv) throws Exception {
    
            Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
            cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
            byte[] encryptedText = cipher.doFinal(pText);
            return encryptedText;
    
        }
    
        // prefix IV length + IV bytes to cipher text
        public static byte[] encryptWithPrefixIV(byte[] pText, SecretKey secret, byte[] iv) throws Exception {
    
            byte[] cipherText = encrypt(pText, secret, iv);
    
            byte[] cipherTextWithIv = ByteBuffer.allocate(iv.length + cipherText.length)
                    .put(iv)
                    .put(cipherText)
                    .array();
            return cipherTextWithIv;
    
        }
    
        public static String decrypt(byte[] cText, SecretKey secret, byte[] iv) throws Exception {
    
            Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
            cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
            byte[] plainText = cipher.doFinal(cText);
            return new String(plainText, UTF_8);
    
        }
    
        public static String decryptWithPrefixIV(byte[] cText, SecretKey secret) throws Exception {
    
            ByteBuffer bb = ByteBuffer.wrap(cText);
    
            byte[] iv = new byte[IV_LENGTH_BYTE];
            bb.get(iv);
            //bb.get(iv, 0, iv.length);
    
            byte[] cipherText = new byte[bb.remaining()];
            bb.get(cipherText);
    
            String plainText = decrypt(cipherText, secret, iv);
            return plainText;
    
        }
    
        public static void main(String[] args) throws Exception {
    
            String OUTPUT_FORMAT = "%-30s:%s";
    
            String pText = "Hello World AES-GCM, Welcome to Cryptography!";
    
            // encrypt and decrypt need the same key.
            // get AES 256 bits (32 bytes) key
            SecretKey secretKey = CryptoUtils.getAESKey(AES_KEY_BIT);
    
            // encrypt and decrypt need the same IV.
            // AES-GCM needs IV 96-bit (12 bytes)
            byte[] iv = CryptoUtils.getRandomNonce(IV_LENGTH_BYTE);
    
            byte[] encryptedText = EncryptorAesGcm.encryptWithPrefixIV(pText.getBytes(UTF_8), secretKey, iv);
    
            System.out.println("\n------ AES GCM Encryption ------");
            System.out.println(String.format(OUTPUT_FORMAT, "Input (plain text)", pText));
            System.out.println(String.format(OUTPUT_FORMAT, "Key (hex)", CryptoUtils.hex(secretKey.getEncoded())));
            System.out.println(String.format(OUTPUT_FORMAT, "IV  (hex)", CryptoUtils.hex(iv)));
            System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (hex) ", CryptoUtils.hex(encryptedText)));
            System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (hex) (block = 16)", CryptoUtils.hexWithBlockSize(encryptedText, 16)));
    
            System.out.println("\n------ AES GCM Decryption ------");
            System.out.println(String.format(OUTPUT_FORMAT, "Input (hex)", CryptoUtils.hex(encryptedText)));
            System.out.println(String.format(OUTPUT_FORMAT, "Input (hex) (block = 16)", CryptoUtils.hexWithBlockSize(encryptedText, 16)));
            System.out.println(String.format(OUTPUT_FORMAT, "Key (hex)", CryptoUtils.hex(secretKey.getEncoded())));
    
            String decryptedText = EncryptorAesGcm.decryptWithPrefixIV(encryptedText, secretKey);
    
            System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));
    
        }
    
    }

    输出量

    纯文本: Hello World AES-GCM

    Terminal
    ------ AES GCM Encryption ------
    Input (plain text)            :Hello World AES-GCM
    Key (hex)                     :603d87185bf855532f14a77a91ec7b025c004bf664e9f5c6e95613ee9577f436
    IV  (hex)                     :bdb271ce5235996a0709e09c
    Encrypted (hex)               :bdb271ce5235996a0709e09c2d03eefe319e9329768724755c56291aecaef88cd1e6bdf72b8c7b54d75a94e66b0cd3
    Encrypted (hex) (block = 16)  :[bdb271ce5235996a0709e09c2d03eefe, 319e9329768724755c56291aecaef88c, d1e6bdf72b8c7b54d75a94e66b0cd3]
    
    ------ AES GCM Decryption ------
    Input (hex)                   :bdb271ce5235996a0709e09c2d03eefe319e9329768724755c56291aecaef88cd1e6bdf72b8c7b54d75a94e66b0cd3
    Input (hex) (block = 16)      :[bdb271ce5235996a0709e09c2d03eefe, 319e9329768724755c56291aecaef88c, d1e6bdf72b8c7b54d75a94e66b0cd3]
    Key (hex)                     :603d87185bf855532f14a77a91ec7b025c004bf664e9f5c6e95613ee9577f436
    Decrypted (plain text)        :Hello World AES-GCM

    纯文本: Hello World AES-GCM, Welcome to Cryptography!

    Terminal
    ------ AES GCM Encryption ------
    Input (plain text)            :Hello World AES-GCM, Welcome to Cryptography!
    Key (hex)                     :ddc24663d104e1c2f81f11aef98156503dafdc435f81e3ac3d705015ebab095c
    IV  (hex)                     :b05d6aedf023f73b9e1e2d11
    Encrypted (hex)               :b05d6aedf023f73b9e1e2d11f6f5137d971aea8c5cdd5b045e0960eb4408e0ee4635cccc2dfeec2c13a89bd400f659be82dc2329e9c36e3b032f38bd42296a8495ac840b0625c097d9
    Encrypted (hex) (block = 16)  :[b05d6aedf023f73b9e1e2d11f6f5137d, 971aea8c5cdd5b045e0960eb4408e0ee, 4635cccc2dfeec2c13a89bd400f659be, 82dc2329e9c36e3b032f38bd42296a84, 95ac840b0625c097d9]
    
    ------ AES GCM Decryption ------
    Input (hex)                   :b05d6aedf023f73b9e1e2d11f6f5137d971aea8c5cdd5b045e0960eb4408e0ee4635cccc2dfeec2c13a89bd400f659be82dc2329e9c36e3b032f38bd42296a8495ac840b0625c097d9
    Input (hex) (block = 16)      :[b05d6aedf023f73b9e1e2d11f6f5137d, 971aea8c5cdd5b045e0960eb4408e0ee, 4635cccc2dfeec2c13a89bd400f659be, 82dc2329e9c36e3b032f38bd42296a84, 95ac840b0625c097d9]
    Key (hex)                     :ddc24663d104e1c2f81f11aef98156503dafdc435f81e3ac3d705015ebab095c
    Decrypted (plain text)        :Hello World AES-GCM, Welcome to Cryptography!

    3.基于AES密码的加密和解密。

    对于基于密码的加密,我们可以使用定义为RFC 8018的基于密码的密码规范(PKCS)从给定的密码生成密钥。

    对于PKCS输入:

    • 密码,您提供。
    • 盐–至少64位(8字节)随机字节。
    • 迭代计数–建议最小迭代计数为1,000。

    什么是盐和迭代计数?

    • salt会为给定的密码生成广泛的密钥集。 例如,如果盐是128位,则每个密码将有多达2 ^ 128个密钥。 因此,它增加了彩虹攻击的难度。 此外,攻击者为一个用户的密码构建的彩虹表对于另一用户变得毫无用处。
    • iteration count增加了从密码生成密钥的成本,因此增加了难度并减慢了攻击速度。

    3.1对于加密的输出,我们在密文前面加上12 bytes IVpassword salt ,因为我们需要相同的IV和密码盐(用于密钥)进行解密。 此外,我们使用Base64编码器将加密的文本编码为字符串表示形式,以便我们可以以字符串格式(字节数组)发送加密的文本或密文。

    如果密码盐是众所周知的,可以吗?
    与IV相同,并且可以公开知道密码盐,唯一的秘诀就是密钥,并对其进行保密和保密。

    EncryptorAesGcmPassword.java
    package com.mkyong.crypto.encryptor;
    
    import com.mkyong.crypto.utils.CryptoUtils;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.GCMParameterSpec;
    import java.nio.ByteBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    
    /**
     * AES-GCM inputs - 12 bytes IV, need the same IV and secret keys for encryption and decryption.
     * <p>
     * The output consist of iv, password's salt, encrypted content and auth tag in the following format:
     * output = byte[] {i i i s s s c c c c c c ...}
     * <p>
     * i = IV bytes
     * s = Salt bytes
     * c = content bytes (encrypted content)
     */
    public class EncryptorAesGcmPassword {
    
        private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
    
        private static final int TAG_LENGTH_BIT = 128; // must be one of {128, 120, 112, 104, 96}
        private static final int IV_LENGTH_BYTE = 12;
        private static final int SALT_LENGTH_BYTE = 16;
        private static final Charset UTF_8 = StandardCharsets.UTF_8;
    
        // return a base64 encoded AES encrypted text
        public static String encrypt(byte[] pText, String password) throws Exception {
    
            // 16 bytes salt
            byte[] salt = CryptoUtils.getRandomNonce(SALT_LENGTH_BYTE);
    
            // GCM recommended 12 bytes iv?
            byte[] iv = CryptoUtils.getRandomNonce(IV_LENGTH_BYTE);
    
            // secret key from password
            SecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.toCharArray(), salt);
    
            Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
    
            // ASE-GCM needs GCMParameterSpec
            cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
    
            byte[] cipherText = cipher.doFinal(pText);
    
            // prefix IV and Salt to cipher text
            byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length)
                    .put(iv)
                    .put(salt)
                    .put(cipherText)
                    .array();
    
            // string representation, base64, send this string to other for decryption.
            return Base64.getEncoder().encodeToString(cipherTextWithIvSalt);
    
        }
    
        // we need the same password, salt and iv to decrypt it
        private static String decrypt(String cText, String password) throws Exception {
    
            byte[] decode = Base64.getDecoder().decode(cText.getBytes(UTF_8));
    
            // get back the iv and salt from the cipher text
            ByteBuffer bb = ByteBuffer.wrap(decode);
    
            byte[] iv = new byte[IV_LENGTH_BYTE];
            bb.get(iv);
    
            byte[] salt = new byte[SALT_LENGTH_BYTE];
            bb.get(salt);
    
            byte[] cipherText = new byte[bb.remaining()];
            bb.get(cipherText);
    
            // get back the aes key from the same password and salt
            SecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.toCharArray(), salt);
    
            Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
    
            cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
    
            byte[] plainText = cipher.doFinal(cipherText);
    
            return new String(plainText, UTF_8);
    
        }
    
        public static void main(String[] args) throws Exception {
    
            String OUTPUT_FORMAT = "%-30s:%s";
            String PASSWORD = "this is a password";
            String pText = "AES-GSM Password-Bases encryption!";
    
            String encryptedTextBase64 = EncryptorAesGcmPassword.encrypt(pText.getBytes(UTF_8), PASSWORD);
    
            System.out.println("\n------ AES GCM Password-based Encryption ------");
            System.out.println(String.format(OUTPUT_FORMAT, "Input (plain text)", pText));
            System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (base64) ", encryptedTextBase64));
    
            System.out.println("\n------ AES GCM Password-based Decryption ------");
            System.out.println(String.format(OUTPUT_FORMAT, "Input (base64)", encryptedTextBase64));
    
            String decryptedText = EncryptorAesGcmPassword.decrypt(encryptedTextBase64, PASSWORD);
            System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));
    
        }
    
    }

    输出量

    Terminal
    ------ AES GCM Password-based Encryption ------
    Input (plain text)            :AES-GSM Password-Bases encryption!
    Encrypted (base64)            :KmrvjnMusJTQo/hB7T5BvlQpvi3bVbdjpZP51NT7I/enrIfSQuDfSK6iXgdPzvUP2IE54mwrKiyHqMkG8224lRZ9tXHcclmdh98I8b3B
    
    ------ AES GCM Password-based Decryption ------
    Input (base64)                :KmrvjnMusJTQo/hB7T5BvlQpvi3bVbdjpZP51NT7I/enrIfSQuDfSK6iXgdPzvUP2IE54mwrKiyHqMkG8224lRZ9tXHcclmdh98I8b3B
    Decrypted (plain text)        :AES-GSM Password-Bases encryption!

    3.2如果密码不匹配,Java会抛出AEADBadTagException: Tag mismatch!

    // change the password to something else
      String decryptedText = EncryptorAesGcmPassword.decrypt(encryptedTextBase64, "other password");
      System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));

    输出量

    Terminal
    Exception in thread "main" javax.crypto.AEADBadTagException: Tag mismatch!
      at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:623)
      at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118)
      at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1055)
      at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:855)
      at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
      at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)
      at com.mkyong.crypto.encryptor.EncryptorAesGcmPassword.decrypt(EncryptorAesGcmPassword.java:88)
      at com.mkyong.crypto.encryptor.EncryptorAesGcmPassword.main(EncryptorAesGcmPassword.java:109)

    4. AES文件加密和解密。

    此示例是基于AES密码的文件加密。 想法是相同的,但是我们需要一些IO类来处理资源或文件。

    这是resources文件夹中的文本文件。

    readme.txt
    This is line 1.
    This is line 2.
    This is line 3.
    This is line 4.
    This is line 5.
    This is line 9.
    This is line 10.

    4.1此示例类似于3.1 EncryptorAesGcmPassword.java ,但有一些小的更改,例如返回byte[]而不是base64编码的字符串。

    public static byte[] encrypt(byte[] pText, String password) throws Exception {
    
            //...
    
            // prefix IV and Salt to cipher text
            byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length)
                    .put(iv)
                    .put(salt)
                    .put(cipherText)
                    .array();
    
            // it works, even if we save the based64 encoded string into a file.
            // return Base64.getEncoder().encodeToString(cipherTextWithIvSalt);
    
            // we save the byte[] into a file.
            return cipherTextWithIvSalt;
    
        }

    添加encryptFiledecryptFile工作与文件。

    public static void encryptFile(String fromFile, String toFile, String password) throws Exception {
    
            // read a normal txt file
            byte[] fileContent = Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(fromFile).toURI()));
    
            // encrypt with a password
            byte[] encryptedText = EncryptorAesGcmPasswordFile.encrypt(fileContent, password);
    
            // save a file
            Path path = Paths.get(toFile);
    
            Files.write(path, encryptedText);
    
        }
    
        public static byte[] decryptFile(String fromEncryptedFile, String password) throws Exception {
    
            // read a file
            byte[] fileContent = Files.readAllBytes(Paths.get(fromEncryptedFile));
    
            return EncryptorAesGcmPasswordFile.decrypt(fileContent, password);
    
        }

    4.2从类路径中读取以上readme.txt文件,对其进行加密,然后将加密的数据保存到新文件c:\test\readme.encrypted.txt

    String password = "password123";
      String fromFile = "readme.txt"; // from resources folder
      String toFile = "c:\\test\\readme.encrypted.txt";
    
      // encrypt file
      EncryptorAesGcmPasswordFile.encryptFile(fromFile, toFile, password);

    输出量

    AES文件加密

    4.3读取加密的文件,解密并打印输出。

    String password = "password123";
      String toFile = "c:\\test\\readme.encrypted.txt";
    
      // decrypt file
      byte[] decryptedText = EncryptorAesGcmPasswordFile.decryptFile(toFile, password);
      String pText = new String(decryptedText, UTF_8);
      System.out.println(pText);

    输出量

    Terminal
    This is line 1.
    This is line 2.
    This is line 3.
    This is line 4.
    This is line 5.
    This is line 9.
    This is line 10.

    PS AES图像加密是相同的概念。

    下载源代码

    $ git clone https://github.com/mkyong/core-java

    $ cd java-crypto

    让我知道文章是否需要改进。 谢谢。

    参考文献

    翻译自: https://mkyong.com/java/java-aes-encryption-and-decryption/

    展开全文
  • JAVA AES加密算法实现代码

    千次阅读 2015-07-28 14:20:29
    JAVA AES加密算法实现代码
  • JAVA AES加密解密

    2015-07-30 20:45:51
    * 编码工具类 * 1.将byte[]转为各种进制的字符串 * 2.base 64 encode * 3.base 64 decode * 4.... * 5.... * 6.... * 7.AES加密 * 8.AES加密为base 64 code * 9.AES解密 * 10.将base 64 code AES解密
  • java AES加密遇到的一些问题

    千次阅读 2017-04-11 14:59:23
    java AES加密遇到的一些问题AES加密工具类见:https://github.com/scottyab/AESCrypt-Android/blob/master/aescrypt/src/main/java/com/scottyab/aescrypt/AESCrypt.java1.Android支持PKCS7Padding填充方式,而java...
  • java AES 加密解密小工具,源码直接打包成jar,可以运行 可以应用于项目中的加密和解密
  • AES加密的两种方式。一种String 一种byte。并且添加进制转换解决加密过程非法报错问题
  • Alright, turns out I suck at Encryption/... I just dont get it.How can I make Java encrypt String message1 = "hello world"; with String salt = "mySalt"; using AES encryption? also how can I de...
  • java AES 加密和linux解密

    千次阅读 2018-06-25 11:05:02
    java AES 加密:package app; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import java.net.URLEncoder; import java.security....
  • JAVA AES加密/解密

    千次阅读 2017-06-15 22:33:26
    JAVA AES-CBC-128 加密解密
  • Java AES加密示例

    千次阅读 2017-09-07 17:33:12
    AES加密示例 import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Base64; import ...
  • Java AES 加密在Windows和linux不同

    千次阅读 2018-01-11 15:52:44
    Java AES 加密在Windows和linux不同 原因: 1. SecureRandom 类中 setSeed()底层调用的是 native 方法.所以造成了不同环境之间随机数出现了差别。导致解密不一致问题。 2. 由于linux和window的内核不同造成的...
  • #!/usr/bin/python ...from Crypto.Cipher import AES from decimal import Decimal import time import md5 import base64 import requests import BiDataCalc import json import datetime import ar...
  • 前一久,在对接支付通道时,遇到上游使用AES加密方式,对方要求加密时使用CBC模式,zeropadding填充,偏移量为0000*4(即16个0),输出十六进制,字符集使用UTF-8。 本以为也没什么问题,可到实际开发时却发现Java...
  • JAVA AES加密与解密

    万次阅读 2017-09-12 09:50:29
    1、AES加密简介 AES加密算法是密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全...
  • java AES加密算法

    2011-07-12 11:31:02
    这是一个写加密算法的例子,为了来您在互联网的安全工作中能够更加得心应手,我为您提供了这个加密算法
  • java编写的AES加密解密,并且包含界面
  • 1 前言java开发中,加密还是一...在javaAES加密用的比较多2 AES对称加密AES加密是一种对称加密,即加密和解密的密钥是相同的。在Android中,使用AES的加密如下:/** * @author Created by qiyei2015 on 2017/12/13.
  • JAVA AES加密使用

    2015-06-10 09:05:26
    AES(Advanced Encryption Standard),高级加密标准,是美国政府用于替换DES的一种加密算法标准,Java SDK中包含了部分AES的实现,但javadoc对于算法的描述非常少,本文将解释Java AES实现的使用和原理。 二.示例...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,307
精华内容 10,922
关键字:

javaaes加密

java 订阅