Different HMAC for CryptoJS and VB - javascript

I have to generate a HMACSHA256 in Visual Basic. Problem is, that I didnt receive the correct HMAC and get different HMACS
InputData = Test\nTest\n\nTest
secret = c39ff802b43a01c08ea759750c41d7d4bac6b1b884b3864d640b577cf1dca21a
HMACa = 330c55857e5ff197a407a9dcd41bbf03a2e8de0b351aba9a405139919b3cae57
HMACb = f701ea7028f20df11a52bee297a336de212655a8bad01d848eeaa87d0f76ee5e
JS(CryptoJS) -> HMACa (Tested directly)
PY -> HMACa (Tested directly)
JS(jsSHA) -> HMACb (Tested under: liavaag.org/English/SHA-Generator/HMAC/)
C#/VB -> HMACb (Tested directly)
Why do i get different HMAC's and what can i do to get HMACa in VB/C#??
Here is my VB Code:
Sub Main()
Dim sToHash As String = "Test\nTest\n\nTest"
Dim sKey As String = "c39ff802b43a01c08ea759750c41d7d4bac6b1b884b3864d640b577cf1dca21a"
Console.WriteLine(getHMAC(sToHash, sKey))
End Sub
Function getHMAC(ToHash As String, SecretKey As String) As String
Dim aoText() As Byte = System.Text.Encoding.UTF8.GetBytes(ToHash)
Dim aoKey() As Byte = System.Text.Encoding.UTF8.GetBytes(SecretKey)
Using oHmac As New System.Security.Cryptography.HMACSHA256(aoKey)
Dim sHash As Byte() = oHmac.ComputeHash(aoText)
Return ByteToString(sHash)
End Using
End Function
Function ByteToString(buff As Byte()) As String
Dim getbinary As String = ""
For i As Integer = 0 To buff.Length - 1
getbinary += buff(i).ToString("X2")
Next
Return (getbinary).ToLower
End Function

It's a lot easier than intended. VB/C# can't Encode '\n' as NewLine. In World of VisualBasic you have to write vbLf to Indicate a NewLine in a String
So the correct InputString is now:
"Test" + vbLf + "Test" + vbLf + vbLf + "Test"
Result => HMACa
Thanks anyway

Related

Not able to decrypt the encryptedValue using crypto

I am trying to decrypt a value (encrypted in des) coming from VB.
When I try to decrypt the encryptedValue using crypto in Javascript the output gives me an empty value.
I have attached how the encryption was done in VB.
HOW I AM TRYING TO DECRYPT IN JAVASCRIPT
var CryptoJS = require("crypto-js");
var key = "peekaboo";
var encryptedValue = "50AznWWn4fJI19T392wIv/ZysP/Ke3mB";
encryptedValue = CryptoJS.enc.Base64.parse(encryptedValue);
var data = CryptoJS.DES.decrypt(encryptedValue, key, { iv: "cbauthiv" });
const email = data.toString(CryptoJS.enc.Utf8);
console.log(email, "ORIGINAL TEXT");
THE WAY IT IS ENCRYPTED IN VB
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Module Module1
Private Const ENCRYPTIONKEY As String = "peekaboo"
Sub Main()
Dim s As String = Encrypt("ditzymoose#outlook.com")
Dim r As String = Decrypt(s)
Console.ReadLine()
End Sub
Private Function Encrypt(stringToEncrypt As String) As String
Dim rng As New RNGCryptoServiceProvider
Dim byteArray() As Byte = New Byte(8) {}
Dim iv_value As String = "cbauthiv"
Dim key() As Byte = {}
Dim IV() As Byte = System.Text.Encoding.UTF8.GetBytes(Left(iv_value, 8))
key = System.Text.Encoding.UTF8.GetBytes(Left(ENCRYPTIONKEY, 8))
Dim des As New DESCryptoServiceProvider
rng.GetBytes(byteArray)
Dim Salt As String = BitConverter.ToString(byteArray)
Dim SaltedInput As String = Salt & "~" & stringToEncrypt
Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes(stringToEncrypt)
Dim ms As New MemoryStream
Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)
cs.FlushFinalBlock()
Return Convert.ToBase64String(ms.ToArray())
End Function
End Module
The key and IV must be passed as WordArray. For the conversion the Utf8-Encoder has to be used, here.
Also, the ciphertext must be passed as a CipherParams object or alternatively Base64 encoded (which is then implicitly converted to a CipherParams object), here.
With these changes the ciphertext of the VB code can be successfully decrypted using the CryptoJS code:
var key = CryptoJS.enc.Utf8.parse("peekaboo");
var iv = CryptoJS.enc.Utf8.parse("cbauthiv");
var encryptedValue = "50AznWWn4fJI19T392wIv/ZysP/Ke3mB";
var data = CryptoJS.DES.decrypt(encryptedValue, key, {iv: iv});
var email = data.toString(CryptoJS.enc.Utf8);
console.log(email, "ORIGINAL TEXT");
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
Please note that DES is insecure (here) and was replaced by AES almost 20 years ago. Also insecure is a static IV. Instead, a random IV should be generated for each encryption.
Furthermore a password should not be used as key. If a password is to be used, the key should be derived from the password using a reliable key derivation function such as PBKDF2.

