1

セッション中にユーザーのパスワードを PC にキャッシュするための安全なソリューションが必要です。

私は多数の AES の例を調べて、これが他の場所で回答されていることを知っていますが、少し混乱していると言わざるを得ません。私のaesSecretKeyまたはaesInitialisationVectorは復号化で正しく機能していませんが、問題がどこにあるのかわかりません。

復号化すると、javax.crypto.BadPaddingException: 与えられた最終ブロックが適切に埋め込まれていないという例外が発生します。

私のクラスは次のようになります

public class LockManagerTest {
    // Need to share the IV and key between encode and decode
    private static byte[] aesInitialisationVector;
    private static SecretKey aesSecretKey;
    private static Cipher aesCipher;

    public LockManagerTest(String sessionKey) {
        try {
            byte[] key = getSecretKey(sessionKey.toCharArray(), getSalt(32),
                                      65536, 128);
            aesSecretKey = new SecretKeySpec(key, "AES");
            aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
            AlgorithmParameters params = aesCipher.getParameters();
            aesInitialisationVector =
                    params.getParameterSpec(IvParameterSpec.class).getIV();
        } catch (Exception e) {
            Util.handleException(e);
        }
    }

    private static byte[] getSecretKey(char[] plaintext,
                                       byte[] salt,
                                       int iterations,
                                       int keySize)
            throws Exception {
        PBEKeySpec spec = new PBEKeySpec(plaintext, salt, iterations, keySize);
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        return skf.generateSecret(spec).getEncoded();
    }

    private static byte[] getSalt(int keyLength) throws Exception {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
        byte[] salt = new byte[keyLength];
        random.nextBytes(salt);
        return salt;
    }

    public byte[] encryptedAes(char[] input) throws Exception {
        // WRONG
        // aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
        //
        aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, 
                       new IvParameterSpec(aesInitialisationVector);
        CharBuffer cBuf = CharBuffer.wrap(input);
        byte[] normalised = Charset.forName("UTF-8").encode(cBuf).array();
        byte[] ciphertext = aesCipher.doFinal(normalised);
        return ciphertext;
    }

    public byte[] decryptAes(byte[] ciphertext) throws Exception {
        aesCipher.init(Cipher.DECRYPT_MODE,
                aesSecretKey, new IvParameterSpec(aesInitialisationVector));
        byte[] plaintext = aesCipher.doFinal(ciphertext);
        return plaintext;
    }
}

セキュリティのレベルに関するコメントも高く評価されています。

4

3 に答える 3

1

init()を呼び出すときにIV を渡す必要がありますencryptedAes()

于 2013-08-30T02:35:17.730 に答える
0

AES は CBC アルゴリズムで、入力をブロックに分割します。これらのブロックは特定のサイズでなければなりません。AES の場合、16 バイトだと思います。入力が 16 バイトの倍数でない場合は、暗号化の前に null を埋め込む必要があります。

于 2013-08-30T02:36:21.460 に答える