Расшифруйте на Голанге то, что было зашифровано на Java (без iv) - PullRequest
0 голосов
/ 28 июня 2018

Когда я пытаюсь расшифровать строку, зашифрованную на Java, я получаю сообщение об ошибке: "шифр: аутентификация сообщения не удалась" .

Имеет ли java inputOffset из AESCipher.engineDoFinal (byte [] input, int inputOffset, int inputLen) означает то же самое, что Go nonceSize в моем коде

И является ли " NewGCMWithNonceSize " правильным декодером для моей проблемы?

Спасибо за помощь. Рабочий раствор:

JAVA

public static String encryptGCM(String data) throws CryptException {
    try {
        SecureRandom random = SecureRandom.getInstanceStrong();
        byte[] iv = new byte[12];
        random.nextBytes(iv);
        log.trace("IV: {}", Arrays.toString(iv));
        Key key = generateGcmKey();
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        byte[] cipherText = cipher.doFinal(data.getBytes("UTF-8"));
        log.trace("encrypted: {}", Arrays.toString(cipherText));
        byte[] result = new byte[cipherText.length + iv.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(cipherText, 0, result, iv.length, cipherText.length);
        log.trace("Not encoded result: {}", Arrays.toString(result));
        return Base64.getEncoder().encodeToString(result);
    } catch (Exception ex) {
        log.error("Failure occured while encrypt text value!", ex);
        throw new CryptException(data, ex);
    }
}

private static Key generateGcmKey() throws CryptException {
    try {
        SecretKey originalKey = new SecretKeySpec(KEY.getBytes(), 0, KEY.getBytes().length, ALGO);
        log.trace("Encoded key: {}", Base64.getEncoder().encodeToString(originalKey.getEncoded()));
        return originalKey;
    } catch (Exception ex) {
        log.error("Failure occured while generate key!", ex);
        throw new CryptException("Failure occured while generate key!", ex);
    }
}

GO

func decode(data string) (string, error) {
  ciphertext, _ := base64.StdEncoding.DecodeString(data)
  key, _ := base64.URLEncoding.DecodeString(decodeKey)
  c, err := aes.NewCipher([]byte(key))
  if err != nil {
    return "", err
  }

  gcm, err := cipher.NewGCM(c)
  if err != nil {
    return "", err
  }

   nonceSize := 12
   if len(ciphertext) < nonceSize {
     return  "", errors.New("ciphertext too short")
   }

   nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]

   result, err := gcm.Open(nil, nonce, ciphertext, nil)
   if err != nil {
     return "", err
   }
   return string(result), nil
 }

1 Ответ

0 голосов
/ 28 июня 2018

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


Проблема в том, что GCM ожидает, что базовые зашифрованные данные будут содержать информацию аутентификации. Эта информация не предоставляется вашей реализацией Java.

Вместо этого вы можете напрямую использовать созданный шифр AES для циклического прохождения блоков сообщения. Это может выглядеть так:

func decode(data string) (string, error) {
    ciphertext, err := base64.StdEncoding.Decode(data)
    if err != nil {
        return "", err
    }

    c, err := aes.NewCipher([]byte(DECODE_KEY))
    if err != nil {
        return "", err
    }

    result := make([]byte, len(ciphertext))
    for i := 0; i < len(ciphertext); i += aes.BlockSize {
        c.Decrypt(result[i:], ciphertext[i:])
    }

    return string(result), nil
}

Каждый вызов c.Decrypt расшифровывает один блок из ciphertext в result, как указано в документации . Также обратите внимание, что приращение между циклами цикла - это размер блока шифра AES.

Последний блок может содержать отступы, которые вам еще нужно удалить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...