2017-07-24 66 views
1

我正在編寫一個加密程序,並希望將多個密碼塊和流模式與哈希機制一起使用。我沒有任何使用OFB等流模式對消息進行加密,解密和驗證的問題,但是當他們使用填充時,我在使用blockcipher moder解密和驗證消息時遇到了問題。在填充和塊密碼模式下使用哈希

例如我使用ECB(我知道它不是很好)與PKCS7Padding和SHA-256。在我解密消息後,它最後有一些字符。除此之外,我收到消息,散列摘要不等於原始摘要。

這個問題不會發生,當我不使用填充。

這裏是我的代碼:

@Override 
public byte[] encrypt(byte[] input) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/ECB/" + getPadding(), "BC"); 
    cipher.init(Cipher.ENCRYPT_MODE, getKey()); 
    byte[] output = getBytesForCipher(cipher, input); 
    int ctLength = cipher.update(input, 0, input.length, output, 0); 
    updateHash(input); 
    cipher.doFinal(getDigest(), 0, getDigest().length, output, ctLength); 
    return output; 
} 

protected byte[] getBytesForCipher(Cipher cipher, byte[] input) { 
    return new byte[cipher.getOutputSize(input.length + hash.getDigestLength())]; 
} 

protected void updateHash(byte[] input) { 
    hash.update(input); 
} 


public byte[] decrypt(byte[] input) throws Exception { 
    Cipher cipher = Cipher.getInstance("AES/ECB/" + getPadding(), "BC"); 
    cipher.init(Cipher.DECRYPT_MODE, getKey()); 
    byte[] output = new byte[cipher.getOutputSize(input.length)]; 
    int ctLength = cipher.update(input, 0, input.length, output, 0); 
    cipher.doFinal(output, ctLength); 
    return removeHash(output); 
} 

protected byte[] removeHash(byte[] output) { 
    int messageLength = output.length - hash.getDigestLength(); 
    hash.update(output, 0, output.length - hash.getDigestLength());; 
    byte[] realOutput = new byte[messageLength]; 
    System.arraycopy(output, 0, realOutput, 0, messageLength); 
    messageValid = isValid(output); 
    return realOutput; 
} 

private boolean isValid(byte[] output) { 
    int messageLength = output.length - hash.getDigestLength(); 
    byte[] messageHash = new byte[hash.getDigestLength()]; 
    System.arraycopy(output, messageLength, messageHash, 0, messageHash.length); 
    return MessageDigest.isEqual(hash.digest(), messageHash); 
} 

我使用BouncyCastle的供應商。

+0

*爲什麼*您是否在使用BC提供程序來實現這種功能?你不喜歡硬件加速?這是應該在默認提供程序上執行的基本功能。 –

回答

2

如果您在CiphergetOutputSize方法來看看你會得到從文檔以下內容:

下一個updatedoFinal調用的實際輸出長度可能小於此方法返回的長度。

而這恰恰是什麼咬你。由於密碼實例在解密前無法確定填充量,因此會假定輸出/明文大小與明文大小相同。實際上,由於始終執行PKCS#7填充,因此它可能會在JCE實現中假設太多一個字節。

所以你不能忽略doFinal的迴應;您需要調整數組大小(例如使用Arrays類),或者從緩衝區中的正確位置抓取明文和散列。

很明顯,流密碼不會有這個問題,因爲明文大小和密文大小是相同的。


通常一個密鑰的散列(即,MAC或HMAC)或認證密碼被用來確保密文未改變。在明文上使用散列可能無法完全保護您的明文。