HMACSHA1 gives different output between JS and VB.Net - vb.net

I'm trying to translate a JavaScript application of TOTP to VB.Net: http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
I have encountered a problem during translation of the HMAC-part:
//Javascript:
var hmacObj = new jsSHA("Hello World!", 'HEX');
var hmac = hmacObj.getHMAC("secret", 'HEX', 'SHA-1', "HEX");
This is a codesnippet of my translation in VB.Net
'VB.Net:
Dim hmacObjTest As New HMACSHA1(System.Text.Encoding.UTF8.GetBytes("secret"))
Dim hmacTest As Byte() = hmacObjTest.ComputeHash(System.Text.Encoding.UTF8.GetBytes("Hello World!"))
Dim hmacHexTest As New StringBuilder()
For i As Integer = 0 To hmacTest.Length - 1
hmacHexTest.Append(hmacTest(i).ToString("x2"))
Next i
Dim strTest As String = "HMAC = " & hmacHexTest.ToString()
The problem is that i get different output from the two languages:
Output JS: 5efed98b0787c83f9cb0135ba283c390ca49320e //Tested from jsSha demo: http://caligatio.github.io/jsSHA/
Output VB.Net: 87b0154b8420c0b58869ca103f481e824d8876ea
The outputs are not at all the same like they are in this question: hmacsha1 output hex strings different between vb.net and python
Does anyone know where I might be doing something wrong?

Hashes don't work on strings - they work on the binary representation of the string. Now you use UTF-8 as encoding for the dotnet version, while the JavaScript version is very likely not to use UTF-8 - so you get different binary representations, resulting in different hashes.
Use either webttolkit or the hackish var utfstring = unescape(encodeURIComponent(rawstring)); to convert to UTF-8 before calcualting the hash.

Related

Validation of dynamic text in testing

I am trying to validate a pin code in my application. I am using Katalon and I have not been able to find an answer.
The pin code that I need to validate is the same length but different each time I run the test and looks like this on my page: PIN Code: 4938475948.
How can I account for the number changing each time I run the test?
I have tried the following regular expressions:
assertEquals(
"PIN Code: [^a-z ]*([.0-9])*\\d",
selenium.getText("//*[#id='RegItemContent0']/div/table/tbody/tr/td[2]/table/tbody/tr[2]/td/div[1]/div[3]/ul/li[2]/span")
);
Note: This was coded in Selenium and converted to Katalon.
In Katalon, use a combination of WebUI.getText() and WebUI.verifyMatch() to do the same thing.
E.g.
TestObject object = new TestObject().addProperty('xpath', ConditionType.EQUALS, '//*[#id='RegItemContent0']/div/table/tbody/tr/td[2]/table/tbody/tr[2]/td/div[1]/div[3]/ul/li[2]/span')
def actualText = WebUI.getText(object)
def expectedText = '4938475948'
WebUI.verifyMatch(actualText, expectedText, true)
Use also toInteger() or toString() groovy methods to convert types, if needed.
Editing upper example but to get this working
TestObject object = new TestObject().addProperty('xpath', ConditionType.EQUALS, '//*[#id='RegItemContent0']/div/table/tbody/tr/td[2]/table/tbody/tr[2]/td/div[1]/div[3]/ul/li[2]/span')
def actualText = WebUI.getText(object)
def expectedText = '4938475948'
WebUI.verifyMatch(actualText, expectedText, true)
This can be done as variable but in Your case I recommend using some java
import java.util.Random;
Random rand = new Random();
int n = rand.nextInt(9000000000) + 1000000000;
// this will also cover the bad PIN (above limit)
I'd tweak your regex just a little since your pin code is the same length each time: you could limit the number of digits that the regex looks for and make sure the following character is white space (i.e. not a digit, or another stray character). Lastly, use the "true" flag to let the WebUI.verifyMatch() know it should expect a regular expression from the second string (the regex must be the second parameter).
def regexExpectedText = "PIN Code: ([0-9]){10}\\s"
TestObject pinCodeTO = new TestObject().addProperty('xpath', ConditionType.EQUALS, '//*[#id='RegItemContent0']/div/table/tbody/tr/td[2]/table/tbody/tr[2]/td/div[1]/div[3]/ul/li[2]/span')
def actualText = WebUI.getText(pinCodeTO)
WebUI.verifyMatch(actualText, expectedText, true)
Hope that helps!

