i have been working with an piece of code, to get it to work. I am using the Microsoft RSA Class I have gotten most of it to work, signing, encrypt, decrypt, but not the verify, it always says false, i can decrypt it, so i am a bit lost. Naturally i don't really want to use both keys for the verify part, but i am just attempting to understand it all. Can somebody tell me what i am doing wrong? So that i can get it working?
Imports System.Security.Cryptography
Imports System.Text
Public Class Generator
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles ButtonEncrypt.Click
Dim encoder As New UTF8Encoding
Dim rsa As RSA
Dim textbytes, encryptedtextbytes, signature As Byte()
'set key size to 2048 bits
rsa = RSA.Create()
rsa.KeySize = 2048
'get textbox value
Dim TexttoEncrypt As String = TextBoxSource.Text
'Use UTF8 to convert the text string into a byte array
textbytes = encoder.GetBytes(TexttoEncrypt)
'encrypt the text
encryptedtextbytes = rsa.Encrypt(textbytes, RSAEncryptionPadding.Pkcs1)
signature = rsa.SignData(textbytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)
'Convert the encrypted byte array into a Base64 string for display purposes
TextBoxEncrypted.Text = Convert.ToBase64String(encryptedtextbytes)
TextBoxSignature.Text = Convert.ToBase64String(signature)
'Create an RSAParameters type
Dim Parameters As New RSAParameters
'export the key and other algorithm values
Parameters = rsa.ExportParameters(True)
'display the private key. Base64 encode the text to make display easier
TextBoxPrivate.Text = rsa.ToXmlString(True)
TextBoxPublic.Text = rsa.ToXmlString(False)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDecrypt.Click
Dim encoder As New UTF8Encoding
Dim rsa As RSA
'get the decrypted clear text byte array
Dim data As Byte() = Convert.FromBase64String(TextBoxEncrypted.Text)
rsa = RSA.Create()
rsa.KeySize = 2048
rsa.FromXmlString(TextBoxPublic.Text)
rsa.FromXmlString(TextBoxPrivate.Text)
Dim textbytes As Byte() = rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1)
'Dim out As Boolean = rsa.VerifyData(encryptedtextbytes, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)
'convert the byte array to text using the same encoding format that was used for encryption
TextBoxDecrypted.Text = encoder.GetString(textbytes)
Dim signatureBytes As Byte() = Convert.FromBase64String(TextBoxSignature.Text)
rsa = RSA.Create()
rsa.KeySize = 2048
rsa.FromXmlString(TextBoxPublic.Text)
rsa.FromXmlString(TextBoxPrivate.Text)
Dim out As Boolean = rsa.VerifyData(data, signatureBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)
TextBoxOutput.Text = out
End Sub
End Class
Related
Summary
I am creating a VB project that requires a user to enter an API key. I do not want to store the API key in plaintext for security purposes, so I am attempting to encrypt it. When changing the source of the "password" from an InputBox to a earlier declared variable, I get an error of System.ArgumentNullException: 'String reference not set to an instance of a String. Parameter name: s', and the execution fails.
Context
For security reasons, I don't want the API key to be stored in Plaintext. Instead, I would like the user to enter it once during the application's initial launch, where it converts the plaintext API key into an encrypted file. To encrypt the file, I don't want the user to enter a password, instead, I have combined a few local variables (User name, MAC address, Install location and Host name.) to serve as a password instead. This means the user shouldn't need to enter it on launch (it will read the encrypted API key from the local file), but if any of the variables change (install location, local username, etc.) then it will error, and the user will need to re-enter the API key.
When I try to change the code from having to type in the password, to using the userKey variable, the program no longer launches correctly. Dim password As String = InputBox("Enter the password:") works fine, but Dim password As String = userKey leads to the above error, despite userKey being defined as a string, it refuses to accept it.
Outcome
I would like to have it so the user only needs to enter the API key once the application is first ever launched. It then takes the machine's data to essentially create a UUID, which is what is used to encrypt the plaintext API key entered by the user. I do not want the user to have to set or remember a password to decrypt the API key. It should be automated, and throw an error if they attempt to login where the automated data doesn't allow successful decryption. It'll wipe the API key and ask the user to re-enter it.
Currently, the code works, but the user has to enter their chosen password each time, which is what I am trying to avoid. I am wanting to fully automate this using the UUID I have generated as userKey which is generated when the form is loaded.
My Code
Please see the current code below. It should be in a working state, but I am unsure as to how I can have it so Dim password as String = userKey doesn't get an error when not having the user actualy typing it.
Conclusion
I am new to VB, so this is a new experiment for me to try and learn VB. Please be gentle - I'd appreciate any tips or tricks on how to best achieve this task and similar. Thanks!
Imports System.IO
Imports Newtonsoft.Json
Imports System.Security.Cryptography
Imports System.Net.NetworkInformation
Imports System.Management
Imports System.Text
Public Class Form1
Public userKey As String
Private posts As List(Of Post)
Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim sHostName As String
Dim sUserName As String
Dim mac As String
Dim exePath As String = Application.ExecutablePath()
mac = getMacAddress()
' Get Host Name / Get Computer Name
sHostName = Environ$("computername")
' Get Current User Name
sUserName = Environ$("username")
Dim userKey As String
userKey = sUserName & mac & exePath & sHostName
Label5.Text = userKey
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim plainText As String = InputBox("Enter the plain text:")
Dim password As String = InputBox("Enter the password:")
Dim wrapper As New Simple3Des(password)
Dim cipherText As String = wrapper.EncryptData(plainText)
MsgBox("The cipher text is: " & cipherText)
My.Computer.FileSystem.WriteAllText("cipherText.txt", cipherText, False)
End Sub
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim cipherText As String = My.Computer.FileSystem.ReadAllText("cipherText.txt")
Dim password As String = InputBox("Enter the password:")
Dim wrapper As New Simple3Des(password)
' DecryptData throws if the wrong password is used.
Try
Dim plainText As String = wrapper.DecryptData(cipherText)
MsgBox("The plain text is: " & plainText)
Catch ex As System.Security.Cryptography.CryptographicException
MsgBox("The data could not be decrypted with the password.")
End Try
End Sub
Function getMacAddress()
Dim nics() As NetworkInterface = NetworkInterface.GetAllNetworkInterfaces()
Return nics(1).GetPhysicalAddress.ToString
End Function
End Class
Public NotInheritable Class Simple3Des
Private TripleDes As New TripleDESCryptoServiceProvider
Private Function TruncateHash(
ByVal key As String,
ByVal length As Integer) As Byte()
Dim sha1 As New SHA1CryptoServiceProvider
' Hash the key.
Dim keyBytes() As Byte =
System.Text.Encoding.Unicode.GetBytes(key)
Dim hash() As Byte = sha1.ComputeHash(keyBytes)
' Truncate or pad the hash.
ReDim Preserve hash(length - 1)
Return hash
End Function
Sub New(ByVal key As String)
' Initialize the crypto provider.
TripleDes.Key = TruncateHash(key, TripleDes.KeySize \ 8)
TripleDes.IV = TruncateHash("", TripleDes.BlockSize \ 8)
End Sub
Public Function EncryptData(
ByVal plaintext As String) As String
' Convert the plaintext string to a byte array.
Dim plaintextBytes() As Byte =
System.Text.Encoding.Unicode.GetBytes(plaintext)
' Create the stream.
Dim ms As New System.IO.MemoryStream
' Create the encoder to write to the stream.
Dim encStream As New CryptoStream(ms,
TripleDes.CreateEncryptor(),
System.Security.Cryptography.CryptoStreamMode.Write)
' Use the crypto stream to write the byte array to the stream.
encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
encStream.FlushFinalBlock()
' Convert the encrypted stream to a printable string.
Return Convert.ToBase64String(ms.ToArray)
End Function
Public Function DecryptData(
ByVal encryptedtext As String) As String
' Convert the encrypted text string to a byte array.
Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedtext)
' Create the stream.
Dim ms As New System.IO.MemoryStream
' Create the decoder to write to the stream.
Dim decStream As New CryptoStream(ms,
TripleDes.CreateDecryptor(),
System.Security.Cryptography.CryptoStreamMode.Write)
' Use the crypto stream to write the byte array to the stream.
decStream.Write(encryptedBytes, 0, encryptedBytes.Length)
decStream.FlushFinalBlock()
' Convert the plaintext stream to a string.
Return System.Text.Encoding.Unicode.GetString(ms.ToArray)
End Function
End Class
I'm rewriting hash_hmac code I got on PHP to VB.Net.
I need same result generated both in PHP and VB.Net.
This is hash_hmac code on PHP:
$data = urlencode('2019-07-21T15:30:57.465Z');
$data = '_ts='.$data;
$signatureSecretKey = "secrete";
$hash = hash_hmac('sha256',$data,$signatureSecretKey,true);
$signature = base64_encode($hash);
echo $signature;
The result shows:
upLQYFI3pI2m9Pu5fyiobpvCRhTvRmEyxrVDrdJOYG4=
And here is my code on VB:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim _ts, data, signature, secrete, hash
secrete = "secret"
_ts = DateTime.Now.ToString("2019-07-21T15:30:57.465Z")
data = "_ts=" & HttpUtility.UrlEncode(_ts)
signature = Encrypt(data, secrete)
TextBox1.Text = signature
End Sub
Public Function Encrypt(Content As String, Secret As String) As String
Dim kode As New System.Text.ASCIIEncoding()
Dim getkode As Byte() = kode.GetBytes(Secret)
Dim cont As Byte() = kode.GetBytes(Content)
Dim hmcKu As New HMACSHA256(getkode)
Dim HashCode As Byte() = hmcKu.ComputeHash(cont)
Return Convert.ToBase64String(HashCode)
End Function
Result of my code is:
892q1ArPxIqrX48PQegliVql703V2fcipb5A08F053o=
You can see my VB code generates different result from PHP.
I have tried almost every method I got from internet but the result always different. So, what is equivalent hash_hmac of PHP on VB and what is the right way to make this same result?
Please help?
Use this:
dim hmac as HMACSHA256 = new HMACSHA256(key) ' key = Encoding.ASCII.GetBytes("<secret>")
dim hashValue as byte() = hmac.ComputeHash(Encoding.ASCII.GetBytes("<message>"))
dim result as string = BitConverter.ToString(hashValue).Replace("-", "").ToLower()
hmac.dispose()
I found solution from fb community.
This is exact solution for this cases:
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports System.Text.RegularExpressions
Public Class Form1
Private Shared DES As New TripleDESCryptoServiceProvider
Private Shared MD5 As New MD5CryptoServiceProvider
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim _ts, data, signature, secrete
secrete = "secret"
_ts = DateTime.Now.ToUniversalTime.ToString("yyyy-MM-dd\THH:mm:ss.fff\Z")
data = "_ts=" & HttpUtility.UrlEncode(_ts)
Dim reg = New Regex("%[a-f0-9]{2}")
data = reg.Replace(data, Function(m) m.Value.ToUpperInvariant())
signature = Encrypt(data, secrete)
TextBox1.Text = signature
End Sub
Public Function Encrypt(Content As String, Secret As String) As String
Try
Dim kode As New System.Text.ASCIIEncoding()
Dim getkode As Byte() = kode.GetBytes(Secret)
Dim cont As Byte() = kode.GetBytes(Content)
Dim hmcKu As New HMACSHA256(getkode)
Dim HashCode As Byte() = hmcKu.ComputeHash(cont)
Return Convert.ToBase64String(HashCode)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Function
End Class
I am supposed to do a text encryption on this project I am working on, I came across this code which works perfectly fine, but I don't know what type of encryption this is, can anyone help me answering what type of encryption it is ?
AES Encryption and Decryption in VB.NET was the title of the project I got the code from. If it is AES, is it AES-128, AES-192 or AES-256?
Public Function AES_Encrypt(ByVal input As String, ByVal pass As String) As String
Try
Dim hash(31) As Byte
Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(pass))
Array.Copy(temp, 0, hash, 0, 16)
Array.Copy(temp, 0, hash, 15, 16)
AES.Key = hash
AES.Mode = Security.Cryptography.CipherMode.ECB
Dim DESEncrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateEncryptor
Dim Buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(input)
encrypted = Convert.ToBase64String(DESEncrypter.TransformFinalBlock(Buffer, 0, Buffer.Length))
Return encrypted
Catch ex As Exception
Return input 'If encryption fails, return the unaltered input.
End Try
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AES_Encrypt(TextBox1.Text, ")l|_^WR]!u;j$5:(vuU6K5j+9%{U<:FC")
Label1.Text = encrypted
End Sub
I am attempting to create a binary file that is not readable by notepad in windows. This file needs to contain text information. The current code I run is readable in notepad (with a few extra characters here and there, but still human readable). Any assistance is greatly appreciated.
Using writer As BinaryWriter = New BinaryWriter(File.Open("file.bin", FileMode.Create))
writer.Write(rtbWriter.Text)
End Using
All files can be read by notepad - whether it is binary or not. If you don't want the text to be readable (or to be more accurate - understandable), consider using encryption.
EDIT: For an introduction on how to use encryption, see the link below to see how to use the 3DES cryptographic service provider in VB.NET:
simple encrypting / decrypting in VB.Net
*A more sophisticated approach would chain together the File Stream and Crypto Stream...
...but here's a very simple example showing how to encrypt/decrypt individual strings so you have something to play with and learn from:
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Public Class Form1
Private Key As String = "SomeRandomKeyThatIsHardCoded"
Private data As New List(Of String)
Private DataFileName As String = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyDocuments, "SomeFile.txt")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Some data to play with:
data.Add("User X, Access Y")
data.Add("User Y, Access Z")
data.Add("User Z, Access A")
ListBox1.DataSource = data
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Write out each entry in encrypted form:
Using SW As New StreamWriter(DataFileName, False)
For Each entry As String In data
SW.WriteLine(Crypto.Encrypt(entry, Key))
Next
End Using
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
data.Clear()
ListBox1.DataSource = Nothing
' Read each encrypted line and decrypt it:
Using SR As New System.IO.StreamReader(DataFileName)
While Not SR.EndOfStream
data.Add(Crypto.Decrypt(SR.ReadLine, Key))
End While
End Using
ListBox1.DataSource = data
End Sub
End Class
Public Class Crypto
Private Shared DES As New TripleDESCryptoServiceProvider
Private Shared MD5 As New MD5CryptoServiceProvider
Public Shared Function MD5Hash(ByVal value As String) As Byte()
Return MD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(value))
End Function
Public Shared Function Encrypt(ByVal stringToEncrypt As String, ByVal key As String) As String
DES.Key = Crypto.MD5Hash(key)
DES.Mode = CipherMode.ECB
Dim Buffer As Byte() = ASCIIEncoding.ASCII.GetBytes(stringToEncrypt)
Return Convert.ToBase64String(DES.CreateEncryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
End Function
Public Shared Function Decrypt(ByVal encryptedString As String, ByVal key As String) As String
Try
DES.Key = Crypto.MD5Hash(key)
DES.Mode = CipherMode.ECB
Dim Buffer As Byte() = Convert.FromBase64String(encryptedString)
Return ASCIIEncoding.ASCII.GetString(DES.CreateDecryptor().TransformFinalBlock(Buffer, 0, Buffer.Length))
Catch ex As Exception
Return ""
End Try
End Function
End Class
Other threads have covered that file.encrypt on vb is not supported on W7HE. however i cant find a simple work around for it, and the only other function i know for encryption is using:
Imports system.security.Cryptography
and then doing along the lines of
Dim rsa As New RSACryptoServiceProvider
Dim encoder As New UTF8Encoding
etc,etc
however that only does strings, i need to encrypt the file as a whole.
Any ideas would be greatly appreciated
file.encrypt uses EFS, which is actually transparent encryption; the user account stores the master certificate, so anyone logged in under that account can access the file contents in any application. Depending on what you need, that might not be what you want at all. If you want to replicate EFS behavior for your app alone, it's as simple as storing a master password somewhere in the user's private files, split your data file into 'key' and 'data' sections, and encrypt the key with the master password. (Real EFS has some subtleties: It can encrypt the password separately for many different users, so it allows different users access per-file, giving a recovery option in case the main user's password is lost. It also uses the user's password to encrypt the master password, so if anyone changes the password they won't be able to open files.)
The basic method is just prompt the user for the password and use that to encrypt or decrypt the entire file at once rather than a string at a time. Serialize your file however you would unencrypted, then pass that whole byte array to something similar to EncryptStringToBytes_Aes. The one and only difference if you're writing bytes instead of a string is changing:
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
to
csEncrypt.Write(plainText);
Either way, for the actual crypto you'd use AesCryptoServiceProvider, not RSACryptoServiceProvider, which is for the top-level authentication and encryption of keys/passwords that get passed to AES and similar algorithms. It's rarely used to encrypt whole files, and is dreadfully slow when you do.
I'm enclosing a program I wrote to help you along the way. It is very effective and will encrypt whatever you want. I left notes in it to answer all your questions. At the bottom, you will see an added class to reduce memory usage of the program. It works rather well, (by 8% -10%) Enjoy. Items needed: *3 buttons (Browse) (Encrypt) (Decrypt) *1 TextBox For the project video, see my link:
Part 1: https://www.youtube.com/watch?v=sVaA2q8ttzQ
Part 2: https://www.youtube.com/watch?v=TyafeBJ53YU
'Created by: Rythorian77 | github.com/rythorian77
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ramClass As New AESRam()
End Sub
Private Sub Browse_Click(sender As Object, e As EventArgs) Handles Browse.Click
'Allows you to access files from folders
Dim fetchCryptDialog As New OpenFileDialog With {
.CheckFileExists = True,
.InitialDirectory = "C:\",
.Multiselect = False
}
If fetchCryptDialog.ShowDialog = DialogResult.OK Then
TextBox1.Text = fetchCryptDialog.FileName
End If
End Sub
Private Sub Encrypt_Click(sender As Object, e As EventArgs) Handles Encrypt.Click
'File path goes to textbox
Dim Rythorian77 As String = TextBox1.Text
'This password can be whater you want.
Dim password As String = "123456789ABCDEFG!##$%^&*()_+"
'A data type is the characteristic of a variable that determines what kind of data it can hold.
'Data types include those in the following table as well as user-defined types and specific types of objects.
Dim key As Byte() = New Byte(31) {}
'When overridden in a derived class, encodes a set of characters into a sequence of bytes.
Encoding.Default.GetBytes(password).CopyTo(key, 0)
'RijndaelManaged still works but is considered obsolete in todays world so we use AES
'Represents the abstract base class from which all implementations of the Advanced Encryption Standard (AES) must inherit.
'https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=net-6.0
Dim aes As New RijndaelManaged() With
{
.Mode = CipherMode.CBC,
.KeySize = 256,
.BlockSize = 256,
.Padding = PaddingMode.Zeros
}
'Reads a sequence of bytes from the current memory stream and advances the position within the memory stream by the number of bytes read.
Using mnemonicData As New MemoryStream
'Defines a stream that links data streams to cryptographic transformations.
Using cStream As New CryptoStream(mnemonicData, aes.CreateEncryptor(key, key), CryptoStreamMode.Write)
Dim buffer As Byte() = File.ReadAllBytes(Rythorian77)
cStream.Write(buffer, 0, buffer.Length)
Dim appendBuffer As Byte() = mnemonicData.ToArray()
Dim finalBuffer As Byte() = New Byte(appendBuffer.Length - 1) {}
appendBuffer.CopyTo(finalBuffer, 0)
File.WriteAllBytes(Rythorian77, finalBuffer)
End Using
End Using
End Sub
'The above code notes compliment the same
Private Sub Decrypt_Click(sender As Object, e As EventArgs) Handles Decrypt.Click
Dim Rythorian77 As String = TextBox1.Text
Dim password As String = "123456789ABCDEFG!##$%^&*()_+"
Dim key As Byte() = New Byte(31) {}
Encoding.Default.GetBytes(password).CopyTo(key, 0)
Dim aes As New RijndaelManaged() With
{
.Mode = CipherMode.CBC,
.KeySize = 256,
.BlockSize = 256,
.Padding = PaddingMode.Zeros
}
Using mnemonicData As New MemoryStream
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> < aes.CreateDecryptor > is the only change from above aes.CreateEncryptor
Using cStream As New CryptoStream(mnemonicData, aes.CreateDecryptor(key, key), CryptoStreamMode.Write)
Dim buffer As Byte() = File.ReadAllBytes(Rythorian77)
cStream.Write(buffer, 0, buffer.Length)
Dim appendBuffer As Byte() = mnemonicData.ToArray()
Dim finalBuffer As Byte() = New Byte(appendBuffer.Length - 1) {}
appendBuffer.CopyTo(finalBuffer, 0)
File.WriteAllBytes(Rythorian77, finalBuffer)
End Using
End Using
End Sub
End Class
**Add this separate Class:**
Imports System.Runtime.InteropServices
Public Class AESRam
'This controls the amount of RAM that your process uses, it doesn't otherwise have any affect on the virtual memory size of your process.
'Sets the minimum and maximum working set sizes for the specified process.
'This will cut memory usage in half.
<DllImport("KERNEL32.DLL", EntryPoint:="SetProcessWorkingSetSize", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Friend Shared Function SetProcessWorkingSetSize(pProcess As IntPtr, dwMinimumWorkingSetSize As Integer, dwMaximumWorkingSetSize As Integer) As Boolean
End Function
'Retrieves a pseudo handle for the current process.
<DllImport("KERNEL32.DLL", EntryPoint:="GetCurrentProcess", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Friend Shared Function GetCurrentProcess() As IntPtr
End Function
'See Above
Public Sub New()
Dim pHandle As IntPtr = GetCurrentProcess()
SetProcessWorkingSetSize(pHandle, -1, -1)
End Sub
End Class