簡體   English   中英

Cipher.doFinal() 為長字符串返回部分解密字符串

[英]Cipher.doFinal() returning part of decrypted string for a long string

使用 sunjce 解密字符串時遇到問題:

javax.crypto.Cipher cipher =
      javax.crypto.Cipher.getInstance("AES/GCM/NoPadding", new BouncyCastleProvider());
  GCMParameterSpec spec = new GCMParameterSpec(Constants.GCM_TAG_BYTES * 8, nonce);
  cipher.init(javax.crypto.Cipher.DECRYPT_MODE, dataKey, spec);

  cipher.update(ciphertext);
  
  return cipher.doFinal();

如果我將整個密文傳遞給 doFinal,它會正常工作,但如果我正確調用它,它只會返回部分字符串。 例如對於輸入

String jsonExample = "{\"dataType\":\"STRING\",\"strValue\":\"000000\"}";

解密的字節只包含“000000”,但如果我使用

return cipher.doFinal(ciphertext); 

並刪除更新,以便正確打印原始字符串。 可能是什么原因? 如果我在更新后將一個空字節數組傳遞給 doFinal,它也會導致相同的數據丟失。 我想知道它背后的邏輯,它適用於小文本,但對於這種大小的文本,它根本不起作用。

這是我的輸入

String jsonExample = "{\"dataType\":\"STRING\",\"strValue\":\"000000\"}";

這就是我打印解密字符串的方式

String decryptedString = new String(decrypted, StandardCharsets.UTF_8);

這就是我將輸入字符串作為字節傳遞給加密 function 的方式

text = jsonExample.getBytes(StandardCharsets.UTF_8)

這就是我調用加密的方式

GCMParameterSpec spec = new GCMParameterSpec(Constants.GCM_TAG_BYTES * 8, nonce);
try {
  cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, dek, spec);
  byte[] ciphertext = cipher.doFinal(text);

當我在解密過程中使用cipher.update(ciphertext)后跟cipher.doFinal()cipher.doFInal(new byte[0])它只返回

"000000"在我使用返回的byte[]String decryptedString = new String(decrypted, StandardCharsets.UTF_8);

但是如果我在解密過程中直接調用cipher.doFInal(cipherText) ,我得到的結果字符串就是原始字符串。

您沒有使用 SunJCE,您使用的是 BouncyCastle 提供程序。 (您正在使用 Sun/Oracle API ——JCA,Java 加密體系結構——如果這就是您的意思,而不是提供商SunJCE。)

JCA 中的大多數密碼從每個或任何update調用(在加密或解密方向)返回部分數據,因此通常如果您使用update ,您必須連接該值(或那些值,如果多次調用)加上從doFinal返回的任何值,然后再使用任何需要它完成的結果,例如解碼 UTF8。 (通常最簡單的方法是將它們全部ByteArrayOutputStream .write或者.put它們全部寫入ByteBuffer ,但還有其他選擇。)但是 SunJCE 提供者不會為 GCM 執行此操作,僅在解密方向上,顯然是因為spec(SP800-38D)要求認證失敗不釋放明文,只能在.doFinal時判斷,然后返回所有明文。

Bouncy 提供程序執行“流式”GCM 解密,可以說這違反了規范,但與通常和傳統的 JCA 行為一致,因此大部分數據是從update調用返回的,只有來自doFinal的最后幾個字節,您需要連接這些如上所述——或者,正如您所發現的,根本不使用update :如果數據在加密時都適合一個緩沖區,那么在解密時它也應該適合。

Bouncy 提供者必須緩沖與標簽相等的數據量,以便它可以刪除和驗證所述標簽; 您的代碼工作的“小文本”——因為 decrypt .update返回任何內容——將達到但不超過您的標簽大小,這顯然是 8 個字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM