【发布时间】:2021-01-09 22:26:43
【问题描述】:
我正在使用 Java 使用 Triple DES 加密文本有效负载。首先,我创建一个用于加密有效负载的临时密钥:
private byte[] createEphemeralKey() throws Exception {
KeyGenerator keygen = KeyGenerator.getInstance("DESede");
keygen.init(168);
return keygen.generateKey().getEncoded();
}
然后我用所述密钥加密我的有效载荷:
private String encryptTripleDES(byte[] ephemeralKey, String payload) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(ephemeralKey, "DESede"));
byte[] plainTextBytes = payload.getBytes();
byte[] cipherText = cipher.doFinal(plainTextBytes);
return Base64.getEncoder().encodeToString(cipherText);
}
还需要一个填充函数来保证数据长度可以被8整除:
private String adjustPadding(String input, int blockSize) {
int len = input.length() % blockSize;
int paddingLength = (len == 0) ? 0 : (blockSize - len);
while (paddingLength > 0) {
input += "F";
paddingLength--;
}
return input;
}
这是我的端到端流程:
String data = "Marnus"
byte[] = ephemeralKey = createEphemeralKey();
String adjustedData = adjustPadding (data,8);
String encryptedPayload = encryptTripleDES(ephemeralKey, adjustedData);
String encodedKey = Base64.getEncoder().encodeToString(ephemeralKey)
所以我采用两个变量encryptedPayload 和encodedKey,它们都是Base64 编码的字符串,并通过HTTP 将其发送到node express 应用程序。
在 Javascript 方面,我使用 node-forge - 这是我的 express 应用程序中执行解密的部分:
let nodeBuffer = Buffer.from(data, 'base64')
let input = forge.util.createBuffer(nodeBuffer.toString('binary'))
// 3DES key and IV sizes
let keySize = 24;
let ivSize = 8;
let derivedBytes = forge.pbe.opensslDeriveBytes(ephemeralKey, null, keySize + ivSize);
let buffer = forge.util.createBuffer(derivedBytes);
let key = buffer.getBytes(keySize)
let iv = buffer.getBytes(ivSize)
let decipher = forge.cipher.createDecipher('3DES-ECB', key)
decipher.start({iv: iv})
decipher.update(input)
console.log('decipher result', decipher.finish())
let decryptedResult = decipher.output.data;
这是 node-forge 文档中的 Triples DES 示例:
几点说明: 我从常规缓冲区创建了一个节点伪造缓冲区,因为我没有示例给出的输入文件。以下是文档说明应该从另一个缓冲区创建一个缓冲区的方式:
*我使用base64,因为这是我在java端用来编码发送的数据。
然后,我没有盐,所以我将第二个参数 null 留在了我应该做的文档中指定的 opensslDeriveBytes 中。
第三,我也不确定我的 keysize 24 是否正确?
我的结果
因此,进行端到端测试会产生以下结果:
在我的 Java 应用中,测试数据是 "Marnus",encryptedPayload 是 ez+RweSAd+4=,encodedKey 是 vCD9mBnWHPEBiQ0BGv7gc6GUCOoBgLCu。
然后在我的 javascript 代码中 data 显然是 ez+RweSAd+4=(encryptedPayload) 而 ephemeralKey 是 vCD9mBnWHPEBiQ0BGv7gc6GUCOoBgLCu(encodedKey)。
解密运行后,decryptedResult的值为©ýÕ?µ{',这显然是垃圾,因为它还没有编码,但我不知道使用哪种编码?
我尝试使用forge.util.encode64(decipher.output.data),但这只是给了我qf3VP7UYeyc=,这是不对的。
对于它的价值,here is the type 那个decipher.output
【问题讨论】:
-
快速回复:在 Java 端没有 DeriveBytes 函数 - 只有一个字节数组直接取自 generateKey 函数。典型的 DES 密钥长度为 8 个字节,因此三重 DES 的长度为 3 * 8 = 24 个字节。
-
java 代码由于一些错误无法编译。此外,您的测试数据似乎不一致:您没有使用任何填充 (
NoPadding)。那么明文的长度应该是块大小的整数倍(3DES 为 8 字节)。但是明文Marnus只有6个字节长。这会导致运行时错误。此外,编码时没有定义字符集 (getBytes(???))。请为定义的起点解决这些问题。谢谢。 -
我更新了帖子,我的错,忘记了填充功能。另外,发布并回答作为我的问题的解决方案:)
标签: javascript java node.js encryption tripledes