duanlu1959 2018-06-28 07:39
浏览 296
已采纳

用Golang解密用Java加密的内容(无iv)

Wenn I try to decrypt a string, encrypted in Java I get an error: "cipher: message authentication failed".

Does java inputOffset from AESCipher.engineDoFinal(byte[] input, int inputOffset, int inputLen) meens the same as the Go nonceSize in my code?

And is "NewGCMWithNonceSize" a right one decoder for my issue?

Thanks for help. Working solution:

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条回答 默认 最新

  • douzhao2047 2018-06-28 09:15
    关注

    As noted in the comments to the question the follwing code is not secure since it uses the ECB mode of operation for encryption which should not be considered secure.


    The problem is that GCM expects the underlying encrypted data to contain authentification information. This information is not supplied by your Java implementation.

    Instead you can use your created AES cipher directly to loop over the blocks of the message. This could look like this:

    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
    }
    

    Each call to c.Decrypt decrypts one block from ciphertext into result as noted in the documentation. Also notice that the increment between loop iterations is the block size of the AES cipher.

    The last block may contain padding, which you still need to remove.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 CSS通配符清除内外边距为什么可以覆盖默认样式?
  • ¥15 SPSS分类模型实训题步骤
  • ¥15 求解决扩散模型代码问题
  • ¥15 工创大赛太阳能电动车项目零基础要学什么
  • ¥20 limma多组间分析最终p值只有一个
  • ¥15 nopCommerce开发问题
  • ¥15 torch.multiprocessing.spawn.ProcessExitedException: process 1 terminated with signal SIGKILL
  • ¥15 QuartusⅡ15.0编译项目后,output_files中的.jdi、.sld、.sof不更新怎么解决
  • ¥15 pycharm输出和导师的一样,但是标红
  • ¥15 想问问富文本拿到的html怎么转成docx的