Welcome Guest!
 VB Helper
 Previous Message All Messages Next Message 
VB Helper Newsletter  Rod Stephens
 Jun 01, 2010 11:13 PDT 

Thanks to everyone who entered the drawing for my new C# book. If you're
a winner, you should have recently received an email asking you to send
me your snail-mail address. Please get me those as soon as possible.

Learn more about the book at

    http://www.csharphelper.com/24hour.html
-----
If you have a copy of any of my other books, please post reviews when
you have a chance. Books live and die based on their reviews!
-----
Have a great week and Thanks for subscribing!

Rod
RodSte-@vb-helper.com

Twitter feeds:
    VBHelper
    CSharpHelper
----------
==========

    VB.NET Contents:
1. New HowTo: Generate random strings in Visual Basic .NET
2. New HowTo: Encrypt or decrypt files in Visual Basic .NET
3. New HowTo: Make a extension methods that encrypt and decrypt strings
in Visual Basic .NET
4. New HowTo: Use the StringBuilder class to concatenate strings quickly
in Visual Basic .NET
==========
++++++++++
<VB.NET>
++++++++++
==========
1. New HowTo: Generate random strings in Visual Basic .NET
http://www.vb-helper.com/howto_net_random_strings.html
http://www.vb-helper.com/HowTo/howto_net_random_strings.zip

The Random class's Next method generates random numbers. To make random
words, make an array of letters. Then use a Random object to pick one of
the letters to add to the word. Repeat until the word is as long as you
need.

When you enter the number of words and the word length and click Go, the
following code generates the random words and adds them to a ListBox.
(In a real program you might want to do something else with the words
such as write them into a file or put them in a list or array.)

' Make the random words.
Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnGo.Click
    lstWords.Items.Clear()

    ' Get the number of words and letters per word.
    Dim num_letters As Integer = Integer.Parse(txtNumLetters.Text)
    Dim num_words As Integer = Integer.Parse(txtNumWords.Text)

    ' Make an array of the letters we will use.
    Dim letters() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()

    ' Make a random number generator.
    Dim rand As New Random()

    ' Make the words.
    For i As Integer = 1 To num_words
        ' Make a word.
        Dim word As String = ""
        For j As Integer = 1 To num_letters
            ' Pick a random number between 0 and 25
            ' to select a letter from the letters array.
            Dim letter_num As Integer = rand.Next(0, letters.Length - 1)

            ' Append the letter.
            word &= letters(letter_num)
        Next j

        ' Add the word to the list.
        lstWords.Items.Add(word)
    Next i
End Sub
==========
2. New HowTo: Encrypt or decrypt files in Visual Basic .NET
http://www.vb-helper.com/howto_net_crypt_file.html
http://www.vb-helper.com/HowTo/howto_net_crypt_file.zip

The CryptFile method encrypts or decrypts a file into an output file at
a fairly high level. The EncryptFile and DecryptFile methods simply call
CryptFile.

' Encrypt or decrypt a file, saving the results in another file.
Public Sub EncryptFile(ByVal password As String, ByVal in_file As
String, ByVal out_file As String)
    CryptFile(password, in_file, out_file, True)
End Sub
Public Sub DecryptFile(ByVal password As String, ByVal in_file As
String, ByVal out_file As String)
    CryptFile(password, in_file, out_file, False)
End Sub
Public Sub CryptFile(ByVal password As String, ByVal in_file As String,
ByVal out_file As String, ByVal encrypt As Boolean)
    ' Create input and output file streams.
    Using in_stream As New FileStream(in_file, FileMode.Open,
FileAccess.Read)
        Using out_stream As New FileStream(out_file, FileMode.Create,
FileAccess.Write)
            ' Encrypt/decrypt the input stream into the output stream.
            CryptStream(password, in_stream, out_stream, encrypt)
        End Using
    End Using
End Sub

The CryptStream method does all of the real work.

