Encrypting/Decrypting Base64 encoded Aes Key with Dpapi Problem

P

Phil C.

Hi. I have the following routine that generates an Aes key and converts it
to a base64 string. The problem is that the returned Base64 string ALways
contains an '=' or 'Equals sign' as the last character which I understand
is the result of padding in the algorithm. However, when I take the
generated key, say:
r50h2Iy4pzXb1wpeBEhZie9wM4JmrE6VXUdGk50+RhY=
and encrypt it with the dpapi on my machine, store it, then decrypt it with
the dpapi,
I get back:
r50h2Iy4pzXb1wpeBEhZie9wM4JmrE6VXUdGk50+RhYA
Any idea why this is happening, and how to correct it? The reason being
that I seem
to get a decryption iv key size error when using the latter key.

Imports System

Imports System.IO

Imports System.Text

Imports System.Security.Cryptography

Public Class KeyAndEntropyGen

Friend Function CreateKey() As String



'Create a new AES Service Provider

Dim aesProvider As New RijndaelManaged

'Declare the key size

aesProvider.KeySize = 256

aesProvider.BlockSize = 256

aesProvider.GenerateKey()

'Dim ucode8 As New UTF8Encoding

'Return ucode8.GetString(aesProvider.Key)

Return Convert.ToBase64String(aesProvider.Key)

'Return unicode string because string is used in webconfig

End Function

Friend Function CreateEntropyValue() As String

Dim rng As New RNGCryptoServiceProvider

Dim rng256EntropyByteValue(32) As Byte

rng.GetBytes(rng256EntropyByteValue)

Return Convert.ToBase64String(rng256EntropyByteValue)

End Function

End Class
 
D

Dominick Baier [DevelopMentor]

Hello Phil C.,

i would encrypt the key first and then convert it to base64 - DPAPI takes
a byte[] as input...
 
P

Phil C.

Dominick,
I generated the key directly without retrieving it from anywhere,encrypted
the key and saved it as a byte array in a shared field/property
and also saved the init vector as a byte array in a shared field/property.
Now I can encrypt, but get a Pkcs7 error upon decryption:

WEB PAGE VB for testing encryption/decryption:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Public Class EncryptDecryptAesWithDpapi

Inherits System.Web.UI.Page

Dim aesCC As New AesCryptClass

Private Shared _savedIVAsByteArray(31) As Byte

Private Shared _savedCipherText As Byte()

Public Shared Property savedCipherText() As Byte()

Get

Return _savedCipherText

End Get

Set(ByVal Value As Byte())

_savedCipherText = Value

End Set

End Property

Public Shared Property savedIVAsByteArray() As Byte()

Get

Return _savedIVAsByteArray

End Get

Set(ByVal Value As Byte())

_savedIVAsByteArray = Value

End Set

End Property

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

End Sub

Protected WithEvents cleartextTextBox As System.Web.UI.WebControls.TextBox

Protected WithEvents ciphertextTextBox As System.Web.UI.WebControls.TextBox

Protected WithEvents encryptButton As System.Web.UI.WebControls.Button

Protected WithEvents decryptButton As System.Web.UI.WebControls.Button

Protected WithEvents initializationVectorLabel As
System.Web.UI.WebControls.Label

Protected WithEvents initializationVectorTextBox As
System.Web.UI.WebControls.TextBox

Protected WithEvents Textbox1 As System.Web.UI.WebControls.TextBox

Protected WithEvents Textbox2 As System.Web.UI.WebControls.TextBox

Protected WithEvents Button1 As System.Web.UI.WebControls.Button

Protected WithEvents Button2 As System.Web.UI.WebControls.Button

Protected WithEvents receivedIVTextBox As System.Web.UI.WebControls.TextBox

'NOTE: The following placeholder declaration is required by the Web Form
Designer.

'Do not delete or move it.

Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init

'CODEGEN: This method call is required by the Web Form Designer

'Do not modify it using the code editor.

InitializeComponent()

End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

'Put user code to initialize the page here

If Not Page.IsPostBack Then

Dim keyGen As New KeyAndEntropyGen

aesCC.key() = keyGen.CreateKey

End If

End Sub

Private Sub encryptButton_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles encryptButton.Click

savedCipherText() = aesCC.Encrypt(cleartextTextBox.Text.TrimEnd())

ciphertextTextBox.Text = Convert.ToBase64String(savedCipherText)

ciphertextTextBox.Text.TrimEnd()

savedIVAsByteArray = aesCC.initVector()

initializationVectorTextBox.Text =
Convert.ToBase64String(aesCC.initVector())

initializationVectorTextBox.Text.TrimEnd()

End Sub



Private Sub decryptButton_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles decryptButton.Click

aesCC.initVector() = savedIVAsByteArray()

receivedIVTextBox.Text = Convert.ToBase64String(savedIVAsByteArray())

cleartextTextBox.Text = aesCC.Decrypt(savedCipherText())



cleartextTextBox.Text.TrimEnd()

End Sub

End Class

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

''AES CRYPT CLASS FOR ABOVE:

Imports System

Imports System.IO

Imports System.Text

Imports System.Security.Cryptography

Public Class AesCryptClass

'Dim utf8encoder As New UTF8Encoding

'Attributes to hold key and IV

'Private _key() As Byte =
utf8encoder.GetBytes(Processor.configHandler.AesKeyString())

'Private Shared _key() As Byte =
Convert.FromBase64String(Processor.configHandler.AesKeyString())

Private Shared _key(31) As Byte

