Java中的AES PBE加密/ Ruby中的Decrypt

使用Bouncy Castle PBEWITHSHA256AND128BITAES-CBC-BC算法加密Java中的字符串数据。 很难在ruby中解密它。 我已经看到了一些类似操作的例子,但是没有java PBEKeySpect被腌制的情况(当然不确定是否存在问题)。 对于某些上下文,这里是Java代码;

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)中分享如何解密这个的例子,我将不胜感激。

UPDATE

下面是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 

当Java端实现PBKDF2WithHmacSHA1算法时(显然),这个ruby代码工作,但由于我无法详细说明的原因,我们不能再使用该实现(因此PBEWITHSHA256AND128BITAES-CBC-BC )。

好的,有。 您可能需要编组一些参数以适应:

 /** * 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); } } 

哦,并将Bouncy添加到您的路径中......这些是必需的import语句:

 import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.PBEParametersGenerator; import org.bouncycastle.crypto.digests.SHA256Digest; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; 

[编辑]示例用法

  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)

特此授予任何获得本软件和相关文档文件(“软件”)副本的人免费许可,无限制地交易本软件,包括但不限于使用,复制,修改,合并的权利根据以下条件,出版,分发,再许可和/或出售本软件的副本,并允许向其提供本软件的人员这样做:

上述版权声明和本许可声明应包含在本软件的所有副本或实质部分中。

本软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性,特定用途的适用性和不侵权的保证。 在任何情况下,作者或版权所有者均不对任何索赔,损害或其他责任承担任何责任,无论是在合同,侵权或其他方面的行为,是由于,是否与本软件或其中的使用或其他交易有关。软件。