' Encrypt the data in the input stream into the output stream.
Public Sub CryptStream(ByVal password As String, ByVal in_stream As
Stream, ByVal out_stream As Stream, ByVal encrypt As Boolean)
    ' Make an AES service provider.
    Dim aes_provider As New AesCryptoServiceProvider()

    ' Find a valid key size for this provider.
    Dim key_size_bits As Integer = 0
    For i As Integer = 1024 To 1 Step -1
        If (aes_provider.ValidKeySize(i)) Then
            key_size_bits = i
            Exit For
        End If
    Next i
    Debug.Assert(key_size_bits > 0)
    Console.WriteLine("Key size: " & key_size_bits)

    ' Get the block size for this provider.
    Dim block_size_bits As Integer = aes_provider.BlockSize

    ' Generate the key and initialization vector.
    Dim key() As Byte = Nothing
    Dim iv() As Byte = Nothing
    Dim salt() As Byte = {&H0, &H0, &H1, &H2, &H3, &H4, &H5, &H6, &HF1,
&HF0, &HEE, &H21, &H22, &H45}
    MakeKeyAndIV(password, salt, key_size_bits, block_size_bits, key,
iv)

    ' Make the encryptor or decryptor.
    Dim crypto_transform As ICryptoTransform
    If (encrypt) Then
        crypto_transform = aes_provider.CreateEncryptor(key, iv)
    Else
        crypto_transform = aes_provider.CreateDecryptor(key, iv)
    End If

    ' Attach a crypto stream to the output stream.
    ' Closing crypto_stream sometimes throws an
    ' exception if the decryption didn't work
    ' (e.g. if we use the wrong password).
    Try
        Using crypto_stream As New CryptoStream(out_stream,
crypto_transform, CryptoStreamMode.Write)
            ' Encrypt or decrypt the file.
            Const block_size As Integer = 1024
            Dim buffer(block_size) As Byte
            Dim bytes_read As Integer
            Do
                ' Read some bytes.
                bytes_read = in_stream.Read(buffer, 0, block_size)
                If (bytes_read = 0) Then Exit Do

                ' Write the bytes into the CryptoStream.
                crypto_stream.Write(buffer, 0, bytes_read)
            Loop
        End Using
    Catch
    End Try

    crypto_transform.Dispose()
End Sub

The basic idea is to make a cryptographic service provider and attach it
to a stream. As you write into the stream, the provider automatically
encrypts or decrypts the data. The details are in creating and
initializing the provider.

The method creates a new AesCryptoServiceProvider to use the AES
encryption method.

Next the program must make a key and initialization vector (IV) to
initialize the service provider. It starts by finding a supported key
size. It starts with a key size of 1,024 and reduces it until the
provider's ValidKeySize method returns true. The keyt size you get will
depend on things such as which version of Windows you are using.

Note: If you will encrypt and decrypt files on different computers, they
must be able to use the same key size. You may need to set this value
yourself if one computer can use a larger key than the other.

The program then calls the MakeKeyAndIV method described shortly to
create a key and IV. The salt is an array of pseudo-random bytes that
you initialize to make breaking the code with a dictionary attack
harder. Pick your own set of values for this, don't use the values shown
here.

The method then creates an encryptor or decryptor, depending on whether
it must encrypt or decrypt the file.

The rest of the method looks messy but is straightforward. It makes a
CryptoStream that associates the encryptor/decryptor with the output
stream and then writes into the stream.

The following code shows the MakeKeyAndIV method.

' Use the password to generate key bytes.
Private Sub MakeKeyAndIV(ByVal password As String, ByVal salt() As Byte,
ByVal key_size_bits As Integer, ByVal block_size_bits As Integer, ByRef
key() As Byte, ByRef iv() As Byte)
    Dim derive_bytes As New Rfc2898DeriveBytes(password, salt, 1000)

    key = derive_bytes.GetBytes(key_size_bits / 8)
    iv = derive_bytes.GetBytes(block_size_bits / 8)
End Sub

This code creates a new Rfc2898DeriveBytes object, passing its
constructor your password, salt, and an iteration number. The object
applies its operation the indicated number of times to make its result
"more random." In this case, it applies a pseudo-random number generator
based on the HMACSHA1 algorithm 1000 times to generate its bytes.

The method then uses the object's GetBytes methods to get the key and IV
that the program needs to initialize the cryptographic service provider.

*** Very Important Note *** Never store a password inside a program. If
you do, then a clever attacker can break open your program, read the
password, and decrypt whatever the program wants to keep secret. This is
particularly easy for .NET programs where it's relatively easy to read
the program's IL code. A much better approach is to make the user enter
the password at run time.

Also note that the password must match exactly to decode a file. If the
password is off by even a single character, the result will be complete
gibberish.
==========
3. New HowTo: Make a extension methods that encrypt and decrypt strings
in Visual Basic .NET
http://www.vb-helper.com/howto_net_crypto_string_extension.html
http://www.vb-helper.com/HowTo/howto_net_crypto_string_extension.zip

The .NET cryptography methods work most naturally with streams or byte
arrays not strings. To make working with strings easier, this program
defines extension methods that convert between byte arrays and strings
containing hexadecimal values. Then when a program encrypts a string
into an array of bytes, it can display the result as a hexadecimal
string.


