Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

.NET Encryption Simplified

, 28 Jan 2007
A simple, string-oriented class for symmetric encryption, asymmetric encryption, and hashing.
Imports NUnit.Framework
Imports EncryptionClassLibrary

''' <summary>
''' unit tests for the Encryption class to verify correct operation
''' see http://www.nunit.org/index.html
''' </summary>
''' <remarks>
'''   Jeff Atwood
'''   http://www.codinghorror.com/
''' </remarks>
<TestFixture()> _
Public Class UnitTests

    Private _TargetString As String
    Private _TargetData As Encryption.Data

    <TestFixtureSetUp()> _
    Public Sub Setup()
        _TargetString = "The instinct of nearly all societies is to lock up anybody who is truly free. " & _
            "First, society begins by trying to beat you up. If this fails, they try to poison you. " & _
            "If this fails too, they finish by loading honors on your head." & _
            " - Jean Cocteau (1889-1963)"
        _TargetData = New Encryption.Data(_TargetString)
    End Sub

    <Test(), Category("Hash")> _
    Public Sub SaltedHashes()
        Assert.AreEqual("6CD9DD96", _
            SaltedHash(Encryption.Hash.Provider.CRC32, _
                New Encryption.Data("Shazam!")).ToHex)
        Assert.AreEqual("4F7FA9C182C5FA60F9197F4830296685", _
            SaltedHash(Encryption.Hash.Provider.MD5, _
                New Encryption.Data("SnapCracklePop")).ToHex)
        Assert.AreEqual("3DC330B4E4E61C8DF039EAE93EC16412E22425FB", _
            SaltedHash(Encryption.Hash.Provider.SHA1, _
                New Encryption.Data("全球最大的華文新聞網站", Text.Encoding.Unicode)).ToHex)
        Assert.AreEqual("EFAE307AEE511D6078FDF0D4372F4D0C8135170C5F7626CB19B04BFDBABBBDB2", _
            SaltedHash(Encryption.Hash.Provider.SHA256, _
                New Encryption.Data("!@#$%^&*()_-+=", Text.Encoding.ASCII)).ToHex)
        Assert.AreEqual( _
            "582B31C13EF16D706EC2514FDA08316A369DF1F130D34A0A2A16B065D82662A1101EA01110AB7C8F9022A1CEA76FD6B9", _
            SaltedHash(Encryption.Hash.Provider.SHA384, _
                New Encryption.Data("supercalifragilisticexpialidocious", Text.Encoding.ASCII)).ToHex)
        Assert.AreEqual( _
            "44FAA06E8E80666408304E3458621769699A76B591C6389F958C0DDA1D80A82965D169E8AA7D3C1A0637BCB7B0F45D420389C629D19E255D64A923F6C4F87FD8", _
            SaltedHash(Encryption.Hash.Provider.SHA512, _
                New Encryption.Data("42", Text.Encoding.ASCII)).ToHex)
    End Sub

    <Test(), Category("Hash")> _
    Public Sub HashFile()
        Dim h1 As New Encryption.Hash(Encryption.Hash.Provider.CRC32)
        Dim hashHex As String
        Dim sr As IO.StreamReader = Nothing
        Using sr
            sr = New IO.StreamReader("../gettysburg.txt")
            hashHex = h1.Calculate(sr.BaseStream).ToHex
        End Using
        Assert.AreEqual(hashHex, "E37F6423")


        Dim h2 As New Encryption.Hash(Encryption.Hash.Provider.MD5)
        Try
            sr = New IO.StreamReader("../sample.doc")
            hashHex = h2.Calculate(sr.BaseStream).ToHex
        Finally
            If Not sr Is Nothing Then sr.Close()
        End Try
        Assert.AreEqual(hashHex, "4F32AB797F0FCC782AAC0B4F4E5B1693")
    End Sub

    <Test(), Category("Hash")> _
    Public Sub Hash()
        Assert.AreEqual("AA692113", _
            Hash(Encryption.Hash.Provider.CRC32).ToHex)
        Assert.AreEqual("44D36517B0CCE797FF57118ABE264FD9", _
            Hash(Encryption.Hash.Provider.MD5).ToHex)
        Assert.AreEqual("9E93AB42BCC8F738C7FBB6CCA27A902DC663DBE1", _
            Hash(Encryption.Hash.Provider.SHA1).ToHex)
        Assert.AreEqual("40AF07ABFE970590B2C313619983651B1E7B2F8C2D855C6FD4266DAFD7A5E670", _
            Hash(Encryption.Hash.Provider.SHA256).ToHex)
        Assert.AreEqual("9FC0AFB3DA61201937C95B133AB397FE62C329D6061A8768DA2B9D09923F07624869D01CD76826E1152DAB7BFAA30915", _
            Hash(Encryption.Hash.Provider.SHA384).ToHex)
        Assert.AreEqual("2E7D4B051DD528F3E9339E0927930007426F4968B5A4A08349472784272F17DA5C532EDCFFE14934988503F77DEF4AB58EB05394838C825632D04A10F42A753B", _
            Hash(Encryption.Hash.Provider.SHA512).ToHex)
    End Sub

    Private Function SaltedHash(ByVal p As Encryption.Hash.Provider, ByVal salt As Encryption.Data) As Encryption.Data
        Dim h As New Encryption.Hash(p)
        Return h.Calculate(New Encryption.Data(_TargetString), salt)
    End Function

    Private Function Hash(ByVal p As Encryption.Hash.Provider) As Encryption.Data
        Dim h As New Encryption.Hash(p)
        Return h.Calculate(New Encryption.Data(_TargetString))
    End Function

    <Test(), Category("Asymmetric")> _
    Public Sub Asymmetric()
        Dim secret As String = "Pack my box with five dozen liquor jugs."
        Assert.AreEqual(secret, AsymmetricNewKey(secret))
        Assert.AreEqual(secret, AsymmetricNewKey(secret, 384))
        Assert.AreEqual(secret, AsymmetricNewKey(secret, 512))
        Assert.AreEqual(secret, AsymmetricNewKey(secret, 1024))
        Assert.AreEqual(secret, AsymmetricConfigKey(secret))
        Assert.AreEqual(secret, AsymmetricXmlKey(secret))
    End Sub

    Private Function AsymmetricXmlKey(ByVal secret As String) As String
        Dim publicKeyXml As String = _
            "<RSAKeyValue>" & _
            "<Modulus>0D59Km2Eo9oopcm7Y2wOXx0TRRXQFybl9HHe/ve47Qcf2EoKbs9nkuMmhCJlJzrq6ZJzgQSEbpVyaWn8OHq0I50rQ13dJsALEquhlfwVWw6Hit7qRvveKlOAGfj8xdkaXJLYS1tA06tKHfYxgt6ysMBZd0DIedYoE1fe3VlLZyE=</Modulus>" & _
            "<Exponent>AQAB</Exponent>" & _
            "</RSAKeyValue>"

        Dim privateKeyXml As String = _
            "<RSAKeyValue>" & _
            "<Modulus>0D59Km2Eo9oopcm7Y2wOXx0TRRXQFybl9HHe/ve47Qcf2EoKbs9nkuMmhCJlJzrq6ZJzgQSEbpVyaWn8OHq0I50rQ13dJsALEquhlfwVWw6Hit7qRvveKlOAGfj8xdkaXJLYS1tA06tKHfYxgt6ysMBZd0DIedYoE1fe3VlLZyE=</Modulus>" & _
            "<Exponent>AQAB</Exponent>" & _
            "<P>/1cvDks8qlF1IXKNwcXW8tjTlhjidjGtbT9k7FCYug+P6ZBDfqhUqfvjgLFF/+dAkoofNqliv89b8DRy4gS4qQ==</P>" & _
            "<Q>0Mgq7lyvmVPR1r197wnba1bWbJt8W2Ki8ilUN6lX6Lkk04ds9y3A0txy0ESya7dyg9NLscfU3NQMH8RRVnJtuQ==</Q>" & _
            "<DP>+uwfRumyxSDlfSgInFqh/+YKD5+GtGXfKtO4hu4xF+8BGqJ1YXtkL+Njz2zmADOt5hOr1tigPSQ2EhhIqUnAeQ==</DP>" & _
            "<DQ>M5Ofd28SOjCIwCHjwG+Q8v1qzz3CBNljI6uuEGoXO3ixbkggVRfKcMzg2C6AXTfeZE6Ifoy9OyhvLlHTPiXakQ==</DQ>" & _
            "<InverseQ>yQIJMLdL6kU4VK7M5b5PqWS8XzkgxfnaowRs9mhSEDdwwWPtUXO8aQ9G3zuiDUqNq9j5jkdt77+c2stBdV97ew==</InverseQ>" & _
            "<D>HOpQXu/OFyJXuo2EY43BgRt8bX9V4aEZFRQqrqSfHOp8VYASasiJzS+VTYupGAVqUPxw5V1HNkOyG0kIKJ+BG6BpIwLIbVKQn/ROs7E3/vBdg2+QXKhikMz/4gYx2oEsXW2kzN1GMRop2lrrJZJNGE/eG6i4lQ1/inj1Tk/sqQE=</D>" & _
            "</RSAKeyValue>"

        Dim encryptedData As Encryption.Data
        Dim decryptedData As Encryption.Data
        Dim asym As New Encryption.Asymmetric
        Dim asym2 As New Encryption.Asymmetric

        encryptedData = asym.Encrypt(New Encryption.Data(secret), publicKeyXml)
        decryptedData = asym2.Decrypt(encryptedData, privateKeyXml)

        Return decryptedData.ToString
    End Function

    Private Function AsymmetricConfigKey(ByVal secret As String) As String
        Dim encryptedData As Encryption.Data
        Dim decryptedData As Encryption.Data
        Dim asym As New Encryption.Asymmetric
        Dim asym2 As New Encryption.Asymmetric

        encryptedData = asym.Encrypt(New Encryption.Data(secret))
        decryptedData = asym2.Decrypt(encryptedData)

        Return decryptedData.ToString
    End Function

    Private Function AsymmetricNewKey(ByVal secret As String, Optional ByVal keysize As Integer = 0) As String
        Dim pubkey As New Encryption.Asymmetric.PublicKey
        Dim privkey As New Encryption.Asymmetric.PrivateKey
        Dim encryptedData As Encryption.Data
        Dim decryptedData As Encryption.Data
        Dim asym As New Encryption.Asymmetric
        Dim asym2 As New Encryption.Asymmetric

        If keysize = 0 Then
            asym = New Encryption.Asymmetric
            asym2 = New Encryption.Asymmetric
        Else
            asym = New Encryption.Asymmetric(keysize)
            asym2 = New Encryption.Asymmetric(keysize)
        End If
        asym.GenerateNewKeyset(pubkey, privkey)

        encryptedData = asym.Encrypt(New Encryption.Data(secret), pubkey)
        decryptedData = asym2.Decrypt(encryptedData, privkey)

        Return decryptedData.ToString
    End Function

    <Test(), Category("Symmetric")> _
    Public Sub Symmetric()
        Assert.AreEqual(_TargetString, SymmetricLoopback(Encryption.Symmetric.Provider.DES))
        Assert.AreEqual(_TargetString, SymmetricWithKey(Encryption.Symmetric.Provider.DES))
        Assert.AreEqual(_TargetString, SymmetricLoopback(Encryption.Symmetric.Provider.RC2))
        Assert.AreEqual(_TargetString, SymmetricWithKey(Encryption.Symmetric.Provider.RC2))
        Assert.AreEqual(_TargetString, SymmetricLoopback(Encryption.Symmetric.Provider.Rijndael))
        Assert.AreEqual(_TargetString, SymmetricWithKey(Encryption.Symmetric.Provider.Rijndael))
        Assert.AreEqual(_TargetString, SymmetricLoopback(Encryption.Symmetric.Provider.TripleDES))
        Assert.AreEqual(_TargetString, SymmetricWithKey(Encryption.Symmetric.Provider.TripleDES))
    End Sub

    <Test(), Category("Symmetric")> _
    Public Sub SymmetricFile()
        '-- compare the hash of the decrypted file to what it should be after encryption/decryption
        '-- using pure file streams
        Dim h As New Encryption.Hash(Encryption.Hash.Provider.MD5)
        Assert.AreEqual("AC27F132E6728E4F8FA3B054013D3456", _
            SymmetricFilePrivate(Encryption.Symmetric.Provider.TripleDES, "gettysburg.txt", "Password, Yo!"))
        Assert.AreEqual("4F32AB797F0FCC782AAC0B4F4E5B1693", _
            SymmetricFilePrivate(Encryption.Symmetric.Provider.RC2, "sample.doc", "0nTheDownLow1"))
    End Sub

    Private Function SymmetricFilePrivate(ByVal p As Encryption.Symmetric.Provider, _
        ByVal fileName As String, ByVal key As String) As String

        Dim EncryptedFilePath As String = "../" & IO.Path.GetFileNameWithoutExtension(fileName) & "-encrypted.txt"

        '-- encrypt the file to memory
        Dim sym As New Encryption.Symmetric(p)
        sym.Key = New Encryption.Data(key)
        Dim encryptedData As New Encryption.Data
        Dim sr As IO.StreamReader = Nothing
        Using sr
            sr = New IO.StreamReader("../" & fileName)
            encryptedData = sym.Encrypt(sr.BaseStream)
        End Using

        '-- write encrypted data to a new binary file
        Dim sw As New IO.StreamWriter(EncryptedFilePath)
        Dim bw As New IO.BinaryWriter(sw.BaseStream)
        bw.Write(encryptedData.Bytes)
        bw.Close()

        '-- decrypt this binary file
        Dim decryptedData As Encryption.Data
        Dim sym2 As New Encryption.Symmetric(p)
        sym2.Key = New Encryption.Data(key)
        Try
            sr = New IO.StreamReader(EncryptedFilePath)
            decryptedData = sym.Decrypt(sr.BaseStream)
        Finally
            If Not sr Is Nothing Then sr.Close()
            IO.File.Delete(EncryptedFilePath)
        End Try

        '-- get the MD5 hash of the returned data
        Dim h As New Encryption.Hash(Encryption.Hash.Provider.MD5)
        Return h.Calculate(decryptedData).ToHex
    End Function

    ''' <summary>
    ''' test using user-provided keys and init vectors
    ''' </summary>
    Private Function SymmetricWithKey(ByVal p As Encryption.Symmetric.Provider) As String
        Dim sym As New Encryption.Symmetric(p, False)
        Dim sym2 As New Encryption.Symmetric(p, False)
        Dim encryptedData As Encryption.Data
        Dim decryptedData As Encryption.Data

        Dim keyData As New Encryption.Data("MySecretPassword")
        Dim ivData As New Encryption.Data("MyInitializationVector")

        sym.IntializationVector = ivData
        encryptedData = sym.Encrypt(_TargetData, keyData)
        sym2.IntializationVector = ivData
        decryptedData = sym2.Decrypt(encryptedData, keyData)

        '-- the data will be padded to the encryption blocksize, so we need to trim it back down.
        Return decryptedData.ToString.Substring(0, _TargetData.Bytes.Length)
    End Function

    ''' <summary>
    ''' test using auto-generated keys
    ''' </summary>
    Private Function SymmetricLoopback(ByVal p As Encryption.Symmetric.Provider) As String
        Dim sym As New Encryption.Symmetric(p)
        Dim sym2 As New Encryption.Symmetric(p)
        Dim encryptedData As Encryption.Data
        Dim decryptedData As Encryption.Data

        encryptedData = sym.Encrypt(New Encryption.Data(_TargetString))
        decryptedData = sym2.Decrypt(encryptedData, sym.Key)

        '-- the data will be padded to the encryption blocksize, so we need to trim it back down.
        Return decryptedData.ToString.Substring(0, _TargetData.Bytes.Length)
    End Function

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

wumpus1
Web Developer
United States United States
My name is Jeff Atwood. I live in Berkeley, CA with my wife, two cats, and far more computers than I care to mention. My first computer was the Texas Instruments TI-99/4a. I've been a Microsoft Windows developer since 1992; primarily in VB. I am particularly interested in best practices and human factors in software development, as represented in my recommended developer reading list. I also have a coding and human factors related blog at www.codinghorror.com.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 29 Jan 2007
Article Copyright 2005 by wumpus1
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid