производить вывод результата шифрования AES с фиксированной длиной, даже если длина входной пружины меняется - PullRequest
0 голосов
/ 17 мая 2018

У меня есть таблица с именем user.that есть столбец firstName varchar (25).

Я шифрую имя имени при вставке с помощью алгоритма AES (AES / CBC / PKCS5Padding)

но каждый раз, когда я зашифровываю значение первого имени, я не получаю выходное значение (зашифрованное) с той же длиной. Когда длина строки значения первого имени изменяется, зашифрованный выходной файл подходит для varchar lenth, определенного для столбца.

String input = "test"; // зашифрованное значение: 978fbfa24962827da56b1f00896a4f2cbfc25b744e836c2a22d4292fb16dd53a

String input = "это тест"; // зашифрованное значение: 978fbfa24962827da56b1f00896a4f2cbfc25b744e836c22a22d4292fb16dd53aa22d4292fb16dd53a

Я получаю следующее исключение.

Усечение данных: данные слишком длинные для столбца

Я добавил свой код здесь.

public String encrypt(String plainText) {

        byte[] cipherBytes = null;

        log.info("Started encryption...");

        if (plainText != null && !plainText.isEmpty()) {
            if (cipher != null && key != null) {
                try {
                    byte[] ivByte = new byte[cipher.getBlockSize()];
                    IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
                    cipher.init(Cipher.ENCRYPT_MODE, key, ivParamsSpec);
                    cipherBytes = cipher.doFinal(plainText.getBytes());
                    plainText = Hex.encodeHexString(cipherBytes);
                    log.info("Completed encryption.");
                    log.info("Encrypted data : "
                            + new String(cipherBytes, "UTF8"));
                } catch (BadPaddingException | IllegalBlockSizeException
                        | InvalidKeyException
                        | InvalidAlgorithmParameterException
                        | UnsupportedEncodingException e) {
                    log.error("Encryption failed : " + e.getMessage());
                    e.printStackTrace();
                    throw new RuntimeException("Encryption failed : "
                            + e.getMessage());
                }
            } else {
                log.error("Encryption failed, cipher, key is null.");
                throw new RuntimeException(
                        "Encryption failed, cipher, key  is null.");
            }
        } else {
            return plainText;
        }
        return plainText;
    }

    public String decrypt(String cipherHexString) throws AuthorizationException {

        log.info("Started decryption...");
        byte[] plainTextBytes = null;
        String resource = "kk";
        String resourceCatagory = "kk tables";
        String accessType = "write";

        try {
            if (decryptionAuthorizer.authorize(resource, resourceCatagory,
                    accessType)) {
                if (cipherHexString != null && !cipherHexString.isEmpty()) {
                    if (cipher != null && key != null) {
                        try {
                            byte[] ivByte = new byte[cipher.getBlockSize()];
                            IvParameterSpec ivParamsSpec = new IvParameterSpec(
                                    ivByte);
                            cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec);
                            plainTextBytes = cipher.doFinal(Hex
                                    .decodeHex(cipherHexString.toCharArray()));
                            cipherHexString = new String(plainTextBytes);
                            log.info("Completed decryption.");
                        } catch (InvalidKeyException
                                | InvalidAlgorithmParameterException
                                | IllegalBlockSizeException
                                | BadPaddingException | DecoderException e) {
                            log.error("Decryption failed : " + e.getMessage());
                            e.printStackTrace();
                            throw new RuntimeException("Decryption failed : "
                                    + e.getMessage());

                        }
                    } else {
                        log.error("Decryption failed, cipher, key is null.");
                        throw new RuntimeException(
                                "Decryption failed, cipher, key is null.");
                    }
                } else {
                    return cipherHexString;
                }
            }
        } catch (AuthorizationException e) {
            throw new AuthorizationException(
                    "User not authorized to decrypt  data.");
        }

        return cipherHexString;
    }

    /**
     * This method is used to manually override max key length permission, as an
     * application level solution instead of configuration changes in
     * security.policy.
     */
    private void fixKeyLength() {
        String errorString = "Failed manually overriding key-length permissions.";
        int newMaxKeyLength;

        try {
            newMaxKeyLength = javax.crypto.Cipher.getMaxAllowedKeyLength("AES");
            log.info("Initial max key size for AES : " + newMaxKeyLength);

            if (newMaxKeyLength < 256) {
                Class c = Class
                        .forName("javax.crypto.CryptoAllPermissionCollection");
                Constructor con = c.getDeclaredConstructor();
                con.setAccessible(true);
                Object allPermissionCollection = con.newInstance();
                Field f = c.getDeclaredField("all_allowed");
                f.setAccessible(true);
                f.setBoolean(allPermissionCollection, true);

                c = Class.forName("javax.crypto.CryptoPermissions");
                con = c.getDeclaredConstructor();
                con.setAccessible(true);
                Object allPermissions = con.newInstance();
                f = c.getDeclaredField("perms");
                f.setAccessible(true);
                ((Map) f.get(allPermissions)).put("*", allPermissionCollection);

                c = Class.forName("javax.crypto.JceSecurityManager");
                f = c.getDeclaredField("defaultPolicy");
                f.setAccessible(true);
                Field mf = Field.class.getDeclaredField("modifiers");
                mf.setAccessible(true);
                mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
                f.set(null, allPermissions);

                newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
                log.info("Max key size permission changed, new max key size for AES : "
                        + newMaxKeyLength);
            }
        } catch (Exception e) {
            throw new RuntimeException(errorString, e);
        }
        if (newMaxKeyLength < 256)
            throw new RuntimeException(errorString);
    }

    public String getAlgo() {
        return algo;
    }

    public void setAlgo(String algo) {
        this.algo = algo;
    }

    public String getKeyAlias() {
        return keyAlias;
    }

Есть ли способ шифрования выходных данных с одинаковой длиной, даже если длина значения входной строки варьируется. Так что я не получаю

Усечение данных: данные слишком длинные для столбца

1 Ответ

0 голосов
/ 17 мая 2018

Очевидно, что вы не получите результат с одинаковой длиной, потому что результат симметричного шифрования кратен размеру блока алгоритма шифрования (в случае не потоковых режимов, таких как ECB и CBC).

В вашем случае у вас есть varchar(25), поэтому максимальный размер составляет 50 байтов (каждый varchar равен 2 байта).Тогда максимальный результат шифрования составляет 32 байта, потому что вы используете алгоритм AES, который имеет размер блока длиной 16 байтов.

Если вы должны иметь такой же размер, вам нужно использовать потоковые режимытакие как CTR.Но я предлагаю держать столбец достаточно длинным для хранения зашифрованных данных в режиме CBC.

В любом случае ваш зашифрованный результат слишком длинный.Я думаю (только предположение, потому что не хватает кода) после получения строки из базы данных, вы кодируете ее в шестнадцатеричную строку, а затем передаете ее функции шифрования.Вот почему вы получаете очень длинный зашифрованный результат:

varchar("test") -> 8 bytes long -> 16 bytes hex string -> 32 bytes after encrypting (with padding) -> 64 bytes hex string
varchar("test is test") -> 24 bytes long -> 48 bytes hex string -> 64 bytes after encrypting (with padding) -> 128 bytes hex string
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...