web-dev-qa-db-ja.com

無効なAESキーの長さを修正するには?

テキストの暗号化と復号化プロジェクトに取り組んでいます(Struts 2に続く)

パスワードとプレーンテキストを入力すると、Invalid AES Key Lengthエラーが発生します。

サービスクラス

package com.anoncrypt.services;

import Java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import Sun.misc.BASE64Decoder;
import Sun.misc.BASE64Encoder;

public class SymAES
{
    private static final String ALGORITHM = "AES";
    private static byte[] keyValue= new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };

     public  String encode(String valueToEnc) throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGORITHM);
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encValue);
        return encryptedValue;
    }

    public  String decode(String encryptedValue) throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGORITHM);
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    public  void start(String passcode)throws Exception
    {
        keyValue = passcode.getBytes();
    }
}

そして、これはエラーです

Java.security.InvalidKeyException: Invalid AES key length: 6 bytes
    com.Sun.crypto.provider.AESCrypt.init(AESCrypt.Java:87)
    com.Sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.Java:93)
    com.Sun.crypto.provider.CipherCore.init(CipherCore.Java:582)
    com.Sun.crypto.provider.CipherCore.init(CipherCore.Java:458)
    com.Sun.crypto.provider.AESCipher.engineInit(AESCipher.Java:307)
    javax.crypto.Cipher.implInit(Cipher.Java:797)
    javax.crypto.Cipher.chooseProvider(Cipher.Java:859)
    javax.crypto.Cipher.init(Cipher.Java:1229)
    javax.crypto.Cipher.init(Cipher.Java:1166)
    com.anoncrypt.services.SymAES.encode(SymAES.Java:35)
    com.anoncrypt.actions.SymEncrypt.execute(SymEncrypt.Java:24)
30

一般的に知っておくべきこと:

  1. Key!= Password
    • SecretKeySpecには、パスワードではなくキーが必要です。下記参照
  2. 32バイトキーの使用を禁止するポリシーの制限が原因である可能性があります。他の回答をご覧ください

あなたの場合

問題は番号1です。キーの代わりにパスワードを渡します。

AESは、16、24、または32バイトのキーサイズのみをサポートします。正確にその金額を提供するか、入力した内容からキーを導出する必要があります。

パスフレーズからキーを取得するには、さまざまな方法があります。 Javaは、そのような目的のためにPBKDF2実装を提供します。

私はエリクソンの answer を使用して完全な画像をペイントしました(復号化は同様ですが、暗号文の分割を含むため、暗号化のみ):

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

KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 256); // AES-256
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = f.generateSecret(spec).getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

byte[] ivBytes = new byte[16];
random.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] encValue = c.doFinal(valueToEnc.getBytes());

byte[] finalCiphertext = new byte[encValue.length+2*16];
System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
System.arraycopy(salt, 0, finalCiphertext, 16, 16);
System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);

return finalCiphertext;

その他の留意事項:

  • 常に完全修飾暗号名を使用してください。 AESは、このような場合には適切ではありません。JVM/ JCEプロバイダーが異なると、動作モードとパディングのデフォルトが異なる可能性があるためです。 AES/CBC/PKCS5Paddingを使用します。 ECBモードは意味的に安全ではないため、使用しないでください。
  • ECBモードを使用しない場合は、暗号文とともにIVを送信する必要があります。これは通常、IVを暗号文バイト配列の前に付けることで行われます。 IVは自動的に作成され、cipherInstance.getIV()から取得できます。
  • 何かを送信するときはいつでも、途中で変更されていないことを確認する必要があります。 MACによる暗号化を正しく実装することは困難です。 CCMやGCMなどの認証モードを使用することをお勧めします。
58
Artjom B.

キーの長さの制限を確認できます。

int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("MaxAllowedKeyLength=[" + maxKeyLen + "].");
4
AOL

私は同じ問題に直面していたので、キーを16バイトにしましたが、今は正しく動作しています。正確に16バイトのキーを作成します。確実に機能します。

4
vineet patel