VB.Net Convert text to WWW form

I want to convert text into the WWW form.
E.g: # should be %40, % should be %25 etc...
There's fine encoder here, but i want to do it in VB.Net.
I need this for httpwebrequest, i think it has something to do with x-www-form-urlencoded.
You can use the Uri.EscapeDataString() method for that:
Dim OriginalURL As String = "http://www.example.com/some file with spaces.php?q1=plus+&q2=at#&q3=svenska språkets 'ö'"
Dim EncodedURL As String = Uri.EscapeDataString(OriginalURL)
Online test: https://ideone.com/h5fqm1
And if you want to just escape parts of the URL but still keep valid components such as : / = ? & (etc.) you'd use Uri.EscapeUriString().

Append binary data to serialized xml header

I need to append binary data to file but before this data is an xml header. Whole file wont be proper xml file but it must proper xml header like following:
<EncryptedFileHeader>
<Algorithm>name</Algorithm>
<KeySize>256</KeySize>
<SubblockLength>64</SubblockLength>
<CipherMode>ECB</CipherMode>
<sessionKey>sessionKey</sessionKey>
</EncryptedFileHeader>
*binary data*
The xml header I do with JAXB marshalling easily, and even easier would be to add this binary data in base64 and store in note inside xml. But this is a clue. I have to store it as binary to save this overhead 33% space used by base64.
So the question is how to add this data and of course later read this back (serialize/deserialize) ?
Another question is how to remove from the first line of document?
I tried to use:
marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
but it throws an exception:
javax.xml.bind.PropertyException: name: com.sun.xml.bind.xmlDeclaration value: false
at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:358)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:527)
Thanks
Actualy I solved this by serializing xml header with JAXB, then appending binary data (bytearray) to existing file.
Reading from file with buffered reader as follows:
BufferedReader reader = new BufferedReader(new FileReader("filepath"));
String line, results = "";
while ((line = reader.readLine()) != null) {
results += line;
}
reader.close();
String[] splited = results.split("</EncryptedFileHeader>");
splited[0] += "</EncryptedFileHeader>";
String s0 = splited[0];
String s1 = new String(splited[1]);
ByteArrayInputStream bais = new ByteArrayInputStream(s0.getBytes());
Now i got a problem with second splited string s1, which consist data from "byteArrayOutputStream.toByteArray();". Now I have to transfer data from this string to byte array. From:
'��A����g�X���
to something like:
[39, -63, -116, 65, -123, -114, 27, -115, -2, 103, -64, 88, -99, -96, -26, -12]
I tried (on the same machine):
byte[] bytes = s1.getBytes();
but bytes array is different and returns 34 bytes instead 16. I read a lot about encodings but still have no idea.
EDIT:
The problem with different number of bytes was due to the different representation of new line by character and byte streams.

c++ Convert string to bytes to send over tcp

I'm trying to send a 28 character string to a remote ip address and port. I've done this successfully in vb.net using the following code snippets:
Dim swon As String = "A55A6B0550000000FFFBDE0030C8"
Dim sendBytes As [Byte]()
sendBytes = Encoding.ASCII.GetBytes(swon)
netStream.Write(sendBytes, 0, sendBytes.Length)
I now have to convert this across to c++ and have the following so far:
char *swon = "A55A6B0550000000FFFBDE0030C8";
array<Byte>^ sendBuffer = gcnew array<Byte>(bufferSize);
sendBuffer = BitConverter::GetBytes( swon );
tcpStream->Write(sendBuffer, 0, sendBuffer->Length);
but am getting stuck at this point. I'm sure I'm missing a simple syntax error but I can't figure it out!
To clarify, I'm not getting an error, but I don't think the string is being converted to bytes correctly as when I convert back, I just get a '01'
Cheers,
Chris
I don't understand why you are not just using the exact same .Net framework classes in your ++/CLI code. eg. System::String for swon, Encoding::ASCII to produce the array of bytes.
Anything you did in VB you can map directly over to C++/CLI without using different classes - that's the easest port for you. When you are in MSDN online, just select the C++ view to get examples of stuff you want to do. Try that on this page, for example: http://msdn.microsoft.com/en-us/library/system.text.encoding.ascii.aspx
Steve is correct that the same logic can be duplicated in C++. But the C++ char* already is ASCII, no conversion is necessary. Just a copy is all that's needed.
const char swon[] = { "A55A6B0550000000FFFBDE0030C8" };
array<Byte>^ sendBuffer = gcnew array<Byte>((sizeof swon) - 1);
pin_ptr<Byte> startBuffer = &sendBuffer[0];
memcpy(startBuffer, swon, sendBuffer->Length);
tcpStream->Write(sendBuffer, 0, sendBuffer->Length);

