【问题标题】:TripleDES Java Encryprion to Javascript DecryptionTripleDES Java 加密到 Javascript 解密
【发布时间】: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)

所以我采用两个变量encryptedPayloadencodedKey,它们都是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"encryptedPayloadez+RweSAd+4=encodedKeyvCD9mBnWHPEBiQ0BGv7gc6GUCOoBgLCu

然后在我的 javascript 代码中 data 显然是 ez+RweSAd+4=(encryptedPayload) 而 ephemeralKeyvCD9mBnWHPEBiQ0BGv7gc6GUCOoBgLCu(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


【解决方案1】:

通过更多的调整和测试不同的选项,我得到了它的工作 - 好消息是我设法使用 nodejs (v12.18.4) 中内置的 crypto 库来完成所有工作。

首先,JAVA 端只需要更改密钥大小(从 168 到 112),其余部分保持不变 - 参见下面的示例作为一个单一方法(为了可测试性,当然应该在最终实现中拆分和可用性):

//Some data:
String payload = "{\"data\":\"somedata\"}";

// Create Key
KeyGenerator keygen = KeyGenerator.getInstance("DESede");
keygen.init(112);
byte[] ephemeralKey = keygen.generateKey().getEncoded();

// Adjust the data, see adjustPadding method in the question for details.
String data = adjustPadding (payload,8);
// Wil now be "{"data":"somedata"}FFFFF", can just chop off extra in JS if need be. When sending JSON one knows the end of the object will always be "}"

// Do Encrypt
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(ephemeralKey, "DESede"));

byte[] plainTextBytes = data.getBytes();
byte[] cipherText = cipher.doFinal(plainTextBytes);
String encryptedPayload = Base64.getEncoder().encodeToString(cipherText);

//Lastly, Base64 the key so you can transport it too
String encodedKey = Base64.getEncoder().encodeToString(ephemeralKey)

在 Javascript 方面,我们保持简单:

// I'm using TS, so change the import if you do plain JS
import crypto = require('crypto')

//need bytes from the base64 payload
let buff = Buffer.from(ephemeralKey, 'base64')

const decipher = crypto.createDecipheriv('des-ede3', buff, null)
decipher.setAutoPadding(false)
let decrypted = decipher.update(data, 'base64', 'utf8')
decrypted += decipher.final('utf8')

console.log(decrypted)
//{"data":"somedata"}FFFFF"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多