VB.NET中的安全加密算法

這幾天需要對系統中的一些關鍵數據進行加密。用VB.NET編寫CLR函數,然後在存儲過程中略加修改即完成任務。

在測試過程中遇到不少問題,比如說不熟悉流對象(初學VB.NET),不熟悉編碼轉換,最重要的是加密的密鑰長度限制,可能很多人會遇到。

下面的代碼中實現了散列加密算法和對稱加密算法,用的都是.NET安全算法的工廠類,並實現常用的Base64編碼和解碼。

常用的散列加密算法有:MD5,SHA(SHA1),RIPEMD160,SHA256,SHA384,SHA512,MACTripleDES

常用的對稱加密算法有:DES,RC2,Rijndael,TripleDES。對稱加密算法有一個key和一個IV,不同的算法要求的key和IV長度不一樣,而且同一個字符串在不同的編碼下長度也不一樣,這一點要特別注意。

經測試,不同編碼對應的key和IV長度對應關係如下:


貼代碼:

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.SqlServer.Server
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Data.SqlTypes
Imports System.Security.Cryptography
Namespace SOP.Security
    Public Class Security
        '散列加密算法
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function HashAlgorithm(ByVal Input As SqlString, ByVal Algorithm As SqlString, ByVal Charset As SqlString) As SqlString
            Dim _md5 As System.Security.Cryptography.HashAlgorithm = System.Security.Cryptography.HashAlgorithm.Create(Algorithm.Value)
            Dim fs() As Byte, sb As New System.Text.StringBuilder
            fs = _md5.ComputeHash(getBytes(Input.Value, Charset.Value))
            For i As Integer = 0 To fs.Length - 1
                sb.Append(fs(i).ToString("x2"))
            Next
            Return sb.ToString()
        End Function
        '對稱加密算法
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function SymmetricEncrypt(ByVal Input As SqlString, ByVal Key As SqlString, ByVal IV As SqlString, ByVal Algorithm As SqlString, ByVal Charset As SqlString) As SqlString
            Dim sa As System.Security.Cryptography.SymmetricAlgorithm = System.Security.Cryptography.SymmetricAlgorithm.Create(Algorithm.Value) ' New System.Security.Cryptography.DESCryptoServiceProvider
            Dim data() As Byte
            sa.Key = getBytes(Key.Value, Charset.Value)
            sa.IV = getBytes(IV.Value, Charset.Value)
            '將數據轉換成字節
            data = getBytes(Input.Value, Charset.Value)
            Using ms As New System.IO.MemoryStream
                '將數據加密,並準備寫入ms內存流中
                Dim cs As New System.Security.Cryptography.CryptoStream(ms, sa.CreateEncryptor, CryptoStreamMode.Write)
                '寫入加密數據至緩存區
                cs.Write(data, 0, data.Length)
                '將數據更新到流對象
                cs.FlushFinalBlock()
                '關閉
                cs.Close()
                '用base64編碼一次
                Return Convert.ToBase64String(ms.ToArray)
            End Using
        End Function
        '對稱解密算法
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function SymmetricDecrypt(ByVal Input As SqlString, ByVal Key As SqlString, ByVal IV As SqlString, ByVal Algorithm As SqlString, ByVal Charset As SqlString) As SqlString
            Dim sa As System.Security.Cryptography.SymmetricAlgorithm = System.Security.Cryptography.SymmetricAlgorithm.Create(Algorithm.Value) '  System.Security.Cryptography.DESCryptoServiceProvider
            Dim data() As Byte
            sa.Key = getBytes(Key.Value, Charset.Value)
            sa.IV = getBytes(IV.Value, Charset.Value)
            '將數據用base64解碼一次
            data = Convert.FromBase64String(Input.Value)
            Using ms As New System.IO.MemoryStream()
                '將數據加密,並準備寫入ms內存流中
                Dim cs As New System.Security.Cryptography.CryptoStream(ms, sa.CreateDecryptor, CryptoStreamMode.Write)
                '寫入加密數據至緩存區
                cs.Write(data, 0, data.Length)
                '將數據更新到流對象
                cs.FlushFinalBlock()
                '關閉
                cs.Close()
                '再轉換回字符串
                Return getString(ms.ToArray, Charset.Value)
            End Using
        End Function
        'Base64
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function Base64Encode(ByVal Input As SqlString, ByVal Charset As SqlString) As SqlString
            Return Convert.ToBase64String(getBytes(Input.Value, Charset.Value))
        End Function
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function Base64Decode(ByVal Input As SqlString, ByVal Charset As SqlString) As SqlString
            Return getString(Convert.FromBase64String(Input.Value), Charset.Value)
        End Function
        '轉換字符串至指定編碼的字節
        Private Shared Function getBytes(ByVal Input As String, ByVal Charset As String) As Byte()
            Select Case Charset
                Case "UTF-16", "Unicode", "UTF16"
                    Return System.Text.Encoding.Unicode.GetBytes(Input)
                Case "UTF-7", "UTF7"
                    Return System.Text.Encoding.UTF7.GetBytes(Input)
                Case "UTF-8", "UTF8"
                    Return System.Text.Encoding.UTF8.GetBytes(Input)
                Case "UTF-32", "UTF32"
                    Return System.Text.Encoding.UTF32.GetBytes(Input)
                Case "ASCII"
                    Return System.Text.Encoding.ASCII.GetBytes(Input)
                Case "", "Default"
                    Return System.Text.Encoding.Default.GetBytes(Input)
                Case Else
                    Return System.Text.Encoding.Default.GetBytes(Input)
            End Select
        End Function
        '字節轉換至指定編碼的字符串
        Private Shared Function getString(ByVal Input() As Byte, ByVal Charset As String) As String
            Select Case Charset
                Case "UTF-16", "Unicode", "UTF16"
                    Return System.Text.Encoding.Unicode.GetString(Input)
                Case "UTF-7", "UTF7"
                    Return System.Text.Encoding.UTF7.GetString(Input)
                Case "UTF-8", "UTF8"
                    Return System.Text.Encoding.UTF8.GetString(Input)
                Case "UTF-32", "UTF32"
                    Return System.Text.Encoding.UTF32.GetString(Input)
                Case "ASCII"
                    Return System.Text.Encoding.ASCII.GetString(Input)
                Case "", "Default"
                    Return System.Text.Encoding.Default.GetString(Input)
                Case Else
                    Return System.Text.Encoding.Default.GetString(Input)
            End Select
        End Function
    End Class


