有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

加密无法解密java中aes256gcm加密的数据

我用OpenSSL aes-256-gcm加密了一个文件。由于命令行不支持aes-256-gcm,我已经安装了LibreSSL,我可以使用下面的命令加密文件的数据

openssl enc-aes-256-gcm-K 6161-iv 768A5C31A97D5FE9-e-in文件。输入输出文件。出去

我需要解密文件中的数据。在爪哇,我无法做到这一点

示例代码:

    // Get Cipher Instance
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

    String key = "61616161616161616161616161616161";
    byte[] IV = "768A5C31A97D5FE9".getBytes();

    // Create SecretKeySpec
    SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

    // Create GCMParameterSpec
    GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, IV);

    // Initialize Cipher for DECRYPT_MODE
    cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);

    // Perform Decryption
    byte[] decryptedText = cipher.doFinal(cipherText); // for the data by reading file.out

然而,javax是一个例外。加密。AEADBadTagException:标记不匹配


共 (1) 个答案

  1. # 1 楼答案

    这不应该奏效。Commandline openssl enc不支持AEAD密码/模式,尽管早期版本的1.0.1(在补丁h下,2012-2014年)在错误地指定此类密码并默默产生错误输出时无法捕获。如果您实际使用的是LibreSSL,而不是OpenSSL,那么它似乎继承了这个问题,而没有修复它,尽管LibreSSL项目的全部要点是,他们将修复由不称职的OpenSSL人员造成的所有错误

    如果这是一个在OpenSSL(以及Java)中正常工作的密码,比如aes-256-ctr,那么您唯一的问题就是openssl enc -K -iv以十六进制(适用于shell上下文)获取它们的参数,而Java crypto是从可以处理二进制数据的代码中调用的,并期望其参数以这种形式出现。因此,您提供给OpenSSL的值实际上是16字节(128位)和8字节(64位),而不是应该的256位和128位(对于CTR;对于GCM来说,96位的IV是正确的,但正如所指出的,GCM在这里不起作用)openssl enc会自动用(二进制)零填充-K -iv,但Java不会。因此,您需要更像

     byte[] key = Arrays.copyOf( javax.xml.bind.DatatypeConverter.parseHexBinary("61616161616161616161616161616161"), 32);
     // Arrays.copyOf zero-pads when expanding an array
     // then use SecretKeySpec (key, "AES")
     // and IVParameterSpec (iv) instead of GCMParameterSpec
    
     // but after Java8 most of javax.xml is removed, so unless you
     // are using a library that contains this (e.g. Apache) 
     // or have already written your own, you need something like
    
     byte[] fromHex(String h){
       byte[] v = new byte[h.length()/2];
       for( int i = 0; i < h.length(); i += 2 ) v[i] = Integer.parseInt(h.substring(i,i+2),16);
       return v;
     }
    

    比较AES encrypt with openssl command line tool, and decrypt in JavaBlowfish encrypt in Java/Scala and decrypt in bash(后者是相反的方向,但匹配的需求是相同的)