如何将ColdFusion加密与Java 1.4.2相匹配?

如何将ColdFusion加密与Java 1.4.2相匹配?,java,encryption,coldfusion,Java,Encryption,Coldfusion,***sweet-感谢Edward Smith提供的CF技术说明,指出ColdFusion的密钥是Base64编码的。有关“修复”的信息,请参见generateKey() 我的任务是使用Java1.4.2来匹配给定ColdFusion代码样本的加密结果 已知/给定值: 24字节的密钥 一个16字节的salt(IVorSalt) 编码是十六进制的 加密算法为AES/CBC/PKCS5P 示例明文值 通过ColdFusion代码后样本明文的加密值 假设: ColdFusion代码中未指定的迭代

***sweet-感谢Edward Smith提供的CF技术说明,指出ColdFusion的密钥是Base64编码的。有关“修复”的信息,请参见generateKey()

我的任务是使用Java1.4.2来匹配给定ColdFusion代码样本的加密结果

已知/给定值:

  • 24字节的密钥
  • 一个16字节的salt(IVorSalt)
  • 编码是十六进制的
  • 加密算法为AES/CBC/PKCS5P
  • 示例明文值
  • 通过ColdFusion代码后样本明文的加密值
假设:

  • ColdFusion代码中未指定的迭代次数,因此我假设只有一次迭代
  • 24字节密钥,所以我假设是192位加密
给定/工作ColdFusion加密代码示例:

<cfset ThisSalt = "16byte-salt-here">
<cfset ThisAlgorithm = "AES/CBC/PKCS5Padding">
<cfset ThisKey = "a-24byte-key-string-here">
<cfset thisAdjustedNow = now()>
<cfset ThisDateTimeVar = DateFormat( thisAdjustedNow , "yyyymmdd" )>
<cfset ThisDateTimeVar = ThisDateTimeVar & TimeFormat( thisAdjustedNow , "HHmmss" )>
<cfset ThisTAID = ThisDateTimeVar & "|" & someOtherData>
<cfset ThisTAIDEnc = Encrypt( ThisTAID , ThisKey , ThisAlgorithm , "Hex" , ThisSalt)>

我的Java 1.4.2加密/解密代码交换:

package so.example;

import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.*;

public class SO_AES192 {

private static final String _AES = "AES";
private static final String _AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
private static final String KEY_VALUE = "a-24byte-key-string-here";
private static final String SALT_VALUE = "16byte-salt-here";
private static final int ITERATIONS = 1;

private static IvParameterSpec ivParameterSpec;

public static String encryptHex(String value) throws Exception {
    Key key = generateKey();

    Cipher c = Cipher.getInstance(_AES_CBC_PKCS5Padding);
    ivParameterSpec = new IvParameterSpec(SALT_VALUE.getBytes());
    c.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);

    String valueToEncrypt = null;
    String eValue = value;
    for (int i = 0; i < ITERATIONS; i++) {
//            valueToEncrypt = SALT_VALUE + eValue; // pre-pend salt - Length > sample length
        valueToEncrypt =  eValue;     // don't pre-pend salt  Length = sample length
        byte[] encValue = c.doFinal(valueToEncrypt.getBytes());
        eValue =  Hex.encodeHexString(encValue);
    }
    return eValue;
}

public static String decryptHex(String value) throws Exception {
    Key key = generateKey();

    Cipher c = Cipher.getInstance(_AES_CBC_PKCS5Padding);
    ivParameterSpec = new IvParameterSpec(SALT_VALUE.getBytes());
    c.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);

    String dValue = null;
    char[] valueToDecrypt = value.toCharArray();
    for (int i = 0; i < ITERATIONS; i++) {
        byte[] decordedValue = Hex.decodeHex(valueToDecrypt);
        byte[] decValue = c.doFinal(decordedValue);
//            dValue = new String(decValue).substring(SALT_VALUE.length()); // when salt is pre-pended
        dValue = new String(decValue);   // when salt is not pre-pended
        valueToDecrypt = dValue.toCharArray();
    }
    return dValue;
}

