| 网站首页 | VB.Net实例分析 | .Net技术文摘 | 下载中心 | VB.Net书籍笔记 | .Net源码 | VBS脚本与组件调用 | Windows2008技术文摘 | 给我们留言 | 
最新公告:

  没有公告

您现在的位置: 乐博网 >> VB.Net实例分析 >> 加密压缩编程 >> 实例分析正文
最新推荐 更多内容
[图文]Salt加密数据的.Net实例
Salt加密数据的.Net实例
作者:obviex    来源:obviex的博客     更新时间:2009-10-14

Salt加密数据的.Net实例

效果图:

 

代码如下:

'------------------------------------------------------------------------------
' SAMPLE: Illustrates symmetric key encryption and decryption using Rijndael
'         algorithm. In addition to performing encryption, this sample 
'         explains how to add a salt value (randomly generated bytes) to 
'         plain text before the value is encrypted. This can help reduce the
'         risk of dictionary attacks.
'
' To run this sample, create a new Visual Basic.NET project using the Console 
' Application template and replace the contents of the Module1.vb file with
' the code below.
'
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
'
' Copyright (C) 2003 Obviex(TM). All rights reserved.
'
Option Strict Off
 
Imports System
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports Microsoft.VisualBasic
 
Module Module1
 
' <summary>
' This class uses a symmetric key algorithm (Rijndael/AES) to encrypt and
' decrypt data. As long as it is initialized with the same constructor
' parameters, the class will use the same key. Before performing encryption,
' the class can prepend random bytes to plain text and generate different
' encrypted values from the same plain text, encryption key, initialization
' vector, and other parameters. This class is thread-safe.
' </summary>
' <remarks>
' Be careful when performing encryption and decryption. There is a bug
' ("feature"?) in .NET Framework, which causes corruption of encryptor/
' decryptor if a cryptographic exception occurs during encryption/
' decryption operation. To correct the problem, re-initialize the class
' instance when a cryptographic exception occurs.
' </remarks>
Public Class RijndaelEnhanced
 
    ' If hashing algorithm is not specified, use SHA-1.
    Private Shared Dim DEFAULT_HASH_ALGORITHM As String = "SHA1"
 
    ' If key size is not specified, use the longest 256-bit key.
    Private Shared Dim DEFAULT_KEY_SIZE       As Integer= 256
 
    ' Do not allow salt to be longer than 255 bytes, because we have only
    ' 1 byte to store its length. 
    Private Shared Dim MAX_ALLOWED_SALT_LEN   As Integer= 255
 
    ' Do not allow salt to be smaller than 4 bytes, because we use the first
    ' 4 bytes of salt to store its length. 
    Private Shared Dim MIN_ALLOWED_SALT_LEN   As Integer= 4
 
    ' Random salt value will be between 4 and 8 bytes long.
    Private Shared Dim DEFAULT_MIN_SALT_LEN   As Integer= MIN_ALLOWED_SALT_LEN
    Private Shared Dim DEFAULT_MAX_SALT_LEN   As Integer= 8
 
    ' Use these members to save min and max salt lengths.
    Private Dim minSaltLen As Integer = -1
    Private Dim maxSaltLen As Integer = -1
 
    ' These members will be used to perform encryption and decryption.
    Private Dim encryptor As ICryptoTransform = Nothing
    Private Dim decryptor As ICryptoTransform = Nothing
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption with 256-bit key, derived using 1 password iteration,
    ' hashing without salt, no initialization vector, electronic codebook
    ' (ECB) mode, SHA-1 hashing algorithm, and 4-to-8 byte long salt.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <remarks>
    ' This constructor is not recommended because it does not use
    ' initialization vector and uses the ECB cipher mode, which is less
    ' secure than the CBC mode.
    ' </remarks>
    Public Sub New(passPhrase As String)
        Me.New(passPhrase, Nothing)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption with 256-bit key, derived using 1 password iteration,
    ' hashing without salt, cipher block chaining (CBC) mode, SHA-1
    ' hashing algorithm, and 4-to-8 byte long salt.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    Public Sub New(passPhrase  As String, _
                   initVector  As String)
        Me.New(passPhrase, initVector, -1)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption with 256-bit key, derived using 1 password iteration,
    ' hashing without salt, cipher block chaining (CBC) mode, SHA-1 
    ' hashing algorithm, and 0-to-8 byte long salt.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    Public Sub New(passPhrase  As String, _
                   initVector  As String, _
                   minSaltLen  As Integer)
        Me.New(passPhrase, initVector, minSaltLen, -1)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption with 256-bit key, derived using 1 password iteration,
    ' hashing without salt, cipher block chaining (CBC) mode, SHA-1
    ' hashing algorithm. Use the minSaltLen and maxSaltLen parameters to
    ' specify the size of randomly generated salt.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    ' <param name="maxSaltLen">
    ' Max size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is negative or greater than 255, the default max value will be
    ' used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
    ' than the specified min value (which can be adjusted to default value),
    ' salt will not be used and plain text value will be encrypted as is.
    ' In this case, salt will not be processed during decryption either.
    ' </param>
    Public Sub New(passPhrase  As String,  _
                   initVector  As String,  _
                   minSaltLen  As Integer, _
                   maxSaltLen  As Integer)
        Me.New(passPhrase, initVector, minSaltLen, maxSaltLen, -1)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption using the key derived from 1 password iteration,
    ' hashing without salt, cipher block chaining (CBC) mode, and
    ' SHA-1 hashing algorithm.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    ' <param name="maxSaltLen">
    ' Max size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is negative or greater than 255, the default max value will be 
    ' used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
    ' than the specified min value (which can be adjusted to default value),
    ' salt will not be used and plain text value will be encrypted as is.
    ' In this case, salt will not be processed during decryption either.
    ' </param>
    ' <param name="keySize">
    ' Size of symmetric key (in bits): 128, 192, or 256.
    ' </param>
    Public Sub New(passPhrase  As String,  _
                   initVector  As String,  _
                   minSaltLen  As Integer, _
                   maxSaltLen  As Integer, _
                   keySize     As Integer)
        Me.New(passPhrase, initVector, minSaltLen, maxSaltLen, keySize, _
               Nothing)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption using the key derived from 1 password iteration, hashing 
    ' without salt, and cipher block chaining (CBC) mode.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    ' <param name="maxSaltLen">
    ' Max size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is negative or greater than 255, the default max value will be
    ' used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
    ' than the specified min value (which can be adjusted to default value),
    ' salt will not be used and plain text value will be encrypted as is.
    ' In this case, salt will not be processed during decryption either.
    ' </param>
    ' <param name="keySize">
    ' Size of symmetric key (in bits): 128, 192, or 256.
    ' </param>
    ' <param name="hashAlgorithm">
    ' Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
    ' </param>
    Public Sub New(passPhrase      As String,  _
                   initVector      As String,  _
                   minSaltLen      As Integer, _
                   maxSaltLen      As Integer, _
                   keySize         As Integer, _
                   hashAlgorithm   As String)
        Me.New(passPhrase, initVector, minSaltLen, maxSaltLen, keySize, _
               hashAlgorithm, Nothing)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption using the key derived from 1 password iteration, and
    ' cipher block chaining (CBC) mode.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key.
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    ' <param name="maxSaltLen">
    ' Max size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is negative or greater than 255, the default max value will be
    ' used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
    ' than the specified min value (which can be adjusted to default value),
    ' salt will not be used and plain text value will be encrypted as is.
    ' In this case, salt will not be processed during decryption either.
    ' </param>
    ' <param name="keySize">
    ' Size of symmetric key (in bits): 128, 192, or 256.
    ' </param>
    ' <param name="hashAlgorithm">
    ' Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
    ' </param>
    ' <param name="saltValue">
    ' Salt value used for password hashing during key generation. This is
    ' not the same as the salt we will use during encryption. This parameter
    ' can be any string.
    ' </param>
    Public Sub New(passPhrase      As String,  _
                   initVector      As String,  _
                   minSaltLen      As Integer, _
                   maxSaltLen      As Integer, _
                   keySize         As Integer, _
                   hashAlgorithm   As String,  _
                   saltValue       As String)
        Me.New(passPhrase, initVector, minSaltLen, maxSaltLen, keySize, _
               hashAlgorithm, saltValue, 1)
    End Sub
 
    ' <summary>
    ' Use this constructor if you are planning to perform encryption/
    ' decryption with the key derived from the explicitly specified
    ' parameters.
    ' </summary>
    ' <param name="passPhrase">
    ' Passphrase from which a pseudo-random password will be derived.
    ' The derived password will be used to generate the encryption key
    ' Passphrase can be any string. In this example we assume that the
    ' passphrase is an ASCII string. Passphrase value must be kept in
    ' secret.
    ' </param>
    ' <param name="initVector">
    ' Initialization vector (IV). This value is required to encrypt the
    ' first block of plaintext data. For RijndaelManaged class IV must be
    ' exactly 16 ASCII characters long. IV value does not have to be kept
    ' in secret.
    ' </param>
    ' <param name="minSaltLen">
    ' Min size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is less than 4, the default min value will be used (currently 4
    ' bytes).
    ' </param>
    ' <param name="maxSaltLen">
    ' Max size (in bytes) of randomly generated salt which will be added at
    ' the beginning of plain text before encryption is performed. When this
    ' value is negative or greater than 255, the default max value will be
    ' used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
    ' than the specified min value (which can be adjusted to default value),
    ' salt will not be used and plain text value will be encrypted as is.
    ' In this case, salt will not be processed during decryption either.
    ' </param>
    ' <param name="keySize">
    ' Size of symmetric key (in bits): 128, 192, or 256.
    ' </param>
    ' <param name="hashAlgorithm">
    ' Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
    ' </param>
    ' <param name="saltValue">
    ' Salt value used for password hashing during key generation. This is
    ' not the same as the salt we will use during encryption. This parameter
    ' can be any string.
    ' </param>
    ' <param name="passwordIterations">
    ' Number of iterations used to hash password. More iterations are
    ' considered more secure but may take longer.
    ' </param>
    Public Sub New(passPhrase          As String,  _
                   initVector          As String,  _
                   minSaltLen          As Integer, _
                   maxSaltLen          As Integer, _
                   keySize             As Integer, _
                   hashAlgorithm       As String,  _
                   saltValue           As String,  _
                   passwordIterations  As Integer)
 
        ' Save min salt length; set it to default if invalid value is passed.
        If (minSaltLen < MIN_ALLOWED_SALT_LEN) Then
            Me.minSaltLen = DEFAULT_MIN_SALT_LEN
        Else
            Me.minSaltLen = minSaltLen
        End If
 
        ' Save max salt length; set it to default if invalid value is passed.
        If (maxSaltLen < 0 Or maxSaltLen > MAX_ALLOWED_SALT_LEN) Then
            Me.maxSaltLen = DEFAULT_MAX_SALT_LEN
        Else
            Me.maxSaltLen = maxSaltLen
        End If
 
        ' Set the size of cryptographic key.
        If (keySize <= 0) Then
            keySize = DEFAULT_KEY_SIZE
        End If
 
        ' Set the name of algorithm. Make sure it is in UPPER CASE and does
        ' not use dashes, e.g. change "sha-1" to "SHA1".
        If (hashAlgorithm Is Nothing) Then
            hashAlgorithm = DEFAULT_HASH_ALGORITHM
        Else
            hashAlgorithm = hashAlgorithm.ToUpper().Replace("-", "")
        End If
 
        ' Initialization vector converted to a byte array.
        Dim initVectorBytes() As Byte = Nothing
 
        ' Salt used for password hashing (to generate the key, not during
        ' encryption) converted to a byte array.
        Dim saltValueBytes() As Byte = Nothing
 
        ' Get bytes of initialization vector.
        If (initVector Is Nothing) Then
            initVectorBytes = New Byte(){}
        Else
            initVectorBytes = Encoding.ASCII.GetBytes(initVector)
        End If
 
        ' Get bytes of salt (used in hashing).
        If(saltValue Is Nothing) Then
            saltValueBytes = New Byte(){}
        Else
            saltValueBytes = Encoding.ASCII.GetBytes(saltValue)
        End If
 
        ' Generate password, which will be used to derive the key.
        Dim password As PasswordDeriveBytes = New PasswordDeriveBytes(  _
                                                    passPhrase,         _
                                                    saltValueBytes,     _
                                                    hashAlgorithm,      _
                                                    passwordIterations)
 
        ' Convert key to a byte array adjusting the size from bits to bytes.
        Dim keyBytes() As Byte = password.GetBytes(keySize / 8)
 
        ' Initialize Rijndael key object.
        Dim symmetricKey As RijndaelManaged = New RijndaelManaged()
 
        ' If we do not have initialization vector, we cannot use the CBC mode.
        ' The only alternative is the ECB mode (which is not as good).
        If (initVectorBytes.Length = 0) Then
            symmetricKey.Mode = CipherMode.ECB
        Else
            symmetricKey.Mode = CipherMode.CBC
        End If
 
        ' Create encryptor and decryptor, which we will use for cryptographic
        ' operations.
        encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
        decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
    End Sub
 
    ' <summary>
    ' Encrypts a string value generating a base64-encoded string.
    ' </summary>
    ' <param name="plainText">
    ' Plain text string to be encrypted.
    ' </param>
    ' <returns>
    ' Cipher text formatted as a base64-encoded string.
    ' </returns>
    Public Function Encrypt(plainText As String) As String
        Encrypt = Encrypt(Encoding.UTF8.GetBytes(plainText))
    End Function
 
    ' <summary>
    ' Encrypts a byte array generating a base64-encoded string.
    ' </summary>
    ' <param name="plainTextBytes">
    ' Plain text bytes to be encrypted.
    ' </param>
    ' <returns>
    ' Cipher text formatted as a base64-encoded string.
    ' </returns>
    Public Function Encrypt(plainTextBytes As Byte()) As String
        Encrypt = Convert.ToBase64String(EncryptToBytes(plainTextBytes))
    End Function
 
    ' <summary>
    ' Encrypts a string value generating a byte array of cipher text.
    ' </summary>
    ' <param name="plainText">
    ' Plain text string to be encrypted.
    ' </param>
    ' <returns>
    ' Cipher text formatted as a byte array.
    ' </returns>
    Public Function EncryptToBytes(plainText As String) As Byte()
        EncryptToBytes = EncryptToBytes(Encoding.UTF8.GetBytes(plainText))
    End Function
 
    ' <summary>
    ' Encrypts a byte array generating a byte array of cipher text.
    ' </summary>
    ' <param name="plainTextBytes">
    ' Plain text bytes to be encrypted.
    ' </param>
    ' <returns>
    ' Cipher text formatted as a byte array.
    ' </returns>
    Public Function EncryptToBytes(plainTextBytes As Byte()) As Byte()
 
        ' Add salt at the beginning of the plain text bytes (if needed).
        Dim plainTextBytesWithSalt() As Byte = AddSalt(plainTextBytes)
 
        ' Encryption will be performed using memory stream.
        Dim memoryStream As MemoryStream = New MemoryStream()
        Dim cryptoStream As CryptoStream = Nothing
 
        ' Let's make cryptographic operations thread-safe.
        SyncLock Me
            ' To perform encryption, we must use the Write mode.
            cryptoStream = New CryptoStream(memoryStream,   _
                                            encryptor,      _
                                            CryptoStreamMode.Write)
 
            ' Start encrypting data.
            cryptoStream.Write( plainTextBytesWithSalt, _ 
                                0,                      _
                                plainTextBytesWithSalt.Length)
             
            ' Finish the encryption operation.
            cryptoStream.FlushFinalBlock
 
            ' Move encrypted data from memory into a byte array.
            Dim cipherTextBytes() As Byte = memoryStream.ToArray()
               
            ' Close memory streams.
            memoryStream.Close
            cryptoStream.Close
 
            ' Return encrypted data.
            EncryptToBytes = cipherTextBytes
        End SyncLock
    End Function
 
    ' <summary>
    ' Decrypts a base64-encoded cipher text value generating a string result.
    ' </summary>
    ' <param name="cipherText">
    ' Base64-encoded cipher text string to be decrypted.
    ' </param>
    ' <returns>
    ' Decrypted string value.
    ' </returns>
    Public Function Decrypt(cipherText As String) As String
        Decrypt = Decrypt(Convert.FromBase64String(cipherText))
    End Function
 
    ' <summary>
    ' Decrypts a byte array containing cipher text value and generates a
    ' string result.
    ' </summary>
    ' <param name="cipherTextBytes">
    ' Byte array containing encrypted data.
    ' </param>
    ' <returns>
    ' Decrypted string value.
    ' </returns>
    Public Function Decrypt(cipherTextBytes As Byte()) As String
        Decrypt = Encoding.UTF8.GetString(DecryptToBytes(cipherTextBytes))
    End Function
 
    ' <summary>
    ' Decrypts a base64-encoded cipher text value and generates a byte array
    ' of plain text data.
    ' </summary>
    ' <param name="cipherText">
    ' Base64-encoded cipher text string to be decrypted.
    ' </param>
    ' <returns>
    ' Byte array containing decrypted value.
    ' </returns>
    Public Function DecryptToBytes(cipherText As String) As Byte()
        DecryptToBytes = DecryptToBytes(Convert.FromBase64String(cipherText))
    End Function
 
    ' <summary>
    ' Decrypts a base64-encoded cipher text value and generates a byte array
    ' of plain text data.
    ' </summary>
    ' <param name="cipherTextBytes">
    ' Byte array containing encrypted data.
    ' </param>
    ' <returns>
    ' Byte array containing decrypted value.
    ' </returns>
    Public Function DecryptToBytes(cipherTextBytes As Byte()) As Byte()
 
        Dim decryptedBytes()    As Byte   = Nothing
        Dim plainTextBytes()    As Byte   = Nothing
        Dim decryptedByteCount  As Integer  = 0
        Dim saltLen             As Integer  = 0
 
        Dim memoryStream As MemoryStream = New MemoryStream(cipherTextBytes)
 
        ' Since we do not know how big decrypted value will be, use the same
        ' size as cipher text. Cipher text is always longer than plain text
        ' (in block cipher encryption), so we will just use the number of
        ' decrypted data byte after we know how big it is.
        decryptedBytes = New Byte(cipherTextBytes.Length - 1){}
 
        ' Let's make cryptographic operations thread-safe.
        SyncLock Me
            ' To perform decryption, we must use the Read mode.
            Dim cryptoStream As CryptoStream = New CryptoStream(        _
                                                        memoryStream,   _
                                                        decryptor,      _
                                                        CryptoStreamMode.Read)
 
            ' Decrypting data and get the count of plain text bytes.
            decryptedByteCount  = cryptoStream.Read(decryptedBytes, _
                                                    0,              _
                                                    decryptedBytes.Length)
            ' Release memory.
            memoryStream.Close
            cryptoStream.Close
        End SyncLock
 
        ' If we are using salt, get its length from the first 4 bytes of plain
        ' text data.
        If (maxSaltLen > 0 And maxSaltLen >= minSaltLen) Then
            saltLen =   (decryptedBytes(0) And &H03) Or _
                        (decryptedBytes(1) And &H0c) Or _
                        (decryptedBytes(2) And &H30) Or _
                        (decryptedBytes(3) And &Hc0)
        End If
 
        ' Allocate the byte array to hold the original plain text
        ' (without salt).
        plainTextBytes = New Byte(decryptedByteCount - saltLen - 1){}
 
        ' Copy original plain text discarding the salt value if needed.
        Array.Copy(decryptedBytes, saltLen, plainTextBytes, _
                    0, decryptedByteCount - saltLen)
 
        ' Return original plain text value.
        DecryptToBytes = plainTextBytes
    End Function
 
    ' <summary>
    ' Adds an array of randomly generated bytes at the beginning of the
    ' array holding original plain text value.
    ' </summary>
    ' <param name="plainTextBytes">
    ' Byte array containing original plain text value.
    ' </param>
    ' <returns>
    ' Either original array of plain text bytes (if salt is not used) or a
    ' modified array containing a randomly generated salt added at the 
    ' beginning of the plain text bytes. 
    ' </returns>
    Private Function AddSalt(plainTextBytes As Byte()) As Byte()
 
        ' The max salt value of 0 (zero) indicates that we should not use 
        ' salt. Also do not use salt if the max salt value is smaller than
        ' the min value.
        If (maxSaltLen = 0 Or maxSaltLen < minSaltLen) Then
            AddSalt = plainTextBytes
            Exit Function
        End If
 
        ' Generate the salt.
        Dim saltBytes() As Byte = GenerateSalt()
 
        ' Allocate array which will hold salt and plain text bytes.
        Dim plainTextBytesWithSalt() As Byte = New Byte( _
                                                plainTextBytes.Length + _
                                                saltBytes.Length - 1){}
        ' First, copy salt bytes.
        Array.Copy(saltBytes, plainTextBytesWithSalt, saltBytes.Length)
 
        ' Append plain text bytes to the salt value.
        Array.Copy( plainTextBytes, 0, _
                    plainTextBytesWithSalt, saltBytes.Length, _
                    plainTextBytes.Length)
 
        AddSalt = plainTextBytesWithSalt
    End Function
 
    ' <summary>
    ' Generates an array holding cryptographically strong bytes.
    ' </summary>
    ' <returns>
    ' Array of randomly generated bytes.
    ' </returns>
    ' <remarks>
    ' Salt size will be defined at random or exactly as specified by the
    ' minSlatLen and maxSaltLen parameters passed to the object constructor.
    ' The first four bytes of the salt array will contain the salt length
    ' split into four two-bit pieces.
    ' </remarks>
    Private Function GenerateSalt() As Byte()
 
        ' We don't have the length, yet.
        Dim saltLen As Integer = 0
 
        ' If min and max salt values are the same, it should not be random.
        If (minSaltLen = maxSaltLen) Then
            saltLen = minSaltLen
        ' Use random number generator to calculate salt length.
        Else
            saltLen = GenerateRandomNumber(minSaltLen, maxSaltLen)
        End If
 
        ' Allocate byte array to hold our salt.
        Dim salt() As Byte = New Byte(saltLen - 1){}
 
        ' Populate salt with cryptographically strong bytes.
        Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()
 
        rng.GetNonZeroBytes(salt)
 
        ' Split salt length (always one byte) into four two-bit pieces and
        ' store these pieces in the first four bytes of the salt array.
        salt(0) = ((salt(0) And &Hfc) Or(saltLen And &H03))
        salt(1) = ((salt(1) And &Hf3) Or(saltLen And &H0c))
        salt(2) = ((salt(2) And &Hcf) Or(saltLen And &H30))
        salt(3) = ((salt(3) And &H3f) Or(saltLen And &Hc0))
 
        GenerateSalt = salt
    End Function
 
    ' <summary>
    ' Generates random integer.
    ' </summary>
    ' <param name="minValue">
    ' Min value (inclusive).
    ' </param>
    ' <param name="maxValue">
    ' Max value (inclusive).
    ' </param>
    ' <returns>
    ' Random integer value between the min and max values (inclusive).
    ' </returns>
    ' <remarks>
    ' This methods overcomes the limitations of .NET Framework's Random
    ' class, which - when initialized multiple times within a very short
    ' period of time - can generate the same "random" number.
    ' </remarks>
    Private Function GenerateRandomNumber(minValue As Integer, _
                                          maxValue As Integer) As Integer
 
        ' We will make up an integer seed from 4 bytes of this array.
        Dim randomBytes() As Byte = New Byte(3){}
 
        ' Generate 4 random bytes.
        Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()
        rng.GetBytes(randomBytes)
 
        ' Convert four random bytes into a positive integer value.
        Dim seed As Integer =  ((randomBytes(0) And &H7f) << 24) Or _
                                (randomBytes(1)           << 16) Or _
                                (randomBytes(2)           <<  8) Or _
                                (randomBytes(3))
 
        ' Now, this looks more like real randomization.
        Dim random As Random = New Random(seed)
 
        ' Calculate a random number.
        GenerateRandomNumber = random.Next(minValue, maxValue+1)
  End Function
 
