2017-02-22 43 views
1

我需要在Java中生成与使用Ruby encrypted_strings库生成的加密字符串相同的加密字符串。我尝试了很多不同的方法,但是我的Java代码一直返回不同的输出结果,我无法理解我做错了什么。按照加密方法从encrypted_strings加密Java中的字符串ruby lib

下面是生成所需输出的ruby脚本,我无法在Java中正确使用它。

#!/usr/bin/ruby 
require 'encrypted_strings' 

data = 'Whackabad' 
password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ' 

encrypted_data = data.encrypt(:symmetric, :password => password) 
printf "Data: #{data}\n" 
printf "Encrypted Data: #{encrypted_data}" 

输出:

Data: Whackabad 
Encrypted Data: AEsDXVcgh2jsTjlDgh+REg== 

我看了一下图书​​馆,它好像是用DES-EDE3-CBC作为加密的默认算法。我从这里推断出我应该使用DESedeTripleDES算法和CBC模式。作为填充选项,我使用的是PKCS5Padding,导致库调用pkcs5_keyivgen

下面是尝试重现相同输出失败的Java代码。

package ... 

import sun.misc.BASE64Encoder; 

import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.DESedeKeySpec; 
import javax.crypto.spec.IvParameterSpec; 

public class SymmetricDESedeCipher { 
    private static final String DATA = "Whackabad"; 
    private static final String key = "bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ"; 
    private static final String ALGORITHM = "DESede"; 
    private static final String XFORM = "DESede/CBC/PKCS5Padding"; 

    private static byte[] iv = new byte[8]; 

    private static byte[] encrypt(byte[] inpBytes, 
            SecretKey key, String XFORM) throws Exception { 
     Cipher cipher = Cipher.getInstance(XFORM); 
     IvParameterSpec ips = new IvParameterSpec(iv); 
     cipher.init(Cipher.ENCRYPT_MODE, key, ips); 
     return cipher.doFinal(inpBytes); 
    } 

    public static void main(String[] unused) throws Exception { 
     byte[] keyBytes = key.getBytes(); 
     DESedeKeySpec desKeySpec = new DESedeKeySpec(keyBytes); 
     SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM); 

     SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec); 

     byte[] dataBytes = DATA.getBytes(); 
     byte[] encBytes = encrypt(dataBytes, secretKey, XFORM); 

     System.out.println("Data: " + DATA); 
     System.out.println("Encrypted Data: " + new BASE64Encoder().encode(encBytes)); 
    } 
} 

输出

Data: Whackabad 
Encrypted Data: ScPTKQBsR9Ni1nJ1tsMaaQ== 

我见过人们从Java加密数据从Ruby和反之亦然用不同的算法进行解密,所以我认为这是可以实现的,但我看不出有什么错误。你有好主意吗?如果是这样,那会有很大的帮助!

感谢

+0

开始通过确保您使用的是相同的字节。字符串表示在不同语言之间差别很大 – chrylis

+1

您确定要使用该红宝石加密库吗?该文档似乎表明它从密码派生初始化向量,这是一个可怕的想法 - [IV应该是随机的](http://crypto.stackexchange.com/a/82) – dnault

+0

是的@dnault,它的遗产是什么我试图翻译成Java,因此这个方法就是这个时候使用的方法,也是我想要复制的方法。 – rakemous

回答

1

要做的第一件事就是derive the IV and key从给定的密码。

从上面的链接中,您将分别得到与"VDiJjncs4ak=""s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU"对应的编码IV和KEY。 这意味着Java代码中使用的密钥和IV矢量是错误的,因为它在注释中说过。

下面是生成的Java代码:

public class SymmetricDESedeCipher { 
    private static final String DATA = "Whackabad"; 
    private static final String ALGORITHM = "DESede"; 
    private static final String XFORM = "DESede/CBC/PKCS5Padding"; 
    private static final String KEY = "s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU"; 
    private static final String IV = "VDiJjncs4ak="; 

    private static byte[] encrypt(String data, 
            SecretKey key, String XFORM, byte[] iv) throws Exception { 
     Cipher cipher = Cipher.getInstance(XFORM); 
     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); 
     return cipher.doFinal(data.getBytes()); 
    } 

    public static void main(String[] unused) throws Exception { 
     DESedeKeySpec spec = new DESedeKeySpec(new BASE64Decoder().decodeBuffer(KEY)); 
     SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM); 
     SecretKey secretKey = secretKeyFactory.generateSecret(spec); 

     byte[] encBytes = encrypt(DATA, secretKey, XFORM, new BASE64Decoder().decodeBuffer(IV)); 

     System.out.println("Data: " + DATA); 
     System.out.println("Encrypted Data: " + new BASE64Encoder().encode(encBytes)); 
    } 
} 

输出:

Data: Whackabad 
Encrypted Data: AEsDXVcgh2jsTjlDgh+REg==