
在node.js环境中,crypto模块提供了丰富的加密功能。原始代码片段旨在实现aes-256-cbc模式的解密过程。
let encKey = "0Z8ZUcy1Qh8lnt199MTwTPEe2g1E2tE3";
encKey = crypto.createHash('sha256').update(encKey).digest('bin').slice(0, 32);
let char = String.fromCharCode(0x0);
let iv = char + char + char + char + char + char + char + char + char + char + char + char + char + char + char + char;
let decryptor = crypto.createDecipheriv("aes-256-cbc", encKey, iv);
let dec = decryptor.update(someAuthString, 'base64', 'utf8') + decryptor.final('utf8');
dec = removePKCS5Padding(dec); // 自定义移除填充函数
// removePKCS5Padding 函数
function removePKCS5Padding(text) {
let pad = ord(text[text.length - 1]);
pad = text.substr(0, -1 * pad)
if (_.isEmpty(pad)) {
return text;
} else {
return pad;
}
}这段代码的核心逻辑包括:
然而,原始Node.js代码中存在两个值得注意的问题:
在Java中,我们可以使用javax.crypto包来实现相同的加密解密逻辑,同时避免Node.js代码中的冗余操作。
Java中通过java.security.MessageDigest类实现SHA-256哈希。
立即学习“Java免费学习笔记(深入)”;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
// 原始密钥字符串
String originalKey = "0Z8ZUcy1Qh8lnt199MTwTPEe2g1E2tE3";
// 将字符串转换为字节数组,注意编码一致性
byte[] keyBytes = originalKey.getBytes(StandardCharsets.US_ASCII); // 或 StandardCharsets.UTF_8,取决于Node.js实际使用的编码
// 获取SHA-256实例并计算哈希
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] derivedKey = sha256.doFinal(keyBytes);
// derivedKey 现在就是32字节的AES密钥注意事项:
Node.js代码中使用了16个零字节作为IV。在Java中,这可以通过简单地创建byte数组并让其自动初始化为零来实现。
byte[] ivBytes = new byte[16]; // Java会自动将byte数组元素初始化为0 // 或者明确填充零: // Arrays.fill(ivBytes, (byte) 0);
Java的javax.crypto.Cipher类是实现加密解密的核心。我们需要指定算法、模式和填充方式。
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
// 创建SecretKeySpec对象,用于AES密钥
SecretKeySpec secretKeySpec = new SecretKeySpec(derivedKey, "AES");
// 创建IvParameterSpec对象,用于IV
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
// 获取Cipher实例,指定"算法/模式/填充"
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 初始化Cipher为解密模式
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);注意事项:
解密过程包括将Base64编码的密文解码为字节数组,然后通过Cipher对象进行解密,最后将解密后的字节数组转换为字符串。
import java.util.Base64; // 假设 someAuthString 是Base64编码的密文字符串 String someAuthString = "your_base64_encoded_ciphertext_here"; // 将Base64编码的密文解码为字节数组 byte[] encryptedBytes = Base64.getDecoder().decode(someAuthString); // 执行解密操作 byte[] decryptedBytes = cipher.doFinal(encryptedBytes); // 将解密后的字节数组转换为字符串,注意编码一致性 String clearText = new String(decryptedBytes, StandardCharsets.UTF_8);
注意事项:
下面是一个将上述步骤整合在一起的完整Java示例代码:
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Arrays; // For explicit IV fill, though not strictly necessary
public class AesDecryptionService {
public static String decrypt(String originalKeyString, String base64Ciphertext) throws Exception {
// 1. 密钥派生:SHA-256哈希
byte[] keyBytes = originalKeyString.getBytes(StandardCharsets.US_ASCII); // 根据Node.js实际编码调整
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] derivedKey = sha256.doFinal(keyBytes);
// 2. 初始化向量(IV)的构建 (16字节全零IV)
byte[] ivBytes = new byte[16];
// Java会自动初始化为零,如果需要明确,可以使用Arrays.fill
// Arrays.fill(ivBytes, (byte) 0);
// 3. Cipher对象的初始化
SecretKeySpec secretKeySpec = new SecretKeySpec(derivedKey, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
// 4. 解密操作的执行
byte[] encryptedBytes = Base64.getDecoder().decode(base64Ciphertext);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
// 将解密后的字节数组转换为字符串
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
public static void main(String[] args) {
String nodeJsEncKey = "0Z8ZUcy1Qh8lnt199MTwTPEe2g1E2tE3";
// 假设这是Node.js加密后输出的Base64编码密文
String someAuthString = "YOUR_BASE64_ENCODED_CIPHERTEXT_HERE";
// 替换为实际的密文,例如:
// String someAuthString = "f+z+v... (实际的Base64密文)";
try {
String decryptedText = decrypt(nodeJsEncKey, someAuthString);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
System.err.println("Decryption failed: " + e.getMessage());
e.printStackTrace();
}
}
}将Node.js crypto模块的AES-256-CBC加解密逻辑迁移到Java是可行的,关键在于理解两种语言中加密API的工作原理,并纠正原始代码中可能存在的冗余或不规范操作。通过利用Java标准库的强大功能,我们可以实现一个安全、高效且符合行业标准的加密解密方案。在实际应用中,务必关注密钥和IV的管理,并遵循最佳安全实践。
以上就是从Node.js到Java:实现AES-256-CBC加解密的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号