java sha1加密ascii码,在Java Sha1 openssl中解密AES加密文件

Im trying to implement file decryption by referring this code:

Encryption part i have done this way:

https//stackoverflow.com/questions/64423926/encrypt-file-in-java-and-decrypt-in-openssl-with-key-aes

And the encrypted file im able to decrypt with openssl.

But the decrypt to file in java is causing error:

java.lang.IllegalArgumentException: Illegal base64 character 5f

at java.util.Base64$Decoder.decode0(Unknown Source)

at java.util.Base64$Decoder.decode(Unknown Source)

at java.util.Base64$Decoder.decode(Unknown Source)

at aes.AesEncryptTask.decryptNew(AesEncryptTask.java:107)

at aes.AesEncryptTask.main(AesEncryptTask.java:58)

Content in my encrypted file is:

Salted__¨‹–1ž#¡ð=—ÖÏùá•NEÄ

Note: Starting salted part is not base64encoded. following data is encoded.

Please suggest on correct implementation of file decryption.

static void decryptNew(String path,String password, String outPath) {

try{

FileInputStream fis = new FileInputStream(path);

FileOutputStream fos = new FileOutputStream(outPath);

final byte[] pass = password.getBytes(StandardCharsets.US_ASCII);

//final byte[] inBytes = Base64.getDecoder().decode(source);

String source = getFileContent(fis);

final Decoder decoder = Base64.getDecoder();

final byte[] inBytes = decoder.decode(source);

//final byte[] inBytes =source.getBytes();//DatatypeConverter.parseBase64Binary(source);

final byte[] shouldBeMagic = Arrays.copyOfRange(inBytes, 0, SALTED_MAGIC.length);

if (!Arrays.equals(shouldBeMagic, SALTED_MAGIC)) {

throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");

}

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

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

byte[] hash = new byte[0];

byte[] keyAndIv = new byte[0];

for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {

final byte[] hashData = array_concat(hash, passAndSalt);

MessageDigest md = null;

md = MessageDigest.getInstance("SHA-1");

hash = md.digest(hashData);

keyAndIv = array_concat(keyAndIv, hash);

}

final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);

final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");

final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);

final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

final byte[] clear = cipher.doFinal(inBytes, 16, inBytes.length - 16);

String contentDecoded = new String(clear, StandardCharsets.UTF_8);

fos.write(contentDecoded.getBytes());

fos.close();

//cipher.init(Cipher.DECRYPT_MODE, sks);

/*CipherInputStream cis = new CipherInputStream(fis, cipher);

int b;

byte[] d = new byte[8];

while((b = cis.read(d)) != -1) {

fos.write(d, 0, b);

}

fos.flush();

fos.close();

cis.close();*/

System.out.println("Decrypt is completed");

}catch(Exception e){

e.printStackTrace();

}

}

解决方案

The below code is doing a complete file encryption and decryption and is compatible to the OpenSSL commands

encrypt: openssl enc -aes-256-cbc -pass pass:testpass -d -p -in plaintext.txt -out plaintext.txt.crypt -md md5

decrypt: openssl aes-256-cbc -d -in plaintext.txt.crypt -out plaintext1.txt -k testpass -md md5

I left out some variables as they are not used in decryption method and on the other hand substituded the byte[]

concatination with a pure Java version.

The simple output is:

encrypt done plaintext.txt

ciphertext: plaintext.txt

Decrypt is completed

Security warning: the key derivation is DEPRECATED and should not used any longer. The code does not have any exception handling and is for educational purpose only.

code:

import javax.crypto.Cipher;

import javax.crypto.CipherOutputStream;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.charset.StandardCharsets;

import java.nio.file.Files;

import java.nio.file.Paths;

import java.security.*;

import java.util.Arrays;

public class MainSo {

public static void main(String[] args) {

System.out.println("https://stackoverflow.com/questions/64443373/decrypt-aes-encrypted-file-in-java-sha1-openssl?noredirect=1#comment113960588_64443373");

String plaintextFilename = "plaintext.txt";

String ciphertextFilename = "plaintext.txt.crypt";

String decryptedtextFilename = "plaintextDecrypted.txt";

String password = "testpass";

// openssl equivalent:

// decrypt: openssl aes-256-cbc -d -in plaintext.txt.crypt -out plaintext1.txt -k testpass -md md5

// encrypt: openssl enc -aes-256-cbc -pass pass:testpass -d -p -in sample.crypt -out sample.txt -md md5

String ciphertext = encryptfile(plaintextFilename, password);

System.out.println("ciphertext: " + ciphertext);

decryptNew(ciphertextFilename, password, decryptedtextFilename);

}

public static String encryptfile(String path, String password) {

try {

FileInputStream fis = new FileInputStream(path);

FileOutputStream fos = new FileOutputStream(path.concat(".crypt"));

final byte[] pass = password.getBytes(StandardCharsets.UTF_8);

final byte[] salt = (new SecureRandom()).generateSeed(8);

fos.write("Salted__".getBytes(StandardCharsets.UTF_8));

fos.write(salt);

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

byte[] hash = new byte[0];

byte[] keyAndIv = new byte[0];

for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {

final byte[] hashData = concatenateByteArrays(hash, passAndSalt);

final MessageDigest md = MessageDigest.getInstance("MD5");

hash = md.digest(hashData);

keyAndIv = concatenateByteArrays(keyAndIv, hash);

}

final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);

final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);

final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");

final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));

CipherOutputStream cos = new CipherOutputStream(fos, cipher);

int b;

byte[] d = new byte[8];

while ((b = fis.read(d)) != -1) {

cos.write(d, 0, b);

}

cos.flush();

cos.close();

fis.close();

System.out.println("encrypt done " + path);

} catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {

e.printStackTrace();

}

return path;

}

static void decryptNew(String path,String password, String outPath) {

byte[] SALTED_MAGIC = "Salted__".getBytes(StandardCharsets.UTF_8);

try{

FileInputStream fis = new FileInputStream(path);

FileOutputStream fos = new FileOutputStream(outPath);

final byte[] pass = password.getBytes(StandardCharsets.US_ASCII);

final byte[] inBytes = Files.readAllBytes(Paths.get(path));

final byte[] shouldBeMagic = Arrays.copyOfRange(inBytes, 0, SALTED_MAGIC.length);

if (!Arrays.equals(shouldBeMagic, SALTED_MAGIC)) {

throw new IllegalArgumentException("Initial bytes from input do not match OpenSSL SALTED_MAGIC salt value.");

}

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

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

byte[] hash = new byte[0];

byte[] keyAndIv = new byte[0];

for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {

final byte[] hashData = concatenateByteArrays(hash, passAndSalt);

MessageDigest md = null;

md = MessageDigest.getInstance("MD5");

hash = md.digest(hashData);

keyAndIv = concatenateByteArrays(keyAndIv, hash);

}

final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);

final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");

final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);

final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

final byte[] clear = cipher.doFinal(inBytes, 16, inBytes.length - 16);

String contentDecoded = new String(clear, StandardCharsets.UTF_8);

fos.write(contentDecoded.getBytes());

fos.close();

System.out.println("Decrypt is completed");

}catch(Exception e){

e.printStackTrace();

}

}

public static byte[] concatenateByteArrays(byte[] a, byte[] b) {

return ByteBuffer

.allocate(a.length + b.length)

.put(a).put(b)

.array();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值