当前位置: 首页 > 知识库问答 >
问题:

无法在java中解密aes-256-gcm加密数据

富凯旋
2023-03-14

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

openssl ENC-AES-256-GCM-K 616161616161616161616161616161616161616161616161616161616161616161-IV 768A5C31A97D5FE9-E-IN FILE.IN-OUT FILE.OUT

我需要在Java中解密File.out的数据,但我无法做到这一点。

    // 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

共有1个答案

陶俊晤
2023-03-14

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

如果这是一个在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和openssl命令行工具,以及Java中的解密和Blowfish encrypt在Java/Scala中的解密和bash中的解密(后者是相反的方向,但需要匹配的是相同的)

 类似资料: