I have a asp.net webapp, and runs in private network
I want determine PCs clients for
allow or block the requests
knows who is connected
connects only by special PCs
and more
I used IP Addresses, but anyone can connect when change the IP Address by one that passed in webapp, I want users login by just some PCs . any suggestions ?
LOGIN and PASSWORD going to a database of preferences... The best way to control everything about users (IP control can be bypassed, it´s not a valid control).
UPDATE
New method to pass info in URL:
To get hardware information:
Dim query As New SelectQuery("Win32_bios")
Dim search As New ManagementObjectSearcher(query)
Dim info As ManagementObject
For Each info In search.Get()
BIOS_Msg = info("version").ToString()
Next
Dim searchMainboard As New ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem")
Dim infoMain As ManagementObject
For Each infoMain In searchMainboard.Get()
Computer_Mainboard = infoMain("model").ToString()
Next
To encode Strings:
You may set a KEY and IV as byte array. The key may change according date and even some specific parameters according to the current time.
Add also:
Imports System.Security.Cryptography
Imports System.Text
Friend Function EncryptStringToBytes_Aes(ByVal plainText As String, ByVal Key() As Byte, ByVal IV() As Byte) As String
' Check arguments.
Dim encrypted() As Byte
' Create an AesCryptoServiceProvider object
' with the specified key and IV.
Using aesAlg As New AesCryptoServiceProvider()
aesAlg.Key = Key
aesAlg.IV = IV
Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
'Write all data to the stream.
swEncrypt.Write(plainText)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
End Using
' Return the encrypted bytes from the memory stream.
Return Convert.ToBase64(encrypted)
End Function 'EncryptStringToBytes_Aes
To decrypt it:
Friend Function DecryptStringFromBytes_Aes(ByVal cipherText As String, ByVal Key() As Byte, ByVal IV() As Byte) As String
Dim plaintext As String = Nothing
Dim SourceText as Byte() = Convert.FromBase64(CipherText)
' Create an AesCryptoServiceProvider object
' with the specified key and IV.
Using aesAlg As New AesCryptoServiceProvider()
aesAlg.Key = Key
aesAlg.IV = IV
' Create a decrytor to perform the stream transform.
Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for decryption.
Using msDecrypt As New MemoryStream(SourceText)
Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
Using srDecrypt As New StreamReader(csDecrypt)
' Read the decrypted bytes from the decrypting stream
' and place them in a string.
plaintext = srDecrypt.ReadToEnd()
End Using
End Using
End Using
End Using
Return plaintext
End Function 'DecryptStringFromBytes_Aes
Using these functions, you can:
- Get specific hardware info;
- Encode any string and convert it to Base64
- Pass them in URL using normal convention.
- Receive them in your code-behind and translate them.
I guess that´s the best way to get reliable and specific information of each workstation instead IP-number. You may also work with the Windows Serial Number.
I am using AES CBC encryption in VB.Net and decryption is done using AS3Crypto. First few characters (about 16) are missing during decryption and replaced with random characters like below.
05[ÚðÊ\ÃPôôÄ]óbR
Here is my .net code. On AS3Crypto demo page, I use Secret Key > AES > CBC. I tried with different settings for Padding and Key Formats still no luck.
Thanks.
Dim plainText = txt2encrypt.Text.Trim
Dim encrypted() As Byte '
Using aesAlg As New AesCryptoServiceProvider()
aesAlg.Mode = CipherMode.CBC
' Create a decrytor to perform the stream transform.
Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
'Write all data to the stream.
swEncrypt.Write(plainText)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
Dim encryptedText = Convert.ToBase64String(encrypted)
txtkey.Text = Convert.ToBase64String(aesAlg.Key)
txtiv.Text = Convert.ToBase64String(aesAlg.IV)
txtkeysize.Text = aesAlg.KeySize
txtencrypted.Text = encryptedText
txtpadding.Text = aesAlg.Padding
End Using
I use the following two methods to encrypt and decrypt strings:
'Encrypts string. Returns encrypted byte array.
Public Function Encrypt(ByVal str As String) As Byte()
Dim inputInBytes() As Byte = Encoding.Unicode.GetBytes(str)
Dim laesProvider As New AesCryptoServiceProvider()
laesProvider.Key = _key
laesProvider.Mode = CipherMode.CBC
laesProvider.IV = _IV
laesProvider.Padding = PaddingMode.PKCS7
Dim lencryptor As ICryptoTransform = laesProvider.CreateEncryptor
Dim encryptedStream As New MemoryStream
Dim cryptStream As CryptoStream = New CryptoStream(encryptedStream, lencryptor, CryptoStreamMode.Write)
cryptStream.Write(inputInBytes, 0, inputInBytes.Length)
cryptStream.FlushFinalBlock()
encryptedStream.Position = 0
Dim result(encryptedStream.Length - 1) As Byte
encryptedStream.Read(result, 0, encryptedStream.Length)
cryptStream.Close()
Return result
End Function
'Decrypts bytearray. Returns string.
Public Function DecryptToStr(ByVal inputInBytes() As Byte) As String
Dim laesProvider As New AesCryptoServiceProvider()
laesProvider.Key = _key
laesProvider.Mode = CipherMode.CBC
laesProvider.IV = _IV
laesProvider.Padding = PaddingMode.PKCS7
Dim ldecryptor As ICryptoTransform = laesProvider.CreateDecryptor
' Provide a memory stream to decrypt information into
Dim decryptedStream As MemoryStream = New MemoryStream()
Dim cryptStream As CryptoStream = New CryptoStream(decryptedStream, ldecryptor, CryptoStreamMode.Write)
cryptStream.Write(inputInBytes, 0, inputInBytes.Length)
cryptStream.FlushFinalBlock() '#### This is where the exception is thrown ####
decryptedStream.Position = 0
' Read the memory stream and convert it back into a string
Dim result(decryptedStream.Length - 1) As Byte
decryptedStream.Read(result, 0, decryptedStream.Length)
cryptStream.Close()
Return Encoding.Unicode.GetString(result)
End Function
The error occurs when attempting to decrypt certain length strings. When the string is a social security # (11 chars including dashes) then is throws "The input data is not a complete block" CryptographicException. If I pass in for example a string that is exactly 8 characters long, then everything works as expected. I thought that the PKCS7 padding would take care of the various lengths. I'm sure that I'm missing something simple, but after hours of googling, the answer eludes me.
The issue wasn't in the encryption method, it was in the length of the varbinary set in the database where it was being stored. So the encrypted data was being truncated.
I can't seem to get past this problem, I've created what I assume to be a 256-bit key using the random generator at GRC and combined that with my IV. I keep getting the error below:
Specified key is not a valid size for this algorithm.
Any help is gratefully received, here is the code I am using to Encrypt/Decrypt:
Private Function Rijndael(ByVal sInput As String, ByVal bEncrypt As Boolean) As String
' Setup the Key and Initialization Vector.
Dim byteKey As Byte() = Encoding.UTF8.GetBytes("C3CA193570B26E5C3CBB50FD805A0E23BAFFABA135E82C41517EEDCB9B7C90AC")
Dim byteIV As Byte() = Encoding.UTF8.GetBytes("c+O2r)J~?L:$]u[2")
' Create an instance of the encyrption algorithm.
Dim _rijndael As New RijndaelManaged()
' Create an encryptor using our key and IV
Dim transform As ICryptoTransform
If bEncrypt Then
transform = _rijndael.CreateEncryptor(byteKey, byteIV)
Else
transform = _rijndael.CreateDecryptor(byteKey, byteIV)
End If
' Create the streams for input and output
Dim msOutput As New System.IO.MemoryStream()
Dim msInput As New CryptoStream(msOutput, transform, CryptoStreamMode.Write)
' Feed data into the crypto stream.
msInput.Write(Encoding.UTF8.GetBytes(sInput), 0, Encoding.UTF8.GetBytes(sInput).Length)
' Flush crypto stream.
msInput.FlushFinalBlock()
Return Convert.ToBase64String(msOutput.ToArray)
End Function
C3CA193570B26E5C3CBB50FD805A0E23BAFFABA135E82C41517EEDCB9B7C90AC is hex code for a 256-bit-long bitstream.
But Encoding.UTF8.GetBytes does not turn hex code into the corresponding bytes in the way you were thinking.
Because you had 64 characters in that string, you get 64 bytes of UTF-8 bytes. That's a 512-bit-long bitstream.
I have a class called tdes which looks like this:
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Security.Cryptography
Imports System.IO
Namespace security
Public Class tdes
Private des As New TripleDESCryptoServiceProvider()
Private utf8 As New UTF8Encoding()
Private keyValue As Byte()
Private iVValue As Byte()
Public Property Key() As Byte()
Get
Return keyValue
End Get
Set(ByVal value As Byte())
keyValue = value
End Set
End Property
Public Property iV() As Byte()
Get
Return iVValue
End Get
Set(ByVal value As Byte())
iVValue = value
End Set
End Property
Public Sub New(ByVal key As Byte(), ByVal iV As Byte())
Me.keyValue = key
Me.iVValue = iV
End Sub
Public Function ByteDecrypt(ByVal bytes As Byte()) As String
Dim output As Byte()
output = Transform(bytes, des.CreateDecryptor(Me.keyValue, Me.iVValue))
'Return Convert.ToBase64String(output)
Return utf8.GetString(output)
End Function
Public Function ByteEncrypt(ByVal bytes As Byte()) As Byte()
Return Transform(bytes, des.CreateEncryptor(Me.keyValue, Me.iVValue))
End Function
Public Function StringDecrypt(ByVal text As String) As String
Dim input As Byte() = Convert.FromBase64String(text)
Dim output As Byte() = Transform(input, des.CreateDecryptor(Me.keyValue, Me.iVValue))
Return utf8.GetString(output)
End Function
Public Function StringEncrypt(ByVal text As String) As String
Dim input As Byte() = utf8.GetBytes(text)
Dim output As Byte() = Transform(input, des.CreateEncryptor(Me.keyValue, Me.iVValue))
Return Convert.ToBase64String(output)
End Function
Public Function StringEncryptByte(ByVal text As String) As Byte()
Dim input As Byte() = utf8.GetBytes(text)
Dim output As Byte() = Transform(input, des.CreateEncryptor(Me.keyValue, Me.iVValue))
'Return Convert.ToBase64String(output)
Return output
End Function
Private Function Transform(ByVal input As Byte(), ByVal cryptoTransform As ICryptoTransform) As Byte()
' Create the necessary streams
Dim memory As New MemoryStream()
Dim stream As New CryptoStream(memory, cryptoTransform, CryptoStreamMode.Write)
' Transform the bytes as requesed
stream.Write(input, 0, input.Length)
stream.FlushFinalBlock()
' Read the memory stream and convert it back into byte array
memory.Position = 0
Dim result As Byte() = New Byte(memory.Length - 1) {}
memory.Read(result, 0, result.Length)
' Clean up
memory.Close()
stream.Close()
' Return result
Return result
End Function
End Class
End Namespace
And it works well encrypting and decrypting things. I want to encrypt some existing passwords in a database table, so I've run a little script on them which encrypt them like so (lots missing for brevity):
Dim key As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
Dim iv As Byte() = {8, 7, 6, 5, 4, 3, 2, 1}
Dim enc As New security.tdes(key, iv)
Dim i As Integer = 0
Using oConn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString)
Using cmd As New SqlCommand("doUpdatePasswords", oConn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#userid", userid)
cmd.Parameters.AddWithValue("#newpassword", enc.StringEncryptByte(currentPassword))
oConn.Open()
Try
i = cmd.ExecuteNonQuery()
Catch ex As Exception
Exit Sub
End Try
End Using
End Using
This has successfully encrypted all my passwords for all the records in the table. Now, when I allow someone to login, I want to compare the two values (what was typed in, to what the stored password is) and I assumed the best way would be to decrypt the stored and compare using strings? Like so:
If (enc.ByteDecrypt(pwdenc).ToString() = pitstop.doMakeSafeForSQL(txtPassword.Text.ToString.ToLower)) Then
However, I get all sorts of bizarre errors; Unable to cast object of type 'System.String' to type 'System.Byte[]'. is one, Invalid character in a Base-64 string. is another based on how I call the password in the proceeding SQLDataReader:
Using oConn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString)
Using cmd As New SqlCommand("doGetEncryptedForLogin", oConn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#email", pitstop.doMakeSafeForSQL(txtEmail.Text.ToString.ToLower))
oConn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
If dr.HasRows() = True Then
While dr.Read()
pwdenc = dr("password_b")
End While
Else
pitstop.doLogIt("Denied login for [" & txtEmail.Text & "]")
litError.Text = "The details you have provided are incorrect. Please try again."
pnlDenied.Visible = True
Exit Sub
End If
dr.Close()
End Using
End Using
End Using
Help or advice welcomed, as I'm stumped here...
Since noone else seems to answer, I'll give you my own two cents. I remember having experienced a similiar situation when I started "playing" with encryption, more than three years ago; in my case the problem was somehow related with the Base64 conversion, though I cannot remember the exact details now.
I suggest you going through a calm and patient debugging session, tracking down all the values of the strings, the byte arrays before and after crypting and decrypting.
I understand it's not a great help, but I hope at least can direct you in the right direction.
I fixed this error by replacing my 'encryption' class with Jeff Atwood's (www.codinghorror.com) fantastic encryption tools.
I did want to salt the passwords and store the salt, but I run out of time to implement that and will have to return to it. In the meantime, I've used this code as my encrypt and decrypt functions - I hope this is of some assistance to someone:
Dim key As String = System.Configuration.ConfigurationManager.AppSettings("key").ToString()
Dim salty As String = pitstop.doMakeSafeForSQL(txtEmail.Text.ToString().ToLower())
Dim p As Encryption.Symmetric.Provider = Encryption.Symmetric.Provider.TripleDES
Dim sym As New Encryption.Symmetric(p)
sym.Key.Text = key
Dim encryptedData As Encryption.Data
encryptedData = sym.Encrypt(New Encryption.Data(pitstop.doMakeSafeForSQL(txtPassword.Text.ToString().ToLower())))
Decryption:
Dim decryptedData As Encryption.Data
Dim pr As Encryption.Symmetric.Provider = Encryption.Symmetric.Provider.TripleDES
Dim sym2 As New Encryption.Symmetric(pr)
sym2.Key.Text = System.Configuration.ConfigurationManager.AppSettings("key").ToString()
Try
decryptedData = sym2.Decrypt(encryptedData)
Catch ex As Exception
// removed for brevity //
End Try
If anyone has any articles or advice on how to create, store and retrieve salted passwords, I'd love to see it.
Chris