簡體   English   中英

如何在Java中加密字符串與在ColdFusion中加密的字符串完全相同?

[英]How can I encrypt a string in Java to be the exact same as it is encrypted in ColdFusion?

我在ColdFusion中加密了數據,我需要能夠使用Java解密和加密到相同的精確值。 我希望有人可以幫助我。 我將指定ColdFusion中使用的所有內容,除了實際的PasswordKey,出於安全目的,我必須保密。 PasswordKey長度為23個字符。 它使用大寫和小寫字母,數字以及+和=符號。 我知道這有很多要問,但任何幫助都將不勝感激。

我嘗試使用我在網上找到的Java加密示例,只是用我們的CF應用程序中使用的23個字符替換下面的行:

private static final byte[] keyValue = new byte[] {'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };` 

但我得到錯誤:

java.security.InvalidKeyException: Invalid AES key length: 23 bytes

CF代碼是:

Application.PasswordKey = "***********************";
Application.Algorithm = "AES";
Application.Encoding = "hex";

<cffunction name="encryptValue" access="public" returntype="string">
        <cfargument name="strEncryptThis" required="yes">

        <cfreturn Encrypt(TRIM(strEncryptThis), Application.PasswordKey, Application.Algorithm, Application.Encoding)>
</cffunction>


<cffunction name="decryptValue" access="public" returntype="string">
    <cfargument name="strDecryptThis" required="yes">

    <cfreturn Decrypt(TRIM(strDecryptThis), Application.PasswordKey, Application.Algorithm, Application.Encoding)>
</cffunction>

您的密鑰很可能是Base64編碼密鑰(23個字符應解碼為大約16個字節,這是AES的128位密鑰的正確長度)。

因此,在您的java代碼中,首先通過Base64解碼器運行您的密鑰字符串,以獲得AES算法的適當長度(16字節)的byte []。

128但AES加密支持16字節的密鑰大小。
16 * 8 = 128位,即使在示例中密鑰是16字節。

聽起來你的密鑰是在Base64中所以使用Base64.decode(key或key.getBytes())來獲取字節數組,檢查它的16字節,否則通過填充使其成為16字節。

感謝大家的幫助。 我想發布我的最終解決方案供其他人使用。 我包括我的整個加密包代碼減去特定的密碼密鑰(再次出於安全考慮)。 此代碼創建與問題中列出的CF代碼相同的十六進制字符串,並將其解密回正確的英文文本字符串。

我在stackoverflow上發現了其他問題中的bytesToHexhexStringToByteArray函數,所以我要感謝用戶們也分別是WeCouldStealAVan和Dave L. 我想我會研究其他基本的64位編碼器/解碼器,以防太陽的一個變得不可用,但這絕對適用於現在。 再次感謝。

package encryptionpackage;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;

public class encryption 
{
    // Note: The full CF default is "AES/ECB/PKCS5Padding"
    private static final String ALGORITHM = "AES";
    // The 24 character key from my CF app (base64 encoded)
    // typically generated with:  generateSecretKey("AES") 
    private static final String passKey = "***********************"; 

     public static String encrypt(String valueToEnc) throws Exception 
     {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        String encryptedValue = bytesToHex(encValue);
        return encryptedValue;
    }

    public static String decrypt(String encryptedValue) throws Exception 
    {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = hexStringToByteArray(encryptedValue);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception 
    {
          byte[] keyValue;
          keyValue = new BASE64Decoder().decodeBuffer(passKey);
        Key key = new SecretKeySpec(keyValue, ALGORITHM);

        return key;
    }

    public static String bytesToHex(byte[] bytes) 
    { 
        final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
        char[] hexChars = new char[bytes.length * 2]; 
        int v; 
        for ( int j = 0; j < bytes.length; j++ ) 
        { 
            v = bytes[j] & 0xFF; 
            hexChars[j * 2] = hexArray[v >>> 4]; 
            hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
        } 
        return new String(hexChars); 
    } 

    public static byte[] hexStringToByteArray(String s) 
    { 
        int len = s.length(); 
        byte[] data = new byte[len / 2]; 
        for (int i = 0; i < len; i += 2) 
        { 
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
                                 + Character.digit(s.charAt(i+1), 16)); 
        } 
        return data; 
    } 

}

AES加密僅支持128位,192位或256位的密鑰大小。

http://en.wikipedia.org/wiki/Advanced_Encryption_Standard

您不能只接受任何字節數組並將其用作AES密鑰。 在上面看到的示例代碼中,示例巧妙地使用了16個字符,這對應於128位密鑰。

這是因為1個字符或者更確切地說1個字節對應於8個比特。

然后,16值字節數組將對應於16 * 8 = 128 bits

23個字符= 23 * 8 = 184 bits ,因此它是無效的密鑰大小。

您需要16個字符,24個字符或32個字符。

話雖這么說,僅使用字符進行AES加密是非常不安全的。 請使用適當且安全的隨機密鑰進行加密。

要生成安全且隨機的AES密鑰:

SecureRandom random = new SecureRandom();
byte [] secret = new byte[16];
random.nextBytes(secret);

http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM