4

私はColdFusionで暗号化されたデータを持っており、Javaを使用して同じ正確な値に復号化および暗号化できる必要があります。私は誰かがこれで私を助けることができるかもしれないことを望んでいました。セキュリティのために秘密にしておく必要がある実際のPasswordKeyを除いて、ColdFusionで使用されるすべてのものを指定します。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>
4

4 に答える 4

2

あなたの秘密鍵はおそらく Base64 でエンコードされた鍵です (23 文字は約 16 バイトにデコードされるはずです。これは AES の 128 ビット鍵の適切な長さです)。

そのため、Java コードでは、最初に Base64 デコーダーを介して秘密鍵文字列を実行し、AES アルゴリズムに適した長さ (16 バイト) の byte[] を取得します。

于 2012-06-13T14:57:33.863 に答える
2

128 ですが、AES 暗号化は 16 バイトのキー キー サイズをサポートします。
16 * 8 = 128 ビット、この例でもキーは 16 バイトです。

キーが Base64 にあるように聞こえるので、Base64.decode(key または key.getBytes()) を使用してバイト配列を取得し、16 バイトでチェックするか、パディングして 16 バイトにします。

于 2012-06-13T14:58:21.253 に答える
1

みなさん、ありがとうございました。他の人が使用できるように、最終的な解決策を投稿したかったのです。暗号化パッケージコード全体から特定のパスワードキーを除いたものを含めています(これもセキュリティのためです)。このコードは、質問にリストされているCFコードと同じ16進文字列を作成し、それを復号化して適切な英語のテキスト文字列に戻します。

bytesToHex私はstackoverflowの他の質問でと 関数を見つけたhexStringToByteArrayので、ユーザーの多分WeCouldStealAVanとDaveL.にもそれぞれ感謝します。太陽からのものが利用できなくなった場合に備えて、他のbase 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; 
    } 

}
于 2012-06-13T17:04:18.253 に答える
0

AES 暗号化は、128 ビット、192 ビット、または 256 ビットのキー サイズのみをサポートします。

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

バイト配列を取得して AES キーとして使用することはできません。上記のサンプル コードでは、128 ビット キーに対応する 16 文字を巧みに使用しています。

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

于 2012-06-13T14:54:12.120 に答える