Extracting binary data from string with sign bit set in javascript

I have a string that looks like this "��is some test text"
The first 2 bytes are the length of the rest of the string (this is legacy network traffic that cannot be changed).
It decodes ok when the sign bit isn't set in the binary data but if it is I get rubbish.
Here is a little test program:
var decode = '';
//decode = new Buffer('ffff', 'hex');
//decode = new Buffer('85ff', 'hex');
decode = new Buffer('364e', 'hex');
//decode = new Buffer('7f5a', 'hex');
//decode = new Buffer('00ff', 'hex');
decode += '<this>is some test text</this>';
console.log(decode);
var testbuf = decode.slice(0,2);
console.log('testbuf =' + testbuf);
var myLength1 = decode.slice(0,1).charCodeAt('hex').toString(16);
console.log('ml1 ' + myLength1.toString());
var myLength2 = decode.slice(1,2).charCodeAt('hex').toString(16);
console.log('ml2 ' + myLength2.toString());
var myLength = myLength1 + myLength2;
console.log('mylength =' + myLength1 + myLength2);
var foo2 = parseInt(myLength, 16);
console.log('ml3 ' + foo2.toString());
Using the code above the output looks like this;
node foo.js
6N<this>is some test text</this>
testbuf =6N
ml1 36
ml2 4e
mylength =364e
ml3 13902
The answer is correct when the sign bit isn't set, but if the data contains a value with the high bit set, I end up with fffd for each character with the high order bit set (the replacement character).
This is output with high order bit data (using the 0x85ff data line above):
node foo.js
��<this>is some test text</this>
testbuf =��
ml1 fffd
ml2 fffd
mylength =fffdfffd
ml3 4294836221
I know it's because the charCodeAt() function desires to return 'fffd' as the replacement character for what it sees as non ascii, the question is, what is the alternative for extracting binary data from a string?
Thanks

C# SHA256 ComputeHash result different with CryptoJS SHA256 function

