使用密码短语的CBC的Java AES [英] Java AES with CBC using passphrase

查看:179
本文介绍了使用密码短语的CBC的Java AES的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Java实现256密钥AES和CBC加密。收件人发送了256位密码作为字符串'absnfjtyrufjdngjvhfgksdfrtifghkv',它完全可以使用这个openssl命令:

  echo test | openssl enc -aes-256-cbc -a -k'absnfjtyrufjdngjvhfgksdfrtifghkv'

base64格式的输出是:U2FsdGVkX1 / yA4J8T + i1M3IZS + TO / V29rBJNl2P88oI =



当我描述它时,它返回原始输入字符串:

  echo U2FsdGVkX1 / yA4J8T + i1M3IZS + TO / V29rBJNl2P88oI = | openssl enc -d -aes-256-cbc -a -k'absnfjtyrufjdngjvhfgksdfrtifghkv'

我的问题是我无法使我的加密工作在java中并使用上面的命令解密它。我知道我的密钥应该使用我的密码生成。下面是我的代码示例,其中IV是随机生成的,密钥是使用密码和随机盐生成的。

  byte [] input = 测试 .getBytes(); 
String passphrase =absnfjtyrufjdngjvhfgksdfrtifghkv;
int saltLength = 8;

SecureRandom random = new SecureRandom();

//随机生成盐
byte [] salt = new byte [saltLength];
random.nextBytes(salt);

//从密码和盐生成密钥
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF2WithHmacSHA1);
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(),salt,1024,256);
SecretKey key = factory.generateSecret(spec);
SecretKey kspec = new SecretKeySpec(key.getEncoded(),AES);

//随机生成IV
字节iv [] =新字节[16];
random.nextBytes(iv);
IvParameterSpec ips = new IvParameterSpec(iv);

Cipher c = Cipher.getInstance(AES / CBC / PKCS5Padding);
c.init(Cipher.ENCRYPT_MODE,kspec,ips);
byte [] encryptedData = c.doFinal(input);
System.out.println(new String(Base64.encodeBase64(encryptedData)));

我的java base64输出是XimWIM + 8UewzobFOMfevaw ==当我尝试运行时:

  echo XimWIM + 8UewzobFOMfevaw = | openssl enc -d -aes-256-cbc -a -k'absnfjtyrufjdngjvhfgksdfrtifghkv'

我变得'糟糕'魔术数字'错误。 java加密的哪一步我做错了?

解决方案

根据这个答案,OpenSSL使用的密钥派生算法与您在Java代码中使用的算法不同。因此,用于加密的密钥在OpenSSL命令和Java程序中会有所不同,因此输出会有所不同且不兼容。



您还应该检查文档OpenSSL中的密钥派生函数。显然它在算法中使用MD5,而您的Java代码使用SHA1。它们不会输出相同的密钥。



您必须指定完全相同的密钥派生函数,或直接指定密钥,而不是从密码短语中派生它。 / p>

最后,避免创建一个密钥派生函数(您可以轻松地使用bash并使用Java实现)并坚持标准,如果安全性是一个问题(如果不是,为什么要使用加密呢?);最有可能的是算法会被破坏。


I want to implement 256 key AES with CBC encryption with Java. Recipient sent me 256 bit passphrase as a String 'absnfjtyrufjdngjvhfgksdfrtifghkv' and it perfectly works using this openssl command:

 echo test | openssl enc  -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'

The output in base64 format is : U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI=

When i decript it, it returns original input string :

 echo U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI= | openssl enc -d -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'     

My problem is that i cannot make make my encryption work in java and decrypt it with above command. I know that my key should be generated using my passphrase. Below is example of my code where IV is generated randomly and key is generating using passphrase and random salt.

byte[] input = "test".getBytes();
String passphrase = "absnfjtyrufjdngjvhfgksdfrtifghkv";
int saltLength = 8; 

SecureRandom random = new SecureRandom();

//randomly generate salt
byte[] salt = new byte[saltLength];
random.nextBytes(salt);

// generating key from passphrase and salt
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 1024, 256);
SecretKey key = factory.generateSecret(spec);
SecretKey kspec = new SecretKeySpec(key.getEncoded(), "AES");

// randomly generate IV
byte iv[] = new byte[16];
random.nextBytes(iv);
IvParameterSpec ips = new IvParameterSpec(iv);

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, kspec, ips);
byte[] encryptedData = c.doFinal(input);
System.out.println(new String(Base64.encodeBase64(encryptedData)));

My java base64 output is XimWIM+8UewzobFOMfevaw== and when I try do run this:

echo XimWIM+8UewzobFOMfevaw= | openssl enc -d -aes-256-cbc -a -k   'absnfjtyrufjdngjvhfgksdfrtifghkv'

I get 'bad magic number' error. What step of java encryption I'm doing wrong?

解决方案

According to this answer, OpenSSL uses a different key derivation algorithm than what you are using in your Java code. Therefore, the key used to encrypt will be different in your OpenSSL command and in your Java program, so the output will be different and incompatible.

You should also check the documentation of the key derivation function in OpenSSL. Apparently it uses MD5 in the algorithm, while your Java code is using SHA1. They won't output the same key.

You have to specify exactly the same key derivation function, or specify the key directly, instead of deriving it from a passphrase.

Finally, avoid creating yourself a key derivation function (that you could easily implement using bash and using Java) and stick to standards, if security is a concern (if it is not, why bother using crypto?); it is most probable that the algorithm will be broken.

这篇关于使用密码短语的CBC的Java AES的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