' Convert a byte array into a readable string of hexadecimal values.
<Extension()> _
Public Function ToHex(ByVal the_bytes() As Byte) As String
    Return ToHex(the_bytes, False)
End Function
<Extension()> _
Public Function ToHex(ByVal the_bytes() As Byte, ByVal add_spaces As
Boolean) As String
    Dim result As String = ""
    Dim separator As String = ""
    If (add_spaces) Then separator = " "
    For i As Integer = 0 To the_bytes.Length - 1
        result &= the_bytes(i).ToString("x2") & separator
    Next i
    Return result
End Function

' Convert a string containing 2-digit hexadecimal values into a byte
array.
<Extension()> _
Public Function ToBytes(ByVal the_string As String) As Byte()
    Dim the_bytes As New List(Of Byte)()
    the_string = the_string.Replace(" ", "")

    For i As Integer = 0 To the_string.Length - 1 Step 2
        the_bytes.Add( _
            Byte.Parse(the_string.Substring(i, 2), _
                System.Globalization.NumberStyles.HexNumber))
    Next i
    Return the_bytes.ToArray()
End Function

The real cryptographic work is done by the CryptBytes method.

' Encrypt or decrypt the data in in_bytes[] and return the result.
Public Function CryptBytes(ByVal password As String, ByVal in_bytes() As
Byte, ByVal encrypt As Boolean) As Byte()
    ' Make an AES service provider.
    Dim aes_provider As New AesCryptoServiceProvider()

    ' Find a valid key size for this provider.
    Dim key_size_bits As Integer = 0
    For i As Integer = 1024 To 1 Step -1
        If (aes_provider.ValidKeySize(i)) Then
            key_size_bits = i
            Exit For
        End If
    Next i
    Debug.Assert(key_size_bits > 0)
    Console.WriteLine("Key size: " & key_size_bits)

    ' Get the block size for this provider.
    Dim block_size_bits As Integer = aes_provider.BlockSize

    ' Generate the key and initialization vector.
    Dim key() As Byte = Nothing
    Dim iv() As Byte = Nothing
    Dim salt() As Byte = {&H0, &H0, &H1, &H2, &H3, &H4, &H5, &H6, &HF1,
&HF0, &HEE, &H21, &H22, &H45}
    MakeKeyAndIV(password, salt, key_size_bits, block_size_bits, key,
iv)

    ' Make the encryptor or decryptor.
    Dim crypto_transform As ICryptoTransform
    If (encrypt) Then
        crypto_transform = aes_provider.CreateEncryptor(key, iv)
    Else
        crypto_transform = aes_provider.CreateDecryptor(key, iv)
    End If

    ' Create the output stream.
    Using out_stream As New MemoryStream()
        ' Attach a crypto stream to the output stream.
        Using crypto_stream As New CryptoStream(out_stream, _
                crypto_transform, CryptoStreamMode.Write)
            ' Write the bytes into the CryptoStream.
            crypto_stream.Write(in_bytes, 0, in_bytes.Length)
            Try
                crypto_stream.FlushFinalBlock()
            Catch ex As CryptographicException
                ' Ignore this exception. The password is bad.
            Catch
                ' Re-throw this exception.
                Throw
            End Try

            ' return the result.
            Return out_stream.ToArray()
        End Using
    End Using
End Function


The basic idea is to make a cryptographic service provider and attach it
to a stream. As you write into the streamm, the provider automatically
encrypts or decrypts the data. The details are in creating and
initializing the provider.

The method creates a new AesCryptoServiceProvider to use the AES
encryption method.

Next the program must make a key and initialization vector (IV) to
initialize the service provider. It starts by finding a supported key
size. It starts with a key size of 1,024 and reduces it until the
provider's ValidKeySize method returns true. The key size you get will
depend on things such as which version of Windows you are using.

Note: If you will encrypt and decrypt files on different computers, they
must be able to use the same key size. You may need to set this value
yourself if one computer can use a larger key than the other.

The program then calls the MakeKeyAndIV method described shortly to
create a key and IV. The salt is an array of pseudo-random bytes that
you initialize to make breaking the code with a dictionary attack
harder. Pick your own set of values for this, don't use the values shown
here.

The method then creates an encryptor or decryptor, depending on whether
it must encrypt or decrypt the file.

The rest of the method looks messy but is straightforward. It makes an
output MemoryStream, associates it with the encryptor/decryptor, and
then writes into the stream.

The following code shows the MakeKeyAndIV method.

