gpt4 book ai didi

java - 将 openssl 迁移到 java

转载 作者:行者123 更新时间:2023-11-30 05:39:44 29 4
gpt4 key购买 nike

我需要将加密包从 C++/openssl 迁移到纯 Java 实现。但是,我遇到了一些我不知道如何解决的问题。

下面是一个 C++ 列表,概述了我目前正在尝试迁移的解密方案。

#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

// set master key
AES_KEY master_key;
const int AES128_KEY_SIZE = 16;
unsigned char* master_secret = "averysecretmastersecret";
AES_set_encrypt_key(master_secret, AES128_KEY_SIZE * 8 , &master_key);

// Base64 decode; encryptedInput is the original input text
// b64_output consists of two parts: a leading salt (16 bytes) and the following actual data
char* b64_output = base64Decode(encryptedInput); // base64Decode(const char* encodedText) -> char* decodedText

// prepare salt
const char SALT_LEN = 16; // first byte is reserved. Actually only use 15 bytes = 120 bit
unsigned char salt[SALT_LEN];
memcpy(salt, b64_output, SALT_LEN); // read salt

// generate key
const int AES128_KEY_SIZE = 16;
unsigned char key[AES128_KEY_SIZE];
salt[0] = 1; //
AES_ecb_encrypt(salt, key, &master_key, AES_ENCRYPT);

// generate iv
const int AES128_IV_SIZE = 16;
unsigned char iv[AES128_IV_SIZE];
salt[0] = 2; // ensure that key and iv are different
AES_ecb_encrypt(salt, iv, &master_key, AES_ENCRYPT);

// initialize cipher context
EVP_CIPHER_CTX *de;
de = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(de);
EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv)

aes_decrypt(b64_output + SALT_LEN, length - SALT_LEN);

// plaintext is a buffer to contain the output
int plaintext_size = DEFAULT_BUFFER_SIZE;
char *plaintext = (char*)malloc(plaintext_size);
int aes_decrypt(const char *ciphertext, int len)
{
int p_len = len, f_len = 0;
// allocate an extra cipher block size of memory because padding is ON
// #define AES_BLOCK_SIZE 16
if(p_len + AES_BLOCK_SIZE > plaintext_size) {
ASSERT_CALL(enlarge_buffer(plaintext, plaintext_size, p_len + AES_BLOCK_SIZE), "enlarge plaintext buffer failed");
}

ASSERT_OPENSSL( EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL), "sets up decode context failed");
ASSERT_OPENSSL( EVP_DecryptUpdate(de, (unsigned char*)plaintext, &p_len, (unsigned char*)ciphertext, len), "decrypt failed");
EVP_DecryptFinal_ex(de, (unsigned char*)plaintext+p_len, &f_len);
return EY_SUCCESS;
}

EVP_CIPHER_CTX_free(de);
dec_result = std::string(plaintext);

下面是我目前拥有的 Java 代码列表(当然不能正常工作)以重现上述 C++ 逻辑:

String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";

String secret = "averysecretmastersecret";

int SALT_LEN = 16;
String keyAlgorithm = "AES";
String ECB_TRANSFORM = "AES/ECB/NoPadding";
String CBC_TRANSFORM = "AES/CBC/NoPadding";

byte[] bytesOfSecret = Arrays.copyOf(secret.getBytes(), 16);
Key key =new SecretKeySpec(bytesOfSecret, keyAlgorithm);
Cipher ecbCipher = Cipher.getInstance(ECB_TRANSFORM);
Cipher cbcCipher = Cipher.getInstance(CBC_TRANSFORM);

// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);

byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);

// get iv
salt[0] = 2;
ecbCipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = ecbCipher.doFinal(salt);
iv = Arrays.copyOf(iv, 16);

AlgorithmParameterSpec parameterSpec = new IvParameterSpec(iv);

cbcCipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
byte[] bytes = cbcCipher.doFinal(data);
String decrypted = new String(bytes);

System.out.println(decrypted);

有几个地方我现在不知道如何从 C++ 映射到 Java。首先,在 C++ 代码中,它使用盐生成 key 和 iv,随后用于初始化 EVP 密码上下文,如 EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv)。我不知道java中的等效操作。

其次,C++代码中没有直接提及是否使用padding。我尝试了 NoPadding 和 PKCS5Padding,但不确定哪个是正确的。

那么,如何在 java 中重现 C++ 逻辑?有例子吗?

更新
我也试过 BouncyCaSTLe。它仍然无法正常工作。下面是我的代码:

int SALT_LEN = 16;

String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";
String password = "averysecretmastersecret";

// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);

BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));

PBEParametersGenerator generator = new OpenSSLPBEParametersGenerator();
byte[] bytesOfSecret = PBEParametersGenerator.PKCS5PasswordToBytes(password.toCharArray());
generator.init(bytesOfSecret, salt, 1);

ParametersWithIV parametersWithIV = (ParametersWithIV) generator.generateDerivedParameters(128, 128);

// for decryption
cipher.init(false, parametersWithIV);

byte[] decrypted = new byte[cipher.getOutputSize(data.length)];
System.out.println("expected decrypted size = " + decrypted.length); // prints ... size = 32

int processedBytes = cipher.processBytes(data, 0, data.length, decrypted, 0);
System.out.println("processed bytes = " + processedBytes); // prints ... bytes = 16

cipher.doFinal(decrypted, processedBytes); // Line 59, run into exception

String output = new String(decrypted);

System.out.println(output);

第 59 行,如上所示,给出了这个异常:

org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted
at org.bouncycastle.crypto.paddings.PKCS7Padding.padCount(Unknown Source)
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(Unknown Source)
...

最佳答案

这是java AES加密的一个例子,希望对你有帮助

      String key = "HkJHBKJBvffdbv";
String IV= "qjfghftrsbdghzir";
String theMessageToCifer ="your message";

SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");

IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
try{

//specify your mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivSpec);

encrypted = cipher.doFinal(theMessageToCifer.getBytes());

bytesEncoded = Base64.encode(encrypted);
System.out.println(" base64 code " +bytesEncoded);
System.out.println("encrypted string: " +encrypted);
// decryption
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec,ivSpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " + originalString );
}catch (Exception e){
e.printStackTrace();
}

关于java - 将 openssl 迁移到 java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32162585/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com