private static Key generateKey() throws Exception {
    // Key key = new SecretKeySpec(KEY_VALUE.getBytes(), _AES); // this was wrong
    Key key = new SecretKeySpec(new BASE64Decoder().decodeBuffer(keyValueString), _AES); // had to un-Base64 the 'known' 24-byte key.
    return key;
}

}
package so.example;
导入java.security.*;
导入javax.crypto.Cipher;
导入javax.crypto.spec.IvParameterSpec;
导入javax.crypto.spec.SecretKeySpec;
导入org.apache.commons.codec.binary.*;
公共类SO_AES192{
私有静态最终字符串_AES=“AES”;
私有静态最终字符串\u AES\u CBC\u PKCS5Padding=“AES/CBC/PKCS5Padding”;
私有静态最终字符串KEY\u VALUE=“a-24byte-KEY-String-here”;
私有静态最终字符串SALT\u VALUE=“16byte SALT here”;
私有静态最终整数迭代=1;
私有静态IvParameterSpec IvParameterSpec;
公共静态字符串encryptHex(字符串值)引发异常{
Key=generateKey();
Cipher c=Cipher.getInstance(_AES_CBC_pkcs5pAdd);
ivParameterSpec=新的ivParameterSpec(SALT_VALUE.getBytes());
c、 init(Cipher.ENCRYPT_模式,密钥,ivParameterSpec);
字符串值ToEnCrypt=null;
字符串eValue=值;
对于(int i=0;i样本长度
valueToEncrypt=eValue;//不预挂起盐长度=样本长度
byte[]encValue=c.doFinal(valueToEncrypt.getBytes());
eValue=Hex.encodeHexString(encValue);
}
返回值;
}
公共静态字符串解密十六进制(字符串值)引发异常{
Key=generateKey();
Cipher c=Cipher.getInstance(_AES_CBC_pkcs5pAdd);
ivParameterSpec=新的ivParameterSpec(SALT_VALUE.getBytes());
c、 init(Cipher.DECRYPT_模式,密钥,ivParameterSpec);
字符串dValue=null;
char[]valueToDecrypt=value.toCharArray();
对于(int i=0;i
我无法创建匹配的加密值,也无法解密给定的加密值。我猜这与我如何处理初始向量/盐有关

我不是很精通密码,但我认为我应该能够获取示例明文,并在Java中生成与ColdFusion相同的加密值。我能够用我的Java代码加密/解密我自己的数据(因此我是一致的),但我无法匹配或解密ColdFusion示例加密值

我可以访问一个本地Web服务,它可以测试加密的输出。给定的ColdFusion输出示例(当然)可以通过/解密。如果我尝试用我的Java代码(使用实际的密钥和salt)解密同一个示例,我会得到一个“给定的最终块没有正确填充”错误。当我将加密尝试(使用实际密钥和salt)传递给测试Web服务时,我得到了相同的净结果


有什么想法吗?

是Coldfusion ThisKey中的值:

<cfset ThisKey = "a-24byte-key-string-here">
你应该是金黄色的。

谢谢你——generateKey()方法创建一个Key对象,其中包含算法“AES”和一个来自已知Key的字节数组,以便匹配。但是…显然,在word文档中传递的示例密钥是bas64编码的,必须先取消编码才能使用。我做了更改并更新了示例Java代码。现在一切都很好。。。
<cfset myKey =
ToBase64(BinaryDecode("8738fed68e7677d374e0946c8f7bd3bb4f50f23717f9f3667b2419483959039c","Hex")>
<cfset encrypted =Encrypt(myString, myKey, "AES")>
private static Key generateKey() throws Exception {
final byte[] decodedKey = new BASE64Decoder().decodeBuffer(KEY_VALUE);
final Key key = new SecretKeySpec(decodedKey, _AES);
return key;
}