AES PBE在Java中加密/在Ruby中解密
使用Bouncy Castle PBewithsha256和128位AES-CBC-BC算法在Java中加密字符串数据。很难用ruby解密。我见过一些类似操作的例子,但没有一个是在JavaPBEkeySpect中使用的(当然不确定这是否是问题所在)。对于某些上下文,这里是Java代码AES PBE在Java中加密/在Ruby中解密,java,ruby,cryptography,encryption,Java,Ruby,Cryptography,Encryption,使用Bouncy Castle PBewithsha256和128位AES-CBC-BC算法在Java中加密字符串数据。很难用ruby解密。我见过一些类似操作的例子,但没有一个是在JavaPBEkeySpect中使用的(当然不确定这是否是问题所在)。对于某些上下文,这里是Java代码 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND128BITAES-CBC-BC",
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND128BITAES-CBC-BC",
org.spongycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME);
KeySpec spec = new PBEKeySpec("password".toCharArray(),
"8 bytes!", 1024, 128);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
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("hello world".getBytes());
这是毫无疑问的。然而,我们还没有发现在Ruby端解密它的神奇序列。如果有人愿意分享如何在ruby(1.9.3)中解密的例子,我们将不胜感激
更新
下面是ruby中目前不起作用的解密代码
d = OpenSSL::Cipher.new("AES-128-CBC")
d.decrypt
key = OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "8 bytes!", 1024, d.key_len)
d.key = key
d.iv = iv.scan(/../).map{|b|b.hex}.pack('c*')
data = enc.scan(/../).map{|b|b.hex}.pack('c*')
d.update(data) << d.final
d=OpenSSL::Cipher.new(“AES-128-CBC”)
d、 解密
key=OpenSSL::PKCS5.pbkdf2_hmac_sha1(“密码”,“8字节!”,1024,d.key_len)
d、 钥匙
d、 iv=iv.scan(///).map{b | b.hex}.pack('c*'))
data=enc.scan(////).map{| b | b.hex}.pack('c*'))
d、 更新(数据)好的,开始了。不过,您可能需要整理一些参数以适应:
/**
* Copied shamelessly from org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator,
* changed only the hash algorithm.
* All rights reserved by Bouncy Castle, see their MIT-like permissive license.
* @author maartenb
*
*/
public class PKCS5S2_SHA256_ParametersGenerator
extends PBEParametersGenerator
{
// NOTE this is the only actual change from PKCS5S2ParametersGenerator
private Mac hMac = new HMac(new SHA256Digest());
/**
* construct a PKCS5 Scheme 2 Parameters generator.
*/
public PKCS5S2_SHA256_ParametersGenerator()
{
}
private void F(
byte[] P,
byte[] S,
int c,
byte[] iBuf,
byte[] out,
int outOff)
{
byte[] state = new byte[hMac.getMacSize()];
CipherParameters param = new KeyParameter(P);
hMac.init(param);
if (S != null)
{
hMac.update(S, 0, S.length);
}
hMac.update(iBuf, 0, iBuf.length);
hMac.doFinal(state, 0);
System.arraycopy(state, 0, out, outOff, state.length);
if (c == 0)
{
throw new IllegalArgumentException("iteration count must be at least 1.");
}
for (int count = 1; count < c; count++)
{
hMac.init(param);
hMac.update(state, 0, state.length);
hMac.doFinal(state, 0);
for (int j = 0; j != state.length; j++)
{
out[outOff + j] ^= state[j];
}
}
}
private void intToOctet(
byte[] buf,
int i)
{
buf[0] = (byte)(i >>> 24);
buf[1] = (byte)(i >>> 16);
buf[2] = (byte)(i >>> 8);
buf[3] = (byte)i;
}
private byte[] generateDerivedKey(
int dkLen)
{
int hLen = hMac.getMacSize();
int l = (dkLen + hLen - 1) / hLen;
byte[] iBuf = new byte[4];
byte[] out = new byte[l * hLen];
for (int i = 1; i <= l; i++)
{
intToOctet(iBuf, i);
F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen);
}
return out;
}
/**
* Generate a key parameter derived from the password, salt, and iteration
* count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
public CipherParameters generateDerivedParameters(
int keySize)
{
keySize = keySize / 8;
byte[] dKey = generateDerivedKey(keySize);
return new KeyParameter(dKey, 0, keySize);
}
/**
* Generate a key with initialisation vector parameter derived from
* the password, salt, and iteration count we are currently initialised
* with.
*
* @param keySize the size of the key we want (in bits)
* @param ivSize the size of the iv we want (in bits)
* @return a ParametersWithIV object.
*/
public CipherParameters generateDerivedParameters(
int keySize,
int ivSize)
{
keySize = keySize / 8;
ivSize = ivSize / 8;
byte[] dKey = generateDerivedKey(keySize + ivSize);
return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
}
/**
* Generate a key parameter for use with a MAC derived from the password,
* salt, and iteration count we are currently initialised with.
*
* @param keySize the size of the key we want (in bits)
* @return a KeyParameter object.
*/
public CipherParameters generateDerivedMacParameters(
int keySize)
{
return generateDerivedParameters(keySize);
}
}
[编辑]示例用法
int iterations = 1000; // minimum
int keySize = 256; // maximum
final byte[] salt = new byte[8];
SecureRandom rng = SecureRandom.getInstance("SHA1PRNG");
rng.nextBytes(salt);
char[] password = new char[] { 'o', 'w', 'l', 's', 't', 'e', 'a', 'd' };
// S2 *is* PBKDF2, but the default used only HMAC(SHA-1)
final PKCS5S2_SHA256_ParametersGenerator gen = new PKCS5S2_SHA256_ParametersGenerator();
// lets not use String, as we cannot destroy strings, BC to the rescue!
final byte[] pwBytes = Strings.toUTF8ByteArray(password);
gen.init(pwBytes, salt, iterations);
final KeyParameter params1 = (KeyParameter) gen.generateDerivedMacParameters(keySize);
// use for/next loop for older Java versions, destroy password information in memory
Arrays.fill(pwBytes, 0, pwBytes.length, (byte) 0);
Arrays.fill(password, 0, password.length, ' ');
final KeyParameter keyParam = params1;
SecretKeySpec secretKey = new SecretKeySpec(keyParam.getKey().clone(), "AES");
[编辑]忘了包括许可证,即使我指向它,但很抱歉将其合法化:
版权所有(c)2000-2011弹跳城堡军团(http://www.bouncycastle.org)
特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人在不受限制的情况下经营本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向其提供软件的人员在符合以下条件的情况下这样做:
上述版权声明和本许可声明应包含在软件的所有副本或实质部分中
本软件按“原样”提供,无任何明示或暗示的担保,包括但不限于适销性、特定用途适用性和非侵权性担保。在任何情况下,作者或版权持有人均不对任何索赔、损害赔偿或其他责任负责,无论是合同诉讼、侵权诉讼还是其他诉讼,均由本软件或本软件的使用或其他交易引起,或与本软件或本软件的使用或其他交易有关 为什么不使用JRuby呢?然后你可以使用相同的软件包进行解密。这很好,但是这段代码是在Android上运行的(api级别8)-而且我们没有在解密发生的服务器端使用jruby的自由。请展示你已经尝试过的。我可以理解有些东西在没有指示的情况下就失败了,但如果你展示一些Ruby代码,你可能会发现人们更愿意发布答案。此外,这将有助于像我这样懂密码学的Ruby noobs。使用getBytes()
可能会导致问题。您需要准确地指定两端使用的编码。类似于,getBytes(“UTF-8”)
@rossum现在我更喜欢Charset.forName(“UTF-8”),因为它消除了选中的异常(无论如何,在符合Java SE的运行时永远不会抛出该异常;UTF-8是一种必需的字符编码)。您需要使用它吗,或者你能自己创造一些解决方案吗?很抱歉反应太晚-是的,我在Sat上花了很长时间。试图整合代码但没有用-如果你有任何见解,我一定会很感激。
int iterations = 1000; // minimum
int keySize = 256; // maximum
final byte[] salt = new byte[8];
SecureRandom rng = SecureRandom.getInstance("SHA1PRNG");
rng.nextBytes(salt);
char[] password = new char[] { 'o', 'w', 'l', 's', 't', 'e', 'a', 'd' };
// S2 *is* PBKDF2, but the default used only HMAC(SHA-1)
final PKCS5S2_SHA256_ParametersGenerator gen = new PKCS5S2_SHA256_ParametersGenerator();
// lets not use String, as we cannot destroy strings, BC to the rescue!
final byte[] pwBytes = Strings.toUTF8ByteArray(password);
gen.init(pwBytes, salt, iterations);
final KeyParameter params1 = (KeyParameter) gen.generateDerivedMacParameters(keySize);
// use for/next loop for older Java versions, destroy password information in memory
Arrays.fill(pwBytes, 0, pwBytes.length, (byte) 0);
Arrays.fill(password, 0, password.length, ' ');
final KeyParameter keyParam = params1;
SecretKeySpec secretKey = new SecretKeySpec(keyParam.getKey().clone(), "AES");