本文介绍了Java等效的OpenSSL AES CBC加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是一个加密技术,特别是因为OpenSSL有很多缺少的文档,我不知道我该如何解决这个问题。

I'm not a cryptography profi and specially due to the fact that OpenSSL has lots of missing documentation, I'm not sure how can I solve this problem.

我有一个外部系统,希望接收加密的消息。提供的唯一示例使用OpenSSL以这种方式:

I have an external system which expects to receive encrypted messages. The only example provided uses OpenSSL in this way:

$ openssl enc -aes-256-cbc -a -in t.txt -k testpass
U2FsdGVkX1/RUdaSJKRXhHv3zUyTsQwu5/ar2ECKDlrNyH5GL4xRR4fgxkiWqkS1
cQstcoSIgWfRPSOFj/5OtdNLeNXiVR6MxSKJ+NvS9LyUD8+Rg6XIcYUvxR4gHi3w
DWT44LAMCpRAh1Q0t4Z2g7rwb0D05T6ygLaWvB5zD/xGZD3brTqSlWmiJb9Imgda
M6soZO7BhbYdqWqEUl5r6+EbkD21f6L3NX3hJFo+BJ+VFctiAlBO8NwT5l4ogo/s
GErm8gqRr57XoX/kvKAimg==

t.txt 文件在一行中包含此字符串:

Where the t.txt file contains this string on one line:

AMOUNT=10&TID=#19:23&CURRENCY=EUR&LANGUAGE=DE&SUCCESS_URL=http://some.url/sucess&ERROR_URL=http://some.url/error&CONFIRMATION_URL=http://some.url/confirm&NAME=customer full name`

我找到其他问题,我已经能够使用以下代码进行加密:

I have found this other question and I have been able to do the encryption using following code:

String password = "passPhrase";
String salt = "15charRandomSalt";
int iterations = 100;

/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(Charset.forName("UTF8")), iterations, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] cipherText = cipher.doFinal(toBeEncrypted.getBytes("UTF-8"));
encryptedData = Base64.getEncoder().encodeToString(cipherText);
encryptedData += Base64.getEncoder().encodeToString(iv);

我不能理解的是我应该如何生成类似的输出(encryptedData)到什么OpenSSL。我有盐,iv和cipherText,是OpenSSL输出的Base64编码结果的串联这些?或者只有其中一个?

What I can not understand is how should I generate similar output (encryptedData) to what OpenSSL does. I have the salt, iv and cipherText, is the OpenSSL output Base64 encoded result of a concatenation of these? or only one single of them?

我在加密之前与其他系统共享的唯一的东西就是密码短语。如果他们不知道盐和迭代次数,他们如何解密结果?

The only thing I share with that other system before encryption is the pass phrase. How could they decrypt the result if salt and number of iterations is not known to them?

有人可以给出那些未知参数的答案,并告诉我如果上面的代码是下面是一个解密上述OPENSSL加密的Java程序(它需要Java 8):

Can somebody give answers to those unknown parameters and also tell me if the above code is the equivalent of OpenSSL process?

推荐答案

/ p>

Following is a Java program to decrypt the above OPENSSL encryption (it requires Java 8):

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Decoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class TestAesDecrypt {

    public static void main(final String[] args) throws Exception {
        final byte[] pass = "testpass".getBytes(StandardCharsets.US_ASCII);
        final byte[] magic = "Salted__".getBytes(StandardCharsets.US_ASCII);
        final String inFile = "e:/t/e.txt";

        String source = new String(Files.readAllBytes(Paths.get(inFile)),
                StandardCharsets.US_ASCII);
        source = source.replaceAll("\\s", "");
        final Decoder decoder = Base64.getDecoder();
        final byte[] inBytes = decoder.decode(source);

        final byte[] shouldBeMagic = Arrays.copyOfRange(inBytes, 0,
                magic.length);
        if (!Arrays.equals(shouldBeMagic, magic)) {
            System.out.println("Bad magic number");
            return;
        }

        final byte[] salt = Arrays.copyOfRange(inBytes, magic.length,
                magic.length + 8);

        final byte[] passAndSalt = concat(pass, salt);

        byte[] hash = new byte[0];
        byte[] keyAndIv = new byte[0];
        for (int i = 0; i < 3; i++) {
            final byte[] data = concat(hash, passAndSalt);
            final MessageDigest md = MessageDigest.getInstance("MD5");
            hash = md.digest(data);
            keyAndIv = concat(keyAndIv, hash);
        }

        final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
        final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        final byte[] clear = cipher.doFinal(inBytes, 16, inBytes.length - 16);
        final String clearText = new String(clear, StandardCharsets.ISO_8859_1);
        System.out.println(clearText);
    }

    private static byte[] concat(final byte[] a, final byte[] b) {
        final byte[] c = new byte[a.length + b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }
}

这篇关于Java等效的OpenSSL AES CBC加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 20:54