I have a C# function as below:
string stringvalue = "530500480530490480530480480520570480520510500490";
var encodedvalue= Encoding.Unicode.GetBytes(stringvalue);
using (HashAlgorithm ssp = System.Security.Cryptography.HashAlgorithm.Create("SHA256"))
{
var digest = ssp.ComputeHash(encodedvalue);
return BitConverter.ToString(digest);
}
I need to create a javascript function that match the code above so that the end result for both C# and JS is the same.
Currently in my JS code, I'm using this:
var hash = CryptoJS.SHA256("530500480530490480530480480520570480520510500490");
var hexhash = hash.toString(CryptoJS.enc.hex);
This is the result of my hexhash:
d956678c8f12c65299daf35019a9a1eb3e6eb9855fd850aeb5aafe46057d179e
But in my C# code, this line of var digest = ssp.ComputeHash(bPass); return the following array:
I don't know much about encoding. Please tell me what type of result is being populated in the c# code above? If I'm not mistaken, the ComputeHash is returning bytes but I need lots of reading to confirm that which is another long hour of studying
I tried many different ways of converting the JS Sha256 code but no luck. I'm stuck at this particular line for almost a day.
Please help. Thanks
EDIT:
Sorry for the code error. I had updated the C# code. ComputeHash accept an array
In my example I am using System.Security.Cryptography.SHA256Managed to get SHA256 in C#.
The method SHA256Managed.ComputeHash takes a byte array as a parameter and return another byte array. Now we need to convert back your byte array to a string.
The following code return the same result a Javascript SHA-256.
byte[] bytes = Encoding.UTF8.GetBytes("530500480530490480530480480520570480520510500490");
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return(hashString);
Just to explain : String.Format("{0:x2}", x)
X means Hexadecimal format.
2 means 2 characters.
I finally found the answer after uncountable hours of trial and error.
The C# code var digest = ssp.ComputeHash(encodedvalue) is returning byte array from the result of var encodedvalue= Encoding.Unicode.GetBytes(stringvalue); as Jean replied. In order to create the function in Javascript, I need to ensure that the encodedvalue is producing the correct encoding format and size just like the one in C#.
Using only CryptoJS, I manage to get the matching result from below
function GetHexFromString() {
var stringVal = '8563A578-7402-4567-A6CE-4DE4E0825B021234';
// Convert the string to UTF 16 little-endian
// Result: 560530540510650530550560450550520480500450520530540550450650540670690450520680690520690480560500530660480500490500510520
var utf16le = CryptoJS.enc.Utf16LE.parse(stringVal);
// Convert to Sha256 format and get the word array
var utf16Sha256 = CryptoJS.SHA256(utf16le);
// Convert the Sha256 word array to Uint8Array to get the 32 byte array just to see the result to ensure it match with the C# function
// Result: 94,203,69,29,35,202,209,149,121,144,44,6,98,250,141,161,102,7,238,35,228,117,111,236,118,115,51,113,134,72,52,69
var utf16sha256Array = convertWordArrayToUint8Array(utf16Sha256);
// Convert the Sha256 to hex (if i'm not mistaken, it's base 16) format
var hexSha256 = utf16Sha256.toString(CryptoJS.enc.hex);
// Insert a dash in between 2 characters in the string
hexSha256 = hexSha256.replace(/(\S{2})/g, "$1-");
// Remove the last dash in the string
hexSha256 = hexSha256.replace(/-$/, "");
// Final Result: 5E-CB-45-1D-23-CA-D1-95-79-90-2C-06-62-FA-8D-A1-66-07-EE-23-E4-75-6F-EC-76-73-33-71-86-48-34-45
return hexSha256.toUpperCase();
}
function convertWordArrayToUint8Array(wordArray) {
var len = wordArray.words.length,
u8_array = new Uint8Array(len << 2),
offset = 0, word, i
;
for (i = 0; i < len; i++) {
var word = wordArray.words[i];
u8_array[offset++] = word >> 24;
u8_array[offset++] = (word >> 16) & 0xff;
u8_array[offset++] = (word >> 8) & 0xff;
u8_array[offset++] = word & 0xff;
}
return u8_array;
}
Hope it help whoever that need such method
An alternative to Koo SengSeng's answer (if you don't want to use CryptoJS library).
SHA256 function is from here, the arrToUintArr function is from Koo SengSeng's answer.
var SHA256=function a(b){function c(a,b){return a>>>b|a<<32-b}for(var d,e,f=Math.pow,g=f(2,32),h="length",i="",j=[],k=8*b[h],l=a.h=a.h||[],m=a.k=a.k||[],n=m[h],o={},p=2;64>n;p++)if(!o[p]){for(d=0;313>d;d+=p)o[d]=p;l[n]=f(p,.5)*g|0,m[n++]=f(p,1/3)*g|0}for(b+="\x80";b[h]%64-56;)b+="\x00";for(d=0;d<b[h];d++){if(e=b.charCodeAt(d),e>>8)return;j[d>>2]|=e<<(3-d)%4*8}for(j[j[h]]=k/g|0,j[j[h]]=k,e=0;e<j[h];){var q=j.slice(e,e+=16),r=l;for(l=l.slice(0,8),d=0;64>d;d++){var s=q[d-15],t=q[d-2],u=l[0],v=l[4],w=l[7]+(c(v,6)^c(v,11)^c(v,25))+(v&l[5]^~v&l[6])+m[d]+(q[d]=16>d?q[d]:q[d-16]+(c(s,7)^c(s,18)^s>>>3)+q[d-7]+(c(t,17)^c(t,19)^t>>>10)|0),x=(c(u,2)^c(u,13)^c(u,22))+(u&l[1]^u&l[2]^l[1]&l[2]);l=[w+x|0].concat(l),l[4]=l[4]+w|0}for(d=0;8>d;d++)l[d]=l[d]+r[d]|0}for(d=0;8>d;d++)for(e=3;e+1;e--){var y=l[d]>>8*e&255;i+=(16>y?0:"")+y.toString(16)}return i};
var arrToUintArr=function(a){for(var l=a.length,b=new Uint8Array(l<<2),o=0,w,i=0;i<l;i++) w=a[i],b[o++]=w>>24,b[o++]=(w>>16)&0xff,b[o++]=(w>>8)&0xff,b[o++]=w&0xff;return b;}
var computeHash=function(k){for(var a=[],s=SHA256(k),i=0;i<8;i++) a.push(parseInt(s.substr(i*8,8),16));return arrToUintArr(a);}
computeHash(k) will return an array of numbers representing bytes.
This is equal to below code in C#:
new System.Security.Cryptography.SHA256CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(k));
Try
var digest = ssp.ComputeHash(Encoding.UTF8.GetBytes(stringvalue))
return BitConverter.ToString(digest)
.Replace("-", string.Empty)
.ToLowerInvariant();
That js library is converting the string to UTF8 before calculating its hash.
typescript code:
private computeHash(text: string): string {
return CryptoJS.SHA256(text).toString();
}
c# equivalent:
private string ComputeHash(string text)
{
using (var sha256 = SHA256.Create())
{
var bytes = Encoding.UTF8.GetBytes(text);
var hash = sha256.ComputeHash(bytes);
return hash.Aggregate(string.Empty, (current, x) => current + $"{x:x2}");
}
}
after two days of research it works perfectly! Two different codes give the same result.
js
const sha1 = require('sha1');
const getHash = str =>{
const hashingBytes = Buffer.from(sha1(str), "hex");
const base64Value = Buffer.from(hashingBytes).toString('base64');
return base64Value;
}
c#
System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
byte[] hashingbytes = sha.ComputeHash(bytes);
var hash = Convert.ToBase64String(hashingbytes);

