有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

将Java Encrypion三倍化为Javascript解密

我正在使用Java对文本负载进行三重加密。首先,我创建一个临时密钥,用于加密有效负载:

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 docs中的一个Triples DES示例: enter image description here

一些注释: 我从一个常规缓冲区创建了一个node forge缓冲区,因为我没有示例中给出的输入文件。以下是文档中的说明,其中一个应该从另一个创建一个缓冲区: enter image description here

*我使用base64,因为我在java端使用base64对发送的数据进行编码

然后,我没有盐,所以我把第二个参数null留在了opensslDeriveBytes中,这是我应该做的文档中指定的

第三,我也不确定我的24键大小是否正确

我的结果

因此,进行端到端测试会产生以下结果:

在我的Java应用程序中,测试数据是"Marnus",测试数据是encryptedPayload,测试数据是ez+RweSAd+4=,测试数据是encodedKey

然后在我的javascript代码中data显然是ez+RweSAd+4=(encryptedPayload),而ephemeralKeyvCD9mBnWHPEBiQ0BGv7gc6GUCOoBgLCu(encodedKey)

解密运行后,decryptedResult的值是©ýÕ?µ{',这显然只是垃圾,因为它还没有编码,但我不知道该使用哪种编码

我试着使用forge.util.encode64(decipher.output.data),但那只是给了我qf3VP7UYeyc=,这是不对的

不管它值多少钱here is the typedecipher.output


共 (1) 个答案

  1. # 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"