Encoding UTF8 string to ISO-8859-1 String (VB.NET)

I need to convert UTF8 string to ISO-8859-1 string using VB.NET.
Any example?
emphasized textI have tried Latin function and not runs. I receive incorrect string.
My case is that I need to send SMS using API.
Now I have this code:
baseurl = "http://www.myweb.com/api/sendsms.php"
client = New WebClient
client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)")
client.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1")
client.QueryString.Add("user", user)
client.QueryString.Add("password", pass)
client.QueryString.Add("alias", myAlias)
client.QueryString.Add("dest", mobile)
textoSms = Me.mmTexto.Text
textoSms = System.Web.HttpUtility.UrlEncode(textoSms)
client.QueryString.Add("message", textoSms)
data = client.OpenRead(baseurl)
reader = New StreamReader(data)
s = reader.ReadToEnd()
data.Close()
reader.Close()
But not runs...I receive incorrect messages. For example
if I write: mañana returns maa ana
If I write aigüa returns aiga
How about:
Dim converted as Byte() = Encoding.Convert(utf8, Encoding.UTF8, _
Encoding.GetEncoding(28591))
That assumes that when you say "UTF8 string" you mean "binary data which is the UTF-8 representation of some text". If you mean something else, please specify :)
Note that ISO-8859-1 only represents a tiny proportion of full Unicode. IIRC, you'll end up with "?" for any character from the source data which isn't available in ISO-8859-1.
The encoding ISO-8859-1 is more commonly called Latin-1. You can get this encoding by doing the following
Dim latin1 = Text.Encoding.GetEncoding(&H6FAF)
The full conversion can be done by the following
Public Function ConvertUtf8ToLatin1(Dim bytes As Byte()) As Bytes()
Dim latin1 = Text.Encoding.GetEncoding(&H6FAF)
Return Encoding.Convert(Encoding.UTF8, latin1, bytes)
End Function
EDIT
As Jon pointed out, it may be easier for people to remember the decimal number 28591 rather than the hex number &H6FAF.
Because System.Text.Encoding.GetEncoding("ISO-8859-1") does not support ñ is my guess, in that case you need to use another encoding type for you SMS.
Please read The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
http://msdn.microsoft.com/en-us/library/system.text.encoding.convert.aspx
Try this with the variable "input" as the UTF-8 String;
VB.NET:
Dim result As Byte() = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("iso-8859-1"), input);
C#:
byte[] result = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("iso-8859-1"), input);
Dont know if this should be posted here but i made a small function in C# to check if a string support the target encoding type.
Hope it can be of any help...
/// <summary>
/// Function for checking if a string can support the target encoding type
/// </summary>
/// <param name="text">The text to check</param>
/// <param name="targetEncoding">The target encoding</param>
/// <returns>True if the encoding supports the string and false if it does not</returns>
public bool SupportsEncoding(string text, Encoding targetEncoding)
{
var btext = Encoding.Unicode.GetBytes(text);
var bencodedtext = Encoding.Convert(Encoding.Unicode, targetEncoding, btext);
var checktext = targetEncoding.GetString(bencodedtext);
return checktext == text;
}
//Call the function demo with ISO-8859-1/Latin-1
if (SupportsEncoding("some text...", Encoding.GetEncoding("ISO-8859-1")))
{
//The encoding is supported
}
else
{
//The encoding is not supported
}