Для дешифрования AES / GCM / NoPadding нужен тег, как найти тег при шифровании

#android #node.js #caesar-cipher #aes-gcm

#Android #node.js #caesar-cipher #aes-gcm

Вопрос:

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

 aesKey=context.getString(R.string.aes_key).getBytes();
iv=context.getString(R.string.input_vector).getBytes();


public Map encrypt(String string){
    byte[] plainText= new byte[0];
    try {
        plainText = string.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/GCM/NoPadding");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
    try {
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(aesKey, "AES"), new IvParameterSpec(iv));
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    byte[] cipherText = new byte[0];
    byte[] tag = new byte[0];
    try {

        cipherText = cipher.doFinal(plainText);
        tag= Arrays.copyOfRange(cipherText, cipherText.length -16, cipherText.length);
        cipherText= Arrays.copyOfRange(cipherText, 0, cipherText.length -16);

        Log.d("testing", "encrypt: " byteArrayToHexString(tag));
        Map<String, Object> map=new HashMap();
        map.put("content",byteArrayToHexString(cipherText));
        map.put("tag",tag);
        Log.d("testing", "encrypt: " new Gson().toJson(map));
        return map;
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    }

    return new HashMap();
}
  

Серверу нужен шестнадцатеричный код, поэтому я конвертирую его в шестнадцатеричный

 public  String byteArrayToHexString(final byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for(byte b : bytes){
        sb.append(String.format("x", bamp;0xff));
    }
    return sb.toString();
}
  

Моя функция дешифрования заключается в том, что возвращает мне строку, которую я получаю, тег и шестнадцатеричную строку с сервера

     public String decrypt(String content,byte[] tag){


    byte[] cipherText = hexStringToByteArray(content byteArrayToHexString(tag));


    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/GCM/NoPadding");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
    try {
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(aesKey, "AES"), new IvParameterSpec(iv));
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    byte[] plainText = new byte[0];
    try {
        plainText = cipher.doFinal(cipherText);
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    }
    try {
        Log.d("testing", "encrypt: plain text:" new String(plainText,"UTF-8"));
        return new String(plainText,"UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return null;
}
  

Комментарии:

1. Интересно, действительно ли этот код выполняется в вашей среде. На моем компьютере InvalidAlgorithmParameterException ( Неподдерживаемый параметр: javax.crypto.spec. Выбрасывается IvParameterSpec ), потому что для GCM на самом деле вместо GCMParameterSpec используется a IvParameterSpec . Когда эта проблема устранена, шифрование выполняется успешно.

2. Какую версию Java и какую среду вы используете? Я не уверен, почему вы можете запускать AES/GCM/NoPadding в сочетании с IvParameterSpec . На самом деле GCM нужен GCMParameterSpec , который позволяет явно указывать длину тега. Обычно длина тега для GCM составляет 16 байт, а IV — 12 байт. Код, размещенный в комментарии, отделяет тег размером 16 байт от зашифрованного текста.

3. Хорошо для Android API, по-видимому, AES/GCM/NoPadding также работает в сочетании с IvParameterSpec , сгенерированный тег имеет длину 16 байт. Поэтому GCMParameterSpec здесь не обязательно обязательно использовать. Это не работает в Java API, здесь GCMParameterSpec необходимо использовать. К вашему сведению: длина тега (независимо от того, использовался ли IvParameterSpec или GCMParameterSpec ) может быть определена с помощью cipher.getParameters().getParameterSpec(GCMParameterSpec.class).getTLen() .

4. На ваши вопросы: есть ли в Android какой-либо другой способ или функция для получения тега? Насколько мне известно, нет (т. Е. вам всегда нужно разделять).

5. Есть ли какой-либо возможный способ, если я не отправляю тег на сервер, а сервер узла расшифровывает мою строку? Вы ничего не опубликовали о реализации GCM на сайте NodeJS, поэтому я могу ответить только в общих чертах: преимущество GCM — это тег, то есть аутентификация. GCM без аутентификации имеет мало смысла, тогда вы также можете использовать режим без аутентификации. В принципе, однако, при 12 байтах IV для GCM возможно дешифрование без тега, смотрите здесь . Но это должно быть реализовано (т. Е. По умолчанию это не работает так).