发送加密信息的简单实现【Java】
(修改期)
一、代码的引用处
public static SecretKeys generateKeys() throws NoSuchAlgorithmException {:
定义一个公共静态方法,用于生成 AES 和 HMAC 密钥对。
public static String encrypt(String plaintext, SecretKey aesKey, SecretKey hmacKey) throws Exception {:
定义一个公共静态方法,用于加密给定的明文,并使用 HMAC 保护其完整性。 它接受明文、AES 密钥和 HMAC 密钥作为输入,并返回 Base64 编码的加密字符串。
public static String decrypt(String encryptedText, SecretKey aesKey, SecretKey hmacKey) throws Exception {:
定义一个公共静态方法,用于解密给定的加密文本并验证其完整性。 它接受 Base64 编码的加密文本、AES 密钥和 HMAC 密钥作为输入,并返回解密的明文。
public static String[] encryptKey(SecretKeys keys, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
定义一个公共静态方法,用于加密生成的AES 密钥和 HMAC 密钥。它接收AES 密钥和 HMAC 密钥和接收者发来的公钥,并返回加密后的密钥字符串数组。
public static SecretKeys decryptKey(String []cipherText,PrivateKey privateKey) throws Exception {
定义一个公共静态方法,用于解密发送端传来的秘钥。它接收密钥字符串数组和接收者生成的私钥,并返回一个包装密钥的SecretKeys对象。
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;public class SecureAESUtils {private static final int GCM_TAG_LENGTH = 128;private static final int IV_LENGTH = 12;private static final int HMACDigest = 32;private static final int AES_KEY_LENGTH = 256;private static final int HMAC_KEY_LENGTH = 256;private static final String encryptionAlgorithm = "AES";private static final String AES_ALGORITHM = encryptionAlgorithm + "/GCM/NoPadding";private static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";private static final String HMAC_ALGORITHM = "HmacSHA256";public static class SecretKeys {private final SecretKey aesKey;private final SecretKey hmacKey;public SecretKeys(SecretKey aesKey, SecretKey hmacKey) {this.aesKey = aesKey;this.hmacKey = hmacKey;}public String getAesKeyBase64() {return Base64.getEncoder().encodeToString(aesKey.getEncoded());}public String getHmacKeyBase64() {return Base64.getEncoder().encodeToString(hmacKey.getEncoded());}public static SecretKeys fromBase64(String aesKeyBase64, String hmacKeyBase64) {SecretKey aesKey = new SecretKeySpec(Base64.getDecoder().decode(aesKeyBase64), encryptionAlgorithm);SecretKey hmacKey = new SecretKeySpec(Base64.getDecoder().decode(hmacKeyBase64), HMAC_ALGORITHM);return new SecretKeys(aesKey, hmacKey);}}public static SecretKeys generateKeys() throws NoSuchAlgorithmException {KeyGenerator aesKeyGen = KeyGenerator.getInstance(encryptionAlgorithm);aesKeyGen.init(AES_KEY_LENGTH);SecretKey secretKey = aesKeyGen.generateKey();KeyGenerator hmacKeyGen = KeyGenerator.getInstance(HMAC_ALGORITHM);hmacKeyGen.init(HMAC_KEY_LENGTH);SecretKey hmacKey = hmacKeyGen.generateKey();return new SecretKeys(secretKey, hmacKey);}public static String encrypt(String plainText, SecretKeys keys) throws Exception {byte[] iv = new byte[IV_LENGTH];SecureRandom random = SecureRandom.getInstanceStrong();random.nextBytes(iv);Cipher cipher = Cipher.getInstance(AES_ALGORITHM);GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.ENCRYPT_MODE, keys.aesKey, gcmSpec);byte[] encryptedText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));Mac hmac = Mac.getInstance(HMAC_ALGORITHM);hmac.init(keys.hmacKey);hmac.update(iv);hmac.update(encryptedText);byte[] hmacDigest = hmac.doFinal();byte[] result = new byte[IV_LENGTH + encryptedText.length + HMACDigest];System.arraycopy(iv, 0, result, 0, IV_LENGTH);System.arraycopy(encryptedText, 0, result, IV_LENGTH, encryptedText.length);System.arraycopy(hmacDigest, 0, result, IV_LENGTH + encryptedText.length, HMACDigest);return Base64.getEncoder().encodeToString(result);}public static String[] encryptKey(SecretKeys keys, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {String aesKey=keys.getAesKeyBase64();String hmacKey=keys.getHmacKeyBase64();Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE,publicKey);byte []encryptAesKey=cipher.doFinal(aesKey.getBytes(StandardCharsets.UTF_8));byte []encryptHmacKey=cipher.doFinal(hmacKey.getBytes(StandardCharsets.UTF_8));return new String[]{Base64.getEncoder().encodeToString(encryptAesKey),Base64.getEncoder().encodeToString(encryptHmacKey)};}public static String decrypt(String cipherText, SecretKeys keys) throws Exception {byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText);if (cipherTextBytes.length < IV_LENGTH + HMACDigest) {throw new IllegalArgumentException("无效的加密数据!");}byte[] iv = new byte[IV_LENGTH];byte[] encryptedData = new byte[cipherTextBytes.length - IV_LENGTH - HMACDigest];byte[] hmacDigest = new byte[HMACDigest];System.arraycopy(cipherTextBytes, 0, iv, 0, IV_LENGTH);System.arraycopy(cipherTextBytes, IV_LENGTH, encryptedData, 0, encryptedData.length);System.arraycopy(cipherTextBytes, IV_LENGTH + HMACDigest, hmacDigest, 0, HMACDigest);Mac hmac = Mac.getInstance(HMAC_ALGORITHM);hmac.init(keys.hmacKey);hmac.update(iv);hmac.update(encryptedData);byte[] calculatedHmacDigest = hmac.doFinal();if(!MessageDigest.isEqual(calculatedHmacDigest, hmacDigest)) {throw new SecurityException("HMAC校验失败,数据可能被篡改!");}Cipher cipher = Cipher.getInstance(AES_ALGORITHM);GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.DECRYPT_MODE, keys.aesKey, gcmSpec);try{byte[] decryptedText = cipher.doFinal(encryptedData);return new String(decryptedText, StandardCharsets.UTF_8);}catch (AEADBadTagException e){throw new SecurityException("GCM 标签校验失败,数据可能被篡改!", e);}}public static SecretKeys decryptKey(String []cipherText,PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedAesBytes = cipher.doFinal(Base64.getDecoder().decode(cipherText[0]));String aesKeyBase64=new String(decryptedAesBytes, StandardCharsets.UTF_8);byte[] decryptedHmacBytes =cipher.doFinal(Base64.getDecoder().decode(cipherText[1]));String hmacKeyBase64=new String(decryptedHmacBytes, StandardCharsets.UTF_8);return SecretKeys.fromBase64(aesKeyBase64,hmacKeyBase64);}
}
这个类提供公钥和私钥的生成。
直接调用构造方法即可生成,用getPrivateKey方法获取私钥,用getPublicKeyBase64方法获取用于发送的公钥。
import java.security.*;
import java.util.Base64;public class GenerateRSAKeyPairs{private static PrivateKey privateKey;public static PublicKey publicKey;public PrivateKey getPrivateKey() {return privateKey;}public String getPublicKeyBase64(){return Base64.getEncoder().encodeToString(publicKey.getEncoded());}public GenerateRSAKeyPairs () throws NoSuchAlgorithmException {KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair keyPair=keyGen.generateKeyPair();privateKey=keyPair.getPrivate();publicKey=keyPair.getPublic();}
}
这个方法将接收到的字符串形形式的公钥还原成PublicKey形式。接受Base64 编码的加密文本,返回公钥。
public static PublicKey restorePublicKey(String data){byte[] publicKeyBytes= Base64.getDecoder().decode(data);X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyBytes);try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(keySpec);} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {throw new RuntimeException(e);}}
二、代码的实现
SecureAESUtils类
1. 导入
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
-
import javax.crypto.*;
: 导入javax.crypto
包下的所有类,该包提供加密和解密相关的类和接口,例如Cipher
、SecretKey
等。 -
import javax.crypto.spec.GCMParameterSpec;
: 导入GCMParameterSpec
类,用于指定GCM( Galois/Counter Mode)模式的参数。 -
import javax.crypto.spec.SecretKeySpec;
: 导入SecretKeySpec
类,用于从字节数组构建SecretKey
对象。 -
import java.nio.charset.StandardCharsets;
: 导入StandardCharsets
类,提供标准的字符集常量,例如UTF-8。 -
import java.security.*;
: 导入java.security
包下的所有类,该包提供安全相关的类和接口,例如KeyPairGenerator
、PublicKey
、PrivateKey
等。 -
import java.security.spec.InvalidKeySpecException;
: 导入InvalidKeySpecException
类,当提供的密钥规范(Key Specification)无效时,抛出此异常。Key Specification 用于将密钥以特定的格式表示(如字节数组),以便于存储或传输。 -
import java.security.spec.X509EncodedKeySpec;
: 导入X509EncodedKeySpec
类,用于表示以X.509标准编码的公钥。 -
import java.util.Base64;
: 导入Base64
类,用于进行Base64编码和解码。
2. 类定义和常量
public class SecureAESUtils { private static final int GCM_TAG_LENGTH = 128;private static final int IV_LENGTH = 12;private static final int HMACDigest = 32;private static final int AES_KEY_LENGTH = 256;private static final int HMAC_KEY_LENGTH = 256;private static final String encryptionAlgorithm = "AES";private static final String AES_ALGORITHM = encryptionAlgorithm + "/GCM/NoPadding";private static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";private static final String HMAC_ALGORITHM = "HmacSHA256";
-
public class SecureAESUtils
: 定义一个公共类SecureAESUtils
,该类提供AES加密相关的工具方法。 -
private static final int GCM_TAG_LENGTH = 128;
: 定义常量GCM_TAG_LENGTH
,指定GCM认证标签的长度为128位。 -
private static final int IV_LENGTH = 12;
: 定义常量IV_LENGTH
,指定初始化向量(IV)的长度为12字节。 -
private static final int HMACDigest = 32;
: 定义常量HMACDigest
,指定HMAC摘要值的长度为32字节。 -
private static final int AES_KEY_LENGTH = 256;
: 定义常量AES_KEY_LENGTH
,指定AES密钥的长度为256位。 -
private static final int HMAC_KEY_LENGTH = 256;
: 定义常量HMAC_KEY_LENGTH
,指定HMAC密钥的长度为256位。 -
private static final String encryptionAlgorithm = "AES";
: 定义常量encryptionAlgorithm
,指定加密算法为AES。 -
private static final String AES_ALGORITHM = encryptionAlgorithm + "/GCM/NoPadding";
: 定义常量AES_ALGORITHM
,指定AES算法的完整模式为AES/GCM/NoPadding。GCM是一种认证加密模式,NoPadding表示不进行填充。 -
private static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";
: 定义常量RSA_ALGORITHM
,指定RSA算法的完整模式为RSA/ECB/PKCS1Padding. ECB代表电子密码本模式,PKCS1Padding 是一种常用的填充方案,用于确保数据块的大小适合 RSA 算法的要求。 -
private static final String HMAC_ALGORITHM = "HmacSHA256";
: 定义常量HMAC_ALGORITHM
,指定HMAC算法为HmacSHA256。
3. 内部类 SecretKeys
public static class SecretKeys {private final SecretKey aesKey;private final SecretKey hmacKey;public SecretKeys(SecretKey aesKey, SecretKey hmacKey) {this.aesKey = aesKey;this.hmacKey = hmacKey;}public String getAesKeyBase64() {return Base64.getEncoder().encodeToString(aesKey.getEncoded());}public String getHmacKeyBase64() {return Base64.getEncoder().encodeToString(hmacKey.getEncoded());}public static SecretKeys fromBase64(String aesKeyBase64, String hmacKeyBase64) {SecretKey aesKey = new SecretKeySpec(Base64.getDecoder().decode(aesKeyBase64), encryptionAlgorithm);SecretKey hmacKey = new SecretKeySpec(Base64.getDecoder().decode(hmacKeyBase64), HMAC_ALGORITHM);return new SecretKeys(aesKey, hmacKey);}}
-
public static class SecretKeys
: 定义一个公共静态内部类SecretKeys
,用于封装AES密钥和HMAC密钥。 -
private final SecretKey aesKey;
: 定义私有final成员变量aesKey
,用于存储AES密钥。 -
private final SecretKey hmacKey;
: 定义私有final成员变量hmacKey
,用于存储HMAC密钥。 -
public SecretKeys(SecretKey aesKey, SecretKey hmacKey)
: 定义构造方法,用于初始化aesKey
和hmacKey
。 -
public String getAesKeyBase64()
: 定义方法getAesKeyBase64
,用于获取AES密钥的Base64编码字符串。-
aesKey.getEncoded()
: 获取AES密钥的原始字节数组。 -
Base64.getEncoder().encodeToString(...)
: 将字节数组进行Base64编码。
-
-
public String getHmacKeyBase64()
: 定义方法getHmacKeyBase64
,用于获取HMAC密钥的Base64编码字符串,原理同上。 -
public static SecretKeys fromBase64(String aesKeyBase64, String hmacKeyBase64)
: 定义静态方法fromBase64
,用于从Base64编码的字符串创建SecretKeys
对象。-
Base64.getDecoder().decode(aesKeyBase64)
: 将Base64编码的AES密钥字符串解码为字节数组。 -
new SecretKeySpec(..., encryptionAlgorithm)
: 使用字节数组和算法名称创建SecretKeySpec
对象,作为AES密钥。 -
Base64.getDecoder().decode(hmacKeyBase64)
: 将Base64编码的HMAC密钥字符串解码为字节数组。 -
new SecretKeySpec(..., HMAC_ALGORITHM)
: 使用字节数组和算法名称创建SecretKeySpec
对象,作为HMAC密钥。 -
return new SecretKeys(aesKey, hmacKey)
: 创建并返回SecretKeys
对象。
-
4. generateKeys() 方法
public static SecretKeys generateKeys() throws NoSuchAlgorithmException {KeyGenerator aesKeyGen = KeyGenerator.getInstance(encryptionAlgorithm);aesKeyGen.init(AES_KEY_LENGTH);SecretKey secretKey = aesKeyGen.generateKey();KeyGenerator hmacKeyGen = KeyGenerator.getInstance(HMAC_ALGORITHM);hmacKeyGen.init(HMAC_KEY_LENGTH);SecretKey hmacKey = hmacKeyGen.generateKey();return new SecretKeys(secretKey, hmacKey);}
public static SecretKeys generateKeys() throws NoSuchAlgorithmException
: 定义公共静态方法generateKeys
,用于生成AES密钥和HMAC密钥。
-
KeyGenerator aesKeyGen = KeyGenerator.getInstance(encryptionAlgorithm);
: 创建一个KeyGenerator
对象,用于生成AES密钥。 -
aesKeyGen.init(AES_KEY_LENGTH);
: 初始化KeyGenerator
对象,指定密钥长度为AES_KEY_LENGTH
(256位)。 -
SecretKey secretKey = aesKeyGen.generateKey();
: 生成一个AES密钥。 -
KeyGenerator hmacKeyGen = KeyGenerator.getInstance(HMAC_ALGORITHM);
: 创建一个KeyGenerator
对象,用于生成HMAC密钥。 -
hmacKeyGen.init(HMAC_KEY_LENGTH);
: 初始化KeyGenerator
对象,指定密钥长度为HMAC_KEY_LENGTH
(256位)。 -
SecretKey hmacKey = hmacKeyGen.generateKey();
: 生成一个HMAC密钥。 -
return new SecretKeys(secretKey, hmacKey);
: 创建并返回包含AES密钥和HMAC密钥的SecretKeys
对象。 -
throws NoSuchAlgorithmException
: 抛出NoSuchAlgorithmException
异常,如果指定的算法不可用。
5. encrypt() 方法
public static String encrypt(String plainText, SecretKeys keys) throws Exception {byte[] iv = new byte[IV_LENGTH];SecureRandom random = SecureRandom.getInstanceStrong();random.nextBytes(iv);Cipher cipher = Cipher.getInstance(AES_ALGORITHM);GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.ENCRYPT_MODE, keys.aesKey, gcmSpec);byte[] encryptedText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));Mac hmac = Mac.getInstance(HMAC_ALGORITHM);hmac.init(keys.hmacKey);hmac.update(iv);hmac.update(encryptedText);byte[] hmacDigest = hmac.doFinal();byte[] result = new byte[IV_LENGTH + encryptedText.length + HMACDigest];System.arraycopy(iv, 0, result, 0, IV_LENGTH);System.arraycopy(encryptedText, 0, result, IV_LENGTH, encryptedText.length);System.arraycopy(hmacDigest, 0, result, IV_LENGTH + encryptedText.length, HMACDigest);return Base64.getEncoder().encodeToString(result);}
-
public static String encrypt(String plainText, SecretKeys keys) throws Exception
: 定义公共静态方法encrypt
,用于加密字符串。-
String plainText
: 要加密的明文字符串。 -
SecretKeys keys
: 包含AES密钥和HMAC密钥的SecretKeys
对象。 -
throws Exception
: 抛出可能出现的异常。
-
-
byte[] iv = new byte[IV_LENGTH];
: 创建一个字节数组iv
,用于存储初始化向量(IV)。 -
SecureRandom random = SecureRandom.getInstanceStrong();
: 创建一个SecureRandom
对象,用于生成安全的随机数。 -
random.nextBytes(iv);
: 使用SecureRandom
对象填充iv
字节数组,生成随机的IV。 -
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
: 创建一个Cipher
对象,用于进行AES加密。 -
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
: 创建一个GCMParameterSpec
对象,用于指定GCM参数。 -
cipher.init(Cipher.ENCRYPT_MODE, keys.aesKey, gcmSpec);
: 初始化Cipher
对象,设置为加密模式,使用AES密钥和GCM参数。 -
byte[] encryptedText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
: 对明文字符串进行加密,并将结果存储在encryptedText
字节数组中。 -
Mac hmac = Mac.getInstance(HMAC_ALGORITHM);
: 创建一个Mac
对象,用于计算HMAC。 -
hmac.init(keys.hmacKey);
: 初始化Mac
对象,使用HMAC密钥。 -
hmac.update(iv);
: 使用IV更新HMAC。 -
hmac.update(encryptedText);
: 使用加密后的数据更新HMAC。 -
byte[] hmacDigest = hmac.doFinal();
: 计算HMAC摘要值,并将结果存储在hmacDigest
字节数组中。 -
byte[] result = new byte[IV_LENGTH + encryptedText.length + HMACDigest];
: 创建一个字节数组result
,用于存储最终的加密结果,包括IV、加密数据和HMAC摘要值。 -
System.arraycopy(iv, 0, result, 0, IV_LENGTH);
: 将IV复制到result
字节数组的开头。 -
System.arraycopy(encryptedText, 0, result, IV_LENGTH, encryptedText.length);
: 将加密数据复制到result
字节数组中,紧跟在IV之后。 -
System.arraycopy(hmacDigest, 0, result, IV_LENGTH + encryptedText.length, HMACDigest);
: 将HMAC摘要值复制到result
字节数组中,紧跟在加密数据之后。 -
return Base64.getEncoder().encodeToString(result);
: 将最终的加密结果进行Base64编码,并返回编码后的字符串。
6. encryptKey() 方法
public static String[] encryptKey(SecretKeys keys, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {String aesKey=keys.getAesKeyBase64();String hmacKey=keys.getHmacKeyBase64();Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE,publicKey);byte []encryptAesKey=cipher.doFinal(aesKey.getBytes(StandardCharsets.UTF_8));byte []encryptHmacKey=cipher.doFinal(hmacKey.getBytes(StandardCharsets.UTF_8));return new String[]{Base64.getEncoder().encodeToString(encryptAesKey),Base64.getEncoder().encodeToString(encryptHmacKey)};}
-
public static String[] encryptKey(SecretKeys keys, PublicKey publicKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
: 定义公共静态方法encryptKey
,用于使用RSA公钥加密AES密钥和HMAC密钥。-
SecretKeys keys
: 包含AES密钥和HMAC密钥的SecretKeys
对象。 -
PublicKey publicKey
: 用于加密密钥的RSA公钥。 -
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
: 抛出可能出现的异常。
-
-
String aesKey=keys.getAesKeyBase64();
: 获取AES密钥的Base64编码字符串。 -
String hmacKey=keys.getHmacKeyBase64();
: 获取HMAC密钥的Base64编码字符串。 -
Cipher cipher=Cipher.getInstance(RSA_ALGORITHM);
: 创建一个Cipher
对象,用于进行RSA加密。 -
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
: 初始化Cipher
对象,设置为加密模式,使用RSA公钥。 -
byte []encryptAesKey=cipher.doFinal(aesKey.getBytes(StandardCharsets.UTF_8));
: 使用RSA公钥加密AES密钥,并将结果存储在encryptAesKey
字节数组中。 -
byte []encryptHmacKey=cipher.doFinal(hmacKey.getBytes(StandardCharsets.UTF_8));
: 使用RSA公钥加密HMAC密钥,并将结果存储在encryptHmacKey
字节数组中。 -
return new String[]{Base64.getEncoder().encodeToString(encryptAesKey), Base64.getEncoder().encodeToString(encryptHmacKey)};
: 将加密后的AES密钥和HMAC密钥进行Base64编码,并返回包含这两个编码字符串的字符串数组。
7. decrypt() 方法
public static String decrypt(String cipherText, SecretKeys keys) throws Exception {byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText);if (cipherTextBytes.length < IV_LENGTH + HMACDigest) {throw new IllegalArgumentException("无效的加密数据!");}byte[] iv = new byte[IV_LENGTH];byte[] encryptedData = new byte[cipherTextBytes.length - IV_LENGTH - HMACDigest];byte[] hmacDigest = new byte[HMACDigest];System.arraycopy(cipherTextBytes, 0, iv, 0, IV_LENGTH);System.arraycopy(cipherTextBytes, IV_LENGTH, encryptedData, 0, encryptedData.length);System.arraycopy(cipherTextBytes, IV_LENGTH + HMACDigest, hmacDigest, 0, HMACDigest);Mac hmac = Mac.getInstance(HMAC_ALGORITHM);hmac.init(keys.hmacKey);hmac.update(iv);hmac.update(encryptedData);byte[] calculatedHmacDigest = hmac.doFinal();if(!MessageDigest.isEqual(calculatedHmacDigest, hmacDigest)) {throw new SecurityException("HMAC校验失败,数据可能被篡改!");}Cipher cipher = Cipher.getInstance(AES_ALGORITHM);GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.DECRYPT_MODE, keys.aesKey, gcmSpec);try{byte[] decryptedText = cipher.doFinal(encryptedData);return new String(decryptedText, StandardCharsets.UTF_8);}catch (AEADBadTagException e){throw new SecurityException("GCM 标签校验失败,数据可能被篡改!", e);}}
-
public static String decrypt(String cipherText, SecretKeys keys) throws Exception
: 定义公共静态方法decrypt
,用于解密字符串。-
String cipherText
: 要解密的密文字符串。 -
SecretKeys keys
: 包含AES密钥和HMAC密钥的SecretKeys
对象。 -
throws Exception
: 抛出可能出现的异常。
-
-
byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText);
: 将Base64编码的密文字符串解码为字节数组。 -
if (cipherTextBytes.length < IV_LENGTH + HMACDigest)
: 检查密文的长度是否足够,如果小于IV长度+HMAC长度,则抛出异常。 -
byte[] iv = new byte[IV_LENGTH];
: 创建一个字节数组iv
,用于存储初始化向量(Initialization Vector)。 -
byte[] encryptedData = new byte[cipherTextBytes.length - IV_LENGTH - HMACDigest];
: 创建一个字节数组encryptedData
,用于存储加密的数据部分。其长度等于总密文长度减去IV长度和HMAC长度。 -
byte[] hmacDigest = new byte[HMACDigest];
: 创建一个字节数组hmacDigest
,用于存储HMAC(Hash-based Message Authentication Code)摘要。 -
System.arraycopy(cipherTextBytes, 0, iv, 0, IV_LENGTH);
: 从密文字节数组中提取IV,复制到iv
数组中。 -
System.arraycopy(cipherTextBytes, IV_LENGTH, encryptedData, 0, encryptedData.length);
: 从密文字节数组中提取加密数据,复制到encryptedData
数组中。 -
System.arraycopy(cipherTextBytes, IV_LENGTH + encryptedData.length, hmacDigest, 0, HMACDigest);
: 从密文字节数组中提取HMAC摘要,复制到hmacDigest
数组中。 -
Mac hmac = Mac.getInstance(HMAC_ALGORITHM);
: 创建一个Mac
对象,用于计算HMAC,使用的算法是之前定义的HMAC_ALGORITHM
(HmacSHA256)。 -
hmac.init(keys.hmacKey);
: 使用存储在keys
对象中的 HMAC 密钥初始化Mac
对象。 -
hmac.update(iv);
: 使用IV更新HMAC。 -
hmac.update(encryptedData);
: 使用加密后的数据更新HMAC。 -
byte[] calculatedHmacDigest = hmac.doFinal();
: 计算HMAC摘要值,并将结果存储在calculatedHmacDigest
字节数组中。 -
if(!MessageDigest.isEqual(calculatedHmacDigest, hmacDigest))
: 验证计算出的 HMAC 摘要是否与提供的摘要匹配。 -
throw new SecurityException("HMAC校验失败,数据可能被篡改!");
: 如果HMAC校验失败,抛出异常。 -
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
: 创建一个Cipher
对象,用于进行AES解密。 -
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
: 创建一个GCMParameterSpec
对象,用于指定GCM参数。 -
cipher.init(Cipher.DECRYPT_MODE, keys.aesKey, gcmSpec);
: 初始化Cipher
对象,设置为解密模式,使用AES密钥和GCM参数。 -
byte[] decryptedText = cipher.doFinal(encryptedData);
: 对密文字符串进行解密,并将结果存储在decryptedText
字节数组中。 -
return new String(decryptedText, StandardCharsets.UTF_8);
: 将解密后的字节数组转换为字符串,并返回。 -
catch (AEADBadTagException e)
: 捕获AEADBadTagException
异常,这通常发生在 GCM 模式下认证标签验证失败时,意味着数据可能已被篡改。 -
throw new SecurityException("GCM 标签校验失败,数据可能被篡改!", e);
: 重新抛出一个SecurityException
异常,以表明 GCM 标签校验失败,数据可能已被篡改。原始的AEADBadTagException
异常作为原因(cause)被包含在新异常中,有助于调试。
8. decryptKey() 方法
public static SecretKeys decryptKey(String []cipherText,PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedAesBytes = cipher.doFinal(Base64.getDecoder().decode(cipherText[0]));String aesKeyBase64=new String(decryptedAesBytes, StandardCharsets.UTF_8);byte[] decryptedHmacBytes =cipher.doFinal(Base64.getDecoder().decode(cipherText[1]));String hmacKeyBase64=new String(decryptedHmacBytes, StandardCharsets.UTF_8);return SecretKeys.fromBase64(aesKeyBase64,hmacKeyBase64);}
-
public static SecretKeys decryptKey(String []cipherText,PrivateKey privateKey) throws Exception
: 定义公共静态方法decryptKey
,用于使用RSA私钥解密AES密钥和HMAC密钥。-
String []cipherText
: 包含加密后的AES密钥和HMAC密钥的字符串数组。 -
PrivateKey privateKey
: 用于解密密钥的RSA私钥。
-
-
throws Exception
: 抛出可能出现的异常。 -
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
: 创建一个Cipher
对象,用于进行RSA解密。 -
cipher.init(Cipher.DECRYPT_MODE, privateKey);
: 初始化Cipher
对象,设置为解密模式,使用RSA私钥。 -
byte[] decryptedAesBytes = cipher.doFinal(Base64.getDecoder().decode(cipherText[0]));
: 使用RSA私钥解密AES密钥,并将结果存储在decryptedAesBytes
字节数组中。 -
String aesKeyBase64=new String(decryptedAesBytes, StandardCharsets.UTF_8);
: 将解密后的AES密钥字节数组转换为字符串。 -
byte[] decryptedHmacBytes =cipher.doFinal(Base64.getDecoder().decode(cipherText[1]));
: 使用RSA私钥解密HMAC密钥,并将结果存储在decryptedHmacBytes
字节数组中。 -
String hmacKeyBase64=new String(decryptedHmacBytes, StandardCharsets.UTF_8);
: 将解密后的HMAC密钥字节数组转换为字符串。 -
return SecretKeys.fromBase64(aesKeyBase64,hmacKeyBase64);
: 调用SecretKeys.fromBase64()
方法,将Base64编码的AES密钥和HMAC密钥转换为SecretKeys
对象,并返回。
9. restorePublicKey() 方法
public static PublicKey restorePublicKey(String data){byte[] publicKeyBytes= Base64.getDecoder().decode(data);X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyBytes);try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(keySpec);} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {throw new RuntimeException(e);}}
-
public static PublicKey restorePublicKey(String data)
: 定义公共静态方法restorePublicKey
,用于从Base64编码的字符串恢复公钥。-
String data
: Base64编码的公钥字符串。
-
-
byte[] publicKeyBytes= Base64.getDecoder().decode(data);
: 将Base64编码的公钥字符串解码为字节数组。 -
X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyBytes);
: 创建一个X509EncodedKeySpec
对象,用于表示X.509编码的公钥。 -
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
: 创建一个KeyFactory
对象,用于生成公钥。 -
return keyFactory.generatePublic(keySpec);
: 使用KeyFactory
对象和X509EncodedKeySpec
对象生成公钥,并返回。 -
catch (NoSuchAlgorithmException | InvalidKeySpecException e)
: 捕获NoSuchAlgorithmException
和InvalidKeySpecException
异常。 -
throw new RuntimeException(e);
: 如果在恢复公钥的过程中出现任何异常,则会创建一个RuntimeException
异常,并将捕获到的原始异常(e
)作为原因(cause)传递给新的RuntimeException
异常。然后,新的RuntimeException
异常会被抛出。
GenerateRSAKeyPairs
类
1. 导入
import java.security.*;
import java.util.Base64;
-
package com.backEndProject.encrypt;
: 声明该类属于com.backEndProject.encrypt
包,用于组织和管理Java类。 -
import java.security.*;
: 导入java.security
包下的所有类,该包提供安全相关的类和接口,例如KeyPairGenerator
、PublicKey
、PrivateKey
等。 -
import java.util.Base64;
: 导入Base64
类,用于进行Base64编码。
2. 类定义和成员变量
public class GenerateRSAKeyPairs{private static PrivateKey privateKey;public static PublicKey publicKey;
-
public class GenerateRSAKeyPairs
: 定义一个公共类GenerateRSAKeyPairs
,该类用于生成RSA密钥对。 -
private static PrivateKey privateKey;
: 定义一个私有静态成员变量privateKey
,用于存储生成的私钥。 使用static,所有此类的示例都共享这个私钥。 -
public static PublicKey publicKey;
: 定义一个公共静态成员变量publicKey
,用于存储生成的公钥。 使用static,所有此类的示例都共享这个公钥。
3. getter方法
public PrivateKey getPrivateKey() {return privateKey;}public String getPublicKeyBase64(){return Base64.getEncoder().encodeToString(publicKey.getEncoded());}
-
public PrivateKey getPrivateKey()
: 定义一个公共方法getPrivateKey
,用于获取私钥。-
return privateKey;
: 返回私钥。
-
-
public String getPublicKeyBase64()
: 定义一个公共方法getPublicKeyBase64
,用于获取公钥的Base64编码字符串。-
publicKey.getEncoded()
: 获取公钥的原始字节数组。 -
Base64.getEncoder().encodeToString(...)
: 将字节数组进行Base64编码。 -
return ...
: 返回Base64编码后的公钥字符串。
-
4. 构造方法
public GenerateRSAKeyPairs () throws NoSuchAlgorithmException {KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair keyPair=keyGen.generateKeyPair();privateKey=keyPair.getPrivate();publicKey=keyPair.getPublic();}
-
public GenerateRSAKeyPairs () throws NoSuchAlgorithmException
: 定义构造方法,用于生成RSA密钥对。-
throws NoSuchAlgorithmException
: 抛出NoSuchAlgorithmException
异常,如果指定的算法不可用。
-
-
KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
: 创建一个KeyPairGenerator
对象,用于生成RSA密钥对。 -
keyGen.initialize(2048);
: 初始化KeyPairGenerator
对象,指定密钥长度为2048位。 -
KeyPair keyPair=keyGen.generateKeyPair();
: 生成一个RSA密钥对。 -
privateKey=keyPair.getPrivate();
: 从密钥对中获取私钥,并赋值给成员变量privateKey
。 -
publicKey=keyPair.getPublic();
: 从密钥对中获取公钥,并赋值给成员变量publicKey
。
相关文章:
发送加密信息的简单实现【Java】
(修改期) 一、代码的引用处 public static SecretKeys generateKeys() throws NoSuchAlgorithmException {: 定义一个公共静态方法,用于生成 AES 和 HMAC 密钥对。 public static String encrypt(String plaintext, SecretKey aesKey, S…...
阿里云域名解析
一、打开域名控制台 PC端浏览器打开阿里云域名控制台:域名控制台,点击"域名解析"。 二、添加解析设置 选择需要解析的域名,点击"解析设置"。 点击"添加记录"。 添加@和www即可。...
DNS域名解析服务(正向 反向 主从)
DNS 1.分散式管理: Hosts文件 一改百度就不会访问了 Ip地址 域名 121.226.246.3 www.jd.com 2.我们会搭建一台 域名解析服务器全世界得域名全靠这台服务器进行解析 中央集权制 域名是由多个部分组成的 www.baidu.com .baidu .com是域…...
ROS2---std_msgs基础消息包
std_msgs 是ROS 2(Robot Operating System 2)里的基础消息包,它定义了一系列简单却常用的消息类型,为不同节点间的通信提供了基础的数据格式。 1. 消息包概述 std_msgs 包包含了多种基础消息类型,这些类型用于表示常…...
python基础:数据类型转换、运算符(算术运算符、比较运算符、逻辑运算符、三元运算符、位运算符)
目录 一、类型转换 隐式类型转换/自动转换: 显示类型转换/强制转换: 二、运算符 算数运算符: - * / 比较运算符 逻辑/布尔运算符 赋值运算符: 三元运算符 位运算符 [二进制] 运算符优先级 一、类型转换 python变量的类…...
[特殊字符] 终端效率提升指南:zsh + tmux
在日常开发中,一个舒适、高效的终端环境能显著提升工作效率。本文将介绍如何通过配置 oh-my-zsh 和 tmux 打造一个功能强大、便捷实用的终端工具集。无论你是 Linux 新手,还是资深开发者,都能从中获得实用的提升技巧。 🌀 一、终…...
【Linux篇】深入理解文件系统:从基础概念到 ext2 文件系统的应用与解析
文件系统的魔法:让计算机理解并存储你的数据 一. 文件系统1.1 块1.2 分区1.3 inode(索引节点) 二. ext2文件系统2.1 认识文件系统2.2 Block Group (块组)2.2.1 Block Group 的基本概念2.2.2 Block Group 的作用 2.3 块组内部结构2.3.1 超级块(Super Bloc…...
MarkDown 输出表格的方法
MarkDown用来输出表格很简单,比Word手搓表格简单多了,而且方便修改。 MarkDown代码: |A|B|C|D| |:-|-:|:-:|-| |1|b|c|d| |2|b|c|d| |3|b|c|d| |4|b|c|d| |5|b|c|d|显示效果: ABCD1bcd2bcd3bcd4bcd5bcd A列强制左对齐…...
DOM解析XML:Java程序员的“乐高积木式“数据搭建
各位代码建筑师们!今天我们要玩一个把XML变成内存乐高城堡的游戏——DOM解析!和SAX那种"边看监控边破案"的刺激不同,DOM就像把整个乐高说明书一次性倒进大脑,然后慢慢拼装(内存:你不要过来啊&…...
Python 数组里找出子超集
碰见一个问题,有一个大数组,如下所示: xx [[1, 3, 4], [3, 4, 5], [1, 2, 3, 4, 5], [6], [7, 8], [6, 7, 8]]大数组里面有好多小的数组,观察发现,小的数组其实有挺多别的小数组的子集,现在问题来了&…...
上层 Makefile 控制下层 Makefile ---- 第二部分(补充一些例子与细节)
1. 递归调用子目录 Makefile 通过 $(MAKE) -C 进入子目录并执行其 Makefile,这是最常见的分层构建方法。 示例:基本递归调用 目录结构: project/ ├── Makefile # 顶层 Makefile ├── lib/ │ ├── Makefile # 子目录…...
LeetCode算法题(Go语言实现)_44
题目 有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。 省份是一组直接或间接相连的城市,组内不含其他没有相连的城市。 给你…...
STM32 HAL库之USART示例代码
串口发送和接收以及回调函数都可在这个文件中查询:stm32f1xx_hal_uart.h 串口配置初始化代码main.c中:MX_USART1_UART_Init();,初始化 UART 高层参数(波特率、数据位、停止位、校验、模式等) void MX_USART1_UART_In…...
头歌educoder——数据库 第10-11章
第10章 1、 事务的( )特性要求事务必须被视为一个不可分割的最小工作单元 A、 原子性 B、 一致性 C、 隔离性 D、 持久性 2、 事务的( )特性要求一个事务在执行时,不会受到其他事务的影响。 A、 原子性 B、 一致性 C…...
从 Vue 到 React:深入理解 useState 的异步更新与函数式写法
目录 从 Vue 到 React:深入理解 useState 的异步更新与函数式写法1. Vue 的响应式回顾:每次赋值立即生效2. React 的状态更新是异步且批量的原因解析 3. 函数式更新:唯一的正确写法4. 对比 Vue vs React 状态更新5. React useState 的核心源码…...
如何实现元素随滚动平滑上升
#技术栈Vue3TypeScript# 相比大家没少见过这个的效果: 作为视觉效果是很不错的 同时实现也很简单,本质是封装一个Vue指令 1,创建指令文件 src / directives / vSlidenIn.ts import type { Directive } from vueconst vSlideIn: Directive …...
Nginx部署spa单页面的小bug
没部署过,都是给后端干的,自己尝试部署了一个下午终于成功了 我遇到的最大的bug是进入后只有首页正常显示 其他页面全是404,于是问问问才知道,需要这个 location / { try_files $uri $uri/ /index.html; } 让…...
关于全球化大规模混合云 Kubernetes Prometheus 监控体系标准化及 GitOps 自动化改进方案
背景 现状 某司概况: PaaS/SaaS 公司,业务面向全球,包括 东南亚/南亚/中东/欧洲/非洲/美洲/东亚…生产 k8s 集群数十套,生产非生产 >100 套(多种集群类型,各种公有云/专有云/私有云/数据中心…)疫情以来ÿ…...
力扣DAY51 | 热100 | 岛屿数量
前言 中等 √ 做得我元气大伤,超级naive方法,新开辟一个数组存岛屿编号,一个数组存岛屿上的点。 题目 给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。 …...
二叉树的最近公共祖先二叉搜索树的最近公共祖先
1 二叉树的最近公共祖先 学习: 代码 class Solution:def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:if root is None or root is p or root is q:return rootleft self.lowestCommonAncestor(root.left,p,q)right …...
关于 LLB 的问题
This error occurs when you’re trying to run a program or library that was compiled with GLIBC (GNU C Library) version 2.29, but your system has an older version of GLIBC installed. Solutions: 1. Upgrade your system’s GLIBC (Recommended if possible) Fo…...
kafka4.0浅尝辄止
最近工作中接触消息队列比较多,前几周又看到kafka4.0发布,故写一篇博客对消息队列做一个复盘。 目录 消息队列对比1. Apache Kafka 4.02. RabbitMQ3. RocketMQ4. ActiveMQ5. Apache Pulsar6. NSQ kafka4.0鲜明的新特性Java 版本要求升级API 更新与精简移…...
nmcli创建wpa-psk2 wifi热点
1. 创建新的WiFi连接: sudo nmcli connection add type wifi ifname wlan0 con-name WiFi名称 autoconnect yes ssid WiFi名称 2. 配置接入点模式和IP共享: sudo nmcli connection modify WiFi名称 802-11-wireless.mode ap 802-11-wireless.band …...
分布式日志治理:Log4j2自定义Appender写日志到RocketMQ
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
【STM32单片机】#8 定时器编码器接口ADC模数转换器
主要参考学习资料: B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…...
dify部署,ollama部署,拉取模型,创建ai聊天应用
dify下载安装 dify1.0.1 windos安装包百度云盘地址 通过网盘分享的文件:dify-1.0.1.zip 链接: 百度网盘 请输入提取码 提取码: 1234 dify安装包 linux安装包百度云盘地址 通过网盘分享的文件:dify-1.0.1.tar.gz 链接: 百度网盘 请输入提取码 提取码…...
213、【图论】有向图的完全联通(Python)
题目描述 原题链接:105. 有向图的完全联通 代码实现 import collectionsn, k list(map(int, input().split())) adjacency collections.defaultdict(list) for _ in range(k):head, tail list(map(int, input().split()))adjacency[head].append(tail)visited_…...
Node.js中util模块详解
Node.js 中 util 模块全部 API 详解 一、类型检查函数 const util require(util);// 1. util.types // 检查对象类型 console.log(util.types.isDate(new Date())); // true console.log(util.types.isRegExp(/abc/)); // true console.log(util.types.isArrayBuffer(new …...
BasicTS:全面基准测试与异质性分析
BasicTS:全面基准测试与异质性分析 在当今数字化时代,多元时间序列(Multivariate Time Series, MTS)分析在众多领域发挥着关键作用,从交通管理到能源系统优化,都离不开对MTS的精准预测。然而,当…...
认识python全栈框架reflex:快速打造工具类网站、模型调用web应用
以下是对reflex的简单介绍: 纯Python编写的,高性能、可自定义的 Web 应用开发框架 网页开发内置组件生态完整,灵活使用、快速接入、快速部署支持路由页面,可以开发复杂系统、企业级系统,这方面优于gradio、streamlit…...
课题申报的立项依据方位指南:使用DeepSeek提高课题立项的关键
在竞争日益激烈的学术研究和科研项目申报环境中,立项依据作为课题申报书的灵魂部分,往往决定着一项研究能否获得评审专家的青睐和资助。 然而,许多研究者尽管学术能力突出,却在立项依据的撰写上显得力不从心,导致优质…...
蓝桥杯电子赛_E2PROM(AT24C02)
目录 一 前言 二 E2PROM的相关讲解 AT24C02的地址 PCF8591的地址 三 根据提供的iic写代码 相关可能会有疑问的地方: 1 三个入口参数,都有什么用? 2 为什么在写中,要用IIC_SendByte,在读中,要用IIC_R…...
Kubernetes服务注册到consul流程实践
文章目录 前言架构图示意一、环境准备二、consul部署1.yaml示例2.consul部署验证 三、consulctl工具实现1.核心功能2.注册到consul的标签及元数据3.consulctl工具使用示例 四、通过Dockerfile构建consulctl工具镜像五、Kubernetes集成方案六、 结果验证1.注册验证2.销毁验证 总…...
供应链业务-供应链全局观(三)- 供应链三流的集成
概述 供应链的全局观的全两篇文章主要描述了供应链的基础概念和供应链的协作和集成问题。 供应链业务-供应链全局观(一)定义了什么是供应链和供应链管理。 所谓供应链就是把采购进来的东西,通过自身的生成加工,进行增值服务&am…...
Docker 提示Docker Engine stopped
做AI开发的时候,安装Docker提示Docker Engine stopped,以下是解决步骤: 一般都是成功的,不成功很可能是电脑兼容问题,通过采用4.4.4版本解决的: docker desktop 4.4.4 旧版本下载:在这里找到了4…...
对自己的优缺点评价
在面试中回答优缺点时,需要既体现自我认知的客观性,又能将优缺点与岗位需求结合,避免暴露可能影响工作的硬伤。以下是一个符合Java开发者角色的回答框架,供参考: 回答思路: 优点:选择与岗位直接…...
解决eNSP在24H2版本下AR_40启动失败问题
前言 1.网络学习中缺少不了模拟,自从Windows版本更新24H2以后,eNSP就出现各种问题,最常见的就是AR报错40【启动失败】,之前我也去网站搜了,也问了Microsoft社区,发现他们在底层逻辑上进行了修改(开启了虚拟…...
计算机组成原理-指令系统
1. 指令系统的定义与作用 指令系统(Instruction Set Architecture, ISA)是计算机硬件与软件之间的接口规范,定义了CPU能够识别和执行的所有指令的集合,是计算机体系结构的核心组成部分。 核心作用: 为程序员提供操作…...
Oracle数据库中 LEVEL start with prior connect by
在Oracle数据库中,处理层次结构数据是一项常见且重要的任务。无论是组织结构、分类目录还是其他具有层级关系的数据,Oracle都提供了强大的工具来简化和优化这些操作。其中,LEVEL伪列结合CONNECT BY和START WITH关键字,成为了处理层…...
HTTP 1.1 比 HTTP1.0 多了什么?(详尽版)
相较于HTTP 1.0,1.1 版本增加了以上特性: 1. 新增了连接管理即 keepalive,允许持久连接。 定义: Keepalive允许客户端和服务器在完成一次请求-响应后,保持连接处于打开状态,以便后续请求复用同一连接&am…...
Java学习手册:Java I/O与NIO
Java I/O(Input/Output)和NIO(New Input/Output)是Java语言中用于处理输入输出操作的重要部分。它们提供了丰富的API来处理文件和网络通信。I/O是Java早期版本中引入的,而NIO是在Java 1.4中引入的,旨在提供…...
linux下的目录文件管理和基本文件管理的基本操作
目录 1.目录创建,文件创建和文件编辑的案例 2.文件编辑进阶 --vim 3. 命令的别名 4. 查看文件内容和文件编辑(重定向)的案例 5. 重定向之追加 6. 查看目录和文件编辑的案例 7. 查看目录和文件编辑(覆盖)的案例 为了加深对linux命令的熟悉程度,这…...
magnet库Hello,world!
1.c文件 #include<iostream> #include"Control.hpp" class O1:public mag::Control{bool b; public:O1(){b1;}bool decide(){return b&&islifing();}void action(){std::cout<<"Hello,world!\n";b0;destroy();} }; int main(){O1 o1;…...
应急响应靶机-Linux(1)
挑战内容 账户密码:defend/defend Root/defend 黑客的IP地址遗留下的三个flag 1、按正常思路来走,先登录一手因已经给出root账户密码,先查看一手执行过的命令,发现一个flag值并且看到他往期编辑了一个文件,咱们顺便进去…...
k8s 部署spring项目+动态启动pod
在 Kubernetes 中部署 Spring Boot 项目并实现 动态管理 Pod(自动扩缩容、滚动更新等),需要结合 Docker 镜像构建、Deployment 配置、Service 暴露和 HPA(Horizontal Pod Autoscaler) 等组件。以下是完整操作步骤&…...
【DINO】
detr 简化了检测流水线,消除了许多手工设置的组件 单阶段目标检测 需要前置的backbone抽取特征 faster_rcnn和yolo都是基于anchor,anchor当作候选框,NMS非极大值抑制 重叠的框只保存一个,效率低 所以detr来了,transformer,既有encoder又有decoder,套一个transforme…...
Nature重磅:后晶体管时代光子芯片革新AI计算!光子处理器运行《吃豆人》性能比肩电子,能效提升超500倍
随着人工智能(AI)模型规模以及应用范围的不断拓展,性能上限和能耗瓶颈正逐渐显现出来。大语言模型(LLM)、强化学习和卷积神经网络等 AI 模型的复杂性不断增长,正在将传统电子计算推向极限,能源需…...
Excel表格文件分组归并——通过sql
将 Excel 表转换为 SQL 数据库并直接执行 SQL 查询以获得所需的输出。以下是使用 SQL 实现此目的的步骤: 第 1 步:将 Excel 数据导入 MySQL 假设您设置了 MySQL 数据库,则需要先将 Excel 数据导入到表中。您可以使用语句或工具(…...
2.微服务拆分流程
文章目录 交易服务1.1.创建项目1.2.引入依赖1.3.创建交易服务启动类1.4.创建并编写配置文件1.5.代码连接池4.2.1.引入依赖4.2.2.开启连接池抽取Feign客户端 1.6.抽取ItemClient接口1.7.抽取CartClient接口改造OrderServiceImpl扫描包 1.8.数据库1.9.配置启动项1.10.测试 以拆分…...
vue入门:计算属性computer监听器watch
文章目录 计算属性computer定义计算属性在模板中使用计算属性计算属性的使用场景 监听器watch基本语法深度监听立即执行监听数组异步操作数据校验副作用处理清理监听器 watch 与 computed 的区别 计算属性computer 在 Vue 中,计算属性(computed…...