做网站客户最关心哪些问题,站外推广怎么做,python做调查问卷网站,网络小说网站三巨头对称密钥加密算法 对称轮数抽象 这是涵盖Java加密算法的三部分博客系列的第2部分。 该系列涵盖如何实现以下功能#xff1a; 使用SHA–512散列 AES–256 RSA–4096 这第二篇文章详细介绍了如何实现单密钥对称AES-256加密。 让我们开始吧。 免责声明 这篇文章仅供参考。 在… 对称密钥加密算法 对称轮数 抽象 这是涵盖Java加密算法的三部分博客系列的第2部分。 该系列涵盖如何实现以下功能 使用SHA–512散列 AES–256 RSA–4096 这第二篇文章详细介绍了如何实现单密钥对称AES-256加密。 让我们开始吧。 免责声明 这篇文章仅供参考。 在使用所提供的任何信息之前请认真思考。 从中学到东西但最终自己做出决定风险自负。 要求 我使用以下主要技术完成了本文的所有工作。 您可能可以使用不同的技术或版本来做相同的事情但不能保证。 Java 1.8.0_152_x64 Java密码术扩展JCE的无限强度 NetBeans 8.2内部版本201609300101 Maven 3.0.5与NetBeans捆绑在一起 下载 访问我的GitHub页面以查看我所有的开源项目。 这篇文章的代码位于项目中 thoth-cryptography 对称加密 关于 对称加密算法基于单个密钥。 此密钥用于加密和解密。 因此对称算法仅应在严格控制密钥的地方使用。 对称算法通常用于安全环境中的数据加密和解密。 一个很好的例子是确保微服务通信的安全。 如果OAuth-2 / JWT体系结构超出范围则API网关可以使用对称算法的单密钥来加密令牌。 然后将此令牌传递给其他微服务。 其他微服务使用相同的密钥来解密令牌。 另一个很好的例子是电子邮件中嵌入的超链接。 电子邮件中的超链接包含一个编码的令牌当单击该超链接时该令牌允许自动登录请求处理。 此令牌是由对称算法生成的高度加密的值因此只能在应用程序服务器上解码。 当然任何时候都需要保护任何类型的密码或凭证使用对称算法对它们进行加密然后可以使用相同的密钥对字节进行解密。 截止目前的研究似乎表明以下是最佳和最安全的单密钥对称加密算法Sheth2017年“选择正确的算法”第2段 算法 AES 模式 GCM 填充 PKCS5Padding 密钥大小 256位 IV大小 96位 AES–256使用256位密钥 需要安装Java密码学扩展JCE无限强度软件包。 让我们看一个例子。 注意 256位密钥需要Java密码术扩展JCE无限强度软件包。 如果未安装则最大为128位密钥。 例 如果尚未安装请下载并安装Java Cryptography ExtensionJCE无限强度软件包。 需要使用256位密钥。 否则必须将以下示例更新为使用128位密钥。 清单1是AesTest.java单元测试。 这是以下内容的完整演示 生成并存储AES 256位密钥 AES加密 AES解密 清单2显示了AesSecretKeyProducer.java 。 这是一个帮助程序类负责产生一个新密钥或从byte[]复制一个现有密钥。 清单3显示了ByteArrayWriter.java 清单4显示了ByteArrayReader.java 。 这些是负责将byte[]写入文件的助手类。 由您决定如何存储密钥的byte[] 但需要将其安全地存储在某个地方文件数据库git存储库等。 最后清单5显示了Aes.java 。 这是一个帮助程序类负责加密和解密。 清单1 – AesTest.java类 package org.thoth.crypto.symmetric;import java.io.ByteArrayOutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import javax.crypto.SecretKey;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.thoth.crypto.io.ByteArrayReader;
import org.thoth.crypto.io.ByteArrayWriter;/**** author Michael Remijan mjremijanyahoo.com mjremijan*/
public class AesTest {static Path secretKeyFile;BeforeClasspublic static void beforeClass() throws Exception {// Store the SecretKey bytes in the ./target diretory. Do// this so it will be ignore by source control. We dont// want this file committed.secretKeyFile Paths.get(./target/Aes256.key).toAbsolutePath();// Generate a SecretKey for the testSecretKey secretKey new AesSecretKeyProducer().produce();// Store the byte[] of the SecretKey. This is the// private key file you want to keep safe.ByteArrayWriter writer new ByteArrayWriter(secretKeyFile);writer.write(secretKey.getEncoded());}Testpublic void encrypt_and_decrypt_using_same_Aes256_instance() {// setupSecretKey secretKey new AesSecretKeyProducer().produce(new ByteArrayReader(secretKeyFile).read());Aes aes new Aes(secretKey);String toEncrypt encrypt me;// runbyte[] encryptedBytes aes.encrypt(toEncrypt, Optional.empty());String decrypted aes.decrypt(encryptedBytes, Optional.empty());// assertAssert.assertEquals(toEncrypt, decrypted);}public void encrypt_and_decrypt_with_aad_using_same_Aes256_instance() {// setupSecretKey secretKey new AesSecretKeyProducer().produce(new ByteArrayReader(secretKeyFile).read());Aes aes new Aes(secretKey);String toEncrypt encrypt me aad;// runbyte[] encryptedBytes aes.encrypt(toEncrypt, Optional.of(JUnit AAD));String decrypted aes.decrypt(encryptedBytes, Optional.of(JUnit AAD));// assertAssert.assertEquals(toEncrypt, decrypted);}Testpublic void encrypt_and_decrypt_using_different_Aes256_instance()throws Exception {// setupSecretKey secretKey new AesSecretKeyProducer().produce(new ByteArrayReader(secretKeyFile).read());Aes aesForEncrypt new Aes(secretKey);Aes aesForDecrypt new Aes(secretKey);String toEncrypt encrypt me;// runbyte[] encryptedBytes aesForEncrypt.encrypt(toEncrypt, Optional.empty());ByteArrayOutputStream baos new ByteArrayOutputStream();baos.write(encryptedBytes);String decrypted aesForDecrypt.decrypt(baos.toByteArray(), Optional.empty());// assertAssert.assertEquals(toEncrypt, decrypted);}
} 清单2 – AesSecretKeyProducer.java类 package org.thoth.crypto.symmetric;import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;/**** author Michael Remijan mjremijanyahoo.com mjremijan*/
public class AesSecretKeyProducer {/*** Generates a new AES-256 bit {code SecretKey}.** return {code SecretKey}, never null* throws RuntimeException All exceptions are caught and re-thrown as {code RuntimeException}*/public SecretKey produce() {KeyGenerator keyGen;try {keyGen KeyGenerator.getInstance(AES);keyGen.init(256);SecretKey secretKey keyGen.generateKey();return secretKey;} catch (Exception ex) {throw new RuntimeException(ex);}}/*** Generates an AES-256 bit {code SecretKey}.** param encodedByteArray The bytes this method will use to regenerate a previously created {code SecretKey}** return {code SecretKey}, never null* throws RuntimeException All exceptions are caught and re-thrown as {code RuntimeException}*/public SecretKey produce(byte [] encodedByteArray) {try {return new SecretKeySpec(encodedByteArray, AES);} catch (Exception ex) {throw new RuntimeException(ex);}}
} 清单3 – ByteArrayWriter.java类 package org.thoth.crypto.io;import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;/**** author Michael Remijan mjremijanyahoo.com mjremijan*/
public class ByteArrayWriter {protected Path outputFile;private void initOutputFile(Path outputFile) {this.outputFile outputFile;}private void initOutputDirectory() {Path outputDirectory outputFile.getParent();if (!Files.exists(outputDirectory)) {try {Files.createDirectories(outputDirectory);} catch (IOException e) {throw new RuntimeException(e);}}}public ByteArrayWriter(Path outputFile) {initOutputFile(outputFile);initOutputDirectory();}public void write(byte[] bytesArrayToWrite) {try (OutputStream os Files.newOutputStream(outputFile);PrintWriter writer new PrintWriter(os);){for (int i0; ibytesArrayToWrite.length; i) {if (i0) {writer.println();}writer.print(bytesArrayToWrite[i]);}} catch (IOException ex) {throw new RuntimeException(ex);}}
} 清单4 – ByteArrayReader.java类 package org.thoth.crypto.io;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Scanner;/**** author Michael Remijan mjremijanyahoo.com mjremijan*/
public class ByteArrayReader {protected Path inputFile;public ByteArrayReader(Path inputFile) {this.inputFile inputFile;}public byte[] read() {try (Scanner scanner new Scanner(inputFile);ByteArrayOutputStream baos new ByteArrayOutputStream();){while (scanner.hasNext()) {baos.write(Byte.parseByte(scanner.nextLine()));}baos.flush();return baos.toByteArray();} catch (IOException ex) {throw new RuntimeException(ex);}}
} 清单5 – Aes.java类 package org.thoth.crypto.symmetric;import java.security.SecureRandom;
import java.util.Optional;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;/**** author Michael Remijan mjremijanyahoo.com mjremijan*/
public class Aes {// If you dont have the Java Cryptography Extension// (JCE) Unlimited Strength packaged installed, use// a 128 bit KEY_SIZE.public static int KEY_SIZE 256;public static int IV_SIZE 12; // 12bytes * 8 96bitspublic static int TAG_BIT_SIZE 128;public static String ALGORITHM_NAME AES;public static String MODE_OF_OPERATION GCM;public static String PADDING_SCHEME PKCS5Padding;protected SecretKey secretKey;protected SecureRandom secureRandom;public Aes(SecretKey secretKey) {this.secretKey secretKey;this.secureRandom new SecureRandom();}public byte[] encrypt(String message, OptionalString aad) {try {// Transformation specifies algortihm, mode of operation and paddingCipher c Cipher.getInstance(String.format(%s/%s/%s,ALGORITHM_NAME,MODE_OF_OPERATION,PADDING_SCHEME));// Generate IVbyte iv[] new byte[IV_SIZE];secureRandom.nextBytes(iv); // SecureRandom initialized using self-seeding// Initialize GCM ParametersGCMParameterSpec spec new GCMParameterSpec(TAG_BIT_SIZE, iv);// Init for encryptionc.init(Cipher.ENCRYPT_MODE, secretKey, spec, secureRandom);// Add AAD tag data if presentaad.ifPresent(t - {try {c.updateAAD(t.getBytes(UTF-8));} catch (Exception e) {throw new RuntimeException(e);}});// Add message to encryptc.update(message.getBytes(UTF-8));// Encryptbyte[] encryptedBytes c.doFinal();// Concatinate IV and encrypted bytes. The IV is needed later// in order to to decrypt. The IV value does not need to be// kept secret, so its OK to encode it in the return value//// Create a new byte[] the combined length of IV and encryptedBytesbyte[] ivPlusEncryptedBytes new byte[iv.length encryptedBytes.length];// Copy IV bytes into the new arraySystem.arraycopy(iv, 0, ivPlusEncryptedBytes, 0, iv.length);// Copy encryptedBytes into the new arraySystem.arraycopy(encryptedBytes, 0, ivPlusEncryptedBytes, iv.length, encryptedBytes.length);// Returnreturn ivPlusEncryptedBytes;} catch (Exception e) {throw new RuntimeException(e);}}public String decrypt(byte[] ivPlusEncryptedBytes, OptionalString aad) {try {// Get IVbyte iv[] new byte[IV_SIZE];System.arraycopy(ivPlusEncryptedBytes, 0, iv, 0, IV_SIZE);// Initialize GCM ParametersGCMParameterSpec spec new GCMParameterSpec(TAG_BIT_SIZE, iv);// Transformation specifies algortihm, mode of operation and paddingCipher c Cipher.getInstance(String.format(%s/%s/%s,ALGORITHM_NAME,MODE_OF_OPERATION,PADDING_SCHEME));// Get encrypted bytesbyte [] encryptedBytes new byte[ivPlusEncryptedBytes.length - IV_SIZE];System.arraycopy(ivPlusEncryptedBytes, IV_SIZE, encryptedBytes, 0, encryptedBytes.length);// Init for decryptionc.init(Cipher.DECRYPT_MODE, secretKey, spec, secureRandom);// Add AAD tag data if presentaad.ifPresent(t - {try {c.updateAAD(t.getBytes(UTF-8));} catch (Exception e) {throw new RuntimeException(e);}});// Add message to decryptc.update(encryptedBytes);// Decryptbyte[] decryptedBytes c.doFinal();// Returnreturn new String(decryptedBytes, UTF-8);} catch (Exception e) {throw new RuntimeException(e);}}
}摘要 加密并不容易。 简单的示例将为您的应用程序带来带有安全漏洞的实现。 如果您需要单密钥对称加密算法请使用具有256位密钥和96位IV的密码AES / GCM / PKCS5Padding。 参考资料 Java密码术扩展JCE无限强度。 nd。 检索自http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html 。 ShethM.2017年4月18日。 Java密码学中的加密和解密。 从https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography检索。 cpast [表示GCM IV是96位即96/8 12字节]。 2015年6月4日。 使用AES–256加密时我可以使用256位IV [Web日志注释]。 从https://security.stackexchange.com/questions/90848/encrypting-using-aes-256-can-i-use-256-bits-iv检索 Bodewes [强烈建议将GCM IV设置为12个字节12 * 8 96但可以是任意大小。 其他尺寸将需要其他计算]M。2015年7月7日。 密文和标签大小以及在GCM模式下使用AES进行IV传输[Web日志注释]。 从https://crypto.stackexchange.com/questions/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode检索。 Figlesquidge。 2013年10月18日。 “密码”和“操作模式”之间有什么区别 [网络日志评论]。 从https://crypto.stackexchange.com/questions/11132/what-is-the-difference-between-a-cipher-and-a-mode-of-operation检索。 ToustS.2013年2月4日。 为什么对称和非对称加密之间的建议密钥大小会有很大差异 取自https://crypto.stackexchange.com/questions/6236/why-does-the-recommended-key-size-between-symmetric-and-asymmetric-encryption-di 。 卡罗宁I.2012年10月5日。 密钥IV和随机数之间的主要区别是什么 从https://crypto.stackexchange.com/questions/3965/what-is-the-main-difference-between-a-key-an-iv-and-a-nonce检索。 分组密码操作模式。 2017年11月6日。 维基百科。 取自https://zh.wikipedia.org/wiki/Block_cipher_mode_of_operation#Initialization_vector_.28IV.29 翻译自: https://www.javacodegeeks.com/2017/12/choosing-java-cryptographic-algorithms-part-2-single-key-symmetric-encryption.html对称密钥加密算法 对称轮数