I'm attemping to deploy a crypto class that we use on a desktop app to SQL Server. I'll use the encryptstring/decryptstring found in this class as User Defined Functions on SQL Server. When I try to deploy the class I'm getting this error:
Error 1 Method, property or field 'EncryptString' of class 'EncryptingDecryptingOASISPWDS.Crypto' in assembly 'EncryptingDecryptingOASISPWDS' is not static. EncryptingDecryptingOASISPWDS
Here is the code:
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Security.Cryptography
Imports System.Text 'for UnicodeEncoding
Imports System.IO 'for MemoryStream, FileStream, Stream, Path
Imports System.Threading 'for Thread.Sleep
Partial Public Class Crypto
'Private Const CodeVersion As String = "01.00.00"
'class member variables
Private m_sPassPhrase As String
'class private variables
Private mbytKey() As Byte 'crypto key
Private mbytIV() As Byte 'Initialization Vector
Private mbKeyIsSet As Boolean = False
Private mksKeyNotSetException As String = "Crypto passphrase is not set."
Private mksPassphraseTooSmall As String = "PassPhrase length must be at least {0} characters."
' class constructors
Public Sub New()
'no passphrase is useful for GetHashString/ValidPassword methods
End Sub
Public Sub New(ByVal CryptoPassPhrase As String)
PassPhrase = CryptoPassPhrase
End Sub
' class public properties
'generate and store encryption key & iv from passphrase
Public Property PassPhrase() As String
Get
Return m_sPassPhrase
End Get
Set(ByVal Value As String)
Const iMinLength As Integer = -1 '-1 disables min length
m_sPassPhrase = Value.Trim
'enforce a rule on minimum length if desired here
If (Value.Length > iMinLength) Or (iMinLength = -1) Then
Dim sha2 As New SHA256Managed()
'256 bits = 32 byte key
mbytKey = sha2.ComputeHash(BytesFromString(m_sPassPhrase))
'convert to Base64 for Initialization Vector, take last 16 chars
Dim sKey As String = Convert.ToBase64String(mbytKey)
mbytIV = Encoding.ASCII.GetBytes(sKey.Remove(0, sKey.Length - 16))
mbKeyIsSet = True
sha2 = Nothing
Else
mbKeyIsSet = False
Throw New Exception(String.Format(mksPassphraseTooSmall, (iMinLength + 1).ToString))
End If
End Set
End Property
'decrypt a stream
Public Function DecryptStream(ByVal EncryptedStream As MemoryStream) As MemoryStream
If mbKeyIsSet Then
Try
'create Crypto Service Provider, set key, transform and crypto stream
Dim oCSP As New RijndaelManaged()
oCSP.Key = mbytKey
oCSP.IV = mbytIV
Dim ct As ICryptoTransform = oCSP.CreateDecryptor()
Dim cs As CryptoStream = New CryptoStream(EncryptedStream, ct, CryptoStreamMode.Read)
'get bytes from encrypted stream
Dim byteArray(EncryptedStream.Length - 1) As Byte
Dim iBytesIn As Integer = cs.Read(byteArray, 0, EncryptedStream.Length)
cs.Close()
'create and write the decrypted output stream
Dim plainStream As New MemoryStream()
plainStream.Write(byteArray, 0, iBytesIn)
Return plainStream
Catch ex As Exception
Return Stream.Null
End Try
Else
Throw New Exception(mksKeyNotSetException)
End If
End Function
'decrypt a string - wrapper without Base64 flag (True by default)
Public Function DecryptString(ByVal EncryptedString As String) As String
Return _DecryptString(EncryptedString, True)
End Function
'decrypt a string - wrapper with Base64 flag
Public Function DecryptString(ByVal EncryptedString As String, ByVal Base64 As Boolean) As String
Return _DecryptString(EncryptedString, Base64)
End Function
'encrypt a stream
Public Function EncryptStream(ByVal PlainStream As MemoryStream) As MemoryStream
Try
'open stream for encrypted data
Dim encStream As New MemoryStream()
'create Crypto Service Provider, set key, transform and crypto stream
Dim oCSP As New RijndaelManaged()
oCSP.Key = mbytKey
oCSP.IV = mbytIV
Dim ct As ICryptoTransform = oCSP.CreateEncryptor()
Dim cs As CryptoStream = New CryptoStream(encStream, ct, CryptoStreamMode.Write)
'get input stream into byte array
Dim byteArray() As Byte = PlainStream.ToArray()
'write input bytes to crypto stream and close up
cs.Write(byteArray, 0, PlainStream.Length)
cs.FlushFinalBlock()
cs.Close()
Return encStream
Catch ex As Exception
Return Stream.Null
End Try
End Function
'encrypt a string - wrapper without Base64 flag (True by default)
<Microsoft.SqlServer.Server.SqlFunction()> _
Function EncryptString(ByVal PlainText As String) As String
Return _EncryptString(PlainText, True)
End Function
''encrypt a string - wrapper with Base64 flag
<Microsoft.SqlServer.Server.SqlFunction()> _
Public Function EncryptString2(ByVal PlainText As String, ByVal Base64 As Boolean) As String
Return _EncryptString(PlainText, Base64)
End Function
'calculates the hash of InputValue, returns a string
'- SHA1 hash is always 20 bytes (160 bits)
Public Function GetHashString(ByVal InputValue As String) As String
Try
Dim inputBytes() As Byte = BytesFromString(InputValue)
Dim hashValue() As Byte = New SHA1Managed().ComputeHash(inputBytes)
Return BytesToHexString(hashValue)
Catch ex As Exception
Return String.Empty
End Try
End Function
'returns True if hash of Passphrase matches HashValue
Public Function ValidPassword(ByVal Passphrase As String, ByVal HashValue As String) As Boolean
Return (GetHashString(Passphrase) = HashValue)
End Function
'internal string decryption
Private Function _DecryptString(ByVal EncryptedString As String, ByVal Base64 As Boolean) As String
Try
'put string in byte array depending on Base64 flag
Dim byteArray() As Byte
If Base64 Then
byteArray = Convert.FromBase64String(EncryptedString)
Else
byteArray = BytesFromString(EncryptedString)
End If
'create the streams, decrypt and return a string
Dim msEnc As New MemoryStream(byteArray)
Dim msPlain As MemoryStream = DecryptStream(msEnc)
Return BytesToString(msPlain.GetBuffer)
Catch ex As Exception
Return String.Empty
End Try
End Function
'internal string encryption
Private Function _EncryptString(ByVal PlainText As String, ByVal Base64 As Boolean) As String
Try
'put string in byte array
Dim byteArray() As Byte = BytesFromString(PlainText)
'create streams and encrypt
Dim msPlain As New MemoryStream(byteArray)
Dim msEnc As MemoryStream = EncryptStream(msPlain)
'return string depending on Base64 flag
If Base64 Then
Return Convert.ToBase64String(msEnc.ToArray)
Else
Return BytesToString(msEnc.ToArray)
End If
Catch ex As Exception
Return String.Empty
End Try
End Function
'returns a Unicode byte array from a string
Private Function BytesFromString(ByVal StringValue As String) As Byte()
Return (New UnicodeEncoding()).GetBytes(StringValue)
End Function
'returns a hex string from a byte array
Private Function BytesToHexString(ByVal byteArray() As Byte) As String
Dim sb As New StringBuilder(40)
Dim bValue As Byte
For Each bValue In byteArray
sb.AppendFormat(bValue.ToString("x2").ToUpper)
Next
Return sb.ToString
End Function
'returns a Unicode string from a byte array
Private Function BytesToString(ByVal byteArray() As Byte) As String
Return (New UnicodeEncoding()).GetString(byteArray)
End Function
'Return True when the file is available for writing
'- returns False if output file locked, for example
Private Function CheckWriteAccess(ByVal FileName As String) As Boolean
'2 second delay with 10,200
Dim iCount As Integer = 0 'retry count
Const iLimit As Integer = 10 'retries
Const iDelay As Integer = 200 'msec
While (iCount < iLimit)
Try
Dim fs As FileStream
fs = New FileStream(FileName, FileMode.Append, _
FileAccess.Write, FileShare.None)
fs.Close()
Return True
Catch ex As Exception
Thread.Sleep(iDelay)
Finally
iCount += 1
End Try
End While
Return False
End Function
End Class
All CLR functions / SP used by SQL Server are required to be Static since sql server cannot instantiate a class before using it... it uses only static methods that does not requires any instance.So you must declare
<Microsoft.SqlServer.Server.SqlFunction()> _
Static Function EncryptString(ByVal PlainText As String) As String
...
No comments:
Post a Comment