End Class
 
' <summary>
' The main entry point for the application.
' </summary>
Sub Main()
    Dim plainText  As String = "Hello, World!"    ' original plaintext
    Dim cipherText As String = ""                 ' encrypted text
    Dim passPhrase As String = "Pas5pr@se"        ' can be any string
    Dim initVector As String = "@1B2c3D4e5F6g7H8" ' must be 16 bytes
 
    ' Before encrypting data, we will append plain text to a random
    ' salt value, which will be between 4 and 8 bytes long (implicitly
    ' used defaults).
    Dim rijndaelKey As RijndaelEnhanced = _
        New RijndaelEnhanced(passPhrase, initVector)
 
    Console.WriteLine(String.Format("Plaintext   : {0}{1}", plainText, vbCrLf))
 
    ' Encrypt the same plain text data 10 time (using the same key,
    ' initialization vector, etc) and see the resulting cipher text;
    ' encrypted values will be different.
    Dim I As Integer
    For I=0 To 9
        cipherText = rijndaelKey.Encrypt(plainText)
        Console.WriteLine( _
            String.Format("Encrypted #{0}: {1}", i, cipherText))
        plainText = rijndaelKey.Decrypt(cipherText)
    Next
 
    ' Make sure we got decryption working correctly.
    Console.WriteLine(String.Format("{0}Decrypted   : {1}", vbCrLf, plainText))
