2017-05-27 205 views
0

我想了解更多关于AES加密的信息。 AES加密使用密钥和IV进行加密,但由于每个IV都不同,AES如何解密密文并返回明文?AES如何解密不同的IV?

http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html https://www.securecoding.cert.org/confluence/display/java/MSC61-J.+Do+not+use+insecure+or+weak+cryptographic+algorithms

public static byte[] encrypt_cbc(SecretKey skey, String plaintext) { 
     /* Precond: skey is valid; otherwise IllegalStateException will be thrown. */ 
     try { 
      byte[] ciphertext = null; 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
      final int blockSize = cipher.getBlockSize(); 
      byte[] initVector = new byte[blockSize]; 
      (new SecureRandom()).nextBytes(initVector); 
      IvParameterSpec ivSpec = new IvParameterSpec(initVector); 
      cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec); 
      byte[] encoded = plaintext.getBytes(java.nio.charset.StandardCharsets.UTF_8); 
      ciphertext = new byte[initVector.length + cipher.getOutputSize(encoded.length)]; 
      for (int i=0; i < initVector.length; i++) { 
       ciphertext[i] = initVector[i]; 
      } 
      // Perform encryption 
      cipher.doFinal(encoded, 0, encoded.length, ciphertext, initVector.length); 
      return ciphertext; 
     } catch (NoSuchPaddingException | InvalidAlgorithmParameterException | ShortBufferException | 
      BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchAlgorithmException e) 
     { 
      /* None of these exceptions should be possible if precond is met. */ 
      throw new IllegalStateException(e.toString()); 
     } 
    } 

    public static String decrypt_cbc(SecretKey skey, byte[] ciphertext) 
     throws BadPaddingException, IllegalBlockSizeException /* these indicate corrupt or malicious ciphertext */ 
    { 
     try { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");   
      final int blockSize = cipher.getBlockSize(); 
      byte[] initVector = Arrays.copyOfRange(ciphertext, 0, blockSize); 
      IvParameterSpec ivSpec = new IvParameterSpec(initVector); 
      cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec); 
      byte[] plaintext = cipher.doFinal(ciphertext, blockSize, ciphertext.length - blockSize); 
      return new String(plaintext); 
     } catch (NoSuchPaddingException | InvalidAlgorithmParameterException | 
      InvalidKeyException | NoSuchAlgorithmException e) 
     { 
      /* None of these exceptions should be possible if precond is met. */ 
      throw new IllegalStateException(e.toString()); 
     } 
    } 
+1

嗯,我认识到我的异常处理,我认为,但我绝不会在我的方法名称中使用下划线或删除catch块中的整个堆栈跟踪。或者现在然后使用'final'。或者给密文分配'null'。或者仍然使用CBC。关于代码实践,这并不是一个很好的例子。虽然可能会恶化很多! –

+0

@youcanlearnanything *“AES如何用**不同的** IV解密?”* - 你能举一个你看过这个的例子吗? IV对于一个加密/解密周期 –

+0

@ ArtjomB必须相同。如果这意味着什么,那么可能是因为纯运气或者IV仅部分不同(它与明文异或,所以),前16个字节有点意义。如果IV不同,只有第一个块受到影响。 –

回答

1

通常随机IV - CBC需要不可预知 IV - 解密之前被前缀到密文和 “删除”。我已经删除了引号,因为删除它可能会被复制并在之后跳过。原则上它可以放在密文的任何地方。 CBC模式的IV等于底层密码的块大小(Cipher#getBlockSize()),即AES的16个字节,所以预先知道大小。

IV不需要被攻击者保密。

一般来说,IV的类型和安全性取决于加密模式。对于CBC,它需要是不可预知的,对于CTR(计数器模式),它不应该与另一个计数器值重叠,对于GCM,它需要是12个字节的随机数。

还有其他共享IV的方式。对于CBC来说,例如可以在双方都保留一个计数器并加密该计数器以形成一个IV(当然,在将其编码为16个字节之后)。这样,IV不需要包含在密文中。

+0

我没有得到的是,你已经显示的代码片段实际上已经在IV前缀,什么给了? –

+0

我一直在阅读有关IV和密钥之间的区别。一般来说,如果将相同的密钥重新用于加密,则建议使用不同的IV。那么如何使用不同的IV有助于防止密文被破译? – youcanlearnanything

+0

一般不会。 IV主要是为了使密码不确定;如果你要重复(部分)消息,你不想拥有与泄露信息相同的密文。重复的消息很常见。一个可能的例外是SIV(合成IV)模式,其中IV兼作身份验证标签。因此,即使不解密密文,重复使用IV也会泄漏信息。 –