' Use the password to generate key bytes.
Private Sub MakeKeyAndIV(ByVal password As String, ByVal salt() As Byte,
ByVal key_size_bits As Integer, ByVal block_size_bits As Integer, ByRef
key() As Byte, ByRef iv() As Byte)
    Dim derive_bytes As New Rfc2898DeriveBytes(password, salt, 1000)

    key = derive_bytes.GetBytes(key_size_bits / 8)
    iv = derive_bytes.GetBytes(block_size_bits / 8)
End Sub

This code creates a new Rfc2898DeriveBytes object, passing its
constructor your password, salt, and an iteration number. The object
applies its operation the indicated number of times to make its result
"more random." In this case, it applies a pseudo-random number generator
based on the HMACSHA1 algorithm 1000 times to generate its bytes.

The method then uses the object's GetBytes methods to get the key and IV
that the program needs to initialize the cryptographic service provider.

*** Very Important Note *** Never store a password inside a program. If
you do, then a clever attacker can break open your program, read the
password, and decrypt whatever the program wants to keep secret. This is
particularly easy for .NET programs where it's relatively easy to read
the program's IL code. A much better approach is to make the user enter
the password at run time.

Also note that the password must match exactly to decode a file. If the
password is off by even a single character, the result will be complete
gibberish.
==========
4. New HowTo: Use the StringBuilder class to concatenate strings quickly
in Visual Basic .NET
http://www.vb-helper.com/howto_net_use_stringbuilder.html
http://www.vb-helper.com/HowTo/howto_net_use_stringbuilder.zip

The example "Generate random strings in Visual Basic .NET"
(http://www.vb-helper.com/howto_net_random_strings.html) uses code
similar to the following to generate a random string of letters.

' Make a word.
Dim word As String = ""
For j As Integer = 1 To num_letters
    ' Pick a random number between 0 and 25
    ' to select a letter from the letters array.
    Dim letter_num As Integer = rand.Next(0, _
        letters.Length - 1)

    ' Append the letter.
    word &= letters(letter_num)
Next j

It may look like this code creates a single string but actually as it
builds its result it creates a whole bunch of strings. For reasons of
its own, .NET strings are immutable. That means you can never modify a
string. Your code may look like it modifies a string but internally .NET
destroys the old string and creates a new one.

In this example if num_letters is 10, then this code actually creates 11
strings. It starts with an empty string and adds the 10 letters one at a
time, creating a new string each time.

The .NET Framework is optimized to make creating and destroying lots of
strings reasonably fast but it still takes more time than it would if
strings were implemented as simple arrays of characters.

The StringBuilder class manages a buffer of characters without turning
them into a string so it can perform operations such as appending text
more quickly than .NET can create a new string.

The following code does the same thing as the previous version except it
use a StringBuilder instead of using &= to concatenate letters to its
strings.

' Make a word.
Dim string_builder As New StringBuilder()
For j As Integer = 1 To num_letters
    ' Pick a random number between 0 and 25
    ' to select a letter from the letters array.
    Dim letter_num As Integer = rand.Next(0, letters.Length - 1)

    ' Append the letter.
    string_builder.Append(letters(letter_num))
Next j

There is some overhead to creating a StringBuilder object so it's not
always faster. The class is most useful when you need to perform a very
large number of operations on strings.

Note that both the &= and StringBuilder methods are very fast. In the
example shown in the picture, the "slow" &= method took around 3.5
seconds to generate 1 million strings while StringBuilder took around
1.9 seconds. That means using StringBuilder saved only about 1.6
microseconds per string.

The moral is that you should generally use whichever method you find
least confusing unless you're performing a *huge* number of string
operations. I find &= easier to read so I use it most of the time.
==========
Archives:
    http://www.topica.com/lists/VBHelper
    http://www.topica.com/lists/VB6Helper
    http://www.topica.com/lists/VBNetHelper

Twitter feeds:
    VBHelper
    CSharpHelper

Post questions at:
    http://www.topica.com/lists/VBHelperQA
	
 Previous Message All Messages Next Message 
  Check It Out!

  Topica Channels
 Best of Topica
 Art & Design
 Books, Movies & TV
 Developers
 Food & Drink
 Health & Fitness
 Internet
 Music
 News & Information
 Personal Finance
 Personal Technology
 Small Business
 Software
 Sports
 Travel & Leisure
 Women & Family

  Start Your Own List!
Email lists are great for debating issues or publishing your views.
Start a List Today!

© 2001 Topica Inc. TFMB
Concerned about privacy? Topica is TrustE certified.
See our Privacy Policy.