' _key =
Convert.FromBase64String(ConfigurationSettings.AppSettings("AeInfo")

'Private Shared _key As Byte() =
Convert.FromBase64String(ConfigurationSettings.AppSettings("AeInfo"))

Private Shared _initVector(31) As Byte

'-------------Public properties to access private attributes


Public Shared Property key() As Byte()

Get

Return _key

End Get

Set(ByVal Value As Byte())

_key = Value

End Set

End Property

Public Shared Property initVector() As Byte()

Get

Return _initVector

End Get

Set(ByVal Value As Byte())

_initVector = Value

End Set

End Property

'--------------------------Function Encrypt---------------------------

Friend Function Encrypt(ByVal plainText As String) As Byte()

'_key =
Convert.FromBase64String(ConfigurationSettings.AppSettings("AeInfo"))

Dim inputInBytes() As Byte = Encoding.UTF8.GetBytes(plainText)



'Create a new AES Service Provider

Dim aesProvider As New RijndaelManaged

'Declare the key size

aesProvider.Padding = PaddingMode.PKCS7

aesProvider.KeySize = 256

aesProvider.BlockSize = 256







aesProvider.GenerateIV()

initVector() = aesProvider.IV



'The ICryptTransform interface uses the Aes crypt provider along with

'encryption key and initialization vector info

'Generate an ICryptoTransform object with the provider create encryptor

Dim cryptoTransform As ICryptoTransform = aesProvider.CreateEncryptor()

' Crypto functions need a stream to output the encrypted info.

'We want to use a memory stream

Dim encryptedStream As New MemoryStream

Dim cryptStream As New CryptoStream(encryptedStream, cryptoTransform,
CryptoStreamMode.Write)

'Write the encrypted information to he stream. Flush the information

'When done to ensure everything is out of the buffer.

cryptStream.Write(inputInBytes, 0, inputInBytes.Length)

cryptStream.FlushFinalBlock()

encryptedStream.Position = 0

'Read the stream back into a byte array and return it

Dim result(encryptedStream.Length - 1) As Byte

encryptedStream.Read(result, 0, encryptedStream.Length)



encryptedStream.Close()

cryptStream.Close()

Return result

End Function

'---------------------------End Function Encrypt



'----------------------------Function Decrypt

Friend Function Decrypt(ByVal inputInBytes() As Byte) As String

'UTFEncoding is used to transform the decrypted Byte Array

'information back into a string.

Dim aesProvider As New RijndaelManaged

aesProvider.Padding = PaddingMode.PKCS7

'Declare the key size

aesProvider.KeySize = 256

aesProvider.BlockSize = 256



'Get the crypto transform object from the provider given the

'key and iv vector

Dim cryptoTransform As ICryptoTransform = aesProvider.CreateDecryptor(key,
initVector())

'Provide memory stream

Dim decryptedStream As New MemoryStream

Dim cryptStream As New CryptoStream(decryptedStream, cryptoTransform,
CryptoStreamMode.Write)

cryptStream.Write(inputInBytes, 0, inputInBytes.Length)

cryptStream.FlushFinalBlock()

decryptedStream.Position = 0

'Read the memory stream and convert it back to a string

Dim result(decryptedStream.Length - 1) As Byte

decryptedStream.Read(result, 0, decryptedStream.Length)



decryptedStream.Close()

cryptStream.Close()

Return Encoding.UTF8.GetString(result)



End Function

End Class

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

''Aes Keygen Class:

Imports System

Imports System.IO

Imports System.Text

Imports System.Security.Cryptography

Public Class KeyAndEntropyGen

Friend Function CreateKey() As Byte()



'Create a new AES Service Provider

Dim aesProvider As New RijndaelManaged

'Declare the key size

aesProvider.KeySize = 256

aesProvider.BlockSize = 256

aesProvider.GenerateKey()

Return (aesProvider.Key)

End Function

Friend Function CreateEntropyValue() As String

Dim rng As New RNGCryptoServiceProvider

Dim rng256EntropyByteValue(32) As Byte

rng.GetBytes(rng256EntropyByteValue)

Return Convert.ToBase64String(rng256EntropyByteValue)

End Function

End Class



'''''''''''''''''''''''''''''''''''''''''''''''''''





Dominick Baier said:
Hello Phil C.,

i would encrypt the key first and then convert it to base64 - DPAPI takes
a byte[] as input...

---------------------------------------
Dominick Baier - DevelopMentor
http://www.leastprivilege.com
Hi. I have the following routine that generates an Aes key and
converts it
to a base64 string. The problem is that the returned Base64 string
ALways
contains an '=' or 'Equals sign' as the last character which I
understand
is the result of padding in the algorithm. However, when I take the
generated key, say:
r50h2Iy4pzXb1wpeBEhZie9wM4JmrE6VXUdGk50+RhY=
and encrypt it with the dpapi on my machine, store it, then decrypt it
with
the dpapi,
I get back:
r50h2Iy4pzXb1wpeBEhZie9wM4JmrE6VXUdGk50+RhYA
Any idea why this is happening, and how to correct it? The reason
being
that I seem
to get a decryption iv key size error when using the latter key.
Imports System

Imports System.IO

Imports System.Text

Imports System.Security.Cryptography

Public Class KeyAndEntropyGen

Friend Function CreateKey() As String

'Create a new AES Service Provider

Dim aesProvider As New RijndaelManaged

'Declare the key size

aesProvider.KeySize = 256

aesProvider.BlockSize = 256

aesProvider.GenerateKey()

'Dim ucode8 As New UTF8Encoding

'Return ucode8.GetString(aesProvider.Key)

Return Convert.ToBase64String(aesProvider.Key)

'Return unicode string because string is used in webconfig

End Function

Friend Function CreateEntropyValue() As String

Dim rng As New RNGCryptoServiceProvider

Dim rng256EntropyByteValue(32) As Byte

rng.GetBytes(rng256EntropyByteValue)

Return Convert.ToBase64String(rng256EntropyByteValue)

End Function

End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top