岳阳网站建设收费标准,网站建设的基本需求有哪些,wordpress安装502,wordpress上传中文图片不显示加密算法
加密算法是一种通过对数据进行编码或转换#xff0c;使其难以被未经授权的人解读或访问的方法#xff0c;常见的加解密算法大致包括以下几类
对称加密算法#xff1a;使用相同的密钥进行加密和解密#xff0c;包括DES、3DES、AES等,对称加密算法适用于数据量较小…加密算法
加密算法是一种通过对数据进行编码或转换使其难以被未经授权的人解读或访问的方法常见的加解密算法大致包括以下几类
对称加密算法使用相同的密钥进行加密和解密包括DES、3DES、AES等,对称加密算法适用于数据量较小的场景。非对称加密算法使用一对密钥公钥和私钥进行加密和解密包括RSA、ECC等非对称加密算法适用于需要安全性较高的场景。哈希算法将任意长度的消息压缩到固定长度的摘要中包括MD5、SHA-1、SHA-256等哈希算法适用于数据完整性校验场景。消息认证码算法对消息进行完整性校验和防篡改校验包括HMAC等消息认证码算法适用于防篡改场景。
AES加密模式
加密算法的选择应根据具体需求和应用场景来决定今天就来详细说说对称加密算法中的AESAES是一种对称加密算法全称为“高级加密标准”Advanced Encryption Standard。它是一个区块加密算法适用于大多数应用场景包括加密和解密还可以在不同的平台和设备之间进行加密和解密操作AES加密算法支持多种加密模式常见的加密模式有以下五种
AES加密算法支持多种加密模式常见的加密模式有以下五种
ECB (Electronic CodeBook)
ECB是最简单的加密模式它将明文按块处理每个块独立加密最后输出密文。这种加密方式的缺点是相同的明文块生成相同的密文块因此不利于安全性。这种加密方式一般不建议使用。
CBC (Cipher Block Chaining)
CBC模式是最常见的加密模式之一它需要一个初始化向量(IV)。加密过程中每个明文块与前一个密文块进行异或操作然后再进行加密。这种加密方式的优点是不容易受到字典攻击缺点是不容易并行处理加密效率低于ECB是SSL、IPSec的标准。
CFB (Cipher FeedBack)
CFB模式是一种比较常见的流加密模式它将明文按照位进行加密每次处理一个比特位。加密过程中将前一次的密文块作为下一次加密的输入同时输出本次密文块。这种加密方式的优点是不需要填充缺点是需要保存前一次的密文块。
OFB (Output FeedBack)
OFB模式也是一种流加密模式它的加密过程类似CFB但是OFB不需要保存前一次的密文块每次加密过程中将前一次加密的输出作为本次的输入。这种加密方式的优点是不需要填充缺点是不容易检测出位错误。
CTR (Counter)
CTR模式是一种比较常见的分组加密模式它的加密过程类似于OFB但是CTR使用了不同的加密方式。CTR不需要填充加密效率高于CBC和OFB适用于加密大量数据。CTR模式需要一个计数器每次加密时将计数器作为密钥与明文块进行异或操作然后输出密文块。每次加密结束后计数器1用于下一次加密。CTR模式可以与GCM模式结合使用提供更强的安全性和认证机制。
为什么有的加密模式需要填充
AES是一种块加密算法块的大小固定为128位因此也称为AES-128。块加密算法将明文按固定大小分成块然后对每个块进行加密操作从而得到密文。块加密算法需要对数据进行填充以保证其长度是块大小的整数倍因为最后一个块可能会比其他块短所以需要填充。块加密算法通常比流加密算法更安全但是对于较长的数据流来说需要更多的存储空间。
实现AES指定密钥和偏移量的加解密
在 Java 中Cipher 类是一个提供加密和解密功能的抽象类。它提供了一个通用的加密或解密的接口可供许多加密算法使用。该类提供了许多加密和解密操作包括对对称加密算法如 AES、DES、3DES和非对称加密算法如 RSA、DSA的支持。
使用 Cipher 类加密或解密时需要指定加密算法、加密模式和填充模式形如
AES/CBC/PKCS5Padding实现有指定的AES秘钥和指定偏移量AES加解密代码如下
package com.zlc.blog.aes;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;/*** author xiangcaimiao*/
public class AesUtils {/*** AES 对称加密RSA非对称加密* CBC 有向量 ECB 无向量* PKCS5Padding 填充模式NoPadding 无填充*/private static final String ALG_AES_CBC_PKCS5 AES/CBC/PKCS5Padding;private static final String ALGORITHM AES;private static final Charset UTF8 StandardCharsets.UTF_8;/*** 指定好的秘钥非Base64和16进制* 长度为16128bit24(192bit)或者32(256bit)*/private static final String AES_KEY 12e476beac1a4g20;/*** 偏移量16(用于构造IvParameterSpec)* IvParameterSpec可以直接使用默认的偏移量进行加解密但如果使用自定*/private static final String AES_IV 2e119e58a526bc64;private static SecretKeySpec skeySpec;private static IvParameterSpec iv;/*** AES加密* param plainText 明文* return Base64编码的密文* throws Exception 加密异常*/public static String encrypt(String plainText) throws Exception {Cipher cipher Cipher.getInstance(ALG_AES_CBC_PKCS5);skeySpec new SecretKeySpec(AES_KEY.getBytes(), ALGORITHM);iv new IvParameterSpec(AES_IV.getBytes());cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);// 这里的编码格式需要与解密编码一致byte[] encryptText cipher.doFinal(plainText.getBytes(UTF8));return Base64.getEncoder().encodeToString(encryptText);}/*** 解密方法* param cipherStr Base64编码的加密字符串* return 解密后的字符串(UTF8编码)* throws Exception 异常*/public static String decrypt(String cipherStr) throws Exception {// step 1 获得一个密码器Cipher cipher Cipher.getInstance(ALG_AES_CBC_PKCS5);// step 2 初始化密码器指定是加密还是解密(Cipher.DECRYPT_MODE 解密; Cipher.ENCRYPT_MODE 加密)// 加密时使用的盐来够造秘钥对象skeySpec new SecretKeySpec(AES_KEY.getBytes(), ALGORITHM);// 加密时使用的向量16位字符串(也可以不显示构造)// String AES_IV 3e119e58a526bc62;iv new IvParameterSpec(AES_IV.getBytes());cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);// 对加密报文进行base64解码byte[] encrypted1 Base64.getDecoder().decode(cipherStr);// 解密后的报文数组byte[] original cipher.doFinal(encrypted1);// 输出utf8编码的字符串输出字符串需要指定编码格式return new String(original, UTF8);}
}单元测试结果如下图所示
说明 如果是通过KeyGenerator生成的秘钥的话他返回的是一个字节数组需要进行Base64(不同Base64的实现得到的字符串结果可能不同)或者转换为16进制进行保存或者将字节数组存放到文件或者数据库中但不具有一般可读性 Cipher 提供了多种方式的加密通过Cipher.getInstance(“AES/CBC/PKCS5Padding”);参数按照 算法、模式、添加模式的方式来获取密码器。 Cipher常见构造密码器参数如下
密码器参数位数AES/CBC/NoPadding128AES/CBC/PKCS5Padding128AES/ECB/NoPadding128AES/ECB/PKCS5Padding128DES/CBC/NoPadding56DES/CBC/PKCS5Padding56DES/ECB/NoPadding56DES/ECB/PKCS5Padding56DESede/CBC/NoPadding168DESede/CBC/PKCS5Padding168DESede/ECB/NoPadding168DESede/ECB/PKCS5Padding168RSA/ECB/PKCS1Padding2024 2048RSA/ECB/OAEPWithSHA-1AndMGF1Padding1024 2048RSA/ECB/OAEPWithSHA-256AndMGF1Padding1024 2048 偏移量的作用 AES/CBC模式下的偏移量长度必须为16字节128位因为AES算法的块长度是128位。如果偏移量长度不是16字节则会抛出InvalidAlgorithmParameterException异常。 在使用块密码模式加密时需要提供一个初始向量IV来保证加密结果的唯一性和安全性因此在加密和解密的过程中需要指定相同的 IV。如果 IV 不同那么同一个明文可能会加密成不同的密文这就会破坏加密算法的可靠性。 在提供 IV 的情况下如果 IV 不正确解密过程会抛出异常解密失败。在代码中IV 被设置为 aesIv并通过 new IvParameterSpec(aesIv.getBytes()) 传入到解密函数中确保了解密时使用相同的 IV。 如果在解密的过程中不提供 IV那么 Cipher 会使用默认的 IV 值进行解密。默认的 IV 值通常是一个全 0 的字符串这样在解密过程中可能会得到正确的结果。但是这种方式不安全因为 IV 没有保密性如果加密多个相同的明文由于 IV 不变加密结果也将相同容易被攻击者破解。 因此为了确保加密算法的安全性推荐在加密和解密的过程中都提供相同的 IV 值并根据具体的加密模式选择不同的偏移量。 如下为在加密阶段与解密阶段使用不同的偏移量得到被加密字符串与解密后的字符串不一致结果 AES 生成随机密钥并实现加解密
添加生成秘钥方法
private static final String SECURE_RANDOM_SEED 123987;
public static SecretKey geneKey() throws Exception {KeyGenerator keyGenerator KeyGenerator.getInstance(ALGORITHM);// 固定随机种子SecureRandom类还会使用系统当前时间和其他熵源来生成随机数。// 指定长度为16128bit24(192bit)或者32(256bit)// 如下方式不会生成固定的密钥keyGenerator.init(128, new SecureRandom(SECURE_RANDOM_SEED.getBytes()));// 随机源每次生成的秘钥都会变需要保存秘钥//keyGenerator.init(new SecureRandom());return keyGenerator.generateKey();}生成的Base64秘钥为
8183ncqKcLf4Ks0o8dd0Qg使用生成的秘钥进行加解密单元测试
Testvoid testGeneAesKey(){String cipherStr;try {byte[] aesKey AesUtils.geneKey().getEncoded();System.out.println(Base64后的密钥: Base64.getEncoder().encodeToString(aesKey));assertEquals(16, aesKey.length);cipherStr AesUtils.encrypt(plainText, aesKey);System.out.println(AES 加密后的Base64报文:[ cipherStr ]);System.out.println(对加密后的报文解密后的明文为:[ AesUtils.decrypt(cipherStr, aesKey) ]);assertEquals(plainText, AesUtils.decrypt(cipherStr, aesKey));} catch (Exception e) {e.printStackTrace();}}单元测试运行结果如下 3. 说明
如果使用AES/CBC/PKCS5Padding 需要指定一个向量KeyGenerator如果使用固定的随机源则每次生成的秘钥都是一样的如果以后想要使用该密钥进行加解密需要将生成的密钥保存起来因为上述生成密钥的方式在方法每次被调用的时候会生成新的密钥
生成固定的秘钥进行加解密
生成固定的秘钥 private static final String PBE_KEY_ALGORITHM PBKDF2WithHmacSHA256;private static final char[] PASSWORD myPassword.toCharArray();private static final byte[] SALT mySaltValue.getBytes(StandardCharsets.UTF_8);private static final int ITERATIONS 10000;private static final int KEY_LENGTH 128;
public static SecretKey geneRegularKey() throws Exception {SecretKeyFactory factory SecretKeyFactory.getInstance(PBE_KEY_ALGORITHM);PBEKeySpec spec new PBEKeySpec(PASSWORD, SALT, ITERATIONS, KEY_LENGTH);return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), ALGORITHM);}
单元测试每次运行是否生成固定的密钥以及使用该密钥进行加解密
Testvoid testGeneRegularKey(){String cipherStr;try {byte [] firstKey AesUtils.geneRegularKey().getEncoded();byte [] secondKey AesUtils.geneRegularKey().getEncoded();// assertEquals(firstKey, secondKey); false 生成的对象的地址不同assertEquals(Base64.getEncoder().encodeToString(firstKey),Base64.getEncoder().encodeToString(secondKey));System.out.println(生成的固定key为: Base64.getEncoder().encodeToString(secondKey));cipherStr AesUtils.encrypt(plainText, firstKey);System.out.println(AES 加密后的Base64报文:[ cipherStr ]);System.out.println(对加密后的报文解密后的明文为:[ AesUtils.decrypt(cipherStr, secondKey) ]);assertEquals(plainText, AesUtils.decrypt(cipherStr, firstKey));} catch (Exception e) {e.printStackTrace();}}单元测试运行结果如下 说明 PBEKeySpec是Java中用于生成基于口令的加密密钥的KeySpec接口的实现类。PBE即Password-Based Encryption即基于口令的加密算法。它可以根据用户输入的密码和盐生成密钥并用于加密和解密数据。 PBE算法通常用于需要用户输入口令的场合例如保护用户数据。PBE算法将用户输入的密码和随机生成的盐值结合使用通过计算生成密钥。由于用户输入的密码可能比较短或者简单容易受到字典攻击等方式的破解因此通过使用盐值增加了加密强度。
DES与AES
在计算机领域安全性是至关重要的。密码学技术是一种应对计算机安全问题的有效手段。其中对称密钥加密算法是密码学技术中最常用的一种算法其中 DES 和 AES 算法是应用最广泛的两种对称密钥加密算法。DES 算法使用56位的密钥AES 算法则可以使用128位、192位或256位的密钥因此 AES 算法相较于 DES 算法更加安全。
AES 算法具有许多优势。首先AES 算法在硬件和软件中的实现效率比 DES 算法高同时 AES 算法的安全性也更强。其次AES 算法可以实现对大块数据的高效加密使其在网络传输时更加安全。最后由于 AES 算法可以使用更长的密钥长度因此在安全性方面也更有优势。
尽管 AES 算法比 DES 算法更加安全和高效但是在一些特殊场合下DES 算法也有其独特的应用价值。例如一些旧系统中可能只支持 DES 算法因此必须使用 DES 算法进行加密和解密。此外由于 DES 算法的密钥长度较短因此在某些嵌入式设备中DES 算法的实现可能更加方便。因此在实际应用中根据具体情况选择合适的对称密钥加密算法是非常重要的。
本文首发于香菜喵打开微信随时随地读文章下方 ↓ ↓ ↓