End Sub
 
End Module
'
' END OF FILE
'------------------------------------------------------------------------------
  • 上一篇:

  • 下一篇:
  • 【字体: 】【打印此文】【关闭窗口
      相关文章:(只显示最新16条)
    VB.Net获取随机密码的实例
    VB.Net用Salt哈希数据的实例
    用DPAPI加密和解密数据的实例
    储存加密的数据库连接字符串到注册表的实例
    Rijndael加密解密的实例
    AES加密的实例
    Rijndael加密的实例
    SHA256 Hash加密的实例
    VB.Net对XML元素进行加密解密的实例
    VB.Net文件CRC32算法的实例
    VB.Net文件SHA1算法的实例
    Blowfish加密算法的实例
    Rijndael类的实例
    TripleDES加解密的实例
    VB.Net实现des加密算法的实例
    VB.Net实现RSA加密的实例

    | 设为首页 | 加入收藏 | 联系站长 | | 友情链接 | 版权申明 |
    乐博网欢迎各种媒体转载我们的原创作品[转载请注明出处];我们鼓励更多VB.Net开发者一起加入研究与探讨;如发现文章访问错误、内容错误或版权疑问、内容有违相关法律(如涉及政治、色情、反动或散布虚假有害信息)等情况,请及时向我们举报,我们将及时纠正!
    联系邮箱:Shiny#vip.qq.com (#替换为@) QQ交流群: 40797788 [闽ICP备05014267号]