HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Encrypt Using AES

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
encryptusingaes

Problem

I'm using Microsoft's example
for encrypting/decripting a string. In their example, they are using Tripple DES. I'm trying to convert their code to use AES.

The modified code, listed below, works. However, I am wondering if I need to change anything in the TruncateHash function or in the AES.Key and AES.IV value.

This is all new to me, so I am still learning.

```
Imports System.Security.Cryptography

Public NotInheritable Class AesCrypto

' Private TripleDes As New TripleDESCryptoServiceProvider
' Changed from Triple DES to AES

Private AES As New AesCryptoServiceProvider

Private Function TruncateHash(ByVal key As String, ByVal length As Integer) As Byte()
' Creates a byte array of a specified length from the hash of the specified key.

Dim sha1 As New SHA1CryptoServiceProvider

' Hash the key.
Dim keyBytes() As Byte = System.Text.Encoding.Unicode.GetBytes(key)
Dim hash() As Byte = sha1.ComputeHash(keyBytes)

' Truncate or pad the hash.
ReDim Preserve hash(length - 1)
Return hash
End Function

Sub New(ByVal key As String)
' Initialize the crypto provider.
AES.Key = TruncateHash(key, AES.KeySize \ 8)
AES.IV = TruncateHash("", AES.BlockSize \ 8)
End Sub

Public Function EncryptData(ByVal plaintext As String) As String
' Encrypt the data.

' Convert the plaintext string to a byte array.
Dim plaintextBytes() As Byte =
System.Text.Encoding.Unicode.GetBytes(plaintext)

' Create the stream.
Dim ms As New System.IO.MemoryStream
' Create the encoder to write to the stream.
Dim encStream As New CryptoStream(ms,
AES.CreateEncryptor(),
System.Security.Cryptography.CryptoStreamMode.Write)

' Use the crypto stream to write the byte array to the stream.
encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
encStream.FlushFinalBlock()

' Convert the encrypted stream to a printable string.
Return Convert.ToBase64String(ms.ToArray)
End Function

Publi

Solution

It seems you did a good job getting the same functionality using AES. The problem is that Microsoft is not using good practices themselves.

They confuse a password with a key, and they do not use a good key derivation function such as PBKDF2 (implemented in .NET by the class RFC2898DeriveBytes). This you should only use if you do not have access to a shared AES key, which can just consist of 16 cryptographic random bytes.

Furthermore, they did not use a random IV. The IV has the right size (the block size of the block cipher) but it has been set to a constant value. This means all the security benefits of having an IV are negated. The IV should be a cryptographic random (or at least fully unpredictable to an adversary), and could be written in front of the ciphertext (e.g. by supplying it to the unencrypted stream). Static IV's are only secure if the AES key is randomized or if the plaintext is sufficiently random itself.

They use UTF-16 (incorrectly called Unicode in .NET) to create plaintext bytes from the input. UTF-16 uses 16 bits for each normal character, instead of the 8 bits used by UTF-8. So their encoding method is not very efficient.

Note that if you want to use this in a communication protocol that you may need to add a MAC to protect the integrity and authenticity of the plaintext. If you do not, you may even loose the confidentiality of the plaintext (as the default CBC mode of encryption is vulnerable to padding oracle attacks).

So good job, cannot say the same thing of Microsoft.

Context

StackExchange Code Review Q#40774, answer score: 5

Revisions (0)

No revisions yet.