Encryption

limi

Member
Joined
Apr 3, 2007
Messages
8
Programming Experience
Beginner
I've been working on devising out a VB.Net equivalent of the following PL-SQL code which encrypts user password :

VB.NET:
key VARCHAR(16) := 'A1B2C3D4E5F6G7H8';
 encryption_mode NUMBER := DBMS_CRYPTO.ENCRYPT_AES128 +  DBMS_CRYPTO.CHAIN_CBC  + DBMS_CRYPTO.PAD_PKCS5;
 RETURN DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW (data, 'AL32UTF8'), encryption_mode, UTL_I18N.STRING_TO_RAW(key, 'AL32UTF8') );

The above code encrypts the word "kiran" to 411736CFE319B335114510FB196DCD0E

What I've been trying to do is this:

VB.NET:
Dim strText As String
strText = "kiran"
Try
Dim InputByteArray() As Byte = System.Text.Encoding.UTF8.GetBytes(strText)
Dim des As SymmetricAlgorithm = New RijndaelManaged
des.Key = System.Text.Encoding.UTF8.GetBytes("A1B2C3D4E5F6G7H8")
des.Padding = PaddingMode.PKCS7
des.Mode = CipherMode.CBC
Dim ms As New MemoryStream
Dim cs As New CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)
cs.Write(InputByteArray, 0, InputByteArray.Length)
cs.FlushFinalBlock()
 
MsgBox("Encrypted string:" & Convert.ToBase64String(ms.ToArray()))
 
Catch ex As Exception
MsgBox(ex.Message)
End Try

The above code does solid encryption but not the one desired. One obstacle is that in the PL-SQL code, PKCS5 padding is done. Whereas in my case, its PKCS7, as PKCS5 is not natively supported in VB 2005, framework 2.0. Can neone suggest what is to be done to get the desired result ?
 
Padding for PKCS5 and PKCS7 is the same I read several places. (for blocksizes up to 256)

ToBase64String is not the same as the string you posted above, which is concatenated hex values. If you add up the ToString("X2") output of each byte in ms.ToArray you will get the hex string.

One thing I don't get is that you don't use a Initialization Vector (IV), when not doing this a new one is generated each call and you get different encryption output each time, also without using the same IV for decryption you won't be able to restore the data. All symmetric algoritms require both key and IV.
 
John,

Thanks for your post. :)

Padding for PKCS5 and PKCS7 are same? Ok.

And, yeah. Sorry. I forgot to specify the IV. :eek: I added the following for the purpose:

VB.NET:
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] IV() [/SIZE][SIZE=2][COLOR=#0000ff]As [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE][SIZE=2] = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF, &H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}[/SIZE]
[/COLOR][/SIZE]

and also added the following to the code given in my previous post:

VB.NET:
[COLOR=#0000ff][SIZE=2]des.IV=IV[/SIZE][/COLOR]

And finally added up the ToString("X2") output of each byte in ms.toArray.

The final result is C2CD95715AE387B09B666CB3ED82B0FA

What else should I do to get the desired output?
 
I don't know your other language but it looked like you didn't set IV there. From this doc page it looks as this field is optional and defaults 'null', .Net does not have such option for IV. I tried some 0 values for .Net IV from a utf8 string without getting same result as yours. Setting aech byte to 0 for IV does finally give same results as the requested:
VB.NET:
des.IV = New Byte() {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
411736CFE319B335114510FB196DCD0E
Try setting some IV explicitly in db code, it will make your encryption much more secure.
 
John,
Thanx for your wonderful reply. :)
I'm having just one more prob now. As you know, "kiran" gets encrypted as "QRc2z+MZszURRRD7GW3NDg==" and then finally into HEX as "411736CFE319B335114510FB196DCD0E". This gets stored in database. Now, while decrypting, I'm converting it from the HEX value again using the following code:
VB.NET:
[SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] s [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]String[/COLOR][/SIZE][SIZE=2], i [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Integer[/COLOR][/SIZE]
 
[SIZE=2]s = txt1.Text 'The HEX string[/SIZE]
[SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] b(s.Length / 2) [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE]
 
 
[SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2] i = 0 [/SIZE][SIZE=2][COLOR=#0000ff]To[/COLOR][/SIZE][SIZE=2] s.Length - 1 [/SIZE][SIZE=2][COLOR=#0000ff]Step[/COLOR][/SIZE][SIZE=2] 2[/SIZE]
[SIZE=2]b(i / 2) = [/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE][SIZE=2].Parse(s.Substring(i, 2), Globalization.NumberStyles.AllowHexSpecifier)[/SIZE]
[SIZE=2][COLOR=#0000ff]Next[/COLOR][/SIZE]
 
 
[SIZE=2]MsgBox(Convert.ToBase64String(b))[/SIZE]
[/COLOR][/SIZE]

But, instead of generating "QRc2z+MZszURRRD7GW3NDg==" , my code generates "QRc2z+MZszURRRD7GW3NDgA=". :(
Where am I getting wrong?
 
"kiran" doesn't get encrypted as "QRc2z+MZszURRRD7GW3NDg==", it get encrypted as an array of bytes, which you can make a string with either the Convert Base64 or translate to the hex string. These two string have nothing to do with each other and one is not converted from the other. The reverse of the Base64 here is Convert.FromBase64String that returns the original encrypted byte array.

Incidentally, you would have gotten the same Base64 if you sized your byte array correct, it is one byte too long now. But I don't see a reason for you to convert to both these string options.
 
Yes, John. "kiran" gets encrypted as an array of bytes only. Its Base64 conversion produces "QRc2z+MZszURRRD7GW3NDg==". And the HEX string has been generated straightaway from the byte array, using byte by byte Tostring("X2") and adding up, as suggested by you.

Now, the code I gave above converts the HEX string again into an array of bytes. I attempted to make a Base64 conversion on this byte array to generate that "QRc2z....." string just to check that the conversion was ok. But then, the discrepancy was found.

Where did I go wrong? [you may have noticed that the discrepancy occurs in just one position. remaining everything is ok]. And, how should have I sized the byte array?
 
You sized the array one byte too long, to be correct the array must be one byte less (-1), if not the decryption or other handling will operate on wrong byte set. What you did was to divide the string length by two, this gives the count, but as you know arrays are zero-based where first element is 0 and second element 1 and so forth. So if Count=4 the array is sized ar(Count -1) equals ar(3) <- this array has four elements.
 
Finally, I made what I intended to make.
My thankfulness knows no bounds when I look upon the invaluable suggestions and comments you made, John.
Thank you so much. Take care.
 
Back
Top