VB 2013: Auto login from my.settings issue

I am using the latest version of Awesomium for the WebControl for my application. When my application arrives at "accounts.google.com/ServiceLogin" it is supposed to execute some Javascript to have it automatically log in. In my.settings.java I have:
"document.getElementById('Email').value=""1"";document.getElementById('Passwd').value=""2"";document.getElementById('signIn').click()"
Value "1" being the email, and "2" being the password. So when the document is ready I have this:
Private Sub WebBrowser1_DocumentReady(sender As Object, e As Awesomium.Core.UrlEventArgs) Handles WebBrowser1.DocumentReady
If WebBrowser1.Source.ToString.Contains("accounts.google.com/ServiceLogin") = True Then
WebBrowser1.ExecuteJavascript(My.Settings.java.ToString)
Else
End If
I don't know why this is not working. When I paste the code directly in like this:
WebBrowser1.ExecuteJavascript("document.getElementById('Email').value=""1"";document.getElementById('Passwd').value=""2"";document.getElementById('signIn').click()")
The code works perfectly and it logs in. The reason I have it in my.settings is because I originally have it in a textbox, then I ask the user for their email and password, and then replace "1" with the email, and "2" with the password, then save the edited textbox text in my.settings.java. Then I have it look for the Javascript there instead of hard coding it into the application, and not being able to customize it for each user. Is any of my code wrong, or is there another way of doing this with Awesomium. Also, I am using the Awesomium WebControl1, I just changed it to WebBrowser1 because that is what I am used to typing. Sorry if this question is simple, as I am a student developer, with very limited knowledge in Javascript.
I never user my.settings when it comes to sensitive data like passwords (even emails). What I always do, I encrypt them in XML file using a simple yet dynamic encryption like this :
Public Function Encrypt(ByVal plainText As String) As String
Dim passPhrase As String = **My.Computer.Name.ToString**
Dim saltValue As String = **My.Computer.Info.OSFullName.ToString**
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 2
Dim initVector As String = "#1B2c3D4e5F6g7H8"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
Dim memoryStream As New IO.MemoryStream()
Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte() = memoryStream.ToArray()
memoryStream.Close()
cryptoStream.Close()
Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
Return cipherText
End Function
Public Function Decrypt(ByVal cipherText As String) As String
Dim passPhrase As String = **My.Computer.Name.ToString**
Dim saltValue As String = **My.Computer.Info.OSFullName.ToString**
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 2
Dim initVector As String = "#1B2c3D4e5F6g7H8"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
Dim memoryStream As New IO.MemoryStream(cipherTextBytes)
Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
memoryStream.Close()
cryptoStream.Close()
Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
Return plainText
End Function
And it's still not that safe. The best way is to let the user put the password.
As for your answer , if I understand you question, you need to create profiles, and store them in files/registry. (I recommend files or database). So that when "John" uses your program, he will select the "John" profile ... and so on.

Dynamically updating dependent variables