End Namespace

以下是在SQL SERVER2005中安裝CLR函數的方法:

alter database    sop set TRUSTWORTHY on;
exec sp_changedbowner sa
go
CREATE ASSEMBLY [SOP.Security]
AUTHORIZATION [dbo]
FROM 'E:\hsl\sop\sop.ScriptEngine.dll'
WITH PERMISSION_SET = unsafe
go
 CREATE ASSEMBLY [SOP.Security]
AUTHORIZATION [dbo]
 WITH PERMISSION_SET = UNSAFE
go
Create FUNCTION [dbo].[SymmetricDecrypt](@Input [nvarchar](4000), @Key [nvarchar](4000), @IV [nvarchar](4000), @Algorithm [nvarchar](4000), @Charset [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SOP.Security].[SOP.Security.Security].[SymmetricDecrypt]
go
Create FUNCTION [dbo].[SymmetricEncrypt](@Input [nvarchar](4000), @Key [nvarchar](4000), @IV [nvarchar](4000), @Algorithm [nvarchar](4000), @Charset [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SOP.Security].[SOP.Security.Security].[SymmetricEncrypt]
GO
Create FUNCTION [dbo].[HashAlgorithm](@Input [nvarchar](4000), @Algorithm [nvarchar](4000), @Charset [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SOP.Security].[SOP.Security.Security].[HashAlgorithm]
GO
Create FUNCTION [dbo].[Base64Encode](@Input [nvarchar](4000), @Charset [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SOP.Security].[SOP.Security.Security].[Base64Encode]
GO
Create FUNCTION [dbo].[Base64Decode](@Input [nvarchar](4000), @Charset [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [SOP.Security].[SOP.Security.Security].[Base64Decode]
go

調用示例:

DECLARE @key VARCHAR(500),@VI VARCHAR(500),@s nVARCHAR(MAX),@d nVARCHAR(MAX),@d1 nVARCHAR(MAX)
SELECT @key='55523423123456785552342312345678',@VI='55523423123456785552342312345678',@s='定義全局變量,並改寫afterFinalSubmit方法'
SELECT @d=dbo.SymmetricEncrypt(@s,left(@key,4),left(@VI,2),'TripleDES','UTF32')
PRINT @d
輸出:
e2TRpdUG4+bY1Glg0roDFinHcKU+s2aKxNnVSdfSKPt4i8bN8leTWqWelGtMndbv2cDp2vacfMN8WmzwYyr6l1Q2pdO3Xsx6xykVcpfGXk2sjS//jO4/AyrDWT7h+HRECmETmS3M2poZhbEYsrNerA/hny/J1xzO


由於不太瞭解.net和加密算法,此文只是我簡單測試後的結果,如有錯誤,請及時指出。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章