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 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?
  • ¥100 求三轴之间相互配合画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题