Have just found a gaping hole in my cs knowledge... this code is written in VBA but I'd be really interested to know how to do this in javascript as well !
Basically I'm in a situation where a whole set of variables depends on one variable - something like this :
Sub test()
Dim start As Integer
Dim var1 As Integer
Dim var2 As Integer
Dim var3 As Integer
var1 = start + 1
var2 = start + 2
var3 = start + 3
End Sub
My problem is that I want the values of var1, var2 and var3 to update dynamically based on the value of start, for example
Sub test()
Dim start As Integer
Dim var1 As Integer
Dim var2 As Integer
Dim var3 As Integer
start = 0
var1 = start + 1
var2 = start + 2
var3 = start + 3
' would like to have var1 = 1, var2 = 2, var3 = 3
MsgBox "start = " & start & vbNewLine & _
"var1 = " & var1 & vbNewLine & _
"var2 = " & var2 & vbNewLine & _
"var3 = " & var3
start = 5
' would now like to have var1 = 6, var2 = 7, var3 = 8
MsgBox "start = " & start & vbNewLine & _
"var1 = " & var1 & vbNewLine & _
"var2 = " & var2 & vbNewLine & _
"var3 = " & var3
End Sub
But clearly this is not working, I get the same values
var1 = 1, var2 = 2, var3 = 3
both times. Is there a way to make this work in VBA ?
And is there a name for this kind of thing so I can better google it ? Something like "dynamic dependent variables" ? Many thanks !
I'm guessing that you are looking for something like Excel cell formulas and the way they cascade updates. There is no built-in mechanism for coding like that in VBA. There are some programming languages that use a paradigm called Functional Programming that behave in a similar way by chaining functions together and evaluating in a lazy manner, but VBA is more of a (weakly) object oriented, imperative flavor.
One way to solve this type of issue generally is by creating a class to encapsulate all your calculations and using member variables as the base elements of the calculations which would be set first, like start, and functions for the derivative numbers, like var1, var2, var3.
Here is an example. Create a class called clsRectangle and copy the following:
Option Compare Database
Option Explicit
Public length As Integer
Public width As Integer
Public Property Get diagonal() As Double
diagonal = VBA.Sqr((length ^ 2) + (width ^ 2))
End Property
Public Property Get area() As Integer
area = length * width
End Property
Public Property Get perimeter() As Integer
perimeter = 2 * (length + width)
End Property
Next create a module called mdlMain and add the following:
Public Sub Main()
Dim rect As clsRectangle
Set rect = New clsRectangle
With rect
.length = 3
.width = 5
MsgBox "perimeter: " & .perimeter & vbCrLf & _
"diagonal: " & .diagonal & vbCrLf & _
"area: " & .area & vbCrLf
'After changing the underlying numbers (like *start* in your example)
'area, perimeter and diagonal all return new values
.length = 2
.width = 7
MsgBox "perimeter: " & .perimeter & vbCrLf & _
"diagonal: " & .diagonal & vbCrLf & _
"area: " & .area & vbCrLf
End With
End Sub
Building a class at compile-time to handle formulaic calculations is good practice because it exposes your math and logic in a very maintainable way and benefits from the syntax and type-checking of the language. However, it does lack some of the flexibility of a run-time system. If you want to attempt something like that, I can give you some pointers, but it would be a pretty heavy lift to accomplish. I've done something similar in the past and had to implement [Topological Sort] to figure out what order to perform the calculation updates in based on a graph of prerequisites.
I can't speak to Javascript directly as I don't have too much experience with it. However, Javascript is a much more dynamic language than VBA and it's entirely possible that libraries already exist to do what you want.
as far as I'm aware this won't be possible in VBA. You could declare your variables at module level (outside of your procedure) and have them updating through a called function as outlined below. It's not quite as simple as you were perhaps expecting, but it is better than manually updating your variables every time 'start' changes.
Dim start As Integer
Dim var1 As Integer
Dim var2 As Integer
Dim var3 As Integer
Sub test()
start = 0
var1 = start + 1
var2 = start + 2
var3 = start + 3
' would like to have var1 = 1, var2 = 2, var3 = 3
MsgBox "start = " & start & vbNewLine & _
"var1 = " & var1 & vbNewLine & _
"var2 = " & var2 & vbNewLine & _
"var3 = " & var3
start = ChangeStart(5)
' would now like to have var1 = 6, var2 = 7, var3 = 8
MsgBox "start = " & start & vbNewLine & _
"var1 = " & var1 & vbNewLine & _
"var2 = " & var2 & vbNewLine & _
"var3 = " & var3
End Sub
Public Function ChangeStart(StartValue As Long)
start = StartValue
var1 = start + 1
var2 = start + 2
var3 = start + 3
End Function

Categories

Resources