patternMinor
Vulnerability of Encryption class using AES + HMAC
Viewed 0 times
encryptionvulnerabilityaeshmacusingclass
Problem
I've written an encryption-decryption class that is to be used in my companies commercial web application that will handle sensitive information. The encrypted data will be passed over the internet via HTTPS but even so it needs to be internally secure.
I've tried to follow best practices but I'm limited in that I only have a password available to use as a key. I found what appears to be a good solution here (the second answer) which I've used as a base for this class:
```
'''
''' Class that provides encryption using AES with HMAC for authentication.
'''
'''
Public NotInheritable Class AESHMACEncryption
'See https://stackoverflow.com/questions/202011/encrypt-and-decrypt-a-string/10366194#10366194
'and http://dotnetslackers.com/articles/security/hashing_macs_and_digital_signatures_in_net.aspx
'''
''' Encrypt the given text using the given password and create an authenticated message that can be decrypted by AESHMAC.Decrypt.
'''
''' String
''' String
''' String
''' AES encryption with HMAC.
Shared Function Encrypt(cleartext As String, password As String) As String
'Sanity checks
If password.Length
''' Decrypt a message encrypted using AESHMAC.Encrypt.
'''
''' String
''' String
''' String
''' AES encryption with HMAC.
Public Shared Function Decrypt(encrypted As String, password As String) As String
'Sanity checks
If password.Length 0 Then Throw New Exception("Message does not pass authentication.")
Using cryptoProvider As New AesCryptoServiceProvider() With {
.KeySize = EncryptionSettings.KeyBitSize,
.BlockSize = EncryptionSettings.BlockBitSize,
.Mode = CipherMode.CBC,
.Padding = PaddingMode.PKCS7
}
'Grab IV from message
Dim iv = New Byte(ivLength - 1) {}
Array.Copy(encryptedMessage, SaltsLength, iv, 0, iv.Length)
I've tried to follow best practices but I'm limited in that I only have a password available to use as a key. I found what appears to be a good solution here (the second answer) which I've used as a base for this class:
```
'''
''' Class that provides encryption using AES with HMAC for authentication.
'''
'''
Public NotInheritable Class AESHMACEncryption
'See https://stackoverflow.com/questions/202011/encrypt-and-decrypt-a-string/10366194#10366194
'and http://dotnetslackers.com/articles/security/hashing_macs_and_digital_signatures_in_net.aspx
'''
''' Encrypt the given text using the given password and create an authenticated message that can be decrypted by AESHMAC.Decrypt.
'''
''' String
''' String
''' String
''' AES encryption with HMAC.
Shared Function Encrypt(cleartext As String, password As String) As String
'Sanity checks
If password.Length
''' Decrypt a message encrypted using AESHMAC.Encrypt.
'''
''' String
''' String
''' String
''' AES encryption with HMAC.
Public Shared Function Decrypt(encrypted As String, password As String) As String
'Sanity checks
If password.Length 0 Then Throw New Exception("Message does not pass authentication.")
Using cryptoProvider As New AesCryptoServiceProvider() With {
.KeySize = EncryptionSettings.KeyBitSize,
.BlockSize = EncryptionSettings.BlockBitSize,
.Mode = CipherMode.CBC,
.Padding = PaddingMode.PKCS7
}
'Grab IV from message
Dim iv = New Byte(ivLength - 1) {}
Array.Copy(encryptedMessage, SaltsLength, iv, 0, iv.Length)
Solution
This isn't anything huge or anything,
you can actually get rid of
This variable is only used to return a value, and you don't need to assign the value to this variable before you return it. by creating a variable you are assigning memory that could be used for other things. Encryption applications can get heavy while a couple of empty variables worth of memory may not wipe out the available memory, it is a good habit to break.
Don't create variables that you don't have to.
The value can be returned directly from inside the using statements.
right here
just change it to this instead
just
Same with this
you can do this inside the using statement in a single return statement
just like this
then you get rid of 2 more variables
And
you can actually get rid of
Dim plaintext As StringThis variable is only used to return a value, and you don't need to assign the value to this variable before you return it. by creating a variable you are assigning memory that could be used for other things. Encryption applications can get heavy while a couple of empty variables worth of memory may not wipe out the available memory, it is a good habit to break.
Don't create variables that you don't have to.
The value can be returned directly from inside the using statements.
right here
Using decrypter As ICryptoTransform = cryptoProvider.CreateDecryptor(kspCrypt.Key, iv)
Using plainTextStream As New MemoryStream()
Using decrypterStream As New CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write)
Using binaryWriter As New BinaryWriter(decrypterStream)
'Decrypt Cipher Text from Message
binaryWriter.Write(encryptedMessage, SaltsLength + iv.Length, encryptedMessage.Length - SaltsLength - iv.Length - sentTag.Length)
End Using
End Using
'Return Plain Text
plaintext = Encoding.UTF8.GetString(plainTextStream.ToArray())
End Using
End Usingjust change it to this instead
Using decrypter As ICryptoTransform = cryptoProvider.CreateDecryptor(kspCrypt.Key, iv)
Using plainTextStream As New MemoryStream()
Using decrypterStream As New CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write)
Using binaryWriter As New BinaryWriter(decrypterStream)
'Decrypt Cipher Text from Message
binaryWriter.Write(encryptedMessage, SaltsLength + iv.Length, encryptedMessage.Length - SaltsLength - iv.Length - sentTag.Length)
End Using
End Using
'Return Plain Text
return Encoding.UTF8.GetString(plainTextStream.ToArray())
End Using
End Usingjust
return Encoding.UTF8.GetString(plainTextStream.ToArray())Same with this
Dim encryptedtext As String = Convert.ToBase64String(signed)
Return encryptedtextyou can do this inside the using statement in a single return statement
just like this
return Convert.ToBase64String(encryptedStream.ToArray())then you get rid of 2 more variables
Dim signed As Byte()And
Dim encryptedtext As String = Convert.ToBase64String(signed)Code Snippets
Dim plaintext As StringUsing decrypter As ICryptoTransform = cryptoProvider.CreateDecryptor(kspCrypt.Key, iv)
Using plainTextStream As New MemoryStream()
Using decrypterStream As New CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write)
Using binaryWriter As New BinaryWriter(decrypterStream)
'Decrypt Cipher Text from Message
binaryWriter.Write(encryptedMessage, SaltsLength + iv.Length, encryptedMessage.Length - SaltsLength - iv.Length - sentTag.Length)
End Using
End Using
'Return Plain Text
plaintext = Encoding.UTF8.GetString(plainTextStream.ToArray())
End Using
End UsingUsing decrypter As ICryptoTransform = cryptoProvider.CreateDecryptor(kspCrypt.Key, iv)
Using plainTextStream As New MemoryStream()
Using decrypterStream As New CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write)
Using binaryWriter As New BinaryWriter(decrypterStream)
'Decrypt Cipher Text from Message
binaryWriter.Write(encryptedMessage, SaltsLength + iv.Length, encryptedMessage.Length - SaltsLength - iv.Length - sentTag.Length)
End Using
End Using
'Return Plain Text
return Encoding.UTF8.GetString(plainTextStream.ToArray())
End Using
End Usingreturn Encoding.UTF8.GetString(plainTextStream.ToArray())Dim encryptedtext As String = Convert.ToBase64String(signed)
Return encryptedtextContext
StackExchange Code Review Q#91143, answer score: 3
Revisions (0)
No revisions yet.