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 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler